diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 8e834d3081..dd9d080ecd 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -1912,7 +1912,11 @@ bool VKGSRender::load_program() if (shadermode == shader_mode::interpreter_only) { - m_program = m_shader_interpreter.get(m_pipeline_properties, current_fp_metadata); + m_program = m_shader_interpreter.get( + m_pipeline_properties, + current_fp_metadata, + current_vertex_program.ctrl, + current_fragment_program.ctrl); return true; } } @@ -2007,7 +2011,11 @@ bool VKGSRender::load_program() // First load the next program if not available if (!m_program) { - m_program = m_shader_interpreter.get(m_pipeline_properties, current_fp_metadata); + m_program = m_shader_interpreter.get( + m_pipeline_properties, + current_fp_metadata, + current_vertex_program.ctrl, + current_fragment_program.ctrl); // Program has changed, reupload m_interpreter_state = rsx::invalidate_pipeline_bits; diff --git a/rpcs3/Emu/RSX/VK/VKShaderInterpreter.cpp b/rpcs3/Emu/RSX/VK/VKShaderInterpreter.cpp index b31e8121e4..94deb013b1 100644 --- a/rpcs3/Emu/RSX/VK/VKShaderInterpreter.cpp +++ b/rpcs3/Emu/RSX/VK/VKShaderInterpreter.cpp @@ -12,7 +12,7 @@ namespace vk { - void shader_interpreter::build_vs() + glsl::shader* shader_interpreter::build_vs(u64 compiler_options) { ::glsl::shader_properties properties{}; properties.domain = ::glsl::program_domain::glsl_vertex_program; @@ -24,6 +24,10 @@ namespace vk std::string shader_str; ParamArray arr; VKVertexProgram vk_prog; + + null_prog.ctrl = (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_INSTANCING) + ? RSX_SHADER_CONTROL_INSTANCED_CONSTANTS + : 0; VKVertexDecompilerThread comp(null_prog, shader_str, arr, vk_prog); ParamType uniforms = { PF_PARAM_UNIFORM, "vec4" }; @@ -45,14 +49,25 @@ namespace vk " uvec4 vp_instructions[];\n" "};\n\n"; + if (compiler_options & program_common::interpreter::COMPILER_OPT_ENABLE_INSTANCING) + { + builder << "#define _ENABLE_INSTANCED_CONSTANTS\n"; + } + + if (compiler_options) + { + builder << "\n"; + } + ::glsl::insert_glsl_legacy_function(builder, properties); ::glsl::insert_vertex_input_fetch(builder, ::glsl::glsl_rules::glsl_rules_vulkan); builder << program_common::interpreter::get_vertex_interpreter(); const std::string s = builder.str(); - m_vs.create(::glsl::program_domain::glsl_vertex_program, s); - m_vs.compile(); + auto vs = std::make_unique(); + vs->create(::glsl::program_domain::glsl_vertex_program, s); + vs->compile(); // Prepare input table const auto& binding_table = vk::get_current_renderer()->get_pipeline_binding_table(); @@ -85,6 +100,10 @@ namespace vk m_vs_inputs.push_back(in); // TODO: Bind textures if needed + + auto ret = vs.get(); + m_shader_cache[compiler_options].m_vs = std::move(vs); + return ret; } glsl::shader* shader_interpreter::build_fs(u64 compiler_options) @@ -201,7 +220,7 @@ namespace vk builder << program_common::interpreter::get_fragment_interpreter(); const std::string s = builder.str(); - auto fs = new glsl::shader(); + auto fs = std::make_unique(); fs->create(::glsl::program_domain::glsl_fragment_program, s); fs->compile(); @@ -228,8 +247,9 @@ namespace vk m_fs_inputs.push_back(in); } - m_fs_cache[compiler_options].reset(fs); - return fs; + auto ret = fs.get(); + m_shader_cache[compiler_options].m_fs = std::move(fs); + return ret; } std::pair shader_interpreter::create_layout(VkDevice dev) @@ -359,10 +379,6 @@ namespace vk m_device = dev; std::tie(m_shared_descriptor_layout, m_shared_pipeline_layout) = create_layout(dev); create_descriptor_pools(dev); - - rsx_log.notice("Building global vertex program interpreter..."); - build_vs(); - // TODO: Seed the cache } void shader_interpreter::destroy() @@ -370,13 +386,13 @@ namespace vk m_program_cache.clear(); m_descriptor_pool.destroy(); - for (auto &fs : m_fs_cache) + for (auto &fs : m_shader_cache) { - fs.second->destroy(); + fs.second.m_vs->destroy(); + fs.second.m_fs->destroy(); } - m_vs.destroy(); - m_fs_cache.clear(); + m_shader_cache.clear(); if (m_shared_pipeline_layout) { @@ -393,21 +409,22 @@ namespace vk glsl::program* shader_interpreter::link(const vk::pipeline_props& properties, u64 compiler_opt) { - glsl::shader* fs; - if (auto found = m_fs_cache.find(compiler_opt); found != m_fs_cache.end()) + glsl::shader *fs, *vs; + if (auto found = m_shader_cache.find(compiler_opt); found != m_shader_cache.end()) { - fs = found->second.get(); + fs = found->second.m_fs.get(); + vs = found->second.m_vs.get(); } else { - rsx_log.notice("Compiling FS..."); fs = build_fs(compiler_opt); + vs = build_vs(compiler_opt); } VkPipelineShaderStageCreateInfo shader_stages[2] = {}; shader_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - shader_stages[0].module = m_vs.get_handle(); + shader_stages[0].module = vs->get_handle(); shader_stages[0].pName = "main"; shader_stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; @@ -496,7 +513,11 @@ namespace vk return m_descriptor_pool.allocate(m_shared_descriptor_layout); } - glsl::program* shader_interpreter::get(const vk::pipeline_props& properties, const program_hash_util::fragment_program_utils::fragment_program_metadata& metadata) + glsl::program* shader_interpreter::get( + const vk::pipeline_props& properties, + const program_hash_util::fragment_program_utils::fragment_program_metadata& metadata, + u32 vp_ctrl, + u32 fp_ctrl) { pipeline_key key; key.compiler_opt = 0; @@ -531,13 +552,14 @@ namespace vk } } - if (rsx::method_registers.shader_control() & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_DEPTH_EXPORT; - if (rsx::method_registers.shader_control() & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_F32_EXPORT; - if (rsx::method_registers.shader_control() & RSX_SHADER_CONTROL_USES_KIL) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_KIL; + if (fp_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_DEPTH_EXPORT; + if (fp_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_F32_EXPORT; + if (fp_ctrl & RSX_SHADER_CONTROL_USES_KIL) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_KIL; if (metadata.referenced_textures_mask) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_TEXTURES; if (metadata.has_branch_instructions) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_FLOW_CTRL; if (metadata.has_pack_instructions) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_PACKING; if (rsx::method_registers.polygon_stipple_enabled()) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_STIPPLING; + if (vp_ctrl & RSX_SHADER_CONTROL_INSTANCED_CONSTANTS) key.compiler_opt |= program_common::interpreter::COMPILER_OPT_ENABLE_INSTANCING; if (m_current_key == key) [[likely]] { diff --git a/rpcs3/Emu/RSX/VK/VKShaderInterpreter.h b/rpcs3/Emu/RSX/VK/VKShaderInterpreter.h index 0820f7f020..d359ca343e 100644 --- a/rpcs3/Emu/RSX/VK/VKShaderInterpreter.h +++ b/rpcs3/Emu/RSX/VK/VKShaderInterpreter.h @@ -12,8 +12,6 @@ namespace vk class shader_interpreter { - glsl::shader m_vs; - std::vector m_vs_inputs; std::vector m_fs_inputs; @@ -41,8 +39,14 @@ namespace vk } }; + struct shader_cache_entry_t + { + std::unique_ptr m_fs; + std::unique_ptr m_vs; + }; + std::unordered_map, key_hasher> m_program_cache; - std::unordered_map> m_fs_cache; + std::unordered_map m_shader_cache; rsx::simple_array m_descriptor_pool_sizes; vk::descriptor_pool m_descriptor_pool; @@ -55,7 +59,7 @@ namespace vk std::pair create_layout(VkDevice dev); void create_descriptor_pools(const vk::render_device& dev); - void build_vs(); + glsl::shader* build_vs(u64 compiler_opt); glsl::shader* build_fs(u64 compiler_opt); glsl::program* link(const vk::pipeline_props& properties, u64 compiler_opt); @@ -63,7 +67,12 @@ namespace vk void init(const vk::render_device& dev); void destroy(); - glsl::program* get(const vk::pipeline_props& properties, const program_hash_util::fragment_program_utils::fragment_program_metadata& metadata); + glsl::program* get( + const vk::pipeline_props& properties, + const program_hash_util::fragment_program_utils::fragment_program_metadata& metadata, + u32 vp_ctrl, + u32 fp_ctrl); + bool is_interpreter(const glsl::program* prog) const; u32 get_vertex_instruction_location() const;