diff --git a/Makefile.am b/Makefile.am index 50b6c48c..92f5365f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -81,6 +81,7 @@ vkd3d_shader_tests = \ tests/hlsl/cf-cond-types.shader_test \ tests/hlsl/clamp.shader_test \ tests/hlsl/clip-distance.shader_test \ + tests/hlsl/clip-planes.shader_test \ tests/hlsl/clip.shader_test \ tests/hlsl/combined-samplers.shader_test \ tests/hlsl/comma.shader_test \ diff --git a/tests/hlsl/clip-planes.shader_test b/tests/hlsl/clip-planes.shader_test new file mode 100644 index 00000000..d3a46f39 --- /dev/null +++ b/tests/hlsl/clip-planes.shader_test @@ -0,0 +1,43 @@ +[require] +clip-planes + +[pixel shader] +float4 main() : sv_target +{ + return 1.0; +} + +[test] +clear rtv 0 0 0 0 0 +clip-plane 1 1.0 1.0 0.0 0.0 +clip-plane 3 -1.0 1.0 0.0 0.0 +draw quad + +probe (320, 120) rgba (1, 1, 1, 1) +probe (320, 360) rgba (0, 0, 0, 0) +probe (160, 240) rgba (0, 0, 0, 0) +probe (480, 240) rgba (0, 0, 0, 0) + +clear rtv 0 0 0 0 0 +clip-plane 0 1.0 0.0 0.0 0.5 +clip-plane 1 -1.0 0.0 0.0 0.5 +clip-plane 2 0.0 1.0 0.0 0.5 +clip-plane 3 0.0 -1.0 0.0 0.5 +clip-plane 5 1.0 1.0 0.0 0.2 +draw quad + +probe (150, 130) rgba (0, 0, 0, 0) +probe (170, 110) rgba (0, 0, 0, 0) +probe (170, 130) rgba (1, 1, 1, 1) + +probe (490, 130) rgba (0, 0, 0, 0) +probe (470, 110) rgba (0, 0, 0, 0) +probe (470, 130) rgba (1, 1, 1, 1) + +probe (150, 350) rgba (0, 0, 0, 0) +probe (170, 370) rgba (0, 0, 0, 0) +probe (170, 350) rgba (0, 0, 0, 0) + +probe (490, 350) rgba (0, 0, 0, 0) +probe (470, 370) rgba (0, 0, 0, 0) +probe (470, 350) rgba (1, 1, 1, 1) diff --git a/tests/shader_runner.c b/tests/shader_runner.c index 51c0a6a3..94b9a79c 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -407,6 +407,10 @@ static void parse_require_directive(struct shader_runner *runner, const char *li { runner->require_depth_bounds = true; } + else if (match_string(line, "clip-planes", &line)) + { + runner->require_clip_planes = true; + } else { fatal_error("Unknown require directive '%s'.\n", line); @@ -1295,6 +1299,27 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) else runner->flat_shading = false; } + else if (match_string(line, "clip-plane", &line)) + { + unsigned int index; + struct vec4 *v; + + index = strtoul(line, (char **)&rest, 10); + if (rest == line || index >= 8) + fatal_error("Malformed clip plane directive '%s'.\n", line); + line = rest; + + v = &runner->clip_planes[index]; + + if (match_string(line, "disable", &line)) + runner->clip_plane_mask &= ~(1u << index); + else + { + if (sscanf(line, "%f %f %f %f", &v->x, &v->y, &v->z, &v->w) < 4) + fatal_error("Malformed float4 constant '%s'.\n", line); + runner->clip_plane_mask |= (1u << index); + } + } else { fatal_error("Unknown test directive '%s'.\n", line); @@ -1610,6 +1635,8 @@ static bool check_capabilities(const struct shader_runner *runner, const struct return false; if (runner->require_depth_bounds && !caps->depth_bounds) return false; + if (runner->require_clip_planes && !caps->clip_planes) + return false; for (i = 0; i < ARRAY_SIZE(runner->require_format_caps); ++i) { @@ -1989,6 +2016,7 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_c runner->require_rov = false; runner->require_wave_ops = false; runner->require_depth_bounds = false; + runner->require_clip_planes = false; memset(runner->require_format_caps, 0, sizeof(runner->require_format_caps)); runner->compile_options = 0; test_action = TEST_ACTION_RUN; diff --git a/tests/shader_runner.h b/tests/shader_runner.h index 78d72ebe..a4ae8b95 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -147,6 +147,7 @@ struct shader_runner_caps bool rov; bool wave_ops; bool depth_bounds; + bool clip_planes; uint32_t format_caps[DXGI_FORMAT_COUNT]; }; @@ -184,6 +185,7 @@ struct shader_runner bool require_rov; bool require_wave_ops; bool require_depth_bounds; + bool require_clip_planes; uint32_t require_format_caps[DXGI_FORMAT_COUNT]; bool last_render_failed; @@ -215,6 +217,8 @@ struct shader_runner enum vkd3d_shader_comparison_func alpha_test_func; float alpha_test_ref; bool flat_shading; + uint8_t clip_plane_mask; + struct vec4 clip_planes[8]; }; struct shader_runner_ops diff --git a/tests/shader_runner_d3d9.c b/tests/shader_runner_d3d9.c index 696dd906..30fc5cdc 100644 --- a/tests/shader_runner_d3d9.c +++ b/tests/shader_runner_d3d9.c @@ -152,6 +152,7 @@ static bool init_test_context(struct d3d9_shader_runner *runner) runner->caps.runner = "d3d9.dll"; runner->caps.minimum_shader_model = SHADER_MODEL_2_0; runner->caps.maximum_shader_model = SHADER_MODEL_3_0; + runner->caps.clip_planes = true; return true; } @@ -469,6 +470,16 @@ static bool d3d9_runner_draw(struct shader_runner *r, runner->r.flat_shading ? D3DSHADE_FLAT : D3DSHADE_GOURAUD); ok(hr == D3D_OK, "Failed to set render state, hr %#lx.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, TRUE); + ok(hr == D3D_OK, "Failed to set render state, hr %#lx.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPLANEENABLE, runner->r.clip_plane_mask); + ok(hr == D3D_OK, "Failed to set render state, hr %#lx.\n", hr); + for (unsigned int i = 0; i < 8; ++i) + { + hr = IDirect3DDevice9_SetClipPlane(device, i, &runner->r.clip_planes[i].x); + ok(hr == D3D_OK, "Failed to set clip plane, 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 36773dcc..8bbbe8d9 100644 --- a/tests/shader_runner_vulkan.c +++ b/tests/shader_runner_vulkan.c @@ -451,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_parameter1 parameters[4]; + struct vkd3d_shader_parameter1 parameters[13]; struct vkd3d_shader_compile_option *option; unsigned int i, compile_options; char profile[7]; @@ -621,6 +621,19 @@ static bool compile_shader(struct vulkan_shader_runner *runner, const char *sour parameters[3].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32; parameters[3].u.immediate_constant.u.u32 = runner->r.flat_shading; + parameters[4].name = VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_MASK; + parameters[4].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT; + parameters[4].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32; + parameters[4].u.immediate_constant.u.u32 = runner->r.clip_plane_mask; + + for (i = 0; i < 8; ++i) + { + parameters[5 + i].name = VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_0 + i; + parameters[5 + i].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT; + parameters[5 + i].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4; + memcpy(parameters[5 + i].u.immediate_constant.u.f32_vec4, &runner->r.clip_planes[i], 4 * sizeof(float)); + } + parameter_info.parameter_count = ARRAY_SIZE(parameters); parameter_info.parameters = parameters; @@ -1787,6 +1800,8 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner) get_physical_device_info(runner, &device_info); ret_features = &device_info.features2.features; + runner->caps.clip_planes = true; + device_desc.pEnabledFeatures = &features; memset(&features, 0, sizeof(features)); @@ -1803,6 +1818,7 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner) ENABLE_FEATURE(fragmentStoresAndAtomics); /* For SV_PrimitiveID/SpvBuiltInPrimitiveId in fragment shaders. */ ENABLE_FEATURE(geometryShader); + ENABLE_FEATURE(shaderClipDistance); ENABLE_FEATURE(shaderImageGatherExtended); ENABLE_FEATURE(shaderStorageImageWriteWithoutFormat);