From afb814788f0728a50b9d396e3c9ec5894889640d Mon Sep 17 00:00:00 2001 From: kd-11 Date: Fri, 29 Aug 2025 03:48:19 +0300 Subject: [PATCH] vk: Fix shader interpreter compilation and crashes --- rpcs3/Emu/RSX/VK/VKShaderInterpreter.cpp | 47 ++++++++++++++++++------ rpcs3/Emu/RSX/VK/VKShaderInterpreter.h | 15 ++++++-- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/rpcs3/Emu/RSX/VK/VKShaderInterpreter.cpp b/rpcs3/Emu/RSX/VK/VKShaderInterpreter.cpp index 06ab05e226..e37e7745b5 100644 --- a/rpcs3/Emu/RSX/VK/VKShaderInterpreter.cpp +++ b/rpcs3/Emu/RSX/VK/VKShaderInterpreter.cpp @@ -71,7 +71,7 @@ namespace vk // Initialize binding layout auto vk_prog = std::make_unique(); - m_vertex_instruction_start = init(vk_prog.get(), compiler_options); + const u32 vertex_instruction_start = init(vk_prog.get(), compiler_options); null_prog.ctrl = (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_INSTANCING) ? RSX_SHADER_CONTROL_INSTANCED_CONSTANTS @@ -93,6 +93,7 @@ namespace vk builder << "layout(location=16) out flat uvec4 draw_params_payload;\n\n"; builder << + "#define xform_constants_offset get_draw_params().xform_constants_offset\n" "#define scale_offset_mat get_vertex_context().scale_offset_mat\n" "#define transform_branch_bits get_vertex_context().transform_branch_bits\n" "#define point_size get_vertex_context().point_size\n" @@ -101,7 +102,7 @@ namespace vk // Insert vp stream input builder << "\n" - "layout(std140, set=0, binding=" << m_vertex_instruction_start << ") readonly restrict buffer VertexInstructionBlock\n" + "layout(std140, set=0, binding=" << vertex_instruction_start << ") readonly restrict buffer VertexInstructionBlock\n" "{\n" " uint base_address;\n" " uint entry;\n" @@ -143,7 +144,7 @@ namespace vk vk::glsl::program_input in; in.set = 0; in.domain = ::glsl::glsl_vertex_program; - in.location = m_vertex_instruction_start; + in.location = vertex_instruction_start; in.type = glsl::input_type_storage_buffer; in.name = "VertexInstructionBlock"; vs_inputs.push_back(in); @@ -170,8 +171,8 @@ namespace vk frag.ctrl |= RSX_SHADER_CONTROL_INTERPRETER_MODEL; auto vk_prog = std::make_unique(); - m_fragment_instruction_start = init(vk_prog.get(), compiler_options); - m_fragment_textures_start = m_fragment_instruction_start + 1; + const u32 fragment_instruction_start = init(vk_prog.get(), compiler_options); + const u32 fragment_textures_start = fragment_instruction_start + 1; VKFragmentDecompilerThread comp(shader_str, arr, frag, len, *vk_prog); @@ -257,7 +258,7 @@ namespace vk { builder << "#define WITH_TEXTURES\n\n"; - for (int i = 0, bind_location = m_fragment_textures_start; i < 4; ++i) + for (int i = 0, bind_location = fragment_textures_start; i < 4; ++i) { builder << "layout(set=1, binding=" << bind_location++ << ") " << "uniform " << type_names[i] << " " << type_names[i] << "_array[16];\n"; } @@ -272,7 +273,7 @@ namespace vk } builder << - "layout(std430, set=1, binding=" << m_fragment_instruction_start << ") readonly restrict buffer FragmentInstructionBlock\n" + "layout(std430, set=1, binding=" << fragment_instruction_start << ") readonly restrict buffer FragmentInstructionBlock\n" "{\n" " uint shader_control;\n" " uint texture_control;\n" @@ -298,14 +299,14 @@ namespace vk vk::glsl::program_input in; in.set = 1; in.domain = ::glsl::glsl_fragment_program; - in.location = m_fragment_instruction_start; + in.location = fragment_instruction_start; in.type = glsl::input_type_storage_buffer; in.name = "FragmentInstructionBlock"; inputs.push_back(in); if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_TEXTURES) { - for (int i = 0, location = m_fragment_textures_start; i < 4; ++i, ++location) + for (int i = 0, location = fragment_textures_start; i < 4; ++i, ++location) { in.location = location; in.name = std::string(type_names[i]) + "_array[16]"; @@ -504,6 +505,7 @@ namespace vk } else { + m_current_pipeline_info_ex = *get_pipeline_info_ex(key.compiler_opt); m_current_key = key; } @@ -526,12 +528,12 @@ namespace vk u32 shader_interpreter::get_vertex_instruction_location() const { - return m_vertex_instruction_start; + return m_current_pipeline_info_ex.vertex_instruction_location; } u32 shader_interpreter::get_fragment_instruction_location() const { - return m_fragment_instruction_start; + return m_current_pipeline_info_ex.fragment_instruction_location; } std::pair shader_interpreter::get_shaders() const @@ -545,4 +547,27 @@ namespace vk return { nullptr, nullptr }; } + + const shader_interpreter::pipeline_info_ex_t* shader_interpreter::get_pipeline_info_ex(u64 compiler_opt) + { + if (auto found = m_pipeline_info_cache.find(compiler_opt); found != m_pipeline_info_cache.end()) + { + return &found->second; + } + + VKVertexProgram vs_stub{}; + VKFragmentProgram fs_stub{}; + const auto vi_location = init(&vs_stub, compiler_opt); + const auto fi_location = init(&fs_stub, compiler_opt); + + pipeline_info_ex_t result + { + .vertex_instruction_location = vi_location, + .fragment_instruction_location = fi_location, + .fragment_textures_location = fi_location + 1 + }; + + auto it = m_pipeline_info_cache.insert_or_assign(compiler_opt, result); + return &it.first->second; + } }; diff --git a/rpcs3/Emu/RSX/VK/VKShaderInterpreter.h b/rpcs3/Emu/RSX/VK/VKShaderInterpreter.h index 9d934b3ffa..ff83be6245 100644 --- a/rpcs3/Emu/RSX/VK/VKShaderInterpreter.h +++ b/rpcs3/Emu/RSX/VK/VKShaderInterpreter.h @@ -43,14 +43,19 @@ namespace vk std::unique_ptr m_vs; }; + struct pipeline_info_ex_t + { + u32 vertex_instruction_location = 0; + u32 fragment_instruction_location = 0; + u32 fragment_textures_location = 0; + }; + std::unordered_map, key_hasher> m_program_cache; std::unordered_map m_shader_cache; - - u32 m_vertex_instruction_start = 0; - u32 m_fragment_instruction_start = 0; - u32 m_fragment_textures_start = 0; + std::unordered_map m_pipeline_info_cache; pipeline_key m_current_key{}; + pipeline_info_ex_t m_current_pipeline_info_ex{}; VKVertexProgram* build_vs(u64 compiler_opt); VKFragmentProgram* build_fs(u64 compiler_opt); @@ -59,6 +64,8 @@ namespace vk u32 init(VKVertexProgram* vk_prog, u64 compiler_opt) const; u32 init(VKFragmentProgram* vk_prog, u64 compiler_opt) const; + const pipeline_info_ex_t* get_pipeline_info_ex(u64 compiler_opt); + public: void init(const vk::render_device& dev); void destroy();