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:
@@ -56,7 +56,12 @@ int main(void)
|
|||||||
PulseCommandList cmd = PulseRequestCommandList(device, PULSE_COMMAND_LIST_GENERAL);
|
PulseCommandList cmd = PulseRequestCommandList(device, PULSE_COMMAND_LIST_GENERAL);
|
||||||
CHECK_PULSE_HANDLE_RETVAL(cmd, 1);
|
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))
|
if(!PulseSubmitCommandList(device, cmd, fence))
|
||||||
fprintf(stderr, "Could not submit command list, %s\n", PulseVerbaliseErrorType(PulseGetLastErrorType()));
|
fprintf(stderr, "Could not submit command list, %s\n", PulseVerbaliseErrorType(PulseGetLastErrorType()));
|
||||||
|
|||||||
@@ -29,14 +29,15 @@ PULSE_DEFINE_NULLABLE_HANDLE(PulseComputePipeline);
|
|||||||
PULSE_DEFINE_NULLABLE_HANDLE(PulseDevice);
|
PULSE_DEFINE_NULLABLE_HANDLE(PulseDevice);
|
||||||
PULSE_DEFINE_NULLABLE_HANDLE(PulseFence);
|
PULSE_DEFINE_NULLABLE_HANDLE(PulseFence);
|
||||||
PULSE_DEFINE_NULLABLE_HANDLE(PulseImage);
|
PULSE_DEFINE_NULLABLE_HANDLE(PulseImage);
|
||||||
|
PULSE_DEFINE_NULLABLE_HANDLE(PulseComputePass);
|
||||||
|
|
||||||
// Flags
|
// Flags
|
||||||
typedef enum PulseBackendBits
|
typedef enum PulseBackendBits
|
||||||
{
|
{
|
||||||
PULSE_BACKEND_INVALID = PULSE_BIT(1),
|
PULSE_BACKEND_INVALID = PULSE_BIT(1),
|
||||||
PULSE_BACKEND_ANY = PULSE_BIT(2),
|
PULSE_BACKEND_ANY = PULSE_BIT(2),
|
||||||
PULSE_BACKEND_VULKAN = PULSE_BIT(3),
|
PULSE_BACKEND_VULKAN = PULSE_BIT(3),
|
||||||
PULSE_BACKEND_METAL = PULSE_BIT(4),
|
PULSE_BACKEND_METAL = PULSE_BIT(4),
|
||||||
// More to come
|
// More to come
|
||||||
} PulseBackendBits;
|
} PulseBackendBits;
|
||||||
typedef PulseFlags PulseBackendFlags;
|
typedef PulseFlags PulseBackendFlags;
|
||||||
@@ -47,7 +48,6 @@ typedef enum PulseBufferUsageBits
|
|||||||
PULSE_BUFFER_USAGE_TRANSFER_DOWNLOAD = PULSE_BIT(2),
|
PULSE_BUFFER_USAGE_TRANSFER_DOWNLOAD = PULSE_BIT(2),
|
||||||
PULSE_BUFFER_USAGE_STORAGE_READ = PULSE_BIT(3),
|
PULSE_BUFFER_USAGE_STORAGE_READ = PULSE_BIT(3),
|
||||||
PULSE_BUFFER_USAGE_STORAGE_WRITE = PULSE_BIT(4),
|
PULSE_BUFFER_USAGE_STORAGE_WRITE = PULSE_BIT(4),
|
||||||
PULSE_BUFFER_USAGE_UNIFORM_ACCESS = PULSE_BIT(5),
|
|
||||||
} PulseShaderFormatBits;
|
} PulseShaderFormatBits;
|
||||||
typedef PulseFlags PulseBufferUsageFlags;
|
typedef PulseFlags PulseBufferUsageFlags;
|
||||||
|
|
||||||
@@ -67,9 +67,9 @@ typedef PulseFlags PulseImageUsageFlags;
|
|||||||
|
|
||||||
typedef enum PulseShaderFormatsBits
|
typedef enum PulseShaderFormatsBits
|
||||||
{
|
{
|
||||||
PULSE_SHADER_FORMAT_SPIRV_BIT = PULSE_BIT(1), // Can be used by Vulkan
|
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_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_METALLIB_BIT = PULSE_BIT(3), // Can be used by Metal
|
||||||
// More to come
|
// More to come
|
||||||
} PulseShaderFormatsBits;
|
} PulseShaderFormatsBits;
|
||||||
typedef PulseFlags PulseShaderFormatsFlags;
|
typedef PulseFlags PulseShaderFormatsFlags;
|
||||||
@@ -133,7 +133,7 @@ typedef enum PulseImageFormat
|
|||||||
PULSE_IMAGE_FORMAT_R16G16_UNORM,
|
PULSE_IMAGE_FORMAT_R16G16_UNORM,
|
||||||
PULSE_IMAGE_FORMAT_R16G16B16A16_UNORM,
|
PULSE_IMAGE_FORMAT_R16G16B16A16_UNORM,
|
||||||
PULSE_IMAGE_FORMAT_R10G10B10A2_UNORM,
|
PULSE_IMAGE_FORMAT_R10G10B10A2_UNORM,
|
||||||
PULSE_IMAGE_FORMAT_B5G6R5_UNORM,
|
PULSE_IMAGE_FORMAT_B5G6R5_UNORM,
|
||||||
PULSE_IMAGE_FORMAT_B5G5R5A1_UNORM,
|
PULSE_IMAGE_FORMAT_B5G5R5A1_UNORM,
|
||||||
PULSE_IMAGE_FORMAT_B4G4R4A4_UNORM,
|
PULSE_IMAGE_FORMAT_B4G4R4A4_UNORM,
|
||||||
PULSE_IMAGE_FORMAT_B8G8R8A8_UNORM,
|
PULSE_IMAGE_FORMAT_B8G8R8A8_UNORM,
|
||||||
@@ -184,14 +184,6 @@ typedef enum PulseImageFormat
|
|||||||
PULSE_IMAGE_FORMAT_R32_INT,
|
PULSE_IMAGE_FORMAT_R32_INT,
|
||||||
PULSE_IMAGE_FORMAT_R32G32_INT,
|
PULSE_IMAGE_FORMAT_R32G32_INT,
|
||||||
PULSE_IMAGE_FORMAT_R32G32B32A32_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
|
PULSE_IMAGE_FORMAT_MAX_ENUM // For internal use only
|
||||||
} PulseImageFormat;
|
} 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 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 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 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 PulseErrorType PulseGetLastErrorType(); // Call to this function resets the internal last error variable
|
||||||
PULSE_API const char* PulseVerbaliseErrorType(PulseErrorType error);
|
PULSE_API const char* PulseVerbaliseErrorType(PulseErrorType error);
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ PulseBuffer VulkanCreateBuffer(PulseDevice device, const PulseBufferCreateInfo*
|
|||||||
vulkan_buffer->usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
vulkan_buffer->usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||||
allocation_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_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;
|
vulkan_buffer->usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||||
allocation_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_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;
|
info.commandBufferCount = 1;
|
||||||
CHECK_VK(pool->device->backend, vulkan_device->vkAllocateCommandBuffers(vulkan_device->device, &info, &vulkan_cmd->cmd), PULSE_ERROR_INITIALIZATION_FAILED);
|
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)
|
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_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);
|
|
||||||
}
|
|
||||||
pool->available_command_lists[pool->available_command_lists_size] = cmd;
|
pool->available_command_lists[pool->available_command_lists_size] = cmd;
|
||||||
pool->available_command_lists_size++;
|
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)
|
PulseCommandList VulkanRequestCommandList(PulseDevice device, PulseCommandListUsage usage)
|
||||||
{
|
{
|
||||||
PULSE_CHECK_HANDLE_RETVAL(device, PULSE_NULL_HANDLE);
|
PULSE_CHECK_HANDLE_RETVAL(device, PULSE_NULL_HANDLE);
|
||||||
@@ -77,7 +92,7 @@ PulseCommandList VulkanRequestCommandList(PulseDevice device, PulseCommandListUs
|
|||||||
VulkanInitCommandList(pool, cmd);
|
VulkanInitCommandList(pool, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd->compute_pipelines_bound_size = 0;
|
cmd->pass = VulkanCreateComputePass(device, cmd);
|
||||||
cmd->state = PULSE_COMMAND_LIST_STATE_RECORDING;
|
cmd->state = PULSE_COMMAND_LIST_STATE_RECORDING;
|
||||||
cmd->is_available = false;
|
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 <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
#include <Pulse.h>
|
#include <Pulse.h>
|
||||||
|
#include "VulkanBuffer.h"
|
||||||
#include "VulkanCommandPool.h"
|
#include "VulkanCommandPool.h"
|
||||||
|
#include "VulkanDescriptor.h"
|
||||||
|
|
||||||
typedef struct VulkanCommandList
|
typedef struct VulkanCommandList
|
||||||
{
|
{
|
||||||
@@ -18,9 +20,19 @@ typedef struct VulkanCommandList
|
|||||||
VkCommandBuffer cmd;
|
VkCommandBuffer cmd;
|
||||||
} VulkanCommandList;
|
} 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);
|
PulseCommandList VulkanRequestCommandList(PulseDevice device, PulseCommandListUsage usage);
|
||||||
bool VulkanSubmitCommandList(PulseDevice device, PulseCommandList cmd, PulseFence fence);
|
bool VulkanSubmitCommandList(PulseDevice device, PulseCommandList cmd, PulseFence fence);
|
||||||
void VulkanReleaseCommandList(PulseDevice device, PulseCommandList cmd);
|
void VulkanReleaseCommandList(PulseDevice device, PulseCommandList cmd);
|
||||||
|
PulseComputePass VulkanBeginComputePass(PulseCommandList cmd);
|
||||||
|
void VulkanEndComputePass(PulseComputePass pass);
|
||||||
|
|
||||||
#endif // PULSE_VULKAN_COMMAND_LIST_H_
|
#endif // PULSE_VULKAN_COMMAND_LIST_H_
|
||||||
|
|
||||||
|
|||||||
@@ -60,16 +60,6 @@ PulseComputePipeline VulkanCreateComputePipeline(PulseDevice device, const Pulse
|
|||||||
return pipeline;
|
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)
|
void VulkanDestroyComputePipeline(PulseDevice device, PulseComputePipeline pipeline)
|
||||||
{
|
{
|
||||||
if(pipeline == PULSE_NULL_HANDLE)
|
if(pipeline == PULSE_NULL_HANDLE)
|
||||||
@@ -91,3 +81,32 @@ void VulkanDestroyComputePipeline(PulseDevice device, PulseComputePipeline pipel
|
|||||||
if(PULSE_IS_BACKEND_HIGH_LEVEL_DEBUG(device->backend))
|
if(PULSE_IS_BACKEND_HIGH_LEVEL_DEBUG(device->backend))
|
||||||
PulseLogInfoFmt(device->backend, "(Vulkan) destroyed compute pipeline %p", pipeline);
|
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;
|
} VulkanComputePipeline;
|
||||||
|
|
||||||
PulseComputePipeline VulkanCreateComputePipeline(PulseDevice device, const PulseComputePipelineCreateInfo* info);
|
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 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_
|
#endif // PULSE_VULKAN_COMPUTE_PIPELINE_H_
|
||||||
|
|
||||||
|
|||||||
@@ -10,28 +10,145 @@
|
|||||||
#include "VulkanDevice.h"
|
#include "VulkanDevice.h"
|
||||||
#include "VulkanDescriptor.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)
|
void VulkanInitDescriptorSetPool(VulkanDescriptorSetPool* pool, PulseDevice device)
|
||||||
{
|
{
|
||||||
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(device, VulkanDevice*);
|
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(device, VulkanDevice*);
|
||||||
memset(pool, 0, sizeof(VulkanDescriptorSetPool));
|
memset(pool, 0, sizeof(VulkanDescriptorSetPool));
|
||||||
pool->device = device;
|
pool->device = device;
|
||||||
|
pool->thread_id = PulseGetThreadID();
|
||||||
|
|
||||||
VkDescriptorPoolSize pool_sizes[
|
VkDescriptorPoolSize pool_sizes[
|
||||||
PULSE_MAX_STORAGE_TEXTURES_BOUND +
|
PULSE_MAX_READ_TEXTURES_BOUND +
|
||||||
PULSE_MAX_STORAGE_BUFFERS_BOUND +
|
PULSE_MAX_READ_BUFFERS_BOUND +
|
||||||
PULSE_MAX_WRITE_TEXTURES_BOUND +
|
PULSE_MAX_WRITE_TEXTURES_BOUND +
|
||||||
PULSE_MAX_WRITE_BUFFERS_BOUND +
|
PULSE_MAX_WRITE_BUFFERS_BOUND +
|
||||||
PULSE_MAX_UNIFORM_BUFFERS_BOUND];
|
PULSE_MAX_UNIFORM_BUFFERS_BOUND];
|
||||||
|
|
||||||
uint32_t i = 0;
|
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].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||||
pool_sizes[i].descriptorCount = VULKAN_POOL_SIZE;
|
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].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||||
pool_sizes[i].descriptorCount = VULKAN_POOL_SIZE;
|
pool_sizes[i].descriptorCount = VULKAN_POOL_SIZE;
|
||||||
@@ -146,7 +263,6 @@ void VulkanDestroyDescriptorSetPool(VulkanDescriptorSetPool* pool)
|
|||||||
memset(pool, 0, sizeof(VulkanDescriptorSetPool));
|
memset(pool, 0, sizeof(VulkanDescriptorSetPool));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void VulkanInitDescriptorSetPoolManager(VulkanDescriptorSetPoolManager* manager, PulseDevice device)
|
void VulkanInitDescriptorSetPoolManager(VulkanDescriptorSetPoolManager* manager, PulseDevice device)
|
||||||
{
|
{
|
||||||
memset(manager, 0, sizeof(VulkanDescriptorSetPoolManager));
|
memset(manager, 0, sizeof(VulkanDescriptorSetPoolManager));
|
||||||
@@ -155,9 +271,10 @@ void VulkanInitDescriptorSetPoolManager(VulkanDescriptorSetPoolManager* manager,
|
|||||||
|
|
||||||
VulkanDescriptorSetPool* VulkanGetAvailableDescriptorSetPool(VulkanDescriptorSetPoolManager* manager)
|
VulkanDescriptorSetPool* VulkanGetAvailableDescriptorSetPool(VulkanDescriptorSetPoolManager* manager)
|
||||||
{
|
{
|
||||||
|
PulseThreadID thread_id = PulseGetThreadID();
|
||||||
for(uint32_t i = 0; i < manager->pools_size; i++)
|
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];
|
return manager->pools[i];
|
||||||
}
|
}
|
||||||
PULSE_EXPAND_ARRAY_IF_NEEDED(manager->pools, VulkanDescriptorSetPool*, manager->pools_size, manager->pools_capacity, 1);
|
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 <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
#include <Pulse.h>
|
#include <Pulse.h>
|
||||||
|
#include "../../PulseInternal.h"
|
||||||
|
|
||||||
#include "VulkanEnums.h"
|
#include "VulkanEnums.h"
|
||||||
|
|
||||||
@@ -18,7 +19,6 @@
|
|||||||
typedef struct VulkanDescriptorSetLayout
|
typedef struct VulkanDescriptorSetLayout
|
||||||
{
|
{
|
||||||
VkDescriptorSetLayout layout;
|
VkDescriptorSetLayout layout;
|
||||||
VulkanDescriptorSetType type;
|
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
@@ -55,6 +55,7 @@ typedef struct VulkanDescriptorSetPool
|
|||||||
uint32_t free_index;
|
uint32_t free_index;
|
||||||
PulseDevice device;
|
PulseDevice device;
|
||||||
VkDescriptorPool pool;
|
VkDescriptorPool pool;
|
||||||
|
PulseThreadID thread_id;
|
||||||
uint32_t allocations_count;
|
uint32_t allocations_count;
|
||||||
} VulkanDescriptorSetPool;
|
} VulkanDescriptorSetPool;
|
||||||
|
|
||||||
@@ -66,10 +67,25 @@ typedef struct VulkanDescriptorSetPoolManager
|
|||||||
uint32_t pools_size;
|
uint32_t pools_size;
|
||||||
} VulkanDescriptorSetPoolManager;
|
} 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);
|
VulkanDescriptorSet* VulkanRequestDescriptorSetFromPool(VulkanDescriptorSetPool* pool, const VulkanDescriptorSetLayout* layout);
|
||||||
void VulkanReturnDescriptorSetToPool(VulkanDescriptorSetPool* pool, const VulkanDescriptorSet* set);
|
void VulkanReturnDescriptorSetToPool(VulkanDescriptorSetPool* pool, const VulkanDescriptorSet* set);
|
||||||
void VulkanDestroyDescriptorSetPool(VulkanDescriptorSetPool* pool);
|
|
||||||
|
|
||||||
void VulkanInitDescriptorSetPoolManager(VulkanDescriptorSetPoolManager* manager, PulseDevice device);
|
void VulkanInitDescriptorSetPoolManager(VulkanDescriptorSetPoolManager* manager, PulseDevice device);
|
||||||
VulkanDescriptorSetPool* VulkanGetAvailableDescriptorSetPool(VulkanDescriptorSetPoolManager* manager);
|
VulkanDescriptorSetPool* VulkanGetAvailableDescriptorSetPool(VulkanDescriptorSetPoolManager* manager);
|
||||||
|
|||||||
@@ -228,6 +228,9 @@ PulseDevice VulkanCreateDevice(PulseBackend backend, PulseDevice* forbiden_devic
|
|||||||
pulse_device->backend = backend;
|
pulse_device->backend = backend;
|
||||||
PULSE_LOAD_DRIVER_DEVICE(Vulkan);
|
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))
|
if(PULSE_IS_BACKEND_HIGH_LEVEL_DEBUG(backend))
|
||||||
PulseLogInfoFmt(backend, "(Vulkan) created device from %s", device->properties.deviceName);
|
PulseLogInfoFmt(backend, "(Vulkan) created device from %s", device->properties.deviceName);
|
||||||
return pulse_device;
|
return pulse_device;
|
||||||
@@ -238,6 +241,8 @@ void VulkanDestroyDevice(PulseDevice device)
|
|||||||
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(device, VulkanDevice*);
|
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(device, VulkanDevice*);
|
||||||
if(vulkan_device == PULSE_NULLPTR || vulkan_device->device == VK_NULL_HANDLE)
|
if(vulkan_device == PULSE_NULLPTR || vulkan_device->device == VK_NULL_HANDLE)
|
||||||
return;
|
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++)
|
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);
|
vulkan_device->vkDestroyCommandPool(vulkan_device->device, vulkan_device->cmd_pools[i].pool, PULSE_NULLPTR);
|
||||||
vmaDestroyAllocator(vulkan_device->allocator);
|
vmaDestroyAllocator(vulkan_device->allocator);
|
||||||
|
|||||||
@@ -17,12 +17,16 @@
|
|||||||
#include <Pulse.h>
|
#include <Pulse.h>
|
||||||
|
|
||||||
#include "VulkanEnums.h"
|
#include "VulkanEnums.h"
|
||||||
|
#include "VulkanDescriptor.h"
|
||||||
#include "VulkanCommandPool.h"
|
#include "VulkanCommandPool.h"
|
||||||
|
|
||||||
struct VulkanQueue;
|
struct VulkanQueue;
|
||||||
|
|
||||||
typedef struct VulkanDevice
|
typedef struct VulkanDevice
|
||||||
{
|
{
|
||||||
|
VulkanDescriptorSetPoolManager descriptor_set_pool_manager;
|
||||||
|
VulkanDescriptorSetLayoutManager descriptor_set_layout_manager;
|
||||||
|
|
||||||
VulkanCommandPool* cmd_pools;
|
VulkanCommandPool* cmd_pools;
|
||||||
uint32_t cmd_pools_size;
|
uint32_t cmd_pools_size;
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdBindPipeline)
|
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdBindPipeline)
|
||||||
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdCopyBuffer)
|
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdCopyBuffer)
|
||||||
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdCopyBufferToImage)
|
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdCopyBufferToImage)
|
||||||
|
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdCopyImageToBuffer)
|
||||||
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdDispatch)
|
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdDispatch)
|
||||||
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdDispatchIndirect)
|
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdDispatchIndirect)
|
||||||
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdExecuteCommands)
|
PULSE_VULKAN_DEVICE_FUNCTION(vkCmdExecuteCommands)
|
||||||
|
|||||||
@@ -15,15 +15,6 @@ typedef enum VulkanQueueType
|
|||||||
VULKAN_QUEUE_END_ENUM // For internal use only
|
VULKAN_QUEUE_END_ENUM // For internal use only
|
||||||
} VulkanQueueType;
|
} 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_VULKAN_ENUMS_H_
|
||||||
|
|
||||||
#endif // PULSE_ENABLE_VULKAN_BACKEND
|
#endif // PULSE_ENABLE_VULKAN_BACKEND
|
||||||
|
|||||||
@@ -5,8 +5,9 @@
|
|||||||
#include "Pulse.h"
|
#include "Pulse.h"
|
||||||
#include "Vulkan.h"
|
#include "Vulkan.h"
|
||||||
#include "VulkanImage.h"
|
#include "VulkanImage.h"
|
||||||
|
#include "VulkanBuffer.h"
|
||||||
#include "VulkanDevice.h"
|
#include "VulkanDevice.h"
|
||||||
#include <vulkan/vulkan_core.h>
|
#include "VulkanCommandList.h"
|
||||||
|
|
||||||
static VkFormat PulseImageFormatToVkFormat[] = {
|
static VkFormat PulseImageFormatToVkFormat[] = {
|
||||||
VK_FORMAT_UNDEFINED, // INVALID
|
VK_FORMAT_UNDEFINED, // INVALID
|
||||||
@@ -61,12 +62,6 @@ static VkFormat PulseImageFormatToVkFormat[] = {
|
|||||||
VK_FORMAT_R32_SINT, // R32_INT
|
VK_FORMAT_R32_SINT, // R32_INT
|
||||||
VK_FORMAT_R32G32_SINT, // R32G32_INT
|
VK_FORMAT_R32G32_SINT, // R32G32_INT
|
||||||
VK_FORMAT_R32G32B32A32_SINT, // R32G32B32A32_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);
|
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)
|
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)
|
bool VulkanBlitImage(PulseCommandList cmd, const PulseImageRegion* src, const PulseImageRegion* dst)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// This file is part of "Pulse"
|
// This file is part of "Pulse"
|
||||||
// For conditions of distribution and use, see copyright notice in LICENSE
|
// For conditions of distribution and use, see copyright notice in LICENSE
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
#include "PulseDefs.h"
|
#include "PulseDefs.h"
|
||||||
#include "PulseInternal.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);
|
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);
|
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 "PulseDefs.h"
|
||||||
#include "PulseInternal.h"
|
#include "PulseInternal.h"
|
||||||
|
|
||||||
|
|
||||||
PULSE_API PulseComputePipeline PulseCreateComputePipeline(PulseDevice device, const PulseComputePipelineCreateInfo* info)
|
PULSE_API PulseComputePipeline PulseCreateComputePipeline(PulseDevice device, const PulseComputePipelineCreateInfo* info)
|
||||||
{
|
{
|
||||||
PULSE_CHECK_HANDLE_RETVAL(device, PULSE_NULL_HANDLE);
|
PULSE_CHECK_HANDLE_RETVAL(device, PULSE_NULL_HANDLE);
|
||||||
if(info == PULSE_NULLPTR && PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend))
|
if(info == PULSE_NULLPTR && PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend))
|
||||||
PulseLogError(device->backend, "null infos pointer");
|
PulseLogError(device->backend, "null infos pointer");
|
||||||
PULSE_CHECK_PTR_RETVAL(info, PULSE_NULL_HANDLE);
|
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(pipeline);
|
||||||
PULSE_CHECK_HANDLE(cmd);
|
|
||||||
|
|
||||||
if(cmd->state != PULSE_COMMAND_LIST_STATE_RECORDING)
|
PULSE_CHECK_COMMAND_LIST_STATE(pass->cmd);
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
case PULSE_COMMAND_LIST_STATE_READY:
|
pass->cmd->device->PFN_BindComputePipeline(pass, pipeline);
|
||||||
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(cmd->device->backend))
|
|
||||||
PulseLogError(cmd->device->backend, "command list is not recording");
|
|
||||||
return;
|
|
||||||
|
|
||||||
case PULSE_COMMAND_LIST_STATE_SENT:
|
pass->current_pipeline = pipeline;
|
||||||
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(cmd->device->backend))
|
|
||||||
PulseLogWarning(cmd->device->backend, "command list has already been submitted");
|
|
||||||
return;
|
|
||||||
|
|
||||||
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);
|
PULSE_API void PulseDispatchComputations(PulseComputePass pass, uint32_t groupcount_x, uint32_t groupcount_y, uint32_t groupcount_z)
|
||||||
pipeline->cmd = cmd;
|
{
|
||||||
|
PULSE_CHECK_HANDLE(pass);
|
||||||
|
|
||||||
if(cmd->compute_pipelines_bound_size == cmd->compute_pipelines_bound_capacity)
|
PULSE_CHECK_COMMAND_LIST_STATE(pass->cmd);
|
||||||
{
|
|
||||||
cmd->compute_pipelines_bound_capacity += 5;
|
pass->cmd->device->PFN_DispatchComputations(pass, groupcount_x, groupcount_y, groupcount_z);
|
||||||
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_API void PulseDestroyComputePipeline(PulseDevice device, PulseComputePipeline pipeline)
|
PULSE_API void PulseDestroyComputePipeline(PulseDevice device, PulseComputePipeline pipeline)
|
||||||
|
|||||||
@@ -62,6 +62,29 @@
|
|||||||
for(size_t defrag_i = start; defrag_i < size - 1; defrag_i++) \
|
for(size_t defrag_i = start; defrag_i < size - 1; defrag_i++) \
|
||||||
array[defrag_i] = array[defrag_i + 1]; \
|
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
|
#ifndef PULSE_STATIC_ASSERT
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L
|
||||||
@@ -81,7 +104,7 @@
|
|||||||
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyDevice, _namespace) \
|
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyDevice, _namespace) \
|
||||||
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(CreateComputePipeline, _namespace) \
|
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(CreateComputePipeline, _namespace) \
|
||||||
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyComputePipeline, _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(CreateFence, _namespace) \
|
||||||
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyFence, _namespace) \
|
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyFence, _namespace) \
|
||||||
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(IsFenceReady, _namespace) \
|
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(IsFenceReady, _namespace) \
|
||||||
@@ -100,5 +123,12 @@
|
|||||||
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(CopyImageToBuffer, _namespace) \
|
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(CopyImageToBuffer, _namespace) \
|
||||||
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(BlitImage, _namespace) \
|
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(BlitImage, _namespace) \
|
||||||
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyImage, _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_
|
#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_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)
|
PULSE_API bool PulseBlitImage(PulseCommandList cmd, const PulseImageRegion* src, const PulseImageRegion* dst)
|
||||||
|
|||||||
@@ -11,6 +11,17 @@
|
|||||||
#include "PulseDefs.h"
|
#include "PulseDefs.h"
|
||||||
#include "PulseEnums.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 uint64_t PulseThreadID;
|
||||||
|
|
||||||
typedef struct PulseBackendHandler
|
typedef struct PulseBackendHandler
|
||||||
@@ -40,11 +51,9 @@ typedef struct PulseBufferHandler
|
|||||||
typedef struct PulseCommandListHandler
|
typedef struct PulseCommandListHandler
|
||||||
{
|
{
|
||||||
PulseDevice device;
|
PulseDevice device;
|
||||||
|
PulseComputePass pass;
|
||||||
void* driver_data;
|
void* driver_data;
|
||||||
PulseThreadID thread_id;
|
PulseThreadID thread_id;
|
||||||
PulseComputePipeline* compute_pipelines_bound;
|
|
||||||
uint32_t compute_pipelines_bound_capacity;
|
|
||||||
uint32_t compute_pipelines_bound_size;
|
|
||||||
PulseCommandListState state;
|
PulseCommandListState state;
|
||||||
PulseCommandListUsage usage;
|
PulseCommandListUsage usage;
|
||||||
bool is_available;
|
bool is_available;
|
||||||
@@ -52,8 +61,12 @@ typedef struct PulseCommandListHandler
|
|||||||
|
|
||||||
typedef struct PulseComputePipelineHandler
|
typedef struct PulseComputePipelineHandler
|
||||||
{
|
{
|
||||||
PulseCommandList cmd;
|
|
||||||
void* driver_data;
|
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;
|
} PulseComputePipelineHandler;
|
||||||
|
|
||||||
typedef struct PulseDeviceHandler
|
typedef struct PulseDeviceHandler
|
||||||
@@ -61,7 +74,7 @@ typedef struct PulseDeviceHandler
|
|||||||
// PFNs
|
// PFNs
|
||||||
PulseDestroyDevicePFN PFN_DestroyDevice;
|
PulseDestroyDevicePFN PFN_DestroyDevice;
|
||||||
PulseCreateComputePipelinePFN PFN_CreateComputePipeline;
|
PulseCreateComputePipelinePFN PFN_CreateComputePipeline;
|
||||||
PulseDispatchComputePipelinePFN PFN_DispatchComputePipeline;
|
PulseDispatchComputationsPFN PFN_DispatchComputations;
|
||||||
PulseDestroyComputePipelinePFN PFN_DestroyComputePipeline;
|
PulseDestroyComputePipelinePFN PFN_DestroyComputePipeline;
|
||||||
PulseCreateFencePFN PFN_CreateFence;
|
PulseCreateFencePFN PFN_CreateFence;
|
||||||
PulseDestroyFencePFN PFN_DestroyFence;
|
PulseDestroyFencePFN PFN_DestroyFence;
|
||||||
@@ -81,6 +94,12 @@ typedef struct PulseDeviceHandler
|
|||||||
PulseCopyImageToBufferPFN PFN_CopyImageToBuffer;
|
PulseCopyImageToBufferPFN PFN_CopyImageToBuffer;
|
||||||
PulseBlitImagePFN PFN_BlitImage;
|
PulseBlitImagePFN PFN_BlitImage;
|
||||||
PulseDestroyImagePFN PFN_DestroyImage;
|
PulseDestroyImagePFN PFN_DestroyImage;
|
||||||
|
PulseBeginComputePassPFN PFN_BeginComputePass;
|
||||||
|
PulseBindStorageBuffersPFN PFN_BindStorageBuffers;
|
||||||
|
PulseBindUniformDataPFN PFN_BindUniformData;
|
||||||
|
PulseBindStorageImagesPFN PFN_BindStorageImages;
|
||||||
|
PulseBindComputePipelinePFN PFN_BindComputePipeline;
|
||||||
|
PulseEndComputePassPFN PFN_EndComputePass;
|
||||||
|
|
||||||
// Attributes
|
// Attributes
|
||||||
void* driver_data;
|
void* driver_data;
|
||||||
@@ -113,6 +132,26 @@ typedef struct PulseImageHandler
|
|||||||
uint32_t layer_count_or_depth;
|
uint32_t layer_count_or_depth;
|
||||||
} PulseImageHandler;
|
} 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();
|
PulseThreadID PulseGetThreadID();
|
||||||
|
|
||||||
void PulseSetInternalError(PulseErrorType error);
|
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 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 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
|
#ifdef PULSE_ENABLE_VULKAN_BACKEND
|
||||||
extern PulseBackendHandler VulkanDriver;
|
extern PulseBackendHandler VulkanDriver;
|
||||||
#endif // PULSE_ENABLE_VULKAN_BACKEND
|
#endif // PULSE_ENABLE_VULKAN_BACKEND
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ typedef PulseDevice (*PulseCreateDevicePFN)(PulseBackend, PulseDevice*, uint32_t
|
|||||||
|
|
||||||
typedef void (*PulseDestroyDevicePFN)(PulseDevice);
|
typedef void (*PulseDestroyDevicePFN)(PulseDevice);
|
||||||
typedef PulseComputePipeline (*PulseCreateComputePipelinePFN)(PulseDevice, const PulseComputePipelineCreateInfo*);
|
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 void (*PulseDestroyComputePipelinePFN)(PulseDevice, PulseComputePipeline);
|
||||||
typedef PulseFence (*PulseCreateFencePFN)(PulseDevice);
|
typedef PulseFence (*PulseCreateFencePFN)(PulseDevice);
|
||||||
typedef void (*PulseDestroyFencePFN)(PulseDevice, PulseFence);
|
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 (*PulseCopyBufferToImageFN)(PulseCommandList, const PulseBufferRegion*, const PulseImageRegion*);
|
||||||
typedef bool (*PulseCopyImageToBufferPFN)(PulseCommandList, const PulseImageRegion*, const PulseBufferRegion*);
|
typedef bool (*PulseCopyImageToBufferPFN)(PulseCommandList, const PulseImageRegion*, const PulseBufferRegion*);
|
||||||
typedef bool (*PulseBlitImagePFN)(PulseCommandList, const PulseImageRegion*, const PulseImageRegion*);
|
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_
|
#endif // PULSE_PFNS_H_
|
||||||
|
|||||||
@@ -36,12 +36,6 @@ void TestBufferCreation()
|
|||||||
TEST_ASSERT_NOT_EQUAL_MESSAGE(buffer, PULSE_NULL_HANDLE, PulseVerbaliseErrorType(PulseGetLastErrorType()));
|
TEST_ASSERT_NOT_EQUAL_MESSAGE(buffer, PULSE_NULL_HANDLE, PulseVerbaliseErrorType(PulseGetLastErrorType()));
|
||||||
PulseDestroyBuffer(device, buffer);
|
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.size = 1024;
|
||||||
buffer_create_info.usage = PULSE_BUFFER_USAGE_STORAGE_READ | PULSE_BUFFER_USAGE_STORAGE_WRITE;
|
buffer_create_info.usage = PULSE_BUFFER_USAGE_STORAGE_READ | PULSE_BUFFER_USAGE_STORAGE_WRITE;
|
||||||
buffer = PulseCreateBuffer(device, &buffer_create_info);
|
buffer = PulseCreateBuffer(device, &buffer_create_info);
|
||||||
|
|||||||
20
Tests/Vulkan/Pipeline.c
git.filemode.normal_file
20
Tests/Vulkan/Pipeline.c
git.filemode.normal_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);
|
||||||
|
}
|
||||||
@@ -43,7 +43,7 @@ end
|
|||||||
add_rules("mode.debug", "mode.release")
|
add_rules("mode.debug", "mode.release")
|
||||||
|
|
||||||
add_includedirs("Includes")
|
add_includedirs("Includes")
|
||||||
set_languages("c11", "cxx20")
|
set_languages("c17", "cxx20")
|
||||||
set_encodings("utf-8")
|
set_encodings("utf-8")
|
||||||
set_warnings("allextra")
|
set_warnings("allextra")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user