vk: Combine all draw-time constants to a single struct and update only the offset id

- Reduces push constants consumed per draw to 4 bytes total
This commit is contained in:
kd-11 2025-08-03 20:55:24 +03:00 committed by kd-11
parent 335f3dbe2f
commit 3452aaf5d5
8 changed files with 69 additions and 68 deletions

View file

@ -22,12 +22,16 @@ struct vertex_context_t
float reserved[3];
};
struct vertex_layout_t
struct draw_parameters_t
{
uint vertex_base_index;
uint vertex_index_offset;
uint draw_id;
uint reserved;
uint xform_constants_offset;
uint vs_context_offset;
uint fs_constants_offset;
uint fs_context_offset;
uint fs_texture_base_index;
uvec2 attrib_data[16];
};

View file

@ -156,7 +156,7 @@ attribute_desc fetch_desc(const in int location)
#ifdef VULKAN
// Fetch parameters streamed separately from draw parameters
uvec2 attrib = vertex_layouts[vs_attrib_layout_offset].attrib_data[location];
uvec2 attrib = get_draw_params().attrib_data[location];
#else
// Data is packed into a ubo
const int block = (location >> 1);
@ -179,8 +179,8 @@ attribute_desc fetch_desc(const in int location)
}
#ifdef VULKAN
#define vertex_index_offset vertex_layouts[vs_attrib_layout_offset].vertex_index_offset
#define vertex_base_index vertex_layouts[vs_attrib_layout_offset].vertex_base_index
#define vertex_index_offset get_draw_params().vertex_index_offset
#define vertex_base_index get_draw_params().vertex_base_index
#endif
vec4 read_location(const in int location)

View file

@ -820,7 +820,7 @@ void VKGSRender::emit_geometry(u32 sub_index)
update_descriptors = true;
// Allocate stream layout memory for this batch
const u64 alloc_size = rsx::method_registers.current_draw_clause.pass_count() * 144;
const u64 alloc_size = rsx::method_registers.current_draw_clause.pass_count() * 160;
m_vertex_layout_dynamic_offset = m_vertex_layout_ring_info.alloc<16>(alloc_size);
}

View file

