From cddd08f92f95d77efa596b2dd328ca1deb588c8d Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Wed, 27 Nov 2024 05:04:49 +0100 Subject: [PATCH] adding Vulkan's buffer creation --- Examples/Vulkan/main.c | 8 ++++ Includes/Pulse.h | 18 +++++--- README.md | 2 +- Sources/Backends/Vulkan/VulkanBuffer.c | 62 ++++++++++++++++++++++++++ Sources/Backends/Vulkan/VulkanBuffer.h | 29 ++++++++++++ Sources/Backends/Vulkan/VulkanDevice.c | 1 + Sources/PulseBuffer.c | 34 ++++++++++++++ Sources/PulseDefs.h | 2 + Sources/PulseInternal.h | 5 +++ Sources/PulsePFNs.h | 2 + 10 files changed, 155 insertions(+), 8 deletions(-) create mode 100644 Sources/Backends/Vulkan/VulkanBuffer.c create mode 100644 Sources/Backends/Vulkan/VulkanBuffer.h create mode 100644 Sources/PulseBuffer.c diff --git a/Examples/Vulkan/main.c b/Examples/Vulkan/main.c index e40f8fb..fa50cc5 100644 --- a/Examples/Vulkan/main.c +++ b/Examples/Vulkan/main.c @@ -44,6 +44,13 @@ int main(void) PulseComputePipeline pipeline = PulseCreateComputePipeline(device, &info); CHECK_PULSE_HANDLE_RETVAL(pipeline, 1); + PulseBufferCreateInfo buffer_create_info = {}; + buffer_create_info.size = 1024; + buffer_create_info.usage = PULSE_BUFFER_USAGE_STORAGE_READ | PULSE_BUFFER_USAGE_STORAGE_WRITE | PULSE_BUFFER_USAGE_TRANSFER_DOWNLOAD; + + PulseBuffer buffer = PulseCreateBuffer(device, &buffer_create_info); + CHECK_PULSE_HANDLE_RETVAL(buffer, 1); + PulseFence fence = PulseCreateFence(device); CHECK_PULSE_HANDLE_RETVAL(fence, 1); PulseCommandList cmd = PulseRequestCommandList(device, PULSE_COMMAND_LIST_GENERAL); @@ -58,6 +65,7 @@ int main(void) PulseReleaseCommandList(device, cmd); PulseDestroyFence(device, fence); + PulseDestroyBuffer(device, buffer); PulseDestroyComputePipeline(device, pipeline); PulseDestroyDevice(device); diff --git a/Includes/Pulse.h b/Includes/Pulse.h index 035cc8c..86f5582 100644 --- a/Includes/Pulse.h +++ b/Includes/Pulse.h @@ -43,10 +43,11 @@ typedef PulseFlags PulseBackendFlags; typedef enum PulseBufferUsageBits { - PULSE_BUFFER_USAGE_TRANSFER_UPLOAD = PULSE_BIT(1), - PULSE_BUFFER_USAGE_TRANSFER_DOWNLOAD = PULSE_BIT(2), - PULSE_BUFFER_USAGE_TRANSFER_STORAGE_READ = PULSE_BIT(3), - PULSE_BUFFER_USAGE_TRANSFER_STORAGE_WRITE = PULSE_BIT(4), + PULSE_BUFFER_USAGE_TRANSFER_UPLOAD = PULSE_BIT(1), + PULSE_BUFFER_USAGE_TRANSFER_DOWNLOAD = PULSE_BIT(2), + PULSE_BUFFER_USAGE_STORAGE_READ = PULSE_BIT(3), + PULSE_BUFFER_USAGE_STORAGE_WRITE = PULSE_BIT(4), + PULSE_BUFFER_USAGE_UNIFORM_ACCESS = PULSE_BIT(5), } PulseShaderFormatBits; typedef PulseFlags PulseBufferUsageFlags; @@ -58,9 +59,9 @@ typedef PulseFlags PulseBufferUsageFlags; */ typedef enum PulseImageUsageBits { - PULSE_IMAGE_USAGE_TRANSFER_STORAGE_READ = PULSE_BIT(1), - PULSE_IMAGE_USAGE_TRANSFER_STORAGE_WRITE = PULSE_BIT(2), - PULSE_IMAGE_USAGE_TRANSFER_STORAGE_SIMULTANEOUS_READWRITE = PULSE_BIT(3), + PULSE_IMAGE_USAGE_STORAGE_READ = PULSE_BIT(1), + PULSE_IMAGE_USAGE_STORAGE_WRITE = PULSE_BIT(2), + PULSE_IMAGE_USAGE_STORAGE_SIMULTANEOUS_READWRITE = PULSE_BIT(3), } PulseImageFormatBits; typedef PulseFlags PulseImageUsageFlags; @@ -268,6 +269,9 @@ PULSE_API void PulseDestroyDevice(PulseDevice device); PULSE_API PulseBackendBits PulseGetBackendInUseByDevice(PulseDevice device); PULSE_API bool PulseDeviceSupportsShaderFormats(PulseDevice device, PulseShaderFormatsFlags shader_formats_used); +PULSE_API PulseBuffer PulseCreateBuffer(PulseDevice device, const PulseBufferCreateInfo* create_infos); +PULSE_API void PulseDestroyBuffer(PulseDevice device, PulseBuffer buffer); + PULSE_API PulseCommandList PulseRequestCommandList(PulseDevice device, PulseCommandListUsage usage); PULSE_API bool PulseSubmitCommandList(PulseDevice device, PulseCommandList cmd, PulseFence fence); PULSE_API void PulseReleaseCommandList(PulseDevice device, PulseCommandList cmd); diff --git a/README.md b/README.md index a976173..3866d35 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # PulseGPU -Pulse is a low level GPGPU library designed for higly intensive general GPU computations with high control over the hardware. It is built on top of Vulkan, D3D11 and a Metal support is in discussion. +Pulse is a low level GPGPU library designed for highly intensive general GPU computations with high control over the hardware. It is built on top of Vulkan, D3D11 and a Metal support is in discussion. diff --git a/Sources/Backends/Vulkan/VulkanBuffer.c b/Sources/Backends/Vulkan/VulkanBuffer.c new file mode 100644 index 0000000..7453fd8 --- /dev/null +++ b/Sources/Backends/Vulkan/VulkanBuffer.c @@ -0,0 +1,62 @@ +// Copyright (C) 2024 kanel +// This file is part of "Pulse" +// For conditions of distribution and use, see copyright notice in LICENSE + +#include "Pulse.h" +#include "Vulkan.h" +#include "VulkanBuffer.h" +#include "VulkanDevice.h" + +PulseBuffer VulkanCreateBuffer(PulseDevice device, const PulseBufferCreateInfo* create_infos) +{ + VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(device, VulkanDevice*); + + PulseBufferHandler* buffer = (PulseBufferHandler*)calloc(1, sizeof(PulseBufferHandler)); + PULSE_CHECK_ALLOCATION_RETVAL(buffer, PULSE_NULL_HANDLE); + + VulkanBuffer* vulkan_buffer = (VulkanBuffer*)calloc(1, sizeof(VulkanBuffer)); + PULSE_CHECK_ALLOCATION_RETVAL(vulkan_buffer, PULSE_NULL_HANDLE); + + buffer->device = device; + buffer->driver_data = vulkan_buffer; + buffer->size = create_infos->size; + buffer->usage = create_infos->usage; + + if(buffer->usage & PULSE_BUFFER_USAGE_TRANSFER_UPLOAD) + { + vulkan_buffer->usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + } + if(buffer->usage & PULSE_BUFFER_USAGE_TRANSFER_DOWNLOAD) + { + vulkan_buffer->usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; + } + if(buffer->usage & PULSE_BUFFER_USAGE_STORAGE_READ || buffer->usage & PULSE_BUFFER_USAGE_STORAGE_WRITE) + { + vulkan_buffer->usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + } + if(buffer->usage & PULSE_BUFFER_USAGE_UNIFORM_ACCESS) + { + vulkan_buffer->usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; + } + + VmaAllocationCreateInfo allocation_create_info = { 0 }; + allocation_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; + allocation_create_info.usage = VMA_MEMORY_USAGE_AUTO; + + VkBufferCreateInfo buffer_create_info = { 0 }; + buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_create_info.size = buffer->size; + buffer_create_info.usage = vulkan_buffer->usage; + buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + CHECK_VK_RETVAL(device->backend, vmaCreateBuffer(vulkan_device->allocator, &buffer_create_info, &allocation_create_info, &vulkan_buffer->buffer, &vulkan_buffer->allocation, PULSE_NULLPTR), PULSE_ERROR_INITIALIZATION_FAILED, PULSE_NULL_HANDLE); + + return buffer; +} + +void VulkanDestroyBuffer(PulseDevice device, PulseBuffer buffer) +{ + VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(device, VulkanDevice*); + VulkanBuffer* vulkan_buffer = VULKAN_RETRIEVE_DRIVER_DATA_AS(buffer, VulkanBuffer*); + vmaDestroyBuffer(vulkan_device->allocator, vulkan_buffer->buffer, vulkan_buffer->allocation); +} diff --git a/Sources/Backends/Vulkan/VulkanBuffer.h b/Sources/Backends/Vulkan/VulkanBuffer.h new file mode 100644 index 0000000..a72dfdc --- /dev/null +++ b/Sources/Backends/Vulkan/VulkanBuffer.h @@ -0,0 +1,29 @@ +// Copyright (C) 2024 kanel +// This file is part of "Pulse" +// For conditions of distribution and use, see copyright notice in LICENSE + +#ifdef PULSE_ENABLE_VULKAN_BACKEND + +#ifndef PULSE_VULKAN_BUFFER_H_ +#define PULSE_VULKAN_BUFFER_H_ + +#include +#include + +#include +#include "../../PulseInternal.h" +#include "VulkanEnums.h" + +typedef struct VulkanBuffer +{ + VkBuffer buffer; + VkBufferUsageFlags usage; + VmaAllocation allocation; +} VulkanBuffer; + +PulseBuffer VulkanCreateBuffer(PulseDevice device, const PulseBufferCreateInfo* create_infos); +void VulkanDestroyBuffer(PulseDevice device, PulseBuffer buffer); + +#endif // PULSE_VULKAN_BUFFER_H_ + +#endif // PULSE_ENABLE_VULKAN_BACKEND diff --git a/Sources/Backends/Vulkan/VulkanDevice.c b/Sources/Backends/Vulkan/VulkanDevice.c index e0181ca..d806f8b 100644 --- a/Sources/Backends/Vulkan/VulkanDevice.c +++ b/Sources/Backends/Vulkan/VulkanDevice.c @@ -11,6 +11,7 @@ #include "VulkanInstance.h" #include "VulkanLoader.h" #include "VulkanQueue.h" +#include "VulkanBuffer.h" #include "../../PulseInternal.h" #include diff --git a/Sources/PulseBuffer.c b/Sources/PulseBuffer.c new file mode 100644 index 0000000..3750b9d --- /dev/null +++ b/Sources/PulseBuffer.c @@ -0,0 +1,34 @@ +// Copyright (C) 2024 kanel +// This file is part of "Pulse" +// For conditions of distribution and use, see copyright notice in LICENSE + +#include "Pulse.h" +#include "PulseInternal.h" + +PULSE_API PulseBuffer PulseCreateBuffer(PulseDevice device, const PulseBufferCreateInfo* create_infos) +{ + PULSE_CHECK_HANDLE_RETVAL(device, PULSE_NULL_HANDLE); + if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend)) + { + if(create_infos == PULSE_NULLPTR) + { + PulseLogError(device->backend, "create_infos is NULL"); + PulseSetInternalError(PULSE_ERROR_INITIALIZATION_FAILED); + return PULSE_NULL_HANDLE; + } + } + return device->PFN_CreateBuffer(device, create_infos); +} + +PULSE_API void PulseDestroyBuffer(PulseDevice device, PulseBuffer buffer) +{ + PULSE_CHECK_HANDLE(device); + + if(buffer == PULSE_NULL_HANDLE) + { + if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend)) + PulseLogWarning(device->backend, "buffer is NULL, this may be a bug in your application"); + return; + } + return device->PFN_DestroyBuffer(device, buffer); +} diff --git a/Sources/PulseDefs.h b/Sources/PulseDefs.h index c6ae67e..1d4a554 100644 --- a/Sources/PulseDefs.h +++ b/Sources/PulseDefs.h @@ -62,5 +62,7 @@ PULSE_LOAD_DRIVER_DEVICE_FUNCTION(RequestCommandList, _namespace) \ PULSE_LOAD_DRIVER_DEVICE_FUNCTION(SubmitCommandList, _namespace) \ PULSE_LOAD_DRIVER_DEVICE_FUNCTION(ReleaseCommandList, _namespace) \ + PULSE_LOAD_DRIVER_DEVICE_FUNCTION(CreateBuffer, _namespace) \ + PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyBuffer, _namespace) \ #endif // PULSE_DEFS_H_ diff --git a/Sources/PulseInternal.h b/Sources/PulseInternal.h index 1d77bf9..89a1e3c 100644 --- a/Sources/PulseInternal.h +++ b/Sources/PulseInternal.h @@ -30,7 +30,10 @@ typedef struct PulseBackendHandler typedef struct PulseBufferHandler { + PulseDevice device; void* driver_data; + PulseBufferUsageFlags usage; + PulseDeviceSize size; } PulseBufferHandler; typedef struct PulseCommandListHandler @@ -66,6 +69,8 @@ typedef struct PulseDeviceHandler PulseRequestCommandListPFN PFN_RequestCommandList; PulseSubmitCommandListPFN PFN_SubmitCommandList; PulseReleaseCommandListPFN PFN_ReleaseCommandList; + PulseCreateBufferPFN PFN_CreateBuffer; + PulseDestroyBufferPFN PFN_DestroyBuffer; // Attributes void* driver_data; diff --git a/Sources/PulsePFNs.h b/Sources/PulsePFNs.h index fe72536..cfa97a0 100644 --- a/Sources/PulsePFNs.h +++ b/Sources/PulsePFNs.h @@ -24,5 +24,7 @@ typedef bool (*PulseWaitForFencesPFN)(PulseDevice, const PulseFence*, uint32_t, typedef PulseCommandList (*PulseRequestCommandListPFN)(PulseDevice, PulseCommandListUsage); typedef bool (*PulseSubmitCommandListPFN)(PulseDevice, PulseCommandList, PulseFence); typedef void (*PulseReleaseCommandListPFN)(PulseDevice, PulseCommandList); +typedef PulseBuffer (*PulseCreateBufferPFN)(PulseDevice, const PulseBufferCreateInfo*); +typedef void (*PulseDestroyBufferPFN)(PulseDevice, PulseBuffer); #endif // PULSE_PFNS_H_