working on vulkan descriptor sets

This commit is contained in:
2025-01-26 00:35:06 +01:00
parent 14b9b28bf9
commit 6a40074c08
23 changed files with 518 additions and 114 deletions

View File

@@ -56,7 +56,12 @@ int main(void)
PulseCommandList cmd = PulseRequestCommandList(device, PULSE_COMMAND_LIST_GENERAL);
CHECK_PULSE_HANDLE_RETVAL(cmd, 1);
PulseDispatchComputePipeline(pipeline, cmd, 8, 8, 8);
PulseComputePass pass = PulseBeginComputePass(cmd);
CHECK_PULSE_HANDLE_RETVAL(pass, 1);
PulseBindStorageBuffers(pass, 0, &buffer, 1);
PulseBindComputePipeline(pass, pipeline);
PulseDispatchComputations(pass, 8, 8, 8);
PulseEndComputePass(pass);
if(!PulseSubmitCommandList(device, cmd, fence))
fprintf(stderr, "Could not submit command list, %s\n", PulseVerbaliseErrorType(PulseGetLastErrorType()));

View File

@@ -29,14 +29,15 @@ PULSE_DEFINE_NULLABLE_HANDLE(PulseComputePipeline);
PULSE_DEFINE_NULLABLE_HANDLE(PulseDevice);
PULSE_DEFINE_NULLABLE_HANDLE(PulseFence);
PULSE_DEFINE_NULLABLE_HANDLE(PulseImage);
PULSE_DEFINE_NULLABLE_HANDLE(PulseComputePass);
// Flags
typedef enum PulseBackendBits
{
PULSE_BACKEND_INVALID = PULSE_BIT(1),
PULSE_BACKEND_ANY = PULSE_BIT(2),
PULSE_BACKEND_VULKAN = PULSE_BIT(3),
PULSE_BACKEND_METAL = PULSE_BIT(4),
PULSE_BACKEND_ANY = PULSE_BIT(2),
PULSE_BACKEND_VULKAN = PULSE_BIT(3),
PULSE_BACKEND_METAL = PULSE_BIT(4),
// More to come
} PulseBackendBits;
typedef PulseFlags PulseBackendFlags;
@@ -47,7 +48,6 @@ typedef enum PulseBufferUsageBits
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;
@@ -67,9 +67,9 @@ typedef PulseFlags PulseImageUsageFlags;
typedef enum PulseShaderFormatsBits
{
PULSE_SHADER_FORMAT_SPIRV_BIT = PULSE_BIT(1), // Can be used by Vulkan
PULSE_SHADER_FORMAT_MSL_BIT = PULSE_BIT(2), // Can be used by Metal
PULSE_SHADER_FORMAT_METALLIB_BIT = PULSE_BIT(3), // Can be used by Metal
PULSE_SHADER_FORMAT_SPIRV_BIT = PULSE_BIT(1), // Can be used by Vulkan
PULSE_SHADER_FORMAT_MSL_BIT = PULSE_BIT(2), // Can be used by Metal
PULSE_SHADER_FORMAT_METALLIB_BIT = PULSE_BIT(3), // Can be used by Metal
// More to come
} PulseShaderFormatsBits;
typedef PulseFlags PulseShaderFormatsFlags;
@@ -133,7 +133,7 @@ typedef enum PulseImageFormat
PULSE_IMAGE_FORMAT_R16G16_UNORM,
PULSE_IMAGE_FORMAT_R16G16B16A16_UNORM,
PULSE_IMAGE_FORMAT_R10G10B10A2_UNORM,
PULSE_IMAGE_FORMAT_B5G6R5_UNORM,
PULSE_IMAGE_FORMAT_B5G6R5_UNORM,
PULSE_IMAGE_FORMAT_B5G5R5A1_UNORM,
PULSE_IMAGE_FORMAT_B4G4R4A4_UNORM,
PULSE_IMAGE_FORMAT_B8G8R8A8_UNORM,
@@ -184,14 +184,6 @@ typedef enum PulseImageFormat
PULSE_IMAGE_FORMAT_R32_INT,
PULSE_IMAGE_FORMAT_R32G32_INT,
PULSE_IMAGE_FORMAT_R32G32B32A32_INT,
// SRGB Unsigned Normalized Color Formats
PULSE_IMAGE_FORMAT_R8G8B8A8_UNORM_SRGB,
PULSE_IMAGE_FORMAT_B8G8R8A8_UNORM_SRGB,
// Compressed SRGB Unsigned Normalized Color Formats
PULSE_IMAGE_FORMAT_BC1_RGBA_UNORM_SRGB,
PULSE_IMAGE_FORMAT_BC2_RGBA_UNORM_SRGB,
PULSE_IMAGE_FORMAT_BC3_RGBA_UNORM_SRGB,
PULSE_IMAGE_FORMAT_BC7_RGBA_UNORM_SRGB,
PULSE_IMAGE_FORMAT_MAX_ENUM // For internal use only
} PulseImageFormat;
@@ -283,9 +275,16 @@ PULSE_API bool PulseIsFenceReady(PulseDevice device, PulseFence fence);
PULSE_API bool PulseWaitForFences(PulseDevice device, const PulseFence* fences, uint32_t fences_count, bool wait_for_all);
PULSE_API PulseComputePipeline PulseCreateComputePipeline(PulseDevice device, const PulseComputePipelineCreateInfo* info);
PULSE_API void PulseDispatchComputePipeline(PulseComputePipeline pipeline, PulseCommandList cmd, uint32_t groupcount_x, uint32_t groupcount_y, uint32_t groupcount_z);
PULSE_API void PulseDestroyComputePipeline(PulseDevice device, PulseComputePipeline pipeline);
PULSE_API PulseComputePass PulseBeginComputePass(PulseCommandList cmd);
PULSE_API void PulseBindStorageBuffers(PulseComputePass pass, uint32_t starting_slot, PulseBuffer* const* buffers, uint32_t num_buffers);
PULSE_API void PulseBindUniformData(PulseComputePass pass, uint32_t slot, const void* data, uint32_t data_size);
PULSE_API void PulseBindStorageImages(PulseComputePass pass, uint32_t starting_slot, PulseImage* const* images, uint32_t num_images);
PULSE_API void PulseBindComputePipeline(PulseComputePass pass, PulseComputePipeline pipeline);
PULSE_API void PulseDispatchComputations(PulseComputePass pass, uint32_t groupcount_x, uint32_t groupcount_y, uint32_t groupcount_z);
PULSE_API void PulseEndComputePass(PulseComputePass pass);
PULSE_API PulseErrorType PulseGetLastErrorType(); // Call to this function resets the internal last error variable
PULSE_API const char* PulseVerbaliseErrorType(PulseErrorType error);

