From: Philip Rebohle Subject: [PATCH vkd3d 10/11] vkd3d-shader: Handle tessellation factor built-ins in emit_output. Message-Id: <20191016195544.23720-11-philip.rebohle@tu-dortmund.de> Date: Wed, 16 Oct 2019 21:55:44 +0200 In-Reply-To: <20191016195544.23720-1-philip.rebohle@tu-dortmund.de> References: <20191016195544.23720-1-philip.rebohle@tu-dortmund.de> Uses the private patch constant array for tess factor built-ins. Fixes two separate issues encountered in Shadow of the Tomb Raider: - The output registers that have one component mapped to any of the TESS_FACTOR sysvals can have their other components mapped to a regular patch constant output, in which case we need to use a private io variable. - The tess factor outputs are not necessarily dynamically indexed within shader code. Previously, this did not work correctly and lead to invalid store operations in the generated SPIR-V. Signed-off-by: Philip Rebohle --- libs/vkd3d-shader/spirv.c | 84 ++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 46 deletions(-) diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 9bffc70..7678db0 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -4311,6 +4311,31 @@ static void vkd3d_dxbc_compiler_emit_output_register(struct vkd3d_dxbc_compiler vkd3d_dxbc_compiler_emit_register_debug_name(builder, output_id, reg); } +static uint32_t vkd3d_dxbc_compiler_emit_shader_phase_builtin_variable(struct vkd3d_dxbc_compiler *compiler, + const struct vkd3d_shader_phase *phase, const struct vkd3d_spirv_builtin *builtin) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t *variable_id, id; + + variable_id = NULL; + + if (builtin->spirv_builtin == SpvBuiltInTessLevelOuter) + variable_id = &compiler->hs.tess_level_outer_id; + else if (builtin->spirv_builtin == SpvBuiltInTessLevelInner) + variable_id = &compiler->hs.tess_level_inner_id; + + if (variable_id && *variable_id) + return *variable_id; + + id = vkd3d_dxbc_compiler_emit_builtin_variable(compiler, builtin, SpvStorageClassOutput, 0); + if (phase->type == VKD3DSIH_HS_FORK_PHASE || phase->type == VKD3DSIH_HS_JOIN_PHASE) + vkd3d_spirv_build_op_decorate(builder, id, SpvDecorationPatch, NULL, 0); + + if (variable_id) + *variable_id = id; + return id; +} + static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_dst_param *dst, enum vkd3d_shader_input_sysval_semantic sysval) { @@ -4396,8 +4421,19 @@ static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler { if (builtin) { - id = vkd3d_dxbc_compiler_emit_builtin_variable(compiler, builtin, storage_class, array_size); + if (phase) + id = vkd3d_dxbc_compiler_emit_shader_phase_builtin_variable(compiler, phase, builtin); + else + id = vkd3d_dxbc_compiler_emit_builtin_variable(compiler, builtin, storage_class, array_size); + + if (builtin->spirv_array_size) + { + compiler->output_info[signature_idx].array_element_mask = + calculate_sysval_array_mask(compiler, shader_signature, sysval); + } + vkd3d_dxbc_compiler_emit_register_execution_mode(compiler, &dst->reg); + if (component_idx) FIXME("Unhandled component index %u.\n", component_idx); } @@ -4480,46 +4516,6 @@ static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler } } -static void vkd3d_dxbc_compiler_emit_shader_phase_output(struct vkd3d_dxbc_compiler *compiler, - const struct vkd3d_shader_phase *phase, const struct vkd3d_shader_dst_param *dst, - enum vkd3d_shader_input_sysval_semantic sysval) -{ - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - const struct vkd3d_shader_register *reg = &dst->reg; - const struct vkd3d_spirv_builtin *builtin; - struct vkd3d_symbol reg_symbol; - uint32_t *variable_id; - - variable_id = NULL; - if ((builtin = get_spirv_builtin_for_sysval(compiler, sysval))) - { - if (builtin->spirv_builtin == SpvBuiltInTessLevelOuter) - variable_id = &compiler->hs.tess_level_outer_id; - else if (builtin->spirv_builtin == SpvBuiltInTessLevelInner) - variable_id = &compiler->hs.tess_level_inner_id; - } - - if (!variable_id) - { - FIXME("Unhandled shader phase output register %#x, sysval %#x.\n", reg->type, sysval); - return; - } - - if (!*variable_id) - { - *variable_id = vkd3d_dxbc_compiler_emit_builtin_variable(compiler, builtin, SpvStorageClassOutput, 0); - if (phase->type == VKD3DSIH_HS_FORK_PHASE || phase->type == VKD3DSIH_HS_JOIN_PHASE) - vkd3d_spirv_build_op_decorate(builder, *variable_id, SpvDecorationPatch, NULL, 0); - } - - vkd3d_symbol_make_register(®_symbol, reg); - vkd3d_symbol_set_register_info(®_symbol, *variable_id, SpvStorageClassOutput, - builtin->component_type, vkd3d_write_mask_from_component_count(builtin->component_count)); - reg_symbol.info.reg.member_idx = builtin->member_idx; - reg_symbol.info.reg.is_aggregate = builtin->spirv_array_size; - vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol); -} - static uint32_t vkd3d_dxbc_compiler_get_output_array_index(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_signature_element *e) { @@ -5381,15 +5377,11 @@ static void vkd3d_dxbc_compiler_emit_dcl_output_siv(struct vkd3d_dxbc_compiler * { enum vkd3d_shader_input_sysval_semantic sysval; const struct vkd3d_shader_dst_param *dst; - const struct vkd3d_shader_phase *phase; dst = &instruction->declaration.register_semantic.reg; sysval = instruction->declaration.register_semantic.sysval_semantic; - if ((phase = vkd3d_dxbc_compiler_get_current_shader_phase(compiler))) - vkd3d_dxbc_compiler_emit_shader_phase_output(compiler, phase, dst, sysval); - else - vkd3d_dxbc_compiler_emit_output(compiler, dst, sysval); + vkd3d_dxbc_compiler_emit_output(compiler, dst, sysval); } static bool vkd3d_dxbc_compiler_check_index_range(struct vkd3d_dxbc_compiler *compiler, -- 2.23.0