diff --git a/Examples/Vulkan/main.c b/Examples/Vulkan/main.c index 7953e4d..1cdba30 100644 --- a/Examples/Vulkan/main.c +++ b/Examples/Vulkan/main.c @@ -1,20 +1,31 @@ #include #include +#include -#define CHECK_PULSE_HANDLE_RETVAL(handle, retval) \ - if(handle == PULSE_NULL_HANDLE) \ - { \ - fprintf(stderr, "Error: %s", PulseVerbaliseErrorType(PulseGetLastErrorType())); \ - return retval; \ - } \ +void DebugCallBack(PulseDebugMessageSeverity severity, const char* message) +{ + if(severity == PULSE_DEBUG_MESSAGE_SEVERITY_ERROR) + { + fprintf(stderr, "Pulse Error: %s", message); + exit(1); + } + else if(severity == PULSE_DEBUG_MESSAGE_SEVERITY_WARNING) + fprintf(stderr, "Pulse Warning: %s", message); + else + printf("Pulse: %s", message); +} int main(void) { PulseBackend backend = PulseLoadBackend(PULSE_BACKEND_VULKAN, PULSE_SHADER_FORMAT_SPIRV_BIT, PULSE_NO_DEBUG); - CHECK_PULSE_HANDLE_RETVAL(backend, 1); + if(backend == PULSE_NULL_HANDLE) + { + fprintf(stderr, "Pulse: could not create backend"); + return 1; + } + PulseSetDebugCallback(backend, DebugCallBack); PulseDevice device = PulseCreateDevice(backend, NULL, 0); - CHECK_PULSE_HANDLE_RETVAL(device, 1); PulseDestroyDevice(device); PulseUnloadBackend(backend); diff --git a/Includes/Pulse.h b/Includes/Pulse.h index c778521..830d653 100644 --- a/Includes/Pulse.h +++ b/Includes/Pulse.h @@ -90,23 +90,6 @@ typedef enum PulseDebugMessageSeverity PULSE_DEBUG_MESSAGE_SEVERITY_ERROR } PulseDebugMessageSeverity; -typedef enum PulseDebugMessageType -{ - PULSE_DEBUG_MESSAGE_TYPE_GENERAL, - PULSE_DEBUG_MESSAGE_TYPE_PERFORMANCE -} PulseDebugMessageType; - -typedef enum PulseErrorType -{ - PULSE_ERROR_NONE, - - PULSE_ERROR_BACKENDS_CANDIDATES_SHADER_FORMAT_MISMATCH, - PULSE_ERROR_INITIALIZATION_FAILED, - PULSE_ERROR_INVALID_HANDLE, - PULSE_ERROR_ALLOCATION_FAILED, - PULSE_ERROR_DEVICE_LOST, -} PulseErrorType; - typedef enum PulseImageType { PULSE_IMAGE_TYPE_2D, @@ -264,7 +247,7 @@ typedef struct PulseImageRegion } PulseImageRegion; // Functions -typedef void (*PulseDebugCallbackPFN)(PulseDebugMessageSeverity, PulseDebugMessageType, const char*); +typedef void (*PulseDebugCallbackPFN)(PulseDebugMessageSeverity, const char*); PULSE_API PulseBackend PulseLoadBackend(PulseBackendFlags backend_candidates, PulseShaderFormatsFlags shader_formats_used, PulseDebugLevel debug_level); PULSE_API void PulseUnloadBackend(PulseBackend backend); @@ -289,15 +272,12 @@ 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 bool PulseWaitForFences(PulseDevice device, const PulseFence* fences, uint32_t fences_count, bool wait_for_all); PULSE_API PulseComputePipeline PulseCreateComputePipeline(PulseDevice device, const PulseComputePipelineCreateInfo* info); PULSE_API 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 const char* PulseVerbaliseErrorType(PulseErrorType error); - #ifdef __cplusplus } #endif diff --git a/Includes/PulseProfile.h b/Includes/PulseProfile.h index ecced4d..2a9d32d 100644 --- a/Includes/PulseProfile.h +++ b/Includes/PulseProfile.h @@ -44,10 +44,13 @@ extern "C" { #define PULSE_PLAT_WINDOWS #elif defined(__linux__) #define PULSE_PLAT_LINUX + #define PULSE_PLAT_POSIX #elif defined(__APPLE__) && defined(__MACH__) #define PULSE_PLAT_MACOS + #define PULSE_PLAT_POSIX #elif defined(unix) || defined(__unix__) || defined(__unix) #define PULSE_PLAT_UNIX + #define PULSE_PLAT_POSIX #else #error "Unknown environment (not Windows, not Linux, not MacOS, not Unix)" #endif diff --git a/Sources/Backends/Vulkan/VulkanCommandList.h b/Sources/Backends/Vulkan/VulkanCommandList.h new file mode 100644 index 0000000..6433f5d --- /dev/null +++ b/Sources/Backends/Vulkan/VulkanCommandList.h @@ -0,0 +1,32 @@ +// 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_COMMAND_LIST_H_ +#define PULSE_VULKAN_COMMAND_LIST_H_ + +#include + +#include +#include "../../PulseInternal.h" +#include "VulkanCommandPool.h" + +typedef struct VulkanCommandList +{ + PulseDevice device; + VulkanCommandPool* pool; + PulseThreadID thread_id; + VkCommandBuffer cmd; + + PulseComputePipeline* compute_pipelines_bound; + uint32_t compute_pipelines_bound_capacity; + uint32_t compute_pipelines_bound_size; +} VulkanCommandList; + +void VulkanInitCommandList(VulkanCommandPool* pool); + +#endif // PULSE_VULKAN_COMMAND_LIST_H_ + +#endif // PULSE_ENABLE_VULKAN_BACKEND diff --git a/Sources/Backends/Vulkan/VulkanCommandPool.c b/Sources/Backends/Vulkan/VulkanCommandPool.c new file mode 100644 index 0000000..a70b8ba --- /dev/null +++ b/Sources/Backends/Vulkan/VulkanCommandPool.c @@ -0,0 +1,47 @@ +// Copyright (C) 2024 kanel +// This file is part of "Pulse" +// For conditions of distribution and use, see copyright notice in LICENSE + +#include "Vulkan.h" +#include "VulkanCommandPool.h" +#include "VulkanDevice.h" +#include "VulkanQueue.h" + +bool VulkanInitCommandPool(PulseDevice device, VulkanCommandPool* pool, VulkanQueueType queue_type) +{ + PULSE_CHECK_HANDLE_RETVAL(device, false); + PULSE_CHECK_PTR_RETVAL(pool, false); + + VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(device, VulkanDevice*); + + VkCommandPoolCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + create_info.queueFamilyIndex = vulkan_device->queues[queue_type]->queue_family_index; + create_info.pNext = PULSE_NULLPTR; + CHECK_VK_RETVAL(vulkan_device->vkCreateCommandPool(vulkan_device->device, &create_info, PULSE_NULLPTR, &pool->pool), PULSE_ERROR_INITIALIZATION_FAILED, false); + + pool->thread_id = PulseGetThreadID(); + + pool->available_command_lists = PULSE_NULLPTR; + pool->available_command_lists_capacity = 0; + pool->available_command_lists_size = 0; + + pool->device = device; + + return true; +} + +void VulkanUninitCommandPool(VulkanCommandPool* pool) +{ + PULSE_CHECK_PTR(pool); + + VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(pool->device, VulkanDevice*); + vulkan_device->vkDestroyCommandPool(vulkan_device->device, pool->pool, PULSE_NULLPTR); + if(pool->available_command_lists != PULSE_NULLPTR) + free(pool->available_command_lists); + pool->thread_id = 0; + pool->available_command_lists = PULSE_NULLPTR; + pool->available_command_lists_capacity = 0; + pool->available_command_lists_size = 0; +} diff --git a/Sources/Backends/Vulkan/VulkanCommandPool.h b/Sources/Backends/Vulkan/VulkanCommandPool.h new file mode 100644 index 0000000..ce4382c --- /dev/null +++ b/Sources/Backends/Vulkan/VulkanCommandPool.h @@ -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 + +#ifdef PULSE_ENABLE_VULKAN_BACKEND + +#ifndef PULSE_VULKAN_COMMAND_POOL_H_ +#define PULSE_VULKAN_COMMAND_POOL_H_ + +#include + +#include +#include "../../PulseInternal.h" +#include "VulkanEnums.h" + +typedef struct VulkanCommandPool +{ + PulseDevice device; + + VkCommandPool pool; + VulkanQueueType queue_type; + + PulseThreadID thread_id; + + PulseCommandList* available_command_lists; + uint32_t available_command_lists_capacity; + uint32_t available_command_lists_size; +} VulkanCommandPool; + +bool VulkanInitCommandPool(PulseDevice device, VulkanCommandPool* pool, VulkanQueueType queue_type); +void VulkanUninitCommandPool(VulkanCommandPool* pool); + +#endif // PULSE_VULKAN_COMMAND_POOL_H_ + +#endif // PULSE_ENABLE_VULKAN_BACKEND diff --git a/Sources/Backends/Vulkan/VulkanDevice.h b/Sources/Backends/Vulkan/VulkanDevice.h index ed8e492..56b1c57 100644 --- a/Sources/Backends/Vulkan/VulkanDevice.h +++ b/Sources/Backends/Vulkan/VulkanDevice.h @@ -17,11 +17,14 @@ #include #include "VulkanEnums.h" +#include "VulkanCommandPool.h" struct VulkanQueue; typedef struct VulkanDevice { + VulkanCommandPool* cmd_pools; + struct VulkanQueue* queues[VULKAN_QUEUE_END_ENUM]; VkPhysicalDeviceFeatures features; diff --git a/Sources/Backends/Vulkan/VulkanEnums.h b/Sources/Backends/Vulkan/VulkanEnums.h index 5afa011..a94614f 100644 --- a/Sources/Backends/Vulkan/VulkanEnums.h +++ b/Sources/Backends/Vulkan/VulkanEnums.h @@ -1,4 +1,5 @@ // Copyright (C) 2024 kanel +// // This file is part of "Pulse" // For conditions of distribution and use, see copyright notice in LICENSE diff --git a/Sources/Backends/Vulkan/VulkanFence.c b/Sources/Backends/Vulkan/VulkanFence.c index 727b817..42dcb08 100644 --- a/Sources/Backends/Vulkan/VulkanFence.c +++ b/Sources/Backends/Vulkan/VulkanFence.c @@ -2,7 +2,8 @@ // This file is part of "Pulse" // For conditions of distribution and use, see copyright notice in LICENSE -#include "Pulse.h" +#include + #include "Vulkan.h" #include "VulkanDevice.h" #include "VulkanFence.h" @@ -45,15 +46,39 @@ bool VulkanIsFenceReady(PulseDevice device, PulseFence fence) VkResult res = vulkan_device->vkGetFenceStatus(vulkan_device->device, vulkan_fence); switch(res) { - case VK_ERROR_DEVICE_LOST: PulseSetInternalError(PULSE_ERROR_DEVICE_LOST); return false; - case VK_NOT_READY: return false; case VK_SUCCESS: return true; + case VK_NOT_READY: return false; + case VK_ERROR_DEVICE_LOST: PulseSetInternalError(PULSE_ERROR_DEVICE_LOST); return false; + default: return false; } return false; } -bool VulkanWaitForFences(PulseDevice device, PulseFence *const *fences, uint32_t fences_count, bool wait_for_all) +bool VulkanWaitForFences(PulseDevice device, const PulseFence* fences, uint32_t fences_count, bool wait_for_all) { + if(fences_count == 0) + return true; + VulkanDevice* vulkan_device = VULKAN_RETRIEVE_DRIVER_DATA_AS(device, VulkanDevice*); + if(vulkan_device == PULSE_NULLPTR || vulkan_device->device == VK_NULL_HANDLE) + return false; + VkFence* vulkan_fences = (VkFence*)calloc(fences_count, sizeof(VkFence)); + PULSE_CHECK_ALLOCATION_RETVAL(vulkan_fences, false); + for(uint32_t i = 0; i < fences_count; i++) + vulkan_fences[i] = VULKAN_RETRIEVE_DRIVER_DATA_AS(((PulseFence)fences + i), VkFence); + VkResult result = vulkan_device->vkWaitForFences(vulkan_device->device, fences_count, vulkan_fences, wait_for_all, UINT64_MAX); + free(vulkan_fences); + switch(result) + { + case VK_SUCCESS: break; + case VK_TIMEOUT: break; + + case VK_ERROR_DEVICE_LOST: PulseSetInternalError(PULSE_ERROR_DEVICE_LOST); return false; + case VK_ERROR_OUT_OF_HOST_MEMORY: PulseSetInternalError(PULSE_ERROR_CPU_ALLOCATION_FAILED); return false; + case VK_ERROR_OUT_OF_DEVICE_MEMORY: PulseSetInternalError(PULSE_ERROR_DEVICE_ALLOCATION_FAILED); return false; + + default: break; + } + return true; } diff --git a/Sources/Backends/Vulkan/VulkanFence.h b/Sources/Backends/Vulkan/VulkanFence.h index e801a43..e165988 100644 --- a/Sources/Backends/Vulkan/VulkanFence.h +++ b/Sources/Backends/Vulkan/VulkanFence.h @@ -7,15 +7,13 @@ #ifndef PULSE_VULKAN_FENCE_H_ #define PULSE_VULKAN_FENCE_H_ -#include - #include #include "VulkanDevice.h" PulseFence VulkanCreateFence(PulseDevice device); void VulkanDestroyFence(PulseDevice device, PulseFence fence); bool VulkanIsFenceReady(PulseDevice device, PulseFence fence); -bool VulkanWaitForFences(PulseDevice device, PulseFence *const *fences, uint32_t fences_count, bool wait_for_all); +bool VulkanWaitForFences(PulseDevice device, const PulseFence* fences, uint32_t fences_count, bool wait_for_all); #endif // PULSE_VULKAN_FENCE_H_ diff --git a/Sources/PulseBackend.c b/Sources/PulseBackend.c index e29ef12..4c25ec1 100644 --- a/Sources/PulseBackend.c +++ b/Sources/PulseBackend.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" @@ -23,11 +25,36 @@ static const PulseCheckBackendSupportPFN backends_supports[] = { PULSE_NULLPTR }; -static PulseErrorType last_error = PULSE_ERROR_NONE; - -void PulseSetInternalError(PulseErrorType error) +struct +{ + char file[1024]; + char function[1024]; + PulseErrorType type; + int line; +} last_error = { .file = { 0 }, .function = { 0 }, .type = PULSE_ERROR_NONE, .line = -1 }; + +void PulseSetInternalErrorBackend(PulseErrorType error, const char* file, const char* function, int line) +{ + strcpy(last_error.file, file); + strcpy(last_error.function, function); + last_error.type = error; + last_error.line = line; +} + +void PulseLogErrorBackend(PulseBackend backend, PulseErrorType error, const char* file, const char* function, int line) +{ + if(backend == PULSE_NULL_HANDLE) + return; + if(!backend->PFN_UserDebugCallback) + return; +} + +void PulseLogWarningBackend(PulseBackend backend, PulseWarningType warning, const char* file, const char* function, int line) +{ +} + +void PulseLogInfoBackend(PulseBackend backend, const char* message, const char* file, const char* function, int line) { - last_error = error; } static PulseBackendFlags PulseSelectBackend(PulseBackendFlags backend_candidates, PulseShaderFormatsFlags shader_formats_used) @@ -47,6 +74,10 @@ static PulseBackendFlags PulseSelectBackend(PulseBackendFlags backend_candidates return PULSE_BACKEND_INVALID; } +static const char* PulseVerbaliseErrorType(PulseErrorType error) +{ +} + static PulseBackend PulseGetBackendFromFlag(PulseBackendBits flag) { switch(flag) @@ -58,9 +89,9 @@ static PulseBackend PulseGetBackendFromFlag(PulseBackendBits flag) case PULSE_BACKEND_VULKAN: return &D3D11Driver; #endif - default: return PULSE_NULL_HANDLE; + default: break; } - return PULSE_NULL_HANDLE; // To avoid warnings + return PULSE_NULL_HANDLE; } PULSE_API PulseBackend PulseLoadBackend(PulseBackendFlags backend_candidates, PulseShaderFormatsFlags shader_formats_used, PulseDebugLevel debug_level) @@ -74,6 +105,7 @@ PULSE_API PulseBackend PulseLoadBackend(PulseBackendFlags backend_candidates, Pu return PULSE_NULL_HANDLE; if(!backend->PFN_LoadBackend(debug_level)) return PULSE_NULL_HANDLE; + backend->PFN_UserDebugCallback = PULSE_NULLPTR; return (PulseBackend)backend; } @@ -96,24 +128,8 @@ PULSE_API bool PulseSupportsBackend(PulseBackendFlags backend_candidates, PulseS return false; } -PULSE_API PulseErrorType PulseGetLastErrorType() +PULSE_API void PulseSetDebugCallback(PulseBackend backend, PulseDebugCallbackPFN callback) { - PulseErrorType error = last_error; - last_error = PULSE_ERROR_NONE; - return error; -} - -PULSE_API const char* PulseVerbaliseErrorType(PulseErrorType error) -{ - switch(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"; - case PULSE_ERROR_DEVICE_LOST: return "device has been lost"; - - default: return "invalid error type"; - }; - return PULSE_NULLPTR; // To avoid warnings, should be unreachable + PULSE_CHECK_HANDLE(backend); + backend->PFN_UserDebugCallback = callback; } diff --git a/Sources/PulseDebug.c b/Sources/PulseDebug.c new file mode 100644 index 0000000..34a3b5d --- /dev/null +++ b/Sources/PulseDebug.c @@ -0,0 +1,32 @@ +// Copyright (C) 2024 kanel +// This file is part of "Pulse" +// For conditions of distribution and use, see copyright notice in LICENSE + +#include +#include "PulseDebug.h" + +const char* PulseVerbaliseErrorType(PulseErrorType error) +{ + switch(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_CPU_ALLOCATION_FAILED: return "a CPU allocation failed"; + case PULSE_ERROR_DEVICE_ALLOCATION_FAILED: return "a device allocation failed"; + case PULSE_ERROR_DEVICE_LOST: return "device has been lost"; + case PULSE_ERROR_INVALID_INTERNAL_POINTER: return "invalid internal pointer"; + case PULSE_ERROR_INVALID_HANDLE: return "invalid handle"; + + default: return "invalid error type"; + }; + return PULSE_NULLPTR; // To avoid warnings, should be unreachable +} + +const char* PulseVerbaliseWarningType(PulseWarningType warning) +{ + switch(warning) + { + default: return "invalid warning type"; + }; + return PULSE_NULLPTR; // To avoid warnings, should be unreachable +} diff --git a/Sources/PulseDebug.h b/Sources/PulseDebug.h new file mode 100644 index 0000000..bfe9884 --- /dev/null +++ b/Sources/PulseDebug.h @@ -0,0 +1,13 @@ +// Copyright (C) 2024 kanel +// This file is part of "Pulse" +// For conditions of distribution and use, see copyright notice in LICENSE + +#ifndef PULSE_DEBUG_H_ +#define PULSE_DEBUG_H_ + +#include "PulseEnums.h" + +const char* PulseVerbaliseErrorType(PulseErrorType error); +const char* PulseVerbaliseWarningType(PulseWarningType warning); + +#endif diff --git a/Sources/PulseDefs.h b/Sources/PulseDefs.h new file mode 100644 index 0000000..50ac73f --- /dev/null +++ b/Sources/PulseDefs.h @@ -0,0 +1,56 @@ +// Copyright (C) 2024 kanel +// This file is part of "Pulse" +// For conditions of distribution and use, see copyright notice in LICENSE + +#ifndef PULSE_DEFS_H_ +#define PULSE_DEFS_H_ + +#include + +#define PulseStaticAllocStack(size) ((char[size]){ 0 }) + +#define PULSE_CHECK_ALLOCATION_RETVAL(ptr, retval) \ + do { \ + if(ptr == PULSE_NULLPTR) \ + { \ + PulseSetInternalError(PULSE_ERROR_CPU_ALLOCATION_FAILED); \ + return retval; \ + } \ + } while(0); \ + +#define PULSE_CHECK_ALLOCATION(ptr) PULSE_CHECK_ALLOCATION_RETVAL(ptr, ) + +#define PULSE_CHECK_HANDLE_RETVAL(handle, retval) \ + do { \ + if(handle == PULSE_NULL_HANDLE) \ + { \ + PulseSetInternalError(PULSE_ERROR_INVALID_HANDLE); \ + return retval; \ + } \ + } while(0); \ + +#define PULSE_CHECK_HANDLE(handle) PULSE_CHECK_HANDLE_RETVAL(handle, ) + +#define PULSE_CHECK_PTR_RETVAL(ptr, retval) \ + do { \ + if(ptr == PULSE_NULLPTR) \ + { \ + PulseSetInternalError(PULSE_ERROR_INVALID_INTERNAL_POINTER); \ + return retval; \ + } \ + } while(0); \ + +#define PULSE_CHECK_PTR(handle) PULSE_CHECK_PTR_RETVAL(handle, ) + +#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) \ + PULSE_LOAD_DRIVER_DEVICE_FUNCTION(CreateComputePipeline, _namespace) \ + PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyComputePipeline, _namespace) \ + PULSE_LOAD_DRIVER_DEVICE_FUNCTION(BindComputePipeline, _namespace) \ + PULSE_LOAD_DRIVER_DEVICE_FUNCTION(CreateFence, _namespace) \ + PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyFence, _namespace) \ + PULSE_LOAD_DRIVER_DEVICE_FUNCTION(IsFenceReady, _namespace) \ + PULSE_LOAD_DRIVER_DEVICE_FUNCTION(WaitForFences, _namespace) \ + +#endif // PULSE_DEFS_H_ diff --git a/Sources/PulseEnums.h b/Sources/PulseEnums.h new file mode 100644 index 0000000..dcf7b46 --- /dev/null +++ b/Sources/PulseEnums.h @@ -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 + +#ifndef PULSE_ENUMS_H_ +#define PULSE_ENUMS_H_ + +typedef enum PulseCommandListState +{ + PULSE_COMMAND_LIST_STATE_INVALID, + PULSE_COMMAND_LIST_STATE_EMPTY, + PULSE_COMMAND_LIST_STATE_RECORDING, + PULSE_COMMAND_LIST_STATE_READY, + PULSE_COMMAND_LIST_STATE_SENT +} PulseCommandListState; + +typedef enum PulseErrorType +{ + PULSE_ERROR_NONE, + + PULSE_ERROR_DEVICE_LOST, + PULSE_ERROR_INVALID_HANDLE, + PULSE_ERROR_INVALID_INTERNAL_POINTER, + PULSE_ERROR_INITIALIZATION_FAILED, + PULSE_ERROR_CPU_ALLOCATION_FAILED, + PULSE_ERROR_DEVICE_ALLOCATION_FAILED, + PULSE_ERROR_BACKENDS_CANDIDATES_SHADER_FORMAT_MISMATCH, +} PulseErrorType; + +typedef enum PulseWarningType +{ + PULSE_WARNING_NONE, +} PulseWarningType; + +#endif diff --git a/Sources/PulseInternal.h b/Sources/PulseInternal.h index 8ce3c4d..ac20d50 100644 --- a/Sources/PulseInternal.h +++ b/Sources/PulseInternal.h @@ -7,48 +7,11 @@ #include -#ifdef __cplusplus -extern "C" { -#endif +#include "PulsePFNs.h" +#include "PulseDefs.h" +#include "PulseEnums.h" -#define PulseStaticAllocStack(size) ((char[size]){ 0 }) - -#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, ) - -#define PULSE_CHECK_HANDLE_RETVAL(handle, retval) \ - do { \ - if(handle == PULSE_NULL_HANDLE) \ - { \ - PulseSetInternalError(PULSE_ERROR_INVALID_HANDLE); \ - return retval; \ - } \ - } while(0); \ - -#define PULSE_CHECK_HANDLE(handle) PULSE_CHECK_HANDLE_RETVAL(handle, ) - -typedef PulseBackendFlags (*PulseCheckBackendSupportPFN)(PulseBackendFlags, PulseShaderFormatsFlags); - -typedef bool (*PulseLoadBackendPFN)(PulseDebugLevel); -typedef void (*PulseUnloadBackendPFN)(PulseBackend); -typedef PulseDevice (*PulseCreateDevicePFN)(PulseBackend, PulseDevice*, uint32_t); - -typedef void (*PulseDestroyDevicePFN)(PulseDevice); -typedef PulseComputePipeline (*PulseCreateComputePipelinePFN)(PulseDevice, const PulseComputePipelineCreateInfo*); -typedef void (*PulseBindComputePipelinePFN)(PulseComputePass, PulseComputePipeline); -typedef void (*PulseDestroyComputePipelinePFN)(PulseDevice, PulseComputePipeline); -typedef PulseFence (*PulseCreateFencePFN)(PulseDevice device); -typedef void (*PulseDestroyFencePFN)(PulseDevice device, PulseFence fence); -typedef bool (*PulseIsFenceReadyPFN)(PulseDevice device, PulseFence fence); -typedef bool (*PulseWaitForFencesPFN)(PulseDevice device, PulseFence* const* fences, uint32_t fences_count, bool wait_for_all); +typedef uint64_t PulseThreadID; typedef struct PulseBackendHandler { @@ -61,8 +24,32 @@ typedef struct PulseBackendHandler PulseBackendFlags backend; PulseShaderFormatsFlags supported_shader_formats; void* driver_data; + PulseDebugCallbackPFN PFN_UserDebugCallback; } PulseBackendHandler; +typedef struct PulseBufferHandler +{ + void* driver_data; +} PulseBufferHandler; + +typedef struct PulseCommandListHandler +{ + PulseDevice device; + void* driver_data; + PulseCommandListState state; + bool is_compute_pipeline_bound; +} PulseCommandListHandler; + +typedef struct PulseComputePassHandler +{ + void* driver_data; +} PulseComputePassHandler; + +typedef struct PulseComputePipelineHandler +{ + void* driver_data; +} PulseComputePipelineHandler; + typedef struct PulseDeviceHandler { // PFNs @@ -85,18 +72,25 @@ typedef struct PulseFenceHandler void* driver_data; } PulseFenceHandler; -void PulseSetInternalError(PulseErrorType error); +typedef struct PulseGeneralPassHandler +{ + void* driver_data; +} PulseGeneralPassHandler; -#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) \ - PULSE_LOAD_DRIVER_DEVICE_FUNCTION(CreateComputePipeline, _namespace) \ - PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyComputePipeline, _namespace) \ - PULSE_LOAD_DRIVER_DEVICE_FUNCTION(BindComputePipeline, _namespace) \ - PULSE_LOAD_DRIVER_DEVICE_FUNCTION(CreateFence, _namespace) \ - PULSE_LOAD_DRIVER_DEVICE_FUNCTION(DestroyFence, _namespace) \ - PULSE_LOAD_DRIVER_DEVICE_FUNCTION(IsFenceReady, _namespace) \ - PULSE_LOAD_DRIVER_DEVICE_FUNCTION(WaitForFences, _namespace) \ +typedef struct PulseImageHandler +{ + void* driver_data; +} PulseImageHandler; + +PulseThreadID PulseGetThreadID(); + +void PulseLogErrorBackend(PulseBackend backend, PulseErrorType error, const char* file, const char* function, int line); +void PulseLogWarningBackend(PulseBackend backend, PulseWarningType warning, const char* file, const char* function, int line); +void PulseLogInfoBackend(PulseBackend backend, const char* message, const char* file, const char* function, int line); + +#define PulseLogError(backend, type) PulseSetInternalErrorBackend(backend, type, __FILE__, __FUNCTION__, __LINE__) +#define PulseLogWarning(backend, type) PulseSetInternalErrorBackend(backend, type, __FILE__, __FUNCTION__, __LINE__) +#define PulseLogInfo(backend, msg) PulseSetInternalErrorBackend(backend, msg, __FILE__, __FUNCTION__, __LINE__) #ifdef PULSE_ENABLE_VULKAN_BACKEND extern PulseBackendHandler VulkanDriver; @@ -105,8 +99,4 @@ void PulseSetInternalError(PulseErrorType error); extern PulseBackendHandler D3D11Driver; #endif // PULSE_ENABLE_D3D11_BACKEND -#ifdef __cplusplus -} -#endif - #endif // PULSE_INTERNAL_H_ diff --git a/Sources/PulsePFNs.h b/Sources/PulsePFNs.h new file mode 100644 index 0000000..b6ed4a0 --- /dev/null +++ b/Sources/PulsePFNs.h @@ -0,0 +1,25 @@ +// Copyright (C) 2024 kanel +// This file is part of "Pulse" +// For conditions of distribution and use, see copyright notice in LICENSE + +#ifndef PULSE_PFNS_H_ +#define PULSE_PFNS_H_ + +#include + +typedef PulseBackendFlags (*PulseCheckBackendSupportPFN)(PulseBackendFlags, PulseShaderFormatsFlags); + +typedef bool (*PulseLoadBackendPFN)(PulseDebugLevel); +typedef void (*PulseUnloadBackendPFN)(PulseBackend); +typedef PulseDevice (*PulseCreateDevicePFN)(PulseBackend, PulseDevice*, uint32_t); + +typedef void (*PulseDestroyDevicePFN)(PulseDevice); +typedef PulseComputePipeline (*PulseCreateComputePipelinePFN)(PulseDevice, const PulseComputePipelineCreateInfo*); +typedef void (*PulseBindComputePipelinePFN)(PulseComputePass, PulseComputePipeline); +typedef void (*PulseDestroyComputePipelinePFN)(PulseDevice, PulseComputePipeline); +typedef PulseFence (*PulseCreateFencePFN)(PulseDevice); +typedef void (*PulseDestroyFencePFN)(PulseDevice, PulseFence); +typedef bool (*PulseIsFenceReadyPFN)(PulseDevice, PulseFence); +typedef bool (*PulseWaitForFencesPFN)(PulseDevice, const PulseFence*, uint32_t, bool); + +#endif // PULSE_PFNS_H_ diff --git a/Sources/PulsePosix.c b/Sources/PulsePosix.c new file mode 100644 index 0000000..5906f48 --- /dev/null +++ b/Sources/PulsePosix.c @@ -0,0 +1,15 @@ +// 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 "PulsePosix.h" + +#ifdef PULSE_PLAT_POSIX + +PulseThreadID PulseGetThreadID() +{ + return (PulseThreadID)pthread_self(); +} + +#endif // PULSE_PLAT_POSIX diff --git a/Sources/PulsePosix.h b/Sources/PulsePosix.h new file mode 100644 index 0000000..d2c55f6 --- /dev/null +++ b/Sources/PulsePosix.h @@ -0,0 +1,17 @@ +// Copyright (C) 2024 kanel +// This file is part of "Pulse" +// For conditions of distribution and use, see copyright notice in LICENSE + +#ifndef PULSE_POSIX_H_ +#define PULSE_POSIX_H_ + +#include +#include "PulseInternal.h" + +#ifdef PULSE_PLAT_POSIX + +#include + +#endif // PULSE_PLAT_WINDOWS + +#endif // PULSE_POSIX_H_ diff --git a/Sources/PulseWindows.c b/Sources/PulseWindows.c new file mode 100644 index 0000000..1da1a51 --- /dev/null +++ b/Sources/PulseWindows.c @@ -0,0 +1,15 @@ +// 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 "PulseWindows.h" + +#ifdef PULSE_PLAT_WINDOWS + +PulseThreadID PulseGetThreadID() +{ + return (PulseThreadID)GetCurrentThreadId(); +} + +#endif // PULSE_PLAT_WINDOWS diff --git a/Sources/PulseWindows.h b/Sources/PulseWindows.h new file mode 100644 index 0000000..6290e15 --- /dev/null +++ b/Sources/PulseWindows.h @@ -0,0 +1,18 @@ +// Copyright (C) 2024 kanel +// This file is part of "Pulse" +// For conditions of distribution and use, see copyright notice in LICENSE + +#ifndef PULSE_WINDOWS_H_ +#define PULSE_WINDOWS_H_ + +#include +#include "PulseInternal.h" + +#ifdef PULSE_PLAT_WINDOWS + +#define NOMINMAX +#include + +#endif // PULSE_PLAT_WINDOWS + +#endif // PULSE_WINDOWS_H_ diff --git a/xmake.lua b/xmake.lua index 1203901..2028185 100644 --- a/xmake.lua +++ b/xmake.lua @@ -41,7 +41,7 @@ end add_rules("mode.debug", "mode.release") add_includedirs("Includes") -set_languages("c99", "cxx20") +set_languages("c11", "cxx20") set_encodings("utf-8") set_warnings("allextra")