[vulkan] Add a couple of staging helper functions

I got tired of writing the same 13 or so lines of code over and over (it
actually put me off experimenting with Vulkan). Thus...

QFV_PacketCopyBuffer does the work of handling barriers and a (full
packet) copy from the staging buffer to a GPU buffer.

QFV_PacketCopyImage does a similar job, but for images. However, it
still needs a lot of work, but it does make getting a basic texture onto
the GPU much less of a hassle.

Both functions should make staging data much less error-prone.
This commit is contained in:
Bill Currie 2022-10-03 09:09:34 +09:00
parent 51b73eee73
commit c028e15943
3 changed files with 61 additions and 2 deletions

View file

@ -6,13 +6,13 @@
#endif
#include <vulkan/vulkan.h>
typedef struct {
typedef struct qfv_imagebarrier_s {
VkPipelineStageFlags srcStages;
VkPipelineStageFlags dstStages;
VkImageMemoryBarrier barrier;
} qfv_imagebarrier_t;
typedef struct {
typedef struct qfv_bufferbarrier_s {
VkPipelineStageFlags srcStages;
VkPipelineStageFlags dstStages;
VkBufferMemoryBarrier barrier;

View file

@ -34,5 +34,12 @@ void QFV_FlushStagingBuffer (qfv_stagebuf_t *stage, size_t offset, size_t size);
qfv_packet_t *QFV_PacketAcquire (qfv_stagebuf_t *stage);
void *QFV_PacketExtend (qfv_packet_t *packet, size_t size);
void QFV_PacketSubmit (qfv_packet_t *packet);
struct qfv_bufferbarrier_s;
void QFV_PacketCopyBuffer (qfv_packet_t *packet, VkBuffer dstBuffer,
const struct qfv_bufferbarrier_s *dstBarrier);
struct qfv_imagebarrier_s;
void QFV_PacketCopyImage (qfv_packet_t *packet, VkImage dstImage,
int width, int height,
const struct qfv_imagebarrier_s *dstBarrier);
#endif//__QF_Vulkan_staging_h

View file

@ -30,6 +30,7 @@
#include "QF/dstring.h"
#include "QF/Vulkan/barrier.h"
#include "QF/Vulkan/buffer.h"
#include "QF/Vulkan/command.h"
#include "QF/Vulkan/debug.h"
@ -279,3 +280,54 @@ QFV_PacketSubmit (qfv_packet_t *packet)
// The fence was reset when the packet was acquired
dfunc->vkQueueSubmit (device->queue.queue, 1, &submitInfo, packet->fence);
}
void
QFV_PacketCopyBuffer (qfv_packet_t *packet, VkBuffer dstBuffer,
const qfv_bufferbarrier_t *dstBarrier)
{
qfv_devfuncs_t *dfunc = packet->stage->device->funcs;
qfv_bufferbarrier_t bb = bufferBarriers[qfv_BB_Unknown_to_TransferWrite];
bb.barrier.buffer = dstBuffer;
bb.barrier.size = packet->length;
dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages,
0, 0, 0, 1, &bb.barrier, 0, 0);
VkBufferCopy copy_region = { packet->offset, 0, packet->length };
dfunc->vkCmdCopyBuffer (packet->cmd, packet->stage->buffer, dstBuffer,
1, &copy_region);
bb = *dstBarrier;
bb.barrier.buffer = dstBuffer;
bb.barrier.size = packet->length;
dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages,
0, 0, 0, 1, &bb.barrier, 0, 0);
}
void
QFV_PacketCopyImage (qfv_packet_t *packet, VkImage dstImage,
int width, int height,
const qfv_imagebarrier_t *dstBarrier)
{
qfv_devfuncs_t *dfunc = packet->stage->device->funcs;
qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst];
ib.barrier.image = dstImage;
ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages,
0, 0, 0, 0, 0, 1, &ib.barrier);
VkBufferImageCopy copy_region = {
.bufferOffset = packet->offset,
.bufferRowLength = 0,
.bufferImageHeight = 0,
.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
{0, 0, 0}, {width, height, 1},
};
dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer,
dstImage,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &copy_region);
ib = *dstBarrier;
ib.barrier.image = dstImage;
ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages,
0, 0, 0, 0, 0, 1, &ib.barrier);
}