From 665ce6847a3b668fc18ff917689058e320433d91 Mon Sep 17 00:00:00 2001 From: Greg Wells Date: Thu, 3 Jul 2025 13:30:47 -0400 Subject: [PATCH] add support for storage buffers in vulkan --- .../apis/vulkan/loader/vulkan_device_loader.c | 2 ++ .../apis/vulkan/src/buffers/vulkan_buffer.c | 17 ++++++++++++++++ .../apis/vulkan/src/buffers/vulkan_buffer.h | 1 + .../apis/vulkan/src/uniforms/vulkan_uniform.c | 20 +++++++++++++++++++ .../apis/vulkan/src/uniforms/vulkan_uniform.h | 1 + .../vulkan/src/uniforms/vulkan_uniform_pool.c | 20 +++++++++---------- projects/core/src/buffers/gryphn_buffer.c | 3 +++ projects/core/src/buffers/gryphn_buffer.h | 4 +++- projects/core/src/uniforms/gryphn_uniform.c | 4 ++++ projects/core/src/uniforms/gryphn_uniform.h | 9 ++++++++- .../core/src/uniforms/gryphn_uniform_layout.h | 2 +- projects/loader/src/gryphn_device_functions.h | 3 +++ .../function_loader/loader/function_loader.c | 2 ++ .../function_loader/src/device_functions.c | 6 ++++++ .../function_loader/src/device_functions.h | 2 ++ 15 files changed, 83 insertions(+), 13 deletions(-) diff --git a/projects/apis/vulkan/loader/vulkan_device_loader.c b/projects/apis/vulkan/loader/vulkan_device_loader.c index c214dea..fad6bb2 100644 --- a/projects/apis/vulkan/loader/vulkan_device_loader.c +++ b/projects/apis/vulkan/loader/vulkan_device_loader.c @@ -41,6 +41,7 @@ gnDeviceFunctions loadVulkanDeviceFunctions() { ._gnCreateBuffer = createBuffer, ._gnBufferData = bufferData, + ._gnBufferSubData = vulkanBufferSubData, ._gnMapBuffer = mapBuffer, ._gnDestroyBuffer = destroyBuffer, @@ -49,6 +50,7 @@ gnDeviceFunctions loadVulkanDeviceFunctions() { ._gnDestroyUniformPool = destroyUniformPool, ._gnUpdateBufferUniform = updateBufferUniform, + ._gnUpdateStorageUniform = updateVulkanStorageUniform, ._gnUpdateImageUniform = updateImageUniform, ._gnCreateTexture = createTexture, diff --git a/projects/apis/vulkan/src/buffers/vulkan_buffer.c b/projects/apis/vulkan/src/buffers/vulkan_buffer.c index 464539a..9a4753f 100644 --- a/projects/apis/vulkan/src/buffers/vulkan_buffer.c +++ b/projects/apis/vulkan/src/buffers/vulkan_buffer.c @@ -11,6 +11,7 @@ VkBufferUsageFlags vkGryphnBufferType(gnBufferType type) { case GN_VERTEX_BUFFER: usageFlags |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; break; case GN_INDEX_BUFFER: usageFlags |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT; break; case GN_UNIFORM_BUFFER: usageFlags |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; break; + case GN_STORAGE_BUFFER: usageFlags |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; break; } return usageFlags; } @@ -114,6 +115,22 @@ void bufferData(gnBufferHandle buffer, size_t dataSize, void* data) { vkUnmapMemory(buffer->device->outputDevice->device, buffer->buffer->buffer.memory); } } +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); + } else { + vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->buffer.memory, 0, dataSize, 0, &bufferData); + memcpy(bufferData + offset, data, dataSize); + vkUnmapMemory(buffer->device->outputDevice->device, buffer->buffer->buffer.memory); + } +} void* mapBuffer(gnBufferHandle buffer) { void* data; vkMapMemory(buffer->device->outputDevice->device, buffer->buffer->buffer.memory, 0, buffer->info.size, 0, &data); diff --git a/projects/apis/vulkan/src/buffers/vulkan_buffer.h b/projects/apis/vulkan/src/buffers/vulkan_buffer.h index 8d5030b..98eb634 100644 --- a/projects/apis/vulkan/src/buffers/vulkan_buffer.h +++ b/projects/apis/vulkan/src/buffers/vulkan_buffer.h @@ -25,5 +25,6 @@ uint32_t VkMemoryIndex(VkPhysicalDevice device, uint32_t memoryType, VkMemoryPro gnReturnCode createBuffer(gnBufferHandle buffer, gnOutputDeviceHandle device, gnBufferInfo info); void bufferData(gnBufferHandle buffer, size_t dataSize, void* data); +void vulkanBufferSubData(gnBufferHandle buffer, size_t offset, size_t dataSize, void* data); void* mapBuffer(gnBufferHandle buffer); void destroyBuffer(gnBufferHandle buffer); diff --git a/projects/apis/vulkan/src/uniforms/vulkan_uniform.c b/projects/apis/vulkan/src/uniforms/vulkan_uniform.c index 4be168d..4e84bde 100644 --- a/projects/apis/vulkan/src/uniforms/vulkan_uniform.c +++ b/projects/apis/vulkan/src/uniforms/vulkan_uniform.c @@ -24,6 +24,26 @@ void updateBufferUniform(gnUniform uniform, gnBufferUniformInfo* info) { vkUpdateDescriptorSets(uniform->pool->device->outputDevice->device, 1, &write, 0, NULL); } +void updateVulkanStorageUniform(gnUniform uniform, gnStorageUniformInfo* info) { + VkDescriptorBufferInfo bufferInfo = { + .buffer = info->buffer->buffer->buffer.buffer, + .offset = info->offset, + .range = info->size + }; + + VkWriteDescriptorSet write = { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .descriptorCount = 1, + .pBufferInfo = &bufferInfo, + .dstSet = uniform->uniform->set, + .dstBinding = info->binding, + .dstArrayElement = 0 + }; + + vkUpdateDescriptorSets(uniform->pool->device->outputDevice->device, 1, &write, 0, NULL); +} + void updateImageUniform(gnUniform uniform, gnImageUniformInfo* info) { VkDescriptorImageInfo imageInfo = { .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, diff --git a/projects/apis/vulkan/src/uniforms/vulkan_uniform.h b/projects/apis/vulkan/src/uniforms/vulkan_uniform.h index 8e59a30..5f4fc2d 100644 --- a/projects/apis/vulkan/src/uniforms/vulkan_uniform.h +++ b/projects/apis/vulkan/src/uniforms/vulkan_uniform.h @@ -7,4 +7,5 @@ typedef struct gnPlatformUniform_t { } gnPlatformUniform; void updateBufferUniform(gnUniform uniform, gnBufferUniformInfo* info); +void updateVulkanStorageUniform(gnUniform uniform, gnStorageUniformInfo* info); void updateImageUniform(gnUniform uniform, gnImageUniformInfo* info); diff --git a/projects/apis/vulkan/src/uniforms/vulkan_uniform_pool.c b/projects/apis/vulkan/src/uniforms/vulkan_uniform_pool.c index 6217454..4f6a20d 100644 --- a/projects/apis/vulkan/src/uniforms/vulkan_uniform_pool.c +++ b/projects/apis/vulkan/src/uniforms/vulkan_uniform_pool.c @@ -50,26 +50,26 @@ gnUniform* allocateUniforms(gnUniformPool pool, gnUniformAllocationInfo allocInf }; // TODO: redo this, its not warning me IDK why cuz its totally wrong - VkDescriptorPoolSize poolSizes[GN_UNIFORM_TYPE_MAX]; - for (int i = 0; i < allocInfo.setCount; i++) { - for (int c = 0; c < allocInfo.sets[i].uniformBindingCount; c++) { + VkDescriptorPoolSize poolSizes[GN_UNIFORM_TYPE_MAX] = { }; + for (int i = 0; i < allocInfo.setCount; i++) + for (int c = 0; c < allocInfo.sets[i].uniformBindingCount; c++) poolSizes[allocInfo.sets[i].uniformBindings[c].type].descriptorCount++; - } - } uint32_t count = 0; - VkDescriptorPoolSize realPoolSize[GN_UNIFORM_TYPE_MAX] = {}; + VkDescriptorPoolSize realPoolSizes[GN_UNIFORM_TYPE_MAX] = {}; for (int i = 0; i < GN_UNIFORM_TYPE_MAX; i++) { - if (poolSizes[i].descriptorCount <= 0) continue; - realPoolSize[count] = poolSizes[i]; - count++; + poolSizes[i].type = vkGryphnUniformType(i); + if (poolSizes[i].descriptorCount > 0) { + realPoolSizes[count] = poolSizes[i]; + count++; + } } VkDescriptorPoolCreateInfo poolInfo = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, .poolSizeCount = count, - .pPoolSizes = realPoolSize, + .pPoolSizes = realPoolSizes, .maxSets = allocInfo.setCount }; diff --git a/projects/core/src/buffers/gryphn_buffer.c b/projects/core/src/buffers/gryphn_buffer.c index 4393787..d422a9e 100644 --- a/projects/core/src/buffers/gryphn_buffer.c +++ b/projects/core/src/buffers/gryphn_buffer.c @@ -11,6 +11,9 @@ gnReturnCode gnCreateBuffer(gnBufferHandle* buffer, gnOutputDeviceHandle device, void gnBufferData(gnBufferHandle buffer, size_t dataSize, void* data) { buffer->device->instance->callingLayer->deviceFunctions._gnBufferData(buffer, dataSize, data); } +void gnBufferSubData(gnBufferHandle buffer, size_t offset, size_t dataSize, gnBufferMemory data) { + buffer->device->instance->callingLayer->deviceFunctions._gnBufferSubData(buffer, offset, dataSize, data); +} void* gnMapBuffer(gnBufferHandle buffer) { if (buffer->info.usage == GN_STATIC_DRAW) return NULL; return buffer->device->instance->callingLayer->deviceFunctions._gnMapBuffer(buffer); diff --git a/projects/core/src/buffers/gryphn_buffer.h b/projects/core/src/buffers/gryphn_buffer.h index 5df6d90..8dcaeec 100644 --- a/projects/core/src/buffers/gryphn_buffer.h +++ b/projects/core/src/buffers/gryphn_buffer.h @@ -11,7 +11,8 @@ typedef enum gnIndexType { typedef enum gnBufferType { GN_VERTEX_BUFFER = 0x00000001, GN_INDEX_BUFFER = 0x00000002, - GN_UNIFORM_BUFFER = 0x00000004 + GN_UNIFORM_BUFFER = 0x00000004, + GN_STORAGE_BUFFER = 0x00000008 } gnBufferType; typedef enum gnBufferUsage { @@ -37,5 +38,6 @@ GN_ARRAY_LIST(gnBufferMemory); gnReturnCode gnCreateBuffer(gnBufferHandle* buffer, gnOutputDeviceHandle device, gnBufferInfo info); void gnBufferData(gnBufferHandle buffer, size_t dataSize, gnBufferMemory data); +void gnBufferSubData(gnBufferHandle buffer, size_t offset, size_t dataSize, gnBufferMemory data); gnBufferMemory gnMapBuffer(gnBufferHandle buffer); void gnDestroyBuffer(gnBufferHandle buffer); diff --git a/projects/core/src/uniforms/gryphn_uniform.c b/projects/core/src/uniforms/gryphn_uniform.c index b3563b2..e2c1c87 100644 --- a/projects/core/src/uniforms/gryphn_uniform.c +++ b/projects/core/src/uniforms/gryphn_uniform.c @@ -7,6 +7,10 @@ void gnUpdateBufferUniform(gnUniform uniform, gnBufferUniformInfo bufferInfo) { uniform->pool->device->instance->callingLayer->deviceFunctions._gnUpdateBufferUniform(uniform, &bufferInfo); } +void gnUpdateStorageUniform(gnUniform uniform, gnStorageUniformInfo storageInfo) { + uniform->pool->device->instance->callingLayer->deviceFunctions._gnUpdateStorageUniform(uniform, &storageInfo); +} + void gnUpdateImageUniform(gnUniform uniform, gnImageUniformInfo imageInfo) { uniform->pool->device->instance->callingLayer->deviceFunctions._gnUpdateImageUniform(uniform, &imageInfo); } diff --git a/projects/core/src/uniforms/gryphn_uniform.h b/projects/core/src/uniforms/gryphn_uniform.h index 0a132b8..e99bdb3 100644 --- a/projects/core/src/uniforms/gryphn_uniform.h +++ b/projects/core/src/uniforms/gryphn_uniform.h @@ -11,6 +11,12 @@ typedef struct gnBufferUniformInfo { size_t size; } gnBufferUniformInfo; +typedef struct gnStorageUniformInfo { + gnBuffer buffer; + size_t offset, size; + uint32_t binding; +} gnStorageUniformInfo; + typedef struct gnImageUniformInfo { uint32_t binding; gnTexture texture; @@ -22,7 +28,8 @@ struct gnUniform_t { gnUniformPool pool; }; #endif -GN_ARRAY_LIST(gnUniform) +GN_ARRAY_LIST(gnUniform); void gnUpdateBufferUniform(gnUniform uniform, gnBufferUniformInfo bufferInfo); +void gnUpdateStorageUniform(gnUniform uniform, gnStorageUniformInfo storageInfo); void gnUpdateImageUniform(gnUniform uniform, gnImageUniformInfo imageInfo); diff --git a/projects/core/src/uniforms/gryphn_uniform_layout.h b/projects/core/src/uniforms/gryphn_uniform_layout.h index f273afa..e12f0f8 100644 --- a/projects/core/src/uniforms/gryphn_uniform_layout.h +++ b/projects/core/src/uniforms/gryphn_uniform_layout.h @@ -4,8 +4,8 @@ typedef enum gnUniformType { GN_UNIFORM_BUFFER_DESCRIPTOR, - GN_SHADER_STORE_BUFFER_DESCRIPTOR, GN_IMAGE_DESCRIPTOR, + GN_SHADER_STORE_BUFFER_DESCRIPTOR, GN_UNIFORM_TYPE_MAX } gnUniformType; diff --git a/projects/loader/src/gryphn_device_functions.h b/projects/loader/src/gryphn_device_functions.h index be02188..235b1c6 100644 --- a/projects/loader/src/gryphn_device_functions.h +++ b/projects/loader/src/gryphn_device_functions.h @@ -13,6 +13,7 @@ typedef struct gnCommandPoolInfo gnCommandPoolInfo; typedef struct gnBufferInfo gnBufferInfo; typedef struct gnUniformAllocationInfo gnUniformAllocationInfo; typedef struct gnBufferUniformInfo gnBufferUniformInfo; +typedef struct gnStorageUniformInfo gnStorageUniformInfo; typedef struct gnImageUniformInfo gnImageUniformInfo; typedef struct gnTextureInfo gnTextureInfo; typedef struct gnSubmitInfo gnSubmitInfo; @@ -43,6 +44,7 @@ typedef struct gnDeviceFunctions { gnReturnCode (*_gnCreateBuffer)(gnBufferHandle buffer, gnDeviceHandle device, gnBufferInfo info); void (*_gnBufferData)(gnBufferHandle buffer, size_t size, void* data); + void (*_gnBufferSubData)(gnBufferHandle buffer, size_t offset, size_t dataSize, void* data); void* (*_gnMapBuffer)(gnBufferHandle buffer); void (*_gnDestroyBuffer)(gnBufferHandle buffer); @@ -51,6 +53,7 @@ typedef struct gnDeviceFunctions { void (*_gnDestroyUniformPool)(gnUniformPool pool); void (*_gnUpdateBufferUniform)(gnUniform uniform, gnBufferUniformInfo* bufferInfo); + void (*_gnUpdateStorageUniform)(gnUniform uniform, gnStorageUniformInfo* storageInfo); void (*_gnUpdateImageUniform)(gnUniform uniform, gnImageUniformInfo* imageInfo); gnReturnCode (*_gnCreateTexture)(gnTexture texture, gnDevice device, const gnTextureInfo info); diff --git a/projects/validation_layers/function_loader/loader/function_loader.c b/projects/validation_layers/function_loader/loader/function_loader.c index 3d0f199..c36956d 100644 --- a/projects/validation_layers/function_loader/loader/function_loader.c +++ b/projects/validation_layers/function_loader/loader/function_loader.c @@ -63,6 +63,7 @@ gnDeviceFunctions loadFunctionLoaderDeviceFunctions() { ._gnCreateBuffer = checkCreateBuffer, ._gnBufferData = checkBufferData, + ._gnBufferSubData = checkBufferSubData, ._gnMapBuffer = checkMapBuffer, ._gnDestroyBuffer = checkDestroyBuffer, @@ -71,6 +72,7 @@ gnDeviceFunctions loadFunctionLoaderDeviceFunctions() { ._gnDestroyUniformPool = checkDestroyUniformPool, ._gnUpdateBufferUniform = checkUpdateBufferUniform, + ._gnUpdateStorageUniform = checkUpdateStorageUniform, ._gnUpdateImageUniform = checkUpdateImageUniform, ._gnCreateTexture = checkCreateTexture, diff --git a/projects/validation_layers/function_loader/src/device_functions.c b/projects/validation_layers/function_loader/src/device_functions.c index e32360a..68ff59e 100644 --- a/projects/validation_layers/function_loader/src/device_functions.c +++ b/projects/validation_layers/function_loader/src/device_functions.c @@ -110,6 +110,9 @@ gnReturnCode checkCreateBuffer(gnBufferHandle buffer, gnDeviceHandle device, gnB void checkBufferData(gnBufferHandle buffer, size_t size, void* data) { CHECK_VOID_FUNCTION(buffer->device->instance, _gnBufferData, buffer, size, data); } +void checkBufferSubData(gnBufferHandle buffer, size_t offset, size_t size, void* data) { + CHECK_VOID_FUNCTION(buffer->device->instance, _gnBufferSubData, buffer, offset, size, data); +} void* checkMapBuffer(gnBufferHandle buffer) { loaderLayer* nextLayer = loaderGetNextLayer(buffer->device->instance); if (nextLayer->deviceFunctions._gnMapBuffer == NULL) { @@ -146,6 +149,9 @@ void checkDestroyUniformPool(gnUniformPool pool) { void checkUpdateBufferUniform(gnUniform uniform, gnBufferUniformInfo* bufferInfo) { CHECK_VOID_FUNCTION(uniform->pool->device->instance, _gnUpdateBufferUniform, uniform, bufferInfo); } +void checkUpdateStorageUniform(gnUniform uniform, gnStorageUniformInfo* storageInfo) { + CHECK_VOID_FUNCTION(uniform->pool->device->instance, _gnUpdateStorageUniform, uniform, storageInfo); +} void checkUpdateImageUniform(gnUniform uniform, gnImageUniformInfo* imageInfo) { CHECK_VOID_FUNCTION(uniform->pool->device->instance, _gnUpdateImageUniform, uniform, imageInfo); } diff --git a/projects/validation_layers/function_loader/src/device_functions.h b/projects/validation_layers/function_loader/src/device_functions.h index 89b0f8f..b086a42 100644 --- a/projects/validation_layers/function_loader/src/device_functions.h +++ b/projects/validation_layers/function_loader/src/device_functions.h @@ -24,6 +24,7 @@ void checkDestroySemaphore(gnSemaphoreHandle semaphore); gnReturnCode checkCreateBuffer(gnBufferHandle buffer, gnDeviceHandle device, gnBufferInfo info); void checkBufferData(gnBufferHandle buffer, size_t size, void* data); +void checkBufferSubData(gnBufferHandle buffer, size_t offset, size_t size, void* data); void* checkMapBuffer(gnBufferHandle buffer); void checkDestroyBuffer(gnBufferHandle buffer); @@ -32,6 +33,7 @@ gnUniform* checkUniformPoolAllocateUniforms(gnUniformPool pool, gnUniformAllocat void checkDestroyUniformPool(gnUniformPool pool); void checkUpdateBufferUniform(gnUniform uniform, gnBufferUniformInfo* bufferInfo); +void checkUpdateStorageUniform(gnUniform uniform, gnStorageUniformInfo* storageInfo); void checkUpdateImageUniform(gnUniform uniform, gnImageUniformInfo* imageInfo); gnReturnCode checkCreateTexture(gnTexture texture, gnDevice device, const gnTextureInfo info);