From 126375c5e3f3ea111a327ddb3f5bd0d13659f14f Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 28 Feb 2024 12:33:22 -0800 Subject: [PATCH] restructure render targets and MSAA passes --- src/Refresh_Driver_Vulkan.c | 694 +++++++++++++++++------------------- 1 file changed, 320 insertions(+), 374 deletions(-) diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index 57cc0fe..930a978 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -797,14 +797,14 @@ struct VulkanTexture uint32_t depth; uint32_t layerCount; uint32_t levelCount; - Refresh_SampleCount sampleCount; + Refresh_SampleCount sampleCount; /* actual sample account of the texture */ VkFormat format; VulkanResourceAccessType resourceAccessType; VkImageUsageFlags usageFlags; - VkImageAspectFlags aspectFlags; - struct VulkanTexture *msaaTex; /* doesn't need to be a handle because render targets are dedicated */ + Refresh_SampleCount renderTargetSampleCount; /* requested sample count for target */ + 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; @@ -830,11 +830,15 @@ typedef struct VulkanTextureContainer uint32_t textureCapacity; uint32_t textureCount; VulkanTextureHandle **textureHandles; + + /* Swapchain images cannot be discarded */ + uint8_t canBeDiscarded; } VulkanTextureContainer; typedef struct VulkanRenderTarget { VkImageView view; + VulkanTexture *msaaTex; /* NULL if sample count is 1 or is depth target */ } VulkanRenderTarget; typedef struct VulkanFramebuffer @@ -857,7 +861,7 @@ typedef struct VulkanSwapchainData /* Swapchain images */ VkExtent2D extent; - VulkanTextureHandle *textureContainers; + VulkanTextureContainer *textureContainers; /* use containers so that swapchain textures can use the same API as other textures */ uint32_t imageCount; /* Synchronization primitives */ @@ -1261,99 +1265,6 @@ static inline void FramebufferHashArray_Remove( arr->count -= 1; } -typedef struct RenderTargetHash -{ - VulkanTexture *texture; - uint32_t depth; - uint32_t layer; - uint32_t level; -} RenderTargetHash; - -typedef struct RenderTargetHashMap -{ - RenderTargetHash key; - VulkanRenderTarget *value; -} RenderTargetHashMap; - -typedef struct RenderTargetHashArray -{ - RenderTargetHashMap *elements; - int32_t count; - int32_t capacity; -} RenderTargetHashArray; - -static inline uint8_t RenderTargetHash_Compare( - RenderTargetHash *a, - RenderTargetHash *b -) { - if (a->texture != b->texture) - { - return 0; - } - - if (a->layer != b->layer) - { - return 0; - } - - if (a->level != b->level) - { - return 0; - } - - if (a->depth != b->depth) - { - return 0; - } - - return 1; -} - -static inline VulkanRenderTarget* RenderTargetHash_Fetch( - RenderTargetHashArray *arr, - RenderTargetHash *key -) { - int32_t i; - - for (i = 0; i < arr->count; i += 1) - { - RenderTargetHash *e = &arr->elements[i].key; - if (RenderTargetHash_Compare(e, key)) - { - return arr->elements[i].value; - } - } - - return NULL; -} - -static inline void RenderTargetHash_Insert( - RenderTargetHashArray *arr, - RenderTargetHash key, - VulkanRenderTarget *value -) { - RenderTargetHashMap map; - map.key = key; - map.value = value; - - EXPAND_ELEMENTS_IF_NEEDED(arr, 4, RenderTargetHashMap) - - arr->elements[arr->count] = map; - arr->count += 1; -} - -static inline void RenderTargetHash_Remove( - RenderTargetHashArray *arr, - uint32_t index -) { - if (index != arr->count - 1) - { - arr->elements[index] = arr->elements[arr->count - 1]; - } - - arr->count -= 1; -} - /* Descriptor Set Caches */ struct DescriptorSetCache @@ -1762,7 +1673,6 @@ typedef struct VulkanRenderer ComputePipelineLayoutHashTable computePipelineLayoutHashTable; RenderPassHashArray renderPassHashArray; FramebufferHashArray framebufferHashArray; - RenderTargetHashArray renderTargetHashArray; VkDescriptorPool defaultDescriptorPool; @@ -1824,7 +1734,6 @@ typedef struct VulkanRenderer SDL_mutex *acquireCommandBufferLock; SDL_mutex *renderPassFetchLock; SDL_mutex *framebufferFetchLock; - SDL_mutex *renderTargetFetchLock; uint8_t defragInProgress; @@ -3529,6 +3438,8 @@ static void VULKAN_INTERNAL_RemoveFramebuffersContainingView( FramebufferHash *hash; int32_t i, j; + SDL_LockMutex(renderer->framebufferFetchLock); + for (i = renderer->framebufferHashArray.count - 1; i >= 0; i -= 1) { hash = &renderer->framebufferHashArray.elements[i].key; @@ -3537,6 +3448,9 @@ static void VULKAN_INTERNAL_RemoveFramebuffersContainingView( { if (hash->colorAttachmentViews[j] == view) { + /* FIXME: do we actually need to queue this? + * The framebuffer should not be in use once the associated texture is being destroyed + */ VULKAN_INTERNAL_QueueDestroyFramebuffer( renderer, renderer->framebufferHashArray.elements[i].value @@ -3551,78 +3465,44 @@ static void VULKAN_INTERNAL_RemoveFramebuffersContainingView( } } } -} - -static void VULKAN_INTERNAL_RemoveRenderTargetsContainingTexture( - VulkanRenderer *renderer, - VulkanTexture *texture -) { - RenderTargetHash *hash; - VkImageView *viewsToCheck; - int32_t viewsToCheckCount; - int32_t viewsToCheckCapacity; - int32_t i; - - viewsToCheckCapacity = 16; - viewsToCheckCount = 0; - viewsToCheck = SDL_malloc(sizeof(VkImageView) * viewsToCheckCapacity); - - SDL_LockMutex(renderer->renderTargetFetchLock); - - for (i = renderer->renderTargetHashArray.count - 1; i >= 0; i -= 1) - { - hash = &renderer->renderTargetHashArray.elements[i].key; - - if (hash->texture == texture) - { - EXPAND_ARRAY_IF_NEEDED( - viewsToCheck, - VkImageView, - viewsToCheckCount + 1, - viewsToCheckCapacity, - viewsToCheckCapacity * 2 - ); - - viewsToCheck[viewsToCheckCount] = renderer->renderTargetHashArray.elements[i].value->view; - viewsToCheckCount += 1; - - VULKAN_INTERNAL_DestroyRenderTarget( - renderer, - renderer->renderTargetHashArray.elements[i].value - ); - - RenderTargetHash_Remove( - &renderer->renderTargetHashArray, - i - ); - } - } - - SDL_UnlockMutex(renderer->renderTargetFetchLock); - - SDL_LockMutex(renderer->framebufferFetchLock); - - for (i = 0; i < viewsToCheckCount; i += 1) - { - VULKAN_INTERNAL_RemoveFramebuffersContainingView( - renderer, - viewsToCheck[i] - ); - } SDL_UnlockMutex(renderer->framebufferFetchLock); - - SDL_free(viewsToCheck); } static void VULKAN_INTERNAL_DestroyTexture( VulkanRenderer* renderer, VulkanTexture* texture ) { - VULKAN_INTERNAL_RemoveRenderTargetsContainingTexture( - renderer, - texture - ); + uint32_t i, j, k, rtIndex; + uint8_t isRenderTarget = + ((texture->usageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0) || + ((texture->usageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0); + + if (isRenderTarget) + { + for (i = 0; i < texture->depth; i += 1) + { + for (j = 0; j < texture->layerCount; j += 1) + { + for (k = 0; k < texture->levelCount; k += 1) + { + rtIndex = VULKAN_INTERNAL_GetRenderTargetIndex( + texture, + i, + j, + k + ); + + VULKAN_INTERNAL_DestroyRenderTarget( + renderer, + &texture->renderTargets[rtIndex] + ); + } + } + } + + SDL_free(texture->renderTargets); + } renderer->vkDestroyImageView( renderer->logicalDevice, @@ -3641,15 +3521,6 @@ static void VULKAN_INTERNAL_DestroyTexture( texture->usedRegion ); - /* destroy the msaa texture, if there is one */ - if (texture->msaaTex != NULL) - { - VULKAN_INTERNAL_DestroyTexture( - renderer, - texture->msaaTex - ); - } - SDL_free(texture); } @@ -3657,13 +3528,21 @@ static void VULKAN_INTERNAL_DestroyRenderTarget( VulkanRenderer *renderer, VulkanRenderTarget *renderTarget ) { + VULKAN_INTERNAL_RemoveFramebuffersContainingView( + renderer, + renderTarget->view + ); + renderer->vkDestroyImageView( renderer->logicalDevice, renderTarget->view, NULL ); - SDL_free(renderTarget); + VULKAN_INTERNAL_DestroyTexture( + renderer, + renderTarget->msaaTex + ); } static void VULKAN_INTERNAL_DestroyBuffer( @@ -3801,18 +3680,21 @@ static void VULKAN_INTERNAL_DestroySwapchain( for (i = 0; i < swapchainData->imageCount; i += 1) { - VULKAN_INTERNAL_RemoveRenderTargetsContainingTexture( + VULKAN_INTERNAL_DestroyRenderTarget( renderer, - swapchainData->textureContainers[i].vulkanTexture + &swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->renderTargets[0] ); + SDL_free(swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->renderTargets); + renderer->vkDestroyImageView( renderer->logicalDevice, - swapchainData->textureContainers[i].vulkanTexture->view, + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->view, NULL ); - SDL_free(swapchainData->textureContainers[i].vulkanTexture); + SDL_free(swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture); + SDL_free(swapchainData->textureContainers[i].activeTextureHandle); } SDL_free(swapchainData->textureContainers); @@ -4917,7 +4799,7 @@ static uint8_t VULKAN_INTERNAL_CreateSwapchain( ); swapchainData->textureContainers = SDL_malloc( - sizeof(VulkanTextureHandle) * swapchainData->imageCount + sizeof(VulkanTextureContainer) * swapchainData->imageCount ); if (!swapchainData->textureContainers) @@ -4955,9 +4837,15 @@ static uint8_t VULKAN_INTERNAL_CreateSwapchain( for (i = 0; i < swapchainData->imageCount; i += 1) { - swapchainData->textureContainers[i].vulkanTexture = SDL_malloc(sizeof(VulkanTexture)); + swapchainData->textureContainers[i].canBeDiscarded = 0; + swapchainData->textureContainers[i].textureCapacity = 0; + swapchainData->textureContainers[i].textureCount = 0; + swapchainData->textureContainers[i].textureHandles = NULL; + swapchainData->textureContainers[i].activeTextureHandle = SDL_malloc(sizeof(VulkanTextureHandle)); - swapchainData->textureContainers[i].vulkanTexture->image = swapchainImages[i]; + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture = SDL_malloc(sizeof(VulkanTexture)); + + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->image = swapchainImages[i]; imageViewCreateInfo.image = swapchainImages[i]; @@ -4965,7 +4853,7 @@ static uint8_t VULKAN_INTERNAL_CreateSwapchain( renderer->logicalDevice, &imageViewCreateInfo, NULL, - &swapchainData->textureContainers[i].vulkanTexture->view + &swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->view ); if (vulkanResult != VK_SUCCESS) @@ -4982,25 +4870,37 @@ static uint8_t VULKAN_INTERNAL_CreateSwapchain( return 0; } - swapchainData->textureContainers[i].vulkanTexture->resourceAccessType = RESOURCE_ACCESS_NONE; + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->resourceAccessType = RESOURCE_ACCESS_NONE; /* Swapchain memory is managed by the driver */ - swapchainData->textureContainers[i].vulkanTexture->usedRegion = NULL; + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->usedRegion = NULL; - swapchainData->textureContainers[i].vulkanTexture->dimensions = swapchainData->extent; - swapchainData->textureContainers[i].vulkanTexture->format = swapchainData->swapchainFormat; - swapchainData->textureContainers[i].vulkanTexture->is3D = 0; - swapchainData->textureContainers[i].vulkanTexture->isCube = 0; - swapchainData->textureContainers[i].vulkanTexture->depth = 1; - swapchainData->textureContainers[i].vulkanTexture->layerCount = 1; - swapchainData->textureContainers[i].vulkanTexture->levelCount = 1; - swapchainData->textureContainers[i].vulkanTexture->sampleCount = REFRESH_SAMPLECOUNT_1; - swapchainData->textureContainers[i].vulkanTexture->usageFlags = + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->dimensions = swapchainData->extent; + 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->depth = 1; + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->layerCount = 1; + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->levelCount = 1; + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->sampleCount = REFRESH_SAMPLECOUNT_1; + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->usageFlags = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - swapchainData->textureContainers[i].vulkanTexture->aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT; - swapchainData->textureContainers[i].vulkanTexture->resourceAccessType = RESOURCE_ACCESS_NONE; - swapchainData->textureContainers[i].vulkanTexture->msaaTex = NULL; + 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->renderTargetSampleCount = REFRESH_SAMPLECOUNT_1; + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->renderTargets = SDL_malloc(sizeof(VulkanRenderTarget)); + VULKAN_INTERNAL_CreateRenderTarget( + renderer, + swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture, + 0, + 0, + 0, + REFRESH_SAMPLECOUNT_1, + &swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->renderTargets[0] + ); } SDL_stack_free(swapchainImages); @@ -5270,8 +5170,6 @@ static void VULKAN_DestroyDevice( SDL_free(renderer->renderPassHashArray.elements); - SDL_free(renderer->renderTargetHashArray.elements); - for (i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) { allocator = &renderer->memoryAllocator->subAllocators[i]; @@ -5317,7 +5215,6 @@ static void VULKAN_DestroyDevice( SDL_DestroyMutex(renderer->acquireCommandBufferLock); SDL_DestroyMutex(renderer->renderPassFetchLock); SDL_DestroyMutex(renderer->framebufferFetchLock); - SDL_DestroyMutex(renderer->renderTargetFetchLock); renderer->vkDestroyDevice(renderer->logicalDevice, NULL); renderer->vkDestroyInstance(renderer->instance, NULL); @@ -5476,6 +5373,101 @@ static void VULKAN_DrawPrimitivesIndirect( VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanBuffer); } +static void VULKAN_INTERNAL_CreateRenderTarget( + VulkanRenderer *renderer, + VulkanTexture *texture, + uint32_t depth, + uint32_t layer, + uint32_t level, + Refresh_SampleCount 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 > REFRESH_SAMPLECOUNT_1) + { + /* 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 + ); + + if (renderTarget->msaaTex == NULL) + { + Refresh_LogError("Failed to create MSAA render texture!"); + return; + } + } + else + { + renderTarget->msaaTex = NULL; + } +} + static VulkanTexture* VULKAN_INTERNAL_CreateTexture( VulkanRenderer *renderer, uint32_t width, @@ -5499,7 +5491,7 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture( ((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; VulkanTexture *texture = SDL_malloc(sizeof(VulkanTexture)); texture->isCube = 0; @@ -5527,7 +5519,7 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture( imageCreateInfo.extent.depth = depth; imageCreateInfo.mipLevels = levelCount; imageCreateInfo.arrayLayers = layerCount; - imageCreateInfo.samples = RefreshToVK_SampleCount[sampleCount]; + imageCreateInfo.samples = sampleCount; imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; imageCreateInfo.usage = imageUsageFlags; imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -5612,80 +5604,26 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture( texture->resourceAccessType = RESOURCE_ACCESS_NONE; texture->usageFlags = imageUsageFlags; texture->aspectFlags = aspectMask; - texture->msaaTex = NULL; SDL_AtomicSet(&texture->referenceCount, 0); + /* these get overwritten if render targets are created */ + texture->renderTargetSampleCount = REFRESH_SAMPLECOUNT_1; + texture->renderTargets = NULL; + return texture; } -static VulkanRenderTarget* VULKAN_INTERNAL_CreateRenderTarget( - VulkanRenderer *renderer, +static uint32_t VULKAN_INTERNAL_GetRenderTargetIndex( VulkanTexture *texture, uint32_t depth, uint32_t layer, uint32_t level ) { - VkResult vulkanResult; - VulkanRenderTarget *renderTarget = (VulkanRenderTarget*) SDL_malloc(sizeof(VulkanRenderTarget)); - 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 NULL; - } - - return renderTarget; + return + (level * texture->depth * texture->layerCount) + + (layer * texture->depth) + + texture->depth; } static VulkanRenderTarget* VULKAN_INTERNAL_FetchRenderTarget( @@ -5695,41 +5633,31 @@ static VulkanRenderTarget* VULKAN_INTERNAL_FetchRenderTarget( uint32_t layer, uint32_t level ) { - RenderTargetHash hash; - VulkanRenderTarget *renderTarget; - - hash.texture = texture; - hash.depth = depth; - hash.layer = layer; - hash.level = level; - - SDL_LockMutex(renderer->renderTargetFetchLock); - - renderTarget = RenderTargetHash_Fetch( - &renderer->renderTargetHashArray, - &hash - ); - - if (renderTarget == NULL) - { - renderTarget = VULKAN_INTERNAL_CreateRenderTarget( - renderer, + return &texture->renderTargets[ + VULKAN_INTERNAL_GetRenderTargetIndex( texture, depth, layer, level - ); + ) + ]; +} - RenderTargetHash_Insert( - &renderer->renderTargetHashArray, - hash, - renderTarget - ); - } - - SDL_UnlockMutex(renderer->renderTargetFetchLock); - - return renderTarget; +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( @@ -5754,32 +5682,13 @@ static VkRenderPass VULKAN_INTERNAL_CreateRenderPass( uint32_t resolveReferenceCount = 0; VulkanTexture *texture; - VulkanTexture *msaaTexture = NULL; for (i = 0; i < colorAttachmentCount; i += 1) { texture = ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture; - if (texture->msaaTex != NULL) + if (texture->renderTargetSampleCount > REFRESH_SAMPLECOUNT_1) { - msaaTexture = texture->msaaTex; - - /* Transition the multisample attachment */ - - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - commandBuffer->commandBuffer, - RESOURCE_ACCESS_COLOR_ATTACHMENT_WRITE, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - msaaTexture->layerCount, - 0, - msaaTexture->levelCount, - 0, - msaaTexture->image, - &msaaTexture->resourceAccessType - ); - /* Resolve attachment and multisample attachment */ attachmentDescriptions[attachmentDescriptionCount].flags = 0; @@ -5809,9 +5718,9 @@ static VkRenderPass VULKAN_INTERNAL_CreateRenderPass( resolveReferenceCount += 1; attachmentDescriptions[attachmentDescriptionCount].flags = 0; - attachmentDescriptions[attachmentDescriptionCount].format = msaaTexture->format; + attachmentDescriptions[attachmentDescriptionCount].format = texture->format; attachmentDescriptions[attachmentDescriptionCount].samples = RefreshToVK_SampleCount[ - msaaTexture->sampleCount + texture->renderTargetSampleCount ]; attachmentDescriptions[attachmentDescriptionCount].loadOp = RefreshToVK_LoadOp[ colorAttachmentInfos[i].loadOp @@ -5916,7 +5825,7 @@ static VkRenderPass VULKAN_INTERNAL_CreateRenderPass( attachmentDescriptionCount += 1; } - if (msaaTexture != NULL) + if (texture->renderTargetSampleCount > REFRESH_SAMPLECOUNT_1) { subpass.pResolveAttachments = resolveReferences; } @@ -6773,11 +6682,15 @@ static Refresh_Texture* VULKAN_CreateTexture( VK_IMAGE_USAGE_TRANSFER_SRC_BIT ); VkImageAspectFlags imageAspectFlags; + uint8_t isRenderTarget = + ((imageUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0) || + ((imageUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0); uint8_t isDepthFormat = IsRefreshDepthFormat(textureCreateInfo->format); VkFormat format; VulkanTextureContainer *container; VulkanTextureHandle *textureHandle; VulkanTexture *vulkanTexture; + uint32_t i, j, k, rtIndex; if (isDepthFormat) { @@ -6822,7 +6735,6 @@ static Refresh_Texture* VULKAN_CreateTexture( imageAspectFlags = VK_IMAGE_ASPECT_COLOR_BIT; } - /* FIXME: what if this fails? */ vulkanTexture = VULKAN_INTERNAL_CreateTexture( renderer, textureCreateInfo->width, @@ -6830,32 +6742,54 @@ static Refresh_Texture* VULKAN_CreateTexture( textureCreateInfo->depth, textureCreateInfo->isCube, textureCreateInfo->levelCount, - isDepthFormat ? - textureCreateInfo->sampleCount : /* depth textures do not have a separate msaaTex */ - REFRESH_SAMPLECOUNT_1, + REFRESH_SAMPLECOUNT_1, /* attachments themselves are always sample count 1, have msaaTex in render target */ format, imageAspectFlags, imageUsageFlags ); - /* create the MSAA texture for color attachments, if needed */ - if ( vulkanTexture != NULL && - !isDepthFormat && - textureCreateInfo->sampleCount > REFRESH_SAMPLECOUNT_1 ) + if (vulkanTexture == NULL) { - /* FIXME: what if this fails? */ - vulkanTexture->msaaTex = VULKAN_INTERNAL_CreateTexture( - renderer, - textureCreateInfo->width, - textureCreateInfo->height, - textureCreateInfo->depth, - textureCreateInfo->isCube, - textureCreateInfo->levelCount, - textureCreateInfo->sampleCount, - format, - imageAspectFlags, - imageUsageFlags + Refresh_LogInfo("Failed to create texture!"); + return NULL; + } + + /* Create render target structures if necessary */ + if (isRenderTarget) + { + vulkanTexture->renderTargetSampleCount = textureCreateInfo->sampleCount; + vulkanTexture->renderTargets = SDL_malloc( + vulkanTexture->depth * + vulkanTexture->layerCount * + vulkanTexture->levelCount * + sizeof(VulkanRenderTarget) ); + + for (i = 0; i < vulkanTexture->depth; i += 1) + { + for (j = 0; j < vulkanTexture->layerCount; j += 1) + { + for (k = 0; k < vulkanTexture->levelCount; k += 1) + { + rtIndex = VULKAN_INTERNAL_GetRenderTargetIndex( + vulkanTexture, + i, + j, + k + ); + + VULKAN_INTERNAL_CreateRenderTarget( + renderer, + vulkanTexture, + i, + j, + k, + textureCreateInfo->sampleCount, + &vulkanTexture->renderTargets[rtIndex] + ); + } + } + } } textureHandle = SDL_malloc(sizeof(VulkanTextureHandle)); @@ -6863,10 +6797,10 @@ static Refresh_Texture* VULKAN_CreateTexture( vulkanTexture->handle = textureHandle; container = SDL_malloc(sizeof(VulkanTextureContainer)); - + container->canBeDiscarded = 1; container->activeTextureHandle = textureHandle; container->textureCapacity = 1; - container->textureCount =1 ; + container->textureCount = 1 ; container->textureHandles = SDL_malloc( container->textureCapacity * sizeof(VulkanTextureHandle*) ); @@ -7493,10 +7427,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass( if (colorAttachmentCount > 0) { texture = ((VulkanTextureHandle*) colorAttachmentInfos[0].texture)->vulkanTexture; - if (texture->msaaTex != NULL) - { - hash.colorAttachmentSampleCount = texture->msaaTex->sampleCount; - } + hash.colorAttachmentSampleCount = texture->renderTargetSampleCount; } hash.colorAttachmentCount = colorAttachmentCount; @@ -7593,19 +7524,9 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( renderTarget->view ); - if (texture->msaaTex != NULL) + if (renderTarget->msaaTex != NULL) { - renderTarget = VULKAN_INTERNAL_FetchRenderTarget( - renderer, - texture->msaaTex, - colorAttachmentInfos[i].depth, - colorAttachmentInfos[i].layer, - colorAttachmentInfos[i].level - ); - - hash.colorMultiSampleAttachmentViews[i] = ( - renderTarget->view - ); + hash.colorMultiSampleAttachmentViews[i] = renderTarget->msaaTex->view; } } @@ -7666,18 +7587,10 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( attachmentCount += 1; - if (texture->msaaTex != NULL) + if (renderTarget->msaaTex != NULL) { - renderTarget = VULKAN_INTERNAL_FetchRenderTarget( - renderer, - texture->msaaTex, - colorAttachmentInfos[i].depth, - colorAttachmentInfos[i].layer, - colorAttachmentInfos[i].level - ); - imageViewAttachments[attachmentCount] = - renderTarget->view; + renderTarget->msaaTex->view; attachmentCount += 1; } @@ -7817,6 +7730,7 @@ static void VULKAN_BeginRenderPass( VulkanFramebuffer *framebuffer; VulkanTexture *texture; + VulkanTexture *msaaTexture = NULL; uint32_t w, h; VkClearValue *clearValues; uint32_t clearCount = colorAttachmentCount; @@ -7846,6 +7760,12 @@ static void VULKAN_BeginRenderPass( { framebufferHeight = h; } + + if (texture->renderTargets == NULL) + { + Refresh_LogError("Color attachment texture was not designated as a target!"); + return; + } } if (depthStencilAttachmentInfo != NULL) @@ -7863,6 +7783,12 @@ static void VULKAN_BeginRenderPass( { framebufferHeight = h; } + + if (texture->renderTargets == NULL) + { + Refresh_LogError("Depth stencil attachment texture was not designated as a target!"); + return; + } } /* Fetch required render objects */ @@ -7893,6 +7819,7 @@ static void VULKAN_BeginRenderPass( { texture = ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture; + /* Transition the attachment */ VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, @@ -7907,13 +7834,37 @@ static void VULKAN_BeginRenderPass( &texture->resourceAccessType ); - if (texture->msaaTex != NULL) + if (texture->renderTargetSampleCount > REFRESH_SAMPLECOUNT_1) { + msaaTexture = VULKAN_INTERNAL_FetchRenderTargetMSAATexture( + renderer, + texture, + colorAttachmentInfos[i].depth, + colorAttachmentInfos[i].layer, + colorAttachmentInfos[i].level + ); + + /* Transition the multisample attachment */ + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_COLOR_ATTACHMENT_WRITE, + VK_IMAGE_ASPECT_COLOR_BIT, + 0, + msaaTexture->layerCount, + 0, + msaaTexture->levelCount, + 0, + msaaTexture->image, + &msaaTexture->resourceAccessType + ); + clearCount += 1; multisampleAttachmentCount += 1; } VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, texture); + /* TODO: do we need to track the msaa texture? or is it implicitly only used when the regular texture is used? */ } if (depthStencilAttachmentInfo != NULL) @@ -7959,7 +7910,7 @@ static void VULKAN_BeginRenderPass( clearValues[i].color.float32[3] = colorAttachmentInfos[i].clearColor.w; texture = ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture; - if (texture->msaaTex != NULL) + if (texture->renderTargetSampleCount > REFRESH_SAMPLECOUNT_1) { clearValues[i+1].color.float32[0] = colorAttachmentInfos[i].clearColor.x; clearValues[i+1].color.float32[1] = colorAttachmentInfos[i].clearColor.y; @@ -8613,7 +8564,7 @@ static void VULKAN_UploadToTexture( VulkanTextureContainer *vulkanTextureContainer = (VulkanTextureContainer*) textureSlice->texture; VkBufferImageCopy imageCopy; - if (option == REFRESH_COPYOPTIONS_SAFEDISCARD && SDL_AtomicGet(&vulkanTextureContainer->activeTextureHandle->vulkanTexture->referenceCount) > 0) + if (option == REFRESH_COPYOPTIONS_SAFEDISCARD && vulkanTextureContainer->canBeDiscarded && SDL_AtomicGet(&vulkanTextureContainer->activeTextureHandle->vulkanTexture->referenceCount) > 0) { VULKAN_INTERNAL_DiscardActiveTexture( renderer, @@ -10207,8 +10158,8 @@ static void VULKAN_Submit( 0, 1, 0, - vulkanCommandBuffer->presentDatas[j].windowData->swapchainData->textureContainers[swapchainImageIndex].vulkanTexture->image, - &vulkanCommandBuffer->presentDatas[j].windowData->swapchainData->textureContainers[swapchainImageIndex].vulkanTexture->resourceAccessType + vulkanCommandBuffer->presentDatas[j].windowData->swapchainData->textureContainers[swapchainImageIndex].activeTextureHandle->vulkanTexture->image, + &vulkanCommandBuffer->presentDatas[j].windowData->swapchainData->textureContainers[swapchainImageIndex].activeTextureHandle->vulkanTexture->resourceAccessType ); } @@ -11560,7 +11511,6 @@ static Refresh_Device* VULKAN_CreateDevice( renderer->acquireCommandBufferLock = SDL_CreateMutex(); renderer->renderPassFetchLock = SDL_CreateMutex(); renderer->framebufferFetchLock = SDL_CreateMutex(); - renderer->renderTargetFetchLock = SDL_CreateMutex(); /* * Create submitted command buffer list @@ -11836,10 +11786,6 @@ static Refresh_Device* VULKAN_CreateDevice( renderer->framebufferHashArray.count = 0; renderer->framebufferHashArray.capacity = 0; - renderer->renderTargetHashArray.elements = NULL; - renderer->renderTargetHashArray.count = 0; - renderer->renderTargetHashArray.capacity = 0; - /* Initialize fence pool */ renderer->fencePool.lock = SDL_CreateMutex();