-- v3: tests/shader-runner: Add sampler comparison tests.
From: Conor McCarthy cmccarthy@codeweavers.com
--- Makefile.am | 1 + tests/hlsl/sample-cmp.shader_test | 160 ++++++++++++++++++++++++++++++ tests/shader_runner.c | 34 +++++++ tests/shader_runner.h | 1 + tests/shader_runner_d3d11.c | 2 +- tests/shader_runner_d3d12.c | 1 + tests/shader_runner_gl.c | 30 ++++++ tests/shader_runner_vulkan.c | 27 +++++ 8 files changed, 255 insertions(+), 1 deletion(-) create mode 100644 tests/hlsl/sample-cmp.shader_test
diff --git a/Makefile.am b/Makefile.am index cfb225f9c..322fd73f8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -160,6 +160,7 @@ vkd3d_shader_tests = \ tests/hlsl/return.shader_test \ tests/hlsl/round.shader_test \ tests/hlsl/sample-bias.shader_test \ + tests/hlsl/sample-cmp.shader_test \ tests/hlsl/sample-grad.shader_test \ tests/hlsl/sample-level.shader_test \ tests/hlsl/sampler-offset.shader_test \ diff --git a/tests/hlsl/sample-cmp.shader_test b/tests/hlsl/sample-cmp.shader_test new file mode 100644 index 000000000..902e3b2c7 --- /dev/null +++ b/tests/hlsl/sample-cmp.shader_test @@ -0,0 +1,160 @@ +[require] +shader model >= 4.0 + +[sampler 0] +filter linear linear linear +address clamp clamp clamp +comparison never + +[srv 0] +format r32 float +size (2d, 2, 2) +0.5 0.5 +0.5 0.5 + +[pixel shader] +Texture2D<float> t : register(t0); +SamplerComparisonState s : register(s0); + +float ref; + +float4 main() : sv_target +{ + return t.SampleCmpLevelZero(s, float2(0.5, 0.5), ref); +} + +[test] +uniform 0 float 1.0 +draw quad +probe all r (0.0) + +uniform 0 float 0.0 +draw quad +probe all r (0.0) + +[sampler 0] +filter linear linear linear +address clamp clamp clamp +comparison less + +[test] +uniform 0 float 0.0 +draw quad +probe all r (1.0) + +uniform 0 float 0.5 +draw quad +probe all r (0.0) + +[sampler 0] +filter linear linear linear +address clamp clamp clamp +comparison equal + +[test] +uniform 0 float 0.5 +draw quad +probe all r (1.0) + +uniform 0 float 0.5000001 +draw quad +probe all r (0.0) + +[sampler 0] +filter linear linear linear +address clamp clamp clamp +comparison less equal + +[test] +% fails on 0.5, at least on RADV +uniform 0 float 0.4999999 +draw quad +probe all r (1.0) + +uniform 0 float 0.5000001 +draw quad +probe all r (0.0) + +[sampler 0] +filter linear linear linear +address clamp clamp clamp +comparison greater + +[test] +uniform 0 float 1.0 +draw quad +probe all r (1.0) + +uniform 0 float 0.5 +draw quad +probe all r (0.0) + +[sampler 0] +filter linear linear linear +address clamp clamp clamp +comparison not equal + +[test] +uniform 0 float 0.5000001 +draw quad +probe all r (1.0) + +uniform 0 float 0.5 +draw quad +probe all r (0.0) + +[sampler 0] +filter linear linear linear +address clamp clamp clamp +comparison greater equal + +[test] +% fails on 0.5, at least on RADV +uniform 0 float 0.5000001 +draw quad +probe all r (1.0) + +uniform 0 float 0.4999999 +draw quad +probe all r (0.0) + +[sampler 0] +filter linear linear linear +address clamp clamp clamp +comparison always + +[test] +uniform 0 float 0.0 +draw quad +probe all r (1.0) + +uniform 0 float 1.0 +draw quad +probe all r (1.0) + + +[sampler 0] +filter linear linear linear +address clamp clamp clamp +comparison greater + +[pixel shader] +Texture2D<float> t : register(t0); +SamplerComparisonState s : register(s0); + +float ref; + +float4 main() : sv_target +{ + return t.SampleCmp(s, float2(0.5, 0.5), ref); +} + +[test] +uniform 0 float 1.0 +draw quad +probe all r (1.0) + +uniform 0 float 0.0 +draw quad +probe all r (0.0) + diff --git a/tests/shader_runner.c b/tests/shader_runner.c index d0d806508..77d129a87 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -410,12 +410,46 @@ static void parse_sampler_directive(struct sampler *sampler, const char *line) if (match_string(line, filters[i].string, &line)) { sampler->filter = filters[i].filter; + if (sampler->func) + sampler->filter |= D3D12_FILTER_REDUCTION_TYPE_COMPARISON << D3D12_FILTER_REDUCTION_TYPE_SHIFT; return; } }
fatal_error("Unknown sampler filter '%s'.\n", line); } + else if (match_string(line, "comparison", &line)) + { + static const struct + { + const char *string; + D3D12_COMPARISON_FUNC func; + } + funcs[] = + { + {"never", D3D12_COMPARISON_FUNC_NEVER}, + {"less", D3D12_COMPARISON_FUNC_LESS}, + {"equal", D3D12_COMPARISON_FUNC_EQUAL}, + {"less equal", D3D12_COMPARISON_FUNC_LESS_EQUAL}, + {"greater", D3D12_COMPARISON_FUNC_GREATER}, + {"not equal", D3D12_COMPARISON_FUNC_NOT_EQUAL}, + {"greater equal", D3D12_COMPARISON_FUNC_GREATER_EQUAL}, + {"always", D3D12_COMPARISON_FUNC_ALWAYS}, + }; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(funcs); ++i) + { + if (match_string(line, funcs[i].string, &line)) + { + sampler->filter |= D3D12_FILTER_REDUCTION_TYPE_COMPARISON << D3D12_FILTER_REDUCTION_TYPE_SHIFT; + sampler->func = funcs[i].func; + return; + } + } + + fatal_error("Unknown sampler func '%s'.\n", line); + } else { fatal_error("Unknown sampler directive '%s'.\n", line); diff --git a/tests/shader_runner.h b/tests/shader_runner.h index 62358d78c..f750dae6d 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -62,6 +62,7 @@ struct sampler
D3D12_FILTER filter; D3D12_TEXTURE_ADDRESS_MODE u_address, v_address, w_address; + D3D12_COMPARISON_FUNC func; };
enum resource_type diff --git a/tests/shader_runner_d3d11.c b/tests/shader_runner_d3d11.c index 528c04e9d..d9310497a 100644 --- a/tests/shader_runner_d3d11.c +++ b/tests/shader_runner_d3d11.c @@ -509,7 +509,7 @@ static ID3D11SamplerState *create_sampler(ID3D11Device *device, const struct sam desc.AddressU = (D3D11_TEXTURE_ADDRESS_MODE)sampler->u_address; desc.AddressV = (D3D11_TEXTURE_ADDRESS_MODE)sampler->v_address; desc.AddressW = (D3D11_TEXTURE_ADDRESS_MODE)sampler->w_address; - desc.ComparisonFunc = D3D11_COMPARISON_NEVER; + desc.ComparisonFunc = sampler->func; desc.MaxLOD = D3D11_FLOAT32_MAX;
hr = ID3D11Device_CreateSamplerState(device, &desc, &d3d11_sampler); diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index ca1375124..ce27ad22a 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -325,6 +325,7 @@ static ID3D12RootSignature *d3d12_runner_create_root_signature(struct d3d12_shad sampler_desc->AddressU = sampler->u_address; sampler_desc->AddressV = sampler->v_address; sampler_desc->AddressW = sampler->w_address; + sampler_desc->ComparisonFunc = sampler->func; sampler_desc->MaxLOD = FLT_MAX; sampler_desc->ShaderRegister = sampler->slot; sampler_desc->RegisterSpace = 0; diff --git a/tests/shader_runner_gl.c b/tests/shader_runner_gl.c index 6cec33a43..fa6289540 100644 --- a/tests/shader_runner_gl.c +++ b/tests/shader_runner_gl.c @@ -785,6 +785,31 @@ static GLuint compile_graphics_shader_program(struct gl_runner *runner, ID3D10Bl return program_id; }
+static unsigned int gl_compare_op_from_d3d12(D3D12_COMPARISON_FUNC op) +{ + switch (op) + { + case D3D12_COMPARISON_FUNC_NEVER: + return GL_NEVER; + case D3D12_COMPARISON_FUNC_LESS: + return GL_LESS; + case D3D12_COMPARISON_FUNC_EQUAL: + return GL_EQUAL; + case D3D12_COMPARISON_FUNC_LESS_EQUAL: + return GL_LEQUAL; + case D3D12_COMPARISON_FUNC_GREATER: + return GL_GREATER; + case D3D12_COMPARISON_FUNC_NOT_EQUAL: + return GL_NOTEQUAL; + case D3D12_COMPARISON_FUNC_GREATER_EQUAL: + return GL_GEQUAL; + case D3D12_COMPARISON_FUNC_ALWAYS: + return GL_ALWAYS; + default: + fatal_error("Unhandled compare op %#x.\n", op); + } +} + static bool gl_runner_draw(struct shader_runner *r, D3D_PRIMITIVE_TOPOLOGY topology, unsigned int vertex_count) { @@ -837,6 +862,11 @@ static bool gl_runner_draw(struct shader_runner *r, glSamplerParameteri(id, GL_TEXTURE_WRAP_R, get_texture_wrap_gl(sampler->w_address)); glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, get_texture_filter_mag_gl(sampler->filter)); glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, get_texture_filter_min_gl(sampler->filter)); + if (sampler->func) + { + glSamplerParameteri(id, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); + glSamplerParameteri(id, GL_TEXTURE_COMPARE_FUNC, gl_compare_op_from_d3d12(sampler->func)); + } sampler_info[i].id = id; }
diff --git a/tests/shader_runner_vulkan.c b/tests/shader_runner_vulkan.c index 35db729b5..f266030ed 100644 --- a/tests/shader_runner_vulkan.c +++ b/tests/shader_runner_vulkan.c @@ -810,6 +810,31 @@ static VkSamplerAddressMode vk_address_mode_from_d3d12(D3D12_TEXTURE_ADDRESS_MOD } }
+static enum VkCompareOp vk_compare_op_from_d3d12(D3D12_COMPARISON_FUNC op) +{ + switch (op) + { + case D3D12_COMPARISON_FUNC_NEVER: + return VK_COMPARE_OP_NEVER; + case D3D12_COMPARISON_FUNC_LESS: + return VK_COMPARE_OP_LESS; + case D3D12_COMPARISON_FUNC_EQUAL: + return VK_COMPARE_OP_EQUAL; + case D3D12_COMPARISON_FUNC_LESS_EQUAL: + return VK_COMPARE_OP_LESS_OR_EQUAL; + case D3D12_COMPARISON_FUNC_GREATER: + return VK_COMPARE_OP_GREATER; + case D3D12_COMPARISON_FUNC_NOT_EQUAL: + return VK_COMPARE_OP_NOT_EQUAL; + case D3D12_COMPARISON_FUNC_GREATER_EQUAL: + return VK_COMPARE_OP_GREATER_OR_EQUAL; + case D3D12_COMPARISON_FUNC_ALWAYS: + return VK_COMPARE_OP_ALWAYS; + default: + fatal_error("Unhandled compare op %#x.\n", op); + } +} + static VkDescriptorSetLayout create_descriptor_set_layout(struct vulkan_shader_runner *runner) { VkDescriptorSetLayoutCreateInfo set_desc = {.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO}; @@ -874,6 +899,8 @@ static VkDescriptorSetLayout create_descriptor_set_layout(struct vulkan_shader_r sampler_desc.addressModeU = vk_address_mode_from_d3d12(sampler->u_address); sampler_desc.addressModeV = vk_address_mode_from_d3d12(sampler->v_address); sampler_desc.addressModeW = vk_address_mode_from_d3d12(sampler->w_address); + sampler_desc.compareEnable = !!sampler->func; + sampler_desc.compareOp = sampler->func ? vk_compare_op_from_d3d12(sampler->func) : 0; sampler_desc.maxLod = FLT_MAX;
VK_CALL(vkCreateSampler(runner->device, &sampler_desc, NULL, &vulkan_sampler->vk_sampler));
Testing without format D32 works on the CI, but fails in OpenGL locally. Using D32 passes all tests locally, but fails to create textures on the Windows CI, so looks like it would need tweaks to texture creation. We could also skip OpenGL if it becomes a problem.