JBR-9174 Vulkan: Cleanup image/buffer barriers

This commit is contained in:
Nikita Gubarkov
2025-08-07 11:08:46 +02:00
parent a1dc378601
commit 26f391e23a
3 changed files with 19 additions and 65 deletions

View File

@@ -30,7 +30,6 @@
#include "VKAllocator.h"
#include "VKBuffer.h"
#include "VKDevice.h"
#include "VKRenderer.h"
#define VK_BUFFER_HOST_COHERENT_MEMORY
@@ -233,6 +232,11 @@ void VKBuffer_Dispose(VKDevice* device, void* data) {
VKBuffer_Destroy(device, buffer);
}
// TODO This is an internal API and should not be used from VKBuffer!
void VKRenderer_RecordBarriers(VKRenderer* renderer,
VkBufferMemoryBarrier* bufferBarriers, VKBarrierBatch* bufferBatch,
VkImageMemoryBarrier* imageBarriers, VKBarrierBatch* imageBatch);
VKBuffer *VKBuffer_CreateFromRaster(VKDevice *device,
VKBuffer_RasterInfo info,
VkPipelineStageFlags stage,
@@ -270,19 +274,10 @@ VKBuffer *VKBuffer_CreateFromRaster(VKDevice *device,
device->vkUnmapMemory(device->handle, buffer->range.memory);
{
VkCommandBuffer cb = VKRenderer_Record(device->renderer);
VkBufferMemoryBarrier barrier;
VKBarrierBatch barrierBatch = {};
VKBuffer_AddBarrier(&barrier, &barrierBatch, buffer,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, stage, access);
if (barrierBatch.barrierCount > 0) {
device->vkCmdPipelineBarrier(cb, barrierBatch.srcStages,
barrierBatch.dstStages,
0, 0, NULL,
barrierBatch.barrierCount, &barrier,
0, NULL);
}
VKBuffer_AddBarrier(&barrier, &barrierBatch, buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, stage, access);
VKRenderer_RecordBarriers(device->renderer, &barrier, &barrierBatch, NULL, NULL);
}
return buffer;
}

View File

@@ -558,36 +558,6 @@ void VKRenderer_Flush(VKRenderer* renderer) {
renderer, submitInfo.commandBufferCount, pendingPresentations);
}
/**
* Prepare image barrier info to be executed in batch, if needed.
*/
void VKRenderer_AddImageBarrier(VkImageMemoryBarrier* barriers, VKBarrierBatch* batch,
VKImage* image, VkPipelineStageFlags stage, VkAccessFlags access, VkImageLayout layout) {
assert(barriers != NULL && batch != NULL && image != NULL);
// TODO Even if stage, access and layout didn't change, we may still need a barrier against WaW hazard.
if (stage != image->lastStage || access != image->lastAccess || layout != image->layout) {
barriers[batch->barrierCount] = (VkImageMemoryBarrier) {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcAccessMask = image->lastAccess,
.dstAccessMask = access,
.oldLayout = image->layout,
.newLayout = layout,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image->handle,
.subresourceRange = { VKUtil_GetFormatGroup(image->format).aspect, 0, 1, 0, 1 }
};
batch->barrierCount++;
batch->srcStages |= image->lastStage;
batch->dstStages |= stage;
image->lastStage = stage;
image->lastAccess = access;
image->layout = layout;
}
}
/**
* Get Color RGBA components in a suitable for the current render pass.
*/
@@ -890,24 +860,20 @@ VkBool32 VKRenderer_FlushRenderPass(VKSDOps* surface) {
}
ARRAY_RESIZE(surface->renderPass->usedSurfaces, 0);
// Insert barriers to prepare surface for rendering.
VkImageMemoryBarrier barriers[2];
VKBarrierBatch barrierBatch = {};
VKRenderer_AddImageBarrier(barriers, &barrierBatch, surface->image,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
VKImage_AddBarrier(barriers, &barrierBatch, surface->image,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
if (surface->stencil != NULL) {
VKRenderer_AddImageBarrier(barriers, &barrierBatch, surface->stencil,
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
}
if (barrierBatch.barrierCount > 0) {
device->vkCmdPipelineBarrier(cb, barrierBatch.srcStages, barrierBatch.dstStages,
0, 0, NULL, 0, NULL, barrierBatch.barrierCount, barriers);
VKImage_AddBarrier(barriers, &barrierBatch, surface->stencil,
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
}
VKRenderer_RecordBarriers(renderer, NULL, NULL, barriers, &barrierBatch);
// If there is a pending clear, record it into render pass.
if (clear) VKRenderer_BeginRenderPass(surface);
@@ -1003,10 +969,9 @@ void VKRenderer_FlushSurface(VKSDOps* surface) {
.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
}};
VKBarrierBatch barrierBatch = {1, surface->image->lastStage | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT};
VKRenderer_AddImageBarrier(barriers, &barrierBatch, surface->image, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
device->vkCmdPipelineBarrier(cb, barrierBatch.srcStages, barrierBatch.dstStages,
0, 0, NULL, 0, NULL, barrierBatch.barrierCount, barriers);
VKImage_AddBarrier(barriers, &barrierBatch, surface->image, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
VKRenderer_RecordBarriers(renderer, NULL, NULL, barriers, &barrierBatch);
}
// Do blit.

View File

@@ -76,12 +76,6 @@ void VKRenderer_FlushDraw(VKSDOps* surface);
*/
VkCommandBuffer VKRenderer_Record(VKRenderer* renderer);
/**
* Prepare image barrier info to be executed in batch, if needed.
*/
void VKRenderer_AddImageBarrier(VkImageMemoryBarrier* barriers, VKBarrierBatch* batch,
VKImage* image, VkPipelineStageFlags stage, VkAccessFlags access, VkImageLayout layout);
/**
* Record barrier batches into the primary command buffer.
*/