device wide staging buffer

This commit is contained in:
Gregory Wells
2025-07-09 16:21:00 -04:00
parent f6f856c1ec
commit 6ecaad4d7a
4 changed files with 44 additions and 44 deletions

View File

@@ -3,7 +3,11 @@
#include "output_device/gryphn_output_device.h" #include "output_device/gryphn_output_device.h"
#include "output_device/vulkan_output_devices.h" #include "output_device/vulkan_output_devices.h"
#include "output_device/vulkan_physical_device.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 vkGryphnBufferType(gnBufferType type) {
VkBufferUsageFlags usageFlags = 0; VkBufferUsageFlags usageFlags = 0;
@@ -58,28 +62,17 @@ gnReturnCode VkCreateBuffer(
return GN_SUCCESS; return GN_SUCCESS;
} }
void VkCopyBuffer(VkBuffer source, VkBuffer destination, size_t size, VkCommandPool pool, VkDevice device, VkQueue queue) { void VkCopyBuffer(gnDevice device, VkBuffer source, VkBuffer destination, VkBufferCopy copy) {
VkCommandBuffer transferBuffer = VkBeginTransferOperation(device, pool); VkCommandBuffer transferBuffer = gnBeginVulkanTransferOperation(device);
VkBufferCopy copyRegion = { vkCmdCopyBuffer(transferBuffer, source, destination, 1, &copy);
.size = size gnEndVulkanTransferOperation(device, transferBuffer);
};
vkCmdCopyBuffer(transferBuffer, source, destination, 1, &copyRegion);
VkEndTransferOperation(transferBuffer, pool, queue, device);
} }
gnReturnCode createBuffer(gnBufferHandle buffer, gnOutputDeviceHandle device, gnBufferInfo info) { gnReturnCode createBuffer(gnBufferHandle buffer, gnOutputDeviceHandle device, gnBufferInfo info) {
buffer->buffer = malloc(sizeof(struct gnPlatformBuffer_t)); buffer->buffer = malloc(sizeof(struct gnPlatformBuffer_t));
VkBufferUsageFlags usage = vkGryphnBufferType(info.type); VkBufferUsageFlags usage = vkGryphnBufferType(info.type);
buffer->buffer->useStagingBuffer = gnFalse; buffer->buffer->useStagingBuffer = (info.usage == GN_STATIC_DRAW);
if (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( return VkCreateBuffer(
&buffer->buffer->buffer, &buffer->buffer->buffer,
info.size, device, info.size, device,
@@ -99,32 +92,31 @@ gnReturnCode createBuffer(gnBufferHandle buffer, gnOutputDeviceHandle device, gn
return GN_SUCCESS; return GN_SUCCESS;
} }
void bufferData(gnBufferHandle buffer, size_t dataSize, void* data) { void bufferData(gnBufferHandle buffer, VkDeviceSize dataSize, void* data) {
void* bufferData; vulkanBufferSubData(buffer, 0, dataSize, data);
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 vulkanBufferSubData(gnBufferHandle buffer, size_t offset, size_t dataSize, void* data) { void vulkanBufferSubData(gnBufferHandle buffer, size_t offset, size_t dataSize, void* data) {
void* bufferData; void* bufferData;
if (buffer->buffer->useStagingBuffer) { if (buffer->buffer->useStagingBuffer) {
vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->stagingBuffer.memory, 0, dataSize, 0, &bufferData); VkGryphnBuffer* stagingBuffer = &buffer->device->outputDevice->stagingBuffer;
memcpy(bufferData + offset, data, dataSize); VkDeviceSize sizeLeft = dataSize;
vkUnmapMemory(buffer->device->outputDevice->device, buffer->buffer->stagingBuffer.memory); int copies = 0;
VkCopyBuffer( while (sizeLeft > 0) {
buffer->buffer->stagingBuffer.buffer, buffer->buffer->buffer.buffer, dataSize, VkDeviceSize chunkSize = (buffer->device->outputDevice->stagingBufferSize < sizeLeft) ? buffer->device->outputDevice->stagingBufferSize : sizeLeft;
buffer->device->outputDevice->transferCommandPool, buffer->device->outputDevice->device, vkMapMemory(buffer->device->outputDevice->device, stagingBuffer->memory, 0, dataSize, 0, &bufferData);
buffer->device->outputDevice->transferQueue); 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 { } else {
vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->buffer.memory, 0, dataSize, 0, &bufferData); vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->buffer.memory, 0, dataSize, 0, &bufferData);
memcpy(bufferData + offset, data, dataSize); memcpy(bufferData + offset, data, dataSize);
@@ -143,7 +135,7 @@ void gnDestroyVulkanBuffer(VkGryphnBuffer* buffer, VkDevice device) {
} }
void destroyBuffer(gnBufferHandle buffer) { 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); gnDestroyVulkanBuffer(&buffer->buffer->buffer, buffer->device->outputDevice->device);
free(buffer->buffer); free(buffer->buffer);
} }

View File

@@ -11,9 +11,6 @@ void gnDestroyVulkanBuffer(VkGryphnBuffer* buffer, VkDevice device);
struct gnPlatformBuffer_t { struct gnPlatformBuffer_t {
VkGryphnBuffer buffer; VkGryphnBuffer buffer;
// for if static draw
VkGryphnBuffer stagingBuffer;
gnBool useStagingBuffer; gnBool useStagingBuffer;
}; };
@@ -21,6 +18,7 @@ gnReturnCode VkCreateBuffer(
VkGryphnBuffer* buffer, size_t size, gnDevice device, VkGryphnBuffer* buffer, size_t size, gnDevice device,
VkMemoryPropertyFlags flags, VkBufferUsageFlags usage VkMemoryPropertyFlags flags, VkBufferUsageFlags usage
); );
void gnDestroyVulkanBuffer(VkGryphnBuffer* buffer, VkDevice device);
uint32_t VkMemoryIndex(VkPhysicalDevice device, uint32_t memoryType, VkMemoryPropertyFlags flags, gnBool* foundMemory); uint32_t VkMemoryIndex(VkPhysicalDevice device, uint32_t memoryType, VkMemoryPropertyFlags flags, gnBool* foundMemory);
gnReturnCode createBuffer(gnBufferHandle buffer, gnOutputDeviceHandle device, gnBufferInfo info); gnReturnCode createBuffer(gnBufferHandle buffer, gnOutputDeviceHandle device, gnBufferInfo info);

View File

@@ -85,7 +85,15 @@ gnReturnCode createOutputDevice(gnOutputDeviceHandle outputDevice, gnInstanceHan
free(queueCreateInfos); free(queueCreateInfos);
free(queueFamilies); 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) { void waitForDevice(const gnOutputDeviceHandle device) {
@@ -93,6 +101,7 @@ void waitForDevice(const gnOutputDeviceHandle device) {
} }
void destroyOutputDevice(gnOutputDeviceHandle device) { void destroyOutputDevice(gnOutputDeviceHandle device) {
gnDestroyVulkanBuffer(&device->outputDevice->stagingBuffer, device->outputDevice->device);
vkDestroyCommandPool(device->outputDevice->device, device->outputDevice->transferCommandPool, NULL); vkDestroyCommandPool(device->outputDevice->device, device->outputDevice->transferCommandPool, NULL);
vkDestroyDevice(device->outputDevice->device, NULL); vkDestroyDevice(device->outputDevice->device, NULL);
free(device->outputDevice); free(device->outputDevice);

View File

@@ -12,6 +12,7 @@ typedef struct gnPlatformOutputDevice_t {
VkCommandPool transferCommandPool; VkCommandPool transferCommandPool;
VkGryphnBuffer stagingBuffer; VkGryphnBuffer stagingBuffer;
VkDeviceSize stagingBufferSize;
gnBool enabledOversizedDescriptorPools; gnBool enabledOversizedDescriptorPools;
} gnPlatformOutputDevice; } gnPlatformOutputDevice;