Backend selection + swapchain API revision (#23)

- The application must now call `Refresh_SetBackend` before creating the device
- `Refresh_SetBackend` can set a preferred backend, but will fall back if it is not available
- Device creation no longer takes presentation parameters
- Windows must now be explicitly claimed by the device
- Windows can be unclaimed by the device
- Windows can have their swapchain present mode changed after creation

Reviewed-on: MoonsideGames/Refresh#23
anisotropy
cosmonaut 2022-09-29 21:11:25 +00:00
parent 5176f790d8
commit 1a0beea402
4 changed files with 315 additions and 108 deletions

View File

@ -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
@ -375,12 +383,6 @@ typedef struct Refresh_TextureSlice
uint32_t level; uint32_t level;
} Refresh_TextureSlice; } Refresh_TextureSlice;
typedef struct Refresh_PresentationParameters
{
void* deviceWindowHandle;
Refresh_PresentMode presentMode;
} Refresh_PresentationParameters;
/* State structures */ /* State structures */
typedef struct Refresh_SamplerStateCreateInfo typedef struct Refresh_SamplerStateCreateInfo
@ -594,15 +596,29 @@ 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, and fills in a window flag bitmask.
* This bitmask should be used to create all windows that the device claims.
*
* 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.
* debugMode: Enable debug mode properties. * debugMode: Enable debug mode properties.
*/ */
REFRESHAPI Refresh_Device* Refresh_CreateDevice( REFRESHAPI Refresh_Device* Refresh_CreateDevice(
Refresh_PresentationParameters *presentationParameters,
uint8_t debugMode uint8_t debugMode
); );
@ -1115,6 +1131,41 @@ REFRESHAPI void Refresh_BindComputeTextures(
/* Submission/Presentation */ /* Submission/Presentation */
/* Claims a window, creating a swapchain structure for it.
* This function MUST be called before any swapchain functions
* are called using the window.
*
* Returns 0 on swapchain creation failure.
*/
REFRESHAPI uint8_t Refresh_ClaimWindow(
Refresh_Device *device,
void *windowHandle,
Refresh_PresentMode presentMode
);
/* Unclaims a window, destroying the swapchain structure for it.
* It is good practice to call this when a window is closed to
* prevent memory bloat, but windows are automatically unclaimed
* by DestroyDevice.
*/
REFRESHAPI void Refresh_UnclaimWindow(
Refresh_Device *device,
void *windowHandle
);
/* Changes the present mode of the swapchain for the given window. */
REFRESHAPI void Refresh_SetSwapchainPresentMode(
Refresh_Device *device,
void *windowHandle,
Refresh_PresentMode presentMode
);
/* Returns the format of the swapchain for the given window. */
REFRESHAPI Refresh_TextureFormat Refresh_GetSwapchainFormat(
Refresh_Device *device,
void *windowHandle
);
/* Returns an allocated Refresh_CommandBuffer* object. /* Returns an allocated Refresh_CommandBuffer* object.
* This command buffer is managed by the implementation and * This command buffer is managed by the implementation and
* should NOT be freed by the user. * should NOT be freed by the user.
@ -1154,12 +1205,6 @@ REFRESHAPI Refresh_Texture* Refresh_AcquireSwapchainTexture(
uint32_t *pHeight uint32_t *pHeight
); );
/* Returns the format of the swapchain for the given window. */
REFRESHAPI Refresh_TextureFormat Refresh_GetSwapchainFormat(
Refresh_Device *device,
void *windowHandle
);
/* Submits all of the enqueued commands. */ /* Submits all of the enqueued commands. */
REFRESHAPI void Refresh_Submit( REFRESHAPI void Refresh_Submit(
Refresh_Device* device, Refresh_Device* device,

View File

@ -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,19 +130,54 @@ 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 (i != preferredBackend && 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,
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,
debugMode debugMode
); );
} }
@ -722,6 +758,30 @@ void Refresh_BindComputeTextures(
); );
} }
uint8_t Refresh_ClaimWindow(
Refresh_Device *device,
void *windowHandle,
Refresh_PresentMode presentMode
) {
if (device == NULL) { return 0; }
return device->ClaimWindow(
device->driverData,
windowHandle,
presentMode
);
}
void Refresh_UnclaimWindow(
Refresh_Device *device,
void *windowHandle
) {
NULL_RETURN(device);
device->UnclaimWindow(
device->driverData,
windowHandle
);
}
Refresh_CommandBuffer* Refresh_AcquireCommandBuffer( Refresh_CommandBuffer* Refresh_AcquireCommandBuffer(
Refresh_Device *device, Refresh_Device *device,
uint8_t fixed uint8_t fixed
@ -761,6 +821,19 @@ Refresh_TextureFormat Refresh_GetSwapchainFormat(
); );
} }
void Refresh_SetSwapchainPresentMode(
Refresh_Device *device,
void *windowHandle,
Refresh_PresentMode presentMode
) {
NULL_RETURN(device);
device->SetSwapchainPresentMode(
device->driverData,
windowHandle,
presentMode
);
}
void Refresh_Submit( void Refresh_Submit(
Refresh_Device *device, Refresh_Device *device,
uint32_t commandBufferCount, uint32_t commandBufferCount,

View File

@ -459,6 +459,17 @@ struct Refresh_Device
Refresh_Texture **pTextures Refresh_Texture **pTextures
); );
uint8_t (*ClaimWindow)(
Refresh_Renderer *driverData,
void *windowHandle,
Refresh_PresentMode presentMode
);
void(*UnclaimWindow)(
Refresh_Renderer *driverData,
void *windowHandle
);
Refresh_CommandBuffer* (*AcquireCommandBuffer)( Refresh_CommandBuffer* (*AcquireCommandBuffer)(
Refresh_Renderer *driverData, Refresh_Renderer *driverData,
uint8_t fixed uint8_t fixed
@ -477,6 +488,12 @@ struct Refresh_Device
void *windowHandle void *windowHandle
); );
void (*SetSwapchainPresentMode)(
Refresh_Renderer *driverData,
void *windowHandle,
Refresh_PresentMode presentMode
);
void(*Submit)( void(*Submit)(
Refresh_Renderer *driverData, Refresh_Renderer *driverData,
uint32_t commandBufferCount, uint32_t commandBufferCount,
@ -533,17 +550,20 @@ struct Refresh_Device
ASSIGN_DRIVER_FUNC(BindComputePipeline, name) \ ASSIGN_DRIVER_FUNC(BindComputePipeline, name) \
ASSIGN_DRIVER_FUNC(BindComputeBuffers, name) \ ASSIGN_DRIVER_FUNC(BindComputeBuffers, name) \
ASSIGN_DRIVER_FUNC(BindComputeTextures, name) \ ASSIGN_DRIVER_FUNC(BindComputeTextures, name) \
ASSIGN_DRIVER_FUNC(ClaimWindow, name) \
ASSIGN_DRIVER_FUNC(UnclaimWindow, name) \
ASSIGN_DRIVER_FUNC(AcquireCommandBuffer, name) \ ASSIGN_DRIVER_FUNC(AcquireCommandBuffer, name) \
ASSIGN_DRIVER_FUNC(AcquireSwapchainTexture, name) \ ASSIGN_DRIVER_FUNC(AcquireSwapchainTexture, name) \
ASSIGN_DRIVER_FUNC(GetSwapchainFormat, name) \ ASSIGN_DRIVER_FUNC(GetSwapchainFormat, name) \
ASSIGN_DRIVER_FUNC(SetSwapchainPresentMode, name) \
ASSIGN_DRIVER_FUNC(Submit, name) \ ASSIGN_DRIVER_FUNC(Submit, name) \
ASSIGN_DRIVER_FUNC(Wait, name) ASSIGN_DRIVER_FUNC(Wait, name)
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,
uint8_t debugMode uint8_t debugMode
); );
} Refresh_Driver; } Refresh_Driver;

View File

@ -1691,8 +1691,6 @@ typedef struct VulkanRenderer
VkQueue computeQueue; VkQueue computeQueue;
VkQueue transferQueue; VkQueue transferQueue;
Refresh_PresentMode presentMode;
VulkanCommandBuffer **submittedCommandBuffers; VulkanCommandBuffer **submittedCommandBuffers;
uint32_t submittedCommandBufferCount; uint32_t submittedCommandBufferCount;
uint32_t submittedCommandBufferCapacity; uint32_t submittedCommandBufferCapacity;
@ -4252,7 +4250,8 @@ static uint8_t VULKAN_INTERNAL_ChooseSwapPresentMode(
static uint8_t VULKAN_INTERNAL_CreateSwapchain( static uint8_t VULKAN_INTERNAL_CreateSwapchain(
VulkanRenderer *renderer, VulkanRenderer *renderer,
void *windowHandle void *windowHandle,
Refresh_PresentMode presentMode
) { ) {
VkResult vulkanResult; VkResult vulkanResult;
VulkanSwapchainData *swapchainData; VulkanSwapchainData *swapchainData;
@ -4351,7 +4350,7 @@ static uint8_t VULKAN_INTERNAL_CreateSwapchain(
} }
if (!VULKAN_INTERNAL_ChooseSwapPresentMode( if (!VULKAN_INTERNAL_ChooseSwapPresentMode(
renderer->presentMode, presentMode,
swapchainSupportDetails.presentModes, swapchainSupportDetails.presentModes,
swapchainSupportDetails.presentModesLength, swapchainSupportDetails.presentModesLength,
&swapchainData->presentMode &swapchainData->presentMode
@ -4642,11 +4641,12 @@ static uint8_t VULKAN_INTERNAL_CreateSwapchain(
static void VULKAN_INTERNAL_RecreateSwapchain( static void VULKAN_INTERNAL_RecreateSwapchain(
VulkanRenderer* renderer, VulkanRenderer* renderer,
void *windowHandle void *windowHandle,
Refresh_PresentMode presentMode
) { ) {
VULKAN_Wait((Refresh_Renderer*) renderer); VULKAN_Wait((Refresh_Renderer*) renderer);
VULKAN_INTERNAL_DestroySwapchain(renderer, windowHandle); VULKAN_INTERNAL_DestroySwapchain(renderer, windowHandle);
VULKAN_INTERNAL_CreateSwapchain(renderer, windowHandle); VULKAN_INTERNAL_CreateSwapchain(renderer, windowHandle, presentMode);
} }
/* Command Buffers */ /* Command Buffers */
@ -9265,22 +9265,39 @@ static Refresh_CommandBuffer* VULKAN_AcquireCommandBuffer(
} }
static VulkanSwapchainData* VULKAN_INTERNAL_FetchSwapchainData( static VulkanSwapchainData* VULKAN_INTERNAL_FetchSwapchainData(
VulkanRenderer *renderer,
void *windowHandle void *windowHandle
) { ) {
VulkanSwapchainData *swapchainData = NULL; return (VulkanSwapchainData*) SDL_GetWindowData(windowHandle, WINDOW_SWAPCHAIN_DATA);
}
swapchainData = (VulkanSwapchainData*) SDL_GetWindowData(windowHandle, WINDOW_SWAPCHAIN_DATA); static uint8_t VULKAN_ClaimWindow(
Refresh_Renderer *driverData,
void *windowHandle,
Refresh_PresentMode presentMode
) {
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanSwapchainData *swapchainData = VULKAN_INTERNAL_FetchSwapchainData(windowHandle);
if (swapchainData == NULL) if (swapchainData == NULL)
{ {
if (VULKAN_INTERNAL_CreateSwapchain(renderer, windowHandle)) return VULKAN_INTERNAL_CreateSwapchain(renderer, windowHandle, presentMode);
}
else
{ {
swapchainData = (VulkanSwapchainData*) SDL_GetWindowData(windowHandle, WINDOW_SWAPCHAIN_DATA); Refresh_LogWarn("Window already claimed!");
return 0;
} }
} }
return swapchainData; static void VULKAN_UnclaimWindow(
Refresh_Renderer *driverData,
void *windowHandle
) {
VULKAN_Wait(driverData);
VULKAN_INTERNAL_DestroySwapchain(
(VulkanRenderer*) driverData,
windowHandle
);
} }
static Refresh_Texture* VULKAN_AcquireSwapchainTexture( static Refresh_Texture* VULKAN_AcquireSwapchainTexture(
@ -9298,10 +9315,11 @@ static Refresh_Texture* VULKAN_AcquireSwapchainTexture(
VulkanTexture *swapchainTexture = NULL; VulkanTexture *swapchainTexture = NULL;
VulkanPresentData *presentData; VulkanPresentData *presentData;
swapchainData = VULKAN_INTERNAL_FetchSwapchainData(renderer, windowHandle); swapchainData = VULKAN_INTERNAL_FetchSwapchainData(windowHandle);
if (swapchainData == NULL) if (swapchainData == NULL)
{ {
Refresh_LogError("Cannot acquire swapchain texture, window has not been claimed!");
return NULL; return NULL;
} }
@ -9317,12 +9335,15 @@ static Refresh_Texture* VULKAN_AcquireSwapchainTexture(
/* Swapchain is invalid, let's try to recreate */ /* Swapchain is invalid, let's try to recreate */
if (acquireResult != VK_SUCCESS && acquireResult != VK_SUBOPTIMAL_KHR) if (acquireResult != VK_SUCCESS && acquireResult != VK_SUBOPTIMAL_KHR)
{ {
VULKAN_INTERNAL_RecreateSwapchain(renderer, windowHandle); swapchainData = VULKAN_INTERNAL_FetchSwapchainData(windowHandle);
swapchainData = VULKAN_INTERNAL_FetchSwapchainData(renderer, windowHandle); VULKAN_INTERNAL_RecreateSwapchain(renderer, windowHandle, swapchainData->presentMode);
swapchainData = VULKAN_INTERNAL_FetchSwapchainData(windowHandle);
if (swapchainData == NULL) if (swapchainData == NULL)
{ {
Refresh_LogWarn("Failed to recreate swapchain!");
return NULL; return NULL;
} }
@ -9433,6 +9454,26 @@ static Refresh_TextureFormat VULKAN_GetSwapchainFormat(
} }
} }
static void VULKAN_SetSwapchainPresentMode(
Refresh_Renderer *driverData,
void *windowHandle,
Refresh_PresentMode presentMode
) {
VulkanSwapchainData *swapchainData = (VulkanSwapchainData*) SDL_GetWindowData(windowHandle, WINDOW_SWAPCHAIN_DATA);
if (swapchainData == NULL)
{
Refresh_LogWarn("Cannot set present mode, window has not been claimed!");
return;
}
VULKAN_INTERNAL_RecreateSwapchain(
(VulkanRenderer *)driverData,
windowHandle,
presentMode
);
}
/* Submission structure */ /* Submission structure */
static void VULKAN_INTERNAL_PerformPendingDestroys( static void VULKAN_INTERNAL_PerformPendingDestroys(
@ -9842,7 +9883,11 @@ static void VULKAN_Submit(
if (presentResult != VK_SUCCESS) if (presentResult != VK_SUCCESS)
{ {
VULKAN_INTERNAL_RecreateSwapchain(renderer, presentData->swapchainData->windowHandle); VULKAN_INTERNAL_RecreateSwapchain(
renderer,
presentData->swapchainData->windowHandle,
presentData->swapchainData->presentMode
);
} }
} }
} }
@ -10285,9 +10330,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 +10556,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,12 +10588,96 @@ static void VULKAN_INTERNAL_LoadEntryPoints(
#include "Refresh_Driver_Vulkan_vkfuncs.h" #include "Refresh_Driver_Vulkan_vkfuncs.h"
} }
static uint8_t VULKAN_INTERNAL_PrepareVulkan(
VulkanRenderer *renderer
) {
SDL_Window *dummyWindowHandle;
VkSurfaceKHR surface;
VULKAN_INTERNAL_LoadEntryPoints();
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;
}
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"
if (!VULKAN_INTERNAL_DeterminePhysicalDevice(renderer, surface))
{
return 0;
}
renderer->vkDestroySurfaceKHR(
renderer->instance,
surface,
NULL
);
SDL_DestroyWindow(dummyWindowHandle);
return 1;
}
static uint8_t VULKAN_PrepareDriver(uint32_t *flags)
{
/* Set up dummy VulkanRenderer */
VulkanRenderer *renderer = (VulkanRenderer*) SDL_malloc(sizeof(VulkanRenderer));
uint8_t result;
SDL_memset(renderer, '\0', sizeof(VulkanRenderer));
result = VULKAN_INTERNAL_PrepareVulkan(renderer);
if (!result)
{
Refresh_LogWarn("Vulkan: Failed to determine a suitable physical device");
}
else
{
*flags = SDL_WINDOW_VULKAN;
}
renderer->vkDestroyInstance(renderer->instance, NULL);
SDL_free(renderer);
return result;
}
static Refresh_Device* VULKAN_CreateDevice( static Refresh_Device* VULKAN_CreateDevice(
Refresh_PresentationParameters *presentationParameters,
uint8_t debugMode uint8_t debugMode
) { ) {
VulkanRenderer *renderer = (VulkanRenderer*) SDL_malloc(sizeof(VulkanRenderer)); VulkanRenderer *renderer = (VulkanRenderer*) SDL_malloc(sizeof(VulkanRenderer));
VkSurfaceKHR surface;
Refresh_Device *result; Refresh_Device *result;
VkResult vulkanResult; VkResult vulkanResult;
@ -10576,66 +10702,14 @@ static Refresh_Device* VULKAN_CreateDevice(
/* Variables: Image Format Detection */ /* Variables: Image Format Detection */
VkImageFormatProperties imageFormatProperties; VkImageFormatProperties imageFormatProperties;
VULKAN_INTERNAL_LoadEntryPoints(renderer);
renderer->presentMode = presentationParameters->presentMode;
renderer->debugMode = debugMode; renderer->debugMode = debugMode;
/* Create the VkInstance */ if (!VULKAN_INTERNAL_PrepareVulkan(renderer))
if (!VULKAN_INTERNAL_CreateInstance(renderer, presentationParameters->deviceWindowHandle))
{ {
Refresh_LogError("Error creating vulkan instance"); Refresh_LogError("Failed to initialize Vulkan!");
return NULL; return NULL;
} }
/*
* Create the WSI vkSurface
*/
if (!SDL_Vulkan_CreateSurface(
(SDL_Window*)presentationParameters->deviceWindowHandle,
renderer->instance,
&surface
)) {
Refresh_LogError(
"SDL_Vulkan_CreateSurface failed: %s",
SDL_GetError()
);
return NULL;
}
/*
* Get vkInstance entry points
*/
#define VULKAN_INSTANCE_FUNCTION(ext, ret, func, params) \
renderer->func = (vkfntype_##func) vkGetInstanceProcAddr(renderer->instance, #func);
#include "Refresh_Driver_Vulkan_vkfuncs.h"
/*
* Choose/Create vkDevice
*/
if (SDL_strcmp(SDL_GetPlatform(), "Stadia") != 0)
{
deviceExtensionCount -= 1;
}
if (!VULKAN_INTERNAL_DeterminePhysicalDevice(
renderer,
surface,
deviceExtensionNames,
deviceExtensionCount
)) {
Refresh_LogError("Failed to determine a suitable physical device");
return NULL;
}
renderer->vkDestroySurfaceKHR(
renderer->instance,
surface,
NULL
);
Refresh_LogInfo("Refresh Driver: Vulkan"); Refresh_LogInfo("Refresh Driver: Vulkan");
Refresh_LogInfo( Refresh_LogInfo(
"Vulkan Device: %s", "Vulkan Device: %s",
@ -10677,7 +10751,7 @@ static Refresh_Device* VULKAN_CreateDevice(
result->driverData = (Refresh_Renderer*) renderer; result->driverData = (Refresh_Renderer*) renderer;
/* /*
* Create initial swapchain * Create initial swapchain array
*/ */
renderer->swapchainDataCapacity = 1; renderer->swapchainDataCapacity = 1;
@ -10686,12 +10760,6 @@ static Refresh_Device* VULKAN_CreateDevice(
renderer->swapchainDataCapacity * sizeof(VulkanSwapchainData*) renderer->swapchainDataCapacity * sizeof(VulkanSwapchainData*)
); );
if (!VULKAN_INTERNAL_CreateSwapchain(renderer, presentationParameters->deviceWindowHandle))
{
Refresh_LogError("Failed to create swapchain");
return NULL;
}
/* Threading */ /* Threading */
renderer->allocatorLock = SDL_CreateMutex(); renderer->allocatorLock = SDL_CreateMutex();
@ -11124,6 +11192,7 @@ static Refresh_Device* VULKAN_CreateDevice(
Refresh_Driver VulkanDriver = { Refresh_Driver VulkanDriver = {
"Vulkan", "Vulkan",
VULKAN_PrepareDriver,
VULKAN_CreateDevice VULKAN_CreateDevice
}; };