From 8e04b0d1c9be4d719d2c0d929069175776f4ad26 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Thu, 29 Feb 2024 10:44:40 -0800 Subject: [PATCH] render target discards and block allocation --- include/Refresh.h | 2 + src/Refresh_Driver_Vulkan.c | 203 ++++++++++++++++++++++-------------- 2 files changed, 127 insertions(+), 78 deletions(-) diff --git a/include/Refresh.h b/include/Refresh.h index 644c9a6..5ffe718 100644 --- a/include/Refresh.h +++ b/include/Refresh.h @@ -587,6 +587,7 @@ typedef struct Refresh_ColorAttachmentInfo Refresh_Vec4 clearColor; /* Can be ignored by RenderPass */ Refresh_LoadOp loadOp; Refresh_StoreOp storeOp; + uint8_t safeDiscard; /* ignored if loadOp is LOAD */ } Refresh_ColorAttachmentInfo; typedef struct Refresh_DepthStencilAttachmentInfo @@ -600,6 +601,7 @@ typedef struct Refresh_DepthStencilAttachmentInfo Refresh_StoreOp storeOp; Refresh_LoadOp stencilLoadOp; Refresh_StoreOp stencilStoreOp; + uint8_t safeDiscard; /* ignored if either loadOp or stencilLoadOp is LOAD*/ } Refresh_DepthStencilAttachmentInfo; /* Functions */ diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index 6ad120f..c190a29 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -2846,7 +2846,6 @@ static uint8_t VULKAN_INTERNAL_BindResourceMemory( static uint8_t VULKAN_INTERNAL_BindMemoryForImage( VulkanRenderer* renderer, VkImage image, - uint8_t isRenderTarget, VulkanMemoryUsedRegion** usedRegion ) { uint8_t bindResult = 0; @@ -2872,7 +2871,7 @@ static uint8_t VULKAN_INTERNAL_BindMemoryForImage( renderer, memoryTypeIndex, &memoryRequirements, - isRenderTarget, + 0, memoryRequirements.memoryRequirements.size, VK_NULL_HANDLE, image, @@ -2895,11 +2894,6 @@ static uint8_t VULKAN_INTERNAL_BindMemoryForImage( memoryTypeIndex = 0; requiredMemoryPropertyFlags = 0; - if (isRenderTarget) - { - Refresh_LogWarn("RenderTarget is allocated in host memory, pre-allocate your targets!"); - } - Refresh_LogWarn("Out of device-local memory, allocating textures on host-local memory!"); while (VULKAN_INTERNAL_FindImageMemoryRequirements( @@ -2913,7 +2907,7 @@ static uint8_t VULKAN_INTERNAL_BindMemoryForImage( renderer, memoryTypeIndex, &memoryRequirements, - isRenderTarget, + 0, memoryRequirements.memoryRequirements.size, VK_NULL_HANDLE, image, @@ -5448,7 +5442,6 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture( bindResult = VULKAN_INTERNAL_BindMemoryForImage( renderer, texture->image, - isRenderTarget, &texture->usedRegion ); @@ -5601,6 +5594,53 @@ static VulkanTextureHandle* VULKAN_INTERNAL_CreateTextureHandle( return textureHandle; } +static void VULKAN_INTERNAL_DiscardActiveTexture( + VulkanRenderer *renderer, + VulkanTextureContainer *textureContainer +) { + VulkanTextureHandle *textureHandle; + uint32_t i; + + /* If a previously-discarded buffer 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) + { + textureContainer->activeTextureHandle = textureHandle; + return; + } + } + + /* No texture handle is available, generate a new one. */ + textureContainer->activeTextureHandle = VULKAN_INTERNAL_CreateTextureHandle( + renderer, + textureContainer->activeTextureHandle->vulkanTexture->dimensions.width, + textureContainer->activeTextureHandle->vulkanTexture->dimensions.height, + textureContainer->activeTextureHandle->vulkanTexture->depth, + textureContainer->activeTextureHandle->vulkanTexture->isCube, + textureContainer->activeTextureHandle->vulkanTexture->levelCount, + textureContainer->activeTextureHandle->vulkanTexture->sampleCount, + textureContainer->activeTextureHandle->vulkanTexture->format, + textureContainer->activeTextureHandle->vulkanTexture->aspectFlags, + textureContainer->activeTextureHandle->vulkanTexture->usageFlags, + 0 + ); + + EXPAND_ARRAY_IF_NEEDED( + textureContainer->textureHandles, + VulkanTextureHandle*, + textureContainer->textureCount + 1, + textureContainer->textureCapacity, + textureContainer->textureCapacity * 2 + ); + + textureContainer->textureHandles[ + textureContainer->textureCount + ] = textureContainer->activeTextureHandle; + textureContainer->textureCount += 1; +} + static void VULKAN_INTERNAL_CreateRenderTarget( VulkanRenderer *renderer, VulkanTexture *texture, @@ -7773,6 +7813,7 @@ static void VULKAN_BeginRenderPass( VkRenderPass renderPass; VulkanFramebuffer *framebuffer; + VulkanTextureContainer *textureContainer; VulkanTexture *texture; VulkanTexture *msaaTexture = NULL; uint32_t w, h; @@ -7787,14 +7828,29 @@ static void VULKAN_BeginRenderPass( uint32_t framebufferWidth = UINT32_MAX; uint32_t framebufferHeight = UINT32_MAX; - /* The framebuffer cannot be larger than the smallest attachment. */ - for (i = 0; i < colorAttachmentCount; i += 1) { - texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->activeTextureHandle->vulkanTexture; + textureContainer = (VulkanTextureContainer*) colorAttachmentInfos[i].texture; + + if ( + colorAttachmentInfos[i].safeDiscard && + colorAttachmentInfos[i].loadOp != REFRESH_LOADOP_LOAD && + textureContainer->canBeDiscarded && + SDL_AtomicGet(&textureContainer->activeTextureHandle->vulkanTexture->referenceCount) > 0 + ) { + VULKAN_INTERNAL_DiscardActiveTexture( + renderer, + textureContainer + ); + } + + texture = textureContainer->activeTextureHandle->vulkanTexture; + w = texture->dimensions.width >> colorAttachmentInfos[i].level; h = texture->dimensions.height >> colorAttachmentInfos[i].level; + /* The framebuffer cannot be larger than the smallest attachment. */ + if (w < framebufferWidth) { framebufferWidth = w; @@ -7814,10 +7870,28 @@ static void VULKAN_BeginRenderPass( if (depthStencilAttachmentInfo != NULL) { - texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture; + textureContainer = (VulkanTextureContainer*) depthStencilAttachmentInfo->texture; + + if ( + depthStencilAttachmentInfo->safeDiscard && + depthStencilAttachmentInfo->loadOp != REFRESH_LOADOP_LOAD && + depthStencilAttachmentInfo->stencilLoadOp != REFRESH_LOADOP_LOAD && + textureContainer->canBeDiscarded && + SDL_AtomicGet(&textureContainer->activeTextureHandle->vulkanTexture->referenceCount) > 0 + ) { + VULKAN_INTERNAL_DiscardActiveTexture( + renderer, + textureContainer + ); + } + + texture = textureContainer->activeTextureHandle->vulkanTexture; + w = texture->dimensions.width >> depthStencilAttachmentInfo->level; h = texture->dimensions.height >> depthStencilAttachmentInfo->level; + /* The framebuffer cannot be larger than the smallest attachment. */ + if (w < framebufferWidth) { framebufferWidth = w; @@ -8493,53 +8567,6 @@ static void VULKAN_INTERNAL_DiscardActiveBuffer( bufferContainer->bufferCount += 1; } -static void VULKAN_INTERNAL_DiscardActiveTexture( - VulkanRenderer *renderer, - VulkanTextureContainer *textureContainer -) { - VulkanTextureHandle *textureHandle; - uint32_t i; - - /* If a previously-discarded buffer 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) - { - textureContainer->activeTextureHandle = textureHandle; - return; - } - } - - /* No texture handle is available, generate a new one. */ - textureContainer->activeTextureHandle = VULKAN_INTERNAL_CreateTextureHandle( - renderer, - textureContainer->activeTextureHandle->vulkanTexture->dimensions.width, - textureContainer->activeTextureHandle->vulkanTexture->dimensions.height, - textureContainer->activeTextureHandle->vulkanTexture->depth, - textureContainer->activeTextureHandle->vulkanTexture->isCube, - textureContainer->activeTextureHandle->vulkanTexture->levelCount, - textureContainer->activeTextureHandle->vulkanTexture->sampleCount, - textureContainer->activeTextureHandle->vulkanTexture->format, - textureContainer->activeTextureHandle->vulkanTexture->aspectFlags, - textureContainer->activeTextureHandle->vulkanTexture->usageFlags, - 0 - ); - - EXPAND_ARRAY_IF_NEEDED( - textureContainer->textureHandles, - VulkanTextureHandle*, - textureContainer->textureCount + 1, - textureContainer->textureCapacity, - textureContainer->textureCapacity * 2 - ); - - textureContainer->textureHandles[ - textureContainer->textureCount - ] = textureContainer->activeTextureHandle; - textureContainer->textureCount += 1; -} - static void VULKAN_SetTransferData( Refresh_Renderer *driverData, void* data, @@ -8550,8 +8577,10 @@ static void VULKAN_SetTransferData( VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; - if (option == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0) - { + if ( + option == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && + SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 + ) { VULKAN_INTERNAL_DiscardActiveBuffer( renderer, transferBufferContainer @@ -8617,8 +8646,11 @@ static void VULKAN_UploadToTexture( VulkanTextureContainer *vulkanTextureContainer = (VulkanTextureContainer*) textureSlice->texture; VkBufferImageCopy imageCopy; - if (option == REFRESH_COPYOPTIONS_SAFEDISCARD && vulkanTextureContainer->canBeDiscarded && 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, vulkanTextureContainer @@ -8688,8 +8720,10 @@ static void VULKAN_UploadToBuffer( VulkanBufferContainer *gpuBufferContainer = (VulkanBufferContainer*) gpuBuffer; VkBufferCopy bufferCopy; - if (option == REFRESH_COPYOPTIONS_SAFEDISCARD && SDL_AtomicGet(&gpuBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0) - { + if ( + option == REFRESH_COPYOPTIONS_SAFEDISCARD && + SDL_AtomicGet(&gpuBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 + ) { VULKAN_INTERNAL_DiscardActiveBuffer( renderer, gpuBufferContainer @@ -8741,8 +8775,10 @@ static void VULKAN_DownloadFromTexture( VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; VkBufferImageCopy imageCopy; - if (option == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0) - { + if ( + option == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && + SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 + ) { VULKAN_INTERNAL_DiscardActiveBuffer( renderer, transferBufferContainer @@ -8812,8 +8848,10 @@ static void VULKAN_DownloadFromBuffer( VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; VkBufferCopy bufferCopy; - if (option == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0) - { + if ( + option == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && + SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 + ) { VULKAN_INTERNAL_DiscardActiveBuffer( renderer, transferBufferContainer @@ -8864,8 +8902,11 @@ static void VULKAN_CopyTextureToTexture( VulkanTextureContainer *dstContainer = (VulkanTextureContainer*) destination->texture; VkImageCopy imageCopy; - if (option == REFRESH_COPYOPTIONS_SAFEDISCARD && dstContainer->canBeDiscarded && SDL_AtomicGet(&dstContainer->activeTextureHandle->vulkanTexture->referenceCount) > 0) - { + if ( + option == REFRESH_COPYOPTIONS_SAFEDISCARD && + dstContainer->canBeDiscarded && + SDL_AtomicGet(&dstContainer->activeTextureHandle->vulkanTexture->referenceCount) > 0 + ) { VULKAN_INTERNAL_DiscardActiveTexture( renderer, dstContainer @@ -8948,8 +8989,10 @@ static void VULKAN_CopyTextureToBuffer( VulkanBufferContainer *bufferContainer = (VulkanBufferContainer*) gpuBuffer; VkBufferImageCopy imageCopy; - if (option == REFRESH_COPYOPTIONS_SAFEDISCARD && SDL_AtomicGet(&bufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0) - { + if ( + option == REFRESH_COPYOPTIONS_SAFEDISCARD && + SDL_AtomicGet(&bufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 + ) { VULKAN_INTERNAL_DiscardActiveBuffer( renderer, bufferContainer @@ -9020,8 +9063,10 @@ static void VULKAN_CopyBufferToTexture( VulkanTextureContainer *textureContainer = (VulkanTextureContainer*) textureSlice->texture; VkBufferImageCopy imageCopy; - if (option == REFRESH_COPYOPTIONS_SAFEDISCARD && textureContainer->canBeDiscarded && SDL_AtomicGet(&textureContainer->activeTextureHandle->vulkanTexture->referenceCount) > 0) - { + if ( + option == REFRESH_COPYOPTIONS_SAFEDISCARD && + textureContainer->canBeDiscarded && SDL_AtomicGet(&textureContainer->activeTextureHandle->vulkanTexture->referenceCount) > 0 + ) { VULKAN_INTERNAL_DiscardActiveTexture( renderer, textureContainer @@ -9092,8 +9137,10 @@ static void VULKAN_CopyBufferToBuffer( VulkanBufferContainer *dstContainer = (VulkanBufferContainer*) destination; VkBufferCopy bufferCopy; - if (option == REFRESH_COPYOPTIONS_SAFEDISCARD && SDL_AtomicGet(&dstContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0) - { + if ( + option == REFRESH_COPYOPTIONS_SAFEDISCARD && + SDL_AtomicGet(&dstContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 + ) { VULKAN_INTERNAL_DiscardActiveBuffer( renderer, dstContainer