mirror of
https://github.com/Kbz-8/Pulse.git
synced 2026-01-11 15:33:34 +00:00
working on images, adding unit tests for image and buffers
This commit is contained in:
@@ -48,7 +48,6 @@ typedef enum PulseBufferUsageBits
|
||||
PULSE_BUFFER_USAGE_STORAGE_READ = PULSE_BIT(3),
|
||||
PULSE_BUFFER_USAGE_STORAGE_WRITE = PULSE_BIT(4),
|
||||
PULSE_BUFFER_USAGE_UNIFORM_ACCESS = PULSE_BIT(5),
|
||||
PULSE_BUFFER_USAGE_HOST_ACCESS = PULSE_BIT(6),
|
||||
} PulseShaderFormatBits;
|
||||
typedef PulseFlags PulseBufferUsageFlags;
|
||||
|
||||
@@ -190,6 +189,8 @@ typedef enum PulseImageFormat
|
||||
PULSE_IMAGE_FORMAT_BC2_RGBA_UNORM_SRGB,
|
||||
PULSE_IMAGE_FORMAT_BC3_RGBA_UNORM_SRGB,
|
||||
PULSE_IMAGE_FORMAT_BC7_RGBA_UNORM_SRGB,
|
||||
|
||||
PULSE_IMAGE_FORMAT_MAX_ENUM // For internal use only
|
||||
} PulseImageFormat;
|
||||
|
||||
// Structs
|
||||
@@ -275,6 +276,9 @@ PULSE_API PulseBuffer PulseCreateBuffer(PulseDevice device, const PulseBufferCre
|
||||
PULSE_API bool PulseGetBufferMap(PulseBuffer buffer, void** data);
|
||||
PULSE_API void PulseDestroyBuffer(PulseDevice device, PulseBuffer buffer);
|
||||
|
||||
PULSE_API PulseImage PulseCreateImage(PulseDevice device, const PulseImageCreateInfo* create_infos);
|
||||
PULSE_API void PulseDestroyImage(PulseDevice device, PulseImage image);
|
||||
|
||||
PULSE_API PulseCommandList PulseRequestCommandList(PulseDevice device, PulseCommandListUsage usage);
|
||||
PULSE_API bool PulseSubmitCommandList(PulseDevice device, PulseCommandList cmd, PulseFence fence);
|
||||
PULSE_API void PulseReleaseCommandList(PulseDevice device, PulseCommandList cmd);
|
||||
|
||||
@@ -113,6 +113,8 @@ extern "C" {
|
||||
#else
|
||||
#define PULSE_NULLPTR NULL
|
||||
#endif
|
||||
#elif defined(__cplusplus) && __cplusplus >= 201103L
|
||||
#define PULSE_NULLPTR nullptr
|
||||
#else
|
||||
#define PULSE_NULLPTR NULL
|
||||
#endif
|
||||
|
||||
@@ -3,9 +3,24 @@
|
||||
// For conditions of distribution and use, see copyright notice in LICENSE
|
||||
|
||||
#include <Pulse.h>
|
||||
#include "../../PulseInternal.h"
|
||||
|
||||
#ifdef PULSE_ENABLE_D3D11_BACKEND
|
||||
#include "D3D11.h"
|
||||
|
||||
PulseBackendFlags D3D11CheckSupport(PulseBackendFlags candidates, PulseShaderFormatsFlags shader_formats_used)
|
||||
{
|
||||
if(candidates != PULSE_BACKEND_ANY && (candidates & PULSE_BACKEND_D3D11) == 0)
|
||||
return PULSE_BACKEND_INVALID;
|
||||
if((shader_formats_used & PULSE_SHADER_FORMAT_DXBC_BIT) == 0)
|
||||
return PULSE_BACKEND_INVALID;
|
||||
return PULSE_BACKEND_INVALID; // Not supported
|
||||
}
|
||||
|
||||
|
||||
#endif // PULSE_ENABLE_D3D11_BACKEND
|
||||
PulseBackendHandler D3D11Driver = {
|
||||
.PFN_LoadBackend = PULSE_NULLPTR,
|
||||
.PFN_UnloadBackend = PULSE_NULLPTR,
|
||||
.PFN_CreateDevice = PULSE_NULLPTR,
|
||||
.backend = PULSE_BACKEND_D3D11,
|
||||
.supported_shader_formats = PULSE_SHADER_FORMAT_DXBC_BIT,
|
||||
.driver_data = PULSE_NULLPTR
|
||||
};
|
||||
|
||||
16
Sources/Backends/D3D11/D3D11.h
git.filemode.normal_file
16
Sources/Backends/D3D11/D3D11.h
git.filemode.normal_file
@@ -0,0 +1,16 @@
|
||||
// Copyright (C) 2024 kanel
|
||||
// This file is part of "Pulse"
|
||||
// For conditions of distribution and use, see copyright notice in LICENSE
|
||||
|
||||
#include <Pulse.h>
|
||||
|
||||
#ifdef PULSE_ENABLE_D3D11_BACKEND
|
||||
|
||||
#ifndef PULSE_D3D11_H_
|
||||
#define PULSE_D3D11_H_
|
||||
|
||||
PulseBackendFlags D3D11CheckSupport(PulseBackendFlags candidates, PulseShaderFormatsFlags shader_formats_used); // Return PULSE_BACKEND_VULKAN in case of success and PULSE_BACKEND_INVALID otherwise
|
||||
|
||||
#endif // PULSE_D3D11_H_
|
||||
|
||||
#endif // PULSE_ENABLE_D3D11_BACKEND
|
||||
@@ -17,13 +17,16 @@
|
||||
#define VULKAN_RETRIEVE_DRIVER_DATA_AS(handle, cast) ((cast)handle->driver_data)
|
||||
|
||||
#define CHECK_VK_RETVAL(backend, res, error, retval) \
|
||||
if((res) != VK_SUCCESS) \
|
||||
{ \
|
||||
if(backend != PULSE_NULL_HANDLE && PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(backend)) \
|
||||
PulseLogErrorFmt(backend, "(Vulkan) call to Vulkan function failed due to %s", VulkanVerbaliseResult(res)); \
|
||||
PulseSetInternalError(error); \
|
||||
return retval; \
|
||||
}
|
||||
do { \
|
||||
if((res) != VK_SUCCESS) \
|
||||
{ \
|
||||
if(backend != PULSE_NULL_HANDLE && PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(backend)) \
|
||||
PulseLogErrorFmt(backend, "(Vulkan) call to Vulkan function failed due to %s", VulkanVerbaliseResult(res)); \
|
||||
PulseSetInternalError(error); \
|
||||
return retval; \
|
||||
} \
|
||||
} while(0) \
|
||||
|
||||
#define CHECK_VK(backend, res, error) CHECK_VK_RETVAL(backend, res, error, )
|
||||
|
||||
typedef struct VulkanGlobal
|
||||
|
||||
@@ -22,20 +22,26 @@ PulseBuffer VulkanCreateBuffer(PulseDevice device, const PulseBufferCreateInfo*
|
||||
buffer->size = create_infos->size;
|
||||
buffer->usage = create_infos->usage;
|
||||
|
||||
if(buffer->usage & PULSE_BUFFER_USAGE_TRANSFER_UPLOAD)
|
||||
vulkan_buffer->usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||
if(buffer->usage & PULSE_BUFFER_USAGE_TRANSFER_DOWNLOAD)
|
||||
vulkan_buffer->usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||
if(buffer->usage & PULSE_BUFFER_USAGE_STORAGE_READ || buffer->usage & PULSE_BUFFER_USAGE_STORAGE_WRITE)
|
||||
vulkan_buffer->usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
if(buffer->usage & PULSE_BUFFER_USAGE_UNIFORM_ACCESS)
|
||||
vulkan_buffer->usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||
|
||||
VmaAllocationCreateInfo allocation_create_info = { 0 };
|
||||
allocation_create_info.usage = VMA_MEMORY_USAGE_AUTO;
|
||||
|
||||
if(buffer->usage & PULSE_BUFFER_USAGE_HOST_ACCESS)
|
||||
if(buffer->usage & PULSE_BUFFER_USAGE_STORAGE_READ || buffer->usage & PULSE_BUFFER_USAGE_STORAGE_WRITE)
|
||||
vulkan_buffer->usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
if(buffer->usage & PULSE_BUFFER_USAGE_TRANSFER_UPLOAD)
|
||||
{
|
||||
vulkan_buffer->usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||
allocation_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
||||
}
|
||||
if(buffer->usage & PULSE_BUFFER_USAGE_TRANSFER_DOWNLOAD)
|
||||
{
|
||||
vulkan_buffer->usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||
allocation_create_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
||||
}
|
||||
if(buffer->usage & PULSE_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 | VMA_ALLOCATION_CREATE_MAPPED_BIT;
|
||||
}
|
||||
|
||||
VkBufferCreateInfo buffer_create_info = { 0 };
|
||||
buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
@@ -68,4 +74,6 @@ void VulkanDestroyBuffer(PulseDevice device, PulseBuffer buffer)
|
||||
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(device, VulkanDevice*);
|
||||
VulkanBuffer* vulkan_buffer = VULKAN_RETRIEVE_DRIVER_DATA_AS(buffer, VulkanBuffer*);
|
||||
vmaDestroyBuffer(vulkan_device->allocator, vulkan_buffer->buffer, vulkan_buffer->allocation);
|
||||
free(vulkan_buffer);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
183
Sources/Backends/Vulkan/VulkanDescriptor.c
git.filemode.normal_file
183
Sources/Backends/Vulkan/VulkanDescriptor.c
git.filemode.normal_file
@@ -0,0 +1,183 @@
|
||||
// Copyright (C) 2024 kanel
|
||||
// This file is part of "Pulse"
|
||||
// For conditions of distribution and use, see copyright notice in LICENSE
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Pulse.h"
|
||||
#include "PulseProfile.h"
|
||||
#include "Vulkan.h"
|
||||
#include "VulkanDevice.h"
|
||||
#include "VulkanDescriptor.h"
|
||||
|
||||
void VulkanInitDescriptorSetPool(VulkanDescriptorSetPool* pool, PulseDevice device)
|
||||
{
|
||||
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(device, VulkanDevice*);
|
||||
memset(pool, 0, sizeof(VulkanDescriptorSetPool));
|
||||
pool->device = device;
|
||||
|
||||
VkDescriptorPoolSize pool_sizes[
|
||||
PULSE_MAX_STORAGE_TEXTURES_BOUND +
|
||||
PULSE_MAX_STORAGE_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++)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
pool_sizes[i].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
pool_sizes[i].descriptorCount = VULKAN_POOL_SIZE;
|
||||
}
|
||||
|
||||
for(uint32_t start = i; i < start + PULSE_MAX_WRITE_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_WRITE_BUFFERS_BOUND; i++)
|
||||
{
|
||||
pool_sizes[i].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
pool_sizes[i].descriptorCount = VULKAN_POOL_SIZE;
|
||||
}
|
||||
|
||||
for(uint32_t start = i; i < start + PULSE_MAX_UNIFORM_BUFFERS_BOUND; i++)
|
||||
{
|
||||
pool_sizes[i].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
|
||||
pool_sizes[i].descriptorCount = VULKAN_POOL_SIZE;
|
||||
}
|
||||
|
||||
VkDescriptorPoolCreateInfo pool_info = { 0 };
|
||||
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
pool_info.poolSizeCount = sizeof(pool_sizes) / sizeof(pool_sizes[0]);
|
||||
pool_info.pPoolSizes = pool_sizes;
|
||||
pool_info.maxSets = VULKAN_POOL_SIZE;
|
||||
pool_info.flags = 0;
|
||||
CHECK_VK(device->backend, vulkan_device->vkCreateDescriptorPool(vulkan_device->device, &pool_info, PULSE_NULLPTR, &pool->pool), PULSE_ERROR_INITIALIZATION_FAILED);
|
||||
}
|
||||
|
||||
VulkanDescriptorSet* VulkanRequestDescriptorSetFromPool(VulkanDescriptorSetPool* pool, const VulkanDescriptorSetLayout* layout)
|
||||
{
|
||||
for(size_t i = 0; i < VULKAN_POOL_SIZE; i++)
|
||||
{
|
||||
if(pool->free_sets[i] == PULSE_NULLPTR)
|
||||
break; // Due to defragmentation we are sure not to find valid sets after the first NULL one
|
||||
if(pool->free_sets[i]->layout == layout)
|
||||
{
|
||||
VulkanDescriptorSet* set = pool->free_sets[i];
|
||||
PULSE_DEFRAG_ARRAY(pool->free_sets, VULKAN_POOL_SIZE, i);
|
||||
pool->free_index--;
|
||||
pool->used_sets[pool->used_index] = (VulkanDescriptorSet*)set;
|
||||
pool->used_index++;
|
||||
return set;
|
||||
}
|
||||
}
|
||||
|
||||
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(pool->device, VulkanDevice*);
|
||||
|
||||
VulkanDescriptorSet* set = (VulkanDescriptorSet*)calloc(1, sizeof(VulkanDescriptorSet));
|
||||
PULSE_CHECK_ALLOCATION_RETVAL(set, PULSE_NULLPTR);
|
||||
|
||||
set->device = pool->device;
|
||||
set->pool = pool;
|
||||
set->layout = (VulkanDescriptorSetLayout*)layout;
|
||||
|
||||
VkDescriptorSetAllocateInfo alloc_info = { 0 };
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
alloc_info.descriptorPool = pool->pool;
|
||||
alloc_info.descriptorSetCount = 1;
|
||||
alloc_info.pSetLayouts = &layout->layout;
|
||||
CHECK_VK_RETVAL(pool->device->backend, vulkan_device->vkAllocateDescriptorSets(vulkan_device->device, &alloc_info, &set->set), PULSE_ERROR_INITIALIZATION_FAILED, PULSE_NULLPTR);
|
||||
|
||||
pool->allocations_count++;
|
||||
return set;
|
||||
}
|
||||
|
||||
void VulkanReturnDescriptorSetToPool(VulkanDescriptorSetPool* pool, const VulkanDescriptorSet* set)
|
||||
{
|
||||
for(size_t i = 0; i < VULKAN_POOL_SIZE; i++)
|
||||
{
|
||||
if(pool->used_sets[i] == PULSE_NULLPTR)
|
||||
break; // Due to defragmentation we are sure not to find valid sets after the first NULL one
|
||||
if(pool->used_sets[i] == set)
|
||||
{
|
||||
PULSE_DEFRAG_ARRAY(pool->used_sets, VULKAN_POOL_SIZE, i);
|
||||
pool->used_index--;
|
||||
pool->free_sets[pool->free_index] = (VulkanDescriptorSet*)set;
|
||||
pool->free_index++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanDestroyDescriptorSetPool(VulkanDescriptorSetPool* pool)
|
||||
{
|
||||
if(pool->pool == VK_NULL_HANDLE)
|
||||
return;
|
||||
|
||||
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(pool->device, VulkanDevice*);
|
||||
|
||||
for(size_t i = 0; i < VULKAN_POOL_SIZE; i++)
|
||||
{
|
||||
if(pool->used_sets[i] != PULSE_NULLPTR)
|
||||
{
|
||||
vulkan_device->vkDestroyDescriptorSetLayout(vulkan_device->device, pool->used_sets[i]->layout->layout, PULSE_NULLPTR);
|
||||
free(pool->used_sets[i]);
|
||||
pool->used_sets[i] = PULSE_NULLPTR;
|
||||
}
|
||||
if(pool->free_sets[i] != PULSE_NULLPTR)
|
||||
{
|
||||
vulkan_device->vkDestroyDescriptorSetLayout(vulkan_device->device, pool->free_sets[i]->layout->layout, PULSE_NULLPTR);
|
||||
free(pool->free_sets[i]);
|
||||
pool->free_sets[i] = PULSE_NULLPTR;
|
||||
}
|
||||
if(pool->free_sets[i] == PULSE_NULLPTR && pool->used_sets[i] == PULSE_NULLPTR)
|
||||
break; // Due to defragmentation we are sure not to find valid sets after the first NULL one
|
||||
}
|
||||
vulkan_device->vkDestroyDescriptorPool(vulkan_device->device, pool->pool, PULSE_NULLPTR);
|
||||
memset(pool, 0, sizeof(VulkanDescriptorSetPool));
|
||||
}
|
||||
|
||||
|
||||
void VulkanInitDescriptorSetPoolManager(VulkanDescriptorSetPoolManager* manager, PulseDevice device)
|
||||
{
|
||||
memset(manager, 0, sizeof(VulkanDescriptorSetPoolManager));
|
||||
manager->device = device;
|
||||
}
|
||||
|
||||
VulkanDescriptorSetPool* VulkanGetAvailableDescriptorSetPool(VulkanDescriptorSetPoolManager* manager)
|
||||
{
|
||||
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)
|
||||
return manager->pools[i];
|
||||
}
|
||||
PULSE_EXPAND_ARRAY_IF_NEEDED(manager->pools, VulkanDescriptorSetPool*, manager->pools_size, manager->pools_capacity, 1);
|
||||
PULSE_CHECK_ALLOCATION_RETVAL(manager->pools, PULSE_NULLPTR);
|
||||
|
||||
manager->pools[manager->pools_size] = (VulkanDescriptorSetPool*)calloc(1, sizeof(VulkanDescriptorSetPool));
|
||||
PULSE_CHECK_ALLOCATION_RETVAL(manager->pools[manager->pools_size], PULSE_NULLPTR);
|
||||
|
||||
VulkanInitDescriptorSetPool(manager->pools[manager->pools_size], manager->device);
|
||||
manager->pools_size++;
|
||||
return manager->pools[manager->pools_size - 1];
|
||||
}
|
||||
|
||||
void VulkanDestroyDescriptorSetPoolManager(VulkanDescriptorSetPoolManager* manager)
|
||||
{
|
||||
for(uint32_t i = 0; i < manager->pools_size; i++)
|
||||
{
|
||||
VulkanDestroyDescriptorSetPool(manager->pools[i]);
|
||||
free(manager->pools[i]);
|
||||
}
|
||||
free(manager->pools);
|
||||
memset(manager, 0, sizeof(VulkanDescriptorSetPoolManager));
|
||||
}
|
||||
@@ -41,6 +41,7 @@ typedef struct VulkanDescriptorSetLayout
|
||||
|
||||
typedef struct VulkanDescriptorSet
|
||||
{
|
||||
PulseDevice device;
|
||||
VulkanDescriptorSetLayout* layout;
|
||||
struct VulkanDescriptorSetPool* pool;
|
||||
VkDescriptorSet set;
|
||||
@@ -50,18 +51,27 @@ typedef struct VulkanDescriptorSetPool
|
||||
{
|
||||
VulkanDescriptorSet* used_sets[VULKAN_POOL_SIZE];
|
||||
VulkanDescriptorSet* free_sets[VULKAN_POOL_SIZE];
|
||||
uint32_t used_index;
|
||||
uint32_t free_index;
|
||||
PulseDevice device;
|
||||
VkDescriptorPool pool;
|
||||
uint32_t sets_count;
|
||||
uint32_t allocations_count;
|
||||
} VulkanDescriptorSetPool;
|
||||
|
||||
typedef struct VulkanDescriptorSetPoolManager
|
||||
{
|
||||
VulkanDescriptorSetPool* pools;
|
||||
PulseDevice device;
|
||||
VulkanDescriptorSetPool** pools;
|
||||
uint32_t pools_capacity;
|
||||
uint32_t pools_size;
|
||||
} VulkanDescriptorSetPoolManager;
|
||||
|
||||
void VulkanInitDescriptorSetPoolManager(VulkanDescriptorSetPoolManager* manager);
|
||||
void VulkanInitDescriptorSetPool(VulkanDescriptorSetPool* pool, PulseDevice device);
|
||||
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);
|
||||
void VulkanDestroyDescriptorSetPoolManager(VulkanDescriptorSetPoolManager* manager);
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "VulkanLoader.h"
|
||||
#include "VulkanQueue.h"
|
||||
#include "VulkanBuffer.h"
|
||||
#include "VulkanImage.h"
|
||||
#include "../../PulseInternal.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
PULSE_VULKAN_DEVICE_FUNCTION(vkCreateDescriptorSetLayout)
|
||||
PULSE_VULKAN_DEVICE_FUNCTION(vkCreateFence)
|
||||
PULSE_VULKAN_DEVICE_FUNCTION(vkCreateImage)
|
||||
PULSE_VULKAN_DEVICE_FUNCTION(vkCreateImageView)
|
||||
PULSE_VULKAN_DEVICE_FUNCTION(vkCreatePipelineCache)
|
||||
PULSE_VULKAN_DEVICE_FUNCTION(vkCreatePipelineLayout)
|
||||
PULSE_VULKAN_DEVICE_FUNCTION(vkCreateSemaphore)
|
||||
@@ -45,6 +46,7 @@
|
||||
PULSE_VULKAN_DEVICE_FUNCTION(vkDestroyDevice)
|
||||
PULSE_VULKAN_DEVICE_FUNCTION(vkDestroyFence)
|
||||
PULSE_VULKAN_DEVICE_FUNCTION(vkDestroyImage)
|
||||
PULSE_VULKAN_DEVICE_FUNCTION(vkDestroyImageView)
|
||||
PULSE_VULKAN_DEVICE_FUNCTION(vkDestroyPipeline)
|
||||
PULSE_VULKAN_DEVICE_FUNCTION(vkDestroyPipelineCache)
|
||||
PULSE_VULKAN_DEVICE_FUNCTION(vkDestroyPipelineLayout)
|
||||
|
||||
191
Sources/Backends/Vulkan/VulkanImage.c
git.filemode.normal_file
191
Sources/Backends/Vulkan/VulkanImage.c
git.filemode.normal_file
@@ -0,0 +1,191 @@
|
||||
// Copyright (C) 2024 kanel
|
||||
// This file is part of "Pulse"
|
||||
// For conditions of distribution and use, see copyright notice in LICENSE
|
||||
|
||||
#include "Pulse.h"
|
||||
#include "Vulkan.h"
|
||||
#include "VulkanImage.h"
|
||||
#include "VulkanDevice.h"
|
||||
|
||||
static VkFormat PulseImageFormatToVkFormat[] = {
|
||||
VK_FORMAT_UNDEFINED, // INVALID
|
||||
VK_FORMAT_R8_UNORM, // A8_UNORM
|
||||
VK_FORMAT_R8_UNORM, // R8_UNORM
|
||||
VK_FORMAT_R8G8_UNORM, // R8G8_UNORM
|
||||
VK_FORMAT_R8G8B8A8_UNORM, // R8G8B8A8_UNORM
|
||||
VK_FORMAT_R16_UNORM, // R16_UNORM
|
||||
VK_FORMAT_R16G16_UNORM, // R16G16_UNORM
|
||||
VK_FORMAT_R16G16B16A16_UNORM, // R16G16B16A16_UNORM
|
||||
VK_FORMAT_A2B10G10R10_UNORM_PACK32, // R10G10B10A2_UNORM
|
||||
VK_FORMAT_R5G6B5_UNORM_PACK16, // B5G6R5_UNORM
|
||||
VK_FORMAT_A1R5G5B5_UNORM_PACK16, // B5G5R5A1_UNORM
|
||||
VK_FORMAT_B4G4R4A4_UNORM_PACK16, // B4G4R4A4_UNORM
|
||||
VK_FORMAT_B8G8R8A8_UNORM, // B8G8R8A8_UNORM
|
||||
VK_FORMAT_BC1_RGBA_UNORM_BLOCK, // BC1_UNORM
|
||||
VK_FORMAT_BC2_UNORM_BLOCK, // BC2_UNORM
|
||||
VK_FORMAT_BC3_UNORM_BLOCK, // BC3_UNORM
|
||||
VK_FORMAT_BC4_UNORM_BLOCK, // BC4_UNORM
|
||||
VK_FORMAT_BC5_UNORM_BLOCK, // BC5_UNORM
|
||||
VK_FORMAT_BC7_UNORM_BLOCK, // BC7_UNORM
|
||||
VK_FORMAT_BC6H_SFLOAT_BLOCK, // BC6H_FLOAT
|
||||
VK_FORMAT_BC6H_UFLOAT_BLOCK, // BC6H_UFLOAT
|
||||
VK_FORMAT_R8_SNORM, // R8_SNORM
|
||||
VK_FORMAT_R8G8_SNORM, // R8G8_SNORM
|
||||
VK_FORMAT_R8G8B8A8_SNORM, // R8G8B8A8_SNORM
|
||||
VK_FORMAT_R16_SNORM, // R16_SNORM
|
||||
VK_FORMAT_R16G16_SNORM, // R16G16_SNORM
|
||||
VK_FORMAT_R16G16B16A16_SNORM, // R16G16B16A16_SNORM
|
||||
VK_FORMAT_R16_SFLOAT, // R16_FLOAT
|
||||
VK_FORMAT_R16G16_SFLOAT, // R16G16_FLOAT
|
||||
VK_FORMAT_R16G16B16A16_SFLOAT, // R16G16B16A16_FLOAT
|
||||
VK_FORMAT_R32_SFLOAT, // R32_FLOAT
|
||||
VK_FORMAT_R32G32_SFLOAT, // R32G32_FLOAT
|
||||
VK_FORMAT_R32G32B32A32_SFLOAT, // R32G32B32A32_FLOAT
|
||||
VK_FORMAT_B10G11R11_UFLOAT_PACK32, // R11G11B10_UFLOAT
|
||||
VK_FORMAT_R8_UINT, // R8_UINT
|
||||
VK_FORMAT_R8G8_UINT, // R8G8_UINT
|
||||
VK_FORMAT_R8G8B8A8_UINT, // R8G8B8A8_UINT
|
||||
VK_FORMAT_R16_UINT, // R16_UINT
|
||||
VK_FORMAT_R16G16_UINT, // R16G16_UINT
|
||||
VK_FORMAT_R16G16B16A16_UINT, // R16G16B16A16_UINT
|
||||
VK_FORMAT_R32_UINT, // R32_UINT
|
||||
VK_FORMAT_R32G32_UINT, // R32G32_UINT
|
||||
VK_FORMAT_R32G32B32A32_UINT, // R32G32B32A32_UINT
|
||||
VK_FORMAT_R8_SINT, // R8_INT
|
||||
VK_FORMAT_R8G8_SINT, // R8G8_INT
|
||||
VK_FORMAT_R8G8B8A8_SINT, // R8G8B8A8_INT
|
||||
VK_FORMAT_R16_SINT, // R16_INT
|
||||
VK_FORMAT_R16G16_SINT, // R16G16_INT
|
||||
VK_FORMAT_R16G16B16A16_SINT, // R16G16B16A16_INT
|
||||
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);
|
||||
|
||||
static VkComponentMapping SwizzleForFormat(PulseImageFormat format)
|
||||
{
|
||||
if(format == PULSE_IMAGE_FORMAT_A8_UNORM)
|
||||
{
|
||||
return (VkComponentMapping){
|
||||
VK_COMPONENT_SWIZZLE_ZERO,
|
||||
VK_COMPONENT_SWIZZLE_ZERO,
|
||||
VK_COMPONENT_SWIZZLE_ZERO,
|
||||
VK_COMPONENT_SWIZZLE_R
|
||||
};
|
||||
}
|
||||
|
||||
if(format == PULSE_IMAGE_FORMAT_B4G4R4A4_UNORM)
|
||||
{
|
||||
return (VkComponentMapping){
|
||||
VK_COMPONENT_SWIZZLE_G,
|
||||
VK_COMPONENT_SWIZZLE_R,
|
||||
VK_COMPONENT_SWIZZLE_A,
|
||||
VK_COMPONENT_SWIZZLE_B
|
||||
};
|
||||
}
|
||||
|
||||
return (VkComponentMapping){
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY
|
||||
};
|
||||
}
|
||||
|
||||
PulseImage VulkanCreateImage(PulseDevice device, const PulseImageCreateInfo* create_infos)
|
||||
{
|
||||
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(device, VulkanDevice*);
|
||||
|
||||
PulseImageHandler* image = (PulseImageHandler*)calloc(1, sizeof(PulseImageHandler));
|
||||
PULSE_CHECK_ALLOCATION_RETVAL(image, PULSE_NULL_HANDLE);
|
||||
|
||||
VulkanImage* vulkan_image = (VulkanImage*)calloc(1, sizeof(VulkanImage));
|
||||
PULSE_CHECK_ALLOCATION_RETVAL(vulkan_image, PULSE_NULL_HANDLE);
|
||||
|
||||
uint32_t layer_count = (create_infos->type == PULSE_IMAGE_TYPE_3D) ? 1 : create_infos->layer_count_or_depth;
|
||||
uint32_t depth = (create_infos->type == PULSE_IMAGE_TYPE_3D) ? create_infos->layer_count_or_depth : 1;
|
||||
|
||||
image->device = device;
|
||||
image->driver_data = vulkan_image;
|
||||
image->usage = create_infos->usage;
|
||||
|
||||
VmaAllocationCreateInfo allocation_create_info = { 0 };
|
||||
allocation_create_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
|
||||
|
||||
VkImageCreateFlags flags = 0;
|
||||
|
||||
if(create_infos->type == PULSE_IMAGE_TYPE_CUBE || create_infos->type == PULSE_IMAGE_TYPE_CUBE_ARRAY)
|
||||
flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
|
||||
else if(create_infos->type == PULSE_IMAGE_TYPE_3D)
|
||||
flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
|
||||
|
||||
VkImageCreateInfo image_info = { 0 };
|
||||
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
image_info.imageType = VK_IMAGE_TYPE_2D;
|
||||
image_info.extent.width = create_infos->width;
|
||||
image_info.extent.height = create_infos->height;
|
||||
image_info.extent.depth = depth;
|
||||
image_info.mipLevels = 1;
|
||||
image_info.arrayLayers = layer_count;
|
||||
image_info.format = PulseImageFormatToVkFormat[create_infos->format];
|
||||
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
image_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
|
||||
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
image_info.flags = flags;
|
||||
|
||||
VkImageCreateInfo image_create_info = { 0 };
|
||||
image_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
image_create_info.usage = vulkan_image->usage;
|
||||
image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
|
||||
CHECK_VK_RETVAL(device->backend, vmaCreateImage(vulkan_device->allocator, &image_create_info, &allocation_create_info, &vulkan_image->image, &vulkan_image->allocation, PULSE_NULLPTR), PULSE_ERROR_INITIALIZATION_FAILED, PULSE_NULL_HANDLE);
|
||||
vmaGetAllocationInfo(vulkan_device->allocator, vulkan_image->allocation, &vulkan_image->allocation_info);
|
||||
|
||||
if(create_infos->usage & PULSE_IMAGE_USAGE_STORAGE_READ)
|
||||
{
|
||||
VkImageViewCreateInfo image_view_create_info = { 0 };
|
||||
image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
image_view_create_info.image = vulkan_image->image;
|
||||
image_view_create_info.format = PulseImageFormatToVkFormat[create_infos->format];
|
||||
image_view_create_info.components = SwizzleForFormat(create_infos->format);
|
||||
image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
image_view_create_info.subresourceRange.baseMipLevel = 0;
|
||||
image_view_create_info.subresourceRange.levelCount = 1;
|
||||
image_view_create_info.subresourceRange.baseArrayLayer = 0;
|
||||
image_view_create_info.subresourceRange.layerCount = layer_count;
|
||||
|
||||
if(create_infos->type == PULSE_IMAGE_TYPE_CUBE)
|
||||
image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
|
||||
else if(create_infos->type == PULSE_IMAGE_TYPE_CUBE_ARRAY)
|
||||
image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
|
||||
else if(create_infos->type == PULSE_IMAGE_TYPE_3D)
|
||||
image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_3D;
|
||||
else if(create_infos->type == PULSE_IMAGE_TYPE_2D_ARRAY)
|
||||
image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
else
|
||||
image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
|
||||
CHECK_VK_RETVAL(device->backend, vulkan_device->vkCreateImageView(vulkan_device->device, &image_view_create_info, PULSE_NULLPTR, &vulkan_image->view), PULSE_ERROR_INITIALIZATION_FAILED, PULSE_NULL_HANDLE);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
void VulkanDestroyImage(PulseDevice device, PulseImage image)
|
||||
{
|
||||
VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(device, VulkanDevice*);
|
||||
VulkanImage* vulkan_image = VULKAN_RETRIEVE_DRIVER_DATA_AS(image, VulkanImage*);
|
||||
vulkan_device->vkDestroyImageView(vulkan_device->device, vulkan_image->view, PULSE_NULLPTR);
|
||||
vmaDestroyImage(vulkan_device->allocator, vulkan_image->image, vulkan_image->allocation);
|
||||
free(vulkan_image);
|
||||
free(image);
|
||||
}
|
||||
31
Sources/Backends/Vulkan/VulkanImage.h
git.filemode.normal_file
31
Sources/Backends/Vulkan/VulkanImage.h
git.filemode.normal_file
@@ -0,0 +1,31 @@
|
||||
// Copyright (C) 2024 kanel
|
||||
// This file is part of "Pulse"
|
||||
// For conditions of distribution and use, see copyright notice in LICENSE
|
||||
|
||||
#ifdef PULSE_ENABLE_VULKAN_BACKEND
|
||||
|
||||
#ifndef PULSE_VULKAN_IMAGE_H_
|
||||
#define PULSE_VULKAN_IMAGE_H_
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include <vk_mem_alloc.h>
|
||||
|
||||
#include <Pulse.h>
|
||||
#include "../../PulseInternal.h"
|
||||
#include "VulkanEnums.h"
|
||||
|
||||
typedef struct VulkanImage
|
||||
{
|
||||
VkImage image;
|
||||
VkImageView view;
|
||||
VkImageUsageFlags usage;
|
||||
VmaAllocation allocation;
|
||||
VmaAllocationInfo allocation_info;
|
||||
} VulkanImage;
|
||||
|
||||
PulseImage VulkanCreateImage(PulseDevice device, const PulseImageCreateInfo* create_infos);
|
||||
void VulkanDestroyImage(PulseDevice device, PulseImage image);
|
||||
|
||||
#endif // PULSE_VULKAN_IMAGE_H_
|
||||
|
||||
#endif // PULSE_ENABLE_VULKAN_BACKEND
|
||||
@@ -49,6 +49,33 @@
|
||||
|
||||
#define PULSE_CHECK_PTR(handle) PULSE_CHECK_PTR_RETVAL(handle, )
|
||||
|
||||
#define PULSE_EXPAND_ARRAY_IF_NEEDED(array, T, size, capacity, increase) \
|
||||
do { \
|
||||
if(size >= capacity) \
|
||||
{ \
|
||||
capacity += increase; \
|
||||
array = (T*)realloc(array, sizeof(T) * capacity); \
|
||||
} \
|
||||
} while(0); \
|
||||
|
||||
#define PULSE_DEFRAG_ARRAY(array, size, start) \
|
||||
for(size_t defrag_i = start; defrag_i < size - 1; defrag_i++) \
|
||||
array[defrag_i] = array[defrag_i + 1]; \
|
||||
|
||||
#ifndef PULSE_STATIC_ASSERT
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus >= 201103L
|
||||
#define PULSE_STATIC_ASSERT(name, x) static_assert(x, #x)
|
||||
#endif
|
||||
#elif PULSE_C_VERSION >= 2023
|
||||
#define PULSE_STATIC_ASSERT(name, x) static_assert(x, #x)
|
||||
#elif PULSE_C_VERSION >= 2011
|
||||
#define PULSE_STATIC_ASSERT(name, x) _Static_assert(x, #x)
|
||||
#else
|
||||
#define PULSE_STATIC_ASSERT(name, x) typedef int pulse_static_assert_##name[(x) ? 1 : -1]
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define PULSE_LOAD_DRIVER_DEVICE_FUNCTION(fn, _namespace) pulse_device->PFN_##fn = _namespace##fn;
|
||||
#define PULSE_LOAD_DRIVER_DEVICE(_namespace) \
|
||||
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyDevice, _namespace) \
|
||||
@@ -65,5 +92,7 @@
|
||||
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(CreateBuffer, _namespace) \
|
||||
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(GetBufferMap, _namespace) \
|
||||
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyBuffer, _namespace) \
|
||||
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(CreateImage, _namespace) \
|
||||
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyImage, _namespace) \
|
||||
|
||||
#endif // PULSE_DEFS_H_
|
||||
|
||||
35
Sources/PulseImage.c
git.filemode.normal_file
35
Sources/PulseImage.c
git.filemode.normal_file
@@ -0,0 +1,35 @@
|
||||
// Copyright (C) 2024 kanel
|
||||
// This file is part of "Pulse"
|
||||
// For conditions of distribution and use, see copyright notice in LICENSE
|
||||
|
||||
#include "Pulse.h"
|
||||
#include "PulseDefs.h"
|
||||
#include "PulseInternal.h"
|
||||
|
||||
PULSE_API PulseImage PulseCreateImage(PulseDevice device, const PulseImageCreateInfo* create_infos)
|
||||
{
|
||||
PULSE_CHECK_HANDLE_RETVAL(device, PULSE_NULL_HANDLE);
|
||||
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend))
|
||||
{
|
||||
if(create_infos == PULSE_NULLPTR)
|
||||
{
|
||||
PulseLogError(device->backend, "create_infos is NULL");
|
||||
PulseSetInternalError(PULSE_ERROR_INITIALIZATION_FAILED);
|
||||
return PULSE_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
return device->PFN_CreateImage(device, create_infos);
|
||||
}
|
||||
|
||||
PULSE_API void PulseDestroyImage(PulseDevice device, PulseImage image)
|
||||
{
|
||||
PULSE_CHECK_HANDLE(device);
|
||||
|
||||
if(image == PULSE_NULL_HANDLE)
|
||||
{
|
||||
if(PULSE_IS_BACKEND_LOW_LEVEL_DEBUG(device->backend))
|
||||
PulseLogWarning(device->backend, "image is NULL, this may be a bug in your application");
|
||||
return;
|
||||
}
|
||||
return device->PFN_DestroyImage(device, image);
|
||||
}
|
||||
@@ -72,6 +72,8 @@ typedef struct PulseDeviceHandler
|
||||
PulseCreateBufferPFN PFN_CreateBuffer;
|
||||
PulseGetBufferMapPFN PFN_GetBufferMap;
|
||||
PulseDestroyBufferPFN PFN_DestroyBuffer;
|
||||
PulseCreateImagePFN PFN_CreateImage;
|
||||
PulseDestroyImagePFN PFN_DestroyImage;
|
||||
|
||||
// Attributes
|
||||
void* driver_data;
|
||||
@@ -86,7 +88,9 @@ typedef struct PulseFenceHandler
|
||||
|
||||
typedef struct PulseImageHandler
|
||||
{
|
||||
PulseDevice device;
|
||||
void* driver_data;
|
||||
PulseImageUsageFlags usage;
|
||||
} PulseImageHandler;
|
||||
|
||||
PulseThreadID PulseGetThreadID();
|
||||
@@ -103,6 +107,12 @@ 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
|
||||
|
||||
@@ -27,5 +27,7 @@ typedef void (*PulseReleaseCommandListPFN)(PulseDevice, PulseCommandList);
|
||||
typedef PulseBuffer (*PulseCreateBufferPFN)(PulseDevice, const PulseBufferCreateInfo*);
|
||||
typedef bool (*PulseGetBufferMapPFN)(PulseBuffer, void**);
|
||||
typedef void (*PulseDestroyBufferPFN)(PulseDevice, PulseBuffer);
|
||||
typedef PulseImage (*PulseCreateImagePFN)(PulseDevice, const PulseImageCreateInfo*);
|
||||
typedef void (*PulseDestroyImagePFN)(PulseDevice, PulseImage);
|
||||
|
||||
#endif // PULSE_PFNS_H_
|
||||
|
||||
77
Tests/Vulkan/Buffer.c
git.filemode.normal_file
77
Tests/Vulkan/Buffer.c
git.filemode.normal_file
@@ -0,0 +1,77 @@
|
||||
#include "Common.h"
|
||||
|
||||
#include <unity/unity.h>
|
||||
#include <Pulse.h>
|
||||
|
||||
void TestBufferCreation()
|
||||
{
|
||||
PulseBackend backend;
|
||||
SetupPulse(&backend);
|
||||
PulseDevice device;
|
||||
SetupDevice(backend, &device);
|
||||
|
||||
PulseBufferCreateInfo buffer_create_info = { 0 };
|
||||
buffer_create_info.size = 1024;
|
||||
buffer_create_info.usage = PULSE_BUFFER_USAGE_STORAGE_READ;
|
||||
PulseBuffer buffer = PulseCreateBuffer(device, &buffer_create_info);
|
||||
TEST_ASSERT_NOT_EQUAL_MESSAGE(buffer, PULSE_NULL_HANDLE, PulseVerbaliseErrorType(PulseGetLastErrorType()));
|
||||
PulseDestroyBuffer(device, buffer);
|
||||
|
||||
buffer_create_info.size = 1024;
|
||||
buffer_create_info.usage = PULSE_BUFFER_USAGE_STORAGE_WRITE;
|
||||
buffer = PulseCreateBuffer(device, &buffer_create_info);
|
||||
TEST_ASSERT_NOT_EQUAL_MESSAGE(buffer, PULSE_NULL_HANDLE, PulseVerbaliseErrorType(PulseGetLastErrorType()));
|
||||
PulseDestroyBuffer(device, buffer);
|
||||
|
||||
buffer_create_info.size = 1024;
|
||||
buffer_create_info.usage = PULSE_BUFFER_USAGE_TRANSFER_DOWNLOAD;
|
||||
buffer = PulseCreateBuffer(device, &buffer_create_info);
|
||||
TEST_ASSERT_NOT_EQUAL_MESSAGE(buffer, PULSE_NULL_HANDLE, PulseVerbaliseErrorType(PulseGetLastErrorType()));
|
||||
PulseDestroyBuffer(device, buffer);
|
||||
|
||||
buffer_create_info.size = 1024;
|
||||
buffer_create_info.usage = PULSE_BUFFER_USAGE_TRANSFER_UPLOAD;
|
||||
buffer = PulseCreateBuffer(device, &buffer_create_info);
|
||||
TEST_ASSERT_NOT_EQUAL_MESSAGE(buffer, PULSE_NULL_HANDLE, PulseVerbaliseErrorType(PulseGetLastErrorType()));
|
||||
PulseDestroyBuffer(device, buffer);
|
||||
|
||||
buffer_create_info.size = 1024;
|
||||
buffer_create_info.usage = PULSE_BUFFER_USAGE_UNIFORM_ACCESS;
|
||||
buffer = PulseCreateBuffer(device, &buffer_create_info);
|
||||
TEST_ASSERT_NOT_EQUAL_MESSAGE(buffer, PULSE_NULL_HANDLE, PulseVerbaliseErrorType(PulseGetLastErrorType()));
|
||||
PulseDestroyBuffer(device, buffer);
|
||||
|
||||
buffer_create_info.size = 1024;
|
||||
buffer_create_info.usage = PULSE_BUFFER_USAGE_STORAGE_READ | PULSE_BUFFER_USAGE_STORAGE_WRITE;
|
||||
buffer = PulseCreateBuffer(device, &buffer_create_info);
|
||||
TEST_ASSERT_NOT_EQUAL_MESSAGE(buffer, PULSE_NULL_HANDLE, PulseVerbaliseErrorType(PulseGetLastErrorType()));
|
||||
PulseDestroyBuffer(device, buffer);
|
||||
|
||||
buffer_create_info.size = 1024;
|
||||
buffer_create_info.usage = PULSE_BUFFER_USAGE_STORAGE_WRITE | PULSE_BUFFER_USAGE_TRANSFER_UPLOAD;
|
||||
buffer = PulseCreateBuffer(device, &buffer_create_info);
|
||||
TEST_ASSERT_NOT_EQUAL_MESSAGE(buffer, PULSE_NULL_HANDLE, PulseVerbaliseErrorType(PulseGetLastErrorType()));
|
||||
PulseDestroyBuffer(device, buffer);
|
||||
|
||||
buffer_create_info.size = 1024;
|
||||
buffer_create_info.usage = PULSE_BUFFER_USAGE_STORAGE_READ | PULSE_BUFFER_USAGE_STORAGE_WRITE | PULSE_BUFFER_USAGE_TRANSFER_DOWNLOAD | PULSE_BUFFER_USAGE_TRANSFER_UPLOAD;
|
||||
buffer = PulseCreateBuffer(device, &buffer_create_info);
|
||||
TEST_ASSERT_NOT_EQUAL_MESSAGE(buffer, PULSE_NULL_HANDLE, PulseVerbaliseErrorType(PulseGetLastErrorType()));
|
||||
PulseDestroyBuffer(device, buffer);
|
||||
|
||||
DISABLE_ERRORS;
|
||||
buffer_create_info.size = -1;
|
||||
buffer_create_info.usage = PULSE_BUFFER_USAGE_STORAGE_READ;
|
||||
buffer = PulseCreateBuffer(device, &buffer_create_info);
|
||||
TEST_ASSERT_EQUAL(buffer, PULSE_NULL_HANDLE);
|
||||
PulseDestroyBuffer(device, buffer);
|
||||
ENABLE_ERRORS;
|
||||
|
||||
CleanupDevice(device);
|
||||
CleanupPulse(backend);
|
||||
}
|
||||
|
||||
void TestBuffer()
|
||||
{
|
||||
RUN_TEST(TestBufferCreation);
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
#include "Common.h"
|
||||
#include <unity/unity.h>
|
||||
|
||||
bool errors_enabled = true;
|
||||
|
||||
void DebugCallBack(PulseDebugMessageSeverity severity, const char* message)
|
||||
{
|
||||
if(severity == PULSE_DEBUG_MESSAGE_SEVERITY_ERROR)
|
||||
if(errors_enabled && severity == PULSE_DEBUG_MESSAGE_SEVERITY_ERROR)
|
||||
TEST_FAIL_MESSAGE(message);
|
||||
}
|
||||
|
||||
@@ -22,6 +24,17 @@ void SetupPulse(PulseBackend* backend)
|
||||
PulseSetDebugCallback(*backend, DebugCallBack);
|
||||
}
|
||||
|
||||
void SetupDevice(PulseBackend backend, PulseDevice* device)
|
||||
{
|
||||
*device = PulseCreateDevice(backend, NULL, 0);
|
||||
TEST_ASSERT_NOT_EQUAL_MESSAGE(device, PULSE_NULL_HANDLE, PulseVerbaliseErrorType(PulseGetLastErrorType()));
|
||||
}
|
||||
|
||||
void CleanupDevice(PulseDevice device)
|
||||
{
|
||||
PulseDestroyDevice(device);
|
||||
}
|
||||
|
||||
void CleanupPulse(PulseBackend backend)
|
||||
{
|
||||
PulseUnloadBackend(backend);
|
||||
|
||||
@@ -19,8 +19,14 @@
|
||||
|
||||
#include <Pulse.h>
|
||||
|
||||
extern bool errors_enabled;
|
||||
#define DISABLE_ERRORS errors_enabled = false
|
||||
#define ENABLE_ERRORS errors_enabled = true
|
||||
|
||||
void DebugCallBack(PulseDebugMessageSeverity severity, const char* message);
|
||||
void SetupPulse(PulseBackend* backend);
|
||||
void SetupDevice(PulseBackend backend, PulseDevice* device);
|
||||
void CleanupDevice(PulseDevice device);
|
||||
void CleanupPulse(PulseBackend backend);
|
||||
|
||||
#endif
|
||||
|
||||
30
Tests/Vulkan/Image.c
git.filemode.normal_file
30
Tests/Vulkan/Image.c
git.filemode.normal_file
@@ -0,0 +1,30 @@
|
||||
#include "Common.h"
|
||||
|
||||
#include <unity/unity.h>
|
||||
#include <Pulse.h>
|
||||
|
||||
void TestImageCreation()
|
||||
{
|
||||
PulseBackend backend;
|
||||
SetupPulse(&backend);
|
||||
PulseDevice device;
|
||||
SetupDevice(backend, &device);
|
||||
|
||||
PulseImageCreateInfo image_create_info = { 0 };
|
||||
image_create_info.type = PULSE_IMAGE_TYPE_2D;
|
||||
image_create_info.format = PULSE_IMAGE_FORMAT_R8G8B8A8_UNORM;
|
||||
image_create_info.usage = PULSE_IMAGE_USAGE_STORAGE_READ;
|
||||
image_create_info.width = 256;
|
||||
image_create_info.height = 256;
|
||||
PulseImage image = PulseCreateImage(device, &image_create_info);
|
||||
TEST_ASSERT_NOT_EQUAL_MESSAGE(image, PULSE_NULL_HANDLE, PulseVerbaliseErrorType(PulseGetLastErrorType()));
|
||||
PulseDestroyImage(device, image);
|
||||
|
||||
CleanupDevice(device);
|
||||
CleanupPulse(backend);
|
||||
}
|
||||
|
||||
void TestImage()
|
||||
{
|
||||
RUN_TEST(TestImageCreation);
|
||||
}
|
||||
@@ -5,11 +5,15 @@
|
||||
|
||||
extern void TestBackend();
|
||||
extern void TestDevice();
|
||||
extern void TestBuffer();
|
||||
extern void TestImage();
|
||||
|
||||
int main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
TestBackend();
|
||||
TestDevice();
|
||||
TestBuffer();
|
||||
TestImage();
|
||||
return UNITY_END();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user