View File

@@ -37,7 +37,7 @@ PulseBuffer VulkanCreateBuffer(PulseDevice device, const PulseBufferCreateInfo*
vulkan_buffer->usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
allocation_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
}
if(buffer->usage & PULSE_BUFFER_USAGE_UNIFORM_ACCESS)
if(buffer->usage & PULSE_INTERNAL_BUFFER_USAGE_UNIFORM_ACCESS)
{
vulkan_buffer->usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
allocation_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;

View File

@@ -26,16 +26,31 @@ static void VulkanInitCommandList(VulkanCommandPool* pool, PulseCommandList cmd)
info.commandBufferCount = 1;
CHECK_VK(pool->device->backend, vulkan_device->vkAllocateCommandBuffers(vulkan_device->device, &info, &vulkan_cmd->cmd), PULSE_ERROR_INITIALIZATION_FAILED);
if(pool->available_command_lists_size == pool->available_command_lists_capacity)
{
pool->available_command_lists_capacity += 5;
pool->available_command_lists = (PulseCommandList*)realloc(pool->available_command_lists, pool->available_command_lists_capacity * sizeof(PulseCommandList));
PULSE_CHECK_ALLOCATION(pool->available_command_lists);
}
PULSE_EXPAND_ARRAY_IF_NEEDED(pool->available_command_lists, PulseCommandList, pool->available_command_lists_size, pool->available_command_lists_capacity, 5);
pool->available_command_lists[pool->available_command_lists_size] = cmd;
pool->available_command_lists_size++;
}
PulseComputePass VulkanCreateComputePass(PulseDevice device, PulseCommandList cmd)
{
PulseComputePass pass = (PulseComputePass)calloc(1, sizeof(PulseComputePassHandler));
PULSE_CHECK_ALLOCATION_RETVAL(pass, PULSE_NULL_HANDLE);
VulkanComputePass* vulkan_pass = (VulkanComputePass*)calloc(1, sizeof(VulkanComputePass));
PULSE_CHECK_ALLOCATION_RETVAL(vulkan_pass, PULSE_NULL_HANDLE);
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(device, VulkanDevice*);
// vulkan_pass->read_only_descriptor_set = VulkanRequestDescriptorSetFromPool(
// VulkanGetAvailableDescriptorSetPool(&vulkan_device->descriptor_set_pool_manager),
// VulkanGetDescriptorSetLayout(&vulkan_device->descriptor_set_layout_manager, ));
pass->cmd = cmd;
pass->driver_data = vulkan_pass;
return pass;
}
PulseCommandList VulkanRequestCommandList(PulseDevice device, PulseCommandListUsage usage)
{
PULSE_CHECK_HANDLE_RETVAL(device, PULSE_NULL_HANDLE);
@@ -77,7 +92,7 @@ PulseCommandList VulkanRequestCommandList(PulseDevice device, PulseCommandListUs
VulkanInitCommandList(pool, cmd);
}
cmd->compute_pipelines_bound_size = 0;
cmd->pass = VulkanCreateComputePass(device, cmd);
cmd->state = PULSE_COMMAND_LIST_STATE_RECORDING;
cmd->is_available = false;
@@ -169,3 +184,12 @@ void VulkanReleaseCommandList(PulseDevice device, PulseCommandList cmd)
}
}
}
PulseComputePass VulkanBeginComputePass(PulseCommandList cmd)
{
return cmd->pass;
}
void VulkanEndComputePass(PulseComputePass pass)
{
}

View File

@@ -10,7 +10,9 @@
#include <vulkan/vulkan_core.h>
#include <Pulse.h>
#include "VulkanBuffer.h"
#include "VulkanCommandPool.h"
#include "VulkanDescriptor.h"
typedef struct VulkanCommandList
{
@@ -18,9 +20,19 @@ typedef struct VulkanCommandList
VkCommandBuffer cmd;
} VulkanCommandList;
typedef struct VulkanComputePass
{
VulkanDescriptorSet* read_only_descriptor_set;
VulkanDescriptorSet* read_write_descriptor_set;
VulkanDescriptorSet* uniform_descriptor_set;
PulseBuffer uniform_buffer;
} VulkanComputePass;
PulseCommandList VulkanRequestCommandList(PulseDevice device, PulseCommandListUsage usage);
bool VulkanSubmitCommandList(PulseDevice device, PulseCommandList cmd, PulseFence fence);
void VulkanReleaseCommandList(PulseDevice device, PulseCommandList cmd);
PulseComputePass VulkanBeginComputePass(PulseCommandList cmd);
void VulkanEndComputePass(PulseComputePass pass);
#endif // PULSE_VULKAN_COMMAND_LIST_H_

View File

