vk: Implement instancing when running in interpreter mode

This commit is contained in:
kd-11 2025-03-16 03:38:18 +03:00 committed by kd-11
parent 023221bd3b
commit 5ae05e26c4
3 changed files with 69 additions and 30 deletions

View file

@ -1912,7 +1912,11 @@ bool VKGSRender::load_program()
if (shadermode == shader_mode::interpreter_only) 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; return true;
} }
} }
@ -2007,7 +2011,11 @@ bool VKGSRender::load_program()
// First load the next program if not available // First load the next program if not available
if (!m_program) 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 // Program has changed, reupload
m_interpreter_state = rsx::invalidate_pipeline_bits; m_interpreter_state = rsx::invalidate_pipeline_bits;

View file

@ -12,7 +12,7 @@
namespace vk namespace vk
{ {
void shader_interpreter::build_vs() glsl::shader* shader_interpreter::build_vs(u64 compiler_options)
{ {
::glsl::shader_properties properties{}; ::glsl::shader_properties properties{};
properties.domain = ::glsl::program_domain::glsl_vertex_program; properties.domain = ::glsl::program_domain::glsl_vertex_program;
@ -24,6 +24,10 @@ namespace vk
std::string shader_str; std::string shader_str;
ParamArray arr; ParamArray arr;
VKVertexProgram vk_prog; 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); VKVertexDecompilerThread comp(null_prog, shader_str, arr, vk_prog);
ParamType uniforms = { PF_PARAM_UNIFORM, "vec4" }; ParamType uniforms = { PF_PARAM_UNIFORM, "vec4" };
@ -45,14 +49,25 @@ namespace vk
" uvec4 vp_instructions[];\n" " uvec4 vp_instructions[];\n"
"};\n\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_glsl_legacy_function(builder, properties);
::glsl::insert_vertex_input_fetch(builder, ::glsl::glsl_rules::glsl_rules_vulkan); ::glsl::insert_vertex_input_fetch(builder, ::glsl::glsl_rules::glsl_rules_vulkan);
builder << program_common::interpreter::get_vertex_interpreter(); builder << program_common::interpreter::get_vertex_interpreter();
const std::string s = builder.str(); const std::string s = builder.str();
m_vs.create(::glsl::program_domain::glsl_vertex_program, s); auto vs = std::make_unique<glsl::shader>();
m_vs.compile(); vs->create(::glsl::program_domain::glsl_vertex_program, s);
vs->compile();
// Prepare input table // Prepare input table
const auto& binding_table = vk::get_current_renderer()->get_pipeline_binding_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); m_vs_inputs.push_back(in);
// TODO: Bind textures if needed // 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) glsl::shader* shader_interpreter::build_fs(u64 compiler_options)
@ -201,7 +220,7 @@ namespace vk
builder << program_common::interpreter::get_fragment_interpreter(); builder << program_common::interpreter::get_fragment_interpreter();
const std::string s = builder.str(); const std::string s = builder.str();
auto fs = new glsl::shader(); auto fs = std::make_unique<glsl::shader>();
fs->create(::glsl::program_domain::glsl_fragment_program, s); fs->create(::glsl::program_domain::glsl_fragment_program, s);
fs->compile(); fs->compile();
@ -228,8 +247,9 @@ namespace vk
m_fs_inputs.push_back(in); m_fs_inputs.push_back(in);
} }
m_fs_cache[compiler_options].reset(fs); auto ret = fs.get();
return fs; m_shader_cache[compiler_options].m_fs = std::move(fs);
return ret;
} }
std::pair<VkDescriptorSetLayout, VkPipelineLayout> shader_interpreter::create_layout(VkDevice dev) std::pair<VkDescriptorSetLayout, VkPipelineLayout> shader_interpreter::create_layout(VkDevice dev)
@ -359,10 +379,6 @@ namespace vk
m_device = dev; m_device = dev;
std::tie(m_shared_descriptor_layout, m_shared_pipeline_layout) = create_layout(dev); std::tie(m_shared_descriptor_layout, m_shared_pipeline_layout) = create_layout(dev);
create_descriptor_pools(dev); create_descriptor_pools(dev);
rsx_log.notice("Building global vertex program interpreter...");
build_vs();
// TODO: Seed the cache
} }
void shader_interpreter::destroy() void shader_interpreter::destroy()
@ -370,13 +386,13 @@ namespace vk
m_program_cache.clear(); m_program_cache.clear();
m_descriptor_pool.destroy(); 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_shader_cache.clear();
m_fs_cache.clear();
if (m_shared_pipeline_layout) 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::program* shader_interpreter::link(const vk::pipeline_props& properties, u64 compiler_opt)
{ {
glsl::shader* fs; glsl::shader *fs, *vs;
if (auto found = m_fs_cache.find(compiler_opt); found != m_fs_cache.end()) 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 else
{ {
rsx_log.notice("Compiling FS...");
fs = build_fs(compiler_opt); fs = build_fs(compiler_opt);
vs = build_vs(compiler_opt);
} }
VkPipelineShaderStageCreateInfo shader_stages[2] = {}; VkPipelineShaderStageCreateInfo shader_stages[2] = {};
shader_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shader_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; 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[0].pName = "main";
shader_stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 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); 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; pipeline_key key;
key.compiler_opt = 0; 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 (fp_ctrl & 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 (fp_ctrl & 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 & 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.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_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 (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 (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]] if (m_current_key == key) [[likely]]
{ {

View file

@ -12,8 +12,6 @@ namespace vk
class shader_interpreter class shader_interpreter
{ {
glsl::shader m_vs;
std::vector<glsl::program_input> m_vs_inputs; std::vector<glsl::program_input> m_vs_inputs;
std::vector<glsl::program_input> m_fs_inputs; std::vector<glsl::program_input> m_fs_inputs;
@ -41,8 +39,14 @@ namespace vk
} }
}; };
struct shader_cache_entry_t
{
std::unique_ptr<glsl::shader> m_fs;
std::unique_ptr<glsl::shader> m_vs;
};
std::unordered_map<pipeline_key, std::unique_ptr<glsl::program>, key_hasher> m_program_cache; std::unordered_map<pipeline_key, std::unique_ptr<glsl::program>, key_hasher> m_program_cache;
std::unordered_map<u64, std::unique_ptr<glsl::shader>> m_fs_cache; std::unordered_map<u64, shader_cache_entry_t> m_shader_cache;
rsx::simple_array<VkDescriptorPoolSize> m_descriptor_pool_sizes; rsx::simple_array<VkDescriptorPoolSize> m_descriptor_pool_sizes;
vk::descriptor_pool m_descriptor_pool; vk::descriptor_pool m_descriptor_pool;
@ -55,7 +59,7 @@ namespace vk
std::pair<VkDescriptorSetLayout, VkPipelineLayout> create_layout(VkDevice dev); std::pair<VkDescriptorSetLayout, VkPipelineLayout> create_layout(VkDevice dev);
void create_descriptor_pools(const vk::render_device& 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::shader* build_fs(u64 compiler_opt);
glsl::program* link(const vk::pipeline_props& properties, 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 init(const vk::render_device& dev);
void destroy(); 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; bool is_interpreter(const glsl::program* prog) const;
u32 get_vertex_instruction_location() const; u32 get_vertex_instruction_location() const;