Skip to content

Commit

Permalink
vk: Optimize redundant QuadBuffer uploads
Browse files Browse the repository at this point in the history
Hashes the contents of the `QuadBuffer` vertex-data such that data is only uploaded when the vertices actually change rather than every frame.
  • Loading branch information
Wunkolo committed Oct 9, 2024
1 parent 556e2ea commit b66df39
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 5 deletions.
25 changes: 24 additions & 1 deletion core/rend/vulkan/quad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,19 @@

#include <memory>

namespace {
size_t hashQuadVertex(const QuadVertex& vertex)
{
size_t seed = 0;
seed ^= std::hash<float>{}(vertex.x) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
seed ^= std::hash<float>{}(vertex.y) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
seed ^= std::hash<float>{}(vertex.z) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
seed ^= std::hash<float>{}(vertex.u) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
seed ^= std::hash<float>{}(vertex.v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
return seed;
}
}

static VulkanContext *GetContext()
{
return VulkanContext::Instance();
Expand Down Expand Up @@ -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()];
Expand Down Expand Up @@ -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;
}
21 changes: 18 additions & 3 deletions core/rend/vulkan/quad.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,37 @@ 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 },
{ 1.f, 1.f, 0.f, 1.f, 1.f },
};
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<BufferData> buffer;

size_t hashQuadVertexData(QuadVertex vertices[4]) const;
size_t lastUploadHash = 0;
};

class QuadPipeline
Expand Down Expand Up @@ -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<QuadBuffer> buffer;
Expand Down
2 changes: 1 addition & 1 deletion core/rend/vulkan/vulkan_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down

0 comments on commit b66df39

Please sign in to comment.