|  |  |  | @ -190,6 +190,7 @@ static VkFormat RefreshToVK_SurfaceFormat[] = | 
		
	
		
			
				|  |  |  |  | 	VK_FORMAT_BC1_RGBA_UNORM_BLOCK,		/* BC1 */ | 
		
	
		
			
				|  |  |  |  | 	VK_FORMAT_BC2_UNORM_BLOCK,		/* BC3 */ | 
		
	
		
			
				|  |  |  |  | 	VK_FORMAT_BC3_UNORM_BLOCK,		/* BC5 */ | 
		
	
		
			
				|  |  |  |  | 	VK_FORMAT_BC7_UNORM_BLOCK,		/* BC7 */ | 
		
	
		
			
				|  |  |  |  | 	VK_FORMAT_R8G8_SNORM,			/* R8G8_SNORM */ | 
		
	
		
			
				|  |  |  |  | 	VK_FORMAT_R8G8B8A8_SNORM,		/* R8G8B8A8_SNORM */ | 
		
	
		
			
				|  |  |  |  | 	VK_FORMAT_A2R10G10B10_UNORM_PACK32,	/* A2R10G10B10 */ | 
		
	
	
		
			
				
					|  |  |  | @ -912,6 +913,7 @@ static inline void DescriptorSetLayoutHashTable_Insert( | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | typedef struct RenderPassColorTargetDescription | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	VkFormat format; | 
		
	
		
			
				|  |  |  |  | 	Refresh_Vec4 clearColor; | 
		
	
		
			
				|  |  |  |  | 	Refresh_LoadOp loadOp; | 
		
	
		
			
				|  |  |  |  | 	Refresh_StoreOp storeOp; | 
		
	
	
		
			
				
					|  |  |  | @ -919,6 +921,7 @@ typedef struct RenderPassColorTargetDescription | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | typedef struct RenderPassDepthStencilTargetDescription | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	VkFormat format; | 
		
	
		
			
				|  |  |  |  | 	Refresh_LoadOp loadOp; | 
		
	
		
			
				|  |  |  |  | 	Refresh_StoreOp storeOp; | 
		
	
		
			
				|  |  |  |  | 	Refresh_LoadOp stencilLoadOp; | 
		
	
	
		
			
				
					|  |  |  | @ -958,6 +961,11 @@ static inline uint8_t RenderPassHash_Compare( | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	for (i = 0; i < a->colorAttachmentCount; i += 1) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		if (a->colorTargetDescriptions[i].format != b->colorTargetDescriptions[i].format) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			return 0; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		if (	a->colorTargetDescriptions[i].clearColor.x != b->colorTargetDescriptions[i].clearColor.x || | 
		
	
		
			
				|  |  |  |  | 			a->colorTargetDescriptions[i].clearColor.y != b->colorTargetDescriptions[i].clearColor.y || | 
		
	
		
			
				|  |  |  |  | 			a->colorTargetDescriptions[i].clearColor.z != b->colorTargetDescriptions[i].clearColor.z || | 
		
	
	
		
			
				
					|  |  |  | @ -977,6 +985,11 @@ static inline uint8_t RenderPassHash_Compare( | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	if (a->depthStencilTargetDescription.format != b->depthStencilTargetDescription.format) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		return 0; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	if (a->depthStencilTargetDescription.loadOp != b->depthStencilTargetDescription.loadOp) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		return 0; | 
		
	
	
		
			
				
					|  |  |  | @ -1674,6 +1687,10 @@ typedef struct VulkanRenderer | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	VkDeviceSize minUBOAlignment; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	/* Some drivers don't support D16 for some reason. Fun! */ | 
		
	
		
			
				|  |  |  |  | 	VkFormat D16Format; | 
		
	
		
			
				|  |  |  |  | 	VkFormat D16S8Format; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	VulkanTexture **texturesToDestroy; | 
		
	
		
			
				|  |  |  |  | 	uint32_t texturesToDestroyCount; | 
		
	
		
			
				|  |  |  |  | 	uint32_t texturesToDestroyCapacity; | 
		
	
	
		
			
				
					|  |  |  | @ -1782,6 +1799,40 @@ static inline void LogVulkanResultAsWarn( | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | /* Utility */ | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static inline VkFormat RefreshToVK_DepthFormat( | 
		
	
		
			
				|  |  |  |  | 	VulkanRenderer* renderer, | 
		
	
		
			
				|  |  |  |  | 	Refresh_TextureFormat format | 
		
	
		
			
				|  |  |  |  | ) { | 
		
	
		
			
				|  |  |  |  | 	switch (format) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		case REFRESH_TEXTUREFORMAT_D16_UNORM: | 
		
	
		
			
				|  |  |  |  | 			return renderer->D16Format; | 
		
	
		
			
				|  |  |  |  | 		case REFRESH_TEXTUREFORMAT_D16_UNORM_S8_UINT: | 
		
	
		
			
				|  |  |  |  | 			return renderer->D16S8Format; | 
		
	
		
			
				|  |  |  |  | 		case REFRESH_TEXTUREFORMAT_D32_SFLOAT: | 
		
	
		
			
				|  |  |  |  | 			return VK_FORMAT_D32_SFLOAT; | 
		
	
		
			
				|  |  |  |  | 		case REFRESH_TEXTUREFORMAT_D32_SFLOAT_S8_UINT: | 
		
	
		
			
				|  |  |  |  | 			return VK_FORMAT_D32_SFLOAT_S8_UINT; | 
		
	
		
			
				|  |  |  |  | 		default: | 
		
	
		
			
				|  |  |  |  | 			return VK_FORMAT_UNDEFINED; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static inline uint8_t IsRefreshDepthFormat(Refresh_TextureFormat format) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	switch (format) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		case REFRESH_TEXTUREFORMAT_D16_UNORM: | 
		
	
		
			
				|  |  |  |  | 		case REFRESH_TEXTUREFORMAT_D32_SFLOAT: | 
		
	
		
			
				|  |  |  |  | 		case REFRESH_TEXTUREFORMAT_D16_UNORM_S8_UINT: | 
		
	
		
			
				|  |  |  |  | 		case REFRESH_TEXTUREFORMAT_D32_SFLOAT_S8_UINT: | 
		
	
		
			
				|  |  |  |  | 			return 1; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		default: | 
		
	
		
			
				|  |  |  |  | 			return 0; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static inline uint8_t IsDepthFormat(VkFormat format) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	switch(format) | 
		
	
	
		
			
				
					|  |  |  | @ -1817,6 +1868,7 @@ static inline uint32_t VULKAN_INTERNAL_BytesPerPixel(VkFormat format) | 
		
	
		
			
				|  |  |  |  | 		case VK_FORMAT_R32G32B32A32_SFLOAT: | 
		
	
		
			
				|  |  |  |  | 		case VK_FORMAT_BC2_UNORM_BLOCK: | 
		
	
		
			
				|  |  |  |  | 		case VK_FORMAT_BC3_UNORM_BLOCK: | 
		
	
		
			
				|  |  |  |  | 		case VK_FORMAT_BC7_UNORM_BLOCK: | 
		
	
		
			
				|  |  |  |  | 			return 16; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		case VK_FORMAT_R8G8B8A8_UNORM: | 
		
	
	
		
			
				
					|  |  |  | @ -1857,6 +1909,40 @@ static inline uint32_t VULKAN_INTERNAL_BytesPerPixel(VkFormat format) | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static inline uint32_t VULKAN_INTERNAL_GetTextureBlockSize( | 
		
	
		
			
				|  |  |  |  | 	VkFormat format | 
		
	
		
			
				|  |  |  |  | ) { | 
		
	
		
			
				|  |  |  |  | 	switch (format) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_BC2_UNORM_BLOCK: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_BC3_UNORM_BLOCK: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_BC7_UNORM_BLOCK: | 
		
	
		
			
				|  |  |  |  | 		return 4; | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_R8G8B8A8_UNORM: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_B8G8R8A8_UNORM: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_R5G6B5_UNORM_PACK16: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_A1R5G5B5_UNORM_PACK16: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_B4G4R4A4_UNORM_PACK16: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_R8G8_SNORM: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_R8G8B8A8_SNORM: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_A2R10G10B10_UNORM_PACK32: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_R16G16_UNORM: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_R16G16B16A16_UNORM: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_R8_UNORM: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_R32_SFLOAT: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_R32G32_SFLOAT: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_R32G32B32A32_SFLOAT: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_R16_SFLOAT: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_R16G16_SFLOAT: | 
		
	
		
			
				|  |  |  |  | 	case VK_FORMAT_R16G16B16A16_SFLOAT: | 
		
	
		
			
				|  |  |  |  | 		return 1; | 
		
	
		
			
				|  |  |  |  | 	default: | 
		
	
		
			
				|  |  |  |  | 		Refresh_LogError("Unrecognized texture format!"); | 
		
	
		
			
				|  |  |  |  | 		return 0; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static inline VkDeviceSize VULKAN_INTERNAL_BytesPerImage( | 
		
	
		
			
				|  |  |  |  | 	uint32_t width, | 
		
	
		
			
				|  |  |  |  | 	uint32_t height, | 
		
	
	
		
			
				
					|  |  |  | @ -1864,12 +1950,12 @@ static inline VkDeviceSize VULKAN_INTERNAL_BytesPerImage( | 
		
	
		
			
				|  |  |  |  | ) { | 
		
	
		
			
				|  |  |  |  | 	uint32_t blocksPerRow = width; | 
		
	
		
			
				|  |  |  |  | 	uint32_t blocksPerColumn = height; | 
		
	
		
			
				|  |  |  |  | 	uint32_t blockSize = VULKAN_INTERNAL_GetTextureBlockSize(format); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	if (format == VK_FORMAT_BC1_RGBA_UNORM_BLOCK || | 
		
	
		
			
				|  |  |  |  | 		format == VK_FORMAT_BC3_UNORM_BLOCK || | 
		
	
		
			
				|  |  |  |  | 		format == VK_FORMAT_BC5_UNORM_BLOCK) | 
		
	
		
			
				|  |  |  |  | 	if (blockSize > 1) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		blocksPerRow = (width + 3) / 4; | 
		
	
		
			
				|  |  |  |  | 		blocksPerRow = (width + blockSize - 1) / blockSize; | 
		
	
		
			
				|  |  |  |  | 		blocksPerColumn = (height + blockSize - 1) / blockSize; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	return blocksPerRow * blocksPerColumn * VULKAN_INTERNAL_BytesPerPixel(format); | 
		
	
	
		
			
				
					|  |  |  | @ -5614,9 +5700,10 @@ static VkRenderPass VULKAN_INTERNAL_CreateTransientRenderPass( | 
		
	
		
			
				|  |  |  |  | 	if (attachmentInfo.hasDepthStencilAttachment) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		attachmentDescriptions[attachmentDescriptionCount].flags = 0; | 
		
	
		
			
				|  |  |  |  | 		attachmentDescriptions[attachmentDescriptionCount].format = RefreshToVK_SurfaceFormat[ | 
		
	
		
			
				|  |  |  |  | 		attachmentDescriptions[attachmentDescriptionCount].format = RefreshToVK_DepthFormat( | 
		
	
		
			
				|  |  |  |  | 			renderer, | 
		
	
		
			
				|  |  |  |  | 			attachmentInfo.depthStencilFormat | 
		
	
		
			
				|  |  |  |  | 		]; | 
		
	
		
			
				|  |  |  |  | 		); | 
		
	
		
			
				|  |  |  |  | 		attachmentDescriptions[attachmentDescriptionCount].samples = | 
		
	
		
			
				|  |  |  |  | 			VK_SAMPLE_COUNT_1_BIT; /* FIXME: do these take multisamples? */ | 
		
	
		
			
				|  |  |  |  | 		attachmentDescriptions[attachmentDescriptionCount].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; | 
		
	
	
		
			
				
					|  |  |  | @ -6313,7 +6400,16 @@ static Refresh_Texture* VULKAN_CreateTexture( | 
		
	
		
			
				|  |  |  |  | 		VK_IMAGE_USAGE_TRANSFER_SRC_BIT | 
		
	
		
			
				|  |  |  |  | 	); | 
		
	
		
			
				|  |  |  |  | 	VkImageAspectFlags imageAspectFlags; | 
		
	
		
			
				|  |  |  |  | 	VkFormat format = RefreshToVK_SurfaceFormat[textureCreateInfo->format]; | 
		
	
		
			
				|  |  |  |  | 	VkFormat format; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	if (IsRefreshDepthFormat(textureCreateInfo->format)) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		format = RefreshToVK_DepthFormat(renderer, textureCreateInfo->format); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	else | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		format = RefreshToVK_SurfaceFormat[textureCreateInfo->format]; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	if (textureCreateInfo->usageFlags & REFRESH_TEXTUREUSAGE_SAMPLER_BIT) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
	
		
			
				
					|  |  |  | @ -6507,6 +6603,9 @@ static void VULKAN_SetTextureData( | 
		
	
		
			
				|  |  |  |  | 	VulkanTransferBuffer *transferBuffer; | 
		
	
		
			
				|  |  |  |  | 	VkBufferImageCopy imageCopy; | 
		
	
		
			
				|  |  |  |  | 	uint8_t *stagingBufferPointer; | 
		
	
		
			
				|  |  |  |  | 	uint32_t blockSize = VULKAN_INTERNAL_GetTextureBlockSize(vulkanTexture->format); | 
		
	
		
			
				|  |  |  |  | 	uint32_t bufferRowLength; | 
		
	
		
			
				|  |  |  |  | 	uint32_t bufferImageHeight; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	if (vulkanCommandBuffer->renderPassInProgress) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
	
		
			
				
					|  |  |  | @ -6555,6 +6654,9 @@ static void VULKAN_SetTextureData( | 
		
	
		
			
				|  |  |  |  | 		&vulkanTexture->resourceAccessType | 
		
	
		
			
				|  |  |  |  | 	); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	bufferRowLength = SDL_max(blockSize, textureSlice->rectangle.w); | 
		
	
		
			
				|  |  |  |  | 	bufferImageHeight = SDL_max(blockSize, textureSlice->rectangle.h); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	imageCopy.imageExtent.width = textureSlice->rectangle.w; | 
		
	
		
			
				|  |  |  |  | 	imageCopy.imageExtent.height = textureSlice->rectangle.h; | 
		
	
		
			
				|  |  |  |  | 	imageCopy.imageExtent.depth = 1; | 
		
	
	
		
			
				
					|  |  |  | @ -6566,8 +6668,8 @@ static void VULKAN_SetTextureData( | 
		
	
		
			
				|  |  |  |  | 	imageCopy.imageSubresource.layerCount = 1; | 
		
	
		
			
				|  |  |  |  | 	imageCopy.imageSubresource.mipLevel = textureSlice->level; | 
		
	
		
			
				|  |  |  |  | 	imageCopy.bufferOffset = transferBuffer->offset; | 
		
	
		
			
				|  |  |  |  | 	imageCopy.bufferRowLength = 0; | 
		
	
		
			
				|  |  |  |  | 	imageCopy.bufferImageHeight = 0; | 
		
	
		
			
				|  |  |  |  | 	imageCopy.bufferRowLength = bufferRowLength; | 
		
	
		
			
				|  |  |  |  | 	imageCopy.bufferImageHeight = bufferImageHeight; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	renderer->vkCmdCopyBufferToImage( | 
		
	
		
			
				|  |  |  |  | 		vulkanCommandBuffer->commandBuffer, | 
		
	
	
		
			
				
					|  |  |  | @ -6692,6 +6794,24 @@ static void VULKAN_SetTextureDataYUV( | 
		
	
		
			
				|  |  |  |  | 		&imageCopy | 
		
	
		
			
				|  |  |  |  | 	); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	if (tex->usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		/* TODO: is it worth it to only transition the specific subresource? */ | 
		
	
		
			
				|  |  |  |  | 		VULKAN_INTERNAL_ImageMemoryBarrier( | 
		
	
		
			
				|  |  |  |  | 			renderer, | 
		
	
		
			
				|  |  |  |  | 			vulkanCommandBuffer->commandBuffer, | 
		
	
		
			
				|  |  |  |  | 			RESOURCE_ACCESS_ANY_SHADER_READ_SAMPLED_IMAGE, | 
		
	
		
			
				|  |  |  |  | 			VK_IMAGE_ASPECT_COLOR_BIT, | 
		
	
		
			
				|  |  |  |  | 			0, | 
		
	
		
			
				|  |  |  |  | 			tex->layerCount, | 
		
	
		
			
				|  |  |  |  | 			0, | 
		
	
		
			
				|  |  |  |  | 			tex->levelCount, | 
		
	
		
			
				|  |  |  |  | 			0, | 
		
	
		
			
				|  |  |  |  | 			tex->image, | 
		
	
		
			
				|  |  |  |  | 			&tex->resourceAccessType | 
		
	
		
			
				|  |  |  |  | 		); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, tex); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	/* These apply to both U and V */ | 
		
	
	
		
			
				
					|  |  |  | @ -6736,6 +6856,24 @@ static void VULKAN_SetTextureDataYUV( | 
		
	
		
			
				|  |  |  |  | 		&imageCopy | 
		
	
		
			
				|  |  |  |  | 	); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	if (tex->usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		/* TODO: is it worth it to only transition the specific subresource? */ | 
		
	
		
			
				|  |  |  |  | 		VULKAN_INTERNAL_ImageMemoryBarrier( | 
		
	
		
			
				|  |  |  |  | 			renderer, | 
		
	
		
			
				|  |  |  |  | 			vulkanCommandBuffer->commandBuffer, | 
		
	
		
			
				|  |  |  |  | 			RESOURCE_ACCESS_ANY_SHADER_READ_SAMPLED_IMAGE, | 
		
	
		
			
				|  |  |  |  | 			VK_IMAGE_ASPECT_COLOR_BIT, | 
		
	
		
			
				|  |  |  |  | 			0, | 
		
	
		
			
				|  |  |  |  | 			tex->layerCount, | 
		
	
		
			
				|  |  |  |  | 			0, | 
		
	
		
			
				|  |  |  |  | 			tex->levelCount, | 
		
	
		
			
				|  |  |  |  | 			0, | 
		
	
		
			
				|  |  |  |  | 			tex->image, | 
		
	
		
			
				|  |  |  |  | 			&tex->resourceAccessType | 
		
	
		
			
				|  |  |  |  | 		); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, tex); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	/* V */ | 
		
	
	
		
			
				
					|  |  |  | @ -6775,11 +6913,9 @@ static void VULKAN_SetTextureDataYUV( | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	transferBuffer->offset += yDataLength + uvDataLength; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, tex); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	/* FIXME: don't we have to do this for every image? */ | 
		
	
		
			
				|  |  |  |  | 	if (tex->usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		/* TODO: is it worth it to only transition the specific subresource? */ | 
		
	
		
			
				|  |  |  |  | 		VULKAN_INTERNAL_ImageMemoryBarrier( | 
		
	
		
			
				|  |  |  |  | 			renderer, | 
		
	
		
			
				|  |  |  |  | 			vulkanCommandBuffer->commandBuffer, | 
		
	
	
		
			
				
					|  |  |  | @ -6794,6 +6930,8 @@ static void VULKAN_SetTextureDataYUV( | 
		
	
		
			
				|  |  |  |  | 			&tex->resourceAccessType | 
		
	
		
			
				|  |  |  |  | 		); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, tex); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | static void VULKAN_INTERNAL_BlitImage( | 
		
	
	
		
			
				
					|  |  |  | @ -6858,8 +6996,8 @@ static void VULKAN_INTERNAL_BlitImage( | 
		
	
		
			
				|  |  |  |  | 	blit.dstOffsets[1].y = destinationTextureSlice->rectangle.y + destinationTextureSlice->rectangle.h; | 
		
	
		
			
				|  |  |  |  | 	blit.dstOffsets[1].z = 1; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	blit.dstSubresource.mipLevel = sourceTextureSlice->level; | 
		
	
		
			
				|  |  |  |  | 	blit.dstSubresource.baseArrayLayer = sourceTextureSlice->layer; | 
		
	
		
			
				|  |  |  |  | 	blit.dstSubresource.mipLevel = destinationTextureSlice->level; | 
		
	
		
			
				|  |  |  |  | 	blit.dstSubresource.baseArrayLayer = destinationTextureSlice->layer; | 
		
	
		
			
				|  |  |  |  | 	blit.dstSubresource.layerCount = 1; | 
		
	
		
			
				|  |  |  |  | 	blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -7656,6 +7794,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass( | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	for (i = 0; i < colorAttachmentCount; i += 1) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		hash.colorTargetDescriptions[i].format = ((VulkanTexture*) colorAttachmentInfos[i].texture)->format; | 
		
	
		
			
				|  |  |  |  | 		hash.colorTargetDescriptions[i].clearColor = colorAttachmentInfos[i].clearColor; | 
		
	
		
			
				|  |  |  |  | 		hash.colorTargetDescriptions[i].loadOp = colorAttachmentInfos[i].loadOp; | 
		
	
		
			
				|  |  |  |  | 		hash.colorTargetDescriptions[i].storeOp = colorAttachmentInfos[i].storeOp; | 
		
	
	
		
			
				
					|  |  |  | @ -7665,6 +7804,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass( | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	if (depthStencilAttachmentInfo == NULL) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		hash.depthStencilTargetDescription.format = 0; | 
		
	
		
			
				|  |  |  |  | 		hash.depthStencilTargetDescription.loadOp = REFRESH_LOADOP_DONT_CARE; | 
		
	
		
			
				|  |  |  |  | 		hash.depthStencilTargetDescription.storeOp = REFRESH_STOREOP_DONT_CARE; | 
		
	
		
			
				|  |  |  |  | 		hash.depthStencilTargetDescription.stencilLoadOp = REFRESH_LOADOP_DONT_CARE; | 
		
	
	
		
			
				
					|  |  |  | @ -7672,6 +7812,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass( | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	else | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		hash.depthStencilTargetDescription.format = ((VulkanTexture*) depthStencilAttachmentInfo->texture)->format; | 
		
	
		
			
				|  |  |  |  | 		hash.depthStencilTargetDescription.loadOp = depthStencilAttachmentInfo->loadOp; | 
		
	
		
			
				|  |  |  |  | 		hash.depthStencilTargetDescription.storeOp = depthStencilAttachmentInfo->storeOp; | 
		
	
		
			
				|  |  |  |  | 		hash.depthStencilTargetDescription.stencilLoadOp = depthStencilAttachmentInfo->stencilLoadOp; | 
		
	
	
		
			
				
					|  |  |  | @ -8000,6 +8141,8 @@ static void VULKAN_BeginRenderPass( | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	if (depthStencilAttachmentInfo != NULL) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		texture = (VulkanTexture*) depthStencilAttachmentInfo->texture; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		if (texture->dimensions.width < framebufferWidth) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			framebufferWidth = texture->dimensions.width; | 
		
	
	
		
			
				
					|  |  |  | @ -9363,9 +9506,9 @@ static void VULKAN_Submit( | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		/* Mark command buffers as submitted */ | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		if (renderer->submittedCommandBufferCount + commandBufferCount >= renderer->submittedCommandBufferCapacity) | 
		
	
		
			
				|  |  |  |  | 		if (renderer->submittedCommandBufferCount + 1 >= renderer->submittedCommandBufferCapacity) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + commandBufferCount; | 
		
	
		
			
				|  |  |  |  | 			renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + 1; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 			renderer->submittedCommandBuffers = SDL_realloc( | 
		
	
		
			
				|  |  |  |  | 				renderer->submittedCommandBuffers, | 
		
	
	
		
			
				
					|  |  |  | @ -9373,12 +9516,9 @@ static void VULKAN_Submit( | 
		
	
		
			
				|  |  |  |  | 			); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		for (i = 0; i < commandBufferCount; i += 1) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 		((VulkanCommandBuffer*)pCommandBuffers[i])->submitted = 1; | 
		
	
		
			
				|  |  |  |  | 		renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = (VulkanCommandBuffer*) pCommandBuffers[i]; | 
		
	
		
			
				|  |  |  |  | 		renderer->submittedCommandBufferCount += 1; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		/* Present, if applicable */ | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -10132,6 +10272,9 @@ static Refresh_Device* VULKAN_CreateDevice( | 
		
	
		
			
				|  |  |  |  | 	VkDescriptorPoolSize poolSizes[4]; | 
		
	
		
			
				|  |  |  |  | 	VkDescriptorSetAllocateInfo descriptorAllocateInfo; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	/* Variables: Image Format Detection */ | 
		
	
		
			
				|  |  |  |  | 	VkImageFormatProperties imageFormatProperties; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	VULKAN_INTERNAL_LoadEntryPoints(renderer); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	renderer->presentMode = presentationParameters->presentMode; | 
		
	
	
		
			
				
					|  |  |  | @ -10571,12 +10714,53 @@ static Refresh_Device* VULKAN_CreateDevice( | 
		
	
		
			
				|  |  |  |  | 	renderer->renderTargetHashArray.capacity = 0; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	/* Initialize transfer buffer pool */ | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	renderer->transferBufferPool.lock = SDL_CreateMutex(); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	renderer->transferBufferPool.availableBufferCapacity = 4; | 
		
	
		
			
				|  |  |  |  | 	renderer->transferBufferPool.availableBufferCount = 0; | 
		
	
		
			
				|  |  |  |  | 	renderer->transferBufferPool.availableBuffers = SDL_malloc(renderer->transferBufferPool.availableBufferCapacity * sizeof(VulkanTransferBuffer*)); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	/* Some drivers don't support D16, so we have to fall back to D32. */ | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	vulkanResult = renderer->vkGetPhysicalDeviceImageFormatProperties( | 
		
	
		
			
				|  |  |  |  | 		renderer->physicalDevice, | 
		
	
		
			
				|  |  |  |  | 		VK_FORMAT_D16_UNORM, | 
		
	
		
			
				|  |  |  |  | 		VK_IMAGE_TYPE_2D, | 
		
	
		
			
				|  |  |  |  | 		VK_IMAGE_TILING_OPTIMAL, | 
		
	
		
			
				|  |  |  |  | 		VK_IMAGE_ASPECT_DEPTH_BIT, | 
		
	
		
			
				|  |  |  |  | 		0, | 
		
	
		
			
				|  |  |  |  | 		&imageFormatProperties | 
		
	
		
			
				|  |  |  |  | 	); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	if (vulkanResult == VK_ERROR_FORMAT_NOT_SUPPORTED) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		renderer->D16Format = VK_FORMAT_D32_SFLOAT; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	else | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		renderer->D16Format = VK_FORMAT_D16_UNORM; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	vulkanResult = renderer->vkGetPhysicalDeviceImageFormatProperties( | 
		
	
		
			
				|  |  |  |  | 		renderer->physicalDevice, | 
		
	
		
			
				|  |  |  |  | 		VK_FORMAT_D16_UNORM_S8_UINT, | 
		
	
		
			
				|  |  |  |  | 		VK_IMAGE_TYPE_2D, | 
		
	
		
			
				|  |  |  |  | 		VK_IMAGE_TILING_OPTIMAL, | 
		
	
		
			
				|  |  |  |  | 		VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, | 
		
	
		
			
				|  |  |  |  | 		0, | 
		
	
		
			
				|  |  |  |  | 		&imageFormatProperties | 
		
	
		
			
				|  |  |  |  | 	); | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	if (vulkanResult == VK_ERROR_FORMAT_NOT_SUPPORTED) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		renderer->D16S8Format = VK_FORMAT_D32_SFLOAT_S8_UINT; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	else | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		renderer->D16S8Format = VK_FORMAT_D16_UNORM_S8_UINT; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	/* Deferred destroy storage */ | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	renderer->texturesToDestroyCapacity = 16; | 
		
	
	
		
			
				
					|  |  |  | 
 |