mirror of
https://github.com/Kbz-8/Pulse.git
synced 2026-01-11 15:33:34 +00:00
adding Vulkan device creation, adding unit tests, adding few API function declarations
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,6 +7,7 @@
|
|||||||
!/Includes/
|
!/Includes/
|
||||||
!/Sources/
|
!/Sources/
|
||||||
!/Tests/
|
!/Tests/
|
||||||
|
!/Examples/
|
||||||
!/.github/
|
!/.github/
|
||||||
build/
|
build/
|
||||||
Build/
|
Build/
|
||||||
|
|||||||
23
Examples/Vulkan/main.c
git.filemode.normal_file
23
Examples/Vulkan/main.c
git.filemode.normal_file
@@ -0,0 +1,23 @@
|
|||||||
|
#include <Pulse.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define CHECK_PULSE_HANDLE_RETVAL(handle, retval) \
|
||||||
|
if(handle == PULSE_NULL_HANDLE) \
|
||||||
|
{ \
|
||||||
|
fprintf(stderr, "Error: %s", PulseVerbaliseErrorType(PulseGetLastErrorType())); \
|
||||||
|
return retval; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
PulseBackend backend = PulseLoadBackend(PULSE_BACKEND_VULKAN, PULSE_SHADER_FORMAT_SPIRV_BIT, PULSE_NO_DEBUG);
|
||||||
|
CHECK_PULSE_HANDLE_RETVAL(backend, 1);
|
||||||
|
PulseDevice device = PulseCreateDevice(backend, NULL, 0);
|
||||||
|
CHECK_PULSE_HANDLE_RETVAL(device, 1);
|
||||||
|
|
||||||
|
PulseDestroyDevice(device);
|
||||||
|
PulseUnloadBackend(backend);
|
||||||
|
puts("Successfully loaded Pulse using Vulkan !");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
target("LoadingPulse")
|
target("VulkanExample")
|
||||||
add_deps("pulse_gpu")
|
add_deps("pulse_gpu")
|
||||||
if is_plat("linux") then
|
if is_plat("linux") then
|
||||||
set_extension(".x86_64")
|
set_extension(".x86_64")
|
||||||
end
|
end
|
||||||
add_files("main.c")
|
add_files("*.c")
|
||||||
target_end()
|
target_end()
|
||||||
7
Examples/xmake.lua
git.filemode.normal_file
7
Examples/xmake.lua
git.filemode.normal_file
@@ -0,0 +1,7 @@
|
|||||||
|
option("examples", { description = "Build the examples", default = false })
|
||||||
|
|
||||||
|
if has_config("examples") then
|
||||||
|
set_group("Examples")
|
||||||
|
includes("*/xmake.lua")
|
||||||
|
end
|
||||||
|
|
||||||
@@ -27,9 +27,9 @@ PULSE_DEFINE_NULLABLE_HANDLE(PulseBuffer);
|
|||||||
PULSE_DEFINE_NULLABLE_HANDLE(PulseCommandList);
|
PULSE_DEFINE_NULLABLE_HANDLE(PulseCommandList);
|
||||||
PULSE_DEFINE_NULLABLE_HANDLE(PulseComputePass);
|
PULSE_DEFINE_NULLABLE_HANDLE(PulseComputePass);
|
||||||
PULSE_DEFINE_NULLABLE_HANDLE(PulseComputePipeline);
|
PULSE_DEFINE_NULLABLE_HANDLE(PulseComputePipeline);
|
||||||
PULSE_DEFINE_NULLABLE_HANDLE(PulseCopyPass);
|
|
||||||
PULSE_DEFINE_NULLABLE_HANDLE(PulseDevice);
|
PULSE_DEFINE_NULLABLE_HANDLE(PulseDevice);
|
||||||
PULSE_DEFINE_NULLABLE_HANDLE(PulseFence);
|
PULSE_DEFINE_NULLABLE_HANDLE(PulseFence);
|
||||||
|
PULSE_DEFINE_NULLABLE_HANDLE(PulseGeneralPass);
|
||||||
PULSE_DEFINE_NULLABLE_HANDLE(PulseImage);
|
PULSE_DEFINE_NULLABLE_HANDLE(PulseImage);
|
||||||
|
|
||||||
// Flags
|
// Flags
|
||||||
@@ -83,6 +83,19 @@ typedef enum PulseDebugLevel
|
|||||||
PULSE_PARANOID_DEBUG // Causes every warning to be treated as error
|
PULSE_PARANOID_DEBUG // Causes every warning to be treated as error
|
||||||
} PulseDebugLevel;
|
} PulseDebugLevel;
|
||||||
|
|
||||||
|
typedef enum PulseDebugMessageSeverity
|
||||||
|
{
|
||||||
|
PULSE_DEBUG_MESSAGE_SEVERITY_INFO,
|
||||||
|
PULSE_DEBUG_MESSAGE_SEVERITY_WARNING,
|
||||||
|
PULSE_DEBUG_MESSAGE_SEVERITY_ERROR
|
||||||
|
} PulseDebugMessageSeverity;
|
||||||
|
|
||||||
|
typedef enum PulseDebugMessageType
|
||||||
|
{
|
||||||
|
PULSE_DEBUG_MESSAGE_TYPE_GENERAL,
|
||||||
|
PULSE_DEBUG_MESSAGE_TYPE_PERFORMANCE
|
||||||
|
} PulseDebugMessageType;
|
||||||
|
|
||||||
typedef enum PulseErrorType
|
typedef enum PulseErrorType
|
||||||
{
|
{
|
||||||
PULSE_ERROR_NONE,
|
PULSE_ERROR_NONE,
|
||||||
@@ -250,14 +263,37 @@ typedef struct PulseImageRegion
|
|||||||
} PulseImageRegion;
|
} PulseImageRegion;
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
|
typedef void (*PulseDebugCallbackPFN)(PulseDebugMessageSeverity, PulseDebugMessageType, const char*);
|
||||||
|
|
||||||
PULSE_API PulseBackend PulseLoadBackend(PulseBackendFlags backend_candidates, PulseShaderFormatsFlags shader_formats_used, PulseDebugLevel debug_level);
|
PULSE_API PulseBackend PulseLoadBackend(PulseBackendFlags backend_candidates, PulseShaderFormatsFlags shader_formats_used, PulseDebugLevel debug_level);
|
||||||
PULSE_API void PulseUnloadBackend(PulseBackend backend);
|
PULSE_API void PulseUnloadBackend(PulseBackend backend);
|
||||||
|
PULSE_API void PulseSetDebugCallback(PulseBackend backend, PulseDebugCallbackPFN callback);
|
||||||
|
|
||||||
PULSE_API PulseDevice PulseCreateDevice(PulseBackend backend, PulseDevice* forbiden_devices, uint32_t forbiden_devices_count);
|
PULSE_API PulseDevice PulseCreateDevice(PulseBackend backend, PulseDevice* forbiden_devices, uint32_t forbiden_devices_count);
|
||||||
PULSE_API void PulseDestroyDevice(PulseDevice device);
|
PULSE_API void PulseDestroyDevice(PulseDevice device);
|
||||||
PULSE_API PulseBackendBits PulseGetBackendInUseByDevice(PulseDevice device);
|
PULSE_API PulseBackendBits PulseGetBackendInUseByDevice(PulseDevice device);
|
||||||
PULSE_API bool PulseSupportsBackend(PulseBackendFlags backend_candidates, PulseShaderFormatsFlags shader_formats_used);
|
PULSE_API bool PulseSupportsBackend(PulseBackendFlags backend_candidates, PulseShaderFormatsFlags shader_formats_used);
|
||||||
PULSE_API bool PulseDeviceSupportsShaderFormats(PulseDevice device, PulseShaderFormatsFlags shader_formats_used);
|
PULSE_API bool PulseDeviceSupportsShaderFormats(PulseDevice device, PulseShaderFormatsFlags shader_formats_used);
|
||||||
|
|
||||||
|
PULSE_API PulseCommandList PulseRequestCommandList(PulseDevice device);
|
||||||
|
PULSE_API bool PulseSubmitCommandList(PulseDevice device, PulseCommandList cmd, PulseFence fence);
|
||||||
|
PULSE_API void PulseReleaseCommandList(PulseDevice device, PulseCommandList cmd);
|
||||||
|
|
||||||
|
PULSE_API PulseComputePass PulseBeginComputePass(PulseCommandList cmd);
|
||||||
|
PULSE_API void PulseEndComputePass(PulseComputePass pass);
|
||||||
|
|
||||||
|
PULSE_API PulseGeneralPass PulseBeginGeneralPass(PulseCommandList cmd);
|
||||||
|
PULSE_API void PulseEndGeneralPass(PulseGeneralPass pass);
|
||||||
|
|
||||||
|
PULSE_API PulseFence PulseCreateFence(PulseDevice device);
|
||||||
|
PULSE_API void PulseDestroyFence(PulseDevice device, PulseFence fence);
|
||||||
|
PULSE_API bool PulseIsFenceReady(PulseDevice device, PulseFence fence);
|
||||||
|
PULSE_API bool PulseWaitForFences(PulseDevice device, PulseFence* const* fences, uint32_t fences_count, bool wait_for_all);
|
||||||
|
|
||||||
|
PULSE_API PulseComputePipeline PulseCreateComputePipeline(PulseDevice device, const PulseComputePipelineCreateInfo* info);
|
||||||
|
PULSE_API void PulseDestroyComputePipeline(PulseDevice device, PulseComputePipeline pipeline);
|
||||||
|
PULSE_API void PulseBindComputePipeline(PulseComputePass pass, PulseComputePipeline pipeline);
|
||||||
|
|
||||||
PULSE_API PulseErrorType PulseGetLastErrorType(); // /!\ Warning /!\ Call to this function resets the internal last error variable
|
PULSE_API PulseErrorType PulseGetLastErrorType(); // /!\ Warning /!\ Call to this function resets the internal last error variable
|
||||||
PULSE_API const char* PulseVerbaliseErrorType(PulseErrorType error);
|
PULSE_API const char* PulseVerbaliseErrorType(PulseErrorType error);
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,18 @@
|
|||||||
#include "VulkanDevice.h"
|
#include "VulkanDevice.h"
|
||||||
#include "VulkanInstance.h"
|
#include "VulkanInstance.h"
|
||||||
|
|
||||||
#define VULKAN_RETRIEVE_DRIVER_DATA(device) ((VulkanDriverData*)device->driver_data)
|
#include "../../PulseInternal.h"
|
||||||
|
|
||||||
|
#define VULKAN_RETRIEVE_DRIVER_DATA(handle) ((VulkanDriverData*)handle->driver_data)
|
||||||
|
|
||||||
|
#define CHECK_VK_RETVAL(res, error, retval) \
|
||||||
|
if((res) != VK_SUCCESS) \
|
||||||
|
{ \
|
||||||
|
PulseSetInternalError(error); \
|
||||||
|
return retval; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CHECK_VK(res, error) CHECK_VK_RETVAL(res, error, )
|
||||||
|
|
||||||
typedef struct VulkanGlobal
|
typedef struct VulkanGlobal
|
||||||
{
|
{
|
||||||
@@ -24,7 +35,6 @@ typedef struct VulkanGlobal
|
|||||||
typedef struct VulkanDriverData
|
typedef struct VulkanDriverData
|
||||||
{
|
{
|
||||||
VulkanInstance instance;
|
VulkanInstance instance;
|
||||||
VulkanDevice device;
|
|
||||||
} VulkanDriverData;
|
} VulkanDriverData;
|
||||||
|
|
||||||
VulkanGlobal* VulkanGetGlobal();
|
VulkanGlobal* VulkanGetGlobal();
|
||||||
|
|||||||
24
Sources/Backends/Vulkan/VulkanComputePipeline.h
git.filemode.normal_file
24
Sources/Backends/Vulkan/VulkanComputePipeline.h
git.filemode.normal_file
@@ -0,0 +1,24 @@
|
|||||||
|
// 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_COMPUTE_PIPELINE_H_
|
||||||
|
#define PULSE_VULKAN_COMPUTE_PIPELINE_H_
|
||||||
|
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
|
#include <Pulse.h>
|
||||||
|
|
||||||
|
typedef struct VulkanComputePipeline
|
||||||
|
{
|
||||||
|
} VulkanComputePipeline;
|
||||||
|
|
||||||
|
PulseComputePipeline VulkanCreateComputePipeline(PulseDevice device, const PulseComputePipelineCreateInfo* info);
|
||||||
|
void VulkanBindComputePipeline(PulseComputePass pass, PulseComputePipeline pipeline);
|
||||||
|
void VulkanDestroyComputePipeline(PulseDevice device, PulseComputePipeline pipeline);
|
||||||
|
|
||||||
|
#endif // PULSE_VULKAN_COMPUTE_PIPELINE_H_
|
||||||
|
|
||||||
|
#endif // PULSE_ENABLE_VULKAN_BACKEND
|
||||||
@@ -2,26 +2,32 @@
|
|||||||
// 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 "VulkanInstance.h"
|
#include "Pulse.h"
|
||||||
|
#include "Vulkan.h"
|
||||||
|
#include "VulkanComputePipeline.h"
|
||||||
#include "VulkanDevice.h"
|
#include "VulkanDevice.h"
|
||||||
|
#include "VulkanInstance.h"
|
||||||
|
#include "VulkanLoader.h"
|
||||||
|
#include "VulkanQueue.h"
|
||||||
#include "../../PulseInternal.h"
|
#include "../../PulseInternal.h"
|
||||||
/*
|
|
||||||
static int32_t VulkanScorePhysicalDevice(VkPhysicalDevice device, const char** device_extensions, uint32_t device_extensions_count)
|
#include <string.h>
|
||||||
|
|
||||||
|
static int32_t VulkanScorePhysicalDevice(VulkanInstance* instance, VkPhysicalDevice device, const char** device_extensions, uint32_t device_extensions_count)
|
||||||
{
|
{
|
||||||
PULSE_DECLARE_STACK_FIXED_ALLOCATOR(allocator, sizeof(VkExtensionProperties) * 4096, sizeof(VkExtensionProperties));
|
|
||||||
// Check extensions support
|
// Check extensions support
|
||||||
uint32_t extension_count;
|
uint32_t extension_count;
|
||||||
kbhGetVulkanPFNs()->vkEnumerateDeviceExtensionProperties(device, PULSE_NULLPTR, &extension_count, PULSE_NULLPTR);
|
instance->vkEnumerateDeviceExtensionProperties(device, PULSE_NULLPTR, &extension_count, PULSE_NULLPTR);
|
||||||
VkExtensionProperties* props = (VkExtensionProperties*)kbhCallocInFixed(&allocator, extension_count, sizeof(VkExtensionProperties));
|
VkExtensionProperties* props = (VkExtensionProperties*)calloc(extension_count, sizeof(VkExtensionProperties));
|
||||||
if(!props)
|
if(!props)
|
||||||
return -1;
|
return -1;
|
||||||
kbhGetVulkanPFNs()->vkEnumerateDeviceExtensionProperties(device, PULSE_NULLPTR, &extension_count, props);
|
instance->vkEnumerateDeviceExtensionProperties(device, PULSE_NULLPTR, &extension_count, props);
|
||||||
|
|
||||||
bool are_there_required_device_extensions = true;
|
bool are_there_required_device_extensions = true;
|
||||||
for(int j = 0; j < device_extensions_count; j++)
|
for(uint32_t j = 0; j < device_extensions_count; j++)
|
||||||
{
|
{
|
||||||
bool is_there_extension = false;
|
bool is_there_extension = false;
|
||||||
for(int k = 0; k < extension_count; k++)
|
for(uint32_t k = 0; k < extension_count; k++)
|
||||||
{
|
{
|
||||||
if(strcmp(device_extensions[j], props[k].extensionName) == 0)
|
if(strcmp(device_extensions[j], props[k].extensionName) == 0)
|
||||||
{
|
{
|
||||||
@@ -40,18 +46,18 @@ static int32_t VulkanScorePhysicalDevice(VkPhysicalDevice device, const char** d
|
|||||||
|
|
||||||
// Check Queue Families Support
|
// Check Queue Families Support
|
||||||
int32_t queue;
|
int32_t queue;
|
||||||
if(kbhFindPhysicalDeviceQueueFamily(device, KBH_VULKAN_QUEUE_COMPUTE, &queue) != KBH_RHI_SUCCESS)
|
if(!VulkanFindPhysicalDeviceQueueFamily(instance, device, VULKAN_QUEUE_COMPUTE, &queue))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
VkPhysicalDeviceProperties device_props;
|
VkPhysicalDeviceProperties device_props;
|
||||||
kbhGetVulkanPFNs()->vkGetPhysicalDeviceProperties(device, &device_props);
|
instance->vkGetPhysicalDeviceProperties(device, &device_props);
|
||||||
|
|
||||||
VkPhysicalDeviceFeatures device_features;
|
VkPhysicalDeviceFeatures device_features;
|
||||||
kbhGetVulkanPFNs()->vkGetPhysicalDeviceFeatures(device, &device_features);
|
instance->vkGetPhysicalDeviceFeatures(device, &device_features);
|
||||||
|
|
||||||
int32_t score = -1;
|
int32_t score = -1;
|
||||||
if(device_props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
|
if(device_props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
|
||||||
score += 1001;
|
score += 10000;
|
||||||
|
|
||||||
score += device_props.limits.maxComputeWorkGroupCount[0];
|
score += device_props.limits.maxComputeWorkGroupCount[0];
|
||||||
score += device_props.limits.maxComputeWorkGroupCount[1];
|
score += device_props.limits.maxComputeWorkGroupCount[1];
|
||||||
@@ -61,7 +67,20 @@ static int32_t VulkanScorePhysicalDevice(VkPhysicalDevice device, const char** d
|
|||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VkPhysicalDevice VulkanPickPhysicalDevice(VulkanInstance* instance)
|
static bool VulkanIsDeviceForbidden(VkPhysicalDevice device, PulseDevice* forbiden_devices, uint32_t forbiden_devices_count)
|
||||||
|
{
|
||||||
|
if(device == VK_NULL_HANDLE)
|
||||||
|
return true;
|
||||||
|
#pragma omp parallel for
|
||||||
|
for(uint32_t i = 0; i < forbiden_devices_count; i++)
|
||||||
|
{
|
||||||
|
if(device == ((VulkanDevice*)forbiden_devices[i]->driver_data)->physical)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VkPhysicalDevice VulkanPickPhysicalDevice(VulkanInstance* instance, PulseDevice* forbiden_devices, uint32_t forbiden_devices_count)
|
||||||
{
|
{
|
||||||
VkPhysicalDevice* devices = PULSE_NULLPTR;
|
VkPhysicalDevice* devices = PULSE_NULLPTR;
|
||||||
VkPhysicalDevice chosen_one = VK_NULL_HANDLE;
|
VkPhysicalDevice chosen_one = VK_NULL_HANDLE;
|
||||||
@@ -73,9 +92,12 @@ static VkPhysicalDevice VulkanPickPhysicalDevice(VulkanInstance* instance)
|
|||||||
PULSE_CHECK_ALLOCATION_RETVAL(devices, VK_NULL_HANDLE);
|
PULSE_CHECK_ALLOCATION_RETVAL(devices, VK_NULL_HANDLE);
|
||||||
instance->vkEnumeratePhysicalDevices(instance->instance, &device_count, devices);
|
instance->vkEnumeratePhysicalDevices(instance->instance, &device_count, devices);
|
||||||
|
|
||||||
for(int i = 0; i < device_count; i++)
|
#pragma omp parallel for
|
||||||
|
for(uint32_t i = 0; i < device_count; i++)
|
||||||
{
|
{
|
||||||
int32_t current_device_score = VulkanScorePhysicalDevice(devices[i], PULSE_NULLPTR, 0);
|
if(VulkanIsDeviceForbidden(devices[i], forbiden_devices, forbiden_devices_count))
|
||||||
|
continue;
|
||||||
|
int32_t current_device_score = VulkanScorePhysicalDevice(instance, devices[i], PULSE_NULLPTR, 0);
|
||||||
if(current_device_score > best_device_score)
|
if(current_device_score > best_device_score)
|
||||||
{
|
{
|
||||||
best_device_score = current_device_score;
|
best_device_score = current_device_score;
|
||||||
@@ -84,17 +106,132 @@ static VkPhysicalDevice VulkanPickPhysicalDevice(VulkanInstance* instance)
|
|||||||
}
|
}
|
||||||
return chosen_one;
|
return chosen_one;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
void* VulkanCreateDevice(PulseBackend backend, PulseDevice* forbiden_devices, uint32_t forbiden_devices_count)
|
PulseDevice VulkanCreateDevice(PulseBackend backend, PulseDevice* forbiden_devices, uint32_t forbiden_devices_count)
|
||||||
{
|
{
|
||||||
|
PULSE_CHECK_HANDLE_RETVAL(backend, PULSE_NULLPTR);
|
||||||
|
|
||||||
|
PulseDevice pulse_device = (PulseDeviceHandler*)calloc(1, sizeof(PulseDeviceHandler));
|
||||||
|
PULSE_CHECK_ALLOCATION_RETVAL(pulse_device, PULSE_NULL_HANDLE);
|
||||||
|
|
||||||
|
VulkanDevice* device = (VulkanDevice*)calloc(1, sizeof(VulkanDevice));
|
||||||
|
PULSE_CHECK_ALLOCATION_RETVAL(device, PULSE_NULLPTR);
|
||||||
|
|
||||||
|
VulkanInstance* instance = &VULKAN_RETRIEVE_DRIVER_DATA(backend)->instance;
|
||||||
|
|
||||||
|
device->physical = VulkanPickPhysicalDevice(instance, forbiden_devices, forbiden_devices_count);
|
||||||
|
PULSE_CHECK_HANDLE_RETVAL(device->physical, PULSE_NULLPTR);
|
||||||
|
|
||||||
|
const float queue_priority = 1.0f;
|
||||||
|
|
||||||
|
VkDeviceQueueCreateInfo* queue_create_infos = (VkDeviceQueueCreateInfo*)PulseStaticAllocStack(VULKAN_QUEUE_END_ENUM * sizeof(VkDeviceQueueCreateInfo));
|
||||||
|
// No need to check allocation, it is allocated on the stack
|
||||||
|
|
||||||
|
uint32_t unique_queues_count = 1;
|
||||||
|
|
||||||
|
for(int32_t i = 0; i < VULKAN_QUEUE_END_ENUM; i++) // Needs to be done before next loop
|
||||||
|
{
|
||||||
|
if(!VulkanPrepareDeviceQueue(instance, device, i))
|
||||||
|
{
|
||||||
|
PulseSetInternalError(PULSE_ERROR_INITIALIZATION_FAILED);
|
||||||
|
return PULSE_NULLPTR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int32_t i = 0; i < VULKAN_QUEUE_END_ENUM; i++)
|
||||||
|
{
|
||||||
|
if(device->queues[i]->queue_family_index == -1)
|
||||||
|
continue;
|
||||||
|
int j;
|
||||||
|
for(j = i; j < VULKAN_QUEUE_END_ENUM; j++) // Ugly shit but array will never be big so it's okay
|
||||||
|
{
|
||||||
|
if(device->queues[i]->queue_family_index == device->queues[j]->queue_family_index)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(j == VULKAN_QUEUE_END_ENUM)
|
||||||
|
unique_queues_count++;
|
||||||
|
queue_create_infos[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||||
|
queue_create_infos[i].queueFamilyIndex = device->queues[i]->queue_family_index;
|
||||||
|
queue_create_infos[i].queueCount = 1;
|
||||||
|
queue_create_infos[i].pQueuePriorities = &queue_priority;
|
||||||
|
queue_create_infos[i].flags = 0;
|
||||||
|
queue_create_infos[i].pNext = PULSE_NULLPTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->vkGetPhysicalDeviceProperties(device->physical, &device->properties);
|
||||||
|
instance->vkGetPhysicalDeviceMemoryProperties(device->physical, &device->memory_properties);
|
||||||
|
instance->vkGetPhysicalDeviceFeatures(device->physical, &device->features);
|
||||||
|
|
||||||
|
VkDeviceCreateInfo create_info = {};
|
||||||
|
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||||
|
create_info.queueCreateInfoCount = unique_queues_count;
|
||||||
|
create_info.pQueueCreateInfos = queue_create_infos;
|
||||||
|
create_info.pEnabledFeatures = &device->features;
|
||||||
|
create_info.enabledExtensionCount = 0;
|
||||||
|
create_info.ppEnabledExtensionNames = PULSE_NULLPTR;
|
||||||
|
create_info.enabledLayerCount = 0;
|
||||||
|
create_info.ppEnabledLayerNames = PULSE_NULLPTR;
|
||||||
|
create_info.flags = 0;
|
||||||
|
create_info.pNext = PULSE_NULLPTR;
|
||||||
|
|
||||||
|
CHECK_VK_RETVAL(instance->vkCreateDevice(device->physical, &create_info, PULSE_NULLPTR, &device->device), PULSE_ERROR_INITIALIZATION_FAILED, PULSE_NULLPTR);
|
||||||
|
if(!VulkanLoadDevice(instance, device))
|
||||||
|
{
|
||||||
|
PulseSetInternalError(PULSE_ERROR_INITIALIZATION_FAILED);
|
||||||
|
return PULSE_NULLPTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int32_t i = 0; i < VULKAN_QUEUE_END_ENUM; i++)
|
||||||
|
{
|
||||||
|
if(!VulkanRetrieveDeviceQueue(device, (VulkanQueueType)i))
|
||||||
|
{
|
||||||
|
PulseSetInternalError(PULSE_ERROR_INITIALIZATION_FAILED);
|
||||||
|
return PULSE_NULLPTR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VmaVulkanFunctions vma_vulkan_func = {};
|
||||||
|
vma_vulkan_func.vkAllocateMemory = device->vkAllocateMemory;
|
||||||
|
vma_vulkan_func.vkBindBufferMemory = device->vkBindBufferMemory;
|
||||||
|
vma_vulkan_func.vkBindImageMemory = device->vkBindImageMemory;
|
||||||
|
vma_vulkan_func.vkCreateBuffer = device->vkCreateBuffer;
|
||||||
|
vma_vulkan_func.vkCreateImage = device->vkCreateImage;
|
||||||
|
vma_vulkan_func.vkDestroyBuffer = device->vkDestroyBuffer;
|
||||||
|
vma_vulkan_func.vkDestroyImage = device->vkDestroyImage;
|
||||||
|
vma_vulkan_func.vkFlushMappedMemoryRanges = device->vkFlushMappedMemoryRanges;
|
||||||
|
vma_vulkan_func.vkFreeMemory = device->vkFreeMemory;
|
||||||
|
vma_vulkan_func.vkGetBufferMemoryRequirements = device->vkGetBufferMemoryRequirements;
|
||||||
|
vma_vulkan_func.vkGetImageMemoryRequirements = device->vkGetImageMemoryRequirements;
|
||||||
|
vma_vulkan_func.vkInvalidateMappedMemoryRanges = device->vkInvalidateMappedMemoryRanges;
|
||||||
|
vma_vulkan_func.vkMapMemory = device->vkMapMemory;
|
||||||
|
vma_vulkan_func.vkUnmapMemory = device->vkUnmapMemory;
|
||||||
|
vma_vulkan_func.vkCmdCopyBuffer = device->vkCmdCopyBuffer;
|
||||||
|
vma_vulkan_func.vkGetPhysicalDeviceMemoryProperties = instance->vkGetPhysicalDeviceMemoryProperties;
|
||||||
|
vma_vulkan_func.vkGetPhysicalDeviceProperties = instance->vkGetPhysicalDeviceProperties;
|
||||||
|
|
||||||
|
VmaAllocatorCreateInfo allocator_create_info = {};
|
||||||
|
allocator_create_info.vulkanApiVersion = VK_API_VERSION_1_0;
|
||||||
|
allocator_create_info.physicalDevice = device->physical;
|
||||||
|
allocator_create_info.device = device->device;
|
||||||
|
allocator_create_info.instance = instance->instance;
|
||||||
|
allocator_create_info.pVulkanFunctions = &vma_vulkan_func;
|
||||||
|
|
||||||
|
CHECK_VK_RETVAL(vmaCreateAllocator(&allocator_create_info, &device->allocator), PULSE_ERROR_INITIALIZATION_FAILED, PULSE_NULLPTR);
|
||||||
|
|
||||||
|
pulse_device->driver_data = device;
|
||||||
|
pulse_device->backend = backend;
|
||||||
|
PULSE_LOAD_DRIVER_DEVICE(Vulkan);
|
||||||
|
return pulse_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanDestroyDevice(VulkanDevice* device)
|
void VulkanDestroyDevice(PulseDevice device)
|
||||||
{
|
{
|
||||||
if(device == PULSE_NULLPTR || device->device == VK_NULL_HANDLE)
|
VulkanDevice* vulkan_device = (VulkanDevice*)device->driver_data;
|
||||||
|
if(vulkan_device == PULSE_NULLPTR || vulkan_device->device == VK_NULL_HANDLE)
|
||||||
return;
|
return;
|
||||||
vmaDestroyAllocator(device->allocator);
|
vmaDestroyAllocator(vulkan_device->allocator);
|
||||||
device->vkDestroyDevice(device->device, PULSE_NULLPTR);
|
vulkan_device->vkDestroyDevice(vulkan_device->device, PULSE_NULLPTR);
|
||||||
device->device = VK_NULL_HANDLE;
|
vulkan_device->device = VK_NULL_HANDLE;
|
||||||
|
free(vulkan_device);
|
||||||
|
free(device);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,14 @@
|
|||||||
|
|
||||||
#include <Pulse.h>
|
#include <Pulse.h>
|
||||||
|
|
||||||
|
#include "VulkanEnums.h"
|
||||||
|
|
||||||
|
struct VulkanQueue;
|
||||||
|
|
||||||
typedef struct VulkanDevice
|
typedef struct VulkanDevice
|
||||||
{
|
{
|
||||||
|
struct VulkanQueue* queues[VULKAN_QUEUE_END_ENUM];
|
||||||
|
|
||||||
VkPhysicalDeviceFeatures features;
|
VkPhysicalDeviceFeatures features;
|
||||||
VkPhysicalDeviceMemoryProperties memory_properties;
|
VkPhysicalDeviceMemoryProperties memory_properties;
|
||||||
VkPhysicalDeviceProperties properties;
|
VkPhysicalDeviceProperties properties;
|
||||||
@@ -32,8 +38,8 @@ typedef struct VulkanDevice
|
|||||||
#undef PULSE_VULKAN_DEVICE_FUNCTION
|
#undef PULSE_VULKAN_DEVICE_FUNCTION
|
||||||
} VulkanDevice;
|
} VulkanDevice;
|
||||||
|
|
||||||
void* VulkanCreateDevice(PulseBackend backend, PulseDevice* forbiden_devices, uint32_t forbiden_devices_count);
|
PulseDevice VulkanCreateDevice(PulseBackend backend, PulseDevice* forbiden_devices, uint32_t forbiden_devices_count);
|
||||||
void VulkanDestroyDevice(VulkanDevice* device);
|
void VulkanDestroyDevice(PulseDevice device);
|
||||||
|
|
||||||
#endif // PULSE_VULKAN_DEVICE_H_
|
#endif // PULSE_VULKAN_DEVICE_H_
|
||||||
|
|
||||||
|
|||||||
20
Sources/Backends/Vulkan/VulkanEnums.h
git.filemode.normal_file
20
Sources/Backends/Vulkan/VulkanEnums.h
git.filemode.normal_file
@@ -0,0 +1,20 @@
|
|||||||
|
// 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_ENUMS_H_
|
||||||
|
#define PULSE_VULKAN_ENUMS_H_
|
||||||
|
|
||||||
|
typedef enum VulkanQueueType
|
||||||
|
{
|
||||||
|
VULKAN_QUEUE_COMPUTE = 0,
|
||||||
|
VULKAN_QUEUE_TRANSFER = 1,
|
||||||
|
|
||||||
|
VULKAN_QUEUE_END_ENUM // For internal use only
|
||||||
|
} VulkanQueueType;
|
||||||
|
|
||||||
|
#endif // PULSE_VULKAN_ENUMS_H_
|
||||||
|
|
||||||
|
#endif // PULSE_ENABLE_VULKAN_BACKEND
|
||||||
@@ -36,7 +36,7 @@ static VkInstance VulkanCreateInstance(const char** extensions_enabled, uint32_t
|
|||||||
create_info.flags = 0;
|
create_info.flags = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
VulkanGetGlobal()->vkCreateInstance(&create_info, PULSE_NULLPTR, &instance);
|
CHECK_VK_RETVAL(VulkanGetGlobal()->vkCreateInstance(&create_info, PULSE_NULLPTR, &instance), PULSE_ERROR_INITIALIZATION_FAILED, VK_NULL_HANDLE);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,10 +52,7 @@ bool VulkanInitInstance(VulkanInstance* instance, PulseDebugLevel debug_level)
|
|||||||
#endif
|
#endif
|
||||||
instance->instance = VulkanCreateInstance(extensions, sizeof(extensions) / sizeof(char*), debug_level);
|
instance->instance = VulkanCreateInstance(extensions, sizeof(extensions) / sizeof(char*), debug_level);
|
||||||
if(instance->instance == VK_NULL_HANDLE)
|
if(instance->instance == VK_NULL_HANDLE)
|
||||||
{
|
|
||||||
PulseSetInternalError(PULSE_ERROR_INITIALIZATION_FAILED);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
if(!VulkanLoadInstance(instance))
|
if(!VulkanLoadInstance(instance))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -2,5 +2,8 @@
|
|||||||
// 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
|
||||||
|
|
||||||
|
#define VMA_STATIC_VULKAN_FUNCTIONS 0
|
||||||
|
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 0
|
||||||
|
#define VMA_VULKAN_VERSION 1000000
|
||||||
#define VMA_IMPLEMENTATION
|
#define VMA_IMPLEMENTATION
|
||||||
#include <vk_mem_alloc.h>
|
#include <vk_mem_alloc.h>
|
||||||
|
|||||||
83
Sources/Backends/Vulkan/VulkanQueue.c
git.filemode.normal_file
83
Sources/Backends/Vulkan/VulkanQueue.c
git.filemode.normal_file
@@ -0,0 +1,83 @@
|
|||||||
|
// Copyright (C) 2024 kanel
|
||||||
|
// This file is part of "Pulse"
|
||||||
|
// For conditions of distribution and use, see copyright notice in LICENSE
|
||||||
|
|
||||||
|
#include "VulkanQueue.h"
|
||||||
|
#include "Vulkan.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
bool VulkanFindPhysicalDeviceQueueFamily(VulkanInstance* instance, VkPhysicalDevice physical, VulkanQueueType type, int32_t* queue_family_index)
|
||||||
|
{
|
||||||
|
if(physical == VK_NULL_HANDLE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint32_t queue_family_count;
|
||||||
|
instance->vkGetPhysicalDeviceQueueFamilyProperties(physical, &queue_family_count, PULSE_NULLPTR);
|
||||||
|
VkQueueFamilyProperties* queue_families = (VkQueueFamilyProperties*)calloc(queue_family_count, sizeof(VkQueueFamilyProperties));
|
||||||
|
if(!queue_families)
|
||||||
|
return false;
|
||||||
|
instance->vkGetPhysicalDeviceQueueFamilyProperties(physical, &queue_family_count, queue_families);
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
for(uint32_t i = 0; i < queue_family_count; i++)
|
||||||
|
{
|
||||||
|
if(type == VULKAN_QUEUE_COMPUTE)
|
||||||
|
{
|
||||||
|
// try to find a queue that's only for compute
|
||||||
|
if(queue_families[i].queueFlags & VK_QUEUE_COMPUTE_BIT && (queue_families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) == 0)
|
||||||
|
{
|
||||||
|
*queue_family_index = i;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(queue_families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) // else just find a compute queue
|
||||||
|
{
|
||||||
|
*queue_family_index = i;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(type == VULKAN_QUEUE_TRANSFER)
|
||||||
|
{
|
||||||
|
if(queue_families[i].queueFlags & VK_QUEUE_TRANSFER_BIT && (queue_families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0)
|
||||||
|
{
|
||||||
|
*queue_family_index = i;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(queue_families[i].queueFlags & VK_QUEUE_TRANSFER_BIT)
|
||||||
|
{
|
||||||
|
*queue_family_index = i;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(queue_families);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VulkanPrepareDeviceQueue(VulkanInstance* instance, VulkanDevice* device, VulkanQueueType type)
|
||||||
|
{
|
||||||
|
if(device == PULSE_NULLPTR)
|
||||||
|
return false;
|
||||||
|
device->queues[(int)type] = (VulkanQueue*)malloc(sizeof(VulkanQueue));
|
||||||
|
if(!device->queues[(int)type])
|
||||||
|
return false;
|
||||||
|
VulkanQueue* queue = device->queues[(int)type];
|
||||||
|
if(!queue)
|
||||||
|
return false;
|
||||||
|
return VulkanFindPhysicalDeviceQueueFamily(instance, device->physical, type, &queue->queue_family_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VulkanRetrieveDeviceQueue(VulkanDevice* device, VulkanQueueType type)
|
||||||
|
{
|
||||||
|
if(device == PULSE_NULLPTR)
|
||||||
|
return false;
|
||||||
|
VulkanQueue* queue = device->queues[(int)type];
|
||||||
|
if(!queue)
|
||||||
|
return false;
|
||||||
|
device->vkGetDeviceQueue(device->device, queue->queue_family_index, 0, &queue->queue);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
27
Sources/Backends/Vulkan/VulkanQueue.h
git.filemode.normal_file
27
Sources/Backends/Vulkan/VulkanQueue.h
git.filemode.normal_file
@@ -0,0 +1,27 @@
|
|||||||
|
// 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_QUEUES_H_
|
||||||
|
#define PULSE_VULKAN_QUEUES_H_
|
||||||
|
|
||||||
|
#include "VulkanEnums.h"
|
||||||
|
#include "VulkanDevice.h"
|
||||||
|
#include "VulkanInstance.h"
|
||||||
|
|
||||||
|
typedef struct VulkanQueue
|
||||||
|
{
|
||||||
|
VulkanDevice* device;
|
||||||
|
VkQueue queue;
|
||||||
|
int32_t queue_family_index;
|
||||||
|
} VulkanQueue;
|
||||||
|
|
||||||
|
bool VulkanFindPhysicalDeviceQueueFamily(VulkanInstance* instance, VkPhysicalDevice physical, VulkanQueueType type, int32_t* queue_family_index);
|
||||||
|
bool VulkanPrepareDeviceQueue(VulkanInstance* instance, VulkanDevice* device, VulkanQueueType type);
|
||||||
|
bool VulkanRetrieveDeviceQueue(VulkanDevice* device, VulkanQueueType type);
|
||||||
|
|
||||||
|
#endif // PULSE_VULKAN_QUEUES_H_
|
||||||
|
|
||||||
|
#endif // PULSE_ENABLE_VULKAN_BACKEND
|
||||||
22
Sources/PulseComputePipeline.c
git.filemode.normal_file
22
Sources/PulseComputePipeline.c
git.filemode.normal_file
@@ -0,0 +1,22 @@
|
|||||||
|
// Copyright (C) 2024 kanel
|
||||||
|
// This file is part of "Pulse"
|
||||||
|
// For conditions of distribution and use, see copyright notice in LICENSE
|
||||||
|
|
||||||
|
#include <Pulse.h>
|
||||||
|
#include "PulseInternal.h"
|
||||||
|
|
||||||
|
PULSE_API PulseComputePipeline PulseCreateComputePipeline(PulseDevice device, const PulseComputePipelineCreateInfo* info)
|
||||||
|
{
|
||||||
|
PULSE_CHECK_HANDLE_RETVAL(device, PULSE_NULL_HANDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
PULSE_API void PulseBindComputePipeline(PulseComputePass pass, PulseComputePipeline pipeline)
|
||||||
|
{
|
||||||
|
PULSE_CHECK_HANDLE(pass);
|
||||||
|
PULSE_CHECK_HANDLE(pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
PULSE_API void PulseDestroyComputePipeline(PulseDevice device, PulseComputePipeline pipeline)
|
||||||
|
{
|
||||||
|
PULSE_CHECK_HANDLE(device);
|
||||||
|
}
|
||||||
@@ -7,17 +7,15 @@
|
|||||||
|
|
||||||
PULSE_API PulseDevice PulseCreateDevice(PulseBackend backend, PulseDevice* forbiden_devices, uint32_t forbiden_devices_count)
|
PULSE_API PulseDevice PulseCreateDevice(PulseBackend backend, PulseDevice* forbiden_devices, uint32_t forbiden_devices_count)
|
||||||
{
|
{
|
||||||
PulseDevice device = backend->PFN_CreateDevice(backend, forbiden_devices, forbiden_devices_count);
|
PULSE_CHECK_HANDLE_RETVAL(backend, PULSE_NULL_HANDLE);
|
||||||
if(device == PULSE_NULL_HANDLE)
|
return backend->PFN_CreateDevice(backend, forbiden_devices, forbiden_devices_count);
|
||||||
PulseSetInternalError(PULSE_ERROR_INITIALIZATION_FAILED);
|
|
||||||
device->backend = backend;
|
|
||||||
return device;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PULSE_API void PulseDestroyDevice(PulseDevice device)
|
PULSE_API void PulseDestroyDevice(PulseDevice device)
|
||||||
{
|
{
|
||||||
PULSE_CHECK_HANDLE(device);
|
PULSE_CHECK_HANDLE(device);
|
||||||
device->PFN_DestroyDevice(device);
|
device->PFN_DestroyDevice(device);
|
||||||
|
device->driver_data = PULSE_NULLPTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
PULSE_API PulseBackendBits PulseGetBackendInUseByDevice(PulseDevice device)
|
PULSE_API PulseBackendBits PulseGetBackendInUseByDevice(PulseDevice device)
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define PulseStaticAllocStack(size) ((char[size]){ 0 })
|
||||||
|
|
||||||
#define PULSE_CHECK_ALLOCATION_RETVAL(ptr, retval) \
|
#define PULSE_CHECK_ALLOCATION_RETVAL(ptr, retval) \
|
||||||
do { \
|
do { \
|
||||||
if(ptr == PULSE_NULLPTR) \
|
if(ptr == PULSE_NULLPTR) \
|
||||||
@@ -37,9 +39,12 @@ typedef PulseBackendFlags (*PulseCheckBackendSupportPFN)(PulseBackendFlags, Puls
|
|||||||
|
|
||||||
typedef bool (*PulseLoadBackendPFN)(PulseDebugLevel);
|
typedef bool (*PulseLoadBackendPFN)(PulseDebugLevel);
|
||||||
typedef void (*PulseUnloadBackendPFN)(PulseBackend);
|
typedef void (*PulseUnloadBackendPFN)(PulseBackend);
|
||||||
typedef void* (*PulseCreateDevicePFN)(PulseBackend, PulseDevice*, uint32_t);
|
typedef PulseDevice (*PulseCreateDevicePFN)(PulseBackend, PulseDevice*, uint32_t);
|
||||||
|
|
||||||
typedef void (*PulseDestroyDevicePFN)(PulseDevice);
|
typedef void (*PulseDestroyDevicePFN)(PulseDevice);
|
||||||
|
typedef PulseComputePipeline (*PulseCreateComputePipelinePFN)(PulseDevice, const PulseComputePipelineCreateInfo*);
|
||||||
|
typedef void (*PulseBindComputePipelinePFN)(PulseComputePass, PulseComputePipeline);
|
||||||
|
typedef void (*PulseDestroyComputePipelinePFN)(PulseDevice, PulseComputePipeline);
|
||||||
|
|
||||||
typedef struct PulseBackendHandler
|
typedef struct PulseBackendHandler
|
||||||
{
|
{
|
||||||
@@ -58,6 +63,9 @@ typedef struct PulseDeviceHandler
|
|||||||
{
|
{
|
||||||
// PFNs
|
// PFNs
|
||||||
PulseDestroyDevicePFN PFN_DestroyDevice;
|
PulseDestroyDevicePFN PFN_DestroyDevice;
|
||||||
|
PulseCreateComputePipelinePFN PFN_CreateComputePipeline;
|
||||||
|
PulseBindComputePipelinePFN PFN_BindComputePipeline;
|
||||||
|
PulseDestroyComputePipelinePFN PFN_DestroyComputePipeline;
|
||||||
|
|
||||||
// Attributes
|
// Attributes
|
||||||
void* driver_data;
|
void* driver_data;
|
||||||
@@ -66,9 +74,12 @@ typedef struct PulseDeviceHandler
|
|||||||
|
|
||||||
void PulseSetInternalError(PulseErrorType error);
|
void PulseSetInternalError(PulseErrorType error);
|
||||||
|
|
||||||
#define PULSE_LOAD_DRIVER_DEVICE_FUNCTION(fn, _namespace) device->PFN_##fn = _namespace##fn;
|
#define PULSE_LOAD_DRIVER_DEVICE_FUNCTION(fn, _namespace) pulse_device->PFN_##fn = _namespace##fn;
|
||||||
#define PULSE_LOAD_DRIVER_DEVICE(_namespace) \
|
#define PULSE_LOAD_DRIVER_DEVICE(_namespace) \
|
||||||
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(BindComputePipeline, _namespace) \
|
||||||
|
PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyComputePipeline, _namespace) \
|
||||||
|
|
||||||
#ifdef PULSE_ENABLE_VULKAN_BACKEND
|
#ifdef PULSE_ENABLE_VULKAN_BACKEND
|
||||||
extern PulseBackendHandler VulkanDriver;
|
extern PulseBackendHandler VulkanDriver;
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
#include <Pulse.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
PulseBackend backend = PulseLoadBackend(PULSE_BACKEND_ANY, PULSE_SHADER_FORMAT_SPIRV_BIT, PULSE_NO_DEBUG);
|
|
||||||
if(backend == PULSE_NULL_HANDLE)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Error while loading Pulse: %s", PulseVerbaliseErrorType(PulseGetLastErrorType()));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
PulseUnloadBackend(backend);
|
|
||||||
puts("Successfully loaded Pulse !");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
11
Tests/Vulkan/DeviceSetup.c
git.filemode.normal_file
11
Tests/Vulkan/DeviceSetup.c
git.filemode.normal_file
@@ -0,0 +1,11 @@
|
|||||||
|
#include <unity/unity.h>
|
||||||
|
#include <Pulse.h>
|
||||||
|
|
||||||
|
extern PulseBackend backend;
|
||||||
|
|
||||||
|
void TestDeviceSetup()
|
||||||
|
{
|
||||||
|
PulseDevice device = PulseCreateDevice(backend, NULL, 0);
|
||||||
|
TEST_ASSERT_NOT_EQUAL_MESSAGE(device, PULSE_NULL_HANDLE, PulseVerbaliseErrorType(PulseGetLastErrorType()));
|
||||||
|
PulseDestroyDevice(device);
|
||||||
|
}
|
||||||
41
Tests/Vulkan/main.c
git.filemode.normal_file
41
Tests/Vulkan/main.c
git.filemode.normal_file
@@ -0,0 +1,41 @@
|
|||||||
|
#include <unity/unity.h>
|
||||||
|
#include <Pulse.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
PulseBackend backend;
|
||||||
|
|
||||||
|
extern void TestDeviceSetup();
|
||||||
|
|
||||||
|
bool SetupPulse()
|
||||||
|
{
|
||||||
|
backend = PulseLoadBackend(PULSE_BACKEND_VULKAN, PULSE_SHADER_FORMAT_SPIRV_BIT, PULSE_NO_DEBUG);
|
||||||
|
if(backend == PULSE_NULL_HANDLE)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Fatal Error: could not load Pulse using Vulkan due to %s", PulseVerbaliseErrorType(PulseGetLastErrorType()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
puts("Pulse loaded using Vulkan");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RunUnitTests()
|
||||||
|
{
|
||||||
|
UNITY_BEGIN();
|
||||||
|
RUN_TEST(TestDeviceSetup);
|
||||||
|
return UNITY_END();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnloadPulse()
|
||||||
|
{
|
||||||
|
PulseUnloadBackend(backend);
|
||||||
|
puts("Pulse unloaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
SetupPulse();
|
||||||
|
int result = RunUnitTests();
|
||||||
|
UnloadPulse();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
16
Tests/Vulkan/xmake.lua
git.filemode.normal_file
16
Tests/Vulkan/xmake.lua
git.filemode.normal_file
@@ -0,0 +1,16 @@
|
|||||||
|
option("vulkan-tests", { description = "Build Vulkan tests", default = false })
|
||||||
|
|
||||||
|
if has_config("vulkan-tests") then
|
||||||
|
set_group("VulkanTests")
|
||||||
|
add_requires("unity_test")
|
||||||
|
|
||||||
|
target("VulkanUnitTests")
|
||||||
|
set_kind("binary")
|
||||||
|
add_deps("pulse_gpu")
|
||||||
|
add_files("**.c")
|
||||||
|
add_packages("unity_test")
|
||||||
|
if is_plat("linux") then
|
||||||
|
set_extension(".x86_64")
|
||||||
|
end
|
||||||
|
target_end()
|
||||||
|
end
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
option("tests", { description = "Build tests", default = false })
|
|
||||||
|
|
||||||
if has_config("tests") then
|
|
||||||
set_group("Tests")
|
|
||||||
includes("*/xmake.lua")
|
|
||||||
end
|
|
||||||
Reference in New Issue
Block a user