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)
{
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;

View file

@ -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<glsl::shader>();
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<glsl::shader>();
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<VkDescriptorSetLayout, VkPipelineLayout> 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]]
{

View file

@ -12,8 +12,6 @@ namespace vk
class shader_interpreter
{
glsl::shader m_vs;
std::vector<glsl::program_input> m_vs_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<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;
vk::descriptor_pool m_descriptor_pool;
@ -55,7 +59,7 @@ namespace vk
std::pair<VkDescriptorSetLayout, VkPipelineLayout> 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;