diff --git a/Makefile.am b/Makefile.am index 0374324a..01d73167 100644 --- a/Makefile.am +++ b/Makefile.am @@ -48,6 +48,7 @@ vkd3d_cross_tests = \ vkd3d_shader_tests = \ tests/hlsl/abs.shader_test \ tests/hlsl/all.shader_test \ + tests/hlsl/alpha-test.shader_test \ tests/hlsl/angle-unit.shader_test \ tests/hlsl/annotations.shader_test \ tests/hlsl/any.shader_test \ diff --git a/tests/hlsl/alpha-test.shader_test b/tests/hlsl/alpha-test.shader_test new file mode 100644 index 00000000..8c5b1b3d --- /dev/null +++ b/tests/hlsl/alpha-test.shader_test @@ -0,0 +1,78 @@ +% Testing equality comparison is a bit tricky here. The alpha test ref is +% fed through a UNORM in d3d, so we can only pass a value that's a multiple of +% 1/255 from 0 to 1. While we can quantize to an integer from 0-255, dividing +% back down by 255 yields slightly inconsistent results. Fortunately, testing +% 1.0 works and is a lot more reliable. + +[require] +shader model < 4.0 + +[vertex shader] +void main(inout float4 pos : position, out float alpha : texcoord) +{ + alpha = pos.x; +} + +[pixel shader] +float4 main(float alpha : texcoord) : sv_target +{ + return float4(0, 1, 0, floor((alpha + 1) * 2 + 0.5) / 2); +} + +[test] + +alpha test always +clear rtv 0 1 0 0 1 +draw quad +probe (160, 0) rgba (0, 1, 0, 0.5) +probe (320, 0) rgba (0, 1, 0, 1.0) +probe (480, 0) rgba (0, 1, 0, 1.5) + +alpha test equal 1.0 +clear rtv 0 1 0 0 1 +draw quad +probe (160, 0) rgba (1, 0, 0, 1) +probe (320, 0) rgba (0, 1, 0, 1.0) +probe (480, 0) rgba (1, 0, 0, 1) + +alpha test not equal 1.0 +clear rtv 0 1 0 0 1 +draw quad +probe (160, 0) rgba (0, 1, 0, 0.5) +probe (320, 0) rgba (1, 0, 0, 1) +probe (480, 0) rgba (0, 1, 0, 1.5) + +alpha test greater 1.0 +clear rtv 0 1 0 0 1 +draw quad +probe (160, 0) rgba (1, 0, 0, 1) +probe (320, 0) rgba (1, 0, 0, 1) +probe (480, 0) rgba (0, 1, 0, 1.5) + +alpha test greater equal 1.0 +clear rtv 0 1 0 0 1 +draw quad +probe (160, 0) rgba (1, 0, 0, 1) +probe (320, 0) rgba (0, 1, 0, 1.0) +probe (480, 0) rgba (0, 1, 0, 1.5) + +alpha test less equal 1.0 +clear rtv 0 1 0 0 1 +draw quad +probe (160, 0) rgba (0, 1, 0, 0.5) +probe (320, 0) rgba (0, 1, 0, 1.0) +probe (480, 0) rgba (1, 0, 0, 1) + +alpha test less 1.0 +clear rtv 0 1 0 0 1 +draw quad +probe (160, 0) rgba (0, 1, 0, 0.5) +probe (320, 0) rgba (1, 0, 0, 1) +probe (480, 0) rgba (1, 0, 0, 1) + +alpha test never +clear rtv 0 1 0 0 1 +draw quad +probe (160, 0) rgba (1, 0, 0, 1) +probe (320, 0) rgba (1, 0, 0, 1) +probe (480, 0) rgba (1, 0, 0, 1) diff --git a/tests/shader_runner.c b/tests/shader_runner.c index 4285d5d5..2019f0c9 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -394,7 +394,7 @@ static DXGI_FORMAT parse_format(const char *line, enum texture_data_type *data_t fatal_error("Unknown format '%s'.\n", line); } -static D3D12_COMPARISON_FUNC parse_comparison_func(const char *line) +static D3D12_COMPARISON_FUNC parse_comparison_func(const char *line, const char **rest) { static const struct { @@ -416,7 +416,7 @@ static D3D12_COMPARISON_FUNC parse_comparison_func(const char *line) for (i = 0; i < ARRAY_SIZE(funcs); ++i) { - if (match_string(line, funcs[i].string, &line)) + if (match_string(line, funcs[i].string, rest)) return funcs[i].func; } @@ -483,7 +483,7 @@ static void parse_sampler_directive(struct sampler *sampler, const char *line) else if (match_string(line, "comparison", &line)) { sampler->filter |= D3D12_FILTER_REDUCTION_TYPE_COMPARISON << D3D12_FILTER_REDUCTION_TYPE_SHIFT; - sampler->func = parse_comparison_func(line); + sampler->func = parse_comparison_func(line, &line); return; } else @@ -868,6 +868,8 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) if (sscanf(line, "%u %f %f %f %f", &slot, &v.x, &v.y, &v.z, &v.w) < 5) fatal_error("Malformed rtv clear arguments '%s'.\n", line); + set_default_target(runner); + if (!(resource = shader_runner_get_resource(runner, RESOURCE_TYPE_RENDER_TARGET, slot))) fatal_error("Resource not found.\n"); runner->ops->clear(runner, resource, &v); @@ -886,7 +888,7 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) } else if (match_string(line, "depth", &line)) { - runner->depth_func = parse_comparison_func(line); + runner->depth_func = parse_comparison_func(line, &line); } else if (match_string(line, "draw quad", &line)) { @@ -1247,6 +1249,12 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) read_uint(&line, &sample_mask, false); runner->sample_mask = sample_mask; } + else if (match_string(line, "alpha test", &line)) + { + runner->alpha_test_func = (enum vkd3d_shader_comparison_func)parse_comparison_func(line, &line); + runner->alpha_test_ref = strtof(line, &rest); + line = rest; + } else { fatal_error("Unknown test directive '%s'.\n", line); @@ -1636,6 +1644,7 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_c runner->caps = caps; runner->minimum_shader_model = caps->minimum_shader_model; runner->maximum_shader_model = caps->maximum_shader_model; + runner->alpha_test_func = VKD3D_SHADER_COMPARISON_FUNC_ALWAYS; runner->sample_mask = ~0u; diff --git a/tests/shader_runner.h b/tests/shader_runner.h index 8588dc3e..277a28de 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -197,6 +197,9 @@ struct shader_runner unsigned int compile_options; D3D12_COMPARISON_FUNC depth_func; + + enum vkd3d_shader_comparison_func alpha_test_func; + float alpha_test_ref; }; struct shader_runner_ops diff --git a/tests/shader_runner_d3d9.c b/tests/shader_runner_d3d9.c index fbfa2d12..2ddc092c 100644 --- a/tests/shader_runner_d3d9.c +++ b/tests/shader_runner_d3d9.c @@ -326,7 +326,15 @@ static bool d3d9_runner_dispatch(struct shader_runner *r, unsigned int x, unsign static void d3d9_runner_clear(struct shader_runner *r, struct resource *resource, const struct vec4 *clear_value) { - fatal_error("Clears are not implemented.\n"); + struct d3d9_shader_runner *runner = d3d9_shader_runner(r); + unsigned int colour; + HRESULT hr; + + colour = vkd3d_make_u32(vkd3d_make_u16(clear_value->z * 255.0, clear_value->y * 255.0), + vkd3d_make_u16(clear_value->x * 255.0, clear_value->w * 255.0)); + + hr = IDirect3DDevice9_ColorFill(runner->device, d3d9_resource(resource)->surface, NULL, colour); + ok(hr == S_OK, "Got hr %#lx.\n", hr); } static bool d3d9_runner_draw(struct shader_runner *r, @@ -448,6 +456,15 @@ static bool d3d9_runner_draw(struct shader_runner *r, ok(hr == D3D_OK, "Failed to set sampler state, hr %#lx.\n", hr); } + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, TRUE); + ok(hr == D3D_OK, "Failed to set render state, hr %#lx.\n", hr); + /* The members of enum vkd3d_shader_parameter_alpha_test_func are + * compatible with D3DCMPFUNC. */ + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAFUNC, runner->r.alpha_test_func); + ok(hr == D3D_OK, "Failed to set render state, hr %#lx.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAREF, runner->r.alpha_test_ref * 255.0); + ok(hr == D3D_OK, "Failed to set render state, hr %#lx.\n", hr); + hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration); ok(hr == D3D_OK, "Failed to create vertex declaration, hr %#lx.\n", hr); hr = IDirect3DDevice9_CreateVertexShader(device, ID3D10Blob_GetBufferPointer(vs_code), &vs); diff --git a/tests/shader_runner_vulkan.c b/tests/shader_runner_vulkan.c index b5d06cce..fc02f680 100644 --- a/tests/shader_runner_vulkan.c +++ b/tests/shader_runner_vulkan.c @@ -443,6 +443,7 @@ static bool compile_shader(struct vulkan_shader_runner *runner, const char *sour { struct vkd3d_shader_spirv_target_info spirv_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_SPIRV_TARGET_INFO}; struct vkd3d_shader_interface_info interface_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO}; + struct vkd3d_shader_parameter_info parameter_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_PARAMETER_INFO}; struct vkd3d_shader_hlsl_source_info hlsl_info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_HLSL_SOURCE_INFO}; struct vkd3d_shader_compile_info info = {.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO}; struct vkd3d_shader_resource_binding bindings[MAX_RESOURCES + MAX_SAMPLERS]; @@ -450,7 +451,7 @@ static bool compile_shader(struct vulkan_shader_runner *runner, const char *sour enum vkd3d_shader_spirv_extension spirv_extensions[2]; struct vkd3d_shader_resource_binding *binding; struct vkd3d_shader_compile_option options[3]; - struct vkd3d_shader_parameter parameters[1]; + struct vkd3d_shader_parameter1 parameters[3]; struct vkd3d_shader_compile_option *option; unsigned int i, compile_options; char profile[7]; @@ -594,6 +595,7 @@ static bool compile_shader(struct vulkan_shader_runner *runner, const char *sour binding->binding.count = 1; } + interface_info.next = ¶meter_info; interface_info.bindings = bindings; interface_info.push_constant_buffer_count = 1; @@ -604,12 +606,22 @@ static bool compile_shader(struct vulkan_shader_runner *runner, const char *sour parameters[0].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32; parameters[0].u.immediate_constant.u.u32 = runner->r.sample_count; - spirv_info.parameter_count = ARRAY_SIZE(parameters); - spirv_info.parameters = parameters; + parameters[1].name = VKD3D_SHADER_PARAMETER_NAME_ALPHA_TEST_FUNC; + parameters[1].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT; + parameters[1].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32; + parameters[1].u.immediate_constant.u.u32 = runner->r.alpha_test_func; + + parameters[2].name = VKD3D_SHADER_PARAMETER_NAME_ALPHA_TEST_REF; + parameters[2].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT; + parameters[2].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32; + parameters[2].u.immediate_constant.u.f32 = runner->r.alpha_test_ref; + + parameter_info.parameter_count = ARRAY_SIZE(parameters); + parameter_info.parameters = parameters; if (!strcmp(type, "vs")) { - interface_info.next = &runner->vs_signatures; + parameter_info.next = &runner->vs_signatures; runner->vs_signatures.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_SIGNATURE_INFO; runner->vs_signatures.next = NULL;