@@ -60,16 +60,6 @@ PulseComputePipeline VulkanCreateComputePipeline(PulseDevice device, const Pulse
return pipeline;
}
void VulkanDispatchComputePipeline(PulseComputePipeline pipeline, PulseCommandList cmd, uint32_t groupcount_x, uint32_t groupcount_y, uint32_t groupcount_z)
{
VulkanComputePipeline* vulkan_pipeline = VULKAN_RETRIEVE_DRIVER_DATA_AS(pipeline, VulkanComputePipeline*);
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(cmd->device, VulkanDevice*);
VulkanCommandList* vulkan_cmd = VULKAN_RETRIEVE_DRIVER_DATA_AS(cmd, VulkanCommandList*);
vulkan_device->vkCmdBindPipeline(vulkan_cmd->cmd, VK_PIPELINE_BIND_POINT_COMPUTE, vulkan_pipeline->pipeline);
vulkan_device->vkCmdDispatch(vulkan_cmd->cmd, groupcount_x, groupcount_y, groupcount_z);
}
void VulkanDestroyComputePipeline(PulseDevice device, PulseComputePipeline pipeline)
{
if(pipeline == PULSE_NULL_HANDLE)
@@ -91,3 +81,32 @@ void VulkanDestroyComputePipeline(PulseDevice device, PulseComputePipeline pipel
if(PULSE_IS_BACKEND_HIGH_LEVEL_DEBUG(device->backend))
PulseLogInfoFmt(device->backend, "(Vulkan) destroyed compute pipeline %p", pipeline);
}
void VulkanBindStorageBuffers(PulseComputePass pass, uint32_t starting_slot, PulseBuffer* const* buffers, uint32_t num_buffers)
{
}
void VulkanBindUniformData(PulseComputePass pass, uint32_t slot, const void* data, uint32_t data_size)
{
}
void VulkanBindStorageImages(PulseComputePass pass, uint32_t starting_slot, PulseImage* const* images, uint32_t num_images)
{
}
void VulkanBindComputePipeline(PulseComputePass pass, PulseComputePipeline pipeline)
{
VulkanComputePipeline* vulkan_pipeline = VULKAN_RETRIEVE_DRIVER_DATA_AS(pipeline, VulkanComputePipeline*);
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(pass->cmd->device, VulkanDevice*);
VulkanCommandList* vulkan_cmd = VULKAN_RETRIEVE_DRIVER_DATA_AS(pass->cmd, VulkanCommandList*);
vulkan_device->vkCmdBindPipeline(vulkan_cmd->cmd, VK_PIPELINE_BIND_POINT_COMPUTE, vulkan_pipeline->pipeline);
}
void VulkanDispatchComputations(PulseComputePass pass, uint32_t groupcount_x, uint32_t groupcount_y, uint32_t groupcount_z)
{
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(pass->cmd->device, VulkanDevice*);
VulkanCommandList* vulkan_cmd = VULKAN_RETRIEVE_DRIVER_DATA_AS(pass->cmd, VulkanCommandList*);
vulkan_device->vkCmdDispatch(vulkan_cmd->cmd, groupcount_x, groupcount_y, groupcount_z);
}

View File

@@ -19,8 +19,12 @@ typedef struct VulkanComputePipeline
} VulkanComputePipeline;
PulseComputePipeline VulkanCreateComputePipeline(PulseDevice device, const PulseComputePipelineCreateInfo* info);
void VulkanDispatchComputePipeline(PulseComputePipeline pipeline, PulseCommandList cmd, uint32_t groupcount_x, uint32_t groupcount_y, uint32_t groupcount_z);
void VulkanDestroyComputePipeline(PulseDevice device, PulseComputePipeline pipeline);
void VulkanBindStorageBuffers(PulseComputePass pass, uint32_t starting_slot, PulseBuffer* const* buffers, uint32_t num_buffers);
void VulkanBindUniformData(PulseComputePass pass, uint32_t slot, const void* data, uint32_t data_size);
void VulkanBindStorageImages(PulseComputePass pass, uint32_t starting_slot, PulseImage* const* images, uint32_t num_images);
void VulkanBindComputePipeline(PulseComputePass pass, PulseComputePipeline pipeline);
void VulkanDispatchComputations(PulseComputePass pass, uint32_t groupcount_x, uint32_t groupcount_y, uint32_t groupcount_z);
#endif // PULSE_VULKAN_COMPUTE_PIPELINE_H_

View File

