From 5611b4b17f8cf07259e33f9318b9265cb277c316 Mon Sep 17 00:00:00 2001 From: Panos Karabelas Date: Thu, 19 Dec 2024 13:32:54 +0000 Subject: [PATCH] [vulkan] fixed performance metrics text flickering which was due to the vertex and index buffers being read while they were being written to --- runtime/RHI/RHI_CommandList.h | 3 ++ runtime/RHI/Vulkan/Vulkan_CommandList.cpp | 32 +++++++++++++++ runtime/Rendering/Font/Font.cpp | 48 ++++++----------------- runtime/Rendering/Font/Font.h | 22 +++-------- runtime/Rendering/Renderer_Passes.cpp | 2 +- 5 files changed, 53 insertions(+), 54 deletions(-) diff --git a/runtime/RHI/RHI_CommandList.h b/runtime/RHI/RHI_CommandList.h index 89f1873f3..66cc98692 100644 --- a/runtime/RHI/RHI_CommandList.h +++ b/runtime/RHI/RHI_CommandList.h @@ -144,6 +144,9 @@ namespace Spartan void BeginTimeblock(const char* name, const bool gpu_marker = true, const bool gpu_timing = true); void EndTimeblock(); + // updates + void UpdateBuffer(RHI_Buffer* buffer, const uint64_t offset, const uint64_t size, const void* data); + // memory barriers void InsertBarrierTexture( void* image, diff --git a/runtime/RHI/Vulkan/Vulkan_CommandList.cpp b/runtime/RHI/Vulkan/Vulkan_CommandList.cpp index 42fb491a6..b2efb80fd 100644 --- a/runtime/RHI/Vulkan/Vulkan_CommandList.cpp +++ b/runtime/RHI/Vulkan/Vulkan_CommandList.cpp @@ -1570,6 +1570,38 @@ namespace Spartan m_timeblock_active = nullptr; } + void RHI_CommandList::UpdateBuffer(RHI_Buffer* buffer, const uint64_t offset, const uint64_t size, const void* data) + { + vkCmdUpdateBuffer + ( + static_cast(m_rhi_resource), + static_cast(buffer->GetRhiResource()), + offset, + size, + data + ); + + VkBufferMemoryBarrier barrier = {}; + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.buffer = static_cast(buffer->GetRhiResource()); + barrier.offset = offset; + barrier.size = size; + + vkCmdPipelineBarrier( + static_cast(m_rhi_resource), + VK_PIPELINE_STAGE_TRANSFER_BIT, // stage where the write happens + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, // stage where subsequent commands can read from the buffer + 0, + 0, nullptr, + 1, &barrier, + 0, nullptr + ); + } + void RHI_CommandList::InsertBarrierTexture( void* image, const uint32_t aspect_mask, diff --git a/runtime/Rendering/Font/Font.cpp b/runtime/Rendering/Font/Font.cpp index ccec6d4c3..a0f4c9a99 100644 --- a/runtime/Rendering/Font/Font.cpp +++ b/runtime/Rendering/Font/Font.cpp @@ -27,6 +27,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "../../Resource/Import/FontImporter.h" #include "../../RHI/RHI_Vertex.h" #include "../../RHI/RHI_Buffer.h" +#include "../../RHI/RHI_CommandList.h" //============================================= //= NAMESPACES =============== @@ -45,12 +46,8 @@ namespace Spartan Font::Font(const string& file_path, const uint32_t font_size, const Color& color) : IResource(ResourceType::Font) { - for (uint32_t i = 0; i < font_buffer_count; i++) - { - m_buffers[i].vertex = make_shared(); - m_buffers[i].index = make_shared(); - } - + m_buffer_vertex = make_shared(); + m_buffer_index = make_shared(); m_char_max_width = 0; m_char_max_height = 0; m_color = color; @@ -91,12 +88,6 @@ namespace Spartan if (Renderer::GetFrameNumber() < 1) return; - // new frame - if (text.empty()) - { - m_buffer_index = (m_buffer_index + 1) % font_buffer_count; - } - const float viewport_width = Renderer::GetViewport().width; const float viewport_height = Renderer::GetViewport().height; const float aspect_ratio = viewport_width / viewport_height; @@ -197,7 +188,7 @@ namespace Spartan m_font_size = Helper::Clamp(size, 8, 50); } - void Font::UpdateVertexAndIndexBuffers() + void Font::UpdateVertexAndIndexBuffers(RHI_CommandList* cmd_list) { if (m_font_data.empty()) return; @@ -223,9 +214,9 @@ namespace Spartan } // grow buffers - if (vertices.size() > GetVertexBuffer()->GetElementCount()) + if (vertices.size() > m_buffer_vertex->GetElementCount()) { - m_buffers[m_buffer_index].vertex = make_shared(RHI_Buffer_Type::Vertex, + m_buffer_vertex = make_shared(RHI_Buffer_Type::Vertex, sizeof(vertices[0]), static_cast(vertices.size()), static_cast(&vertices[0]), @@ -233,7 +224,7 @@ namespace Spartan "font" ); - m_buffers[m_buffer_index].index = make_shared(RHI_Buffer_Type::Index, + m_buffer_index = make_shared(RHI_Buffer_Type::Index, sizeof(indices[0]), static_cast(indices.size()), static_cast(&indices[0]), @@ -243,32 +234,15 @@ namespace Spartan } // copy the data over to the gpu - { - if (RHI_Vertex_PosTex* vertex_buffer = static_cast(GetVertexBuffer()->GetMappedData())) - { - // zero out the entire buffer first - this is because the buffer grows but doesn't shrink back (so it can hold previous data) - memset(vertex_buffer, 0, GetVertexBuffer()->GetObjectSize()); - - // now copy your actual vertices - copy(vertices.begin(), vertices.end(), vertex_buffer); - } - - if (uint32_t* index_buffer = static_cast(GetIndexBuffer()->GetMappedData())) - { - // zero out the entire buffer first - this is because the buffer grows but doesn't shrink back (so it can hold previous data) - memset(index_buffer, 0, GetIndexBuffer()->GetObjectSize()); - - // now copy your actual indices - copy(indices.begin(), indices.end(), index_buffer); - } - } + cmd_list->UpdateBuffer(m_buffer_vertex.get(), 0, vertices.size() * sizeof(RHI_Vertex_PosTex), vertices.data()); + cmd_list->UpdateBuffer(m_buffer_index.get(), 0, indices.size() * sizeof(uint32_t), indices.data()); m_font_data.clear(); } uint32_t Font::GetIndexCount() { - SP_ASSERT(GetIndexBuffer()); - return GetIndexBuffer()->GetElementCount(); + SP_ASSERT(m_buffer_index); + return m_buffer_index->GetElementCount(); } } diff --git a/runtime/Rendering/Font/Font.h b/runtime/Rendering/Font/Font.h index 32b909850..08b6f2311 100644 --- a/runtime/Rendering/Font/Font.h +++ b/runtime/Rendering/Font/Font.h @@ -26,9 +26,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include "Glyph.h" #include "../Color.h" -#include "../../RHI/RHI_Definitions.h" #include "../../Resource/IResource.h" -#include "../../Core/Definitions.h" +#include "../../RHI/RHI_Definitions.h" //==================================== namespace Spartan @@ -60,13 +59,6 @@ namespace Spartan Math::Vector2 position; }; - struct FontBuffer - { - std::shared_ptr vertex; - std::shared_ptr index; - }; - const uint32_t font_buffer_count = 3; - class Font : public IResource { public: @@ -104,13 +96,13 @@ namespace Spartan void SetAtlasOutline(const std::shared_ptr& atlas) { m_atlas_outline = atlas; } // misc - void UpdateVertexAndIndexBuffers(); + void UpdateVertexAndIndexBuffers(RHI_CommandList* cmd_list); uint32_t GetIndexCount(); // properties void SetSize(uint32_t size); - RHI_Buffer* GetIndexBuffer() const { return m_buffers[m_buffer_index].index.get(); } - RHI_Buffer* GetVertexBuffer() const { return m_buffers[m_buffer_index].vertex.get(); } + RHI_Buffer* GetIndexBuffer() const { return m_buffer_index.get(); } + RHI_Buffer* GetVertexBuffer() const { return m_buffer_vertex.get(); } uint32_t GetSize() const { return m_font_size; } Font_Hinting_Type GetHinting() const { return m_hinting; } auto GetForceAutohint() const { return m_force_autohint; } @@ -132,9 +124,7 @@ namespace Spartan std::shared_ptr m_atlas_outline; std::vector m_vertices; std::vector m_indices; - - // buffers - std::array m_buffers; - uint32_t m_buffer_index = 0; + std::shared_ptr m_buffer_index; + std::shared_ptr m_buffer_vertex; }; } diff --git a/runtime/Rendering/Renderer_Passes.cpp b/runtime/Rendering/Renderer_Passes.cpp index e4d1e454e..174c655d8 100644 --- a/runtime/Rendering/Renderer_Passes.cpp +++ b/runtime/Rendering/Renderer_Passes.cpp @@ -2301,7 +2301,7 @@ namespace Spartan pso.clear_color[0] = rhi_color_load; cmd_list->SetPipelineState(pso); - font->UpdateVertexAndIndexBuffers(); + font->UpdateVertexAndIndexBuffers(cmd_list); cmd_list->SetBufferVertex(font->GetVertexBuffer()); cmd_list->SetBufferIndex(font->GetIndexBuffer()); cmd_list->SetCullMode(RHI_CullMode::Back);