-- v4: tests: Add a test for SV_ViewportArrayIndex. tests: Use test utils to create the pipeline state in test_ps_layer(). tests: Test using SV_RenderTargetArrayIndex in the vertex shader. tests: Compile HLSL shaders at runtime in test_ps_layer(). vkd3d-shader/tpf: Support SV_ViewportArrayIndex in pixel and vertex shaders. vkd3d-shader/tpf: Support SV_InstanceID in vertex shaders. vkd3d-shader/tpf: Support SV_RenderTargetArrayIndex in pixel and vertex shaders. vkd3d-shader/spirv: Use capability ShaderViewportIndexLayerEXT for decoration ViewportIndex. vkd3d-shader/spirv: Use capability ShaderViewportIndexLayerEXT for decoration Layer.
From: Giovanni Mascellani gmascellani@codeweavers.com
Capability Geometry allows to use the Layer builtin in geometry and pixel shaders. For vertex and domain shaders ShaderLayer should be used, but it's only available starting from SPIR-V 1.5. ShaderViewportIndexLayerEXT can be used instead with extension SPV_EXT_shader_viewport_index_layer. --- include/vkd3d_shader.h | 2 ++ libs/vkd3d-shader/spirv.c | 28 +++++++++++++++++++++++++++- libs/vkd3d/device.c | 9 +++++++-- libs/vkd3d/vkd3d_private.h | 3 ++- 4 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index b1a1fff64..040284531 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -871,6 +871,8 @@ enum vkd3d_shader_spirv_extension VKD3D_SHADER_SPIRV_EXTENSION_EXT_DESCRIPTOR_INDEXING, /** \since 1.3 */ VKD3D_SHADER_SPIRV_EXTENSION_EXT_STENCIL_EXPORT, + /** \since 1.11 */ + VKD3D_SHADER_SPIRV_EXTENSION_EXT_VIEWPORT_INDEX_LAYER,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_SPIRV_EXTENSION), }; diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 8a4704e56..ec14104b9 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -1949,6 +1949,8 @@ static bool vkd3d_spirv_compile_module(struct vkd3d_spirv_builder *builder, vkd3d_spirv_build_op_extension(&stream, "SPV_EXT_descriptor_indexing"); if (vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityStencilExportEXT)) vkd3d_spirv_build_op_extension(&stream, "SPV_EXT_shader_stencil_export"); + if (vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityShaderViewportIndexLayerEXT)) + vkd3d_spirv_build_op_extension(&stream, "SPV_EXT_shader_viewport_index_layer");
if (builder->ext_instr_set_glsl_450) vkd3d_spirv_build_op_ext_inst_import(&stream, builder->ext_instr_set_glsl_450, "GLSL.std.450"); @@ -4284,7 +4286,31 @@ static void spirv_compiler_decorate_builtin(struct spirv_compiler *compiler, spirv_compiler_emit_execution_mode(compiler, SpvExecutionModeDepthReplacing, NULL, 0); break; case SpvBuiltInLayer: - vkd3d_spirv_enable_capability(builder, SpvCapabilityGeometry); + switch (compiler->shader_type) + { + case VKD3D_SHADER_TYPE_PIXEL: + case VKD3D_SHADER_TYPE_GEOMETRY: + vkd3d_spirv_enable_capability(builder, SpvCapabilityGeometry); + break; + + case VKD3D_SHADER_TYPE_VERTEX: + case VKD3D_SHADER_TYPE_DOMAIN: + if (!spirv_compiler_is_target_extension_supported(compiler, + VKD3D_SHADER_SPIRV_EXTENSION_EXT_VIEWPORT_INDEX_LAYER)) + { + FIXME("The target environment does not support decoration Layer.\n"); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE, + "Cannot use SV_RenderTargetArrayIndex. " + "The target environment does not support decoration Layer."); + } + vkd3d_spirv_enable_capability(builder, SpvCapabilityShaderViewportIndexLayerEXT); + break; + + default: + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_SHADER, + "Invalid use of SV_RenderTargetArrayIndex."); + break; + } break; case SpvBuiltInViewportIndex: vkd3d_spirv_enable_capability(builder, SpvCapabilityMultiViewport); diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 69a46e918..f3a04ec01 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -97,6 +97,7 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] = VK_EXTENSION(EXT_ROBUSTNESS_2, EXT_robustness2), VK_EXTENSION(EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION, EXT_shader_demote_to_helper_invocation), VK_EXTENSION(EXT_SHADER_STENCIL_EXPORT, EXT_shader_stencil_export), + VK_EXTENSION(EXT_SHADER_VIEWPORT_INDEX_LAYER, EXT_shader_viewport_index_layer), VK_EXTENSION(EXT_TEXEL_BUFFER_ALIGNMENT, EXT_texel_buffer_alignment), VK_EXTENSION(EXT_TRANSFORM_FEEDBACK, EXT_transform_feedback), VK_EXTENSION(EXT_VERTEX_ATTRIBUTE_DIVISOR, EXT_vertex_attribute_divisor), @@ -1510,8 +1511,6 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, device->feature_options.StandardSwizzle64KBSupported = FALSE; device->feature_options.CrossNodeSharingTier = D3D12_CROSS_NODE_SHARING_TIER_NOT_SUPPORTED; device->feature_options.CrossAdapterRowMajorTextureSupported = FALSE; - /* SPV_EXT_shader_viewport_index_layer */ - device->feature_options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation = FALSE; device->feature_options.ResourceHeapTier = D3D12_RESOURCE_HEAP_TIER_2;
/* Shader Model 6 support. */ @@ -1615,6 +1614,8 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, vkd3d_free(vk_extensions);
device->feature_options.PSSpecifiedStencilRefSupported = vulkan_info->EXT_shader_stencil_export; + device->feature_options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation = + vulkan_info->EXT_shader_viewport_index_layer;
vkd3d_init_feature_level(vulkan_info, features, &device->feature_options); if (vulkan_info->max_feature_level < create_info->minimum_feature_level) @@ -1640,6 +1641,10 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, vulkan_info->shader_extensions[vulkan_info->shader_extension_count++] = VKD3D_SHADER_SPIRV_EXTENSION_EXT_STENCIL_EXPORT;
+ if (vulkan_info->EXT_shader_viewport_index_layer) + vulkan_info->shader_extensions[vulkan_info->shader_extension_count++] + = VKD3D_SHADER_SPIRV_EXTENSION_EXT_VIEWPORT_INDEX_LAYER; + /* Disable unused Vulkan features. */ features->shaderTessellationAndGeometryPointSize = VK_FALSE;
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index bf32d04c2..16bf040e0 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -55,7 +55,7 @@
#define VKD3D_MAX_COMPATIBLE_FORMAT_COUNT 6u #define VKD3D_MAX_QUEUE_FAMILY_COUNT 3u -#define VKD3D_MAX_SHADER_EXTENSIONS 3u +#define VKD3D_MAX_SHADER_EXTENSIONS 4u #define VKD3D_MAX_SHADER_STAGES 5u #define VKD3D_MAX_VK_SYNC_OBJECTS 4u #define VKD3D_MAX_DEVICE_BLOCKED_QUEUES 16u @@ -136,6 +136,7 @@ struct vkd3d_vulkan_info bool EXT_robustness2; bool EXT_shader_demote_to_helper_invocation; bool EXT_shader_stencil_export; + bool EXT_shader_viewport_index_layer; bool EXT_texel_buffer_alignment; bool EXT_transform_feedback; bool EXT_vertex_attribute_divisor;
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index ec14104b9..f7a26f7b5 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -4313,7 +4313,31 @@ static void spirv_compiler_decorate_builtin(struct spirv_compiler *compiler, } break; case SpvBuiltInViewportIndex: - vkd3d_spirv_enable_capability(builder, SpvCapabilityMultiViewport); + switch (compiler->shader_type) + { + case VKD3D_SHADER_TYPE_PIXEL: + case VKD3D_SHADER_TYPE_GEOMETRY: + vkd3d_spirv_enable_capability(builder, SpvCapabilityMultiViewport); + break; + + case VKD3D_SHADER_TYPE_VERTEX: + case VKD3D_SHADER_TYPE_DOMAIN: + if (!spirv_compiler_is_target_extension_supported(compiler, + VKD3D_SHADER_SPIRV_EXTENSION_EXT_VIEWPORT_INDEX_LAYER)) + { + FIXME("The target environment does not support decoration ViewportIndex.\n"); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE, + "Cannot use SV_ViewportArrayIndex. " + "The target environment does not support decoration ViewportIndex."); + } + vkd3d_spirv_enable_capability(builder, SpvCapabilityShaderViewportIndexLayerEXT); + break; + + default: + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_SHADER, + "Invalid use of SV_ViewportArrayIndex."); + break; + } break; case SpvBuiltInSampleId: vkd3d_spirv_enable_capability(builder, SpvCapabilitySampleRateShading);
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/tpf.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 2cc56663e..2236bc22d 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -2797,6 +2797,7 @@ bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semant {"position", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_POSITION}, {"sv_position", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_POSITION}, {"sv_isfrontface", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_IS_FRONT_FACE}, + {"sv_rendertargetarrayindex", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_RENDER_TARGET_ARRAY_INDEX},
{"color", true, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_TARGET}, {"depth", true, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_DEPTH}, @@ -2808,6 +2809,7 @@ bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semant
{"position", true, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_POSITION}, {"sv_position", true, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_POSITION}, + {"sv_rendertargetarrayindex", true, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_RENDER_TARGET_ARRAY_INDEX}, }; bool needs_compat_mapping = ascii_strncasecmp(semantic->name, "sv_", 3);
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/tpf.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 2236bc22d..372e234b1 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -2806,6 +2806,7 @@ bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semant
{"sv_position", false, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_UNDEFINED}, {"sv_vertexid", false, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_VERTEX_ID}, + {"sv_instanceid", false, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_INSTANCE_ID},
{"position", true, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_POSITION}, {"sv_position", true, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_POSITION},
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/tpf.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 372e234b1..111de3e33 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -2798,6 +2798,7 @@ bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semant {"sv_position", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_POSITION}, {"sv_isfrontface", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_IS_FRONT_FACE}, {"sv_rendertargetarrayindex", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_RENDER_TARGET_ARRAY_INDEX}, + {"sv_viewportarrayindex", false, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_VIEWPORT_ARRAY_INDEX},
{"color", true, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_TARGET}, {"depth", true, VKD3D_SHADER_TYPE_PIXEL, D3D_NAME_DEPTH}, @@ -2811,6 +2812,7 @@ bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semant {"position", true, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_POSITION}, {"sv_position", true, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_POSITION}, {"sv_rendertargetarrayindex", true, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_RENDER_TARGET_ARRAY_INDEX}, + {"sv_viewportarrayindex", true, VKD3D_SHADER_TYPE_VERTEX, D3D_NAME_VIEWPORT_ARRAY_INDEX}, }; bool needs_compat_mapping = ascii_strncasecmp(semantic->name, "sv_", 3);
From: Giovanni Mascellani gmascellani@codeweavers.com
--- tests/d3d12.c | 62 +++++++++++++++++++++------------------------------ 1 file changed, 25 insertions(+), 37 deletions(-)
diff --git a/tests/d3d12.c b/tests/d3d12.c index 427e59c22..f41de115f 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -28079,7 +28079,9 @@ static void test_ps_layer(void) { D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc; ID3D12GraphicsCommandList *command_list; + ID3D10Blob *vs_bytecode, *ps_bytecode; struct test_context_desc desc; + D3D12_SHADER_BYTECODE vs, ps; struct test_context context; ID3D12CommandQueue *queue; ID3D12Device *device; @@ -28087,23 +28089,11 @@ static void test_ps_layer(void) HRESULT hr;
static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; - static const DWORD vs_code[] = - { -#if 0 - void main(in uint vertex_id : SV_VertexID, out uint layer : LAYER) - { - layer = vertex_id; - } -#endif - 0x43425844, 0xd2b4abd8, 0xf9adf7df, 0xed1b4eb0, 0x4bf54391, 0x00000001, 0x000000d8, 0x00000003, - 0x0000002c, 0x00000060, 0x00000090, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, - 0x00000000, 0x00000006, 0x00000001, 0x00000000, 0x00000101, 0x565f5653, 0x65747265, 0x00444978, - 0x4e47534f, 0x00000028, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, - 0x00000000, 0x00000e01, 0x4559414c, 0xabab0052, 0x58454853, 0x00000040, 0x00010050, 0x00000010, - 0x0100086a, 0x04000060, 0x00101012, 0x00000000, 0x00000006, 0x03000065, 0x00102012, 0x00000000, - 0x05000036, 0x00102012, 0x00000000, 0x0010100a, 0x00000000, 0x0100003e, - }; - static const D3D12_SHADER_BYTECODE vs = {vs_code, sizeof(vs_code)}; + static const char vs_code[] = + "void main(in uint vertex_id : SV_VertexID, out uint layer : LAYER)\n" + "{\n" + " layer = vertex_id;\n" + "}\n"; static const DWORD gs_code[] = { #if 0 @@ -28153,26 +28143,11 @@ static void test_ps_layer(void) 0x0020100a, 0x00000000, 0x00000000, 0x03000075, 0x00110000, 0x00000000, 0x0100003e, }; static const D3D12_SHADER_BYTECODE gs = {gs_code, sizeof(gs_code)}; - static const DWORD ps_code[] = - { -#if 0 - float4 main(float4 p : SV_Position, uint layer : SV_RenderTargetArrayIndex) : SV_Target0 - { - return layer / 255.0; - } -#endif - 0x43425844, 0x53474926, 0xbd247b84, 0x389660f4, 0x331cf598, 0x00000001, 0x00000140, 0x00000003, - 0x0000002c, 0x00000094, 0x000000c8, 0x4e475349, 0x00000060, 0x00000002, 0x00000008, 0x00000038, - 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000004, - 0x00000001, 0x00000001, 0x00000101, 0x505f5653, 0x7469736f, 0x006e6f69, 0x525f5653, 0x65646e65, - 0x72615472, 0x41746567, 0x79617272, 0x65646e49, 0xabab0078, 0x4e47534f, 0x0000002c, 0x00000001, - 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, - 0x65677261, 0xabab0074, 0x58454853, 0x00000070, 0x00000050, 0x0000001c, 0x0100086a, 0x04000864, - 0x00101012, 0x00000001, 0x00000004, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, - 0x05000056, 0x00100012, 0x00000000, 0x0010100a, 0x00000001, 0x0a000038, 0x001020f2, 0x00000000, - 0x00100006, 0x00000000, 0x00004002, 0x3b808081, 0x3b808081, 0x3b808081, 0x3b808081, 0x0100003e, - }; - static const D3D12_SHADER_BYTECODE ps = {ps_code, sizeof(ps_code)}; + static const char ps_code[] = + "float4 main(float4 p : SV_Position, uint layer : SV_RenderTargetArrayIndex) : SV_Target0\n" + "{\n" + " return layer / 255.0;\n" + "}\n"; static const unsigned int expected_results[] = { 0x00000000, @@ -28183,11 +28158,21 @@ static void test_ps_layer(void) 0x05050505, };
+ vs_bytecode = compile_shader(vs_code, sizeof(vs_code) - 1, "vs_4_0"); + vs = shader_bytecode_from_blob(vs_bytecode); + + ps_bytecode = compile_shader(ps_code, sizeof(ps_code) - 1, "ps_4_0"); + ps = shader_bytecode_from_blob(ps_bytecode); + memset(&desc, 0, sizeof(desc)); desc.rt_array_size = 6; desc.no_pipeline = true; if (!init_test_context(&context, &desc)) + { + ID3D10Blob_Release(vs_bytecode); + ID3D10Blob_Release(ps_bytecode); return; + } device = context.device; command_list = context.list; queue = context.queue; @@ -28220,6 +28205,9 @@ static void test_ps_layer(void) }
destroy_test_context(&context); + + ID3D10Blob_Release(vs_bytecode); + ID3D10Blob_Release(ps_bytecode); }
static void test_nop_tessellation_shaders(void)
From: Giovanni Mascellani gmascellani@codeweavers.com
--- tests/d3d12.c | 95 ++++++++++++++++++++++----------------------------- 1 file changed, 40 insertions(+), 55 deletions(-)
diff --git a/tests/d3d12.c b/tests/d3d12.c index f41de115f..a70b356e9 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -576,6 +576,21 @@ static bool are_typed_uav_load_additional_formats_supported(ID3D12Device *device return options.TypedUAVLoadAdditionalFormats; }
+static bool is_vs_array_index_supported(ID3D12Device *device) +{ + D3D12_FEATURE_DATA_D3D12_OPTIONS options; + HRESULT hr; + + if (FAILED(hr = ID3D12Device_CheckFeatureSupport(device, + D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)))) + { + trace("Failed to check feature support, hr %#x.\n", hr); + return false; + } + + return options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportedWithoutGSEmulation; +} + #define create_cb_root_signature(a, b, c, e) create_cb_root_signature_(__LINE__, a, b, c, e) static ID3D12RootSignature *create_cb_root_signature_(unsigned int line, ID3D12Device *device, unsigned int reg_idx, D3D12_SHADER_VISIBILITY shader_visibility, @@ -28090,59 +28105,22 @@ static void test_ps_layer(void)
static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const char vs_code[] = - "void main(in uint vertex_id : SV_VertexID, out uint layer : LAYER)\n" + "float4 main(in uint vertex_id : SV_VertexID, in uint instance_id : SV_InstanceID,\n" + " out uint layer : SV_RenderTargetArrayIndex) : SV_Position\n" "{\n" - " layer = vertex_id;\n" + " layer = instance_id;\n" + " switch (vertex_id)\n" + " {\n" + " case 0:\n" + " return float4(-1, 1, 0, 1);\n" + " case 1:\n" + " return float4(3, 1, 0, 1);\n" + " case 2:\n" + " return float4(-1, -3, 0, 1);\n" + " default:\n" + " return float4(0, 0, 0, 0);\n" + " }\n" "}\n"; - static const DWORD gs_code[] = - { -#if 0 - struct gs_in - { - uint layer : LAYER; - }; - - struct gs_out - { - float4 position : SV_Position; - uint layer : SV_RenderTargetArrayIndex; - }; - - [maxvertexcount(3)] - void main(point gs_in vin[1], inout TriangleStream<gs_out> vout) - { - gs_out o; - - o.layer = vin[0].layer; - - o.position = float4(-1, 1, 0, 1); - vout.Append(o); - - o.position = float4(3, 1, 0, 1); - vout.Append(o); - - o.position = float4(-1, -3, 0, 1); - vout.Append(o); - } -#endif - 0x43425844, 0x2589d822, 0x7557587c, 0x7d7e9cc0, 0x6bad86aa, 0x00000001, 0x000001fc, 0x00000003, - 0x0000002c, 0x0000005c, 0x000000cc, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020, - 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000101, 0x4559414c, 0xabab0052, 0x3547534f, - 0x00000068, 0x00000002, 0x00000008, 0x00000000, 0x00000040, 0x00000000, 0x00000001, 0x00000003, - 0x00000000, 0x0000000f, 0x00000000, 0x0000004c, 0x00000000, 0x00000004, 0x00000001, 0x00000001, - 0x00000e01, 0x505f5653, 0x7469736f, 0x006e6f69, 0x525f5653, 0x65646e65, 0x72615472, 0x41746567, - 0x79617272, 0x65646e49, 0xabab0078, 0x58454853, 0x00000128, 0x00020050, 0x0000004a, 0x0100086a, - 0x0400005f, 0x00201012, 0x00000001, 0x00000000, 0x0100085d, 0x0300008f, 0x00110000, 0x00000000, - 0x0100285c, 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x04000067, 0x00102012, 0x00000001, - 0x00000004, 0x0200005e, 0x00000003, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, 0xbf800000, - 0x3f800000, 0x00000000, 0x3f800000, 0x06000036, 0x00102012, 0x00000001, 0x0020100a, 0x00000000, - 0x00000000, 0x03000075, 0x00110000, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, 0x00004002, - 0x40400000, 0x3f800000, 0x00000000, 0x3f800000, 0x06000036, 0x00102012, 0x00000001, 0x0020100a, - 0x00000000, 0x00000000, 0x03000075, 0x00110000, 0x00000000, 0x08000036, 0x001020f2, 0x00000000, - 0x00004002, 0xbf800000, 0xc0400000, 0x00000000, 0x3f800000, 0x06000036, 0x00102012, 0x00000001, - 0x0020100a, 0x00000000, 0x00000000, 0x03000075, 0x00110000, 0x00000000, 0x0100003e, - }; - static const D3D12_SHADER_BYTECODE gs = {gs_code, sizeof(gs_code)}; static const char ps_code[] = "float4 main(float4 p : SV_Position, uint layer : SV_RenderTargetArrayIndex) : SV_Target0\n" "{\n" @@ -28173,14 +28151,21 @@ static void test_ps_layer(void) ID3D10Blob_Release(ps_bytecode); return; } + + if (!is_vs_array_index_supported(context.device)) + { + skip("The device does not support SV_RenderTargetArrayIndex in VS.\n"); + destroy_test_context(&context); + return; + } + device = context.device; command_list = context.list; queue = context.queue;
init_pipeline_state_desc(&pso_desc, context.root_signature, context.render_target_desc.Format, &vs, &ps, NULL); - pso_desc.GS = gs; - pso_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; + pso_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; hr = ID3D12Device_CreateGraphicsPipelineState(device, &pso_desc, &IID_ID3D12PipelineState, (void **)&context.pipeline_state); ok(hr == S_OK, "Failed to create graphics pipeline state, hr %#x.\n", hr); @@ -28192,8 +28177,8 @@ static void test_ps_layer(void) ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); - ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_POINTLIST); - ID3D12GraphicsCommandList_DrawInstanced(command_list, 6, 1, 0, 0); + ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 6, 0, 0);
transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE);
From: Giovanni Mascellani gmascellani@codeweavers.com
--- tests/d3d12.c | 14 ++------------ tests/d3d12_test_utils.h | 3 ++- 2 files changed, 4 insertions(+), 13 deletions(-)
diff --git a/tests/d3d12.c b/tests/d3d12.c index a70b356e9..b5447f962 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -28092,16 +28092,13 @@ static void test_layered_rendering(void)
static void test_ps_layer(void) { - D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc; ID3D12GraphicsCommandList *command_list; ID3D10Blob *vs_bytecode, *ps_bytecode; struct test_context_desc desc; D3D12_SHADER_BYTECODE vs, ps; struct test_context context; ID3D12CommandQueue *queue; - ID3D12Device *device; unsigned int i; - HRESULT hr;
static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; static const char vs_code[] = @@ -28144,7 +28141,8 @@ static void test_ps_layer(void)
memset(&desc, 0, sizeof(desc)); desc.rt_array_size = 6; - desc.no_pipeline = true; + desc.vs = &vs; + desc.ps = &ps; if (!init_test_context(&context, &desc)) { ID3D10Blob_Release(vs_bytecode); @@ -28159,17 +28157,9 @@ static void test_ps_layer(void) return; }
- device = context.device; command_list = context.list; queue = context.queue;
- init_pipeline_state_desc(&pso_desc, context.root_signature, - context.render_target_desc.Format, &vs, &ps, NULL); - pso_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; - hr = ID3D12Device_CreateGraphicsPipelineState(device, &pso_desc, - &IID_ID3D12PipelineState, (void **)&context.pipeline_state); - ok(hr == S_OK, "Failed to create graphics pipeline state, hr %#x.\n", hr); - ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL);
ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); diff --git a/tests/d3d12_test_utils.h b/tests/d3d12_test_utils.h index 7473bbc43..e50ac45c5 100644 --- a/tests/d3d12_test_utils.h +++ b/tests/d3d12_test_utils.h @@ -994,6 +994,7 @@ struct test_context_desc bool no_render_target; bool no_root_signature; bool no_pipeline; + const D3D12_SHADER_BYTECODE *vs; const D3D12_SHADER_BYTECODE *ps; };
@@ -1153,7 +1154,7 @@ static inline bool init_test_context_(unsigned int line, struct test_context *co
context->pipeline_state = create_pipeline_state_(line, device, context->root_signature, context->render_target_desc.Format, - NULL, desc ? desc->ps : NULL, NULL); + desc ? desc->vs : NULL, desc ? desc->ps : NULL, NULL);
return true; }
From: Giovanni Mascellani gmascellani@codeweavers.com
--- tests/d3d12.c | 98 ++++++++++++++++++++++++++++++++++++++++ tests/d3d12_test_utils.h | 12 +++++ 2 files changed, 110 insertions(+)
diff --git a/tests/d3d12.c b/tests/d3d12.c index b5447f962..dad9c317c 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -28185,6 +28185,103 @@ static void test_ps_layer(void) ID3D10Blob_Release(ps_bytecode); }
+static void test_ps_viewport_index(void) +{ + ID3D12GraphicsCommandList *command_list; + ID3D10Blob *vs_bytecode, *ps_bytecode; + struct test_context_desc desc; + D3D12_SHADER_BYTECODE vs, ps; + struct test_context context; + D3D12_VIEWPORT viewports[4]; + ID3D12CommandQueue *queue; + D3D12_BOX box; + + static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; + static const char vs_code[] = + "float4 main(in uint vertex_id : SV_VertexID, in uint instance_id : SV_InstanceID,\n" + " out uint viewport : SV_ViewportArrayIndex) : SV_Position\n" + "{\n" + " viewport = instance_id;\n" + " switch (vertex_id)\n" + " {\n" + " case 0:\n" + " return float4(-1, 1, 0, 1);\n" + " case 1:\n" + " return float4(3, 1, 0, 1);\n" + " case 2:\n" + " return float4(-1, -3, 0, 1);\n" + " default:\n" + " return float4(0, 0, 0, 0);\n" + " }\n" + "}\n"; + static const char ps_code[] = + "float4 main(float4 p : SV_Position, uint viewport : SV_ViewportArrayIndex) : SV_Target0\n" + "{\n" + " return viewport / 255.0;\n" + "}\n"; + + vs_bytecode = compile_shader(vs_code, sizeof(vs_code) - 1, "vs_4_0"); + vs = shader_bytecode_from_blob(vs_bytecode); + + ps_bytecode = compile_shader(ps_code, sizeof(ps_code) - 1, "ps_4_0"); + ps = shader_bytecode_from_blob(ps_bytecode); + + memset(&desc, 0, sizeof(desc)); + desc.vs = &vs; + desc.ps = &ps; + if (!init_test_context(&context, &desc)) + { + ID3D10Blob_Release(vs_bytecode); + ID3D10Blob_Release(ps_bytecode); + return; + } + + if (!is_vs_array_index_supported(context.device)) + { + skip("The device does not support SV_ViewportArrayIndex in VS.\n"); + destroy_test_context(&context); + return; + } + + command_list = context.list; + queue = context.queue; + + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, white, 0, NULL); + + set_viewport(&viewports[0], + 0.0f, 0.0f, + context.render_target_desc.Width / 2, context.render_target_desc.Height / 2, 0.0f, 1.0f); + set_viewport(&viewports[1], + context.render_target_desc.Width / 2, 0.0f, + context.render_target_desc.Width, context.render_target_desc.Height / 2, 0.0f, 1.0f); + set_viewport(&viewports[2], + 0.0f, context.render_target_desc.Height / 2, + context.render_target_desc.Width / 2, context.render_target_desc.Height, 0.0f, 1.0f); + set_viewport(&viewports[3], + context.render_target_desc.Width / 2, context.render_target_desc.Height / 2, + context.render_target_desc.Width, context.render_target_desc.Height, 0.0f, 1.0f); + + ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); + ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); + ID3D12GraphicsCommandList_RSSetViewports(command_list, ARRAY_SIZE(viewports), viewports); + ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); + ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); + ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 4, 0, 0); + + transition_resource_state(command_list, context.render_target, + D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); + + set_box(&box, 0, 0, 0, context.render_target_desc.Width / 2, context.render_target_desc.Height / 2, 1); + check_sub_resource_uint_with_box(context.render_target, 0, queue, command_list, &box, 0x00000000, 0); + reset_command_list(command_list, context.allocator); + + destroy_test_context(&context); + + ID3D10Blob_Release(vs_bytecode); + ID3D10Blob_Release(ps_bytecode); +} + static void test_nop_tessellation_shaders(void) { static const float white[] = {1.0f, 1.0f, 1.0f, 1.0f}; @@ -37641,6 +37738,7 @@ START_TEST(d3d12) run_test(test_geometry_shader); run_test(test_layered_rendering); run_test(test_ps_layer); + run_test(test_ps_viewport_index); run_test(test_nop_tessellation_shaders); run_test(test_quad_tessellation); run_test(test_tessellation_dcl_index_range); diff --git a/tests/d3d12_test_utils.h b/tests/d3d12_test_utils.h index e50ac45c5..6de828d17 100644 --- a/tests/d3d12_test_utils.h +++ b/tests/d3d12_test_utils.h @@ -585,6 +585,18 @@ static inline void check_sub_resource_uint_(unsigned int line, ID3D12Resource *t release_resource_readback(&rb); }
+#define check_sub_resource_uint_with_box(a, b, c, d, e, f, g) check_sub_resource_uint_with_box_(__LINE__, a, b, c, d, e, f, g) +static inline void check_sub_resource_uint_with_box_(unsigned int line, ID3D12Resource *texture, + unsigned int sub_resource_idx, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list, + const D3D12_BOX *box, unsigned int expected, unsigned int max_diff) +{ + struct d3d12_resource_readback rb; + + get_resource_readback_with_command_list(texture, sub_resource_idx, &rb, queue, command_list); + check_readback_data_uint_(line, &rb.rb, box, expected, max_diff); + release_resource_readback(&rb); +} + #define check_sub_resource_vec4(a, b, c, d, e, f) check_sub_resource_vec4_(__LINE__, a, b, c, d, e, f) static inline void check_sub_resource_vec4_(unsigned int line, ID3D12Resource *texture, unsigned int sub_resource_idx, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list,
This merge request was approved by Giovanni Mascellani.
This should now be appropriately tested.
This merge request was approved by Henri Verbeet.
Why both a FIXME and a spirv_compiler_error()?
On Mon Jan 22 20:52:58 2024 +0000, Zebediah Figura wrote:
Why both a FIXME and a spirv_compiler_error()?
I copied that from a similar instance. We're also using that scheme a lot in the DXIL parser. The reason I see is that the error is meant to be sent to the API client, so they know why their shader is failing compilation. But that information might not necessarily reach the Wine developer who is trying to make an application work with vkd3d, hence the FIXME.
On Mon Jan 22 20:52:58 2024 +0000, Giovanni Mascellani wrote:
I copied that from a similar instance. We're also using that scheme a lot in the DXIL parser. The reason I see is that the error is meant to be sent to the API client, so they know why their shader is failing compilation. But that information might not necessarily reach the Wine developer who is trying to make an application work with vkd3d, hence the FIXME.
Isn't the solution there for Wine to be printing vkd3d-shader errors as ERR? I thought I remembered a discussion specifically about this before.
On Mon Jan 22 21:26:34 2024 +0000, Zebediah Figura wrote:
Isn't the solution there for Wine to be printing vkd3d-shader errors as ERR? I thought I remembered a discussion specifically about this before.
It might be an alternative solution I guess. Right now, though, compilation errors are not even stored if logging is not enabled, while even if the application doesn't want logging (and, for example, vkd3d doesn't request logging when compiling to SPIR-V IIRC) the Wine developer could still be interested in seeing those failures. Also ERRs are shown even vkd3d-shader crashes before finishing the compilation. Of course both of these objections could be handled in a different way, but the current solution doesn't look terrible either to me, so I never cared too much.