From 721854921d9d61fbef68e3392bc283f7ce5f8e7a Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Thu, 29 Feb 2024 17:17:49 -0800 Subject: [PATCH] restructure texture subresources --- include/Refresh.h | 20 +- src/Refresh.c | 6 +- src/Refresh_Driver.h | 3 +- src/Refresh_Driver_Vulkan.c | 1335 ++++++++++++++++------------------- 4 files changed, 608 insertions(+), 756 deletions(-) diff --git a/include/Refresh.h b/include/Refresh.h index 5ffe718..0c635b7 100644 --- a/include/Refresh.h +++ b/include/Refresh.h @@ -385,8 +385,7 @@ typedef struct Refresh_TextureSlice { Refresh_Texture *texture; uint32_t mipLevel; - uint32_t baseLayer; - uint32_t layerCount; + uint32_t layer; uint32_t x; uint32_t y; uint32_t z; @@ -495,6 +494,7 @@ typedef struct Refresh_TextureCreateInfo uint32_t height; uint32_t depth; uint8_t isCube; + uint32_t layerCount; uint32_t levelCount; Refresh_SampleCount sampleCount; Refresh_TextureFormat format; @@ -580,8 +580,7 @@ typedef struct Refresh_GraphicsPipelineCreateInfo typedef struct Refresh_ColorAttachmentInfo { - Refresh_Texture *texture; /* We can't use TextureSlice because render passes take a single rectangle. */ - uint32_t depth; + Refresh_Texture *texture; uint32_t layer; uint32_t level; Refresh_Vec4 clearColor; /* Can be ignored by RenderPass */ @@ -592,8 +591,7 @@ typedef struct Refresh_ColorAttachmentInfo typedef struct Refresh_DepthStencilAttachmentInfo { - Refresh_Texture *texture; /* We can't use TextureSlice because render passes take a single rectangle. */ - uint32_t depth; + Refresh_Texture *texture; uint32_t layer; uint32_t level; Refresh_DepthStencilValue depthStencilClearValue; /* Can be ignored by RenderPass */ @@ -1004,20 +1002,14 @@ REFRESHAPI void Refresh_BindComputeBuffers( /* Binds textures for use with the currently bound compute pipeline. * - * pTextures: An array of textures to bind. - * Length must be equal to the number of buffers - * specified by the compute pipeline. - * - * pLevels: An array of levels to bind, - * corresponding to the indices in pTextures. + * pTextureSlices: An array of texture slices to bind. * Length must be equal to the number of buffers * specified by the compute pipeline. */ REFRESHAPI void Refresh_BindComputeTextures( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, - Refresh_Texture **pTextures, - uint32_t **pLevels + Refresh_TextureSlice **pTextureSlices ); /* Pushes compute shader params to the device. diff --git a/src/Refresh.c b/src/Refresh.c index 986922f..3a1ce54 100644 --- a/src/Refresh.c +++ b/src/Refresh.c @@ -675,15 +675,13 @@ void Refresh_BindComputeBuffers( void Refresh_BindComputeTextures( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, - Refresh_Texture **pTextures, - uint32_t **pLevels + Refresh_TextureSlice **pTextureSlices ) { NULL_RETURN(device); device->BindComputeTextures( device->driverData, commandBuffer, - pTextures, - pLevels + pTextureSlices ); } diff --git a/src/Refresh_Driver.h b/src/Refresh_Driver.h index 6e92761..3aa3bce 100644 --- a/src/Refresh_Driver.h +++ b/src/Refresh_Driver.h @@ -389,8 +389,7 @@ struct Refresh_Device void (*BindComputeTextures)( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_Texture **pTextures, - uint32_t **pLevels + Refresh_TextureSlice **pTextureSlices ); void (*PushComputeShaderUniforms)( diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index c190a29..028468f 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -778,17 +778,27 @@ typedef struct VulkanShaderModule SDL_atomic_t referenceCount; } VulkanShaderModule; -typedef struct VulkanRenderTarget -{ - VkImageView view; - VulkanTexture *msaaTex; /* NULL if sample count is 1 or is depth target */ -} VulkanRenderTarget; - typedef struct VulkanTextureHandle { VulkanTexture *vulkanTexture; } VulkanTextureHandle; +/* Textures are made up of individual slices. + * This helps us barrier the resource efficiently. + */ +typedef struct VulkanTextureSlice +{ + VulkanTexture *parent; + uint32_t layer; + uint32_t level; + + VulkanResourceAccessType resourceAccessType; + SDL_atomic_t referenceCount; + + VkImageView view; + VulkanTexture *msaaTex; /* NULL if parent sample count is 1 or is depth target */ +} VulkanTextureSlice; + struct VulkanTexture { VulkanMemoryUsedRegion *usedRegion; @@ -799,19 +809,18 @@ struct VulkanTexture uint8_t is3D; uint8_t isCube; + uint8_t isRenderTarget; uint32_t depth; uint32_t layerCount; uint32_t levelCount; VkSampleCountFlagBits sampleCount; /* NOTE: This refers to the sample count of a render target pass using this texture, not the actual sample count of the texture */ VkFormat format; - VulkanResourceAccessType resourceAccessType; VkImageUsageFlags usageFlags; VkImageAspectFlags aspectFlags; - VulkanRenderTarget *renderTargets; /* NULL if usage is not color target or depth target, or if this texture is itself an MSAA texture */ - - SDL_atomic_t referenceCount; + uint32_t sliceCount; + VulkanTextureSlice *slices; VulkanTextureHandle *handle; @@ -1482,9 +1491,9 @@ typedef struct VulkanCommandBuffer uint32_t fragmentUniformOffset; uint32_t computeUniformOffset; - VulkanTexture *renderPassColorTargetTextures[MAX_COLOR_TARGET_BINDINGS]; - uint32_t renderPassColorTargetCount; - VulkanTexture *renderPassDepthTexture; /* can be NULL */ + VulkanTextureSlice *renderPassColorTargetTextureSlices[MAX_COLOR_TARGET_BINDINGS]; + uint32_t renderPassColorTargetTextureSliceCount; + VulkanTextureSlice *renderPassDepthTextureSlice; /* can be NULL */ VkDescriptorSet vertexSamplerDescriptorSet; /* updated by BindVertexSamplers */ VkDescriptorSet fragmentSamplerDescriptorSet; /* updated by BindFragmentSamplers */ @@ -1502,9 +1511,9 @@ typedef struct VulkanCommandBuffer uint32_t boundComputeBufferCount; uint32_t boundComputeBufferCapacity; - VulkanTexture **boundComputeTextures; - uint32_t boundComputeTextureCount; - uint32_t boundComputeTextureCapacity; + VulkanTextureSlice **boundComputeTextureSlices; + uint32_t boundComputeTextureSliceCount; + uint32_t boundComputeTextureSliceCapacity; /* Keep track of copy resources for memory barriers */ @@ -1512,9 +1521,9 @@ typedef struct VulkanCommandBuffer uint32_t copiedGpuBufferCount; uint32_t copiedGpuBufferCapacity; - VulkanTexture **copiedTextures; - uint32_t copiedTextureCount; - uint32_t copiedTextureCapacity; + VulkanTextureSlice **copiedTextureSlices; + uint32_t copiedTextureSliceCount; + uint32_t copiedTextureSliceCapacity; /* Viewport/scissor state */ @@ -1527,9 +1536,9 @@ typedef struct VulkanCommandBuffer uint32_t usedBufferCount; uint32_t usedBufferCapacity; - VulkanTexture **usedTextures; - uint32_t usedTextureCount; - uint32_t usedTextureCapacity; + VulkanTextureSlice **usedTextureSlices; + uint32_t usedTextureSliceCount; + uint32_t usedTextureSliceCapacity; VulkanSampler **usedSamplers; uint32_t usedSamplerCount; @@ -1754,16 +1763,7 @@ static void VULKAN_INTERNAL_BeginCommandBuffer(VulkanRenderer *renderer, VulkanC static void VULKAN_UnclaimWindow(Refresh_Renderer *driverData, void *windowHandle); static void VULKAN_Wait(Refresh_Renderer *driverData); static void VULKAN_Submit(Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer); -static void VULKAN_INTERNAL_CreateRenderTarget( - VulkanRenderer *renderer, - VulkanTexture *texture, - uint32_t depth, - uint32_t layer, - uint32_t level, - VkSampleCountFlagBits sampleCount, - VulkanRenderTarget *renderTarget -); -static void VULKAN_INTERNAL_DestroyRenderTarget(VulkanRenderer *renderer, VulkanRenderTarget *renderTarget); +static VulkanTextureSlice* VULKAN_INTERNAL_FetchTextureSlice(VulkanTexture* texture, uint32_t layer, uint32_t level); /* Error Handling */ @@ -2846,6 +2846,7 @@ static uint8_t VULKAN_INTERNAL_BindResourceMemory( static uint8_t VULKAN_INTERNAL_BindMemoryForImage( VulkanRenderer* renderer, VkImage image, + uint8_t dedicated, VulkanMemoryUsedRegion** usedRegion ) { uint8_t bindResult = 0; @@ -2871,7 +2872,7 @@ static uint8_t VULKAN_INTERNAL_BindMemoryForImage( renderer, memoryTypeIndex, &memoryRequirements, - 0, + dedicated, memoryRequirements.memoryRequirements.size, VK_NULL_HANDLE, image, @@ -3126,14 +3127,7 @@ static void VULKAN_INTERNAL_ImageMemoryBarrier( VulkanRenderer *renderer, VkCommandBuffer commandBuffer, VulkanResourceAccessType nextAccess, - VkImageAspectFlags aspectMask, - uint32_t baseLayer, - uint32_t layerCount, - uint32_t baseLevel, - uint32_t levelCount, - uint8_t discardContents, - VkImage image, - VulkanResourceAccessType *resourceAccessType + VulkanTextureSlice *textureSlice ) { VkPipelineStageFlags srcStages = 0; VkPipelineStageFlags dstStages = 0; @@ -3149,14 +3143,14 @@ static void VULKAN_INTERNAL_ImageMemoryBarrier( memoryBarrier.newLayout = VK_IMAGE_LAYOUT_UNDEFINED; memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - memoryBarrier.image = image; - memoryBarrier.subresourceRange.aspectMask = aspectMask; - memoryBarrier.subresourceRange.baseArrayLayer = baseLayer; - memoryBarrier.subresourceRange.layerCount = layerCount; - memoryBarrier.subresourceRange.baseMipLevel = baseLevel; - memoryBarrier.subresourceRange.levelCount = levelCount; + memoryBarrier.image = textureSlice->parent->image; + memoryBarrier.subresourceRange.aspectMask = textureSlice->parent->aspectFlags; + memoryBarrier.subresourceRange.baseArrayLayer = textureSlice->layer; + memoryBarrier.subresourceRange.layerCount = 1; + memoryBarrier.subresourceRange.baseMipLevel = textureSlice->level; + memoryBarrier.subresourceRange.levelCount = 1; - prevAccess = *resourceAccessType; + prevAccess = textureSlice->resourceAccessType; pPrevAccessInfo = &AccessMap[prevAccess]; srcStages |= pPrevAccessInfo->stageMask; @@ -3166,14 +3160,7 @@ static void VULKAN_INTERNAL_ImageMemoryBarrier( memoryBarrier.srcAccessMask |= pPrevAccessInfo->accessMask; } - if (discardContents) - { - memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - } - else - { - memoryBarrier.oldLayout = pPrevAccessInfo->imageLayout; - } + memoryBarrier.oldLayout = pPrevAccessInfo->imageLayout; pNextAccessInfo = &AccessMap[nextAccess]; @@ -3204,7 +3191,40 @@ static void VULKAN_INTERNAL_ImageMemoryBarrier( &memoryBarrier ); - *resourceAccessType = nextAccess; + textureSlice->resourceAccessType = nextAccess; +} + +static void VULKAN_INTERNAL_ImageMemoryMultiBarrier( + VulkanRenderer *renderer, + VkCommandBuffer commandBuffer, + VulkanResourceAccessType nextAccess, + VulkanTexture *texture, + uint32_t baseLayer, + uint32_t layerCount, + uint32_t baseLevel, + uint32_t levelCount +) { + VulkanTextureSlice *textureSlice; + uint32_t i, j; + + for (i = baseLayer; i < baseLayer + layerCount; i += 1) + { + for (j = baseLevel; j < baseLevel + levelCount; j += 1) + { + textureSlice = VULKAN_INTERNAL_FetchTextureSlice( + texture, + i, + j + ); + + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + commandBuffer, + nextAccess, + textureSlice + ); + } + } } /* Resource tracking */ @@ -3268,17 +3288,17 @@ static void VULKAN_INTERNAL_TrackBuffer( ) } -static void VULKAN_INTERNAL_TrackTexture( +static void VULKAN_INTERNAL_TrackTextureSlice( VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer, - VulkanTexture *texture + VulkanTextureSlice *textureSlice ) { TRACK_RESOURCE( - texture, - VulkanTexture*, - usedTextures, - usedTextureCount, - usedTextureCapacity + textureSlice, + VulkanTextureSlice*, + usedTextureSlices, + usedTextureSliceCount, + usedTextureSliceCapacity ) } @@ -3352,32 +3372,32 @@ static void VULKAN_INTERNAL_TrackComputeBuffer( ); } -static void VULKAN_INTERNAL_TrackComputeTexture( +static void VULKAN_INTERNAL_TrackComputeTextureSlice( VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer, - VulkanTexture *computeTexture + VulkanTextureSlice *textureSlice ) { ADD_TO_ARRAY_UNIQUE( - computeTexture, - VulkanTexture*, - boundComputeTextures, - boundComputeTextureCount, - boundComputeTextureCapacity + textureSlice, + VulkanTextureSlice*, + boundComputeTextureSlices, + boundComputeTextureSliceCount, + boundComputeTextureSliceCapacity ); } /* For tracking Textures used in a copy pass. */ -static void VULKAN_INTERNAL_TrackCopiedTexture( +static void VULKAN_INTERNAL_TrackCopiedTextureSlice( VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer, - VulkanTexture *texture + VulkanTextureSlice *textureSlice ) { ADD_TO_ARRAY_UNIQUE( - texture, - VulkanTexture*, - copiedTextures, - copiedTextureCount, - copiedTextureCapacity + textureSlice, + VulkanTextureSlice*, + copiedTextureSlices, + copiedTextureSliceCount, + copiedTextureSliceCapacity ); } @@ -3475,31 +3495,36 @@ static void VULKAN_INTERNAL_DestroyTexture( VulkanRenderer* renderer, VulkanTexture* texture ) { - uint32_t i, j, k, rtIndex; + uint32_t sliceIndex; - if (texture->renderTargets != NULL) + /* Clean up slices */ + for (sliceIndex = 0; sliceIndex < texture->sliceCount; sliceIndex += 1) { - rtIndex = 0; - - for (i = 0; i < texture->depth; i += 1) + if (texture->isRenderTarget) { - for (j = 0; j < texture->layerCount; j += 1) - { - for (k = 0; k < texture->levelCount; k += 1) - { - VULKAN_INTERNAL_DestroyRenderTarget( - renderer, - &texture->renderTargets[rtIndex] - ); + VULKAN_INTERNAL_RemoveFramebuffersContainingView( + renderer, + texture->slices[sliceIndex].view + ); - rtIndex += 1; - } + if (texture->slices[sliceIndex].msaaTex != NULL) + { + VULKAN_INTERNAL_DestroyTexture( + renderer, + texture->slices[sliceIndex].msaaTex + ); } } - SDL_free(texture->renderTargets); + renderer->vkDestroyImageView( + renderer->logicalDevice, + texture->slices[sliceIndex].view, + NULL + ); } + SDL_free(texture->slices); + renderer->vkDestroyImageView( renderer->logicalDevice, texture->view, @@ -3520,30 +3545,6 @@ static void VULKAN_INTERNAL_DestroyTexture( SDL_free(texture); } -static void VULKAN_INTERNAL_DestroyRenderTarget( - VulkanRenderer *renderer, - VulkanRenderTarget *renderTarget -) { - VULKAN_INTERNAL_RemoveFramebuffersContainingView( - renderer, - renderTarget->view - ); - - renderer->vkDestroyImageView( - renderer->logicalDevice, - renderTarget->view, - NULL - ); - - if (renderTarget->msaaTex != NULL) - { - VULKAN_INTERNAL_DestroyTexture( - renderer, - renderTarget->msaaTex - ); - } -} - static void VULKAN_INTERNAL_DestroyBuffer( VulkanRenderer* renderer, VulkanBuffer* buffer @@ -3584,11 +3585,11 @@ static void VULKAN_INTERNAL_DestroyCommandPool( SDL_free(commandBuffer->signalSemaphores); SDL_free(commandBuffer->boundDescriptorSetDatas); SDL_free(commandBuffer->boundComputeBuffers); - SDL_free(commandBuffer->boundComputeTextures); + SDL_free(commandBuffer->boundComputeTextureSlices); SDL_free(commandBuffer->copiedGpuBuffers); - SDL_free(commandBuffer->copiedTextures); + SDL_free(commandBuffer->copiedTextureSlices); SDL_free(commandBuffer->usedBuffers); - SDL_free(commandBuffer->usedTextures); + SDL_free(commandBuffer->usedTextureSlices); SDL_free(commandBuffer->usedSamplers); SDL_free(commandBuffer->usedGraphicsPipelines); SDL_free(commandBuffer->usedComputePipelines); @@ -3679,12 +3680,13 @@ static void VULKAN_INTERNAL_DestroySwapchain( for (i = 0; i < swapchainData->imageCount; i += 1) { - VULKAN_INTERNAL_DestroyRenderTarget( - renderer, - &swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->renderTargets[0] + renderer->vkDestroyImageView( + renderer->logicalDevice, + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->slices[0].view, + NULL ); - SDL_free(swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->renderTargets); + SDL_free(swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->slices); renderer->vkDestroyImageView( renderer->logicalDevice, @@ -4339,6 +4341,98 @@ static void VULKAN_INTERNAL_DestroyUniformBufferObject( SDL_free(uniformBufferObject); } +/* Texture Slice Utilities */ + +static uint32_t VULKAN_INTERNAL_GetTextureSliceIndex( + VulkanTexture *texture, + uint32_t layer, + uint32_t level +) { + return (layer * texture->levelCount) + level; +} + +static VulkanTextureSlice* VULKAN_INTERNAL_FetchTextureSlice( + VulkanTexture *texture, + uint32_t layer, + uint32_t level +) { + return &texture->slices[ + VULKAN_INTERNAL_GetTextureSliceIndex( + texture, + layer, + level + ) + ]; +} + +static VulkanTexture* VULKAN_INTERNAL_FetchMSAATexture( + VulkanTexture *texture, + uint32_t layer, + uint32_t level +) { + return texture->slices[ + VULKAN_INTERNAL_GetTextureSliceIndex( + texture, + layer, + level + ) + ].msaaTex; +} + +static VulkanTextureSlice* VULKAN_INTERNAL_RefreshToVulkanTextureSlice( + Refresh_TextureSlice *refreshTextureSlice +) { + return VULKAN_INTERNAL_FetchTextureSlice( + ((VulkanTextureContainer*) refreshTextureSlice->texture)->activeTextureHandle->vulkanTexture, + refreshTextureSlice->layer, + refreshTextureSlice->mipLevel + ); +} + +static void VULKAN_INTERNAL_CreateSliceView( + VulkanRenderer *renderer, + VulkanTexture *texture, + uint32_t layer, + uint32_t level, + VkImageView *pView +) { + VkResult vulkanResult; + VkImageViewCreateInfo imageViewCreateInfo; + VkComponentMapping swizzle = IDENTITY_SWIZZLE; + + /* create framebuffer compatible views for RenderTarget */ + imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + imageViewCreateInfo.pNext = NULL; + imageViewCreateInfo.flags = 0; + imageViewCreateInfo.image = texture->image; + imageViewCreateInfo.format = texture->format; + imageViewCreateInfo.components = swizzle; + imageViewCreateInfo.subresourceRange.aspectMask = texture->aspectFlags; + imageViewCreateInfo.subresourceRange.baseMipLevel = level; + imageViewCreateInfo.subresourceRange.levelCount = 1; + imageViewCreateInfo.subresourceRange.baseArrayLayer = layer; + imageViewCreateInfo.subresourceRange.layerCount = 1; + imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + + vulkanResult = renderer->vkCreateImageView( + renderer->logicalDevice, + &imageViewCreateInfo, + NULL, + pView + ); + + if (vulkanResult != VK_SUCCESS) + { + LogVulkanResultAsError( + "vkCreateImageView", + vulkanResult + ); + Refresh_LogError("Failed to create color attachment image view"); + *pView = NULL; + return; + } +} + /* Swapchain */ static uint8_t VULKAN_INTERNAL_QuerySwapChainSupport( @@ -4869,8 +4963,6 @@ static uint8_t VULKAN_INTERNAL_CreateSwapchain( return 0; } - swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->resourceAccessType = RESOURCE_ACCESS_NONE; - /* Swapchain memory is managed by the driver */ swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->usedRegion = NULL; @@ -4878,6 +4970,7 @@ static uint8_t VULKAN_INTERNAL_CreateSwapchain( swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->format = swapchainData->swapchainFormat; swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->is3D = 0; swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->isCube = 0; + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->isRenderTarget = 1; swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->depth = 1; swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->layerCount = 1; swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->levelCount = 1; @@ -4886,19 +4979,23 @@ static uint8_t VULKAN_INTERNAL_CreateSwapchain( VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT; - swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->resourceAccessType = RESOURCE_ACCESS_NONE; - /* Create render target */ - swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->renderTargets = SDL_malloc(sizeof(VulkanRenderTarget)); - VULKAN_INTERNAL_CreateRenderTarget( + /* Create slice */ + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->sliceCount = 1; + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->slices = SDL_malloc(sizeof(VulkanTextureSlice)); + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->slices[0].parent = swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture; + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->slices[0].layer = 0; + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->slices[0].level = 0; + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->slices[0].resourceAccessType = RESOURCE_ACCESS_NONE; + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->slices[0].msaaTex = NULL; + VULKAN_INTERNAL_CreateSliceView( renderer, swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture, 0, 0, - 0, - VK_SAMPLE_COUNT_1_BIT, - &swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->renderTargets[0] + &swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->slices[0].view ); + SDL_AtomicSet(&swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->slices[0].referenceCount, 0); } SDL_stack_free(swapchainImages); @@ -5377,6 +5474,7 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture( uint32_t height, uint32_t depth, uint32_t isCube, + uint32_t layerCount, uint32_t levelCount, VkSampleCountFlagBits sampleCount, VkFormat format, @@ -5390,16 +5488,16 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture( VkImageViewCreateInfo imageViewCreateInfo; uint8_t bindResult; uint8_t is3D = depth > 1 ? 1 : 0; - uint8_t layerCount = isCube ? 6 : 1; uint8_t isRenderTarget = ((imageUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0) || ((imageUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0); VkComponentMapping swizzle = IDENTITY_SWIZZLE; - uint32_t i, j, k, rtIndex; + uint32_t i, j, sliceIndex; VulkanTexture *texture = SDL_malloc(sizeof(VulkanTexture)); texture->isCube = 0; texture->is3D = 0; + texture->isRenderTarget = isRenderTarget; texture->markedForDestroy = 0; if (isCube) @@ -5442,6 +5540,7 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture( bindResult = VULKAN_INTERNAL_BindMemoryForImage( renderer, texture->image, + isMsaaTexture, /* bind MSAA texture as dedicated alloc so we don't have to track it in defrag */ &texture->usedRegion ); @@ -5504,46 +5603,59 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture( texture->levelCount = levelCount; texture->layerCount = layerCount; texture->sampleCount = sampleCount; - texture->resourceAccessType = RESOURCE_ACCESS_NONE; texture->usageFlags = imageUsageFlags; texture->aspectFlags = aspectMask; - SDL_AtomicSet(&texture->referenceCount, 0); + /* Define slices */ + texture->sliceCount = + texture->layerCount * + texture->levelCount; - /* these get overwritten if render targets are created */ - texture->renderTargets = NULL; + texture->slices = SDL_malloc( + texture->sliceCount * sizeof(VulkanTextureSlice) + ); - /* Create render target structures if necessary */ - if (isRenderTarget && !isMsaaTexture) + for (i = 0; i < texture->layerCount; i += 1) { - texture->renderTargets = SDL_malloc( - texture->depth * - texture->layerCount * - texture->levelCount * - sizeof(VulkanRenderTarget) - ); - - rtIndex = 0; - - for (i = 0; i < texture->depth; i += 1) + for (j = 0; j < texture->levelCount; j += 1) { - for (j = 0; j < texture->layerCount; j += 1) - { - for (k = 0; k < texture->levelCount; k += 1) - { - /* NOTE: this will recursively create an MSAA texture if sampleCount > 1 */ - VULKAN_INTERNAL_CreateRenderTarget( - renderer, - texture, - i, - j, - k, - sampleCount, - &texture->renderTargets[rtIndex] - ); + sliceIndex = VULKAN_INTERNAL_GetTextureSliceIndex( + texture, + i, + j + ); - rtIndex += 1; - } + VULKAN_INTERNAL_CreateSliceView( + renderer, + texture, + i, + j, + &texture->slices[sliceIndex].view + ); + + texture->slices[sliceIndex].parent = texture; + texture->slices[sliceIndex].layer = i; + texture->slices[sliceIndex].level = j; + texture->slices[sliceIndex].resourceAccessType = RESOURCE_ACCESS_NONE; + texture->slices[sliceIndex].msaaTex = NULL; + SDL_AtomicSet(&texture->slices[sliceIndex].referenceCount, 0); + + if (sampleCount > VK_SAMPLE_COUNT_1_BIT && isRenderTarget && !isMsaaTexture) + { + texture->slices[sliceIndex].msaaTex = VULKAN_INTERNAL_CreateTexture( + renderer, + texture->dimensions.width, + texture->dimensions.height, + 1, + 0, + 1, + 1, + sampleCount, + texture->format, + aspectMask, + imageUsageFlags, + 1 + ); } } } @@ -5557,6 +5669,7 @@ static VulkanTextureHandle* VULKAN_INTERNAL_CreateTextureHandle( uint32_t height, uint32_t depth, uint32_t isCube, + uint32_t layerCount, uint32_t levelCount, VkSampleCountFlagBits sampleCount, VkFormat format, @@ -5573,6 +5686,7 @@ static VulkanTextureHandle* VULKAN_INTERNAL_CreateTextureHandle( height, depth, isCube, + layerCount, levelCount, sampleCount, format, @@ -5599,13 +5713,21 @@ static void VULKAN_INTERNAL_DiscardActiveTexture( VulkanTextureContainer *textureContainer ) { VulkanTextureHandle *textureHandle; - uint32_t i; + uint32_t i, j; + int32_t refCountTotal; - /* If a previously-discarded buffer is available, we can use that. */ + /* If a previously-discarded texture is available, we can use that. */ for (i = 0; i < textureContainer->textureCount; i += 1) { textureHandle = textureContainer->textureHandles[i]; - if (SDL_AtomicGet(&textureHandle->vulkanTexture->referenceCount) == 0) + + refCountTotal = 0; + for (j = 0; j < textureHandle->vulkanTexture->sliceCount; j += 1) + { + refCountTotal += SDL_AtomicGet(&textureHandle->vulkanTexture->slices[j].referenceCount); + } + + if (refCountTotal == 0) { textureContainer->activeTextureHandle = textureHandle; return; @@ -5619,6 +5741,7 @@ static void VULKAN_INTERNAL_DiscardActiveTexture( textureContainer->activeTextureHandle->vulkanTexture->dimensions.height, textureContainer->activeTextureHandle->vulkanTexture->depth, textureContainer->activeTextureHandle->vulkanTexture->isCube, + textureContainer->activeTextureHandle->vulkanTexture->layerCount, textureContainer->activeTextureHandle->vulkanTexture->levelCount, textureContainer->activeTextureHandle->vulkanTexture->sampleCount, textureContainer->activeTextureHandle->vulkanTexture->format, @@ -5641,148 +5764,6 @@ static void VULKAN_INTERNAL_DiscardActiveTexture( textureContainer->textureCount += 1; } -static void VULKAN_INTERNAL_CreateRenderTarget( - VulkanRenderer *renderer, - VulkanTexture *texture, - uint32_t depth, - uint32_t layer, - uint32_t level, - VkSampleCountFlagBits sampleCount, - VulkanRenderTarget *renderTarget -) { - VkResult vulkanResult; - VkImageViewCreateInfo imageViewCreateInfo; - VkComponentMapping swizzle = IDENTITY_SWIZZLE; - VkImageAspectFlags aspectFlags = 0; - - if (IsDepthFormat(texture->format)) - { - aspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT; - - if (IsStencilFormat(texture->format)) - { - aspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT; - } - } - else - { - aspectFlags |= VK_IMAGE_ASPECT_COLOR_BIT; - } - - /* create framebuffer compatible views for RenderTarget */ - imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - imageViewCreateInfo.pNext = NULL; - imageViewCreateInfo.flags = 0; - imageViewCreateInfo.image = texture->image; - imageViewCreateInfo.format = texture->format; - imageViewCreateInfo.components = swizzle; - imageViewCreateInfo.subresourceRange.aspectMask = aspectFlags; - imageViewCreateInfo.subresourceRange.baseMipLevel = level; - imageViewCreateInfo.subresourceRange.levelCount = 1; - imageViewCreateInfo.subresourceRange.baseArrayLayer = 0; - if (texture->is3D) - { - imageViewCreateInfo.subresourceRange.baseArrayLayer = depth; - } - else if (texture->isCube) - { - imageViewCreateInfo.subresourceRange.baseArrayLayer = layer; - } - imageViewCreateInfo.subresourceRange.layerCount = 1; - imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - - vulkanResult = renderer->vkCreateImageView( - renderer->logicalDevice, - &imageViewCreateInfo, - NULL, - &renderTarget->view - ); - - if (vulkanResult != VK_SUCCESS) - { - LogVulkanResultAsError( - "vkCreateImageView", - vulkanResult - ); - Refresh_LogError("Failed to create color attachment image view"); - return; - } - - if (sampleCount > VK_SAMPLE_COUNT_1_BIT) - { - /* Create MSAA texture */ - renderTarget->msaaTex = VULKAN_INTERNAL_CreateTexture( - renderer, - texture->dimensions.width, - texture->dimensions.height, - 1, - 0, - 1, - sampleCount, - texture->format, - texture->aspectFlags, - texture->usageFlags, - 1 - ); - - if (renderTarget->msaaTex == NULL) - { - Refresh_LogError("Failed to create MSAA render texture!"); - return; - } - } - else - { - renderTarget->msaaTex = NULL; - } -} - -static uint32_t VULKAN_INTERNAL_GetRenderTargetIndex( - VulkanTexture *texture, - uint32_t depth, - uint32_t layer, - uint32_t level -) { - return - (level * texture->depth * texture->layerCount) + - (layer * texture->depth) + - depth; -} - -static VulkanRenderTarget* VULKAN_INTERNAL_FetchRenderTarget( - VulkanRenderer *renderer, - VulkanTexture *texture, - uint32_t depth, - uint32_t layer, - uint32_t level -) { - return &texture->renderTargets[ - VULKAN_INTERNAL_GetRenderTargetIndex( - texture, - depth, - layer, - level - ) - ]; -} - -static VulkanTexture* VULKAN_INTERNAL_FetchRenderTargetMSAATexture( - VulkanRenderer *renderer, - VulkanTexture *texture, - uint32_t depth, - uint32_t layer, - uint32_t level -) { - return texture->renderTargets[ - VULKAN_INTERNAL_GetRenderTargetIndex( - texture, - depth, - layer, - level - ) - ].msaaTex; -} - static VkRenderPass VULKAN_INTERNAL_CreateRenderPass( VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer, @@ -6857,6 +6838,7 @@ static Refresh_Texture* VULKAN_CreateTexture( textureCreateInfo->height, textureCreateInfo->depth, textureCreateInfo->isCube, + textureCreateInfo->layerCount, textureCreateInfo->levelCount, RefreshToVK_SampleCount[textureCreateInfo->sampleCount], format, @@ -7198,7 +7180,7 @@ static void VULKAN_BindVertexSamplers( VulkanTexture *currentTexture; VulkanSampler *currentSampler; - uint32_t i, samplerCount; + uint32_t i, samplerCount, sliceIndex; VkDescriptorImageInfo descriptorImageInfos[MAX_TEXTURE_SAMPLERS]; if (graphicsPipeline->pipelineLayout->vertexSamplerDescriptorSetCache == NULL) @@ -7216,8 +7198,11 @@ static void VULKAN_BindVertexSamplers( descriptorImageInfos[i].sampler = currentSampler->sampler; descriptorImageInfos[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, currentTexture); VULKAN_INTERNAL_TrackSampler(renderer, vulkanCommandBuffer, currentSampler); + for (sliceIndex = 0; sliceIndex < currentTexture->sliceCount; sliceIndex += 1) + { + VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, ¤tTexture->slices[sliceIndex]); + } } vulkanCommandBuffer->vertexSamplerDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet( @@ -7241,7 +7226,7 @@ static void VULKAN_BindFragmentSamplers( VulkanTexture *currentTexture; VulkanSampler *currentSampler; - uint32_t i, samplerCount; + uint32_t i, samplerCount, sliceIndex; VkDescriptorImageInfo descriptorImageInfos[MAX_TEXTURE_SAMPLERS]; if (graphicsPipeline->pipelineLayout->fragmentSamplerDescriptorSetCache == NULL) @@ -7259,8 +7244,11 @@ static void VULKAN_BindFragmentSamplers( descriptorImageInfos[i].sampler = currentSampler->sampler; descriptorImageInfos[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, currentTexture); VULKAN_INTERNAL_TrackSampler(renderer, vulkanCommandBuffer, currentSampler); + for (sliceIndex = 0; sliceIndex < currentTexture->sliceCount; sliceIndex += 1) + { + VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, ¤tTexture->slices[sliceIndex]); + } } vulkanCommandBuffer->fragmentSamplerDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet( @@ -7580,7 +7568,7 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( VkImageView imageViewAttachments[2 * MAX_COLOR_TARGET_BINDINGS + 1]; FramebufferHash hash; VulkanTexture *texture; - VulkanRenderTarget *renderTarget; + VulkanTextureSlice *textureSlice; uint32_t attachmentCount = 0; uint32_t i; @@ -7595,22 +7583,17 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( for (i = 0; i < colorAttachmentCount; i += 1) { texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->activeTextureHandle->vulkanTexture; - - renderTarget = VULKAN_INTERNAL_FetchRenderTarget( - renderer, + textureSlice = VULKAN_INTERNAL_FetchTextureSlice( texture, - colorAttachmentInfos[i].depth, colorAttachmentInfos[i].layer, colorAttachmentInfos[i].level ); - hash.colorAttachmentViews[i] = ( - renderTarget->view - ); + hash.colorAttachmentViews[i] = textureSlice->view; - if (renderTarget->msaaTex != NULL) + if (textureSlice->msaaTex != NULL) { - hash.colorMultiSampleAttachmentViews[i] = renderTarget->msaaTex->view; + hash.colorMultiSampleAttachmentViews[i] = textureSlice->msaaTex->view; } } @@ -7621,14 +7604,12 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( else { texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture; - renderTarget = VULKAN_INTERNAL_FetchRenderTarget( - renderer, + textureSlice = VULKAN_INTERNAL_FetchTextureSlice( texture, - depthStencilAttachmentInfo->depth, depthStencilAttachmentInfo->layer, depthStencilAttachmentInfo->level ); - hash.depthStencilAttachmentView = renderTarget->view; + hash.depthStencilAttachmentView = textureSlice->view; } hash.width = width; @@ -7657,24 +7638,21 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( for (i = 0; i < colorAttachmentCount; i += 1) { texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->activeTextureHandle->vulkanTexture; - - renderTarget = VULKAN_INTERNAL_FetchRenderTarget( - renderer, + textureSlice = VULKAN_INTERNAL_FetchTextureSlice( texture, - colorAttachmentInfos[i].depth, colorAttachmentInfos[i].layer, colorAttachmentInfos[i].level ); imageViewAttachments[attachmentCount] = - renderTarget->view; + textureSlice->view; attachmentCount += 1; - if (renderTarget->msaaTex != NULL) + if (textureSlice->msaaTex != NULL) { imageViewAttachments[attachmentCount] = - renderTarget->msaaTex->view; + textureSlice->msaaTex->view; attachmentCount += 1; } @@ -7683,15 +7661,14 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( if (depthStencilAttachmentInfo != NULL) { texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture; - renderTarget = VULKAN_INTERNAL_FetchRenderTarget( - renderer, + textureSlice = VULKAN_INTERNAL_FetchTextureSlice( texture, - depthStencilAttachmentInfo->depth, depthStencilAttachmentInfo->layer, depthStencilAttachmentInfo->level ); - imageViewAttachments[attachmentCount] = renderTarget->view; + imageViewAttachments[attachmentCount] = + textureSlice->view; attachmentCount += 1; } @@ -7814,6 +7791,7 @@ static void VULKAN_BeginRenderPass( VulkanFramebuffer *framebuffer; VulkanTextureContainer *textureContainer; + VulkanTextureSlice *textureSlice; VulkanTexture *texture; VulkanTexture *msaaTexture = NULL; uint32_t w, h; @@ -7831,12 +7809,17 @@ static void VULKAN_BeginRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { textureContainer = (VulkanTextureContainer*) colorAttachmentInfos[i].texture; + textureSlice = VULKAN_INTERNAL_FetchTextureSlice( + textureContainer->activeTextureHandle->vulkanTexture, + colorAttachmentInfos[i].layer, + colorAttachmentInfos[i].level + ); if ( colorAttachmentInfos[i].safeDiscard && colorAttachmentInfos[i].loadOp != REFRESH_LOADOP_LOAD && textureContainer->canBeDiscarded && - SDL_AtomicGet(&textureContainer->activeTextureHandle->vulkanTexture->referenceCount) > 0 + SDL_AtomicGet(&textureSlice->referenceCount) > 0 ) { VULKAN_INTERNAL_DiscardActiveTexture( renderer, @@ -7845,6 +7828,11 @@ static void VULKAN_BeginRenderPass( } texture = textureContainer->activeTextureHandle->vulkanTexture; + textureSlice = VULKAN_INTERNAL_FetchTextureSlice( + texture, + colorAttachmentInfos[i].layer, + colorAttachmentInfos[i].level + ); w = texture->dimensions.width >> colorAttachmentInfos[i].level; h = texture->dimensions.height >> colorAttachmentInfos[i].level; @@ -7861,7 +7849,7 @@ static void VULKAN_BeginRenderPass( framebufferHeight = h; } - if (texture->renderTargets == NULL) + if (!textureSlice->parent->isRenderTarget) { Refresh_LogError("Color attachment texture was not designated as a target!"); return; @@ -7871,13 +7859,18 @@ static void VULKAN_BeginRenderPass( if (depthStencilAttachmentInfo != NULL) { textureContainer = (VulkanTextureContainer*) depthStencilAttachmentInfo->texture; + textureSlice = VULKAN_INTERNAL_FetchTextureSlice( + textureContainer->activeTextureHandle->vulkanTexture, + depthStencilAttachmentInfo->layer, + depthStencilAttachmentInfo->level + ); if ( depthStencilAttachmentInfo->safeDiscard && depthStencilAttachmentInfo->loadOp != REFRESH_LOADOP_LOAD && depthStencilAttachmentInfo->stencilLoadOp != REFRESH_LOADOP_LOAD && textureContainer->canBeDiscarded && - SDL_AtomicGet(&textureContainer->activeTextureHandle->vulkanTexture->referenceCount) > 0 + SDL_AtomicGet(&textureSlice->referenceCount) > 0 ) { VULKAN_INTERNAL_DiscardActiveTexture( renderer, @@ -7886,6 +7879,11 @@ static void VULKAN_BeginRenderPass( } texture = textureContainer->activeTextureHandle->vulkanTexture; + textureSlice = VULKAN_INTERNAL_FetchTextureSlice( + texture, + depthStencilAttachmentInfo->layer, + depthStencilAttachmentInfo->level + ); w = texture->dimensions.width >> depthStencilAttachmentInfo->level; h = texture->dimensions.height >> depthStencilAttachmentInfo->level; @@ -7902,7 +7900,7 @@ static void VULKAN_BeginRenderPass( framebufferHeight = h; } - if (texture->renderTargets == NULL) + if (!textureSlice->parent->isRenderTarget) { Refresh_LogError("Depth stencil attachment texture was not designated as a target!"); return; @@ -7936,28 +7934,26 @@ static void VULKAN_BeginRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->activeTextureHandle->vulkanTexture; + textureSlice = VULKAN_INTERNAL_FetchTextureSlice( + texture, + colorAttachmentInfos[i].layer, + colorAttachmentInfos[i].level + ); + + vulkanCommandBuffer->renderPassColorTargetTextureSlices[i] = textureSlice; /* Transition the attachment */ VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_COLOR_ATTACHMENT_READ_WRITE, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - texture->layerCount, - 0, - texture->levelCount, - 0, - texture->image, - &texture->resourceAccessType + textureSlice ); if (texture->sampleCount > VK_SAMPLE_COUNT_1_BIT) { - msaaTexture = VULKAN_INTERNAL_FetchRenderTargetMSAATexture( - renderer, + msaaTexture = VULKAN_INTERNAL_FetchMSAATexture( texture, - colorAttachmentInfos[i].depth, colorAttachmentInfos[i].layer, colorAttachmentInfos[i].level ); @@ -7967,27 +7963,31 @@ static void VULKAN_BeginRenderPass( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_COLOR_ATTACHMENT_WRITE, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - msaaTexture->layerCount, - 0, - msaaTexture->levelCount, - 0, - msaaTexture->image, - &msaaTexture->resourceAccessType + &msaaTexture->slices[0] ); clearCount += 1; multisampleAttachmentCount += 1; } - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, texture); + VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, textureSlice); /* TODO: do we need to track the msaa texture? or is it implicitly only used when the regular texture is used? */ } + vulkanCommandBuffer->renderPassColorTargetTextureSliceCount = colorAttachmentCount; + + vulkanCommandBuffer->renderPassDepthTextureSlice = NULL; if (depthStencilAttachmentInfo != NULL) { texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture; + textureSlice = VULKAN_INTERNAL_FetchTextureSlice( + texture, + depthStencilAttachmentInfo->layer, + depthStencilAttachmentInfo->level + ); + + vulkanCommandBuffer->renderPassDepthTextureSlice = textureSlice; + depthAspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT; if (IsStencilFormat(texture->format)) @@ -7999,19 +7999,12 @@ static void VULKAN_BeginRenderPass( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_WRITE, - depthAspectFlags, - 0, - texture->layerCount, - 0, - texture->levelCount, - 0, - texture->image, - &texture->resourceAccessType + textureSlice ); clearCount += 1; - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, texture); + VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, textureSlice); } /* Set clear values */ @@ -8066,17 +8059,6 @@ static void VULKAN_BeginRenderPass( SDL_stack_free(clearValues); - for (i = 0; i < colorAttachmentCount; i += 1) - { - vulkanCommandBuffer->renderPassColorTargetTextures[i] = - ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->activeTextureHandle->vulkanTexture; - } - vulkanCommandBuffer->renderPassColorTargetCount = colorAttachmentCount; - - if (depthStencilAttachmentInfo != NULL) - { - vulkanCommandBuffer->renderPassDepthTexture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture; } - /* Set sensible default viewport state */ defaultViewport.x = 0; @@ -8108,7 +8090,7 @@ static void VULKAN_EndRenderPass( ) { VulkanRenderer* renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTexture *currentTexture; + VulkanTextureSlice *currentTextureSlice; uint32_t i; renderer->vkCmdEndRenderPass( @@ -8116,67 +8098,46 @@ static void VULKAN_EndRenderPass( ); /* If the render targets can be sampled, transition them to sample layout */ - for (i = 0; i < vulkanCommandBuffer->renderPassColorTargetCount; i += 1) + for (i = 0; i < vulkanCommandBuffer->renderPassColorTargetTextureSliceCount; i += 1) { - currentTexture = vulkanCommandBuffer->renderPassColorTargetTextures[i]; + currentTextureSlice = vulkanCommandBuffer->renderPassColorTargetTextureSlices[i]; - if (currentTexture->usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) + if (currentTextureSlice->parent->usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) { VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_ANY_SHADER_READ_SAMPLED_IMAGE, - currentTexture->aspectFlags, - 0, - currentTexture->layerCount, - 0, - currentTexture->levelCount, - 0, - currentTexture->image, - ¤tTexture->resourceAccessType + currentTextureSlice ); } - else if (currentTexture->usageFlags & VK_IMAGE_USAGE_STORAGE_BIT) + else if (currentTextureSlice->parent->usageFlags & VK_IMAGE_USAGE_STORAGE_BIT) { VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_COMPUTE_SHADER_STORAGE_IMAGE_READ_WRITE, - currentTexture->aspectFlags, - 0, - currentTexture->layerCount, - 0, - currentTexture->levelCount, - 0, - currentTexture->image, - ¤tTexture->resourceAccessType + currentTextureSlice ); } } - vulkanCommandBuffer->renderPassColorTargetCount = 0; + vulkanCommandBuffer->renderPassColorTargetTextureSliceCount = 0; - if (vulkanCommandBuffer->renderPassDepthTexture != NULL) + if (vulkanCommandBuffer->renderPassDepthTextureSlice != NULL) { - currentTexture = vulkanCommandBuffer->renderPassDepthTexture; + currentTextureSlice = vulkanCommandBuffer->renderPassDepthTextureSlice; - if (currentTexture->usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) + if (currentTextureSlice->parent->usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) { VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_ANY_SHADER_READ_SAMPLED_IMAGE, - currentTexture->aspectFlags, - 0, - currentTexture->layerCount, - 0, - currentTexture->levelCount, - 0, - currentTexture->image, - ¤tTexture->resourceAccessType + currentTextureSlice ); } } - vulkanCommandBuffer->renderPassDepthTexture = NULL; + vulkanCommandBuffer->renderPassDepthTextureSlice = NULL; vulkanCommandBuffer->currentGraphicsPipeline = NULL; } @@ -8286,7 +8247,7 @@ static void VULKAN_BeginComputePass( VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; vulkanCommandBuffer->boundComputeBufferCount = 0; - vulkanCommandBuffer->boundComputeTextureCount = 0; + vulkanCommandBuffer->boundComputeTextureSliceCount = 0; } static void VULKAN_BindComputePipeline( @@ -8370,14 +8331,13 @@ static void VULKAN_BindComputeBuffers( static void VULKAN_BindComputeTextures( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_Texture **pTextures, - uint32_t **pLevels + Refresh_TextureSlice **pTextureSlices ) { VulkanRenderer* renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanComputePipeline *computePipeline = vulkanCommandBuffer->currentComputePipeline; - VulkanTexture *currentTexture; + VulkanTextureSlice *currentTextureSlice; VkDescriptorImageInfo descriptorImageInfos[MAX_TEXTURE_SAMPLERS]; uint32_t i; @@ -8388,8 +8348,8 @@ static void VULKAN_BindComputeTextures( for (i = 0; i < computePipeline->pipelineLayout->imageDescriptorSetCache->bindingCount; i += 1) { - currentTexture = ((VulkanTextureContainer*) pTextures[i])->activeTextureHandle->vulkanTexture; - descriptorImageInfos[i].imageView = currentTexture->view; + currentTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(pTextureSlices[i]); + descriptorImageInfos[i].imageView = currentTextureSlice->view; descriptorImageInfos[i].sampler = VK_NULL_HANDLE; descriptorImageInfos[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; @@ -8397,18 +8357,11 @@ static void VULKAN_BindComputeTextures( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_COMPUTE_SHADER_STORAGE_IMAGE_READ_WRITE, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - currentTexture->layerCount, - 0, - currentTexture->levelCount, - 0, - currentTexture->image, - ¤tTexture->resourceAccessType + currentTextureSlice ); - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, currentTexture); - VULKAN_INTERNAL_TrackComputeTexture(renderer, vulkanCommandBuffer, currentTexture); + VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, currentTextureSlice); + VULKAN_INTERNAL_TrackComputeTextureSlice(renderer, vulkanCommandBuffer, currentTextureSlice); } vulkanCommandBuffer->imageDescriptorSet = @@ -8463,7 +8416,7 @@ static void VULKAN_EndComputePass( VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanBuffer *currentComputeBuffer; - VulkanTexture *currentComputeTexture; + VulkanTextureSlice *currentComputeTextureSlice; VulkanResourceAccessType resourceAccessType = RESOURCE_ACCESS_NONE; uint32_t i; @@ -8497,26 +8450,17 @@ static void VULKAN_EndComputePass( } /* Re-transition sampler images */ - for (i = 0; i < vulkanCommandBuffer->boundComputeTextureCount; i += 1) + for (i = 0; i < vulkanCommandBuffer->boundComputeTextureSliceCount; i += 1) { - currentComputeTexture = vulkanCommandBuffer->boundComputeTextures[i]; + currentComputeTextureSlice = vulkanCommandBuffer->boundComputeTextureSlices[i]; - if (currentComputeTexture->usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) + if (currentComputeTextureSlice->parent->usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) { - resourceAccessType = RESOURCE_ACCESS_ANY_SHADER_READ_SAMPLED_IMAGE; - VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, - resourceAccessType, - currentComputeTexture->aspectFlags, - 0, - currentComputeTexture->layerCount, - 0, - currentComputeTexture->levelCount, - 0, - currentComputeTexture->image, - ¤tComputeTexture->resourceAccessType + RESOURCE_ACCESS_ANY_SHADER_READ_SAMPLED_IMAGE, + currentComputeTextureSlice ); } } @@ -8629,7 +8573,7 @@ static void VULKAN_BeginCopyPass( VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; vulkanCommandBuffer->copiedGpuBufferCount = 0; - vulkanCommandBuffer->copiedTextureCount = 0; + vulkanCommandBuffer->copiedTextureSliceCount = 0; } static void VULKAN_UploadToTexture( @@ -8644,17 +8588,22 @@ static void VULKAN_UploadToTexture( VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; VulkanTextureContainer *vulkanTextureContainer = (VulkanTextureContainer*) textureSlice->texture; + VulkanTextureSlice *vulkanTextureSlice; VkBufferImageCopy imageCopy; + vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(textureSlice); + if ( option == REFRESH_COPYOPTIONS_SAFEDISCARD && vulkanTextureContainer->canBeDiscarded && - SDL_AtomicGet(&vulkanTextureContainer->activeTextureHandle->vulkanTexture->referenceCount) > 0 + SDL_AtomicGet(&vulkanTextureSlice->referenceCount) > 0 ) { VULKAN_INTERNAL_DiscardActiveTexture( renderer, vulkanTextureContainer ); + + vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(textureSlice); } VULKAN_INTERNAL_BufferMemoryBarrier( @@ -8668,14 +8617,7 @@ static void VULKAN_UploadToTexture( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_WRITE, - vulkanTextureContainer->activeTextureHandle->vulkanTexture->aspectFlags, - 0, - vulkanTextureContainer->activeTextureHandle->vulkanTexture->layerCount, - 0, - vulkanTextureContainer->activeTextureHandle->vulkanTexture->levelCount, - 0, - vulkanTextureContainer->activeTextureHandle->vulkanTexture->image, - &vulkanTextureContainer->activeTextureHandle->vulkanTexture->resourceAccessType + vulkanTextureSlice ); imageCopy.imageExtent.width = textureSlice->w; @@ -8684,9 +8626,9 @@ static void VULKAN_UploadToTexture( imageCopy.imageOffset.x = textureSlice->x; imageCopy.imageOffset.y = textureSlice->y; imageCopy.imageOffset.z = textureSlice->z; - imageCopy.imageSubresource.aspectMask = vulkanTextureContainer->activeTextureHandle->vulkanTexture->aspectFlags; - imageCopy.imageSubresource.baseArrayLayer = textureSlice->baseLayer; - imageCopy.imageSubresource.layerCount = textureSlice->layerCount; + imageCopy.imageSubresource.aspectMask = vulkanTextureSlice->parent->aspectFlags; + imageCopy.imageSubresource.baseArrayLayer = textureSlice->layer; + imageCopy.imageSubresource.layerCount = 1; imageCopy.imageSubresource.mipLevel = textureSlice->mipLevel; imageCopy.bufferOffset = copyParams->bufferOffset; imageCopy.bufferRowLength = copyParams->bufferStride; @@ -8695,15 +8637,15 @@ static void VULKAN_UploadToTexture( renderer->vkCmdCopyBufferToImage( vulkanCommandBuffer->commandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer, - vulkanTextureContainer->activeTextureHandle->vulkanTexture->image, - AccessMap[vulkanTextureContainer->activeTextureHandle->vulkanTexture->resourceAccessType].imageLayout, + vulkanTextureSlice->parent->image, + AccessMap[vulkanTextureSlice->resourceAccessType].imageLayout, 1, &imageCopy ); VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer); - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTextureContainer->activeTextureHandle->vulkanTexture); - VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, vulkanTextureContainer->activeTextureHandle->vulkanTexture); + VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice); + VULKAN_INTERNAL_TrackCopiedTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice); } static void VULKAN_UploadToBuffer( @@ -8771,10 +8713,12 @@ static void VULKAN_DownloadFromTexture( ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTextureContainer *vulkanTextureContainer = (VulkanTextureContainer*) textureSlice->texture; + VulkanTextureSlice *vulkanTextureSlice; VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; VkBufferImageCopy imageCopy; + vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(textureSlice); + if ( option == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 @@ -8796,14 +8740,7 @@ static void VULKAN_DownloadFromTexture( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_READ, - vulkanTextureContainer->activeTextureHandle->vulkanTexture->aspectFlags, - 0, - vulkanTextureContainer->activeTextureHandle->vulkanTexture->layerCount, - 0, - vulkanTextureContainer->activeTextureHandle->vulkanTexture->levelCount, - 0, - vulkanTextureContainer->activeTextureHandle->vulkanTexture->image, - &vulkanTextureContainer->activeTextureHandle->vulkanTexture->resourceAccessType + vulkanTextureSlice ); imageCopy.imageExtent.width = textureSlice->w; @@ -8812,9 +8749,9 @@ static void VULKAN_DownloadFromTexture( imageCopy.imageOffset.x = textureSlice->x; imageCopy.imageOffset.y = textureSlice->y; imageCopy.imageOffset.z = textureSlice->z; - imageCopy.imageSubresource.aspectMask = vulkanTextureContainer->activeTextureHandle->vulkanTexture->aspectFlags; - imageCopy.imageSubresource.baseArrayLayer = textureSlice->baseLayer; - imageCopy.imageSubresource.layerCount = textureSlice->layerCount; + imageCopy.imageSubresource.aspectMask = vulkanTextureSlice->parent->aspectFlags; + imageCopy.imageSubresource.baseArrayLayer = textureSlice->layer; + imageCopy.imageSubresource.layerCount = 1; imageCopy.imageSubresource.mipLevel = textureSlice->mipLevel; imageCopy.bufferOffset = copyParams->bufferOffset; imageCopy.bufferRowLength = copyParams->bufferStride; @@ -8822,16 +8759,16 @@ static void VULKAN_DownloadFromTexture( renderer->vkCmdCopyImageToBuffer( vulkanCommandBuffer->commandBuffer, - vulkanTextureContainer->activeTextureHandle->vulkanTexture->image, - AccessMap[vulkanTextureContainer->activeTextureHandle->vulkanTexture->resourceAccessType].imageLayout, + vulkanTextureSlice->parent->image, + AccessMap[vulkanTextureSlice->resourceAccessType].imageLayout, transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer, 1, &imageCopy ); VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer); - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTextureContainer->activeTextureHandle->vulkanTexture); - VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, vulkanTextureContainer->activeTextureHandle->vulkanTexture); + VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice); + VULKAN_INTERNAL_TrackCopiedTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice); } static void VULKAN_DownloadFromBuffer( @@ -8900,60 +8837,52 @@ static void VULKAN_CopyTextureToTexture( VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanTextureContainer *srcContainer = (VulkanTextureContainer*) source->texture; VulkanTextureContainer *dstContainer = (VulkanTextureContainer*) destination->texture; + VulkanTextureSlice *srcSlice; + VulkanTextureSlice *dstSlice; VkImageCopy imageCopy; + srcSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(source); + dstSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(destination); + if ( option == REFRESH_COPYOPTIONS_SAFEDISCARD && dstContainer->canBeDiscarded && - SDL_AtomicGet(&dstContainer->activeTextureHandle->vulkanTexture->referenceCount) > 0 + SDL_AtomicGet(&dstSlice->referenceCount) > 0 ) { VULKAN_INTERNAL_DiscardActiveTexture( renderer, dstContainer ); + dstSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(destination); } VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_READ, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - srcContainer->activeTextureHandle->vulkanTexture->layerCount, - 0, - srcContainer->activeTextureHandle->vulkanTexture->levelCount, - 0, - srcContainer->activeTextureHandle->vulkanTexture->image, - &srcContainer->activeTextureHandle->vulkanTexture->resourceAccessType + srcSlice ); VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_WRITE, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - dstContainer->activeTextureHandle->vulkanTexture->layerCount, - 0, - dstContainer->activeTextureHandle->vulkanTexture->levelCount, - 0, - dstContainer->activeTextureHandle->vulkanTexture->image, - &dstContainer->activeTextureHandle->vulkanTexture->resourceAccessType + dstSlice ); imageCopy.srcOffset.x = source->x; imageCopy.srcOffset.y = source->y; imageCopy.srcOffset.z = source->z; - imageCopy.srcSubresource.aspectMask = srcContainer->activeTextureHandle->vulkanTexture->aspectFlags; - imageCopy.srcSubresource.baseArrayLayer = source->baseLayer; - imageCopy.srcSubresource.layerCount = source->layerCount; + imageCopy.srcSubresource.aspectMask = srcSlice->parent->aspectFlags; + imageCopy.srcSubresource.baseArrayLayer = source->layer; + imageCopy.srcSubresource.layerCount = 1; imageCopy.srcSubresource.mipLevel = source->mipLevel; imageCopy.dstOffset.x = destination->x; imageCopy.dstOffset.y = destination->y; imageCopy.dstOffset.z = destination->z; - imageCopy.dstSubresource.aspectMask = dstContainer->activeTextureHandle->vulkanTexture->aspectFlags; - imageCopy.dstSubresource.baseArrayLayer = destination->baseLayer; - imageCopy.dstSubresource.layerCount = destination->layerCount; + imageCopy.dstSubresource.aspectMask = dstSlice->parent->aspectFlags; + imageCopy.dstSubresource.baseArrayLayer = destination->layer; + imageCopy.dstSubresource.layerCount = 1; imageCopy.dstSubresource.mipLevel = destination->mipLevel; imageCopy.extent.width = source->w; imageCopy.extent.height = source->h; @@ -8961,18 +8890,18 @@ static void VULKAN_CopyTextureToTexture( renderer->vkCmdCopyImage( vulkanCommandBuffer->commandBuffer, - srcContainer->activeTextureHandle->vulkanTexture->image, - AccessMap[srcContainer->activeTextureHandle->vulkanTexture->resourceAccessType].imageLayout, - dstContainer->activeTextureHandle->vulkanTexture->image, - AccessMap[dstContainer->activeTextureHandle->vulkanTexture->resourceAccessType].imageLayout, + srcSlice->parent->image, + AccessMap[srcSlice->resourceAccessType].imageLayout, + dstSlice->parent->image, + AccessMap[dstSlice->resourceAccessType].imageLayout, 1, &imageCopy ); - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, srcContainer->activeTextureHandle->vulkanTexture); - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, dstContainer->activeTextureHandle->vulkanTexture); - VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, srcContainer->activeTextureHandle->vulkanTexture); - VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, dstContainer->activeTextureHandle->vulkanTexture); + VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, srcSlice); + VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, dstSlice); + VULKAN_INTERNAL_TrackCopiedTextureSlice(renderer, vulkanCommandBuffer, srcSlice); + VULKAN_INTERNAL_TrackCopiedTextureSlice(renderer, vulkanCommandBuffer, dstSlice); } static void VULKAN_CopyTextureToBuffer( @@ -8986,9 +8915,12 @@ static void VULKAN_CopyTextureToBuffer( VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanTextureContainer *textureContainer = (VulkanTextureContainer*) textureSlice->texture; + VulkanTextureSlice *vulkanTextureSlice; VulkanBufferContainer *bufferContainer = (VulkanBufferContainer*) gpuBuffer; VkBufferImageCopy imageCopy; + vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(textureSlice); + if ( option == REFRESH_COPYOPTIONS_SAFEDISCARD && SDL_AtomicGet(&bufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 @@ -9003,14 +8935,7 @@ static void VULKAN_CopyTextureToBuffer( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_READ, - textureContainer->activeTextureHandle->vulkanTexture->aspectFlags, - 0, - textureContainer->activeTextureHandle->vulkanTexture->layerCount, - 0, - textureContainer->activeTextureHandle->vulkanTexture->levelCount, - 0, - textureContainer->activeTextureHandle->vulkanTexture->image, - &textureContainer->activeTextureHandle->vulkanTexture->resourceAccessType + vulkanTextureSlice ); VULKAN_INTERNAL_BufferMemoryBarrier( @@ -9026,9 +8951,9 @@ static void VULKAN_CopyTextureToBuffer( imageCopy.imageOffset.x = textureSlice->x; imageCopy.imageOffset.y = textureSlice->y; imageCopy.imageOffset.z = textureSlice->z; - imageCopy.imageSubresource.aspectMask = textureContainer->activeTextureHandle->vulkanTexture->aspectFlags; - imageCopy.imageSubresource.baseArrayLayer = textureSlice->baseLayer; - imageCopy.imageSubresource.layerCount = textureSlice->layerCount; + imageCopy.imageSubresource.aspectMask = vulkanTextureSlice->parent->aspectFlags; + imageCopy.imageSubresource.baseArrayLayer = textureSlice->layer; + imageCopy.imageSubresource.layerCount = 1; imageCopy.imageSubresource.mipLevel = textureSlice->mipLevel; imageCopy.bufferOffset = copyParams->bufferOffset; imageCopy.bufferRowLength = copyParams->bufferStride; @@ -9036,17 +8961,17 @@ static void VULKAN_CopyTextureToBuffer( renderer->vkCmdCopyImageToBuffer( vulkanCommandBuffer->commandBuffer, - textureContainer->activeTextureHandle->vulkanTexture->image, - AccessMap[textureContainer->activeTextureHandle->vulkanTexture->resourceAccessType].imageLayout, + vulkanTextureSlice->parent->image, + AccessMap[vulkanTextureSlice->resourceAccessType].imageLayout, bufferContainer->activeBufferHandle->vulkanBuffer->buffer, 1, &imageCopy ); VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, bufferContainer->activeBufferHandle->vulkanBuffer); - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, textureContainer->activeTextureHandle->vulkanTexture); + VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice); VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, bufferContainer->activeBufferHandle->vulkanBuffer); - VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, textureContainer->activeTextureHandle->vulkanTexture); + VULKAN_INTERNAL_TrackCopiedTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice); } static void VULKAN_CopyBufferToTexture( @@ -9061,16 +8986,21 @@ static void VULKAN_CopyBufferToTexture( VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanBufferContainer *bufferContainer = (VulkanBufferContainer*) gpuBuffer; VulkanTextureContainer *textureContainer = (VulkanTextureContainer*) textureSlice->texture; + VulkanTextureSlice *vulkanTextureSlice; VkBufferImageCopy imageCopy; + vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(textureSlice); + if ( option == REFRESH_COPYOPTIONS_SAFEDISCARD && - textureContainer->canBeDiscarded && SDL_AtomicGet(&textureContainer->activeTextureHandle->vulkanTexture->referenceCount) > 0 + textureContainer->canBeDiscarded && + SDL_AtomicGet(&vulkanTextureSlice->referenceCount) > 0 ) { VULKAN_INTERNAL_DiscardActiveTexture( renderer, textureContainer ); + vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(textureSlice); } VULKAN_INTERNAL_BufferMemoryBarrier( @@ -9084,14 +9014,7 @@ static void VULKAN_CopyBufferToTexture( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_WRITE, - textureContainer->activeTextureHandle->vulkanTexture->aspectFlags, - 0, - textureContainer->activeTextureHandle->vulkanTexture->layerCount, - 0, - textureContainer->activeTextureHandle->vulkanTexture->levelCount, - 0, - textureContainer->activeTextureHandle->vulkanTexture->image, - &textureContainer->activeTextureHandle->vulkanTexture->resourceAccessType + vulkanTextureSlice ); imageCopy.imageExtent.width = textureSlice->w; @@ -9100,9 +9023,9 @@ static void VULKAN_CopyBufferToTexture( imageCopy.imageOffset.x = textureSlice->x; imageCopy.imageOffset.y = textureSlice->y; imageCopy.imageOffset.z = textureSlice->z; - imageCopy.imageSubresource.aspectMask = textureContainer->activeTextureHandle->vulkanTexture->aspectFlags; - imageCopy.imageSubresource.baseArrayLayer = textureSlice->baseLayer; - imageCopy.imageSubresource.layerCount = textureSlice->layerCount; + imageCopy.imageSubresource.aspectMask = vulkanTextureSlice->parent->aspectFlags; + imageCopy.imageSubresource.baseArrayLayer = textureSlice->layer; + imageCopy.imageSubresource.layerCount = 1; imageCopy.imageSubresource.mipLevel = textureSlice->mipLevel; imageCopy.bufferOffset = copyParams->bufferOffset; imageCopy.bufferRowLength = copyParams->bufferStride; @@ -9111,16 +9034,16 @@ static void VULKAN_CopyBufferToTexture( renderer->vkCmdCopyBufferToImage( vulkanCommandBuffer->commandBuffer, bufferContainer->activeBufferHandle->vulkanBuffer->buffer, - textureContainer->activeTextureHandle->vulkanTexture->image, - AccessMap[textureContainer->activeTextureHandle->vulkanTexture->resourceAccessType].imageLayout, + vulkanTextureSlice->parent->image, + AccessMap[vulkanTextureSlice->resourceAccessType].imageLayout, 1, &imageCopy ); VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, bufferContainer->activeBufferHandle->vulkanBuffer); - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, textureContainer->activeTextureHandle->vulkanTexture); + VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice); VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, bufferContainer->activeBufferHandle->vulkanBuffer); - VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, textureContainer->activeTextureHandle->vulkanTexture); + VULKAN_INTERNAL_TrackCopiedTextureSlice(renderer, vulkanCommandBuffer, vulkanTextureSlice); } static void VULKAN_CopyBufferToBuffer( @@ -9187,52 +9110,41 @@ static void VULKAN_GenerateMipmaps( VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) texture)->activeTextureHandle->vulkanTexture; - VulkanResourceAccessType *levelAccessType; + VulkanTextureSlice *srcTextureSlice; + VulkanTextureSlice *dstTextureSlice; VkImageBlit blit; - uint32_t level; + uint32_t layer, level; if (vulkanTexture->levelCount <= 1) { return; } - /* Store the original image layout... */ - levelAccessType = SDL_stack_alloc( - VulkanResourceAccessType, - vulkanTexture->levelCount - ); - - for (level = 0; level < vulkanTexture->levelCount; level += 1) - { - levelAccessType[level] = vulkanTexture->resourceAccessType; - } - - /* Blit each mip sequentially. Barriers, barriers everywhere! */ + /* Blit each slice sequentially. Barriers, barriers everywhere! */ + for (layer = 0; layer < vulkanTexture->layerCount; layer += 1) for (level = 1; level < vulkanTexture->levelCount; level += 1) { + srcTextureSlice = VULKAN_INTERNAL_FetchTextureSlice( + vulkanTexture, + layer, + level - 1 + ); + + dstTextureSlice = VULKAN_INTERNAL_FetchTextureSlice( + vulkanTexture, + layer, + level + ); + VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_READ, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - vulkanTexture->layerCount, - level - 1, - 1, - 0, - vulkanTexture->image, - &levelAccessType[level - 1] + srcTextureSlice ); VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_WRITE, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - vulkanTexture->layerCount, - level, - 1, - 1, - vulkanTexture->image, - &levelAccessType[level] + dstTextureSlice ); blit.srcOffsets[0].x = 0; @@ -9252,13 +9164,13 @@ static void VULKAN_GenerateMipmaps( blit.dstOffsets[1].z = 1; blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.srcSubresource.baseArrayLayer = 0; - blit.srcSubresource.layerCount = vulkanTexture->layerCount; + blit.srcSubresource.baseArrayLayer = layer; + blit.srcSubresource.layerCount = 1; blit.srcSubresource.mipLevel = level - 1; blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - blit.dstSubresource.baseArrayLayer = 0; - blit.dstSubresource.layerCount = vulkanTexture->layerCount; + blit.dstSubresource.baseArrayLayer = layer; + blit.dstSubresource.layerCount = 1; blit.dstSubresource.mipLevel = level; renderer->vkCmdBlitImage( @@ -9272,26 +9184,6 @@ static void VULKAN_GenerateMipmaps( VK_FILTER_LINEAR ); } - - /* Transition final level to READ */ - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_READ, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - vulkanTexture->layerCount, - vulkanTexture->levelCount - 1, - 1, - 1, - vulkanTexture->image, - &levelAccessType[vulkanTexture->levelCount - 1] - ); - - /* The whole texture is in READ layout now, so set the access type on the texture */ - vulkanTexture->resourceAccessType = RESOURCE_ACCESS_TRANSFER_READ; - - SDL_stack_free(levelAccessType); } static void VULKAN_EndCopyPass( @@ -9301,7 +9193,7 @@ static void VULKAN_EndCopyPass( VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanBuffer *currentBuffer; - VulkanTexture *currentTexture; + VulkanTextureSlice *currentTextureSlice; VulkanResourceAccessType resourceAccessType = RESOURCE_ACCESS_NONE; uint32_t i; @@ -9335,29 +9227,25 @@ static void VULKAN_EndCopyPass( } /* Re-transition textures */ - for (i = 0; i < vulkanCommandBuffer->copiedTextureCount; i += 1) + for (i = 0; i < vulkanCommandBuffer->copiedTextureSliceCount; i += 1) { - currentTexture = vulkanCommandBuffer->copiedTextures[i]; + currentTextureSlice = vulkanCommandBuffer->copiedTextureSlices[i]; - if (currentTexture->usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) + if (currentTextureSlice->parent->usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) { resourceAccessType = RESOURCE_ACCESS_ANY_SHADER_READ_SAMPLED_IMAGE; VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, - resourceAccessType, - currentTexture->aspectFlags, - 0, - currentTexture->layerCount, - 0, - currentTexture->levelCount, - 0, - currentTexture->image, - ¤tTexture->resourceAccessType + RESOURCE_ACCESS_ANY_SHADER_READ_SAMPLED_IMAGE, + currentTextureSlice ); } } + + vulkanCommandBuffer->copiedGpuBufferCount = 0; + vulkanCommandBuffer->copiedTextureSliceCount = 0; } static void VULKAN_INTERNAL_AllocateCommandBuffers( @@ -9405,7 +9293,7 @@ static void VULKAN_INTERNAL_AllocateCommandBuffers( commandBuffer->commandBuffer = commandBuffers[i]; commandBuffer->inFlightFence = VK_NULL_HANDLE; - commandBuffer->renderPassDepthTexture = NULL; + commandBuffer->renderPassDepthTextureSlice = NULL; /* Presentation tracking */ @@ -9443,10 +9331,10 @@ static void VULKAN_INTERNAL_AllocateCommandBuffers( commandBuffer->boundComputeBufferCapacity * sizeof(VulkanBuffer*) ); - commandBuffer->boundComputeTextureCapacity = 16; - commandBuffer->boundComputeTextureCount = 0; - commandBuffer->boundComputeTextures = SDL_malloc( - commandBuffer->boundComputeTextureCapacity * sizeof(VulkanTexture*) + commandBuffer->boundComputeTextureSliceCapacity = 16; + commandBuffer->boundComputeTextureSliceCount = 0; + commandBuffer->boundComputeTextureSlices = SDL_malloc( + commandBuffer->boundComputeTextureSliceCapacity * sizeof(VulkanTextureSlice*) ); /* Copy resource tracking */ @@ -9457,10 +9345,10 @@ static void VULKAN_INTERNAL_AllocateCommandBuffers( commandBuffer->copiedGpuBufferCapacity * sizeof(VulkanBuffer*) ); - commandBuffer->copiedTextureCapacity = 16; - commandBuffer->copiedTextureCount = 0; - commandBuffer->copiedTextures = SDL_malloc( - commandBuffer->copiedTextureCapacity * sizeof(VulkanTexture*) + commandBuffer->copiedTextureSliceCapacity = 16; + commandBuffer->copiedTextureSliceCount = 0; + commandBuffer->copiedTextureSlices = SDL_malloc( + commandBuffer->copiedTextureSliceCapacity * sizeof(VulkanTextureSlice*) ); /* Resource tracking */ @@ -9471,10 +9359,10 @@ static void VULKAN_INTERNAL_AllocateCommandBuffers( commandBuffer->usedBufferCapacity * sizeof(VulkanBuffer*) ); - commandBuffer->usedTextureCapacity = 4; - commandBuffer->usedTextureCount = 0; - commandBuffer->usedTextures = SDL_malloc( - commandBuffer->usedTextureCapacity * sizeof(VulkanTexture*) + commandBuffer->usedTextureSliceCapacity = 4; + commandBuffer->usedTextureSliceCount = 0; + commandBuffer->usedTextureSlices = SDL_malloc( + commandBuffer->usedTextureSliceCapacity * sizeof(VulkanTextureSlice*) ); commandBuffer->usedSamplerCapacity = 4; @@ -9620,7 +9508,7 @@ static Refresh_CommandBuffer* VULKAN_AcquireCommandBuffer( commandBuffer->fragmentUniformOffset = 0; commandBuffer->computeUniformOffset = 0; - commandBuffer->renderPassColorTargetCount = 0; + commandBuffer->renderPassColorTargetTextureSliceCount = 0; commandBuffer->autoReleaseFence = 1; commandBuffer->isDefrag = 0; @@ -9745,6 +9633,7 @@ static Refresh_Texture* VULKAN_AcquireSwapchainTexture( VulkanSwapchainData *swapchainData; VkResult acquireResult = VK_SUCCESS; VulkanTextureContainer *swapchainTextureContainer = NULL; + VulkanTextureSlice *swapchainTextureSlice; VulkanPresentData *presentData; windowData = VULKAN_INTERNAL_FetchWindowData(windowHandle); @@ -9813,19 +9702,17 @@ static Refresh_Texture* VULKAN_AcquireSwapchainTexture( } swapchainTextureContainer = &swapchainData->textureContainers[swapchainImageIndex]; + swapchainTextureSlice = VULKAN_INTERNAL_FetchTextureSlice( + swapchainTextureContainer->activeTextureHandle->vulkanTexture, + 0, + 0 + ); VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_COLOR_ATTACHMENT_WRITE, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - 1, - 0, - 1, - 0, - swapchainTextureContainer->activeTextureHandle->vulkanTexture->image, - &swapchainTextureContainer->activeTextureHandle->vulkanTexture->resourceAccessType + swapchainTextureSlice ); /* Set up present struct */ @@ -10005,13 +9892,20 @@ static void VULKAN_INTERNAL_ReturnFenceToPool( static void VULKAN_INTERNAL_PerformPendingDestroys( VulkanRenderer *renderer ) { - int32_t i; + int32_t i, sliceIndex; + int32_t refCountTotal; SDL_LockMutex(renderer->disposeLock); for (i = renderer->texturesToDestroyCount - 1; i >= 0; i -= 1) { - if (SDL_AtomicGet(&renderer->texturesToDestroy[i]->referenceCount) == 0) + refCountTotal = 0; + for (sliceIndex = 0; sliceIndex < renderer->texturesToDestroy[i]->sliceCount; sliceIndex += 1) + { + refCountTotal += SDL_AtomicGet(&renderer->texturesToDestroy[i]->slices[sliceIndex].referenceCount); + } + + if (refCountTotal == 0) { VULKAN_INTERNAL_DestroyTexture( renderer, @@ -10159,11 +10053,11 @@ static void VULKAN_INTERNAL_CleanCommandBuffer( } commandBuffer->usedBufferCount = 0; - for (i = 0; i < commandBuffer->usedTextureCount; i += 1) + for (i = 0; i < commandBuffer->usedTextureSliceCount; i += 1) { - SDL_AtomicDecRef(&commandBuffer->usedTextures[i]->referenceCount); + SDL_AtomicDecRef(&commandBuffer->usedTextureSlices[i]->referenceCount); } - commandBuffer->usedTextureCount = 0; + commandBuffer->usedTextureSliceCount = 0; for (i = 0; i < commandBuffer->usedSamplerCount; i += 1) { @@ -10288,6 +10182,7 @@ static void VULKAN_Submit( VulkanCommandBuffer *vulkanCommandBuffer; VkPipelineStageFlags waitStages[MAX_PRESENT_COUNT]; uint32_t swapchainImageIndex; + VulkanTextureSlice *swapchainTextureSlice; uint8_t commandBufferCleaned = 0; VulkanMemorySubAllocator *allocator; int32_t i, j; @@ -10305,19 +10200,17 @@ static void VULKAN_Submit( for (j = 0; j < vulkanCommandBuffer->presentDataCount; j += 1) { swapchainImageIndex = vulkanCommandBuffer->presentDatas[j].swapchainImageIndex; + swapchainTextureSlice = VULKAN_INTERNAL_FetchTextureSlice( + vulkanCommandBuffer->presentDatas[j].windowData->swapchainData->textureContainers[swapchainImageIndex].activeTextureHandle->vulkanTexture, + 0, + 0 + ); VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_PRESENT, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - 1, - 0, - 1, - 0, - vulkanCommandBuffer->presentDatas[j].windowData->swapchainData->textureContainers[swapchainImageIndex].activeTextureHandle->vulkanTexture->image, - &vulkanCommandBuffer->presentDatas[j].windowData->swapchainData->textureContainers[swapchainImageIndex].activeTextureHandle->vulkanTexture->resourceAccessType + swapchainTextureSlice ); } @@ -10456,11 +10349,11 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory( VulkanBuffer* newBuffer; VulkanTexture* newTexture; VkBufferCopy bufferCopy; - VkImageCopy *imageCopyRegions; + VkImageCopy imageCopy; VulkanCommandBuffer *commandBuffer; - uint32_t i, level; - VulkanResourceAccessType copyResourceAccessType = RESOURCE_ACCESS_NONE; - VulkanResourceAccessType originalResourceAccessType; + VulkanTextureSlice *srcSlice; + VulkanTextureSlice *dstSlice; + uint32_t i, sliceIndex; SDL_LockMutex(renderer->allocatorLock); @@ -10479,7 +10372,6 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory( for (i = 0; i < allocation->usedRegionCount; i += 1) { currentRegion = allocation->usedRegions[i]; - copyResourceAccessType = RESOURCE_ACCESS_NONE; if (currentRegion->isBuffer && !currentRegion->vulkanBuffer->markedForDestroy) { @@ -10502,10 +10394,8 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory( return 0; } - originalResourceAccessType = currentRegion->vulkanBuffer->resourceAccessType; - /* Copy buffer contents if necessary */ - if (originalResourceAccessType != RESOURCE_ACCESS_NONE) + if (currentRegion->vulkanBuffer->resourceAccessType != RESOURCE_ACCESS_NONE) { VULKAN_INTERNAL_BufferMemoryBarrier( renderer, @@ -10533,12 +10423,14 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory( &bufferCopy ); + /* VULKAN_INTERNAL_BufferMemoryBarrier( renderer, commandBuffer->commandBuffer, originalResourceAccessType, newBuffer ); + */ VULKAN_INTERNAL_TrackBuffer(renderer, commandBuffer, currentRegion->vulkanBuffer); VULKAN_INTERNAL_TrackBuffer(renderer, commandBuffer, newBuffer); @@ -10556,20 +10448,19 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory( } else if (!currentRegion->vulkanTexture->markedForDestroy) { - originalResourceAccessType = currentRegion->vulkanTexture->resourceAccessType; - newTexture = VULKAN_INTERNAL_CreateTexture( renderer, currentRegion->vulkanTexture->dimensions.width, currentRegion->vulkanTexture->dimensions.height, currentRegion->vulkanTexture->depth, currentRegion->vulkanTexture->isCube, + currentRegion->vulkanTexture->layerCount, currentRegion->vulkanTexture->levelCount, currentRegion->vulkanTexture->sampleCount, currentRegion->vulkanTexture->format, currentRegion->vulkanTexture->aspectFlags, currentRegion->vulkanTexture->usageFlags, - 0 + 0 /* MSAA is dedicated so never defrags */ ); if (newTexture == NULL) @@ -10578,87 +10469,59 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory( return 0; } - if (originalResourceAccessType != RESOURCE_ACCESS_NONE) + for (sliceIndex = 0; sliceIndex < currentRegion->vulkanTexture->sliceCount; sliceIndex += 1) { - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - commandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_READ, - currentRegion->vulkanTexture->aspectFlags, - 0, - currentRegion->vulkanTexture->layerCount, - 0, - currentRegion->vulkanTexture->levelCount, - 0, - currentRegion->vulkanTexture->image, - ¤tRegion->vulkanTexture->resourceAccessType - ); + /* copy slice if necessary */ + srcSlice = ¤tRegion->vulkanTexture->slices[sliceIndex]; + dstSlice = &newTexture->slices[sliceIndex]; - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - commandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_WRITE, - currentRegion->vulkanTexture->aspectFlags, - 0, - currentRegion->vulkanTexture->layerCount, - 0, - currentRegion->vulkanTexture->levelCount, - 0, - newTexture->image, - ©ResourceAccessType - ); - - imageCopyRegions = SDL_stack_alloc(VkImageCopy, currentRegion->vulkanTexture->levelCount); - - for (level = 0; level < currentRegion->vulkanTexture->levelCount; level += 1) + if (srcSlice->resourceAccessType != RESOURCE_ACCESS_NONE) { - imageCopyRegions[level].srcOffset.x = 0; - imageCopyRegions[level].srcOffset.y = 0; - imageCopyRegions[level].srcOffset.z = 0; - imageCopyRegions[level].srcSubresource.aspectMask = currentRegion->vulkanTexture->aspectFlags; - imageCopyRegions[level].srcSubresource.baseArrayLayer = 0; - imageCopyRegions[level].srcSubresource.layerCount = currentRegion->vulkanTexture->layerCount; - imageCopyRegions[level].srcSubresource.mipLevel = level; - imageCopyRegions[level].extent.width = SDL_max(1, currentRegion->vulkanTexture->dimensions.width >> level); - imageCopyRegions[level].extent.height = SDL_max(1, currentRegion->vulkanTexture->dimensions.height >> level); - imageCopyRegions[level].extent.depth = currentRegion->vulkanTexture->depth; - imageCopyRegions[level].dstOffset.x = 0; - imageCopyRegions[level].dstOffset.y = 0; - imageCopyRegions[level].dstOffset.z = 0; - imageCopyRegions[level].dstSubresource.aspectMask = currentRegion->vulkanTexture->aspectFlags; - imageCopyRegions[level].dstSubresource.baseArrayLayer = 0; - imageCopyRegions[level].dstSubresource.layerCount = currentRegion->vulkanTexture->layerCount; - imageCopyRegions[level].dstSubresource.mipLevel = level; + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + commandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_READ, + srcSlice + ); + + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + commandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_WRITE, + dstSlice + ); + + imageCopy.srcOffset.x = 0; + imageCopy.srcOffset.y = 0; + imageCopy.srcOffset.z = 0; + imageCopy.srcSubresource.aspectMask = srcSlice->parent->aspectFlags; + imageCopy.srcSubresource.baseArrayLayer = srcSlice->layer; + imageCopy.srcSubresource.layerCount = 1; + imageCopy.srcSubresource.mipLevel = srcSlice->level; + imageCopy.extent.width = SDL_max(1, srcSlice->parent->dimensions.width >> srcSlice->level); + imageCopy.extent.height = SDL_max(1, srcSlice->parent->dimensions.height >> srcSlice->level); + imageCopy.extent.depth = srcSlice->parent->depth; + imageCopy.dstOffset.x = 0; + imageCopy.dstOffset.y = 0; + imageCopy.dstOffset.z = 0; + imageCopy.dstSubresource.aspectMask = dstSlice->parent->aspectFlags; + imageCopy.dstSubresource.baseArrayLayer = dstSlice->layer; + imageCopy.dstSubresource.layerCount = 1; + imageCopy.dstSubresource.mipLevel = dstSlice->level; + + renderer->vkCmdCopyImage( + commandBuffer->commandBuffer, + currentRegion->vulkanTexture->image, + AccessMap[srcSlice->resourceAccessType].imageLayout, + newTexture->image, + AccessMap[dstSlice->resourceAccessType].imageLayout, + 1, + &imageCopy + ); + + VULKAN_INTERNAL_TrackTextureSlice(renderer, commandBuffer, srcSlice); + VULKAN_INTERNAL_TrackTextureSlice(renderer, commandBuffer, dstSlice); } - - renderer->vkCmdCopyImage( - commandBuffer->commandBuffer, - currentRegion->vulkanTexture->image, - AccessMap[currentRegion->vulkanTexture->resourceAccessType].imageLayout, - newTexture->image, - AccessMap[copyResourceAccessType].imageLayout, - currentRegion->vulkanTexture->levelCount, - imageCopyRegions - ); - - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - commandBuffer->commandBuffer, - originalResourceAccessType, - currentRegion->vulkanTexture->aspectFlags, - 0, - currentRegion->vulkanTexture->layerCount, - 0, - currentRegion->vulkanTexture->levelCount, - 0, - newTexture->image, - ©ResourceAccessType - ); - - SDL_stack_free(imageCopyRegions); - - VULKAN_INTERNAL_TrackTexture(renderer, commandBuffer, currentRegion->vulkanTexture); - VULKAN_INTERNAL_TrackTexture(renderer, commandBuffer, newTexture); } /* re-point original container to new texture */