@ -225,6 +225,18 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS)
}
}
// Always provided by vertex program, not part of local bindings
OS <<
"layout(std430, set=0, binding=2) readonly buffer DrawParametersBuffer\n"
"{\n"
" draw_parameters_t draw_parameters[];\n"
"};\n\n"
"#define get_draw_params() draw_parameters[draw_parameters_offset]\n"
"#define fs_constants_offset get_draw_params().fs_constants_offset\n"
"#define fs_context_offset get_draw_params().fs_context_offset\n"
"#define fs_texture_base_index get_draw_params().fs_texture_base_index\n\n";
if (!properties.constant_offsets.empty())
{
OS << "layout(std430, set=1, binding=" << vk_prog->binding_table.cbuf_location << ") readonly buffer FragmentConstantsBuffer\n";
@ -282,16 +294,14 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS)
OS <<
"layout(push_constant) uniform push_constants_block\n"
"{\n"
" layout(offset=12) uint fs_constants_offset;\n"
" uint fs_context_offset;\n"
" uint fs_texture_base_index;\n"
" uint draw_parameters_offset;\n"
"};\n\n";
const vk::glsl::program_input push_constants
{
.domain = glsl::glsl_fragment_program,
.type = vk::glsl::input_type_push_constant,
.bound_data = vk::glsl::push_constant_ref{.offset = 12, .size = 12 },
.bound_data = vk::glsl::push_constant_ref{.offset = 0, .size = 4 },
.set = vk::glsl::binding_set_index_vertex,
.location = umax,
.name = "fs_push_constants_block"

View file

@ -2184,26 +2184,16 @@ void VKGSRender::upload_transform_constants(const rsx::io_buffer& buffer)
void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_info)
{
#pragma pack(push, 1)
struct rsx_vs_prog_push_constants_block_t
{
u32 xform_constants_offset;
u32 vs_context_offset;
u32 vs_attrib_layout_offset;
};
struct rsx_fs_prog_push_constants_block_t
{
u32 fs_constants_offset;
u32 fs_context_offset;
u32 fs_texture_base_index;
};
struct rsx_prog_vertex_layout_entry_t
{
u32 vertex_base_index;
u32 vertex_index_offset;
u32 draw_id;
u32 reserved;
u32 xform_constants_offset;
u32 vs_context_offset;
u32 fs_constants_offset;
u32 fs_context_offset;
u32 fs_texture_base_index;
s32 attrib_data[1];
};
#pragma pack(pop)
@ -2211,46 +2201,36 @@ void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_
// Actual allocation must have been done previously
const u32 vs_constant_id_offset = static_cast<u32>(m_xform_constants_dynamic_offset) / 16u;
const u32 vertex_context_offset = static_cast<u32>(m_vertex_env_dynamic_offset) / 96u;
const u32 vertex_layout_offset = static_cast<u32>(m_vertex_layout_dynamic_offset) / 144u;
const u32 vertex_layout_offset = static_cast<u32>(m_vertex_layout_dynamic_offset) / 160u;
const u32 fs_constant_id_offset = static_cast<u32>(m_fragment_constants_dynamic_offset) / 16u;
const u32 fs_context_offset = static_cast<u32>(m_fragment_env_dynamic_offset) / 32u;
const u32 fs_texture_base_index = static_cast<u32>(m_texture_parameters_dynamic_offset) / 48u;
// Pack
rsx_vs_prog_push_constants_block_t vs_push_constants;
vs_push_constants.xform_constants_offset = vs_constant_id_offset;
vs_push_constants.vs_context_offset = vertex_context_offset;
vs_push_constants.vs_attrib_layout_offset = vertex_layout_offset + id;
rsx_fs_prog_push_constants_block_t fs_push_constants;
fs_push_constants.fs_constants_offset = fs_constant_id_offset;
fs_push_constants.fs_context_offset = fs_context_offset;
fs_push_constants.fs_texture_base_index = fs_texture_base_index;
vkCmdPushConstants(
*m_current_command_buffer,
m_program->layout(),
VK_SHADER_STAGE_VERTEX_BIT,
0,
sizeof(vs_push_constants),
&vs_push_constants);
vkCmdPushConstants(
*m_current_command_buffer,
m_program->layout(),
VK_SHADER_STAGE_FRAGMENT_BIT,
sizeof(vs_push_constants),
sizeof(fs_push_constants),
&fs_push_constants);
// Now actually fill in the data
auto buf = m_vertex_layout_ring_info.map(m_vertex_layout_dynamic_offset + (144u * id), 144);
auto buf = m_vertex_layout_ring_info.map(m_vertex_layout_dynamic_offset + (160u * id), 160u);
auto dst = reinterpret_cast<rsx_prog_vertex_layout_entry_t*>(buf);
// Pack
dst->vertex_base_index = vertex_info.vertex_index_base;
dst->vertex_index_offset = vertex_info.vertex_index_offset;
dst->draw_id = id;
dst->reserved = 0;
dst->xform_constants_offset = vs_constant_id_offset;
dst->vs_context_offset = vertex_context_offset;
dst->fs_constants_offset = fs_constant_id_offset;
dst->fs_context_offset = fs_context_offset;
dst->fs_texture_base_index = fs_texture_base_index;
const u32 push_val = vertex_layout_offset + id;
vkCmdPushConstants(
*m_current_command_buffer,
m_program->layout(),
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
0,
4,
&push_val);
// Now actually fill in the data
m_draw_processor.fill_vertex_layout_state(
m_vertex_layout,
current_vp_metadata,

View file

@ -651,7 +651,7 @@ namespace vk
.binding = input.location,
.descriptorType = type,
.descriptorCount = descriptor_count(input.name),
.stageFlags = to_shader_stage_flags(input.domain)
.stageFlags = to_shader_stage_flags(input.domain) | input.ex_stages
};
bindings.push_back(binding);

View file

@ -60,6 +60,8 @@ namespace vk
u32 location = umax;
std::string name = "undefined";
VkFlags ex_stages = 0;
inline bound_buffer& as_buffer() { return *std::get_if<bound_buffer>(&bound_data); }
inline bound_sampler& as_sampler() { return *std::get_if<bound_sampler>(&bound_data); }
inline push_constant_ref& as_push_constant() { return *std::get_if<push_constant_ref>(&bound_data); }

View file

@ -79,14 +79,20 @@ void VKVertexDecompilerThread::insertHeader(std::stringstream &OS)
glsl::insert_subheader_block(OS);
OS <<
// Variable redirection
"#define get_draw_params() draw_parameters[draw_parameters_offset]\n"
"#define vs_context_offset get_draw_params().vs_context_offset\n"
"#define xform_constants_offset get_draw_params().xform_constants_offset\n\n"
// Helpers
"#define get_vertex_context() vertex_contexts[vs_context_offset]\n"
"#define get_user_clip_config() get_vertex_context().user_clip_configuration_bits\n\n";
OS <<
"layout(std430, set=0, binding=" << vk_prog->binding_table.context_buffer_location << ") readonly buffer VertexContextBuffer\n"
"{\n"
" vertex_context_t vertex_contexts[];\n"
"};\n\n"
""
"#define get_vertex_context() vertex_contexts[vs_context_offset]\n"
"#define get_user_clip_config() get_vertex_context().user_clip_configuration_bits\n\n";
"};\n\n";
const vk::glsl::program_input context_input
{
@ -118,9 +124,9 @@ void VKVertexDecompilerThread::insertHeader(std::stringstream &OS)
}
OS <<
"layout(std430, set=0, binding=" << vk_prog->binding_table.vertex_buffers_location + 2 << ") readonly buffer VertexLayoutBuffer\n"
"layout(std430, set=0, binding=" << vk_prog->binding_table.vertex_buffers_location + 2 << ") readonly buffer DrawParametersBuffer\n"
"{\n"
" vertex_layout_t vertex_layouts[];\n"
" draw_parameters_t draw_parameters[];\n"
"};\n\n";
const vk::glsl::program_input layouts_input
@ -129,23 +135,22 @@ void VKVertexDecompilerThread::insertHeader(std::stringstream &OS)
.type = vk::glsl::input_type_storage_buffer,
.set = vk::glsl::binding_set_index_vertex,
.location = vk_prog->binding_table.vertex_buffers_location + 2,
.name = "VertexLayoutBuffer"
.name = "DrawParametersBuffer",
.ex_stages = VK_SHADER_STAGE_FRAGMENT_BIT // Shared with fragment shader
};
inputs.push_back(layouts_input);
OS <<
"layout(push_constant) uniform push_constants_block\n"
"{\n"
" uint xform_constants_offset;\n"
" uint vs_context_offset;\n"
" uint vs_attrib_layout_offset;\n"
" uint draw_parameters_offset;\n"
"};\n\n";
const vk::glsl::program_input push_constants
{
.domain = glsl::glsl_vertex_program,
.type = vk::glsl::input_type_push_constant,
.bound_data = vk::glsl::push_constant_ref{ .offset = 0, .size = 12 },
.bound_data = vk::glsl::push_constant_ref{ .offset = 0, .size = 4 },
.set = vk::glsl::binding_set_index_vertex,
.location = umax,
.name = "push_constants_block"