DiligentGraphics/DiligentCore

Improve Pipeline Resource Signature Compatibility wrt Immutable Samplers

TheMostDiligent opened this issue · 2 comments

Currently, two pipeline resource signatures are compatible only when all their immutable samplers match exactly. If any property of one of the immutable samplers differs, SRBs created by one signature cannot be used by another. This requirement however seems to be unnecessary and can be relaxed since:

  • In Vulkan, immutable samplers are initialized directly in the descriptor set layout (PipelineResourceSignatureVkImpl::CreateSetLayouts). If an immutable sampler is initialized in the set layout, the sampler can’t be updated in the descriptor.
  • In Direct3D12, immutable samplers are compiled directly into the PSO. As long as the number of samplers is the same, the two SRBs should be compatible
  • In Direct3D11, OpenGL and Metal immutable samplers are emulated and bound like normal samplers by CommitShaderResources. This logic can be moved to SetPipelineState.

The goal of this feature is to allow two signatures to be compatible if they have the same number of immutable samplers, but the samplers do not need to be identical.

Implementation Notes

  • In Direct3D11 and Direct3D12, registers for immutable samplers are allocated prior to registers for normal samplers (PipelineResourceSignatureD3D12Impl::AllocateRootParameters, PipelineResourceSignatureD3D11Impl::CreateLayout). Allowing the number of samplers to be different is complicated
  • In Direct3D11, immutable samplers are copied to the shader resource cache by PipelineResourceSignatureD3D11Impl::CopyStaticResources. Immutable samplers are bound like all normal samplers. This logic should be moved to DeviceContextD3D11Impl::SetPipelineState.
  • Important: immutable samplers must be ignored in CommitShaderResources so that samplers previously set by the PSO are not overwritten
    • Immutable samplers do not need to be stored in the resource cache.
    • Update debug checks
  • Metal: implementation is conceptually similar to Direct3D11 and requires similar changes.
  • OpenGL: similar to Direct3D11, static resources are copied in PipelineResourceSignatureGLImpl::CopyStaticResources, but they are committed in DeviceContextGLImpl::BindProgramResources. Apparently, samplers may need to be stored in the device context or taken from currently bound signatures. Alternatively, check if it is possible to bind samplers separately similar to other backends.
  • Add new tests that validate both separate immutable samplers and combined immutable samplers:
    • Set pipeline A that uses immutable sampler for TexA (e.g. clamp), bind SRBA; set pipeline B that uses different immutable sampler for TexA (e.g wrap); render with pipeline B using sampler; validate the result.
    • Add tests that use explicit and implicit signatures

Apparently in Vulkan this is an undefined behavior. This change may need to be reverted

From Vulkan spec:

VUID-vkCmdDraw-None-02697
For each set n that is statically used by the VkPipeline bound to the pipeline bind point used by this command, a descriptor set must have been bound to n at the same pipeline bind point, with a VkPipelineLayout that is compatible for set n, with the VkPipelineLayout used to create the current VkPipeline, as described in Pipeline Layout Compatibility

Pipeline Layout Compatibility:

Two pipeline layouts are defined to be “compatible for set N” if they were created with identically defined descriptor set layouts for sets zero through N, if both of them either were or were not created with VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT, and if they were created with identical push constant ranges.