initial backend selection implementation
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
5176f790d8
commit
c0e4e50863
|
@ -332,6 +332,14 @@ typedef enum Refresh_BorderColor
|
||||||
REFRESH_BORDERCOLOR_INT_OPAQUE_WHITE
|
REFRESH_BORDERCOLOR_INT_OPAQUE_WHITE
|
||||||
} Refresh_BorderColor;
|
} Refresh_BorderColor;
|
||||||
|
|
||||||
|
typedef enum Refresh_Backend
|
||||||
|
{
|
||||||
|
REFRESH_BACKEND_DONTCARE,
|
||||||
|
REFRESH_BACKEND_VULKAN,
|
||||||
|
REFRESH_BACKEND_PS5,
|
||||||
|
REFRESH_BACKEND_INVALID
|
||||||
|
} Refresh_Backend;
|
||||||
|
|
||||||
/* Structures */
|
/* Structures */
|
||||||
|
|
||||||
typedef struct Refresh_DepthStencilValue
|
typedef struct Refresh_DepthStencilValue
|
||||||
|
@ -594,9 +602,24 @@ REFRESHAPI void Refresh_HookLogFunctions(
|
||||||
Refresh_LogFunc error
|
Refresh_LogFunc error
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* Backend selection */
|
||||||
|
|
||||||
|
/* Select the graphics API backend that Refresh should use.
|
||||||
|
*
|
||||||
|
* Note that Refresh is not required to select your preferred backend
|
||||||
|
* if it detects an incompatibility.
|
||||||
|
*
|
||||||
|
* Returns the backend that will actually be used.
|
||||||
|
*
|
||||||
|
* preferredBackend: The preferred backend that Refresh should select.
|
||||||
|
* flags: A pointer to a bitflag value that will be filled in with required SDL_WindowFlags masks.
|
||||||
|
*/
|
||||||
|
REFRESHAPI Refresh_Backend Refresh_SelectBackend(Refresh_Backend preferredBackend, uint32_t *flags);
|
||||||
|
|
||||||
/* Device */
|
/* Device */
|
||||||
|
|
||||||
/* Create a rendering context for use on the calling thread.
|
/* Create a rendering context for use on the calling thread.
|
||||||
|
* You MUST have called Refresh_SelectDriver prior to calling this function.
|
||||||
*
|
*
|
||||||
* presentationParameters: A window handle and presentation mode.
|
* presentationParameters: A window handle and presentation mode.
|
||||||
* debugMode: Enable debug mode properties.
|
* debugMode: Enable debug mode properties.
|
||||||
|
|
|
@ -33,7 +33,8 @@
|
||||||
|
|
||||||
/* Drivers */
|
/* Drivers */
|
||||||
|
|
||||||
static const Refresh_Driver *drivers[] = {
|
static const Refresh_Driver *backends[] = {
|
||||||
|
NULL,
|
||||||
#ifdef REFRESH_DRIVER_VULKAN
|
#ifdef REFRESH_DRIVER_VULKAN
|
||||||
&VulkanDriver,
|
&VulkanDriver,
|
||||||
#endif
|
#endif
|
||||||
|
@ -129,18 +130,55 @@ uint32_t Refresh_LinkedVersion(void)
|
||||||
|
|
||||||
/* Driver Functions */
|
/* Driver Functions */
|
||||||
|
|
||||||
static int32_t selectedDriver = 0;
|
static Refresh_Backend selectedBackend = REFRESH_BACKEND_INVALID;
|
||||||
|
|
||||||
|
Refresh_Backend Refresh_SelectBackend(Refresh_Backend preferredBackend, uint32_t *flags)
|
||||||
|
{
|
||||||
|
uint32_t backendIndex, i;
|
||||||
|
|
||||||
|
if (preferredBackend != REFRESH_BACKEND_DONTCARE)
|
||||||
|
{
|
||||||
|
/* Try to force it! */
|
||||||
|
backendIndex = preferredBackend;
|
||||||
|
|
||||||
|
if (backends[backendIndex]->PrepareDriver(flags))
|
||||||
|
{
|
||||||
|
selectedBackend = preferredBackend;
|
||||||
|
return selectedBackend;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Iterate until we find an appropriate backend. */
|
||||||
|
|
||||||
|
for (i = 1; backends[i] != NULL; i += 1)
|
||||||
|
{
|
||||||
|
if (backends[i]->PrepareDriver(flags))
|
||||||
|
{
|
||||||
|
selectedBackend = i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backends[i] == NULL)
|
||||||
|
{
|
||||||
|
Refresh_LogError("No supported Refresh backend found!");
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedBackend = REFRESH_BACKEND_INVALID;
|
||||||
|
return REFRESH_BACKEND_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
Refresh_Device* Refresh_CreateDevice(
|
Refresh_Device* Refresh_CreateDevice(
|
||||||
Refresh_PresentationParameters *presentationParameters,
|
Refresh_PresentationParameters *presentationParameters,
|
||||||
uint8_t debugMode
|
uint8_t debugMode
|
||||||
) {
|
) {
|
||||||
if (selectedDriver < 0)
|
if (selectedBackend == REFRESH_BACKEND_INVALID)
|
||||||
{
|
{
|
||||||
|
Refresh_LogError("Invalid backend selection. Did you call Refresh_SelectBackend?");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return drivers[selectedDriver]->CreateDevice(
|
return backends[selectedBackend]->CreateDevice(
|
||||||
presentationParameters,
|
presentationParameters,
|
||||||
debugMode
|
debugMode
|
||||||
);
|
);
|
||||||
|
|
|
@ -542,6 +542,7 @@ struct Refresh_Device
|
||||||
typedef struct Refresh_Driver
|
typedef struct Refresh_Driver
|
||||||
{
|
{
|
||||||
const char *Name;
|
const char *Name;
|
||||||
|
uint8_t (*PrepareDriver)(uint32_t *flags);
|
||||||
Refresh_Device* (*CreateDevice)(
|
Refresh_Device* (*CreateDevice)(
|
||||||
Refresh_PresentationParameters *presentationParameters,
|
Refresh_PresentationParameters *presentationParameters,
|
||||||
uint8_t debugMode
|
uint8_t debugMode
|
||||||
|
|
|
@ -10285,9 +10285,7 @@ static void VULKAN_INTERNAL_GetPhysicalDeviceProperties(
|
||||||
|
|
||||||
static uint8_t VULKAN_INTERNAL_DeterminePhysicalDevice(
|
static uint8_t VULKAN_INTERNAL_DeterminePhysicalDevice(
|
||||||
VulkanRenderer *renderer,
|
VulkanRenderer *renderer,
|
||||||
VkSurfaceKHR surface,
|
VkSurfaceKHR surface
|
||||||
const char **deviceExtensionNames,
|
|
||||||
uint32_t deviceExtensionCount
|
|
||||||
) {
|
) {
|
||||||
VkResult vulkanResult;
|
VkResult vulkanResult;
|
||||||
VkPhysicalDevice *physicalDevices;
|
VkPhysicalDevice *physicalDevices;
|
||||||
|
@ -10513,9 +10511,8 @@ static uint8_t VULKAN_INTERNAL_CreateLogicalDevice(
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void VULKAN_INTERNAL_LoadEntryPoints(
|
static void VULKAN_INTERNAL_LoadEntryPoints()
|
||||||
VulkanRenderer *renderer
|
{
|
||||||
) {
|
|
||||||
/* Load Vulkan entry points */
|
/* Load Vulkan entry points */
|
||||||
if (SDL_Vulkan_LoadLibrary(NULL) < 0)
|
if (SDL_Vulkan_LoadLibrary(NULL) < 0)
|
||||||
{
|
{
|
||||||
|
@ -10546,6 +10543,83 @@ static void VULKAN_INTERNAL_LoadEntryPoints(
|
||||||
#include "Refresh_Driver_Vulkan_vkfuncs.h"
|
#include "Refresh_Driver_Vulkan_vkfuncs.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t VULKAN_PrepareDriver(uint32_t *flags)
|
||||||
|
{
|
||||||
|
SDL_Window *dummyWindowHandle;
|
||||||
|
VulkanRenderer *renderer;
|
||||||
|
VkSurfaceKHR surface;
|
||||||
|
uint8_t result;
|
||||||
|
|
||||||
|
VULKAN_INTERNAL_LoadEntryPoints();
|
||||||
|
|
||||||
|
/* Test if we can create a Vulkan device */
|
||||||
|
|
||||||
|
dummyWindowHandle = SDL_CreateWindow(
|
||||||
|
"Refresh Vulkan",
|
||||||
|
0, 0,
|
||||||
|
128, 128,
|
||||||
|
SDL_WINDOW_VULKAN | SDL_WINDOW_HIDDEN
|
||||||
|
);
|
||||||
|
|
||||||
|
if (dummyWindowHandle == NULL)
|
||||||
|
{
|
||||||
|
Refresh_LogWarn("Vulkan: Could not create dummy window");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* partially set up VulkanRenderer so we can fall back in case of device non-compliance */
|
||||||
|
renderer = (VulkanRenderer*) SDL_malloc(sizeof(VulkanRenderer));
|
||||||
|
SDL_memset(renderer, '\0', sizeof(VulkanRenderer));
|
||||||
|
|
||||||
|
if (!VULKAN_INTERNAL_CreateInstance(renderer, dummyWindowHandle))
|
||||||
|
{
|
||||||
|
SDL_DestroyWindow(dummyWindowHandle);
|
||||||
|
SDL_free(renderer);
|
||||||
|
Refresh_LogWarn("Vulkan: Could not create Vulkan instance");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SDL_Vulkan_CreateSurface(
|
||||||
|
(SDL_Window*) dummyWindowHandle,
|
||||||
|
renderer->instance,
|
||||||
|
&surface
|
||||||
|
)) {
|
||||||
|
SDL_DestroyWindow(dummyWindowHandle);
|
||||||
|
SDL_free(renderer);
|
||||||
|
Refresh_LogWarn(
|
||||||
|
"SDL_Vulkan_CreateSurface failed: %s",
|
||||||
|
SDL_GetError()
|
||||||
|
);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define VULKAN_INSTANCE_FUNCTION(ext, ret, func, params) \
|
||||||
|
renderer->func = (vkfntype_##func) vkGetInstanceProcAddr(renderer->instance, #func);
|
||||||
|
#include "Refresh_Driver_Vulkan_vkfuncs.h"
|
||||||
|
|
||||||
|
result = VULKAN_INTERNAL_DeterminePhysicalDevice(renderer, surface);
|
||||||
|
|
||||||
|
renderer->vkDestroySurfaceKHR(
|
||||||
|
renderer->instance,
|
||||||
|
surface,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
renderer->vkDestroyInstance(renderer->instance, NULL);
|
||||||
|
SDL_DestroyWindow(dummyWindowHandle);
|
||||||
|
SDL_free(renderer);
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
Refresh_LogWarn("Vulkan: Failed to determine a suitable physical device");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*flags = SDL_WINDOW_VULKAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static Refresh_Device* VULKAN_CreateDevice(
|
static Refresh_Device* VULKAN_CreateDevice(
|
||||||
Refresh_PresentationParameters *presentationParameters,
|
Refresh_PresentationParameters *presentationParameters,
|
||||||
uint8_t debugMode
|
uint8_t debugMode
|
||||||
|
@ -10622,9 +10696,7 @@ static Refresh_Device* VULKAN_CreateDevice(
|
||||||
}
|
}
|
||||||
if (!VULKAN_INTERNAL_DeterminePhysicalDevice(
|
if (!VULKAN_INTERNAL_DeterminePhysicalDevice(
|
||||||
renderer,
|
renderer,
|
||||||
surface,
|
surface
|
||||||
deviceExtensionNames,
|
|
||||||
deviceExtensionCount
|
|
||||||
)) {
|
)) {
|
||||||
Refresh_LogError("Failed to determine a suitable physical device");
|
Refresh_LogError("Failed to determine a suitable physical device");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -11124,6 +11196,7 @@ static Refresh_Device* VULKAN_CreateDevice(
|
||||||
|
|
||||||
Refresh_Driver VulkanDriver = {
|
Refresh_Driver VulkanDriver = {
|
||||||
"Vulkan",
|
"Vulkan",
|
||||||
|
VULKAN_PrepareDriver,
|
||||||
VULKAN_CreateDevice
|
VULKAN_CreateDevice
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue