new Fence API
	
		
			
	
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is failing
				
					Details
				
			
		
	
				
					
				
			
				
	
				continuous-integration/drone/push Build is failing
				
					Details
				
			
		
	
							parent
							
								
									f55968814f
								
							
						
					
					
						commit
						6e3607999a
					
				|  | @ -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 */ | ||||||
|  |  | ||||||
|  | @ -268,7 +268,7 @@ struct Refresh_Device | ||||||
| 
 | 
 | ||||||
| 	/* Setters */ | 	/* Setters */ | ||||||
| 
 | 
 | ||||||
| 	void(*SetTextureData)( | 	void (*SetTextureData)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer *commandBuffer, | 		Refresh_CommandBuffer *commandBuffer, | ||||||
| 		Refresh_TextureSlice *textureSlice, | 		Refresh_TextureSlice *textureSlice, | ||||||
|  | @ -276,7 +276,7 @@ struct Refresh_Device | ||||||
| 		uint32_t dataLengthInBytes | 		uint32_t dataLengthInBytes | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*SetTextureDataYUV)( | 	void (*SetTextureDataYUV)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer* commandBuffer, | 		Refresh_CommandBuffer* commandBuffer, | ||||||
| 		Refresh_Texture *y, | 		Refresh_Texture *y, | ||||||
|  | @ -295,7 +295,7 @@ struct Refresh_Device | ||||||
| 		uint32_t uvStride | 		uint32_t uvStride | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*CopyTextureToTexture)( | 	void (*CopyTextureToTexture)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer *commandBuffer, | 		Refresh_CommandBuffer *commandBuffer, | ||||||
| 		Refresh_TextureSlice *sourceTextureSlice, | 		Refresh_TextureSlice *sourceTextureSlice, | ||||||
|  | @ -303,14 +303,14 @@ struct Refresh_Device | ||||||
| 		Refresh_Filter filter | 		Refresh_Filter filter | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*CopyTextureToBuffer)( | 	void (*CopyTextureToBuffer)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer *commandBuffer, | 		Refresh_CommandBuffer *commandBuffer, | ||||||
| 		Refresh_TextureSlice *textureSlice, | 		Refresh_TextureSlice *textureSlice, | ||||||
| 		Refresh_Buffer *buffer | 		Refresh_Buffer *buffer | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*SetBufferData)( | 	void (*SetBufferData)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer *commandBuffer, | 		Refresh_CommandBuffer *commandBuffer, | ||||||
| 		Refresh_Buffer *buffer, | 		Refresh_Buffer *buffer, | ||||||
|  | @ -319,14 +319,14 @@ struct Refresh_Device | ||||||
| 		uint32_t dataLength | 		uint32_t dataLength | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	uint32_t(*PushVertexShaderUniforms)( | 	uint32_t (*PushVertexShaderUniforms)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer *commandBuffer, | 		Refresh_CommandBuffer *commandBuffer, | ||||||
| 		void *data, | 		void *data, | ||||||
| 		uint32_t dataLengthInBytes | 		uint32_t dataLengthInBytes | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	uint32_t(*PushFragmentShaderUniforms)( | 	uint32_t (*PushFragmentShaderUniforms)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer *commandBuffer, | 		Refresh_CommandBuffer *commandBuffer, | ||||||
| 		void *data, | 		void *data, | ||||||
|  | @ -340,14 +340,14 @@ struct Refresh_Device | ||||||
| 		uint32_t dataLengthInBytes | 		uint32_t dataLengthInBytes | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*BindVertexSamplers)( | 	void (*BindVertexSamplers)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer *commandBuffer, | 		Refresh_CommandBuffer *commandBuffer, | ||||||
| 		Refresh_Texture **pTextures, | 		Refresh_Texture **pTextures, | ||||||
| 		Refresh_Sampler **pSamplers | 		Refresh_Sampler **pSamplers | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*BindFragmentSamplers)( | 	void (*BindFragmentSamplers)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer *commandBuffer, | 		Refresh_CommandBuffer *commandBuffer, | ||||||
| 		Refresh_Texture **pTextures, | 		Refresh_Texture **pTextures, | ||||||
|  | @ -356,7 +356,7 @@ struct Refresh_Device | ||||||
| 
 | 
 | ||||||
| 	/* Getters */ | 	/* Getters */ | ||||||
| 
 | 
 | ||||||
| 	void(*GetBufferData)( | 	void (*GetBufferData)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_Buffer *buffer, | 		Refresh_Buffer *buffer, | ||||||
| 		void *data, | 		void *data, | ||||||
|  | @ -365,39 +365,39 @@ struct Refresh_Device | ||||||
| 
 | 
 | ||||||
| 	/* Disposal */ | 	/* Disposal */ | ||||||
| 
 | 
 | ||||||
| 	void(*QueueDestroyTexture)( | 	void (*QueueDestroyTexture)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_Texture *texture | 		Refresh_Texture *texture | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*QueueDestroySampler)( | 	void (*QueueDestroySampler)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_Sampler *sampler | 		Refresh_Sampler *sampler | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*QueueDestroyBuffer)( | 	void (*QueueDestroyBuffer)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_Buffer *buffer | 		Refresh_Buffer *buffer | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*QueueDestroyShaderModule)( | 	void (*QueueDestroyShaderModule)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_ShaderModule *shaderModule | 		Refresh_ShaderModule *shaderModule | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*QueueDestroyComputePipeline)( | 	void (*QueueDestroyComputePipeline)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_ComputePipeline *computePipeline | 		Refresh_ComputePipeline *computePipeline | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*QueueDestroyGraphicsPipeline)( | 	void (*QueueDestroyGraphicsPipeline)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_GraphicsPipeline *graphicsPipeline | 		Refresh_GraphicsPipeline *graphicsPipeline | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	/* Graphics State */ | 	/* Graphics State */ | ||||||
| 
 | 
 | ||||||
| 	void(*BeginRenderPass)( | 	void (*BeginRenderPass)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer *commandBuffer, | 		Refresh_CommandBuffer *commandBuffer, | ||||||
| 		Refresh_ColorAttachmentInfo *colorAttachmentInfos, | 		Refresh_ColorAttachmentInfo *colorAttachmentInfos, | ||||||
|  | @ -405,30 +405,30 @@ struct Refresh_Device | ||||||
| 		Refresh_DepthStencilAttachmentInfo *depthStencilAttachmentInfo | 		Refresh_DepthStencilAttachmentInfo *depthStencilAttachmentInfo | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*EndRenderPass)( | 	void (*EndRenderPass)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer *commandBuffer | 		Refresh_CommandBuffer *commandBuffer | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*SetViewport)( | 	void (*SetViewport)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer *commandBuffer, | 		Refresh_CommandBuffer *commandBuffer, | ||||||
| 		Refresh_Viewport *viewport | 		Refresh_Viewport *viewport | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*SetScissor)( | 	void (*SetScissor)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer *commandBuffer, | 		Refresh_CommandBuffer *commandBuffer, | ||||||
| 		Refresh_Rect *scissor | 		Refresh_Rect *scissor | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*BindGraphicsPipeline)( | 	void (*BindGraphicsPipeline)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer *commandBuffer, | 		Refresh_CommandBuffer *commandBuffer, | ||||||
| 		Refresh_GraphicsPipeline *graphicsPipeline | 		Refresh_GraphicsPipeline *graphicsPipeline | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*BindVertexBuffers)( | 	void (*BindVertexBuffers)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer *commandBuffer, | 		Refresh_CommandBuffer *commandBuffer, | ||||||
| 		uint32_t firstBinding, | 		uint32_t firstBinding, | ||||||
|  | @ -437,7 +437,7 @@ struct Refresh_Device | ||||||
| 		uint64_t *pOffsets | 		uint64_t *pOffsets | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*BindIndexBuffer)( | 	void (*BindIndexBuffer)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer *commandBuffer, | 		Refresh_CommandBuffer *commandBuffer, | ||||||
| 		Refresh_Buffer *buffer, | 		Refresh_Buffer *buffer, | ||||||
|  | @ -445,19 +445,19 @@ struct Refresh_Device | ||||||
| 		Refresh_IndexElementSize indexElementSize | 		Refresh_IndexElementSize indexElementSize | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*BindComputePipeline)( | 	void (*BindComputePipeline)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer *commandBuffer, | 		Refresh_CommandBuffer *commandBuffer, | ||||||
| 		Refresh_ComputePipeline *computePipeline | 		Refresh_ComputePipeline *computePipeline | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*BindComputeBuffers)( | 	void (*BindComputeBuffers)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer *commandBuffer, | 		Refresh_CommandBuffer *commandBuffer, | ||||||
| 		Refresh_Buffer **pBuffers | 		Refresh_Buffer **pBuffers | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*BindComputeTextures)( | 	void (*BindComputeTextures)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		Refresh_CommandBuffer *commandBuffer, | 		Refresh_CommandBuffer *commandBuffer, | ||||||
| 		Refresh_Texture **pTextures | 		Refresh_Texture **pTextures | ||||||
|  | @ -469,7 +469,7 @@ struct Refresh_Device | ||||||
| 		Refresh_PresentMode presentMode | 		Refresh_PresentMode presentMode | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*UnclaimWindow)( | 	void (*UnclaimWindow)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		void *windowHandle | 		void *windowHandle | ||||||
| 	); | 	); | ||||||
|  | @ -497,16 +497,37 @@ struct Refresh_Device | ||||||
| 		Refresh_PresentMode presentMode | 		Refresh_PresentMode presentMode | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*Submit)( | 	void (*Submit)( | ||||||
| 		Refresh_Renderer *driverData, | 		Refresh_Renderer *driverData, | ||||||
| 		uint32_t commandBufferCount, | 		Refresh_CommandBuffer *commandBuffer | ||||||
| 		Refresh_CommandBuffer **pCommandBuffers |  | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void(*Wait)( | 	void (*SubmitAndAcquireFence)( | ||||||
|  | 		Refresh_Renderer *driverData, | ||||||
|  | 		Refresh_CommandBuffer *commandBuffer | ||||||
|  | 	); | ||||||
|  | 
 | ||||||
|  | 	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; | ||||||
|  | @ -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; | ||||||
|  | @ -10239,6 +10224,8 @@ static void VULKAN_Wait( | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/* TODO: consider if it's not a good idea to do cleanup here */ | ||||||
|  | 
 | ||||||
| 	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 +10237,93 @@ static void VULKAN_Wait( | ||||||
| 	SDL_UnlockMutex(renderer->submitLock); | 	SDL_UnlockMutex(renderer->submitLock); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 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; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	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); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return fence; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void VULKAN_INTERNAL_ReturnFenceToPool( | ||||||
|  | 	VulkanRenderer *renderer, | ||||||
|  | 	VkFence fence | ||||||
|  | ) { | ||||||
|  | 	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; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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,99 +10338,97 @@ 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) | 		VULKAN_INTERNAL_ImageMemoryBarrier( | ||||||
| 		{ | 			renderer, | ||||||
| 			swapchainImageIndex = currentCommandBuffer->presentDatas[j].swapchainImageIndex; | 			vulkanCommandBuffer->commandBuffer, | ||||||
| 
 | 			RESOURCE_ACCESS_PRESENT, | ||||||
| 			VULKAN_INTERNAL_ImageMemoryBarrier( | 			VK_IMAGE_ASPECT_COLOR_BIT, | ||||||
| 				renderer, | 			0, | ||||||
| 				currentCommandBuffer->commandBuffer, |  | ||||||
| 				RESOURCE_ACCESS_PRESENT, |  | ||||||
| 				VK_IMAGE_ASPECT_COLOR_BIT, |  | ||||||
| 				0, |  | ||||||
| 				1, |  | ||||||
| 				0, |  | ||||||
| 				1, |  | ||||||
| 				0, |  | ||||||
| 				currentCommandBuffer->presentDatas[j].windowData->swapchainData->textureContainers[swapchainImageIndex].vulkanTexture->image, |  | ||||||
| 				¤tCommandBuffer->presentDatas[j].windowData->swapchainData->textureContainers[swapchainImageIndex].vulkanTexture->resourceAccessType |  | ||||||
| 			); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		VULKAN_INTERNAL_EndCommandBuffer(renderer, currentCommandBuffer); |  | ||||||
| 
 |  | ||||||
| 		submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; |  | ||||||
| 		submitInfo.pNext = NULL; |  | ||||||
| 		submitInfo.commandBufferCount = 1; |  | ||||||
| 		submitInfo.pCommandBuffers = ¤tCommandBuffer->commandBuffer; |  | ||||||
| 
 |  | ||||||
| 		submitInfo.pWaitDstStageMask = waitStages; |  | ||||||
| 		submitInfo.pWaitSemaphores = currentCommandBuffer->waitSemaphores; |  | ||||||
| 		submitInfo.waitSemaphoreCount = currentCommandBuffer->waitSemaphoreCount; |  | ||||||
| 		submitInfo.pSignalSemaphores = currentCommandBuffer->signalSemaphores; |  | ||||||
| 		submitInfo.signalSemaphoreCount = currentCommandBuffer->signalSemaphoreCount; |  | ||||||
| 
 |  | ||||||
| 		vulkanResult = renderer->vkQueueSubmit( |  | ||||||
| 			renderer->unifiedQueue, |  | ||||||
| 			1, | 			1, | ||||||
| 			&submitInfo, | 			0, | ||||||
| 			currentCommandBuffer->inFlightFence | 			1, | ||||||
|  | 			0, | ||||||
|  | 			vulkanCommandBuffer->presentDatas[j].windowData->swapchainData->textureContainers[swapchainImageIndex].vulkanTexture->image, | ||||||
|  | 			&vulkanCommandBuffer->presentDatas[j].windowData->swapchainData->textureContainers[swapchainImageIndex].vulkanTexture->resourceAccessType | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	VULKAN_INTERNAL_EndCommandBuffer(renderer, vulkanCommandBuffer); | ||||||
|  | 
 | ||||||
|  | 	vulkanCommandBuffer->autoReleaseFence = 1; | ||||||
|  | 	vulkanCommandBuffer->inFlightFence = VULKAN_INTERNAL_AcquireFenceFromPool(renderer); | ||||||
|  | 
 | ||||||
|  | 	submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; | ||||||
|  | 	submitInfo.pNext = NULL; | ||||||
|  | 	submitInfo.commandBufferCount = 1; | ||||||
|  | 	submitInfo.pCommandBuffers = &vulkanCommandBuffer->commandBuffer; | ||||||
|  | 
 | ||||||
|  | 	submitInfo.pWaitDstStageMask = waitStages; | ||||||
|  | 	submitInfo.pWaitSemaphores = vulkanCommandBuffer->waitSemaphores; | ||||||
|  | 	submitInfo.waitSemaphoreCount = vulkanCommandBuffer->waitSemaphoreCount; | ||||||
|  | 	submitInfo.pSignalSemaphores = vulkanCommandBuffer->signalSemaphores; | ||||||
|  | 	submitInfo.signalSemaphoreCount = vulkanCommandBuffer->signalSemaphoreCount; | ||||||
|  | 
 | ||||||
|  | 	vulkanResult = renderer->vkQueueSubmit( | ||||||
|  | 		renderer->unifiedQueue, | ||||||
|  | 		1, | ||||||
|  | 		&submitInfo, | ||||||
|  | 		vulkanCommandBuffer->inFlightFence | ||||||
|  | 	); | ||||||
|  | 
 | ||||||
|  | 	if (vulkanResult != VK_SUCCESS) | ||||||
|  | 	{ | ||||||
|  | 		LogVulkanResultAsError("vkQueueSubmit", vulkanResult); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Mark command buffers as submitted */ | ||||||
|  | 
 | ||||||
|  | 	if (renderer->submittedCommandBufferCount + 1 >= renderer->submittedCommandBufferCapacity) | ||||||
|  | 	{ | ||||||
|  | 		renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + 1; | ||||||
|  | 
 | ||||||
|  | 		renderer->submittedCommandBuffers = SDL_realloc( | ||||||
|  | 			renderer->submittedCommandBuffers, | ||||||
|  | 			sizeof(VulkanCommandBuffer*) * renderer->submittedCommandBufferCapacity | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = vulkanCommandBuffer; | ||||||
|  | 	renderer->submittedCommandBufferCount += 1; | ||||||
|  | 
 | ||||||
|  | 	/* Present, if applicable */ | ||||||
|  | 
 | ||||||
|  | 	for (j = 0; j < vulkanCommandBuffer->presentDataCount; j += 1) | ||||||
|  | 	{ | ||||||
|  | 		presentData = &vulkanCommandBuffer->presentDatas[j]; | ||||||
|  | 
 | ||||||
|  | 		presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; | ||||||
|  | 		presentInfo.pNext = NULL; | ||||||
|  | 		presentInfo.pWaitSemaphores = &presentData->windowData->swapchainData->renderFinishedSemaphore; | ||||||
|  | 		presentInfo.waitSemaphoreCount = 1; | ||||||
|  | 		presentInfo.pSwapchains = &presentData->windowData->swapchainData->swapchain; | ||||||
|  | 		presentInfo.swapchainCount = 1; | ||||||
|  | 		presentInfo.pImageIndices = &presentData->swapchainImageIndex; | ||||||
|  | 		presentInfo.pResults = NULL; | ||||||
|  | 
 | ||||||
|  | 		presentResult = renderer->vkQueuePresentKHR( | ||||||
|  | 			renderer->unifiedQueue, | ||||||
|  | 			&presentInfo | ||||||
| 		); | 		); | ||||||
| 
 | 
 | ||||||
| 		if (vulkanResult != VK_SUCCESS) | 		if (presentResult != VK_SUCCESS) | ||||||
| 		{ | 		{ | ||||||
| 			LogVulkanResultAsError("vkQueueSubmit", vulkanResult); | 			VULKAN_INTERNAL_RecreateSwapchain( | ||||||
| 		} | 				renderer, | ||||||
| 
 | 				presentData->windowData | ||||||
| 		/* Mark command buffers as submitted */ |  | ||||||
| 
 |  | ||||||
| 		if (renderer->submittedCommandBufferCount + 1 >= renderer->submittedCommandBufferCapacity) |  | ||||||
| 		{ |  | ||||||
| 			renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + 1; |  | ||||||
| 
 |  | ||||||
| 			renderer->submittedCommandBuffers = SDL_realloc( |  | ||||||
| 				renderer->submittedCommandBuffers, |  | ||||||
| 				sizeof(VulkanCommandBuffer*) * renderer->submittedCommandBufferCapacity |  | ||||||
| 			); | 			); | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = (VulkanCommandBuffer*) pCommandBuffers[i]; |  | ||||||
| 		renderer->submittedCommandBufferCount += 1; |  | ||||||
| 
 |  | ||||||
| 		/* Present, if applicable */ |  | ||||||
| 
 |  | ||||||
| 		for (j = 0; j < currentCommandBuffer->presentDataCount; j += 1) |  | ||||||
| 		{ |  | ||||||
| 			presentData = ¤tCommandBuffer->presentDatas[j]; |  | ||||||
| 
 |  | ||||||
| 			presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; |  | ||||||
| 			presentInfo.pNext = NULL; |  | ||||||
| 			presentInfo.pWaitSemaphores = &presentData->windowData->swapchainData->renderFinishedSemaphore; |  | ||||||
| 			presentInfo.waitSemaphoreCount = 1; |  | ||||||
| 			presentInfo.pSwapchains = &presentData->windowData->swapchainData->swapchain; |  | ||||||
| 			presentInfo.swapchainCount = 1; |  | ||||||
| 			presentInfo.pImageIndices = &presentData->swapchainImageIndex; |  | ||||||
| 			presentInfo.pResults = NULL; |  | ||||||
| 
 |  | ||||||
| 			presentResult = renderer->vkQueuePresentKHR( |  | ||||||
| 				renderer->unifiedQueue, |  | ||||||
| 				&presentInfo |  | ||||||
| 			); |  | ||||||
| 
 |  | ||||||
| 			if (presentResult != VK_SUCCESS) |  | ||||||
| 			{ |  | ||||||
| 				VULKAN_INTERNAL_RecreateSwapchain( |  | ||||||
| 					renderer, |  | ||||||
| 					presentData->windowData |  | ||||||
| 				); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Check if we can perform any cleanups */ | 	/* Check if we can perform any cleanups */ | ||||||
|  | @ -10381,6 +10442,16 @@ static void VULKAN_Submit( | ||||||
| 
 | 
 | ||||||
| 		if (vulkanResult == VK_SUCCESS) | 		if (vulkanResult == VK_SUCCESS) | ||||||
| 		{ | 		{ | ||||||
|  | 			if (renderer->submittedCommandBuffers[i]->autoReleaseFence) | ||||||
|  | 			{ | ||||||
|  | 				VULKAN_INTERNAL_ReturnFenceToPool( | ||||||
|  | 					renderer, | ||||||
|  | 					renderer->submittedCommandBuffers[i]->inFlightFence | ||||||
|  | 				); | ||||||
|  | 
 | ||||||
|  | 				renderer->submittedCommandBuffers[i]->inFlightFence = VK_NULL_HANDLE; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			VULKAN_INTERNAL_CleanCommandBuffer( | 			VULKAN_INTERNAL_CleanCommandBuffer( | ||||||
| 				renderer, | 				renderer, | ||||||
| 				renderer->submittedCommandBuffers[i] | 				renderer->submittedCommandBuffers[i] | ||||||
|  | @ -10670,8 +10741,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 +10749,60 @@ 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, | ||||||
|  | 		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(driverData, (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 +12090,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