From bbea352e3b9dc07bb97519e1af75fedf3a138b9c Mon Sep 17 00:00:00 2001 From: Wunkolo Date: Tue, 8 Oct 2024 20:13:16 -0700 Subject: [PATCH] vk: Optimize redundant `QuadBuffer` uploads Hashes the contents of the `QuadBuffer` vertex-data such that data is only uploaded when the vertices actually change rather than every frame. --- core/rend/vulkan/quad.cpp | 25 ++++++++++++++++++++++++- core/rend/vulkan/quad.h | 21 ++++++++++++++++++--- core/rend/vulkan/vk_context_lr.cpp | 2 +- core/rend/vulkan/vulkan_context.cpp | 4 ++-- 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/core/rend/vulkan/quad.cpp b/core/rend/vulkan/quad.cpp index 3458075cba..c82868f530 100644 --- a/core/rend/vulkan/quad.cpp +++ b/core/rend/vulkan/quad.cpp @@ -23,6 +23,19 @@ #include +namespace { + size_t hashQuadVertex(const QuadVertex& vertex) + { + size_t seed = 0; + seed ^= std::hash{}(vertex.x) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + seed ^= std::hash{}(vertex.y) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + seed ^= std::hash{}(vertex.z) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + seed ^= std::hash{}(vertex.u) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + seed ^= std::hash{}(vertex.v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + return seed; + } +} + static VulkanContext *GetContext() { return VulkanContext::Instance(); @@ -169,7 +182,7 @@ void QuadDrawer::Init(QuadPipeline *pipeline) descSet.reset(); } -void QuadDrawer::Draw(vk::CommandBuffer commandBuffer, vk::ImageView imageView, QuadVertex vertices[], bool nearestFilter, const float *color) +void QuadDrawer::Draw(vk::CommandBuffer commandBuffer, vk::ImageView imageView, QuadVertex vertices[4], bool nearestFilter, const float *color) { VulkanContext *context = GetContext(); auto &descSet = descriptorSets[context->GetCurrentImageIndex()]; @@ -198,3 +211,13 @@ void QuadDrawer::Draw(vk::CommandBuffer commandBuffer, vk::ImageView imageView, commandBuffer.pushConstants(pipeline->GetPipelineLayout(), vk::ShaderStageFlagBits::eFragment, 0, sizeof(float) * 4, color); buffer->Draw(commandBuffer); } + +size_t QuadBuffer::hashQuadVertexData(QuadVertex vertices[4]) const +{ + size_t seed = 0; + seed ^= hashQuadVertex(vertices[0]) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + seed ^= hashQuadVertex(vertices[1]) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + seed ^= hashQuadVertex(vertices[2]) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + seed ^= hashQuadVertex(vertices[3]) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + return seed; +} diff --git a/core/rend/vulkan/quad.h b/core/rend/vulkan/quad.h index cc36bef081..d3e060e641 100644 --- a/core/rend/vulkan/quad.h +++ b/core/rend/vulkan/quad.h @@ -50,11 +50,12 @@ class QuadBuffer commandBuffer.draw(4, 1, 0, 0); } - void Update(QuadVertex vertices[] = nullptr) + void Update(QuadVertex vertices[4] = nullptr) { if (vertices == nullptr) { - static QuadVertex defaultVtx[] { + static QuadVertex defaultVtx[4] + { { -1.f, -1.f, 0.f, 0.f, 0.f }, { 1.f, -1.f, 0.f, 1.f, 0.f }, { -1.f, 1.f, 0.f, 0.f, 1.f }, @@ -62,10 +63,24 @@ class QuadBuffer }; vertices = defaultVtx; }; + + const size_t quadVerticesHash = hashQuadVertexData(vertices);; + if (quadVerticesHash == lastUploadHash) + { + // data already uploaded + return; + } + + // new data to upload, update hash + lastUploadHash = quadVerticesHash; buffer->upload(sizeof(QuadVertex) * 4, vertices); + } private: std::unique_ptr buffer; + + size_t hashQuadVertexData(QuadVertex vertices[4]) const; + size_t lastUploadHash = 0; }; class QuadPipeline @@ -119,7 +134,7 @@ class QuadDrawer QuadDrawer& operator=(const QuadDrawer &) = delete; void Init(QuadPipeline *pipeline); - void Draw(vk::CommandBuffer commandBuffer, vk::ImageView imageView, QuadVertex vertices[] = nullptr, bool nearestFilter = false, const float *color = nullptr); + void Draw(vk::CommandBuffer commandBuffer, vk::ImageView imageView, QuadVertex vertices[4] = nullptr, bool nearestFilter = false, const float *color = nullptr); private: QuadPipeline *pipeline = nullptr; std::unique_ptr buffer; diff --git a/core/rend/vulkan/vk_context_lr.cpp b/core/rend/vulkan/vk_context_lr.cpp index 4f999de65c..5f0db5c724 100644 --- a/core/rend/vulkan/vk_context_lr.cpp +++ b/core/rend/vulkan/vk_context_lr.cpp @@ -329,7 +329,7 @@ void VulkanContext::PresentFrame(vk::Image image, vk::ImageView imageView, const getVideoShift(shiftX, shiftY); beginFrame(extent); - QuadVertex vtx[] { + QuadVertex vtx[4] { { -1, -1, 0, 0, 0 }, { 1, -1, 0, 1, 0 }, { -1, 1, 0, 0, 1 }, diff --git a/core/rend/vulkan/vulkan_context.cpp b/core/rend/vulkan/vulkan_context.cpp index 6761420571..c3b7d153c8 100644 --- a/core/rend/vulkan/vulkan_context.cpp +++ b/core/rend/vulkan/vulkan_context.cpp @@ -924,7 +924,7 @@ void VulkanContext::Present() noexcept void VulkanContext::DrawFrame(vk::ImageView imageView, const vk::Extent2D& extent, float aspectRatio) { - QuadVertex vtx[] { + QuadVertex vtx[4] { { -1, -1, 0, 0, 0 }, { 1, -1, 0, 1, 0 }, { -1, 1, 0, 0, 1 }, @@ -1314,7 +1314,7 @@ bool VulkanContext::GetLastFrame(std::vector& data, int& width, int& height) pipeline.BindPipeline(*commandBuffer); // Draw - QuadVertex vtx[] { + QuadVertex vtx[4] { { -1, -1, 0, 0, 0 }, { 1, -1, 0, 1, 0 }, { -1, 1, 0, 0, 1 },