Skip to content

Commit

Permalink
vulkan: memory barriers for buffer copy/write operations.
Browse files Browse the repository at this point in the history
  • Loading branch information
slime73 committed Sep 30, 2024
1 parent 6d40eab commit 64e4eae
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/modules/graphics/Graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ namespace opengl { extern love::graphics::Graphics *createInstance(); }
namespace metal { extern love::graphics::Graphics *createInstance(); }
#endif
#ifdef LOVE_GRAPHICS_VULKAN
namespace vulkan { extern love::graphics::Graphics* createInstance(); }
namespace vulkan { extern love::graphics::Graphics *createInstance(); }
#endif

static const Renderer rendererOrder[] = {
Expand Down
67 changes: 63 additions & 4 deletions src/modules/graphics/vulkan/Buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ bool Buffer::loadVolatile()
throw love::Exception("failed to create buffer");

if (zeroInitialize)
vkCmdFillBuffer(vgfx->getCommandBufferForDataTransfer(), buffer, 0, VK_WHOLE_SIZE, 0);
{
auto cmd = vgfx->getCommandBufferForDataTransfer();
vkCmdFillBuffer(cmd, buffer, 0, VK_WHOLE_SIZE, 0);
postGPUWriteBarrier(cmd);
}

if (initialData)
fill(0, size, initialData);
Expand Down Expand Up @@ -235,7 +239,10 @@ bool Buffer::fill(size_t offset, size_t size, const void *data)
bufferCopy.dstOffset = offset;
bufferCopy.size = size;

vkCmdCopyBuffer(vgfx->getCommandBufferForDataTransfer(), fillBuffer, buffer, 1, &bufferCopy);
auto cmd = vgfx->getCommandBufferForDataTransfer();
vkCmdCopyBuffer(cmd, fillBuffer, buffer, 1, &bufferCopy);

postGPUWriteBarrier(cmd);

vgfx->queueCleanUp([allocator = allocator, fillBuffer = fillBuffer, fillAllocation = fillAllocation]() {
vmaDestroyBuffer(allocator, fillBuffer, fillAllocation);
Expand All @@ -258,7 +265,10 @@ void Buffer::unmap(size_t usedoffset, size_t usedsize)
if (~memoryProperties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
vmaFlushAllocation(allocator, stagingAllocation, bufferCopy.srcOffset, usedsize);

vkCmdCopyBuffer(vgfx->getCommandBufferForDataTransfer(), stagingBuffer, buffer, 1, &bufferCopy);
auto cmd = vgfx->getCommandBufferForDataTransfer();
vkCmdCopyBuffer(cmd, stagingBuffer, buffer, 1, &bufferCopy);

postGPUWriteBarrier(cmd);

vgfx->queueCleanUp([allocator = allocator, stagingBuffer = stagingBuffer, stagingAllocation = stagingAllocation]() {
vmaDestroyBuffer(allocator, stagingBuffer, stagingAllocation);
Expand All @@ -268,7 +278,9 @@ void Buffer::unmap(size_t usedoffset, size_t usedsize)

void Buffer::clearInternal(size_t offset, size_t size)
{
vkCmdFillBuffer(vgfx->getCommandBufferForDataTransfer(), buffer, offset, size, 0);
auto cmd = vgfx->getCommandBufferForDataTransfer();
vkCmdFillBuffer(cmd, buffer, offset, size, 0);
postGPUWriteBarrier(cmd);
}

void Buffer::copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size)
Expand All @@ -281,6 +293,53 @@ void Buffer::copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t de
bufferCopy.size = size;

vkCmdCopyBuffer(commandBuffer, buffer, (VkBuffer) dest->getHandle(), 1, &bufferCopy);

((Buffer *)dest)->postGPUWriteBarrier(commandBuffer);
}

void Buffer::postGPUWriteBarrier(VkCommandBuffer cmd)
{
VkMemoryBarrier barrier{};
barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;

VkPipelineStageFlags dstStageMask = 0;
addPostGPUWriteBarrierFlags(barrier.dstAccessMask, dstStageMask);

vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, dstStageMask, 0, 1, &barrier, 0, nullptr, 0, nullptr);
}

void Buffer::addPostGPUWriteBarrierFlags(VkAccessFlags &dstAccessFlags, VkPipelineStageFlags &dstStageFlags)
{
// All buffers can be copied to and from.
dstAccessFlags |= VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
dstStageFlags |= VK_PIPELINE_STAGE_TRANSFER_BIT;

if (usageFlags & BUFFERUSAGEFLAG_VERTEX)
{
dstAccessFlags |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
dstStageFlags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
}
if (usageFlags & BUFFERUSAGEFLAG_INDEX)
{
dstAccessFlags |= VK_ACCESS_INDEX_READ_BIT;
dstStageFlags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
}
if (usageFlags & BUFFERUSAGEFLAG_TEXEL)
{
dstAccessFlags |= VK_ACCESS_SHADER_READ_BIT;
dstStageFlags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
}
if (usageFlags & BUFFERUSAGEFLAG_SHADER_STORAGE)
{
dstAccessFlags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
dstStageFlags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
}
if (usageFlags & BUFFERUSAGEFLAG_INDIRECT_ARGUMENTS)
{
dstAccessFlags |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
dstStageFlags |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
}
}

} // vulkan
Expand Down
3 changes: 3 additions & 0 deletions src/modules/graphics/vulkan/Buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ class Buffer final
ptrdiff_t getHandle() const override;
ptrdiff_t getTexelBufferHandle() const override;

void postGPUWriteBarrier(VkCommandBuffer cmd);
void addPostGPUWriteBarrierFlags(VkAccessFlags &dstAccessFlags, VkPipelineStageFlags &dstStageFlags);

private:

void clearInternal(size_t offset, size_t size) override;
Expand Down
4 changes: 4 additions & 0 deletions src/modules/graphics/vulkan/Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "Texture.h"
#include "Graphics.h"
#include "Vulkan.h"
#include "Buffer.h"

#include <limits>

Expand Down Expand Up @@ -683,6 +684,9 @@ void Texture::copyToBuffer(graphics::Buffer *dest, int slice, int mipmap, const
}
else
vkCmdCopyImageToBuffer(commandBuffer, textureImage, VK_IMAGE_LAYOUT_GENERAL, (VkBuffer)dest->getHandle(), 1, &region);

// TODO: This could be combined with the cmdTransitionImageLayout barrier.
((Buffer *)dest)->postGPUWriteBarrier(commandBuffer);
}

} // vulkan
Expand Down

0 comments on commit 64e4eae

Please sign in to comment.