@@ -10,28 +10,145 @@
#include "VulkanDevice.h"
#include "VulkanDescriptor.h"
#undef NDEBUG
#include <assert.h>
void VulkanInitDescriptorSetLayoutManager(VulkanDescriptorSetLayoutManager* manager, PulseDevice device)
{
memset(manager, 0, sizeof(VulkanDescriptorSetLayoutManager));
manager->device = device;
}
VulkanDescriptorSetLayout* VulkanGetDescriptorSetLayout(VulkanDescriptorSetLayoutManager* manager,
uint32_t read_storage_buffers_count,
uint32_t read_storage_images_count,
uint32_t write_storage_buffers_count,
uint32_t write_storage_images_count,
uint32_t uniform_buffers_count)
{
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(manager->device, VulkanDevice*);
for(uint32_t i = 0; i < manager->layouts_size; i++)
{
VulkanDescriptorSetLayout* layout = &manager->layouts[i];
if( layout->ReadOnly.storage_buffer_count == read_storage_buffers_count &&
layout->ReadOnly.storage_texture_count == read_storage_images_count &&
layout->ReadWrite.storage_buffer_count == write_storage_buffers_count &&
layout->ReadWrite.storage_texture_count == write_storage_images_count &&
layout->Uniform.buffer_count == uniform_buffers_count)
{
return layout;
}
}
PULSE_EXPAND_ARRAY_IF_NEEDED(manager->layouts, VulkanDescriptorSetLayout, manager->layouts_size, manager->layouts_capacity, 1);
PULSE_CHECK_ALLOCATION_RETVAL(manager->layouts, PULSE_NULLPTR);
VulkanDescriptorSetLayout* layout = &manager->layouts[manager->layouts_size];
VkDescriptorSetLayoutBinding* bindings = (VkDescriptorSetLayoutBinding*)PulseStaticAllocStack(PULSE_MAX_READ_BUFFERS_BOUND + PULSE_MAX_READ_TEXTURES_BOUND + PULSE_MAX_WRITE_BUFFERS_BOUND + PULSE_MAX_WRITE_TEXTURES_BOUND + PULSE_MAX_UNIFORM_BUFFERS_BOUND);
// Category 1
for(uint32_t i = 0; i < read_storage_images_count; i++)
{
bindings[i].binding = i;
bindings[i].descriptorCount = 1;
bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
bindings[i].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
bindings[i].pImmutableSamplers = PULSE_NULLPTR;
}
for(uint32_t i = read_storage_images_count; i < read_storage_images_count + read_storage_buffers_count; i++)
{
bindings[i].binding = i;
bindings[i].descriptorCount = 1;
bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
bindings[i].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
bindings[i].pImmutableSamplers = PULSE_NULLPTR;
}
// Category 2
for(uint32_t i = 0; i < write_storage_images_count; i++) {
bindings[i].binding = i;
bindings[i].descriptorCount = 1;
bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
bindings[i].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
bindings[i].pImmutableSamplers = PULSE_NULLPTR;
}
for(uint32_t i = write_storage_images_count; i < write_storage_images_count + write_storage_buffers_count; i++)
{
bindings[i].binding = i;
bindings[i].descriptorCount = 1;
bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
bindings[i].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
bindings[i].pImmutableSamplers = PULSE_NULLPTR;
}
// Category 3
for(uint32_t i = 0; i < uniform_buffers_count; i++)
{
bindings[i].binding = i;
bindings[i].descriptorCount = 1;
bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
bindings[i].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
bindings[i].pImmutableSamplers = PULSE_NULLPTR;
}
VkDescriptorSetLayoutCreateInfo layout_info = { 0 };
layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layout_info.bindingCount = read_storage_buffers_count + read_storage_images_count + write_storage_buffers_count + write_storage_images_count + uniform_buffers_count;
layout_info.pBindings = bindings;
CHECK_VK_RETVAL(manager->device->backend, vulkan_device->vkCreateDescriptorSetLayout(vulkan_device->device, &layout_info, PULSE_NULLPTR, &layout->layout), PULSE_ERROR_INITIALIZATION_FAILED, PULSE_NULLPTR);
layout->ReadOnly.storage_buffer_count = read_storage_buffers_count;
layout->ReadOnly.storage_texture_count = read_storage_images_count;
layout->ReadWrite.storage_buffer_count = write_storage_buffers_count;
layout->ReadWrite.storage_texture_count = write_storage_images_count;
layout->Uniform.buffer_count = uniform_buffers_count;
return layout;
}
void VulkanDestroyDescriptorSetLayout(VulkanDescriptorSetLayout* layout, PulseDevice device)
{
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(device, VulkanDevice*);
vulkan_device->vkDestroyDescriptorSetLayout(vulkan_device->device, layout->layout, PULSE_NULLPTR);
}
void VulkanDestroyDescriptorSetLayoutManager(VulkanDescriptorSetLayoutManager* manager)
{
for(uint32_t i = 0; i < manager->layouts_size; i++)
{
VulkanDestroyDescriptorSetLayout(&manager->layouts[i], manager->device);
}
free(manager->layouts);
memset(manager, 0, sizeof(VulkanDescriptorSetPoolManager));
}
void VulkanInitDescriptorSetPool(VulkanDescriptorSetPool* pool, PulseDevice device)
{
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(device, VulkanDevice*);
memset(pool, 0, sizeof(VulkanDescriptorSetPool));
pool->device = device;
pool->thread_id = PulseGetThreadID();
VkDescriptorPoolSize pool_sizes[
PULSE_MAX_STORAGE_TEXTURES_BOUND +
PULSE_MAX_STORAGE_BUFFERS_BOUND +
PULSE_MAX_READ_TEXTURES_BOUND +
PULSE_MAX_READ_BUFFERS_BOUND +
PULSE_MAX_WRITE_TEXTURES_BOUND +
PULSE_MAX_WRITE_BUFFERS_BOUND +
PULSE_MAX_UNIFORM_BUFFERS_BOUND];
uint32_t i = 0;
for(uint32_t start = i; i < start + PULSE_MAX_STORAGE_TEXTURES_BOUND; i++)
for(uint32_t start = i; i < start + PULSE_MAX_READ_TEXTURES_BOUND; i++)
{
pool_sizes[i].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
pool_sizes[i].descriptorCount = VULKAN_POOL_SIZE;
}
for(uint32_t start = i; i < start + PULSE_MAX_STORAGE_BUFFERS_BOUND; i++)
for(uint32_t start = i; i < start + PULSE_MAX_READ_BUFFERS_BOUND; i++)
{
pool_sizes[i].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
pool_sizes[i].descriptorCount = VULKAN_POOL_SIZE;
@@ -146,7 +263,6 @@ void VulkanDestroyDescriptorSetPool(VulkanDescriptorSetPool* pool)
memset(pool, 0, sizeof(VulkanDescriptorSetPool));
}
void VulkanInitDescriptorSetPoolManager(VulkanDescriptorSetPoolManager* manager, PulseDevice device)
{
memset(manager, 0, sizeof(VulkanDescriptorSetPoolManager));
@@ -155,9 +271,10 @@ void VulkanInitDescriptorSetPoolManager(VulkanDescriptorSetPoolManager* manager,
VulkanDescriptorSetPool* VulkanGetAvailableDescriptorSetPool(VulkanDescriptorSetPoolManager* manager)
{
PulseThreadID thread_id = PulseGetThreadID();
for(uint32_t i = 0; i < manager->pools_size; i++)
{
if(manager->pools[i]->allocations_count < VULKAN_POOL_SIZE || manager->pools[i]->free_sets[0] != PULSE_NULLPTR)
if(thread_id == manager->pools[i]->thread_id && (manager->pools[i]->allocations_count < VULKAN_POOL_SIZE || manager->pools[i]->free_sets[0] != PULSE_NULLPTR))
return manager->pools[i];
}
PULSE_EXPAND_ARRAY_IF_NEEDED(manager->pools, VulkanDescriptorSetPool*, manager->pools_size, manager->pools_capacity, 1);

View File

@@ -10,6 +10,7 @@
#include <vulkan/vulkan_core.h>
#include <Pulse.h>
#include "../../PulseInternal.h"
#include "VulkanEnums.h"
@@ -18,7 +19,6 @@
typedef struct VulkanDescriptorSetLayout
{
VkDescriptorSetLayout layout;
VulkanDescriptorSetType type;
union
{
@@ -55,6 +55,7 @@ typedef struct VulkanDescriptorSetPool
uint32_t free_index;
PulseDevice device;
VkDescriptorPool pool;
PulseThreadID thread_id;
uint32_t allocations_count;
} VulkanDescriptorSetPool;
@@ -66,10 +67,25 @@ typedef struct VulkanDescriptorSetPoolManager
uint32_t pools_size;
} VulkanDescriptorSetPoolManager;
void VulkanInitDescriptorSetPool(VulkanDescriptorSetPool* pool, PulseDevice device);
typedef struct VulkanDescriptorSetLayoutManager
{
PulseDevice device;
VulkanDescriptorSetLayout* layouts;
uint32_t layouts_capacity;
uint32_t layouts_size;
} VulkanDescriptorSetLayoutManager;
void VulkanInitDescriptorSetLayoutManager(VulkanDescriptorSetLayoutManager* manager, PulseDevice device);
VulkanDescriptorSetLayout* VulkanGetDescriptorSetLayout(VulkanDescriptorSetLayoutManager* manager,
uint32_t read_storage_buffers_count,
uint32_t read_storage_images_count,
uint32_t write_storage_buffers_count,
uint32_t write_storage_images_count,
uint32_t uniform_buffers_count);
void VulkanDestroyDescriptorSetLayoutManager(VulkanDescriptorSetLayoutManager* manager);
VulkanDescriptorSet* VulkanRequestDescriptorSetFromPool(VulkanDescriptorSetPool* pool, const VulkanDescriptorSetLayout* layout);
void VulkanReturnDescriptorSetToPool(VulkanDescriptorSetPool* pool, const VulkanDescriptorSet* set);
void VulkanDestroyDescriptorSetPool(VulkanDescriptorSetPool* pool);
void VulkanInitDescriptorSetPoolManager(VulkanDescriptorSetPoolManager* manager, PulseDevice device);
VulkanDescriptorSetPool* VulkanGetAvailableDescriptorSetPool(VulkanDescriptorSetPoolManager* manager);

View File

@@ -228,6 +228,9 @@ PulseDevice VulkanCreateDevice(PulseBackend backend, PulseDevice* forbiden_devic
pulse_device->backend = backend;
PULSE_LOAD_DRIVER_DEVICE(Vulkan);
VulkanInitDescriptorSetPoolManager(&device->descriptor_set_pool_manager, pulse_device);
VulkanInitDescriptorSetLayoutManager(&device->descriptor_set_layout_manager, pulse_device);
if(PULSE_IS_BACKEND_HIGH_LEVEL_DEBUG(backend))
PulseLogInfoFmt(backend, "(Vulkan) created device from %s", device->properties.deviceName);
return pulse_device;
@@ -238,6 +241,8 @@ void VulkanDestroyDevice(PulseDevice device)
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(device, VulkanDevice*);
if(vulkan_device == PULSE_NULLPTR || vulkan_device->device == VK_NULL_HANDLE)
return;
VulkanDestroyDescriptorSetPoolManager(&vulkan_device->descriptor_set_pool_manager);
VulkanDestroyDescriptorSetLayoutManager(&vulkan_device->descriptor_set_layout_manager);
for(uint32_t i = 0; i < vulkan_device->cmd_pools_size; i++)
vulkan_device->vkDestroyCommandPool(vulkan_device->device, vulkan_device->cmd_pools[i].pool, PULSE_NULLPTR);
vmaDestroyAllocator(vulkan_device->allocator);

View File

@@ -17,12 +17,16 @@
#include <Pulse.h>
#include "VulkanEnums.h"
#include "VulkanDescriptor.h"
#include "VulkanCommandPool.h"
struct VulkanQueue;
typedef struct VulkanDevice
{
VulkanDescriptorSetPoolManager descriptor_set_pool_manager;
VulkanDescriptorSetLayoutManager descriptor_set_layout_manager;
VulkanCommandPool* cmd_pools;
uint32_t cmd_pools_size;

View File

@@ -19,6 +19,7 @@
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdBindPipeline)
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdCopyBuffer)
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdCopyBufferToImage)
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdCopyImageToBuffer)
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdDispatch)
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdDispatchIndirect)
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdExecuteCommands)

View File

@@ -15,15 +15,6 @@ typedef enum VulkanQueueType
VULKAN_QUEUE_END_ENUM // For internal use only
} VulkanQueueType;
typedef enum VulkanDescriptorSetType
{
VULKAN_DESCRIPTOR_SET_READ_ONLY = 0,
VULKAN_DESCRIPTOR_SET_READ_WRITE,
VULKAN_DESCRIPTOR_SET_UNIFORM,
VULKAN_DESCRIPTOR_SET_END_ENUM // For internal use only
} VulkanDescriptorSetType;
#endif // PULSE_VULKAN_ENUMS_H_
#endif // PULSE_ENABLE_VULKAN_BACKEND

View File

@@ -5,8 +5,9 @@
#include "Pulse.h"
#include "Vulkan.h"
#include "VulkanImage.h"
#include "VulkanBuffer.h"
#include "VulkanDevice.h"
#include <vulkan/vulkan_core.h>
#include "VulkanCommandList.h"
static VkFormat PulseImageFormatToVkFormat[] = {
VK_FORMAT_UNDEFINED, // INVALID
@@ -61,12 +62,6 @@ static VkFormat PulseImageFormatToVkFormat[] = {
VK_FORMAT_R32_SINT, // R32_INT
VK_FORMAT_R32G32_SINT, // R32G32_INT
VK_FORMAT_R32G32B32A32_SINT, // R32G32B32A32_INT
VK_FORMAT_R8G8B8A8_SRGB, // R8G8B8A8_UNORM_SRGB
VK_FORMAT_B8G8R8A8_SRGB, // B8G8R8A8_UNORM_SRGB
VK_FORMAT_BC1_RGBA_SRGB_BLOCK, // BC1_UNORM_SRGB
VK_FORMAT_BC2_SRGB_BLOCK, // BC3_UNORM_SRGB
VK_FORMAT_BC3_SRGB_BLOCK, // BC3_UNORM_SRGB
VK_FORMAT_BC7_SRGB_BLOCK, // BC7_UNORM_SRGB
};
PULSE_STATIC_ASSERT(PulseImageFormatToVkFormat, (sizeof(PulseImageFormatToVkFormat) / sizeof(VkFormat)) == PULSE_IMAGE_FORMAT_MAX_ENUM);
@@ -189,6 +184,25 @@ bool VulkanIsImageFormatValid(PulseDevice device, PulseImageFormat format, Pulse
bool VulkanCopyImageToBuffer(PulseCommandList cmd, const PulseImageRegion* src, const PulseBufferRegion* dst)
{
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(src->image->device, VulkanDevice*);
VulkanImage* vulkan_image = VULKAN_RETRIEVE_DRIVER_DATA_AS(src->image, VulkanImage*);
VulkanBuffer* vulkan_buffer = VULKAN_RETRIEVE_DRIVER_DATA_AS(dst->buffer, VulkanBuffer*);
VulkanCommandList* vulkan_cmd = VULKAN_RETRIEVE_DRIVER_DATA_AS(cmd, VulkanCommandList*);
VkOffset3D offset = { src->x, src->y, src->z };
VkExtent3D extent = { src->width, src->height, src->depth };
VkBufferImageCopy region = {};
region.bufferOffset = dst->offset;
region.bufferRowLength = 0;
region.bufferImageHeight = 0;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.mipLevel = 0;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;
region.imageOffset = offset;
region.imageExtent = extent;
vulkan_device->vkCmdCopyImageToBuffer(vulkan_cmd->cmd, vulkan_image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, vulkan_buffer->buffer, 1, &region);
return true;
}
bool VulkanBlitImage(PulseCommandList cmd, const PulseImageRegion* src, const PulseImageRegion* dst)

View File

@@ -2,6 +2,7 @@
// This file is part of "Pulse"
// For conditions of distribution and use, see copyright notice in LICENSE
#include <string.h>
#include "PulseDefs.h"
#include "PulseInternal.h"
@@ -39,6 +40,16 @@ PULSE_API bool PulseSubmitCommandList(PulseDevice device, PulseCommandList cmd,
}
}
if(cmd->pass->is_recording)
{
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend))
PulseLogWarning(device->backend, "submitting command list with a recording compute pass, stopping record");
PulseEndComputePass(cmd->pass);
}
memset(cmd->pass->compute_pipelines_bound, 0, sizeof(PulseComputePipeline) * cmd->pass->compute_pipelines_bound_size);
cmd->pass->compute_pipelines_bound_size = 0;
return device->PFN_SubmitCommandList(device, cmd, fence);
}
@@ -64,3 +75,42 @@ PULSE_API void PulseReleaseCommandList(PulseDevice device, PulseCommandList cmd)
}
return device->PFN_ReleaseCommandList(device, cmd);
}
PULSE_API PulseComputePass PulseBeginComputePass(PulseCommandList cmd)
{
PULSE_CHECK_HANDLE_RETVAL(cmd, PULSE_NULL_HANDLE);
PULSE_CHECK_HANDLE_RETVAL(cmd->device, PULSE_NULL_HANDLE);
PULSE_CHECK_COMMAND_LIST_STATE_RETVAL(cmd, PULSE_NULL_HANDLE);
PulseComputePass pass = cmd->device->PFN_BeginComputePass(cmd);
if(pass->is_recording == true)
{
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(cmd->device->backend))
PulseLogWarning(cmd->device->backend, "a compute pass is already recording in this command buffer, please call PulseEndComputePass before beginning a new one");
return PULSE_NULL_HANDLE;
}
pass->is_recording = true;
return pass;
}
PULSE_API void PulseEndComputePass(PulseComputePass pass)
{
if(pass == PULSE_NULL_HANDLE)
{
PULSE_CHECK_HANDLE(pass->cmd);
PULSE_CHECK_HANDLE(pass->cmd->device);
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(pass->cmd->device->backend))
PulseLogWarning(pass->cmd->device->backend, "command list is NULL, this may be a bug in your application");
return;
}
PULSE_CHECK_COMMAND_LIST_STATE(pass->cmd);
memset(pass->readonly_images, 0, PULSE_MAX_READ_TEXTURES_BOUND * sizeof(PulseImage));
memset(pass->readwrite_images, 0, PULSE_MAX_WRITE_TEXTURES_BOUND * sizeof(PulseImage));
memset(pass->readonly_storage_buffers, 0, PULSE_MAX_READ_BUFFERS_BOUND * sizeof(PulseBuffer));
memset(pass->readwrite_storage_buffers, 0, PULSE_MAX_WRITE_BUFFERS_BOUND * sizeof(PulseBuffer));
pass->current_pipeline = PULSE_NULL_HANDLE;
pass->is_recording = false;
}

View File

@@ -5,54 +5,74 @@
#include "PulseDefs.h"
#include "PulseInternal.h"
PULSE_API PulseComputePipeline PulseCreateComputePipeline(PulseDevice device, const PulseComputePipelineCreateInfo* info)
{
PULSE_CHECK_HANDLE_RETVAL(device, PULSE_NULL_HANDLE);
if(info == PULSE_NULLPTR && PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend))
PulseLogError(device->backend, "null infos pointer");
PULSE_CHECK_PTR_RETVAL(info, PULSE_NULL_HANDLE);
return device->PFN_CreateComputePipeline(device, info);
PulseComputePipeline pipeline = device->PFN_CreateComputePipeline(device, info);
if(pipeline == PULSE_NULL_HANDLE)
return PULSE_NULL_HANDLE;
pipeline->num_readonly_storage_images = info->num_readonly_storage_images;
pipeline->num_readonly_storage_buffers = info->num_readonly_storage_buffers;
pipeline->num_readwrite_storage_images = info->num_readwrite_storage_buffers;
pipeline->num_readwrite_storage_buffers = info->num_readwrite_storage_buffers;
pipeline->num_uniform_buffers = info->num_uniform_buffers;
return pipeline;
}
PULSE_API void PulseDispatchComputePipeline(PulseComputePipeline pipeline, PulseCommandList cmd, uint32_t groupcount_x, uint32_t groupcount_y, uint32_t groupcount_z)
PULSE_API void PulseBindStorageBuffers(PulseComputePass pass, uint32_t starting_slot, PulseBuffer* const* buffers, uint32_t num_buffers)
{
PULSE_CHECK_HANDLE(pass);
PULSE_CHECK_COMMAND_LIST_STATE(pass->cmd);
pass->cmd->device->PFN_BindStorageBuffers(pass, starting_slot, buffers, num_buffers);
}
PULSE_API void PulseBindUniformData(PulseComputePass pass, uint32_t slot, const void* data, uint32_t data_size)
{
PULSE_CHECK_HANDLE(pass);
PULSE_CHECK_COMMAND_LIST_STATE(pass->cmd);
pass->cmd->device->PFN_BindUniformData(pass, slot, data, data_size);
}
PULSE_API void PulseBindStorageImages(PulseComputePass pass, uint32_t starting_slot, PulseImage* const* images, uint32_t num_images)
{
PULSE_CHECK_HANDLE(pass);
PULSE_CHECK_COMMAND_LIST_STATE(pass->cmd);
pass->cmd->device->PFN_BindStorageImages(pass, starting_slot, images, num_images);
}
PULSE_API void PulseBindComputePipeline(PulseComputePass pass, PulseComputePipeline pipeline)
{
PULSE_CHECK_HANDLE(pass);
PULSE_CHECK_HANDLE(pipeline);
PULSE_CHECK_HANDLE(cmd);
if(cmd->state != PULSE_COMMAND_LIST_STATE_RECORDING)
{
switch(cmd->state)
{
case PULSE_COMMAND_LIST_STATE_INVALID:
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(cmd->device->backend))
PulseLogError(cmd->device->backend, "command list is in invalid state");
return;
PULSE_CHECK_COMMAND_LIST_STATE(pass->cmd);
case PULSE_COMMAND_LIST_STATE_READY:
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(cmd->device->backend))
PulseLogError(cmd->device->backend, "command list is not recording");
return;
pass->cmd->device->PFN_BindComputePipeline(pass, pipeline);
case PULSE_COMMAND_LIST_STATE_SENT:
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(cmd->device->backend))
PulseLogWarning(cmd->device->backend, "command list has already been submitted");
return;
pass->current_pipeline = pipeline;
default: break;
}
}
PULSE_EXPAND_ARRAY_IF_NEEDED(pass->compute_pipelines_bound, PulseComputePipeline, pass->compute_pipelines_bound_size, pass->compute_pipelines_bound_capacity, 2);
pass->compute_pipelines_bound[pass->compute_pipelines_bound_size] = pipeline;
pass->compute_pipelines_bound_size++;
}
cmd->device->PFN_DispatchComputePipeline(pipeline, cmd, groupcount_x, groupcount_y, groupcount_z);
pipeline->cmd = cmd;
PULSE_API void PulseDispatchComputations(PulseComputePass pass, uint32_t groupcount_x, uint32_t groupcount_y, uint32_t groupcount_z)
{
PULSE_CHECK_HANDLE(pass);
if(cmd->compute_pipelines_bound_size == cmd->compute_pipelines_bound_capacity)
{
cmd->compute_pipelines_bound_capacity += 5;
cmd->compute_pipelines_bound = (PulseComputePipeline*)realloc(cmd->compute_pipelines_bound, cmd->compute_pipelines_bound_capacity * sizeof(PulseComputePipeline));
PULSE_CHECK_ALLOCATION(cmd->compute_pipelines_bound);
}
cmd->compute_pipelines_bound[cmd->compute_pipelines_bound_size] = pipeline;
cmd->compute_pipelines_bound_size++;
PULSE_CHECK_COMMAND_LIST_STATE(pass->cmd);
pass->cmd->device->PFN_DispatchComputations(pass, groupcount_x, groupcount_y, groupcount_z);
}
PULSE_API void PulseDestroyComputePipeline(PulseDevice device, PulseComputePipeline pipeline)

View File

@@ -62,6 +62,29 @@
for(size_t defrag_i = start; defrag_i < size - 1; defrag_i++) \
array[defrag_i] = array[defrag_i + 1]; \
#define PULSE_CHECK_COMMAND_LIST_STATE_RETVAL(cmd, retval) \
if(cmd->state != PULSE_COMMAND_LIST_STATE_RECORDING) \
{ \
switch(cmd->state) \
{ \
case PULSE_COMMAND_LIST_STATE_INVALID: \
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(cmd->device->backend)) \
PulseLogError(cmd->device->backend, "command list is in invalid state"); \
return retval; \
case PULSE_COMMAND_LIST_STATE_READY: \
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(cmd->device->backend)) \
PulseLogError(cmd->device->backend, "command list is not recording"); \
return retval; \
case PULSE_COMMAND_LIST_STATE_SENT: \
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(cmd->device->backend)) \
PulseLogWarning(cmd->device->backend, "command list has already been submitted"); \
return retval; \
default: break; \
} \
} \
#define PULSE_CHECK_COMMAND_LIST_STATE(cmd) PULSE_CHECK_COMMAND_LIST_STATE_RETVAL(cmd, )
#ifndef PULSE_STATIC_ASSERT
#ifdef __cplusplus
#if __cplusplus >= 201103L
@@ -81,7 +104,7 @@
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyDevice, _namespace) \
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(CreateComputePipeline, _namespace) \
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyComputePipeline, _namespace) \
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DispatchComputePipeline, _namespace) \
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DispatchComputations, _namespace) \
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(CreateFence, _namespace) \
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyFence, _namespace) \
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(IsFenceReady, _namespace) \
@@ -100,5 +123,12 @@
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(CopyImageToBuffer, _namespace) \
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(BlitImage, _namespace) \
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyImage, _namespace) \
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(BeginComputePass, _namespace) \
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(EndComputePass, _namespace) \
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(BindStorageBuffers, _namespace) \
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(BindUniformData, _namespace) \
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(BindStorageImages, _namespace) \
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(BindStorageImages, _namespace) \
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(BindComputePipeline, _namespace) \
#endif // PULSE_DEFS_H_

View File

@@ -124,6 +124,46 @@ PULSE_API bool PulseIsImageFormatValid(PulseDevice device, PulseImageFormat form
PULSE_API bool PulseCopyImageToBuffer(PulseCommandList cmd, const PulseImageRegion* src, const PulseBufferRegion* dst)
{
PULSE_CHECK_PTR_RETVAL(src, false);
PULSE_CHECK_HANDLE_RETVAL(src->image, false);
PULSE_CHECK_PTR_RETVAL(dst, false);
PULSE_CHECK_HANDLE_RETVAL(dst->buffer, false);
PulseBackend backend = src->image->device->backend;
if(src->image->device != dst->buffer->device)
{
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(backend))
PulseLogErrorFmt(backend, "source image has been created on a different device (%p) than the destination buffer (%p)", src->image->device, dst->buffer->device);
PulseSetInternalError(PULSE_ERROR_INVALID_DEVICE);
return false;
}
if(dst->size + dst->offset > dst->buffer->size)
{
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(backend))
PulseLogErrorFmt(backend, "destination buffer region (%lld) is bigger than the buffer size (%lld)", dst->size + dst->offset, dst->buffer->size);
PulseSetInternalError(PULSE_ERROR_INVALID_REGION);
return false;
}
if(src->width > src->image->width)
{
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(backend))
PulseLogErrorFmt(backend, "source image region width (%lld) is bigger than image width (%lld)", src->width, src->image->width);
PulseSetInternalError(PULSE_ERROR_INVALID_REGION);
return false;
}
if(src->height > src->image->height)
{
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(backend))
PulseLogErrorFmt(backend, "source image region height (%lld) is bigger than image height (%lld)", src->height, src->image->height);
PulseSetInternalError(PULSE_ERROR_INVALID_REGION);
return false;
}
return src->image->device->PFN_CopyImageToBuffer(cmd, src, dst);
}
PULSE_API bool PulseBlitImage(PulseCommandList cmd, const PulseImageRegion* src, const PulseImageRegion* dst)

View File

@@ -11,6 +11,17 @@
#include "PulseDefs.h"
#include "PulseEnums.h"
#define PULSE_MAX_READ_TEXTURES_BOUND 8
#define PULSE_MAX_READ_BUFFERS_BOUND 8
#define PULSE_MAX_WRITE_TEXTURES_BOUND 8
#define PULSE_MAX_WRITE_BUFFERS_BOUND 8
#define PULSE_MAX_UNIFORM_BUFFERS_BOUND 8
typedef enum PulseInternalBufferUsageBits
{
PULSE_INTERNAL_BUFFER_USAGE_UNIFORM_ACCESS = PULSE_BIT(31)
} PulseInternalBufferUsageBits;
typedef uint64_t PulseThreadID;
typedef struct PulseBackendHandler
@@ -40,11 +51,9 @@ typedef struct PulseBufferHandler
typedef struct PulseCommandListHandler
{
PulseDevice device;
PulseComputePass pass;
void* driver_data;
PulseThreadID thread_id;
PulseComputePipeline* compute_pipelines_bound;
uint32_t compute_pipelines_bound_capacity;
uint32_t compute_pipelines_bound_size;
PulseCommandListState state;
PulseCommandListUsage usage;
bool is_available;
@@ -52,8 +61,12 @@ typedef struct PulseCommandListHandler
typedef struct PulseComputePipelineHandler
{
PulseCommandList cmd;
void* driver_data;
uint32_t num_readonly_storage_images;
uint32_t num_readonly_storage_buffers;
uint32_t num_readwrite_storage_images;
uint32_t num_readwrite_storage_buffers;
uint32_t num_uniform_buffers;
} PulseComputePipelineHandler;
typedef struct PulseDeviceHandler
@@ -61,7 +74,7 @@ typedef struct PulseDeviceHandler
// PFNs
PulseDestroyDevicePFN PFN_DestroyDevice;
PulseCreateComputePipelinePFN PFN_CreateComputePipeline;
PulseDispatchComputePipelinePFN PFN_DispatchComputePipeline;
PulseDispatchComputationsPFN PFN_DispatchComputations;
PulseDestroyComputePipelinePFN PFN_DestroyComputePipeline;
PulseCreateFencePFN PFN_CreateFence;
PulseDestroyFencePFN PFN_DestroyFence;
@@ -81,6 +94,12 @@ typedef struct PulseDeviceHandler
PulseCopyImageToBufferPFN PFN_CopyImageToBuffer;
PulseBlitImagePFN PFN_BlitImage;
PulseDestroyImagePFN PFN_DestroyImage;
PulseBeginComputePassPFN PFN_BeginComputePass;
PulseBindStorageBuffersPFN PFN_BindStorageBuffers;
PulseBindUniformDataPFN PFN_BindUniformData;
PulseBindStorageImagesPFN PFN_BindStorageImages;
PulseBindComputePipelinePFN PFN_BindComputePipeline;
PulseEndComputePassPFN PFN_EndComputePass;
// Attributes
void* driver_data;
@@ -113,6 +132,26 @@ typedef struct PulseImageHandler
uint32_t layer_count_or_depth;
} PulseImageHandler;
typedef struct PulseComputePassHandler
{
PulseBuffer readonly_storage_buffers[PULSE_MAX_READ_BUFFERS_BOUND];
PulseBuffer readwrite_storage_buffers[PULSE_MAX_WRITE_BUFFERS_BOUND];
PulseImage readonly_images[PULSE_MAX_READ_TEXTURES_BOUND];
PulseImage readwrite_images[PULSE_MAX_WRITE_TEXTURES_BOUND];
PulseCommandList cmd;
PulseComputePipeline current_pipeline;
void* driver_data;
PulseComputePipeline* compute_pipelines_bound;
uint32_t compute_pipelines_bound_capacity;
uint32_t compute_pipelines_bound_size;
bool is_recording;
} PulseComputePassHandler;
PulseThreadID PulseGetThreadID();
void PulseSetInternalError(PulseErrorType error);
@@ -127,12 +166,6 @@ void PulseLogBackend(PulseBackend backend, PulseDebugMessageSeverity type, const
#define PulseLogWarningFmt(backend, msg, ...) PulseLogBackend(backend, PULSE_DEBUG_MESSAGE_SEVERITY_WARNING, msg, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
#define PulseLogInfoFmt(backend, msg, ...) PulseLogBackend(backend, PULSE_DEBUG_MESSAGE_SEVERITY_INFO, msg, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
#define PULSE_MAX_STORAGE_TEXTURES_BOUND 8
#define PULSE_MAX_STORAGE_BUFFERS_BOUND 8
#define PULSE_MAX_UNIFORM_BUFFERS_BOUND 4
#define PULSE_MAX_WRITE_TEXTURES_BOUND 8
#define PULSE_MAX_WRITE_BUFFERS_BOUND 8
#ifdef PULSE_ENABLE_VULKAN_BACKEND
extern PulseBackendHandler VulkanDriver;
#endif // PULSE_ENABLE_VULKAN_BACKEND

View File

@@ -15,7 +15,7 @@ typedef PulseDevice (*PulseCreateDevicePFN)(PulseBackend, PulseDevice*, uint32_t
typedef void (*PulseDestroyDevicePFN)(PulseDevice);
typedef PulseComputePipeline (*PulseCreateComputePipelinePFN)(PulseDevice, const PulseComputePipelineCreateInfo*);
typedef void (*PulseDispatchComputePipelinePFN)(PulseComputePipeline, PulseCommandList, uint32_t, uint32_t, uint32_t);
typedef void (*PulseDispatchComputationsPFN)(PulseComputePass, uint32_t, uint32_t, uint32_t);
typedef void (*PulseDestroyComputePipelinePFN)(PulseDevice, PulseComputePipeline);
typedef PulseFence (*PulseCreateFencePFN)(PulseDevice);
typedef void (*PulseDestroyFencePFN)(PulseDevice, PulseFence);
@@ -35,5 +35,11 @@ typedef bool (*PulseCopyBufferToBufferPFN)(PulseCommandList, const PulseBufferRe
typedef bool (*PulseCopyBufferToImageFN)(PulseCommandList, const PulseBufferRegion*, const PulseImageRegion*);
typedef bool (*PulseCopyImageToBufferPFN)(PulseCommandList, const PulseImageRegion*, const PulseBufferRegion*);
typedef bool (*PulseBlitImagePFN)(PulseCommandList, const PulseImageRegion*, const PulseImageRegion*);
typedef PulseComputePass (*PulseBeginComputePassPFN)(PulseCommandList);
typedef void (*PulseBindStorageBuffersPFN)(PulseComputePass, uint32_t, PulseBuffer* const*, uint32_t);
typedef void (*PulseBindUniformDataPFN)(PulseComputePass, uint32_t, const void*, uint32_t);
typedef void (*PulseBindStorageImagesPFN)(PulseComputePass, uint32_t, PulseImage* const*, uint32_t);
typedef void (*PulseBindComputePipelinePFN)(PulseComputePass, PulseComputePipeline);
typedef void (*PulseEndComputePassPFN)(PulseComputePass);
#endif // PULSE_PFNS_H_

View File

@@ -36,12 +36,6 @@ void TestBufferCreation()
TEST_ASSERT_NOT_EQUAL_MESSAGE(buffer, PULSE_NULL_HANDLE, PulseVerbaliseErrorType(PulseGetLastErrorType()));
PulseDestroyBuffer(device, buffer);
buffer_create_info.size = 1024;
buffer_create_info.usage = PULSE_BUFFER_USAGE_UNIFORM_ACCESS;
buffer = PulseCreateBuffer(device, &buffer_create_info);
TEST_ASSERT_NOT_EQUAL_MESSAGE(buffer, PULSE_NULL_HANDLE, PulseVerbaliseErrorType(PulseGetLastErrorType()));
PulseDestroyBuffer(device, buffer);
buffer_create_info.size = 1024;
buffer_create_info.usage = PULSE_BUFFER_USAGE_STORAGE_READ | PULSE_BUFFER_USAGE_STORAGE_WRITE;
buffer = PulseCreateBuffer(device, &buffer_create_info);

20
Tests/Vulkan/Pipeline.c git.filemode.normal_file
View File

@@ -0,0 +1,20 @@
#include "Common.h"
#include <unity/unity.h>
#include <Pulse.h>
void TestPipelineSetup()
{
PulseBackend backend;
SetupPulse(&backend);
PulseDevice device;
SetupDevice(backend, &device);
CleanupDevice(device);
CleanupPulse(backend);
}
void TestPipeline()
{
RUN_TEST(TestPipelineSetup);
}

View File

@@ -43,7 +43,7 @@ end
add_rules("mode.debug", "mode.release")
add_includedirs("Includes")
set_languages("c11", "cxx20")
set_languages("c17", "cxx20")
set_encodings("utf-8")
set_warnings("allextra")