mirror of
https://github.com/Kbz-8/Pulse.git
synced 2026-01-11 15:33:34 +00:00
127 lines
3.9 KiB
C
127 lines
3.9 KiB
C
// 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"
|
|
|
|
#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, )
|
|
|
|
// Ordered by default preference
|
|
static const PulseBackendLoader* backends[] = {
|
|
#ifdef PULSE_ENABLE_VULKAN_BACKEND
|
|
&VulkanDriver,
|
|
#endif
|
|
#ifdef PULSE_ENABLE_D3D11_BACKEND
|
|
&D3D11Driver,
|
|
#endif
|
|
PULSE_NULLPTR
|
|
};
|
|
|
|
static PulseErrorType last_error = PULSE_ERROR_NONE;
|
|
|
|
void PulseSetInternalError(PulseErrorType error)
|
|
{
|
|
last_error = error;
|
|
}
|
|
|
|
static const PulseBackendLoader* PulseSelectBackend(PulseBackendFlags backend_candidates, PulseShaderFormatsFlags shader_formats_used)
|
|
{
|
|
if((backend_candidates & PULSE_BACKEND_INVALID) != 0)
|
|
{
|
|
PulseSetInternalError(PULSE_ERROR_INITIALIZATION_FAILED);
|
|
return PULSE_NULLPTR;
|
|
}
|
|
for(int i = 0; backends[i] != PULSE_NULLPTR; i++)
|
|
{
|
|
if(backend_candidates != PULSE_BACKEND_ANY && (backend_candidates & backends[i]->backend) == 0)
|
|
continue;
|
|
if((shader_formats_used & backends[i]->supported_shader_formats) == 0)
|
|
{
|
|
PulseSetInternalError(PULSE_ERROR_BACKENDS_CANDIDATES_SHADER_FORMAT_MISMATCH);
|
|
return PULSE_NULLPTR;
|
|
}
|
|
if(backends[i]->PFN_LoadBackend())
|
|
return backends[i];
|
|
}
|
|
PulseSetInternalError(PULSE_ERROR_INITIALIZATION_FAILED);
|
|
return PULSE_NULLPTR;
|
|
}
|
|
|
|
PULSE_API PulseDevice PulseCreateDevice(PulseBackendFlags backend_candidates, PulseShaderFormatsFlags shader_formats_used, PulseDebugLevel debug_level)
|
|
{
|
|
const PulseBackendLoader* backend = PulseSelectBackend(backend_candidates, shader_formats_used);
|
|
if(backend == PULSE_NULLPTR) // Error code already set by PulseSelectBackend
|
|
return PULSE_NULL_HANDLE;
|
|
|
|
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->backend->PFN_DestroyDevice(device);
|
|
}
|
|
|
|
PULSE_API PulseBackendBits PulseGetBackendInUseByDevice(PulseDevice device)
|
|
{
|
|
PULSE_CHECK_HANDLE_RETVAL(device, PULSE_BACKEND_INVALID);
|
|
return device->backend->backend;
|
|
}
|
|
|
|
PULSE_API bool PulseSupportsBackend(PulseBackendFlags backend_candidates, PulseShaderFormatsFlags shader_formats_used)
|
|
{
|
|
if((backend_candidates & PULSE_BACKEND_INVALID) != 0)
|
|
return false;
|
|
if((backend_candidates & PULSE_BACKEND_ANY) != 0)
|
|
return true;
|
|
for(int i = 0; backends[i] != PULSE_NULLPTR; i++)
|
|
{
|
|
if((backend_candidates & backends[i]->backend) == 0)
|
|
continue;
|
|
if((shader_formats_used & backends[i]->supported_shader_formats) != 0)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
PULSE_API bool PulseDeviceSupportsSahderFormats(PulseDevice device, PulseShaderFormatsFlags shader_formats_used)
|
|
{
|
|
PULSE_CHECK_HANDLE_RETVAL(device, false);
|
|
return (device->backend->supported_shader_formats & shader_formats_used) != 0;
|
|
}
|
|
|
|
PULSE_API PulseErrorType PulseGetLastErrorType()
|
|
{
|
|
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";
|
|
|
|
default: return "invalid error type";
|
|
};
|
|
return PULSE_NULLPTR; // To avoid warnings, should be unreachable
|
|
}
|