diff --git a/rpcs3/Emu/RSX/VK/VKDraw.cpp b/rpcs3/Emu/RSX/VK/VKDraw.cpp index 0f3a11b794..f74cf485ce 100644 --- a/rpcs3/Emu/RSX/VK/VKDraw.cpp +++ b/rpcs3/Emu/RSX/VK/VKDraw.cpp @@ -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 + { + 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 diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index df7e06ac3d..5a1786e8b1 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -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 + { + 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{} - : std::span(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{} + : std::span(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 diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index 9e1a78c504..f2af5468bf 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -234,10 +234,12 @@ private: VkDescriptorSet allocate_descriptor_set(); vk::vertex_upload_info upload_vertex_data(); + rsx::simple_array 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();