Fence API #45
			
				
			
		
		
		
	|  | @ -76,6 +76,7 @@ typedef struct Refresh_ShaderModule Refresh_ShaderModule; | ||||||
| typedef struct Refresh_ComputePipeline Refresh_ComputePipeline; | typedef struct Refresh_ComputePipeline Refresh_ComputePipeline; | ||||||
| typedef struct Refresh_GraphicsPipeline Refresh_GraphicsPipeline; | typedef struct Refresh_GraphicsPipeline Refresh_GraphicsPipeline; | ||||||
| typedef struct Refresh_CommandBuffer Refresh_CommandBuffer; | typedef struct Refresh_CommandBuffer Refresh_CommandBuffer; | ||||||
|  | typedef struct Refresh_Fence Refresh_Fence; | ||||||
| 
 | 
 | ||||||
| typedef enum Refresh_PresentMode | typedef enum Refresh_PresentMode | ||||||
| { | { | ||||||
|  | @ -1206,15 +1207,50 @@ REFRESHAPI Refresh_Texture* Refresh_AcquireSwapchainTexture( | ||||||
| /* 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, | ||||||
| 	uint32_t commandBufferCount, | 	Refresh_CommandBuffer *commandBuffer | ||||||
| 	Refresh_CommandBuffer **pCommandBuffers |  | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| /* Waits for all submissions to complete. */ | /* Submits a command buffer and acquires a fence.
 | ||||||
|  |  * You can use the fence to check if or wait until the command buffer has finished processing. | ||||||
|  |  * You are responsible for releasing this fence when you are done using it. | ||||||
|  |  */ | ||||||
|  | REFRESHAPI Refresh_Fence* Refresh_SubmitAndAcquireFence( | ||||||
|  | 	Refresh_Device* device, | ||||||
|  | 	Refresh_CommandBuffer *commandBuffer | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | /* Waits for the device to become idle. */ | ||||||
| REFRESHAPI void Refresh_Wait( | REFRESHAPI void Refresh_Wait( | ||||||
| 	Refresh_Device *device | 	Refresh_Device *device | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
|  | /* Waits for given fences to be signaled.
 | ||||||
|  |  * | ||||||
|  |  * waitAll: If 0, waits for any fence to be signaled. If 1, waits for all fences to be signaled. | ||||||
|  |  * fenceCount: The number of fences being submitted. | ||||||
|  |  * pFences: An array of fences to be waited on. | ||||||
|  |  */ | ||||||
|  | REFRESHAPI void Refresh_WaitForFences( | ||||||
|  | 	Refresh_Device *device, | ||||||
|  | 	uint8_t waitAll, | ||||||
|  | 	uint32_t fenceCount, | ||||||
|  | 	Refresh_Fence **pFences | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | /* Check the status of a fence. 1 means the fence is signaled. */ | ||||||
|  | REFRESHAPI int Refresh_QueryFence( | ||||||
|  | 	Refresh_Device *device, | ||||||
|  | 	Refresh_Fence *fence | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | /* Allows the fence to be reused by future command buffer submissions.
 | ||||||
|  |  * If you do not release fences after acquiring them, you will cause unbounded resource growth. | ||||||
|  |  */ | ||||||
|  | REFRESHAPI void Refresh_ReleaseFence( | ||||||
|  | 	Refresh_Device *device, | ||||||
|  | 	Refresh_Fence *fence | ||||||
|  | ); | ||||||
|  | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
| #endif /* __cplusplus */ | #endif /* __cplusplus */ | ||||||
|  |  | ||||||
|  | @ -892,14 +892,23 @@ void Refresh_SetSwapchainPresentMode( | ||||||
| 
 | 
 | ||||||
| void Refresh_Submit( | void Refresh_Submit( | ||||||
| 	Refresh_Device *device, | 	Refresh_Device *device, | ||||||
| 	uint32_t commandBufferCount, | 	Refresh_CommandBuffer *commandBuffer | ||||||
| 	Refresh_CommandBuffer **pCommandBuffers |  | ||||||
| ) { | ) { | ||||||
| 	NULL_RETURN(device); | 	NULL_RETURN(device); | ||||||
| 	device->Submit( | 	device->Submit( | ||||||
| 		device->driverData, | 		device->driverData, | ||||||
| 		commandBufferCount, | 		commandBuffer | ||||||
| 		pCommandBuffers | 	); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Refresh_Fence* Refresh_SubmitAndAcquireFence( | ||||||
|  | 	Refresh_Device *device, | ||||||
|  | 	Refresh_CommandBuffer *commandBuffer | ||||||
|  | ) { | ||||||
|  | 	NULL_RETURN_NULL(device); | ||||||
|  | 	return device->SubmitAndAcquireFence( | ||||||
|  | 		device->driverData, | ||||||
|  | 		commandBuffer | ||||||
| 	); | 	); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -912,4 +921,44 @@ void Refresh_Wait( | ||||||
| 	); | 	); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void Refresh_WaitForFences( | ||||||
|  | 	Refresh_Device *device, | ||||||
|  | 	uint8_t waitAll, | ||||||
|  | 	uint32_t fenceCount, | ||||||
|  | 	Refresh_Fence **pFences | ||||||
|  | ) { | ||||||
|  | 	NULL_RETURN(device); | ||||||
|  | 	device->WaitForFences( | ||||||
|  | 		device->driverData, | ||||||
|  | 		waitAll, | ||||||
|  | 		fenceCount, | ||||||
|  | 		pFences | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int Refresh_QueryFence( | ||||||
|  | 	Refresh_Device *device, | ||||||
|  | 	Refresh_Fence *fence | ||||||
|  | ) { | ||||||
|  | 	if (device == NULL) { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return device->QueryFence( | ||||||
|  | 		device->driverData, | ||||||
|  | 		fence | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Refresh_ReleaseFence( | ||||||
|  | 	Refresh_Device *device, | ||||||
|  | 	Refresh_Fence *fence | ||||||
|  | ) { | ||||||
|  | 	NULL_RETURN(device); | ||||||
|  | 	device->ReleaseFence( | ||||||
|  | 		device->driverData, | ||||||
|  | 		fence | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* vim: set noexpandtab shiftwidth=8 tabstop=8: */ | /* vim: set noexpandtab shiftwidth=8 tabstop=8: */ | ||||||
|  |  | ||||||
|  | @ -499,14 +499,35 @@ struct Refresh_Device | ||||||
| 
 | 
 | ||||||
| 	void (*Submit)( | 	void (*Submit)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		uint32_t commandBufferCount, | 		Refresh_CommandBuffer *commandBuffer | ||||||
| 		Refresh_CommandBuffer **pCommandBuffers | 	); | ||||||
|  | 
 | ||||||
|  | 	Refresh_Fence* (*SubmitAndAcquireFence)( | ||||||
|  | 		Refresh_Renderer *driverData, | ||||||
|  | 		Refresh_CommandBuffer *commandBuffer | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void (*Wait)( | 	void (*Wait)( | ||||||
| 		Refresh_Renderer *driverData | 		Refresh_Renderer *driverData | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
|  | 	void (*WaitForFences)( | ||||||
|  | 		Refresh_Renderer *driverData, | ||||||
|  | 		uint8_t waitAll, | ||||||
|  | 		uint32_t fenceCount, | ||||||
|  | 		Refresh_Fence **pFences | ||||||
|  | 	); | ||||||
|  | 
 | ||||||
|  | 	int (*QueryFence)( | ||||||
|  | 		Refresh_Renderer *driverData, | ||||||
|  | 		Refresh_Fence *fence | ||||||
|  | 	); | ||||||
|  | 
 | ||||||
|  | 	void (*ReleaseFence)( | ||||||
|  | 		Refresh_Renderer *driverData, | ||||||
|  | 		Refresh_Fence *fence | ||||||
|  | 	); | ||||||
|  | 
 | ||||||
| 	/* Opaque pointer for the Driver */ | 	/* Opaque pointer for the Driver */ | ||||||
| 	Refresh_Renderer *driverData; | 	Refresh_Renderer *driverData; | ||||||
| }; | }; | ||||||
|  | @ -560,7 +581,11 @@ struct Refresh_Device | ||||||
| 	ASSIGN_DRIVER_FUNC(GetSwapchainFormat, name) \ | 	ASSIGN_DRIVER_FUNC(GetSwapchainFormat, name) \ | ||||||
| 	ASSIGN_DRIVER_FUNC(SetSwapchainPresentMode, name) \ | 	ASSIGN_DRIVER_FUNC(SetSwapchainPresentMode, name) \ | ||||||
| 	ASSIGN_DRIVER_FUNC(Submit, name) \ | 	ASSIGN_DRIVER_FUNC(Submit, name) \ | ||||||
| 	ASSIGN_DRIVER_FUNC(Wait, name) | 	ASSIGN_DRIVER_FUNC(SubmitAndAcquireFence, name) \ | ||||||
|  | 	ASSIGN_DRIVER_FUNC(Wait, name) \ | ||||||
|  | 	ASSIGN_DRIVER_FUNC(WaitForFences, name) \ | ||||||
|  | 	ASSIGN_DRIVER_FUNC(QueryFence, name) \ | ||||||
|  | 	ASSIGN_DRIVER_FUNC(ReleaseFence, name) | ||||||
| 
 | 
 | ||||||
| typedef struct Refresh_Driver | typedef struct Refresh_Driver | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -1533,6 +1533,15 @@ typedef struct VulkanTransferBufferPool | ||||||
| 	uint32_t availableBufferCapacity; | 	uint32_t availableBufferCapacity; | ||||||
| } VulkanTransferBufferPool; | } VulkanTransferBufferPool; | ||||||
| 
 | 
 | ||||||
|  | typedef struct VulkanFencePool | ||||||
|  | { | ||||||
|  | 	SDL_mutex *lock; | ||||||
|  | 
 | ||||||
|  | 	VkFence *availableFences; | ||||||
|  | 	uint32_t availableFenceCount; | ||||||
|  | 	uint32_t availableFenceCapacity; | ||||||
|  | } VulkanFencePool; | ||||||
|  | 
 | ||||||
| typedef struct VulkanCommandPool VulkanCommandPool; | typedef struct VulkanCommandPool VulkanCommandPool; | ||||||
| 
 | 
 | ||||||
| typedef struct VulkanCommandBuffer | typedef struct VulkanCommandBuffer | ||||||
|  | @ -1624,6 +1633,7 @@ typedef struct VulkanCommandBuffer | ||||||
| 	/* Shader modules have references tracked by pipelines */ | 	/* Shader modules have references tracked by pipelines */ | ||||||
| 
 | 
 | ||||||
| 	VkFence inFlightFence; | 	VkFence inFlightFence; | ||||||
|  | 	uint8_t autoReleaseFence; | ||||||
| } VulkanCommandBuffer; | } VulkanCommandBuffer; | ||||||
| 
 | 
 | ||||||
| struct VulkanCommandPool | struct VulkanCommandPool | ||||||
|  | @ -1737,6 +1747,7 @@ typedef struct VulkanRenderer | ||||||
| 	uint32_t submittedCommandBufferCapacity; | 	uint32_t submittedCommandBufferCapacity; | ||||||
| 
 | 
 | ||||||
| 	VulkanTransferBufferPool transferBufferPool; | 	VulkanTransferBufferPool transferBufferPool; | ||||||
|  | 	VulkanFencePool fencePool; | ||||||
| 
 | 
 | ||||||
| 	CommandPoolHashTable commandPoolHashTable; | 	CommandPoolHashTable commandPoolHashTable; | ||||||
| 	DescriptorSetLayoutHashTable descriptorSetLayoutHashTable; | 	DescriptorSetLayoutHashTable descriptorSetLayoutHashTable; | ||||||
|  | @ -1828,7 +1839,7 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(VulkanRenderer *renderer); | ||||||
| static void VULKAN_INTERNAL_BeginCommandBuffer(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer); | static void VULKAN_INTERNAL_BeginCommandBuffer(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer); | ||||||
| static void VULKAN_UnclaimWindow(Refresh_Renderer *driverData, void *windowHandle); | static void VULKAN_UnclaimWindow(Refresh_Renderer *driverData, void *windowHandle); | ||||||
| static void VULKAN_Wait(Refresh_Renderer *driverData); | static void VULKAN_Wait(Refresh_Renderer *driverData); | ||||||
| static void VULKAN_Submit(Refresh_Renderer *driverData, uint32_t commandBufferCount, Refresh_CommandBuffer **pCommandBuffers); | static void VULKAN_Submit(Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer); | ||||||
| static void VULKAN_INTERNAL_DestroyRenderTarget(VulkanRenderer *renderer, VulkanRenderTarget *renderTarget); | static void VULKAN_INTERNAL_DestroyRenderTarget(VulkanRenderer *renderer, VulkanRenderTarget *renderTarget); | ||||||
| 
 | 
 | ||||||
| /* Error Handling */ | /* Error Handling */ | ||||||
|  | @ -3589,12 +3600,6 @@ static void VULKAN_INTERNAL_DestroyCommandPool( | ||||||
| 	{ | 	{ | ||||||
| 		commandBuffer = commandPool->inactiveCommandBuffers[i]; | 		commandBuffer = commandPool->inactiveCommandBuffers[i]; | ||||||
| 
 | 
 | ||||||
| 		renderer->vkDestroyFence( |  | ||||||
| 			renderer->logicalDevice, |  | ||||||
| 			commandBuffer->inFlightFence, |  | ||||||
| 			NULL |  | ||||||
| 		); |  | ||||||
| 
 |  | ||||||
| 		SDL_free(commandBuffer->presentDatas); | 		SDL_free(commandBuffer->presentDatas); | ||||||
| 		SDL_free(commandBuffer->waitSemaphores); | 		SDL_free(commandBuffer->waitSemaphores); | ||||||
| 		SDL_free(commandBuffer->signalSemaphores); | 		SDL_free(commandBuffer->signalSemaphores); | ||||||
|  | @ -5158,6 +5163,14 @@ static void VULKAN_DestroyDevice( | ||||||
| 	SDL_free(renderer->transferBufferPool.availableBuffers); | 	SDL_free(renderer->transferBufferPool.availableBuffers); | ||||||
| 	SDL_DestroyMutex(renderer->transferBufferPool.lock); | 	SDL_DestroyMutex(renderer->transferBufferPool.lock); | ||||||
| 
 | 
 | ||||||
|  | 	for (i = 0; i < renderer->fencePool.availableFenceCount; i += 1) | ||||||
|  | 	{ | ||||||
|  | 		renderer->vkDestroyFence(renderer->logicalDevice, renderer->fencePool.availableFences[i], NULL); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	SDL_free(renderer->fencePool.availableFences); | ||||||
|  | 	SDL_DestroyMutex(renderer->fencePool.lock); | ||||||
|  | 
 | ||||||
| 	for (i = 0; i < NUM_COMMAND_POOL_BUCKETS; i += 1) | 	for (i = 0; i < NUM_COMMAND_POOL_BUCKETS; i += 1) | ||||||
| 	{ | 	{ | ||||||
| 		commandPoolHashArray = renderer->commandPoolHashTable.buckets[i]; | 		commandPoolHashArray = renderer->commandPoolHashTable.buckets[i]; | ||||||
|  | @ -9362,7 +9375,6 @@ static void VULKAN_INTERNAL_AllocateCommandBuffers( | ||||||
| 	uint32_t allocateCount | 	uint32_t allocateCount | ||||||
| ) { | ) { | ||||||
| 	VkCommandBufferAllocateInfo allocateInfo; | 	VkCommandBufferAllocateInfo allocateInfo; | ||||||
| 	VkFenceCreateInfo fenceCreateInfo; |  | ||||||
| 	VkResult vulkanResult; | 	VkResult vulkanResult; | ||||||
| 	uint32_t i; | 	uint32_t i; | ||||||
| 	VkCommandBuffer *commandBuffers = SDL_stack_alloc(VkCommandBuffer, allocateCount); | 	VkCommandBuffer *commandBuffers = SDL_stack_alloc(VkCommandBuffer, allocateCount); | ||||||
|  | @ -9401,23 +9413,7 @@ static void VULKAN_INTERNAL_AllocateCommandBuffers( | ||||||
| 		commandBuffer->commandPool = vulkanCommandPool; | 		commandBuffer->commandPool = vulkanCommandPool; | ||||||
| 		commandBuffer->commandBuffer = commandBuffers[i]; | 		commandBuffer->commandBuffer = commandBuffers[i]; | ||||||
| 
 | 
 | ||||||
| 		/* Create fence */ | 		commandBuffer->inFlightFence = VK_NULL_HANDLE; | ||||||
| 		fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; |  | ||||||
| 		fenceCreateInfo.pNext = NULL; |  | ||||||
| 		fenceCreateInfo.flags = 0; |  | ||||||
| 
 |  | ||||||
| 		vulkanResult = renderer->vkCreateFence( |  | ||||||
| 			renderer->logicalDevice, |  | ||||||
| 			&fenceCreateInfo, |  | ||||||
| 			NULL, |  | ||||||
| 			&commandBuffer->inFlightFence |  | ||||||
| 		); |  | ||||||
| 
 |  | ||||||
| 		if (vulkanResult != VK_SUCCESS) |  | ||||||
| 		{ |  | ||||||
| 			LogVulkanResultAsError("vkCreateFence", vulkanResult); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		commandBuffer->renderPassDepthTexture = NULL; | 		commandBuffer->renderPassDepthTexture = NULL; | ||||||
| 
 | 
 | ||||||
| 		/* Presentation tracking */ | 		/* Presentation tracking */ | ||||||
|  | @ -9650,17 +9646,6 @@ static Refresh_CommandBuffer* VULKAN_AcquireCommandBuffer( | ||||||
| 		LogVulkanResultAsError("vkResetCommandBuffer", result); | 		LogVulkanResultAsError("vkResetCommandBuffer", result); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	result = renderer->vkResetFences( |  | ||||||
| 		renderer->logicalDevice, |  | ||||||
| 		1, |  | ||||||
| 		&commandBuffer->inFlightFence |  | ||||||
| 	); |  | ||||||
| 
 |  | ||||||
| 	if (result != VK_SUCCESS) |  | ||||||
| 	{ |  | ||||||
| 		LogVulkanResultAsError("vkResetFences", result); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	VULKAN_INTERNAL_BeginCommandBuffer(renderer, commandBuffer); | 	VULKAN_INTERNAL_BeginCommandBuffer(renderer, commandBuffer); | ||||||
| 
 | 
 | ||||||
| 	return (Refresh_CommandBuffer*) commandBuffer; | 	return (Refresh_CommandBuffer*) commandBuffer; | ||||||
|  | @ -9949,6 +9934,77 @@ static void VULKAN_SetSwapchainPresentMode( | ||||||
| 
 | 
 | ||||||
| /* Submission structure */ | /* Submission structure */ | ||||||
| 
 | 
 | ||||||
|  | static VkFence VULKAN_INTERNAL_AcquireFenceFromPool( | ||||||
|  | 	VulkanRenderer *renderer | ||||||
|  | ) { | ||||||
|  | 	VkFenceCreateInfo fenceCreateInfo; | ||||||
|  | 	VkFence fence; | ||||||
|  | 	VkResult vulkanResult; | ||||||
|  | 
 | ||||||
|  | 	if (renderer->fencePool.availableFenceCount == 0) | ||||||
|  | 	{ | ||||||
|  | 		/* Create fence */ | ||||||
|  | 		fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; | ||||||
|  | 		fenceCreateInfo.pNext = NULL; | ||||||
|  | 		fenceCreateInfo.flags = 0; | ||||||
|  | 
 | ||||||
|  | 		vulkanResult = renderer->vkCreateFence( | ||||||
|  | 			renderer->logicalDevice, | ||||||
|  | 			&fenceCreateInfo, | ||||||
|  | 			NULL, | ||||||
|  | 			&fence | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		if (vulkanResult != VK_SUCCESS) | ||||||
|  | 		{ | ||||||
|  | 			LogVulkanResultAsError("vkCreateFence", vulkanResult); | ||||||
|  | 			return NULL; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return fence; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	SDL_LockMutex(renderer->fencePool.lock); | ||||||
|  | 
 | ||||||
|  | 	fence = renderer->fencePool.availableFences[renderer->fencePool.availableFenceCount - 1]; | ||||||
|  | 	renderer->fencePool.availableFenceCount -= 1; | ||||||
|  | 
 | ||||||
|  | 	vulkanResult = renderer->vkResetFences( | ||||||
|  | 		renderer->logicalDevice, | ||||||
|  | 		1, | ||||||
|  | 		&fence | ||||||
|  | 	); | ||||||
|  | 
 | ||||||
|  | 	if (vulkanResult != VK_SUCCESS) | ||||||
|  | 	{ | ||||||
|  | 		LogVulkanResultAsError("vkResetFences", vulkanResult); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	SDL_UnlockMutex(renderer->fencePool.lock); | ||||||
|  | 
 | ||||||
|  | 	return fence; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void VULKAN_INTERNAL_ReturnFenceToPool( | ||||||
|  | 	VulkanRenderer *renderer, | ||||||
|  | 	VkFence fence | ||||||
|  | ) { | ||||||
|  | 	SDL_LockMutex(renderer->fencePool.lock); | ||||||
|  | 
 | ||||||
|  | 	EXPAND_ARRAY_IF_NEEDED( | ||||||
|  | 		renderer->fencePool.availableFences, | ||||||
|  | 		VkFence, | ||||||
|  | 		renderer->fencePool.availableFenceCount + 1, | ||||||
|  | 		renderer->fencePool.availableFenceCapacity, | ||||||
|  | 		renderer->fencePool.availableFenceCapacity * 2 | ||||||
|  | 	); | ||||||
|  | 
 | ||||||
|  | 	renderer->fencePool.availableFences[renderer->fencePool.availableFenceCount] = fence; | ||||||
|  | 	renderer->fencePool.availableFenceCount += 1; | ||||||
|  | 
 | ||||||
|  | 	SDL_UnlockMutex(renderer->fencePool.lock); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void VULKAN_INTERNAL_PerformPendingDestroys( | static void VULKAN_INTERNAL_PerformPendingDestroys( | ||||||
| 	VulkanRenderer *renderer | 	VulkanRenderer *renderer | ||||||
| ) { | ) { | ||||||
|  | @ -10064,6 +10120,16 @@ static void VULKAN_INTERNAL_CleanCommandBuffer( | ||||||
| 	VulkanUniformBuffer *uniformBuffer; | 	VulkanUniformBuffer *uniformBuffer; | ||||||
| 	DescriptorSetData *descriptorSetData; | 	DescriptorSetData *descriptorSetData; | ||||||
| 
 | 
 | ||||||
|  | 	if (commandBuffer->autoReleaseFence) | ||||||
|  | 	{ | ||||||
|  | 		VULKAN_INTERNAL_ReturnFenceToPool( | ||||||
|  | 			renderer, | ||||||
|  | 			commandBuffer->inFlightFence | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		commandBuffer->inFlightFence = VK_NULL_HANDLE; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/* Bound uniform buffers are now available */ | 	/* Bound uniform buffers are now available */ | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < commandBuffer->boundUniformBufferCount; i += 1) | 	for (i = 0; i < commandBuffer->boundUniformBufferCount; i += 1) | ||||||
|  | @ -10219,26 +10285,16 @@ static void VULKAN_Wait( | ||||||
| 	VkResult result; | 	VkResult result; | ||||||
| 	int32_t i; | 	int32_t i; | ||||||
| 
 | 
 | ||||||
| 	SDL_LockMutex(renderer->submitLock); | 	result = renderer->vkDeviceWaitIdle(renderer->logicalDevice); | ||||||
| 
 |  | ||||||
| 	for (i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) |  | ||||||
| 	{ |  | ||||||
| 		commandBuffer = renderer->submittedCommandBuffers[i]; |  | ||||||
| 
 |  | ||||||
| 		result = renderer->vkWaitForFences( |  | ||||||
| 			renderer->logicalDevice, |  | ||||||
| 			1, |  | ||||||
| 			&commandBuffer->inFlightFence, |  | ||||||
| 			VK_TRUE, |  | ||||||
| 			UINT64_MAX |  | ||||||
| 		); |  | ||||||
| 
 | 
 | ||||||
| 	if (result != VK_SUCCESS) | 	if (result != VK_SUCCESS) | ||||||
| 	{ | 	{ | ||||||
| 			LogVulkanResultAsError("vkWaitForFences", result); | 		LogVulkanResultAsError("vkDeviceWaitIdle", result); | ||||||
| 		} | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	SDL_LockMutex(renderer->submitLock); | ||||||
|  | 
 | ||||||
| 	for (i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) | 	for (i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) | ||||||
| 	{ | 	{ | ||||||
| 		commandBuffer = renderer->submittedCommandBuffers[i]; | 		commandBuffer = renderer->submittedCommandBuffers[i]; | ||||||
|  | @ -10250,17 +10306,30 @@ static void VULKAN_Wait( | ||||||
| 	SDL_UnlockMutex(renderer->submitLock); | 	SDL_UnlockMutex(renderer->submitLock); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static Refresh_Fence* VULKAN_SubmitAndAcquireFence( | ||||||
|  | 	Refresh_Renderer *driverData, | ||||||
|  | 	Refresh_CommandBuffer *commandBuffer | ||||||
|  | ) { | ||||||
|  | 	VulkanCommandBuffer *vulkanCommandBuffer; | ||||||
|  | 
 | ||||||
|  | 	VULKAN_Submit(driverData, commandBuffer); | ||||||
|  | 
 | ||||||
|  | 	vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; | ||||||
|  | 	vulkanCommandBuffer->autoReleaseFence = 0; | ||||||
|  | 
 | ||||||
|  | 	return (Refresh_Fence*) vulkanCommandBuffer->inFlightFence; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void VULKAN_Submit( | static void VULKAN_Submit( | ||||||
| 	Refresh_Renderer *driverData, | 	Refresh_Renderer *driverData, | ||||||
| 	uint32_t commandBufferCount, | 	Refresh_CommandBuffer *commandBuffer | ||||||
| 	Refresh_CommandBuffer **pCommandBuffers |  | ||||||
| ) { | ) { | ||||||
| 	VulkanRenderer* renderer = (VulkanRenderer*)driverData; | 	VulkanRenderer* renderer = (VulkanRenderer*)driverData; | ||||||
| 	VkSubmitInfo submitInfo; | 	VkSubmitInfo submitInfo; | ||||||
| 	VkPresentInfoKHR presentInfo; | 	VkPresentInfoKHR presentInfo; | ||||||
| 	VulkanPresentData *presentData; | 	VulkanPresentData *presentData; | ||||||
| 	VkResult vulkanResult, presentResult = VK_SUCCESS; | 	VkResult vulkanResult, presentResult = VK_SUCCESS; | ||||||
| 	VulkanCommandBuffer *currentCommandBuffer; | 	VulkanCommandBuffer *vulkanCommandBuffer; | ||||||
| 	VkPipelineStageFlags waitStages[MAX_PRESENT_COUNT]; | 	VkPipelineStageFlags waitStages[MAX_PRESENT_COUNT]; | ||||||
| 	uint32_t swapchainImageIndex; | 	uint32_t swapchainImageIndex; | ||||||
| 	uint8_t commandBufferCleaned = 0; | 	uint8_t commandBufferCleaned = 0; | ||||||
|  | @ -10275,19 +10344,15 @@ static void VULKAN_Submit( | ||||||
| 		waitStages[i] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; | 		waitStages[i] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Submit the commands finally */ | 	vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < commandBufferCount; i += 1) | 	for (j = 0; j < vulkanCommandBuffer->presentDataCount; j += 1) | ||||||
| 	{ | 	{ | ||||||
| 		currentCommandBuffer = (VulkanCommandBuffer*)pCommandBuffers[i]; | 		swapchainImageIndex = vulkanCommandBuffer->presentDatas[j].swapchainImageIndex; | ||||||
| 
 |  | ||||||
| 		for (j = 0; j < currentCommandBuffer->presentDataCount; j += 1) |  | ||||||
| 		{ |  | ||||||
| 			swapchainImageIndex = currentCommandBuffer->presentDatas[j].swapchainImageIndex; |  | ||||||
| 
 | 
 | ||||||
| 		VULKAN_INTERNAL_ImageMemoryBarrier( | 		VULKAN_INTERNAL_ImageMemoryBarrier( | ||||||
| 			renderer, | 			renderer, | ||||||
| 				currentCommandBuffer->commandBuffer, | 			vulkanCommandBuffer->commandBuffer, | ||||||
| 			RESOURCE_ACCESS_PRESENT, | 			RESOURCE_ACCESS_PRESENT, | ||||||
| 			VK_IMAGE_ASPECT_COLOR_BIT, | 			VK_IMAGE_ASPECT_COLOR_BIT, | ||||||
| 			0, | 			0, | ||||||
|  | @ -10295,29 +10360,32 @@ static void VULKAN_Submit( | ||||||
| 			0, | 			0, | ||||||
| 			1, | 			1, | ||||||
| 			0, | 			0, | ||||||
| 				currentCommandBuffer->presentDatas[j].windowData->swapchainData->textureContainers[swapchainImageIndex].vulkanTexture->image, | 			vulkanCommandBuffer->presentDatas[j].windowData->swapchainData->textureContainers[swapchainImageIndex].vulkanTexture->image, | ||||||
| 				¤tCommandBuffer->presentDatas[j].windowData->swapchainData->textureContainers[swapchainImageIndex].vulkanTexture->resourceAccessType | 			&vulkanCommandBuffer->presentDatas[j].windowData->swapchainData->textureContainers[swapchainImageIndex].vulkanTexture->resourceAccessType | ||||||
| 		); | 		); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 		VULKAN_INTERNAL_EndCommandBuffer(renderer, currentCommandBuffer); | 	VULKAN_INTERNAL_EndCommandBuffer(renderer, vulkanCommandBuffer); | ||||||
|  | 
 | ||||||
|  | 	vulkanCommandBuffer->autoReleaseFence = 1; | ||||||
|  | 	vulkanCommandBuffer->inFlightFence = VULKAN_INTERNAL_AcquireFenceFromPool(renderer); | ||||||
| 
 | 
 | ||||||
| 	submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; | 	submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; | ||||||
| 	submitInfo.pNext = NULL; | 	submitInfo.pNext = NULL; | ||||||
| 	submitInfo.commandBufferCount = 1; | 	submitInfo.commandBufferCount = 1; | ||||||
| 		submitInfo.pCommandBuffers = ¤tCommandBuffer->commandBuffer; | 	submitInfo.pCommandBuffers = &vulkanCommandBuffer->commandBuffer; | ||||||
| 
 | 
 | ||||||
| 	submitInfo.pWaitDstStageMask = waitStages; | 	submitInfo.pWaitDstStageMask = waitStages; | ||||||
| 		submitInfo.pWaitSemaphores = currentCommandBuffer->waitSemaphores; | 	submitInfo.pWaitSemaphores = vulkanCommandBuffer->waitSemaphores; | ||||||
| 		submitInfo.waitSemaphoreCount = currentCommandBuffer->waitSemaphoreCount; | 	submitInfo.waitSemaphoreCount = vulkanCommandBuffer->waitSemaphoreCount; | ||||||
| 		submitInfo.pSignalSemaphores = currentCommandBuffer->signalSemaphores; | 	submitInfo.pSignalSemaphores = vulkanCommandBuffer->signalSemaphores; | ||||||
| 		submitInfo.signalSemaphoreCount = currentCommandBuffer->signalSemaphoreCount; | 	submitInfo.signalSemaphoreCount = vulkanCommandBuffer->signalSemaphoreCount; | ||||||
| 
 | 
 | ||||||
| 	vulkanResult = renderer->vkQueueSubmit( | 	vulkanResult = renderer->vkQueueSubmit( | ||||||
| 		renderer->unifiedQueue, | 		renderer->unifiedQueue, | ||||||
| 		1, | 		1, | ||||||
| 		&submitInfo, | 		&submitInfo, | ||||||
| 			currentCommandBuffer->inFlightFence | 		vulkanCommandBuffer->inFlightFence | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	if (vulkanResult != VK_SUCCESS) | 	if (vulkanResult != VK_SUCCESS) | ||||||
|  | @ -10337,14 +10405,14 @@ static void VULKAN_Submit( | ||||||
| 		); | 		); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 		renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = (VulkanCommandBuffer*) pCommandBuffers[i]; | 	renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = vulkanCommandBuffer; | ||||||
| 	renderer->submittedCommandBufferCount += 1; | 	renderer->submittedCommandBufferCount += 1; | ||||||
| 
 | 
 | ||||||
| 	/* Present, if applicable */ | 	/* Present, if applicable */ | ||||||
| 
 | 
 | ||||||
| 		for (j = 0; j < currentCommandBuffer->presentDataCount; j += 1) | 	for (j = 0; j < vulkanCommandBuffer->presentDataCount; j += 1) | ||||||
| 	{ | 	{ | ||||||
| 			presentData = ¤tCommandBuffer->presentDatas[j]; | 		presentData = &vulkanCommandBuffer->presentDatas[j]; | ||||||
| 
 | 
 | ||||||
| 		presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; | 		presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; | ||||||
| 		presentInfo.pNext = NULL; | 		presentInfo.pNext = NULL; | ||||||
|  | @ -10368,7 +10436,6 @@ static void VULKAN_Submit( | ||||||
| 			); | 			); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	/* Check if we can perform any cleanups */ | 	/* Check if we can perform any cleanups */ | ||||||
| 
 | 
 | ||||||
|  | @ -10670,8 +10737,7 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory( | ||||||
| 
 | 
 | ||||||
| 	VULKAN_Submit( | 	VULKAN_Submit( | ||||||
| 		(Refresh_Renderer*) renderer, | 		(Refresh_Renderer*) renderer, | ||||||
| 		1, | 		(Refresh_CommandBuffer*) commandBuffer | ||||||
| 		(Refresh_CommandBuffer**) &commandBuffer |  | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	renderer->defragInProgress = 0; | 	renderer->defragInProgress = 0; | ||||||
|  | @ -10679,6 +10745,63 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory( | ||||||
| 	return 1; | 	return 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void VULKAN_WaitForFences( | ||||||
|  | 	Refresh_Renderer *driverData, | ||||||
|  | 	uint8_t waitAll, | ||||||
|  | 	uint32_t fenceCount, | ||||||
|  | 	Refresh_Fence **pFences | ||||||
|  | ) { | ||||||
|  | 	VulkanRenderer* renderer = (VulkanRenderer*) driverData; | ||||||
|  | 	VkResult result; | ||||||
|  | 
 | ||||||
|  | 	result = renderer->vkWaitForFences( | ||||||
|  | 		renderer->logicalDevice, | ||||||
|  | 		fenceCount, | ||||||
|  | 		(VkFence*) pFences, | ||||||
|  | 		waitAll, | ||||||
|  | 		UINT64_MAX | ||||||
|  | 	); | ||||||
|  | 
 | ||||||
|  | 	if (result != VK_SUCCESS) | ||||||
|  | 	{ | ||||||
|  | 		LogVulkanResultAsError("vkWaitForFences", result); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int VULKAN_QueryFence( | ||||||
|  | 	Refresh_Renderer *driverData, | ||||||
|  | 	Refresh_Fence *fence | ||||||
|  | ) { | ||||||
|  | 	VulkanRenderer* renderer = (VulkanRenderer*) driverData; | ||||||
|  | 	VkResult result; | ||||||
|  | 
 | ||||||
|  | 	result = renderer->vkGetFenceStatus( | ||||||
|  | 		renderer->logicalDevice, | ||||||
|  | 		(VkFence) fence | ||||||
|  | 	); | ||||||
|  | 
 | ||||||
|  | 	if (result == VK_SUCCESS) | ||||||
|  | 	{ | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  | 	else if (result == VK_NOT_READY) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		LogVulkanResultAsError("vkGetFenceStatus", result); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void VULKAN_ReleaseFence( | ||||||
|  | 	Refresh_Renderer *driverData, | ||||||
|  | 	Refresh_Fence *fence | ||||||
|  | ) { | ||||||
|  | 	VULKAN_INTERNAL_ReturnFenceToPool((VulkanRenderer*) driverData, (VkFence) fence); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* Device instantiation */ | /* Device instantiation */ | ||||||
| 
 | 
 | ||||||
| static inline uint8_t CheckDeviceExtensions( | static inline uint8_t CheckDeviceExtensions( | ||||||
|  | @ -11966,6 +12089,16 @@ static Refresh_Device* VULKAN_CreateDevice( | ||||||
| 		renderer->transferBufferPool.availableBufferCount += 1; | 		renderer->transferBufferPool.availableBufferCount += 1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/* Initialize fence pool */ | ||||||
|  | 
 | ||||||
|  | 	renderer->fencePool.lock = SDL_CreateMutex(); | ||||||
|  | 
 | ||||||
|  | 	renderer->fencePool.availableFenceCapacity = 4; | ||||||
|  | 	renderer->fencePool.availableFenceCount = 0; | ||||||
|  | 	renderer->fencePool.availableFences = SDL_malloc( | ||||||
|  | 		renderer->fencePool.availableFenceCapacity * sizeof(VkFence) | ||||||
|  | 	); | ||||||
|  | 
 | ||||||
| 	/* Some drivers don't support D16, so we have to fall back to D32. */ | 	/* Some drivers don't support D16, so we have to fall back to D32. */ | ||||||
| 
 | 
 | ||||||
| 	vulkanResult = renderer->vkGetPhysicalDeviceImageFormatProperties( | 	vulkanResult = renderer->vkGetPhysicalDeviceImageFormatProperties( | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue