diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 261a1453..6a3eb10c 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2029,6 +2029,7 @@ struct vkd3d_hull_shader_variables { uint32_t tess_level_outer_id; uint32_t tess_level_inner_id; + uint32_t patch_constants_id; }; struct vkd3d_dxbc_compiler @@ -4322,7 +4323,8 @@ static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler write_mask = dst->write_mask; else if (get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_NO_SWIZZLE || needs_private_io_variable(shader_signature, signature_element->register_index, - builtin, &output_component_count, &write_mask)) + builtin, &output_component_count, &write_mask) + || is_patch_constant) { use_private_variable = true; write_mask = VKD3DSP_WRITEMASK_ALL; @@ -4393,6 +4395,8 @@ static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler var_id = RB_ENTRY_VALUE(entry, const struct vkd3d_symbol, entry)->id; else if (!use_private_variable) var_id = id; + else if (is_patch_constant) + var_id = compiler->hs.patch_constants_id; else var_id = vkd3d_dxbc_compiler_emit_variable(compiler, &builder->global_stream, storage_class, VKD3D_TYPE_FLOAT, VKD3D_VEC4_SIZE); @@ -4400,15 +4404,21 @@ static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler { vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, use_private_variable ? VKD3D_TYPE_FLOAT : component_type, write_mask); - reg_symbol.info.reg.is_aggregate = use_private_variable ? false : array_size; + reg_symbol.info.reg.is_aggregate = use_private_variable ? is_patch_constant : array_size; if (!use_private_variable && is_control_point_phase(phase)) { reg_symbol.info.reg.member_idx = vkd3d_dxbc_compiler_get_invocation_id(compiler); reg_symbol.info.reg.is_dynamically_indexed = true; } + else if (is_patch_constant) + { + reg_symbol.info.reg.member_idx = reg->idx[0].offset; + } + vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol); - vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg); + if (!is_patch_constant) + vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg); } if (use_private_variable) @@ -4416,6 +4426,9 @@ static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler unsigned int idx = vkd3d_dxbc_compiler_get_output_variable_index(compiler, reg->idx[0].offset); compiler->private_output_variable[idx] = var_id; compiler->private_output_variable_write_mask[idx] |= dst->write_mask; + if (is_patch_constant) + compiler->private_output_variable_array_idx[idx] = vkd3d_dxbc_compiler_get_constant_uint( + compiler, reg->idx[0].offset); if (!compiler->epilogue_function_id) compiler->epilogue_function_id = vkd3d_spirv_alloc_id(builder); } @@ -4626,6 +4639,24 @@ static void vkd3d_dxbc_compiler_emit_hull_shader_builtins(struct vkd3d_dxbc_comp vkd3d_dxbc_compiler_emit_input_register(compiler, &dst); } +static void vkd3d_dxbc_compiler_emit_hull_shader_patch_constants(struct vkd3d_dxbc_compiler *compiler) +{ + const struct vkd3d_shader_signature *signature = compiler->patch_constant_signature; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t register_count = 0; + unsigned int signature_idx; + + for (signature_idx = 0; signature_idx < signature->element_count; ++signature_idx) + register_count = max(register_count, signature->elements[signature_idx].register_index + 1); + + if (!register_count) + return; + + compiler->hs.patch_constants_id = vkd3d_dxbc_compiler_emit_array_variable(compiler, &builder->global_stream, + SpvStorageClassPrivate, VKD3D_TYPE_FLOAT, VKD3D_VEC4_SIZE, register_count); + vkd3d_spirv_build_op_name(builder, compiler->hs.patch_constants_id, "opc"); +} + static void vkd3d_dxbc_compiler_emit_initial_declarations(struct vkd3d_dxbc_compiler *compiler) { const struct vkd3d_shader_transform_feedback_info *xfb_info = compiler->xfb_info; @@ -4639,6 +4670,7 @@ static void vkd3d_dxbc_compiler_emit_initial_declarations(struct vkd3d_dxbc_comp case VKD3D_SHADER_TYPE_HULL: vkd3d_spirv_set_execution_model(builder, SpvExecutionModelTessellationControl); vkd3d_dxbc_compiler_emit_hull_shader_builtins(compiler); + vkd3d_dxbc_compiler_emit_hull_shader_patch_constants(compiler); break; case VKD3D_SHADER_TYPE_DOMAIN: vkd3d_spirv_set_execution_model(builder, SpvExecutionModelTessellationEvaluation);