Signed-off-by: Henri Verbeet hverbeet@codeweavers.com --- libs/vkd3d-shader/spirv.c | 38 +++++++++++++++++++++++++++++++++----- tests/d3d12.c | 2 +- 2 files changed, 34 insertions(+), 6 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index a639f7e8..a6e5e223 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -4252,7 +4252,9 @@ static uint32_t vkd3d_dxbc_compiler_emit_input(struct vkd3d_dxbc_compiler *compi }
if (!(use_private_var = builtin && builtin->fixup_pfn) - && needs_private_io_variable(shader_signature, reg_idx, builtin, &input_component_count, &write_mask)) + && needs_private_io_variable(shader_signature, reg_idx, builtin, &input_component_count, &write_mask) + && (compiler->shader_type != VKD3D_SHADER_TYPE_HULL + || (reg->type != VKD3DSPR_INCONTROLPOINT && reg->type != VKD3DSPR_PATCHCONST))) use_private_var = true; else component_idx = vkd3d_write_mask_get_component_idx(write_mask); @@ -4266,20 +4268,45 @@ static uint32_t vkd3d_dxbc_compiler_emit_input(struct vkd3d_dxbc_compiler *compi symbol = RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry); input_id = symbol->id; } - else if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL && reg->type == VKD3DSPR_INCONTROLPOINT) - { + else if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL + && (reg->type == VKD3DSPR_INCONTROLPOINT || reg->type == VKD3DSPR_PATCHCONST)) + { + /* Input/output registers from one phase can be used as inputs in + * subsequent phases. Specifically: + * + * - Control phase inputs are available as "vicp" in fork and join + * phases. + * - Control phase outputs are available as "vocp" in fork and join + * phases. + * - Fork phase patch constants are available as "vpc" in join + * phases. + * + * We handle "vicp" and "vpc" here by creating aliases to the shader's + * global inputs and outputs. We handle "vocp" in + * vkd3d_dxbc_compiler_leave_shader_phase(). */ + tmp_symbol = reg_symbol; - tmp_symbol.key.reg.type = VKD3DSPR_INPUT; + if (reg->type == VKD3DSPR_PATCHCONST) + tmp_symbol.key.reg.type = VKD3DSPR_OUTPUT; + else + tmp_symbol.key.reg.type = VKD3DSPR_INPUT;
if ((entry = rb_get(&compiler->symbol_table, &tmp_symbol))) { symbol = RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry); tmp_symbol = *symbol; - tmp_symbol.key.reg.type = VKD3DSPR_INCONTROLPOINT; + tmp_symbol.key.reg.type = reg->type; vkd3d_dxbc_compiler_put_symbol(compiler, &tmp_symbol);
input_id = symbol->id; } + else + { + if (reg->type == VKD3DSPR_PATCHCONST) + ERR("Patch constant register %u was not declared in a previous phase.\n", reg_idx); + else + ERR("Input control point register %u was not declared in a previous phase.\n", reg_idx); + } }
if (!symbol || ~symbol->info.reg.dcl_mask & write_mask) @@ -4418,6 +4445,7 @@ static void vkd3d_dxbc_compiler_emit_shader_phase_input(struct vkd3d_dxbc_compil { case VKD3DSPR_INPUT: case VKD3DSPR_INCONTROLPOINT: + case VKD3DSPR_PATCHCONST: vkd3d_dxbc_compiler_emit_input(compiler, dst, VKD3D_SIV_NONE, VKD3DSIM_NONE); return; case VKD3DSPR_PRIMID: diff --git a/tests/d3d12.c b/tests/d3d12.c index dfdbefa5..f289a10d 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -33809,7 +33809,7 @@ static void test_hull_shader_patch_constant_inputs(void) transition_resource_state(command_list, so_buffer, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_RESOURCE_STATE_COPY_SOURCE); get_buffer_readback_with_command_list(so_buffer, DXGI_FORMAT_UNKNOWN, &rb, queue, command_list); - todo check_triangles(&rb, &expected_triangle, 1); + check_triangles(&rb, &expected_triangle, 1); release_resource_readback(&rb);
ID3D12Resource_Release(so_buffer);