diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index aec1f747b0..5c187c726e 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -435,6 +435,10 @@ VKGSRender::VKGSRender() : GSRender(frame_type::Vulkan) alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; CHECK_RESULT(vkAllocateDescriptorSets(*m_device, &alloc_info, &descriptor_sets)); + + + null_buffer = std::make_unique(*m_device, 32, m_memory_type_mapping.host_visible_coherent, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, 0); + null_buffer_view = std::make_unique(*m_device, null_buffer->value, VK_FORMAT_R32_SFLOAT, 0, 32); } VKGSRender::~VKGSRender() @@ -459,8 +463,10 @@ VKGSRender::~VKGSRender() m_index_buffer.release(); m_uniform_buffer.release(); - - + m_attrib_buffers.release(); + null_buffer.release(); + null_buffer_view.release(); + m_buffer_view_to_clean.clear(); for (auto &render_pass : m_render_passes) if (render_pass) @@ -713,25 +719,13 @@ void VKGSRender::set_viewport() void VKGSRender::on_init_thread() { GSRender::on_init_thread(); - - for (auto &attrib_buffer : m_attrib_buffers) - { - attrib_buffer.create((*m_device), 65536, VK_FORMAT_R8_UNORM, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT); - - u8 *data = static_cast(attrib_buffer.map(0, 65536)); - memset(data, 0, 65536); - attrib_buffer.unmap(); - } + m_attrib_ring_info.init(8 * RING_BUFFER_SIZE); + m_attrib_buffers.reset(new vk::buffer(*m_device, 8 * RING_BUFFER_SIZE, m_memory_type_mapping.host_visible_coherent, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, 0)); } void VKGSRender::on_exit() { m_texture_cache.destroy(); - - for (auto &attrib_buffer : m_attrib_buffers) - { - attrib_buffer.destroy(); - } } void VKGSRender::clear_surface(u32 mask) @@ -1181,6 +1175,7 @@ void VKGSRender::flip(int buffer) m_uniform_buffer_ring_info.m_get_pos = m_uniform_buffer_ring_info.get_current_put_pos_minus_one(); m_index_buffer_ring_info.m_get_pos = m_index_buffer_ring_info.get_current_put_pos_minus_one(); + m_attrib_ring_info.m_get_pos = m_attrib_ring_info.get_current_put_pos_minus_one(); if (m_present_semaphore) { vkDestroySemaphore((*m_device), m_present_semaphore, nullptr); @@ -1191,6 +1186,8 @@ void VKGSRender::flip(int buffer) m_texture_cache.merge_dirty_textures(m_rtts.invalidated_resources); m_rtts.invalidated_resources.clear(); + m_buffer_view_to_clean.clear(); + m_draw_calls = 0; dirty_frame = true; m_frame->flip(m_context); diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index 29f89743a8..e1d92908a2 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -104,7 +104,8 @@ private: rsx::surface_info m_surface; - vk::buffer_deprecated m_attrib_buffers[rsx::limits::vertex_count]; + vk::data_heap m_attrib_ring_info; + std::unique_ptr m_attrib_buffers; vk::texture_cache m_texture_cache; rsx::vk_render_targets m_rtts; @@ -112,6 +113,9 @@ private: vk::gpu_formats_support m_optimal_tiling_supported_formats; vk::memory_type_mapping m_memory_type_mapping; + std::unique_ptr null_buffer; + std::unique_ptr null_buffer_view; + public: //vk::fbo draw_fbo; @@ -146,6 +150,8 @@ private: VkPipelineLayout pipeline_layout; vk::descriptor_pool descriptor_pool; + std::vector > m_buffer_view_to_clean; + u32 m_draw_calls = 0; u8 m_draw_buffers_count = 0; diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.cpp b/rpcs3/Emu/RSX/VK/VKHelpers.cpp index 699d225ce0..0acde2d1a3 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.cpp +++ b/rpcs3/Emu/RSX/VK/VKHelpers.cpp @@ -6,7 +6,6 @@ namespace vk context *g_current_vulkan_ctx = nullptr; render_device g_current_renderer; - buffer_deprecated g_null_buffer; texture g_null_texture; VkSampler g_null_sampler = nullptr; @@ -102,15 +101,6 @@ namespace vk return callbacks; } - VkBuffer null_buffer() - { - if (g_null_buffer.size()) - return g_null_buffer; - - g_null_buffer.create(g_current_renderer, 32, VK_FORMAT_R32_SFLOAT, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT); - return g_null_buffer; - } - VkSampler null_sampler() { if (g_null_sampler) @@ -147,18 +137,8 @@ namespace vk return g_null_image_view; } - VkBufferView null_buffer_view() - { - if (g_null_buffer.size()) - return g_null_buffer; - - g_null_buffer.create(g_current_renderer, 32, VK_FORMAT_R32_SFLOAT, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT); - return g_null_buffer; - } - void destroy_global_resources() { - g_null_buffer.destroy(); g_null_texture.destroy(); if (g_null_sampler) diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index b450abed1c..c06b6987d5 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -55,10 +55,8 @@ namespace vk VkImageSubresource default_image_subresource(); VkImageSubresourceRange default_image_subresource_range(); - VkBuffer null_buffer(); VkSampler null_sampler(); VkImageView null_image_view(); - VkBufferView null_buffer_view(); void destroy_global_resources(); @@ -464,167 +462,6 @@ namespace vk VkDevice m_device; }; - class buffer_deprecated - { - VkBufferView m_view = nullptr; - VkBuffer m_buffer = nullptr; - VkMemoryRequirements m_memory_layout; - VkFormat m_internal_format = VK_FORMAT_UNDEFINED; - VkBufferUsageFlagBits m_usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - VkBufferCreateFlags m_flags = 0; - - vk::render_device *owner; - vk::memory_block_deprecated vram; - u64 m_size = 0; - - bool viewable = false; - - public: - buffer_deprecated() {} - ~buffer_deprecated() {} - - void create(vk::render_device &dev, u64 size, VkFormat format = VK_FORMAT_UNDEFINED, VkBufferUsageFlagBits usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VkBufferCreateFlags flags = 0) - { - if (m_buffer) throw EXCEPTION("Buffer create called on an existing buffer!"); - - owner = &dev; - - VkBufferCreateInfo infos = {}; - infos.size = size; - infos.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - infos.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - infos.flags = flags; - infos.usage = usage; - - CHECK_RESULT(vkCreateBuffer(dev, &infos, nullptr, &m_buffer)); - - //Allocate vram for this buffer - vkGetBufferMemoryRequirements(dev, m_buffer, &m_memory_layout); - vram.allocate_from_pool(dev, m_memory_layout.size, m_memory_layout.memoryTypeBits); - - viewable = !!(usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)); - - //Bind buffer memory - vkBindBufferMemory(dev, m_buffer, vram, 0); - - m_size = m_memory_layout.size; - m_usage = usage; - m_flags = flags; - - set_format(format); - } - - void *map(u32 offset, u64 size) - { - if (!vram.is_mappable()) return nullptr; - - void *data = nullptr; - - if (size == VK_WHOLE_SIZE) - size = m_memory_layout.size; - - CHECK_RESULT(vkMapMemory((*owner), vram, offset, size, 0, &data)); - return data; - } - - void unmap() - { - vkUnmapMemory((*owner), vram); - } - - void sub_data(u32 offset, u32 size, void *data) - { - //TODO: Synchronization - if (!data && (m_size < size)) - { - vk::render_device *pdev = owner; - - destroy(); - create((*pdev), size, m_internal_format, m_usage, m_flags); - } - - if (!data) return; - if ((offset + size) > m_size) - { - vk::render_device *tmp_owner = owner; - destroy(); - create((*tmp_owner), size, m_internal_format, m_usage, m_flags); - } - - u8 *dst = (u8*)map(offset, size); - u8 *src = (u8*)data; - - memcpy(dst, src, size); - unmap(); - } - - void destroy() - { - if (!owner) return; - - vkDestroyBufferView((*owner), m_view, nullptr); - vkDestroyBuffer((*owner), m_buffer, nullptr); - vram.destroy(); - - owner = nullptr; - m_view = nullptr; - m_buffer = nullptr; - m_internal_format = VK_FORMAT_UNDEFINED; - } - - void set_format(VkFormat format) - { - if (m_internal_format == format || format == VK_FORMAT_UNDEFINED || !viewable) - return; - - if (m_view) - { - vkDestroyBufferView((*owner), m_view, nullptr); - m_view = nullptr; - } - - VkFormatProperties format_properties; - vk::physical_device dev = owner->gpu(); - vkGetPhysicalDeviceFormatProperties(dev, format, &format_properties); - - if (!(format_properties.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)) - throw EXCEPTION("Can't map view to requested format"); - - VkBufferViewCreateInfo view_info = {}; - view_info.buffer = m_buffer; - view_info.format = format; - view_info.range = m_size; - view_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; - - CHECK_RESULT(vkCreateBufferView((*owner), &view_info, nullptr, &m_view)); - - m_internal_format = format; - } - - u64 size() - { - return m_size; - } - - vk::render_device& get_owner() - { - return (*owner); - } - - operator VkBuffer() - { - return m_buffer; - } - - operator VkBufferView() - { - if (!viewable) - throw EXCEPTION("Invalid usage! Buffer cannot be viewed as texels."); - - return m_view; - } - }; - class framebuffer { VkFramebuffer m_vk_framebuffer = nullptr; @@ -1302,7 +1139,7 @@ namespace vk struct bound_buffer { - VkBufferView buffer_view = nullptr; + VkFormat format = VK_FORMAT_UNDEFINED; VkBuffer buffer = nullptr; u64 offset = 0; u64 size = 0; diff --git a/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp b/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp index 28aca5f727..a5cf747b32 100644 --- a/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp +++ b/rpcs3/Emu/RSX/VK/VKVertexBuffers.cpp @@ -216,6 +216,20 @@ namespace vk } } +namespace +{ + size_t alloc_and_copy(vk::buffer* buffer, vk::data_heap& data_heap_info, size_t size, std::function ptr)> copy_function) + { + size_t offset = data_heap_info.alloc<256>(size); + void* buf = buffer->map(offset, size); + gsl::span mapped_span = {reinterpret_cast(buf), gsl::narrow(size) }; + copy_function(mapped_span); + buffer->unmap(); + return offset; + } +} + + std::tuple VKGSRender::upload_vertex_data() { @@ -327,13 +341,10 @@ VKGSRender::upload_vertex_data() throw EXCEPTION("Unknown base type %d", vertex_info.type); } - auto &buffer = m_attrib_buffers[index]; + size_t offset_in_attrib_buffer = alloc_and_copy(m_attrib_buffers.get(), m_attrib_ring_info, data_size, [&vertex_arrays_data, data_size](gsl::span ptr) { memcpy(ptr.data(), vertex_arrays_data.data(), data_size); }); - buffer.sub_data(0, data_size, vertex_arrays_data.data()); - buffer.set_format(format); - - //Link texture to uniform location - m_program->bind_uniform(buffer, reg_table[index], descriptor_sets); + m_buffer_view_to_clean.push_back(std::make_unique(*m_device, m_attrib_buffers->value, format, offset_in_attrib_buffer, data_size)); + m_program->bind_uniform(m_buffer_view_to_clean.back()->value, reg_table[index], descriptor_sets); } } @@ -417,11 +428,9 @@ VKGSRender::upload_vertex_data() const VkFormat format = vk::get_suitable_vk_format(vertex_info.type, vertex_info.size); const u32 data_size = vk::get_suitable_vk_size(vertex_info.type, vertex_info.size) * num_stored_verts; - auto &buffer = m_attrib_buffers[index]; - - buffer.sub_data(0, data_size, data_ptr); - buffer.set_format(format); - m_program->bind_uniform(buffer, reg_table[index], descriptor_sets); + size_t offset_in_attrib_buffer = alloc_and_copy(m_attrib_buffers.get(), m_attrib_ring_info, data_size, [data_ptr, data_size](gsl::span ptr) { memcpy(ptr.data(), data_ptr, data_size); }); + m_buffer_view_to_clean.push_back(std::make_unique(*m_device, m_attrib_buffers->value, format, offset_in_attrib_buffer, data_size)); + m_program->bind_uniform(m_buffer_view_to_clean.back()->value, reg_table[index], descriptor_sets); } else if (register_vertex_info[index].size > 0) { @@ -455,12 +464,10 @@ VKGSRender::upload_vertex_data() data_size = converted_buffer.size(); } - auto &buffer = m_attrib_buffers[index]; - buffer.sub_data(0, data_size, data_ptr); - buffer.set_format(format); - - m_program->bind_uniform(buffer, reg_table[index], descriptor_sets); + size_t offset_in_attrib_buffer = alloc_and_copy(m_attrib_buffers.get(), m_attrib_ring_info, data_size, [data_ptr, data_size](gsl::span ptr) { memcpy(ptr.data(), data_ptr, data_size); }); + m_buffer_view_to_clean.push_back(std::make_unique(*m_device, m_attrib_buffers->value, format, offset_in_attrib_buffer, data_size)); + m_program->bind_uniform(m_buffer_view_to_clean.back()->value, reg_table[index], descriptor_sets); break; } default: