Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Sampler compareEnable needs to be specified at sampler creation, and validated against the shader #552

@austinEng

Description

@austinEng

The sampler compare function can be used strictly when sampling the depth component to return either 0.0 or 1.0 based on comparison to a reference value in the shader, instead of returning the actual depth value.

tldr; Because of documented constraints in Vulkan, we need to specify whether the compare function is enabled at the time of sampler creation. And, we must validate this against whether or not the sampler is being used for comparison in the shader.

This same restriction applies for OpenGL. I didn't find any documentation for Metal and D3D12.

Suggested Changes

Add a compareEnable flag, or add an additional "disabled" enum.

GPUSamplerDescriptor {
  bool compareEnable = false;
  // OR
  GPUCompareFunction compare = "disabled";
}

and add an additional GPUBindingType "comparison-sampler". If a comparison sampler is used in the shader, then this new binding type must be used.

In Vulkan:

The compareFunction is specified on the VkCreateSamplerInfo, but compareEnable must also be set to true or false, depending on how the sampler is used in the shader.

SPIR-V disassembly snippet:

              11:             TypeImage 6(float) 2D sampled format:Unknown
              12:             TypePointer UniformConstant 11
    13(uTexture):     12(ptr) Variable UniformConstant
              15:             TypeSampler
              16:             TypePointer UniformConstant 15
    17(uSampler):     16(ptr) Variable UniformConstant
              19:             TypeImage 6(float) 2D depth sampled format:Unknown
              20:             TypeSampledImage 19

               6:             TypeFloat 32
               9:    6(float) Constant 1067869798
                              Store 8(ref) 9

              14:          11 Load 13(uTexture)
              18:          15 Load 17(uSampler)
              21:          20 SampledImage 14 18
              25:   22(fvec2) Load 24(uv)
              26:    6(float) Load 8(ref)
              28:    6(float) CompositeExtract 25 0
              29:    6(float) CompositeExtract 25 1
              30:   27(fvec3) CompositeConstruct 28 29 26
              31:    6(float) CompositeExtract 30 2

              // Relevant OpImage*Dref* here!
              32:    6(float) ImageSampleDrefImplicitLod 21 30 31
                              Store 10(passed) 32

According to section 15.3.1. Texel Input Validation Operations of the Vulkan spec:

There are a number of cases where a SPIR-V instruction can mismatch with the sampler, the image, or both. There are a number of cases where the sampler can mismatch with the image. In such cases the value of the texel returned is undefined.

These cases include:

  • The SPIR-V instruction is one of the OpImage*Dref* instructions and the sampler compareEnable is VK_FALSE
  • The SPIR-V instruction is not one of the OpImage*Dref* instructions and the sampler compareEnable is VK_TRUE
  • The SPIR-V instruction is one of the OpImage*Dref* instructions and the image format is not one of the depth/stencil formats with a depth component, or the image aspect is not VK_IMAGE_ASPECT_DEPTH_BIT.

So, an OpImage*Dref* may be used if and only if it matches the compareEnable flag passed to sampler creation, and it is used on the depth component of a texture.

Other APIs for reference:

In D3D12:

Compare function is specified in the D3D12_SAMPLER_DESC

Texture2D<float4> uTexture : register(t0);
SamplerComparisonState uSampler : register(s1);

// ...
float ref = 1.3;
float passed = uTexture.SampleCmp(uSampler, uv, ref);

In Metal:

Compare function is specified in the MTLSamplerDescriptor

// depth2d<float> uTexture [[texture(0)]]
// sampler uSampler [[sampler(0)]]

float ref = 1.3;
float passed = uTexture.sample_compare(uSampler, uv, ref); // 0.0 or 1.0

In OpenGL:

Set GL_TEXTURE_COMPARE_FUNC and set GL_TEXTURE_COMPARE_MODE to GL_COMPARE_REF_TO_TEXTURE
https://www.khronos.org/opengl/wiki/Sampler_Object#Comparison_mode

https://www.khronos.org/opengl/wiki/Sampler_(GLSL)#Shadow_samplers

If a texture has a depth or depth-stencil image format and has the depth comparison activated, it cannot be used with a normal sampler. Attempting to do so results in undefined behavior. Such textures must be used with a shadow sampler.

layout(binding = 0) uniform texture2D uTexture;
layout(binding = 1) uniform sampler uSampler;

layout(location = 0) in vec2 uv;

float ref = 1.3;
float passed = texture(sampler2DShadow(uTexture, uSampler), vec3(uv, ref));

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions