From 6ecaad4d7ae8b95b952a1185a033821002ce990e Mon Sep 17 00:00:00 2001 From: Gregory Wells Date: Wed, 9 Jul 2025 16:21:00 -0400 Subject: [PATCH] device wide staging buffer --- .../apis/vulkan/src/buffers/vulkan_buffer.c | 72 +++++++++---------- .../apis/vulkan/src/buffers/vulkan_buffer.h | 4 +- .../src/output_device/vulkan_output_device.c | 11 ++- .../src/output_device/vulkan_output_devices.h | 1 + 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/projects/apis/vulkan/src/buffers/vulkan_buffer.c b/projects/apis/vulkan/src/buffers/vulkan_buffer.c index 9a4753f..5f41969 100644 --- a/projects/apis/vulkan/src/buffers/vulkan_buffer.c +++ b/projects/apis/vulkan/src/buffers/vulkan_buffer.c @@ -3,7 +3,11 @@ #include "output_device/gryphn_output_device.h" #include "output_device/vulkan_output_devices.h" #include "output_device/vulkan_physical_device.h" -#include "commands/command_buffer/vulkan_command_buffer.h" + +VkDeviceSize min(VkDeviceSize a, VkDeviceSize b) { + if (a >= b) return a; + return b; +} VkBufferUsageFlags vkGryphnBufferType(gnBufferType type) { VkBufferUsageFlags usageFlags = 0; @@ -58,28 +62,17 @@ gnReturnCode VkCreateBuffer( return GN_SUCCESS; } -void VkCopyBuffer(VkBuffer source, VkBuffer destination, size_t size, VkCommandPool pool, VkDevice device, VkQueue queue) { - VkCommandBuffer transferBuffer = VkBeginTransferOperation(device, pool); - VkBufferCopy copyRegion = { - .size = size - }; - vkCmdCopyBuffer(transferBuffer, source, destination, 1, ©Region); - VkEndTransferOperation(transferBuffer, pool, queue, device); +void VkCopyBuffer(gnDevice device, VkBuffer source, VkBuffer destination, VkBufferCopy copy) { + VkCommandBuffer transferBuffer = gnBeginVulkanTransferOperation(device); + vkCmdCopyBuffer(transferBuffer, source, destination, 1, ©); + gnEndVulkanTransferOperation(device, transferBuffer); } gnReturnCode createBuffer(gnBufferHandle buffer, gnOutputDeviceHandle device, gnBufferInfo info) { buffer->buffer = malloc(sizeof(struct gnPlatformBuffer_t)); VkBufferUsageFlags usage = vkGryphnBufferType(info.type); - buffer->buffer->useStagingBuffer = gnFalse; + buffer->buffer->useStagingBuffer = (info.usage == GN_STATIC_DRAW); if (info.usage == GN_STATIC_DRAW) { - buffer->buffer->useStagingBuffer = gnTrue; - VkCreateBuffer( - &buffer->buffer->stagingBuffer, - info.size, device, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT - ); - return VkCreateBuffer( &buffer->buffer->buffer, info.size, device, @@ -99,32 +92,31 @@ gnReturnCode createBuffer(gnBufferHandle buffer, gnOutputDeviceHandle device, gn return GN_SUCCESS; } -void bufferData(gnBufferHandle buffer, size_t dataSize, void* data) { - void* bufferData; - if (buffer->buffer->useStagingBuffer) { - vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->stagingBuffer.memory, 0, dataSize, 0, &bufferData); - memcpy(bufferData, data, dataSize); - vkUnmapMemory(buffer->device->outputDevice->device, buffer->buffer->stagingBuffer.memory); - VkCopyBuffer( - buffer->buffer->stagingBuffer.buffer, buffer->buffer->buffer.buffer, dataSize, - buffer->device->outputDevice->transferCommandPool, buffer->device->outputDevice->device, - buffer->device->outputDevice->transferQueue); - } else { - vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->buffer.memory, 0, dataSize, 0, &bufferData); - memcpy(bufferData, data, dataSize); - vkUnmapMemory(buffer->device->outputDevice->device, buffer->buffer->buffer.memory); - } +void bufferData(gnBufferHandle buffer, VkDeviceSize dataSize, void* data) { + vulkanBufferSubData(buffer, 0, dataSize, data); } void vulkanBufferSubData(gnBufferHandle buffer, size_t offset, size_t dataSize, void* data) { void* bufferData; + if (buffer->buffer->useStagingBuffer) { - vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->stagingBuffer.memory, 0, dataSize, 0, &bufferData); - memcpy(bufferData + offset, data, dataSize); - vkUnmapMemory(buffer->device->outputDevice->device, buffer->buffer->stagingBuffer.memory); - VkCopyBuffer( - buffer->buffer->stagingBuffer.buffer, buffer->buffer->buffer.buffer, dataSize, - buffer->device->outputDevice->transferCommandPool, buffer->device->outputDevice->device, - buffer->device->outputDevice->transferQueue); + VkGryphnBuffer* stagingBuffer = &buffer->device->outputDevice->stagingBuffer; + VkDeviceSize sizeLeft = dataSize; + int copies = 0; + while (sizeLeft > 0) { + VkDeviceSize chunkSize = (buffer->device->outputDevice->stagingBufferSize < sizeLeft) ? buffer->device->outputDevice->stagingBufferSize : sizeLeft; + vkMapMemory(buffer->device->outputDevice->device, stagingBuffer->memory, 0, dataSize, 0, &bufferData); + memcpy(bufferData, data + (dataSize - sizeLeft), chunkSize); + vkUnmapMemory(buffer->device->outputDevice->device, stagingBuffer->memory); + + VkBufferCopy copyRegion = { + .srcOffset = 0, + .dstOffset = offset + (dataSize - sizeLeft), + .size = chunkSize + }; + VkCopyBuffer(buffer->device, stagingBuffer->buffer, buffer->buffer->buffer.buffer, copyRegion); + sizeLeft -= chunkSize; + copies++; + } } else { vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->buffer.memory, 0, dataSize, 0, &bufferData); memcpy(bufferData + offset, data, dataSize); @@ -143,7 +135,7 @@ void gnDestroyVulkanBuffer(VkGryphnBuffer* buffer, VkDevice device) { } void destroyBuffer(gnBufferHandle buffer) { - if (buffer->buffer->useStagingBuffer == gnTrue) gnDestroyVulkanBuffer(&buffer->buffer->stagingBuffer, buffer->device->outputDevice->device); + // if (buffer->buffer->useStagingBuffer == gnTrue) gnDestroyVulkanBuffer(&buffer->buffer->stagingBuffer, buffer->device->outputDevice->device); gnDestroyVulkanBuffer(&buffer->buffer->buffer, buffer->device->outputDevice->device); free(buffer->buffer); } diff --git a/projects/apis/vulkan/src/buffers/vulkan_buffer.h b/projects/apis/vulkan/src/buffers/vulkan_buffer.h index 98eb634..d7f3524 100644 --- a/projects/apis/vulkan/src/buffers/vulkan_buffer.h +++ b/projects/apis/vulkan/src/buffers/vulkan_buffer.h @@ -11,9 +11,6 @@ void gnDestroyVulkanBuffer(VkGryphnBuffer* buffer, VkDevice device); struct gnPlatformBuffer_t { VkGryphnBuffer buffer; - - // for if static draw - VkGryphnBuffer stagingBuffer; gnBool useStagingBuffer; }; @@ -21,6 +18,7 @@ gnReturnCode VkCreateBuffer( VkGryphnBuffer* buffer, size_t size, gnDevice device, VkMemoryPropertyFlags flags, VkBufferUsageFlags usage ); +void gnDestroyVulkanBuffer(VkGryphnBuffer* buffer, VkDevice device); uint32_t VkMemoryIndex(VkPhysicalDevice device, uint32_t memoryType, VkMemoryPropertyFlags flags, gnBool* foundMemory); gnReturnCode createBuffer(gnBufferHandle buffer, gnOutputDeviceHandle device, gnBufferInfo info); diff --git a/projects/apis/vulkan/src/output_device/vulkan_output_device.c b/projects/apis/vulkan/src/output_device/vulkan_output_device.c index 156bdb4..5c761b4 100644 --- a/projects/apis/vulkan/src/output_device/vulkan_output_device.c +++ b/projects/apis/vulkan/src/output_device/vulkan_output_device.c @@ -85,7 +85,15 @@ gnReturnCode createOutputDevice(gnOutputDeviceHandle outputDevice, gnInstanceHan free(queueCreateInfos); free(queueFamilies); - return GN_SUCCESS; + // create the massive staging buffer + outputDevice->outputDevice->stagingBufferSize = 128 * 1024 * 1024; + gnReturnCode code = VkCreateBuffer( + &outputDevice->outputDevice->stagingBuffer, + outputDevice->outputDevice->stagingBufferSize, outputDevice, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT + ); + return code; // lowkey is a hack } void waitForDevice(const gnOutputDeviceHandle device) { @@ -93,6 +101,7 @@ void waitForDevice(const gnOutputDeviceHandle device) { } void destroyOutputDevice(gnOutputDeviceHandle device) { + gnDestroyVulkanBuffer(&device->outputDevice->stagingBuffer, device->outputDevice->device); vkDestroyCommandPool(device->outputDevice->device, device->outputDevice->transferCommandPool, NULL); vkDestroyDevice(device->outputDevice->device, NULL); free(device->outputDevice); diff --git a/projects/apis/vulkan/src/output_device/vulkan_output_devices.h b/projects/apis/vulkan/src/output_device/vulkan_output_devices.h index 8d5668d..76172a1 100644 --- a/projects/apis/vulkan/src/output_device/vulkan_output_devices.h +++ b/projects/apis/vulkan/src/output_device/vulkan_output_devices.h @@ -12,6 +12,7 @@ typedef struct gnPlatformOutputDevice_t { VkCommandPool transferCommandPool; VkGryphnBuffer stagingBuffer; + VkDeviceSize stagingBufferSize; gnBool enabledOversizedDescriptorPools; } gnPlatformOutputDevice;