Backend selection + swapchain API revision #23
			
				
			
		
		
		
	|  | @ -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, | ||||||
|  |  | ||||||
|  | @ -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, | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue