mirror of
https://github.com/Kbz-8/Pulse.git
synced 2026-01-11 15:33:34 +00:00
working on vulkan descriptor sets
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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_
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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_
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, ®ion);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VulkanBlitImage(PulseCommandList cmd, const PulseImageRegion* src, const PulseImageRegion* dst)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_
|
||||
|
||||
Reference in New Issue
Block a user