vk: Implement dynamic transform constant updates

This commit is contained in:
kd-11 2024-04-19 04:20:23 +03:00 committed by kd-11
parent 96793193b5
commit 279393337e
3 changed files with 75 additions and 17 deletions

View File

@ -707,13 +707,13 @@ void VKGSRender::emit_geometry(u32 sub_index)
m_profiler.start();
const rsx::flags32_t vertex_state_mask = rsx::vertex_base_changed | rsx::vertex_arrays_changed;
const rsx::flags32_t vertex_state = (sub_index == 0) ? rsx::vertex_arrays_changed : draw_call.execute_pipeline_dependencies(m_ctx) & vertex_state_mask;
const rsx::flags32_t state_flags = (sub_index == 0) ? rsx::vertex_arrays_changed : draw_call.execute_pipeline_dependencies(m_ctx);
if (vertex_state & rsx::vertex_arrays_changed)
if (state_flags & rsx::vertex_arrays_changed)
{
analyse_inputs_interleaved(m_vertex_layout);
}
else if (vertex_state & rsx::vertex_base_changed)
else if (state_flags & rsx::vertex_base_changed)
{
// Rebase vertex bases instead of
for (auto& info : m_vertex_layout.interleaved_blocks)
@ -732,7 +732,44 @@ void VKGSRender::emit_geometry(u32 sub_index)
}
}
if (vertex_state && !m_vertex_layout.validate())
if (state_flags & rsx::transform_constants_changed)
{
auto allocate_mem = [&](usz size) -> std::pair<void*, usz>
{
vertex_scratchpad.resize(size);
return { vertex_scratchpad.data(), size };
};
rsx::io_buffer iobuf(allocate_mem);
upload_transform_constants(iobuf);
ensure(iobuf.size() >= m_vertex_constants_buffer_info.range);
vk::insert_buffer_memory_barrier(
*m_current_command_buffer,
m_vertex_constants_buffer_info.buffer,
m_vertex_constants_buffer_info.offset,
m_vertex_constants_buffer_info.range,
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_MEMORY_READ_BIT, VK_ACCESS_TRANSFER_WRITE_BIT);
vkCmdUpdateBuffer(
*m_current_command_buffer,
m_vertex_constants_buffer_info.buffer,
m_vertex_constants_buffer_info.offset,
m_vertex_constants_buffer_info.range,
iobuf.data());
vk::insert_buffer_memory_barrier(
*m_current_command_buffer,
m_vertex_constants_buffer_info.buffer,
m_vertex_constants_buffer_info.offset,
m_vertex_constants_buffer_info.range,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT);
}
if ((state_flags & vertex_state_mask) && !m_vertex_layout.validate())
{
// No vertex inputs enabled
// Execute remainining pipeline barriers with NOP draw

View File

@ -2138,22 +2138,24 @@ void VKGSRender::load_program_env()
if (update_transform_constants)
{
// Transform constants
const usz transform_constants_size = (!m_vertex_prog || m_vertex_prog->has_indexed_constants) ? 8192 : m_vertex_prog->constant_ids.size() * 16;
usz transform_constants_size = 0;
usz mem_offset = 0;
auto alloc_storage = [&](usz size) -> std::pair<void*, usz>
{
const auto alignment = m_device->gpu().get_limits().minUniformBufferOffsetAlignment;
mem_offset = m_transform_constants_ring_info.alloc<1>(utils::align(size, alignment));
transform_constants_size = size;
return std::make_pair(m_transform_constants_ring_info.map(mem_offset, transform_constants_size), size);
};
auto io_buf = rsx::io_buffer(alloc_storage);
upload_transform_constants(io_buf);
if (transform_constants_size)
{
check_heap_status(VK_HEAP_CHECK_TRANSFORM_CONSTANTS_STORAGE);
const auto alignment = m_device->gpu().get_limits().minUniformBufferOffsetAlignment;
auto mem = m_transform_constants_ring_info.alloc<1>(utils::align(transform_constants_size, alignment));
auto buf = m_transform_constants_ring_info.map(mem, transform_constants_size);
const auto constant_ids = (transform_constants_size == 8192)
? std::span<const u16>{}
: std::span<const u16>(m_vertex_prog->constant_ids);
fill_vertex_program_constants_data(buf, constant_ids);
m_transform_constants_ring_info.unmap();
m_vertex_constants_buffer_info = { m_transform_constants_ring_info.heap->value, mem, transform_constants_size };
m_vertex_constants_buffer_info = { m_transform_constants_ring_info.heap->value, mem_offset, transform_constants_size };
}
}
@ -2290,6 +2292,23 @@ void VKGSRender::load_program_env()
rsx::pipeline_state::fragment_texture_state_dirty);
}
void VKGSRender::upload_transform_constants(const rsx::io_buffer& buffer)
{
const usz transform_constants_size = (!m_vertex_prog || m_vertex_prog->has_indexed_constants) ? 8192 : m_vertex_prog->constant_ids.size() * 16;
if (transform_constants_size)
{
check_heap_status(VK_HEAP_CHECK_TRANSFORM_CONSTANTS_STORAGE);
buffer.reserve(transform_constants_size);
auto buf = buffer.data();
const auto constant_ids = (transform_constants_size == 8192)
? std::span<const u16>{}
: std::span<const u16>(m_vertex_prog->constant_ids);
fill_vertex_program_constants_data(buf, constant_ids);
}
}
void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_info)
{
// Actual allocation must have been done previously

View File

@ -234,10 +234,12 @@ private:
VkDescriptorSet allocate_descriptor_set();
vk::vertex_upload_info upload_vertex_data();
rsx::simple_array<u8> vertex_scratchpad;
bool load_program();
void load_program_env();
void update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_info);
void upload_transform_constants(const rsx::io_buffer& buffer);
void load_texture_env();
bool bind_texture_env();