Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- tests/d3d12.c | 106 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 30 deletions(-)
diff --git a/tests/d3d12.c b/tests/d3d12.c index 89b1f000..09cc0e98 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -14417,11 +14417,11 @@ static void test_gather_c(void)
static void test_sample_c_lz(void) { + struct depth_stencil_resource ds, ds_offset; D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc; ID3D12GraphicsCommandList *command_list; D3D12_DEPTH_STENCIL_VIEW_DESC dsv_desc; D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle; - struct depth_stencil_resource ds; struct test_context_desc desc; struct resource_readback rb; struct test_context context; @@ -14429,7 +14429,7 @@ static void test_sample_c_lz(void) ID3D12CommandQueue *queue; struct vec4 ps_constant; ID3D12Device *device; - unsigned int i; + unsigned int i, j; RECT rect;
static const D3D12_STATIC_SAMPLER_DESC sampler_desc = @@ -14472,6 +14472,36 @@ static void test_sample_c_lz(void) 0x00000000, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x0100003e, }; static const D3D12_SHADER_BYTECODE ps_array = {ps_array_code, sizeof(ps_array_code)}; + static const DWORD ps_array_offset_code[] = + { +#if 0 + Texture2DArray t; + SamplerComparisonState s; + + float ref; + float layer; + + float4 main(float4 position : SV_Position) : SV_Target + { + return t.SampleCmpLevelZero(s, float3(position.x / 5120.0f, position.y / 3840.0f, layer), ref, + int2(4, 4)); + } +#endif + 0x43425844, 0xdf99ade1, 0x420d8d11, 0x3abe4b31, 0x116badd9, 0x00000001, 0x0000018c, 0x00000003, + 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, + 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x7469736f, 0x006e6f69, + 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, + 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x000000f0, 0x00000050, + 0x0000003c, 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x0300085a, 0x00106000, + 0x00000000, 0x04004058, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, + 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000038, 0x00100032, + 0x00000000, 0x00101046, 0x00000000, 0x00004002, 0x394ccccd, 0x39888889, 0x00000000, 0x00000000, + 0x06000036, 0x00100042, 0x00000000, 0x0020801a, 0x00000000, 0x00000000, 0x8f000047, 0x80008801, + 0x80000202, 0x00155543, 0x00100012, 0x00000000, 0x00100246, 0x00000000, 0x00107006, 0x00000000, + 0x00106000, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x05000036, 0x001020f2, 0x00000000, + 0x00100006, 0x00000000, 0x0100003e, + }; + static const D3D12_SHADER_BYTECODE ps_array_offset = {ps_array_offset_code, sizeof(ps_array_offset_code)}; static const DWORD ps_cube_code[] = { #if 0 @@ -14590,15 +14620,15 @@ static void test_sample_c_lz(void) heap = create_gpu_descriptor_heap(context.device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 6); cpu_handle = ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(heap);
- /* 2D array texture */ - context.pipeline_state = create_pipeline_state(context.device, - context.root_signature, context.render_target_desc.Format, NULL, &ps_array, NULL); - init_depth_stencil(&ds, device, 32, 32, ARRAY_SIZE(depth_values), 2, DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_D32_FLOAT, NULL); + init_depth_stencil(&ds_offset, device, 32, 32, ARRAY_SIZE(depth_values), 2, + DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_D32_FLOAT, NULL);
for (i = 0; i < ARRAY_SIZE(depth_values); ++i) { + static const D3D12_RECT rects[] = {{0, 0, 3, 3}, {3, 3, 32, 32}}; + memset(&dsv_desc, 0, sizeof(dsv_desc)); dsv_desc.Format = DXGI_FORMAT_D32_FLOAT; dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DARRAY; @@ -14607,6 +14637,11 @@ static void test_sample_c_lz(void) ID3D12Device_CreateDepthStencilView(device, ds.texture, &dsv_desc, ds.dsv_handle); ID3D12GraphicsCommandList_ClearDepthStencilView(command_list, ds.dsv_handle, D3D12_CLEAR_FLAG_DEPTH, depth_values[i], 0, 0, NULL); + ID3D12Device_CreateDepthStencilView(device, ds_offset.texture, &dsv_desc, ds_offset.dsv_handle); + ID3D12GraphicsCommandList_ClearDepthStencilView(command_list, ds_offset.dsv_handle, + D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 1, &rects[0]); + ID3D12GraphicsCommandList_ClearDepthStencilView(command_list, ds_offset.dsv_handle, + D3D12_CLEAR_FLAG_DEPTH, depth_values[i], 0, 1, &rects[1]);
dsv_desc.Texture2DArray.MipSlice = 1; ID3D12Device_CreateDepthStencilView(device, ds.texture, &dsv_desc, ds.dsv_handle); @@ -14623,44 +14658,54 @@ static void test_sample_c_lz(void) srv_desc.Texture2DArray.FirstArraySlice = 0; srv_desc.Texture2DArray.ArraySize = ARRAY_SIZE(depth_values); ID3D12Device_CreateShaderResourceView(context.device, ds.texture, &srv_desc, cpu_handle); + ID3D12Device_CreateShaderResourceView(context.device, ds_offset.texture, &srv_desc, + get_cpu_descriptor_handle(&context, heap, 1));
transition_resource_state(command_list, ds.texture, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
memset(&ps_constant, 0, sizeof(ps_constant)); - for (i = 0; i < ARRAY_SIZE(tests); ++i) + for (j = 0; j < 2; ++j) { - vkd3d_test_set_context("test %u", i); + /* 2D array texture */ + context.pipeline_state = create_pipeline_state(context.device, + context.root_signature, context.render_target_desc.Format, NULL, + j ? &ps_array_offset : &ps_array, NULL);
- ps_constant.x = tests[i].d_ref; - ps_constant.y = tests[i].layer; + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + vkd3d_test_set_context("test %u%s", i, j ? " offset" : "");
- ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, clear_color, 0, NULL); - ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); - ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); - ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); - ID3D12GraphicsCommandList_SetDescriptorHeaps(command_list, 1, &heap); - ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, 0, - get_gpu_descriptor_handle(&context, heap, 0)); - ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(command_list, 1, 4, &ps_constant.x, 0); - ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); - ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); - ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); + ps_constant.x = tests[i].d_ref; + ps_constant.y = tests[i].layer;
- transition_resource_state(command_list, context.render_target, - D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context.rtv, clear_color, 0, NULL); + ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context.rtv, false, NULL); + ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context.root_signature); + ID3D12GraphicsCommandList_SetPipelineState(command_list, context.pipeline_state); + ID3D12GraphicsCommandList_SetDescriptorHeaps(command_list, 1, &heap); + ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, 0, + get_gpu_descriptor_handle(&context, heap, j)); + ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(command_list, 1, 4, &ps_constant.x, 0); + ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context.viewport); + ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context.scissor_rect); + ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0);
- check_sub_resource_float(context.render_target, 0, queue, command_list, tests[i].expected, 2); + transition_resource_state(command_list, context.render_target, + D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE);
- reset_command_list(command_list, context.allocator); - transition_resource_state(command_list, context.render_target, - D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); + todo_if(j && tests[i].d_ref > 0.0f) + check_sub_resource_float(context.render_target, 0, queue, command_list, tests[i].expected, 2); + + reset_command_list(command_list, context.allocator); + transition_resource_state(command_list, context.render_target, + D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); + } + ID3D12PipelineState_Release(context.pipeline_state); } vkd3d_test_set_context(NULL);
- ID3D12PipelineState_Release(context.pipeline_state); - /* cube texture */ context.pipeline_state = create_pipeline_state(context.device, context.root_signature, context.render_target_desc.Format, NULL, &ps_cube, NULL); @@ -14709,6 +14754,7 @@ static void test_sample_c_lz(void) vkd3d_test_set_context(NULL);
destroy_depth_stencil(&ds); + destroy_depth_stencil(&ds_offset); ID3D12DescriptorHeap_Release(heap); destroy_test_context(&context); }
From: Philip Rebohle philip.rebohle@tu-dortmund.de Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 13 +++++++++---- tests/d3d12.c | 1 - 2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index f604b8ef..5a8fd9e1 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -8196,12 +8196,9 @@ static void vkd3d_dxbc_compiler_emit_sample_c(struct vkd3d_dxbc_compiler *compil SpvImageOperandsMask operands_mask = 0; unsigned int image_operand_count = 0; struct vkd3d_shader_image image; - uint32_t image_operands[1]; + uint32_t image_operands[2]; SpvOp op;
- if (vkd3d_shader_instruction_has_texel_offset(instruction)) - FIXME("Texel offset not supported.\n"); - if (instruction->handler_idx == VKD3DSIH_SAMPLE_C_LZ) { op = SpvOpImageSampleDrefExplicitLod; @@ -8216,6 +8213,14 @@ static void vkd3d_dxbc_compiler_emit_sample_c(struct vkd3d_dxbc_compiler *compil
vkd3d_dxbc_compiler_prepare_image(compiler, &image, &src[1].reg, &src[2].reg, VKD3D_IMAGE_FLAG_SAMPLED | VKD3D_IMAGE_FLAG_DEPTH); + + if (vkd3d_shader_instruction_has_texel_offset(instruction)) + { + operands_mask |= SpvImageOperandsConstOffsetMask; + image_operands[image_operand_count++] = vkd3d_dxbc_compiler_emit_texel_offset(compiler, + instruction, image.resource_type_info); + } + sampled_type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, 1); coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_ALL); dref_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[3], VKD3DSP_WRITEMASK_0); diff --git a/tests/d3d12.c b/tests/d3d12.c index 09cc0e98..6c435ac0 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -14695,7 +14695,6 @@ static void test_sample_c_lz(void) transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE);
- todo_if(j && tests[i].d_ref > 0.0f) check_sub_resource_float(context.render_target, 0, queue, command_list, tests[i].expected, 2);
reset_command_list(command_list, context.allocator);
This was fixed around three years ago in the 396 and later 390 drivers.
From: Philip Rebohle philip.rebohle@tu-dortmund.de Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 5a8fd9e1..ac544acb 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -8189,7 +8189,7 @@ static void vkd3d_dxbc_compiler_emit_sample(struct vkd3d_dxbc_compiler *compiler static void vkd3d_dxbc_compiler_emit_sample_c(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { - uint32_t sampled_type_id, coordinate_id, dref_id, val_id, type_id; + uint32_t sampled_type_id, coordinate_id, dref_id, val_id; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; const struct vkd3d_shader_dst_param *dst = instruction->dst; const struct vkd3d_shader_src_param *src = instruction->src; @@ -8224,10 +8224,6 @@ static void vkd3d_dxbc_compiler_emit_sample_c(struct vkd3d_dxbc_compiler *compil sampled_type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, 1); coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_ALL); dref_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[3], VKD3DSP_WRITEMASK_0); - /* XXX: Nvidia is broken and expects that the D_ref is packed together with coordinates. */ - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE); - coordinate_id = vkd3d_spirv_build_op_composite_insert1(builder, - type_id, dref_id, coordinate_id, image.resource_type_info->coordinate_component_count); val_id = vkd3d_spirv_build_op_image_sample_dref(builder, op, sampled_type_id, image.sampled_image_id, coordinate_id, dref_id, operands_mask, image_operands, image_operand_count);
Works around a driver bug on NV which affected RE2 in particular, but probably other titles as well.
Based on a vkd3d-proton patch by Hans-Kristian Arntzen.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index ac544acb..19e9cfc6 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -8177,7 +8177,10 @@ static void vkd3d_dxbc_compiler_emit_sample(struct vkd3d_dxbc_compiler *compiler }
sampled_type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE); - coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_ALL); + /* Technically, we can always pass vec4 down to sample operations, but NV drivers currently + * have a bug here when using texture arrays. */ + coordinate_id = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[0], + vkd3d_write_mask_from_component_count(image.resource_type_info->coordinate_component_count)); assert(image_operand_count <= ARRAY_SIZE(image_operands)); val_id = vkd3d_spirv_build_op_image_sample(builder, op, sampled_type_id, image.sampled_image_id, coordinate_id, operands_mask, image_operands, image_operand_count);
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- tests/d3d12.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/tests/d3d12.c b/tests/d3d12.c index 6c435ac0..86a295a9 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -9881,6 +9881,8 @@ static void test_shader_instructions(void) {{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}}, {&ps_ishl, {{{0xfefefefe, 0x0fefefef, 0x0f0f0f0f, 0x12345678}, {~0x1fu, 0, 32, 64}}}, {{0xfefefefe, 0x0fefefef, 0x0f0f0f0f, 0x12345678}}}, + {&ps_ishl, {{{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, { 33, 34, 65, 66}}}, + {{0xfffffffe, 0xfffffffc, 0xfffffffe, 0xfffffffc}}}, {&ps_ishl, {{{0x00000000, 0x00000000, 0x00000000, 0x00000000}, { 31, 7, 15, 11}}}, {{0x00000000, 0x00000000, 0x00000000, 0x00000000}}}, {&ps_ishl, {{{0x80000000, 0x80000000, 0x80000000, 0x80000000}, { 31, 7, 15, 11}}},
This is undefined behaviour in SPIR-V, but well-defined in DXBC, so we should explicitly 'and' the shift amount with 31.
Based on a vkd3d-proton patch by Philip Rebohle.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 19e9cfc6..9499159c 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -6829,6 +6829,16 @@ static void vkd3d_dxbc_compiler_emit_alu_instruction(struct vkd3d_dxbc_compiler for (i = 0; i < instruction->src_count; ++i) src_ids[i] = vkd3d_dxbc_compiler_emit_load_src(compiler, &src[i], dst->write_mask);
+ /* The SPIR-V specification states, "The resulting value is undefined if Shift is greater than or + * equal to the bit width of the components of Base." D3D applies only the lowest 5 bits of the shift. */ + if (src[1].reg.type != VKD3DSPR_IMMCONST && (instruction->handler_idx == VKD3DSIH_ISHL + || instruction->handler_idx == VKD3DSIH_ISHR || instruction->handler_idx == VKD3DSIH_USHR)) + { + uint32_t mask_id = vkd3d_dxbc_compiler_get_constant_vector(compiler, VKD3D_SHADER_COMPONENT_UINT, + vkd3d_write_mask_component_count(dst->write_mask), 0x1f); + src_ids[1] = vkd3d_spirv_build_op_and(builder, type_id, src_ids[1], mask_id); + } + val_id = vkd3d_spirv_build_op_trv(builder, &builder->function_stream, op, type_id, src_ids, instruction->src_count); if (instruction->flags & VKD3DSI_PRECISE_XYZW)
On Tue, 28 Sept 2021 at 07:39, Conor McCarthy cmccarthy@codeweavers.com wrote:
- /* The SPIR-V specification states, "The resulting value is undefined if Shift is greater than or
* equal to the bit width of the components of Base." D3D applies only the lowest 5 bits of the shift. */
- if (src[1].reg.type != VKD3DSPR_IMMCONST && (instruction->handler_idx == VKD3DSIH_ISHL
|| instruction->handler_idx == VKD3DSIH_ISHR || instruction->handler_idx == VKD3DSIH_USHR))
- {
uint32_t mask_id = vkd3d_dxbc_compiler_get_constant_vector(compiler, VKD3D_SHADER_COMPONENT_UINT,
vkd3d_write_mask_component_count(dst->write_mask), 0x1f);
src_ids[1] = vkd3d_spirv_build_op_and(builder, type_id, src_ids[1], mask_id);
- }
Is there any particular reason to avoid handling VKD3DSPR_IMMCONST shifts? I suppose immediate shifts are unlikely to be larger than 31, but it should also be easy to verify that.
October 12, 2021 1:59 AM, "Henri Verbeet" hverbeet@gmail.com wrote:
Is there any particular reason to avoid handling VKD3DSPR_IMMCONST shifts? I suppose immediate shifts are unlikely to be larger than 31, but it should also be easy to verify that.
It turns out fxc will happily compile a shift > 31 and store the constants unmasked. The simplest solution is emit the OpBitwiseAnd for immediate shifts too, which drivers should easily be able to optimise out. I'll send a new patch for this.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- tests/d3d12.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
diff --git a/tests/d3d12.c b/tests/d3d12.c index 86a295a9..20eeac9d 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -7807,6 +7807,45 @@ static void test_shader_instructions(void) 0x00000000, 0x0100003e, }; static struct named_shader ps_loop_break = {"loop_break", ps_loop_break_code, sizeof(ps_loop_break_code)}; + static const DWORD ps_loop_end_break_code[] = + { +#if 0 + float4 src0; + + void main(out float4 dst : SV_Target) + { + float tmp = 0.0f; + for (int i = 0; i < src0.x; ++i) + { + if (i != src0.y) + { + tmp += 1.0f; + continue; + } + tmp = 1.0f; + break; + } + + dst = float4(tmp, 0, 0, 0); + } +#endif + 0x43425844, 0x0239f900, 0x5b94f73f, 0x68b75aa3, 0x27d353d2, 0x00000001, 0x000001e0, 0x00000003, + 0x0000002c, 0x0000003c, 0x00000070, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, + 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000, + 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x58454853, 0x00000168, 0x00000050, 0x0000005a, + 0x0100086a, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, + 0x02000068, 0x00000001, 0x08000036, 0x00100032, 0x00000000, 0x00004002, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x01000030, 0x0500002b, 0x00100042, 0x00000000, 0x0010001a, 0x00000000, + 0x0800001d, 0x00100082, 0x00000000, 0x0010002a, 0x00000000, 0x0020800a, 0x00000000, 0x00000000, + 0x03040003, 0x0010003a, 0x00000000, 0x08000039, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, + 0x0020801a, 0x00000000, 0x00000000, 0x0304001f, 0x0010002a, 0x00000000, 0x07000000, 0x00100012, + 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0700001e, 0x00100042, 0x00000000, + 0x0010001a, 0x00000000, 0x00004001, 0x00000001, 0x05000036, 0x00100032, 0x00000000, 0x00100086, + 0x00000000, 0x01000007, 0x01000015, 0x05000036, 0x00100012, 0x00000000, 0x00004001, 0x3f800000, + 0x01000002, 0x01000016, 0x05000036, 0x00102012, 0x00000000, 0x0010000a, 0x00000000, 0x08000036, + 0x001020e2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0100003e, + }; + static struct named_shader ps_loop_end_break = {"loop_end_break", ps_loop_end_break_code, sizeof(ps_loop_end_break_code)}; static const DWORD ps_loop_ret_code[] = { #if 0 @@ -9617,6 +9656,8 @@ static void test_shader_instructions(void) {&ps_loop_break, {{7.0f, 8.0f}}, {{7.0f}}}, {&ps_loop_break, {{7.0f, 9.0f}}, {{7.0f}}},
+ {&ps_loop_end_break, {{7.0f, 2.0f}}, {{1.0f}}}, + {&ps_loop_ret, {{0.0f, 0.0f}}, {{0.0f}}}, {&ps_loop_ret, {{1.0f, 9.0f}}, {{1.0f}}}, {&ps_loop_ret, {{2.0f, 2.0f}}, {{2.0f}}}, @@ -10350,6 +10391,12 @@ static void test_shader_instructions(void) continue; }
+ if (tests[i].ps == &ps_loop_end_break && !vkd3d_test_platform_is_windows()) + { + skip("Skipping shader '%s' test (would generate invalid SPIR-V).\n", tests[i].ps->name); + continue; + } + if (current_ps != tests[i].ps) { if (context.pipeline_state)
Fixes invalid SPIR-V in case there is an unconditional break right before the loop ends.
From: Philip Rebohle philip.rebohle@tu-dortmund.de Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 4 +++- tests/d3d12.c | 6 ------ 2 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 9499159c..7d479184 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -7615,6 +7615,7 @@ static int vkd3d_dxbc_compiler_emit_control_flow_instruction(struct vkd3d_dxbc_c cf_info->u.loop.continue_block_id = continue_block_id; cf_info->u.loop.merge_block_id = merge_block_id; cf_info->current_block = VKD3D_BLOCK_LOOP; + cf_info->inside_block = true;
vkd3d_spirv_build_op_name(builder, loop_header_block_id, "loop%u_header", compiler->loop_id); vkd3d_spirv_build_op_name(builder, loop_body_block_id, "loop%u_body", compiler->loop_id); @@ -7627,7 +7628,8 @@ static int vkd3d_dxbc_compiler_emit_control_flow_instruction(struct vkd3d_dxbc_c assert(compiler->control_flow_depth); assert(cf_info->current_block == VKD3D_BLOCK_LOOP);
- vkd3d_spirv_build_op_branch(builder, cf_info->u.loop.continue_block_id); + if (cf_info->inside_block) + vkd3d_spirv_build_op_branch(builder, cf_info->u.loop.continue_block_id);
vkd3d_spirv_build_op_label(builder, cf_info->u.loop.continue_block_id); vkd3d_spirv_build_op_branch(builder, cf_info->u.loop.header_block_id); diff --git a/tests/d3d12.c b/tests/d3d12.c index 20eeac9d..8dbced41 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -10391,12 +10391,6 @@ static void test_shader_instructions(void) continue; }
- if (tests[i].ps == &ps_loop_end_break && !vkd3d_test_platform_is_windows()) - { - skip("Skipping shader '%s' test (would generate invalid SPIR-V).\n", tests[i].ps->name); - continue; - } - if (current_ps != tests[i].ps) { if (context.pipeline_state)
This can happen if a continue statement is immediately followed by a break instruction in a switch case.
From: Philip Rebohle philip.rebohle@tu-dortmund.de Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 7d479184..849f5e86 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -7754,8 +7754,10 @@ static int vkd3d_dxbc_compiler_emit_control_flow_instruction(struct vkd3d_dxbc_c } else if (breakable_cf_info->current_block == VKD3D_BLOCK_SWITCH) { - assert(breakable_cf_info->inside_block); - vkd3d_spirv_build_op_branch(builder, breakable_cf_info->u.switch_.merge_block_id); + /* It is possible that we already broke out of the + * current case block with a continue statement. */ + if (breakable_cf_info->inside_block) + vkd3d_spirv_build_op_branch(builder, breakable_cf_info->u.switch_.merge_block_id); }
cf_info->inside_block = false;