From b075f8ea73e1603c25a0963b3ccace049afdee7d Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Tue, 8 Oct 2024 15:23:20 +0200 Subject: [PATCH] working on vulkan --- Includes/Pulse.h | 1 + Includes/PulseProfile.h | 6 +-- Sources/Backends/Vulkan/Vulkan.c | 26 ++++++++++- Sources/Backends/Vulkan/Vulkan.h | 4 +- Sources/Backends/Vulkan/VulkanDevice.c | 7 +++ Sources/Backends/Vulkan/VulkanDevice.h | 5 +++ Sources/Backends/Vulkan/VulkanInstance.c | 55 ++++++++++++++++++++++++ Sources/Backends/Vulkan/VulkanInstance.h | 5 +++ Sources/Backends/Vulkan/VulkanLoader.c | 41 +++++++++++------- Sources/Backends/Vulkan/VulkanLoader.h | 4 +- Sources/PulseDevice.c | 8 ++-- Sources/PulseInternal.h | 34 +++++++++------ Tests/LoadingPulse/xmake.lua | 1 - Tests/xmake.lua | 2 +- xmake.lua | 41 ++++++++---------- 15 files changed, 174 insertions(+), 66 deletions(-) create mode 100644 Sources/Backends/Vulkan/VulkanDevice.c create mode 100644 Sources/Backends/Vulkan/VulkanInstance.c diff --git a/Includes/Pulse.h b/Includes/Pulse.h index 17ef256..5ba512b 100644 --- a/Includes/Pulse.h +++ b/Includes/Pulse.h @@ -89,6 +89,7 @@ typedef enum PulseErrorType PULSE_ERROR_BACKENDS_CANDIDATES_SHADER_FORMAT_MISMATCH, PULSE_ERROR_INITIALIZATION_FAILED, PULSE_ERROR_INVALID_HANDLE, + PULSE_ERROR_ALLOCATION_FAILED, } PulseErrorType; typedef enum PulseImageType diff --git a/Includes/PulseProfile.h b/Includes/PulseProfile.h index 8787d42..ecced4d 100644 --- a/Includes/PulseProfile.h +++ b/Includes/PulseProfile.h @@ -116,11 +116,7 @@ extern "C" { #define PULSE_DEFINE_NULLABLE_HANDLE(object) typedef struct object##Handler* object -#if (defined(__cplusplus) && (__cplusplus >= 201103L)) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201103L)) - #define PULSE_NULL_HANDLE nullptr -#else - #define PULSE_NULL_HANDLE ((void*)0) -#endif +#define PULSE_NULL_HANDLE PULSE_NULLPTR #define PULSE_MAKE_VERSION(major, minor, patch) ((((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch))) diff --git a/Sources/Backends/Vulkan/Vulkan.c b/Sources/Backends/Vulkan/Vulkan.c index 6694b57..ee5cf09 100644 --- a/Sources/Backends/Vulkan/Vulkan.c +++ b/Sources/Backends/Vulkan/Vulkan.c @@ -2,6 +2,8 @@ // This file is part of "Pulse" // For conditions of distribution and use, see copyright notice in LICENSE +#include + #include #include "../../PulseInternal.h" @@ -18,13 +20,33 @@ bool VulkanLoadBackend() { if(!VulkanInitLoader()) return false; - return true; } +PulseDevice VulkanCreatePulseDevice(PulseDebugLevel debug_level) +{ + VulkanPulseDevice* vulkan_device = (VulkanPulseDevice*)calloc(1, sizeof(VulkanPulseDevice)); + PULSE_CHECK_ALLOCATION_RETVAL(vulkan_device, PULSE_NULL_HANDLE); + + if(!VulkanInitInstance(&vulkan_device->instance, debug_level)) + return PULSE_NULL_HANDLE; + + PulseDeviceHandler* pulse_device = (PulseDeviceHandler*)calloc(1, sizeof(PulseDeviceHandler)); + PULSE_CHECK_ALLOCATION_RETVAL(pulse_device, PULSE_NULL_HANDLE); + pulse_device->debug_level = debug_level; + pulse_device->driver_data = vulkan_device; + return pulse_device; +} + +void VulkanDestroyPulseDevice(PulseDevice device) +{ + +} + PulseBackendLoader VulkanDriver = { .PFN_LoadBackend = VulkanLoadBackend, - .PFN_CreateDevice = PULSE_NULLPTR, + .PFN_CreateDevice = VulkanCreatePulseDevice, + .PFN_DestroyDevice = VulkanDestroyPulseDevice, .backend = PULSE_BACKEND_VULKAN, .supported_shader_formats = PULSE_SHADER_FORMAT_SPIRV_BIT }; diff --git a/Sources/Backends/Vulkan/Vulkan.h b/Sources/Backends/Vulkan/Vulkan.h index 001f471..0040b7d 100644 --- a/Sources/Backends/Vulkan/Vulkan.h +++ b/Sources/Backends/Vulkan/Vulkan.h @@ -19,11 +19,11 @@ typedef struct VulkanGlobal #undef PULSE_VULKAN_GLOBAL_FUNCTION } VulkanGlobal; -typedef struct VulkanContext +typedef struct VulkanPulseDevice { VulkanInstance instance; VulkanDevice device; -} VulkanContext; +} VulkanPulseDevice; VulkanGlobal* VulkanGetGlobal(); diff --git a/Sources/Backends/Vulkan/VulkanDevice.c b/Sources/Backends/Vulkan/VulkanDevice.c new file mode 100644 index 0000000..772ccaf --- /dev/null +++ b/Sources/Backends/Vulkan/VulkanDevice.c @@ -0,0 +1,7 @@ +// Copyright (C) 2024 kanel +// This file is part of "Pulse" +// For conditions of distribution and use, see copyright notice in LICENSE + +#include "VulkanDevice.h" + + diff --git a/Sources/Backends/Vulkan/VulkanDevice.h b/Sources/Backends/Vulkan/VulkanDevice.h index dd746c8..23be3cb 100644 --- a/Sources/Backends/Vulkan/VulkanDevice.h +++ b/Sources/Backends/Vulkan/VulkanDevice.h @@ -14,6 +14,8 @@ #define VMA_VULKAN_VERSION 1000000 #include +#include + typedef struct VulkanDevice { VkPhysicalDeviceFeatures features; @@ -30,6 +32,9 @@ typedef struct VulkanDevice #undef PULSE_VULKAN_DEVICE_FUNCTION } VulkanDevice; +VulkanDevice* VulkanCreateDevice(PulseDebugLevel debug_level); +void VulkanDestroyDevice(VulkanDevice* device); + #endif // PULSE_VULKAN_DEVICE_H_ #endif // PULSE_ENABLE_VULKAN_BACKEND diff --git a/Sources/Backends/Vulkan/VulkanInstance.c b/Sources/Backends/Vulkan/VulkanInstance.c new file mode 100644 index 0000000..c5e40c1 --- /dev/null +++ b/Sources/Backends/Vulkan/VulkanInstance.c @@ -0,0 +1,55 @@ +// Copyright (C) 2024 kanel +// This file is part of "Pulse" +// For conditions of distribution and use, see copyright notice in LICENSE + +#include "../../PulseInternal.h" +#include "VulkanInstance.h" +#include "VulkanLoader.h" +#include "Vulkan.h" + +static VkInstance VulkanCreateInstance(const char** extensions_enabled, uint32_t extensions_count, PulseDebugLevel debug_level) +{ + static const char* layer_names[] = { "VK_LAYER_KHRONOS_validation" }; + + VkInstance instance = VK_NULL_HANDLE; + + VkApplicationInfo app_info = {}; + app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + app_info.pEngineName = "PulseGPU"; + app_info.engineVersion = PULSE_VERSION; + app_info.apiVersion = VK_API_VERSION_1_0; + + VkInstanceCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + create_info.pApplicationInfo = &app_info; + create_info.enabledExtensionCount = extensions_count; + create_info.ppEnabledExtensionNames = extensions_enabled; + create_info.enabledLayerCount = sizeof(layer_names) / sizeof(layer_names[0]); + create_info.ppEnabledLayerNames = layer_names; + create_info.pNext = PULSE_NULLPTR; + #ifdef PULSE_PLAT_MACOS + create_info.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + #else + create_info.flags = 0; + #endif + + VulkanGetGlobal()->vkCreateInstance(&create_info, PULSE_NULLPTR, &instance); + return instance; +} + +bool VulkanInitInstance(VulkanInstance* instance, PulseDebugLevel debug_level) +{ + instance->instance = VulkanCreateInstance(NULL, 0, debug_level); + if(instance->instance == VK_NULL_HANDLE) + { + PulseSetInternalError(PULSE_ERROR_INITIALIZATION_FAILED); + return false; + } + if(VulkanLoadInstance(instance)) + return false; + return true; +} + +void VulkanDestroyInstance(VulkanInstance* instance) +{ +} diff --git a/Sources/Backends/Vulkan/VulkanInstance.h b/Sources/Backends/Vulkan/VulkanInstance.h index f937ab6..67b7d2a 100644 --- a/Sources/Backends/Vulkan/VulkanInstance.h +++ b/Sources/Backends/Vulkan/VulkanInstance.h @@ -9,6 +9,8 @@ #include +#include + typedef struct VulkanInstance { VkInstance instance; @@ -18,6 +20,9 @@ typedef struct VulkanInstance #undef PULSE_VULKAN_INSTANCE_FUNCTION } VulkanInstance; +bool VulkanInitInstance(VulkanInstance* instance, PulseDebugLevel debug_level); +void VulkanDestroyInstance(VulkanInstance* instance); + #endif // PULSE_VULKAN_INSTANCE_H_ #endif // PULSE_ENABLE_VULKAN_BACKEND diff --git a/Sources/Backends/Vulkan/VulkanLoader.c b/Sources/Backends/Vulkan/VulkanLoader.c index e2b9abf..0bc4004 100644 --- a/Sources/Backends/Vulkan/VulkanLoader.c +++ b/Sources/Backends/Vulkan/VulkanLoader.c @@ -40,9 +40,9 @@ static LibModule vulkan_lib_module = PULSE_NULLPTR; -static void VulkanLoadGlobalFunctions(void* context, PFN_vkVoidFunction (*load)(void*, const char*)); -static void VulkanLoadInstanceFunctions(VulkanInstance* instance, PFN_vkVoidFunction (*load)(void*, const char*)); -static void VulkanLoadDeviceFunctions(VulkanInstance* instance, VulkanDevice* device, PFN_vkVoidFunction (*load)(VulkanInstance*, void*, const char*)); +static bool VulkanLoadGlobalFunctions(void* context, PFN_vkVoidFunction (*load)(void*, const char*)); +static bool VulkanLoadInstanceFunctions(VulkanInstance* instance, PFN_vkVoidFunction (*load)(void*, const char*)); +static bool VulkanLoadDeviceFunctions(VulkanInstance* instance, VulkanDevice* device, PFN_vkVoidFunction (*load)(VulkanInstance*, void*, const char*)); static inline PFN_vkVoidFunction vkGetInstanceProcAddrStub(void* context, const char* name) { @@ -127,18 +127,17 @@ bool VulkanInitLoader() PulseSetInternalError(PULSE_ERROR_INITIALIZATION_FAILED); return false; } - VulkanLoadGlobalFunctions(PULSE_NULLPTR, vkGetInstanceProcAddrStub); - return true; + return VulkanLoadGlobalFunctions(PULSE_NULLPTR, vkGetInstanceProcAddrStub); } -void VulkanLoadInstance(VulkanInstance* instance) +bool VulkanLoadInstance(VulkanInstance* instance) { - VulkanLoadInstanceFunctions(instance, vkGetInstanceProcAddrStub); + return VulkanLoadInstanceFunctions(instance, vkGetInstanceProcAddrStub); } -void VulkanLoadDevice(VulkanInstance* instance, VulkanDevice* device) +bool VulkanLoadDevice(VulkanInstance* instance, VulkanDevice* device) { - VulkanLoadDeviceFunctions(instance, device, vkGetDeviceProcAddrStub); + return VulkanLoadDeviceFunctions(instance, device, vkGetDeviceProcAddrStub); } void VulkanLoaderShutdown() @@ -147,23 +146,35 @@ void VulkanLoaderShutdown() vulkan_lib_module = PULSE_NULLPTR; } -static void VulkanLoadGlobalFunctions(void* context, PFN_vkVoidFunction (*load)(void*, const char*)) +static bool VulkanLoadGlobalFunctions(void* context, PFN_vkVoidFunction (*load)(void*, const char*)) { - #define PULSE_VULKAN_GLOBAL_FUNCTION(func) VulkanGetGlobal()->func = (PFN_##func)load(context, #func); + #define PULSE_VULKAN_GLOBAL_FUNCTION(func) \ + VulkanGetGlobal()->func = (PFN_##func)load(context, #func); \ + if(!VulkanGetGlobal()->func) \ + return false; #include "VulkanGlobalPrototypes.h" #undef PULSE_VULKAN_GLOBAL_FUNCTION + return true; } -static void VulkanLoadInstanceFunctions(VulkanInstance* instance, PFN_vkVoidFunction (*load)(void*, const char*)) +static bool VulkanLoadInstanceFunctions(VulkanInstance* instance, PFN_vkVoidFunction (*load)(void*, const char*)) { - #define PULSE_VULKAN_INSTANCE_FUNCTION(func) instance->func = (PFN_##func)load(instance->instance, #func); + #define PULSE_VULKAN_INSTANCE_FUNCTION(func) \ + instance->func = (PFN_##func)load(instance->instance, #func); \ + if(!instance->func) \ + return false; #include "VulkanInstancePrototypes.h" #undef PULSE_VULKAN_INSTANCE_FUNCTION + return true; } -static void VulkanLoadDeviceFunctions(VulkanInstance* instance, VulkanDevice* device, PFN_vkVoidFunction (*load)(VulkanInstance*, void*, const char*)) +static bool VulkanLoadDeviceFunctions(VulkanInstance* instance, VulkanDevice* device, PFN_vkVoidFunction (*load)(VulkanInstance*, void*, const char*)) { - #define PULSE_VULKAN_DEVICE_FUNCTION(func) device->func = (PFN_##func)load(instance, device->device, #func); + #define PULSE_VULKAN_DEVICE_FUNCTION(func) \ + device->func = (PFN_##func)load(instance, device->device, #func); \ + if(!device->func) \ + return false; #include "VulkanDevicePrototypes.h" #undef PULSE_VULKAN_DEVICE_FUNCTION + return true; } diff --git a/Sources/Backends/Vulkan/VulkanLoader.h b/Sources/Backends/Vulkan/VulkanLoader.h index 59b172e..a4743bf 100644 --- a/Sources/Backends/Vulkan/VulkanLoader.h +++ b/Sources/Backends/Vulkan/VulkanLoader.h @@ -9,8 +9,8 @@ #include -typedef struct VulkanInstance VulkanInstance; -typedef struct VulkanDevice VulkanDevice; +#include "VulkanDevice.h" +#include "VulkanInstance.h" bool VulkanInitLoader(); bool VulkanLoadInstance(VulkanInstance* instance); diff --git a/Sources/PulseDevice.c b/Sources/PulseDevice.c index ae0982a..17845d4 100644 --- a/Sources/PulseDevice.c +++ b/Sources/PulseDevice.c @@ -66,19 +66,20 @@ PULSE_API PulseDevice PulseCreateDevice(PulseBackendFlags backend_candidates, Pu PulseDevice device = backend->PFN_CreateDevice(debug_level); if(device == PULSE_NULL_HANDLE) PulseSetInternalError(PULSE_ERROR_INITIALIZATION_FAILED); + device->backend = backend; return device; } PULSE_API void PulseDestroyDevice(PulseDevice device) { PULSE_CHECK_HANDLE(device); - device->PFN_DestroyDevice(device); + device->backend->PFN_DestroyDevice(device); } PULSE_API PulseBackendBits PulseGetBackendInUseByDevice(PulseDevice device) { PULSE_CHECK_HANDLE_RETVAL(device, PULSE_BACKEND_INVALID); - return device->backend; + return device->backend->backend; } PULSE_API bool PulseSupportsBackend(PulseBackendFlags backend_candidates, PulseShaderFormatsFlags shader_formats_used) @@ -100,7 +101,7 @@ PULSE_API bool PulseSupportsBackend(PulseBackendFlags backend_candidates, PulseS PULSE_API bool PulseDeviceSupportsSahderFormats(PulseDevice device, PulseShaderFormatsFlags shader_formats_used) { PULSE_CHECK_HANDLE_RETVAL(device, false); - return (device->supported_shader_formats & shader_formats_used) != 0; + return (device->backend->supported_shader_formats & shader_formats_used) != 0; } PULSE_API PulseErrorType PulseGetLastErrorType() @@ -117,6 +118,7 @@ PULSE_API const char* PulseVerbaliseErrorType(PulseErrorType error) case PULSE_ERROR_NONE: return "no error"; case PULSE_ERROR_BACKENDS_CANDIDATES_SHADER_FORMAT_MISMATCH: return "no backend candidates support the required shader formats"; case PULSE_ERROR_INITIALIZATION_FAILED: return "initialization of an object could not be completed for implementation-specific reasons"; + case PULSE_ERROR_ALLOCATION_FAILED: return "an internal allocation failed"; default: return "invalid error type"; }; diff --git a/Sources/PulseInternal.h b/Sources/PulseInternal.h index 2cd1c53..3c6e396 100644 --- a/Sources/PulseInternal.h +++ b/Sources/PulseInternal.h @@ -11,33 +11,43 @@ extern "C" { #endif +#define PULSE_CHECK_ALLOCATION_RETVAL(ptr, retval) \ + do { \ + if(ptr == PULSE_NULLPTR) \ + { \ + PulseSetInternalError(PULSE_ERROR_ALLOCATION_FAILED); \ + return retval; \ + } \ + } while(0); \ + +#define PULSE_CHECK_ALLOCATION(ptr) PULSE_CHECK_ALLOCATION_RETVAL(ptr, ) + typedef bool (*PulseLoadBackendPFN)(void); typedef PulseDevice (*PulseCreateDevicePFN)(PulseDebugLevel); - typedef void (*PulseDestroyDevicePFN)(PulseDevice); -typedef struct PulseDeviceHandler -{ - // PFNs - PulseDestroyDevicePFN PFN_DestroyDevice; - - // Attributes - PulseBackendFlags backend; - PulseShaderFormatsFlags supported_shader_formats; - PulseDebugLevel debug_level; -} PulseDeviceHandler; - typedef struct PulseBackendLoader { // PFNs PulseLoadBackendPFN PFN_LoadBackend; PulseCreateDevicePFN PFN_CreateDevice; + PulseDestroyDevicePFN PFN_DestroyDevice; // Attributes PulseBackendFlags backend; PulseShaderFormatsFlags supported_shader_formats; } PulseBackendLoader; +typedef struct PulseDeviceHandler +{ + // PFNs + + // Attributes + void* driver_data; + const PulseBackendLoader* backend; + PulseDebugLevel debug_level; +} PulseDeviceHandler; + void PulseSetInternalError(PulseErrorType error); #define PULSE_LOAD_DRIVER_DEVICE_FUNCTION(fn, _namespace) device->PFN_##fn = _namespace##fn; diff --git a/Tests/LoadingPulse/xmake.lua b/Tests/LoadingPulse/xmake.lua index 5dc3c00..1839a52 100644 --- a/Tests/LoadingPulse/xmake.lua +++ b/Tests/LoadingPulse/xmake.lua @@ -4,5 +4,4 @@ target("LoadingPulse") set_extension(".x86_64") end add_files("main.c") - set_targetdir("build/") target_end() diff --git a/Tests/xmake.lua b/Tests/xmake.lua index 46e818b..c4cde8f 100644 --- a/Tests/xmake.lua +++ b/Tests/xmake.lua @@ -1,4 +1,4 @@ -option("tests", { description = "Build tests", default = true }) +option("tests", { description = "Build tests", default = false }) if has_config("tests") then set_group("Tests") diff --git a/xmake.lua b/xmake.lua index 309b05b..77c26ad 100644 --- a/xmake.lua +++ b/xmake.lua @@ -63,36 +63,31 @@ end target("pulse_gpu") set_kind("$(kind)") add_defines("PULSE_BUILD") - add_headerfiles("Includes/*.hpp)") add_headerfiles("Sources/*.h", { prefixdir = "private", install = false }) add_headerfiles("Sources/*.inl", { prefixdir = "private", install = false }) add_files("Sources/*.c") for name, module in pairs(backends) do - if not has_config(module.option) then - goto continue + if has_config(module.option) then + if module.packages then + add_packages(table.unpack(module.packages)) + end + + add_defines("PULSE_ENABLE_" .. name:upper() .. "_BACKEND") + + add_headerfiles("Sources/Backends/" .. name .. "/**.h", { prefixdir = "private", install = false }) + add_headerfiles("Sources/Backends/" .. name .. "/**.inl", { prefixdir = "private", install = false }) + + add_files("Sources/Backends/" .. name .. "/**.c") + if module.has_cpp_files then + add_files("Sources/Backends/" .. name .. "/**.cpp") + end + + if module.custom then + module.custom() + end end - - if module.packages then - add_packages(table.unpack(module.packages)) - end - - add_defines("PULSE_ENABLE_" .. name:upper() .. "_BACKEND") - - add_headerfiles("Sources/Backends/" .. name .. "/**.h", { prefixdir = "private", install = false }) - add_headerfiles("Sources/Backends/" .. name .. "/*.inl", { prefixdir = "private", install = false }) - - add_files("Sources/Backends/" .. name .. "/**.c") - if module.has_cpp_files then - add_files("Sources/Backends/" .. name .. "/**.cpp") - end - - if module.custom then - module.custom() - end - - ::continue:: end on_load(function(target)