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; | ||||
| 
 | ||||
| typedef enum Refresh_Backend | ||||
| { | ||||
| 	REFRESH_BACKEND_DONTCARE, | ||||
| 	REFRESH_BACKEND_VULKAN, | ||||
| 	REFRESH_BACKEND_PS5, | ||||
| 	REFRESH_BACKEND_INVALID | ||||
| } Refresh_Backend; | ||||
| 
 | ||||
| /* Structures */ | ||||
| 
 | ||||
| typedef struct Refresh_DepthStencilValue | ||||
|  | @ -594,9 +602,24 @@ REFRESHAPI void Refresh_HookLogFunctions( | |||
| 	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 */ | ||||
| 
 | ||||
| /* 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. | ||||
|  |  | |||
|  | @ -33,7 +33,8 @@ | |||
| 
 | ||||
| /* Drivers */ | ||||
| 
 | ||||
| static const Refresh_Driver *drivers[] = { | ||||
| static const Refresh_Driver *backends[] = { | ||||
| 	NULL, | ||||
| #ifdef REFRESH_DRIVER_VULKAN | ||||
| 	&VulkanDriver, | ||||
| #endif | ||||
|  | @ -129,18 +130,55 @@ uint32_t Refresh_LinkedVersion(void) | |||
| 
 | ||||
| /* 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_PresentationParameters *presentationParameters, | ||||
| 	uint8_t debugMode | ||||
| ) { | ||||
| 	if (selectedDriver < 0) | ||||
| 	if (selectedBackend == REFRESH_BACKEND_INVALID) | ||||
| 	{ | ||||
| 		Refresh_LogError("Invalid backend selection. Did you call Refresh_SelectBackend?"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	return drivers[selectedDriver]->CreateDevice( | ||||
| 	return backends[selectedBackend]->CreateDevice( | ||||
| 		presentationParameters, | ||||
| 		debugMode | ||||
| 	); | ||||
|  |  | |||
|  | @ -542,6 +542,7 @@ struct Refresh_Device | |||
| typedef struct Refresh_Driver | ||||
| { | ||||
| 	const char *Name; | ||||
| 	uint8_t (*PrepareDriver)(uint32_t *flags); | ||||
| 	Refresh_Device* (*CreateDevice)( | ||||
| 		Refresh_PresentationParameters *presentationParameters, | ||||
| 		uint8_t debugMode | ||||
|  |  | |||
|  | @ -10285,9 +10285,7 @@ static void VULKAN_INTERNAL_GetPhysicalDeviceProperties( | |||
| 
 | ||||
| static uint8_t VULKAN_INTERNAL_DeterminePhysicalDevice( | ||||
| 	VulkanRenderer *renderer, | ||||
| 	VkSurfaceKHR surface, | ||||
| 	const char **deviceExtensionNames, | ||||
| 	uint32_t deviceExtensionCount | ||||
| 	VkSurfaceKHR surface | ||||
| ) { | ||||
| 	VkResult vulkanResult; | ||||
| 	VkPhysicalDevice *physicalDevices; | ||||
|  | @ -10513,9 +10511,8 @@ static uint8_t VULKAN_INTERNAL_CreateLogicalDevice( | |||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| static void VULKAN_INTERNAL_LoadEntryPoints( | ||||
| 	VulkanRenderer *renderer | ||||
| ) { | ||||
| static void VULKAN_INTERNAL_LoadEntryPoints() | ||||
| { | ||||
| 	/* Load Vulkan entry points */ | ||||
| 	if (SDL_Vulkan_LoadLibrary(NULL) < 0) | ||||
| 	{ | ||||
|  | @ -10546,6 +10543,83 @@ static void VULKAN_INTERNAL_LoadEntryPoints( | |||
| 	#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( | ||||
| 	Refresh_PresentationParameters *presentationParameters, | ||||
| 	uint8_t debugMode | ||||
|  | @ -10609,7 +10683,7 @@ static Refresh_Device* VULKAN_CreateDevice( | |||
| 	 */ | ||||
| 
 | ||||
| 	#define VULKAN_INSTANCE_FUNCTION(ext, ret, func, params) \ | ||||
| 			renderer->func = (vkfntype_##func) vkGetInstanceProcAddr(renderer->instance, #func); | ||||
| 		renderer->func = (vkfntype_##func) vkGetInstanceProcAddr(renderer->instance, #func); | ||||
| 	#include "Refresh_Driver_Vulkan_vkfuncs.h" | ||||
| 
 | ||||
| 	/*
 | ||||
|  | @ -10622,9 +10696,7 @@ static Refresh_Device* VULKAN_CreateDevice( | |||
| 	} | ||||
| 	if (!VULKAN_INTERNAL_DeterminePhysicalDevice( | ||||
| 		renderer, | ||||
| 		surface, | ||||
| 		deviceExtensionNames, | ||||
| 		deviceExtensionCount | ||||
| 		surface | ||||
| 	)) { | ||||
| 		Refresh_LogError("Failed to determine a suitable physical device"); | ||||
| 		return NULL; | ||||
|  | @ -11124,6 +11196,7 @@ static Refresh_Device* VULKAN_CreateDevice( | |||
| 
 | ||||
| Refresh_Driver VulkanDriver = { | ||||
| 	"Vulkan", | ||||
| 	VULKAN_PrepareDriver, | ||||
| 	VULKAN_CreateDevice | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue