From 5b416ffe82c9761a71662205f914ff8ff0a104ed Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 27 Feb 2024 17:04:26 -0800 Subject: [PATCH 01/16] starting on resource rotation --- include/Refresh.h | 51 +++-- src/Refresh.c | 46 ++-- src/Refresh_Driver.h | 28 ++- src/Refresh_Driver_Vulkan.c | 445 ++++++++++++++++++++++-------------- 4 files changed, 352 insertions(+), 218 deletions(-) diff --git a/include/Refresh.h b/include/Refresh.h index adb2aa0..8ad8888 100644 --- a/include/Refresh.h +++ b/include/Refresh.h @@ -327,11 +327,17 @@ typedef enum Refresh_BorderColor REFRESH_BORDERCOLOR_INT_OPAQUE_WHITE } Refresh_BorderColor; -typedef enum Refresh_SetDataOptions +typedef enum Refresh_TransferOptions { - REFRESH_SETDATAOPTIONS_SAFEDISCARD, - REFRESH_SETDATAOPTIONS_OVERWRITE -} Refresh_SetDataOptions; + REFRESH_TRANSFEROPTIONS_SAFEDISCARD, + REFRESH_TRANSFEROPTIONS_OVERWRITE +} Refresh_TransferOptions; + +typedef enum Refresh_CopyOptions +{ + REFRESH_COPYOPTIONS_SAFEDISCARD, + REFRESH_COPYOPTIONS_SAFEOVERWRITE +} Refresh_CopyOptions; typedef enum Refresh_Backend { @@ -1064,16 +1070,16 @@ REFRESHAPI void Refresh_EndComputePass( * Overwrites the data regardless of whether a copy has been issued. * Use this option with great care, as it can cause data races to occur! */ -REFRESHAPI void Refresh_SetData( +REFRESHAPI void Refresh_SetTransferData( Refresh_Device *device, void* data, Refresh_TransferBuffer *transferBuffer, Refresh_BufferCopy *copyParams, - Refresh_SetDataOptions option + Refresh_TransferOptions option ); /* Immediately copies data from a TransferBuffer into a pointer. */ -REFRESHAPI void Refresh_GetData( +REFRESHAPI void Refresh_GetTransferData( Refresh_Device *device, Refresh_TransferBuffer *transferBuffer, void* data, @@ -1093,13 +1099,27 @@ REFRESHAPI void Refresh_BeginCopyPass( * You MAY assume that the copy has finished for subsequent commands. */ +/* + * option: + * SAFEDISCARD: + * If this TransferBuffer has been used in a copy command that has not completed, + * the issued copy commands will still be valid at the cost of increased memory usage. + * Otherwise the data will overwrite. + * It is not recommended to use this option with large resources. + * + * OVERWRITE: + * Overwrites the data regardless of whether a copy has been issued. + * Use this option with great care, as it can cause data races to occur! + */ + /* Uploads data from a TransferBuffer to a texture. */ REFRESHAPI void Refresh_UploadToTexture( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, Refresh_TransferBuffer *transferBuffer, Refresh_TextureSlice *textureSlice, - Refresh_BufferImageCopy *copyParams + Refresh_BufferImageCopy *copyParams, + Refresh_CopyOptions option ); /* Uploads data from a TransferBuffer to a GpuBuffer. */ @@ -1108,7 +1128,8 @@ REFRESHAPI void Refresh_UploadToBuffer( Refresh_CommandBuffer *commandBuffer, Refresh_TransferBuffer *transferBuffer, Refresh_GpuBuffer *gpuBuffer, - Refresh_BufferCopy *copyParams + Refresh_BufferCopy *copyParams, + Refresh_CopyOptions option ); /* GPU-to-CPU copies occur on the GPU timeline. @@ -1144,7 +1165,8 @@ REFRESHAPI void Refresh_CopyTextureToTexture( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, Refresh_TextureSlice *source, - Refresh_TextureSlice *destination + Refresh_TextureSlice *destination, + Refresh_CopyOptions option ); /* Copies image data from a texture slice into a buffer. */ @@ -1153,7 +1175,8 @@ REFRESHAPI void Refresh_CopyTextureToBuffer( Refresh_CommandBuffer *commandBuffer, Refresh_TextureSlice *textureSlice, Refresh_GpuBuffer *gpuBuffer, - Refresh_BufferImageCopy *copyParams + Refresh_BufferImageCopy *copyParams, + Refresh_CopyOptions option ); /* Copies data from a buffer to a texture slice. */ @@ -1162,7 +1185,8 @@ REFRESHAPI void Refresh_CopyBufferToTexture( Refresh_CommandBuffer *commandBuffer, Refresh_GpuBuffer *gpuBuffer, Refresh_TextureSlice *textureSlice, - Refresh_BufferImageCopy *copyParams + Refresh_BufferImageCopy *copyParams, + Refresh_CopyOptions option ); /* Copies data from a buffer to a buffer. */ @@ -1171,7 +1195,8 @@ REFRESHAPI void Refresh_CopyBufferToBuffer( Refresh_CommandBuffer *commandBuffer, Refresh_GpuBuffer *source, Refresh_GpuBuffer *destination, - Refresh_BufferCopy *copyParams + Refresh_BufferCopy *copyParams, + Refresh_CopyOptions option ); /* Generate mipmaps for the given texture. */ diff --git a/src/Refresh.c b/src/Refresh.c index d8f1553..ac170a0 100644 --- a/src/Refresh.c +++ b/src/Refresh.c @@ -732,15 +732,15 @@ void Refresh_EndComputePass( /* TransferBuffer Set/Get */ -void Refresh_SetData( +void Refresh_SetTransferData( Refresh_Device *device, void* data, Refresh_TransferBuffer *transferBuffer, Refresh_BufferCopy *copyParams, - Refresh_SetDataOptions option + Refresh_TransferOptions option ) { NULL_RETURN(device); - device->SetData( + device->SetTransferData( device->driverData, data, transferBuffer, @@ -749,14 +749,14 @@ void Refresh_SetData( ); } -void Refresh_GetData( +void Refresh_GetTransferData( Refresh_Device *device, Refresh_TransferBuffer *transferBuffer, void* data, Refresh_BufferCopy *copyParams ) { NULL_RETURN(device); - device->GetData( + device->GetTransferData( device->driverData, transferBuffer, data, @@ -782,7 +782,8 @@ void Refresh_UploadToTexture( Refresh_CommandBuffer *commandBuffer, Refresh_TransferBuffer *transferBuffer, Refresh_TextureSlice *textureSlice, - Refresh_BufferImageCopy *copyParams + Refresh_BufferImageCopy *copyParams, + Refresh_CopyOptions option ) { NULL_RETURN(device); device->UploadToTexture( @@ -790,7 +791,8 @@ void Refresh_UploadToTexture( commandBuffer, transferBuffer, textureSlice, - copyParams + copyParams, + option ); } @@ -799,7 +801,8 @@ void Refresh_UploadToBuffer( Refresh_CommandBuffer *commandBuffer, Refresh_TransferBuffer *transferBuffer, Refresh_GpuBuffer *gpuBuffer, - Refresh_BufferCopy *copyParams + Refresh_BufferCopy *copyParams, + Refresh_CopyOptions option ) { NULL_RETURN(device); device->UploadToBuffer( @@ -807,7 +810,8 @@ void Refresh_UploadToBuffer( commandBuffer, transferBuffer, gpuBuffer, - copyParams + copyParams, + option ); } @@ -849,14 +853,16 @@ void Refresh_CopyTextureToTexture( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, Refresh_TextureSlice *sourceTextureSlice, - Refresh_TextureSlice *destinationTextureSlice + Refresh_TextureSlice *destinationTextureSlice, + Refresh_CopyOptions option ) { NULL_RETURN(device); device->CopyTextureToTexture( device->driverData, commandBuffer, sourceTextureSlice, - destinationTextureSlice + destinationTextureSlice, + option ); } @@ -865,7 +871,8 @@ void Refresh_CopyTextureToBuffer( Refresh_CommandBuffer *commandBuffer, Refresh_TextureSlice *textureSlice, Refresh_GpuBuffer *gpuBuffer, - Refresh_BufferImageCopy *copyParameters + Refresh_BufferImageCopy *copyParameters, + Refresh_CopyOptions option ) { NULL_RETURN(device); device->CopyTextureToBuffer( @@ -873,7 +880,8 @@ void Refresh_CopyTextureToBuffer( commandBuffer, textureSlice, gpuBuffer, - copyParameters + copyParameters, + option ); } @@ -882,7 +890,8 @@ void Refresh_CopyBufferToTexture( Refresh_CommandBuffer *commandBuffer, Refresh_GpuBuffer *gpuBuffer, Refresh_TextureSlice *textureSlice, - Refresh_BufferImageCopy *copyParams + Refresh_BufferImageCopy *copyParams, + Refresh_CopyOptions option ) { NULL_RETURN(device); device->CopyBufferToTexture( @@ -890,7 +899,8 @@ void Refresh_CopyBufferToTexture( commandBuffer, gpuBuffer, textureSlice, - copyParams + copyParams, + option ); } @@ -899,7 +909,8 @@ void Refresh_CopyBufferToBuffer( Refresh_CommandBuffer *commandBuffer, Refresh_GpuBuffer *source, Refresh_GpuBuffer *destination, - Refresh_BufferCopy *copyParams + Refresh_BufferCopy *copyParams, + Refresh_CopyOptions option ) { NULL_RETURN(device); device->CopyBufferToBuffer( @@ -907,7 +918,8 @@ void Refresh_CopyBufferToBuffer( commandBuffer, source, destination, - copyParams + copyParams, + option ); } diff --git a/src/Refresh_Driver.h b/src/Refresh_Driver.h index e95b63f..7629855 100644 --- a/src/Refresh_Driver.h +++ b/src/Refresh_Driver.h @@ -415,15 +415,15 @@ struct Refresh_Device /* TransferBuffer Set/Get */ - void (*SetData)( + void (*SetTransferData)( Refresh_Renderer *driverData, void* data, Refresh_TransferBuffer *transferBuffer, Refresh_BufferCopy *copyParams, - Refresh_SetDataOptions option + Refresh_TransferOptions option ); - void (*GetData)( + void (*GetTransferData)( Refresh_Renderer *driverData, Refresh_TransferBuffer *transferBuffer, void* data, @@ -442,7 +442,8 @@ struct Refresh_Device Refresh_CommandBuffer *commandBuffer, Refresh_TransferBuffer *transferBuffer, Refresh_TextureSlice *textureSlice, - Refresh_BufferImageCopy *copyParams + Refresh_BufferImageCopy *copyParams, + Refresh_CopyOptions option ); void (*UploadToBuffer)( @@ -450,7 +451,8 @@ struct Refresh_Device Refresh_CommandBuffer *commandBuffer, Refresh_TransferBuffer *transferBuffer, Refresh_GpuBuffer *gpuBuffer, - Refresh_BufferCopy *copyParams + Refresh_BufferCopy *copyParams, + Refresh_CopyOptions option ); void (*DownloadFromTexture)( @@ -473,7 +475,8 @@ struct Refresh_Device Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_TextureSlice *source, - Refresh_TextureSlice *destination + Refresh_TextureSlice *destination, + Refresh_CopyOptions option ); void (*CopyTextureToBuffer)( @@ -481,7 +484,8 @@ struct Refresh_Device Refresh_CommandBuffer *commandBuffer, Refresh_TextureSlice *textureSlice, Refresh_GpuBuffer *gpuBuffer, - Refresh_BufferImageCopy *copyParams + Refresh_BufferImageCopy *copyParams, + Refresh_CopyOptions option ); void (*CopyBufferToTexture)( @@ -489,7 +493,8 @@ struct Refresh_Device Refresh_CommandBuffer *commandBuffer, Refresh_GpuBuffer *gpuBuffer, Refresh_TextureSlice *textureSlice, - Refresh_BufferImageCopy *copyParams + Refresh_BufferImageCopy *copyParams, + Refresh_CopyOptions option ); void (*CopyBufferToBuffer)( @@ -497,7 +502,8 @@ struct Refresh_Device Refresh_CommandBuffer *commandBuffer, Refresh_GpuBuffer *source, Refresh_GpuBuffer *destination, - Refresh_BufferCopy *copyParams + Refresh_BufferCopy *copyParams, + Refresh_CopyOptions option ); void (*GenerateMipmaps)( @@ -622,8 +628,8 @@ struct Refresh_Device ASSIGN_DRIVER_FUNC(PushComputeShaderUniforms, name) \ ASSIGN_DRIVER_FUNC(DispatchCompute, name) \ ASSIGN_DRIVER_FUNC(EndComputePass, name) \ - ASSIGN_DRIVER_FUNC(SetData, name) \ - ASSIGN_DRIVER_FUNC(GetData, name) \ + ASSIGN_DRIVER_FUNC(SetTransferData, name) \ + ASSIGN_DRIVER_FUNC(GetTransferData, name) \ ASSIGN_DRIVER_FUNC(BeginCopyPass, name) \ ASSIGN_DRIVER_FUNC(UploadToTexture, name) \ ASSIGN_DRIVER_FUNC(UploadToBuffer, name) \ diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index 56fc807..57cc0fe 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -695,28 +695,10 @@ static const VulkanResourceAccessInfo AccessMap[RESOURCE_ACCESS_TYPES_COUNT] = /* We use pointer indirection so that defrag can occur without objects * needing to be aware of the backing buffers changing. */ -typedef struct VulkanBufferContainer +typedef struct VulkanBufferHandle { VulkanBuffer *vulkanBuffer; -} VulkanBufferContainer; - -/* TransferBuffers consist of multiple backing buffer containers so that data transfers - * can occur safely without the client having to explicitly manage transfer timing. - */ -typedef struct VulkanTransferBufferContainer /* cast from Refresh_TransferBuffer */ -{ - uint32_t sizeInBytes; - VulkanBufferContainer *activeBuffer; - - /* These are all the buffers that have been used by this container. - * If a buffer is bound and then updated with Discard, a new buffer - * will be added to this list. - * These can be reused after they are submitted and command processing is complete. - */ - uint32_t bufferCapacity; - uint32_t bufferCount; - VulkanBufferContainer **backingBuffers; -} VulkanTransferBufferContainer; +} VulkanBufferHandle; struct VulkanBuffer { @@ -729,15 +711,34 @@ struct VulkanBuffer uint8_t requireHostVisible; uint8_t preferDeviceLocal; uint8_t preferHostLocal; - uint8_t preserveContentsOnDefrag; SDL_atomic_t referenceCount; /* Tracks command buffer usage */ - VulkanBufferContainer *container; + VulkanBufferHandle *handle; uint8_t markedForDestroy; /* so that defrag doesn't double-free */ }; +/* Buffer resources consist of multiple backing buffer handles so that data transfers + * can occur without blocking or the client having to manage extra resources. + * + * Cast from Refresh_GpuBuffer or Refresh_TransferBuffer. + */ +typedef struct VulkanBufferContainer +{ + VulkanBufferHandle *activeBufferHandle; + + /* These are all the buffer handles that have been used by this container. + * If the resource is bound and then updated with SafeDiscard, a new resource + * will be added to this list. + * These can be reused after they are submitted and command processing is complete. + */ + uint32_t bufferCapacity; + uint32_t bufferCount; + VulkanBufferHandle **bufferHandles; + +} VulkanBufferContainer; + typedef enum VulkanUniformBufferType { UNIFORM_BUFFER_VERTEX, @@ -777,10 +778,10 @@ typedef struct VulkanShaderModule SDL_atomic_t referenceCount; } VulkanShaderModule; -typedef struct VulkanTextureContainer /* Cast from Refresh_Texture */ +typedef struct VulkanTextureHandle { VulkanTexture *vulkanTexture; -} VulkanTextureContainer; +} VulkanTextureHandle; struct VulkanTexture { @@ -803,15 +804,34 @@ struct VulkanTexture VkImageAspectFlags aspectFlags; - struct VulkanTexture *msaaTex; + struct VulkanTexture *msaaTex; /* doesn't need to be a handle because render targets are dedicated */ SDL_atomic_t referenceCount; - VulkanTextureContainer *container; + VulkanTextureHandle *handle; uint8_t markedForDestroy; /* so that defrag doesn't double-free */ }; +/* Texture resources consist of multiple backing texture handles so that data transfers + * can occur without blocking or the client having to manage extra resources. + * + * Cast from Refresh_Texture. + */ +typedef struct VulkanTextureContainer +{ + VulkanTextureHandle *activeTextureHandle; + + /* These are all the texture handles that have been used by this container. + * If the resource is bound and then updated with SafeDiscard, a new resource + * will be added to this list. + * These can be reused after they are submitted and command processing is complete. + */ + uint32_t textureCapacity; + uint32_t textureCount; + VulkanTextureHandle **textureHandles; +} VulkanTextureContainer; + typedef struct VulkanRenderTarget { VkImageView view; @@ -837,7 +857,7 @@ typedef struct VulkanSwapchainData /* Swapchain images */ VkExtent2D extent; - VulkanTextureContainer *textureContainers; + VulkanTextureHandle *textureContainers; uint32_t imageCount; /* Synchronization primitives */ @@ -4195,8 +4215,7 @@ static VulkanBuffer* VULKAN_INTERNAL_CreateBuffer( uint8_t requireHostVisible, uint8_t preferHostLocal, uint8_t preferDeviceLocal, - uint8_t dedicatedAllocation, - uint8_t preserveContentsOnDefrag + uint8_t dedicatedAllocation ) { VulkanBuffer* buffer; VkResult vulkanResult; @@ -4211,7 +4230,6 @@ static VulkanBuffer* VULKAN_INTERNAL_CreateBuffer( buffer->requireHostVisible = requireHostVisible; buffer->preferHostLocal = preferHostLocal; buffer->preferDeviceLocal = preferDeviceLocal; - buffer->preserveContentsOnDefrag = preserveContentsOnDefrag; buffer->markedForDestroy = 0; bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; @@ -4253,7 +4271,7 @@ static VulkanBuffer* VULKAN_INTERNAL_CreateBuffer( } buffer->usedRegion->vulkanBuffer = buffer; /* lol */ - buffer->container = NULL; + buffer->handle = NULL; buffer->resourceAccessType = resourceAccessType; @@ -4304,7 +4322,6 @@ static VulkanUniformBufferObject* VULKAN_INTERNAL_CreateUniformBufferObject( 1, 0, 1, - 1, 1 ); @@ -4350,18 +4367,16 @@ static VulkanUniformBufferObject* VULKAN_INTERNAL_CreateUniformBufferObject( } /* Indirection so we can cleanly defrag buffers */ -static VulkanBufferContainer* VULKAN_INTERNAL_CreateBufferContainer( +static VulkanBufferHandle* VULKAN_INTERNAL_CreateBufferHandle( VulkanRenderer *renderer, uint32_t sizeInBytes, VulkanResourceAccessType resourceAccessType, VkBufferUsageFlags usageFlags, uint8_t requireHostVisible, uint8_t preferHostLocal, - uint8_t preferDeviceLocal, - uint8_t dedicatedAllocation, - uint8_t preserveContentsOnDefrag + uint8_t preferDeviceLocal ) { - VulkanBufferContainer* bufferContainer; + VulkanBufferHandle* bufferHandle; VulkanBuffer* buffer; /* always set transfer bits so we can defrag */ @@ -4375,8 +4390,7 @@ static VulkanBufferContainer* VULKAN_INTERNAL_CreateBufferContainer( requireHostVisible, preferHostLocal, preferDeviceLocal, - dedicatedAllocation, - preserveContentsOnDefrag + 0 ); if (buffer == NULL) @@ -4385,11 +4399,53 @@ static VulkanBufferContainer* VULKAN_INTERNAL_CreateBufferContainer( return NULL; } - bufferContainer = SDL_malloc(sizeof(VulkanBufferContainer)); - bufferContainer->vulkanBuffer = buffer; - buffer->container = bufferContainer; + bufferHandle = SDL_malloc(sizeof(VulkanBufferHandle)); + bufferHandle->vulkanBuffer = buffer; + buffer->handle = bufferHandle; - return (VulkanBufferContainer*) bufferContainer; + return bufferHandle; +} + +static VulkanBufferContainer* VULKAN_INTERNAL_CreateBufferContainer( + VulkanRenderer *renderer, + uint32_t sizeInBytes, + VulkanResourceAccessType resourceAccessType, + VkBufferUsageFlags usageFlags, + uint8_t requireHostVisible, + uint8_t preferHostLocal, + uint8_t preferDeviceLocal +) { + VulkanBufferContainer *bufferContainer; + VulkanBufferHandle *bufferHandle; + + bufferHandle = VULKAN_INTERNAL_CreateBufferHandle( + renderer, + sizeInBytes, + resourceAccessType, + usageFlags, + requireHostVisible, + preferHostLocal, + preferDeviceLocal + ); + + if (bufferHandle == NULL) + { + Refresh_LogError("Failed to create buffer container!"); + return NULL; + } + + bufferContainer = SDL_malloc(sizeof(VulkanBufferContainer)); + + bufferContainer->activeBufferHandle = bufferHandle; + + bufferContainer->bufferCapacity = 1; + bufferContainer->bufferCount = 1; + bufferContainer->bufferHandles = SDL_malloc( + bufferContainer->bufferCapacity * sizeof(VulkanBufferHandle*) + ); + bufferContainer->bufferHandles[0] = bufferContainer->activeBufferHandle; + + return bufferContainer; } static void VULKAN_INTERNAL_DestroyUniformBufferObject( @@ -4861,7 +4917,7 @@ static uint8_t VULKAN_INTERNAL_CreateSwapchain( ); swapchainData->textureContainers = SDL_malloc( - sizeof(VulkanTextureContainer) * swapchainData->imageCount + sizeof(VulkanTextureHandle) * swapchainData->imageCount ); if (!swapchainData->textureContainers) @@ -4935,6 +4991,7 @@ static uint8_t VULKAN_INTERNAL_CreateSwapchain( 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; @@ -5385,7 +5442,7 @@ static void VULKAN_DrawPrimitivesIndirect( ) { VulkanRenderer* renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer*) gpuBuffer)->vulkanBuffer; + VulkanBuffer *vulkanBuffer = ((VulkanBufferHandle*) gpuBuffer)->vulkanBuffer; VkDescriptorSet descriptorSets[4]; uint32_t dynamicOffsets[2]; @@ -5701,7 +5758,7 @@ static VkRenderPass VULKAN_INTERNAL_CreateRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { - texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->vulkanTexture; + texture = ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture; if (texture->msaaTex != NULL) { @@ -5824,7 +5881,7 @@ static VkRenderPass VULKAN_INTERNAL_CreateRenderPass( } else { - texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->vulkanTexture; + texture = ((VulkanTextureHandle*) depthStencilAttachmentInfo->texture)->vulkanTexture; attachmentDescriptions[attachmentDescriptionCount].flags = 0; attachmentDescriptions[attachmentDescriptionCount].format = texture->format; @@ -6719,6 +6776,7 @@ static Refresh_Texture* VULKAN_CreateTexture( uint8_t isDepthFormat = IsRefreshDepthFormat(textureCreateInfo->format); VkFormat format; VulkanTextureContainer *container; + VulkanTextureHandle *textureHandle; VulkanTexture *vulkanTexture; if (isDepthFormat) @@ -6764,6 +6822,7 @@ static Refresh_Texture* VULKAN_CreateTexture( imageAspectFlags = VK_IMAGE_ASPECT_COLOR_BIT; } + /* FIXME: what if this fails? */ vulkanTexture = VULKAN_INTERNAL_CreateTexture( renderer, textureCreateInfo->width, @@ -6784,6 +6843,7 @@ static Refresh_Texture* VULKAN_CreateTexture( !isDepthFormat && textureCreateInfo->sampleCount > REFRESH_SAMPLECOUNT_1 ) { + /* FIXME: what if this fails? */ vulkanTexture->msaaTex = VULKAN_INTERNAL_CreateTexture( renderer, textureCreateInfo->width, @@ -6798,9 +6858,18 @@ static Refresh_Texture* VULKAN_CreateTexture( ); } + textureHandle = SDL_malloc(sizeof(VulkanTextureHandle)); + textureHandle->vulkanTexture = vulkanTexture; + vulkanTexture->handle = textureHandle; + container = SDL_malloc(sizeof(VulkanTextureContainer)); - container->vulkanTexture = vulkanTexture; - vulkanTexture->container = container; + + container->activeTextureHandle = textureHandle; + container->textureCapacity = 1; + container->textureCount =1 ; + container->textureHandles = SDL_malloc( + container->textureCapacity * sizeof(VulkanTextureHandle*) + ); return (Refresh_Texture*) container; } @@ -6850,8 +6919,6 @@ static Refresh_GpuBuffer* VULKAN_CreateGpuBuffer( vulkanUsageFlags, 0, 0, - 1, - 0, 1 ); } @@ -6860,32 +6927,15 @@ static Refresh_TransferBuffer* VULKAN_CreateTransferBuffer( Refresh_Renderer *driverData, uint32_t sizeInBytes ) { - VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VkBufferUsageFlags vulkanUsageFlags = - VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; - VulkanTransferBufferContainer *transferBufferContainer = (VulkanTransferBufferContainer*) SDL_malloc(sizeof(VulkanTransferBufferContainer)); - - transferBufferContainer->sizeInBytes = sizeInBytes; - transferBufferContainer->activeBuffer = VULKAN_INTERNAL_CreateBufferContainer( - renderer, + return (Refresh_TransferBuffer*) VULKAN_INTERNAL_CreateBufferContainer( + (VulkanRenderer*) driverData, sizeInBytes, RESOURCE_ACCESS_NONE, - vulkanUsageFlags, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, 1, 1, - 0, - 0, 0 ); - - transferBufferContainer->bufferCapacity = 1; - transferBufferContainer->bufferCount = 1; - transferBufferContainer->backingBuffers = SDL_malloc( - transferBufferContainer->bufferCapacity * sizeof(VulkanBufferContainer*) - ); - transferBufferContainer->backingBuffers[0] = transferBufferContainer->activeBuffer; - - return (Refresh_TransferBuffer*) transferBufferContainer; } /* Setters */ @@ -7150,7 +7200,7 @@ static void VULKAN_BindVertexSamplers( for (i = 0; i < samplerCount; i += 1) { - currentTexture = ((VulkanTextureContainer*) pTextures[i])->vulkanTexture; + currentTexture = ((VulkanTextureHandle*) pTextures[i])->vulkanTexture; currentSampler = (VulkanSampler*) pSamplers[i]; descriptorImageInfos[i].imageView = currentTexture->view; descriptorImageInfos[i].sampler = currentSampler->sampler; @@ -7193,7 +7243,7 @@ static void VULKAN_BindFragmentSamplers( for (i = 0; i < samplerCount; i += 1) { - currentTexture = ((VulkanTextureContainer*) pTextures[i])->vulkanTexture; + currentTexture = ((VulkanTextureHandle*) pTextures[i])->vulkanTexture; currentSampler = (VulkanSampler*) pSamplers[i]; descriptorImageInfos[i].imageView = currentTexture->view; descriptorImageInfos[i].sampler = currentSampler->sampler; @@ -7243,7 +7293,7 @@ static void VULKAN_QueueDestroyTexture( Refresh_Texture *texture ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VulkanTextureContainer *vulkanTextureContainer = (VulkanTextureContainer *)texture; + VulkanTextureHandle *vulkanTextureContainer = (VulkanTextureHandle *)texture; VulkanTexture *vulkanTexture = vulkanTextureContainer->vulkanTexture; SDL_LockMutex(renderer->disposeLock); @@ -7310,7 +7360,7 @@ static void VULKAN_QueueDestroyGpuBuffer( Refresh_GpuBuffer *gpuBuffer ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VulkanBufferContainer *vulkanBufferContainer = (VulkanBufferContainer*) gpuBuffer; + VulkanBufferHandle *vulkanBufferContainer = (VulkanBufferHandle*) gpuBuffer; VulkanBuffer *vulkanBuffer = vulkanBufferContainer->vulkanBuffer; SDL_LockMutex(renderer->disposeLock); @@ -7328,19 +7378,19 @@ static void VULKAN_QueueDestroyTransferBuffer( Refresh_TransferBuffer *transferBuffer ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VulkanTransferBufferContainer *transferBufferContainer = (VulkanTransferBufferContainer*) transferBuffer; + VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; uint32_t i; SDL_LockMutex(renderer->disposeLock); for (i = 0; i < transferBufferContainer->bufferCount; i += 1) { - VULKAN_INTERNAL_QueueDestroyBuffer(renderer, transferBufferContainer->backingBuffers[i]->vulkanBuffer); - SDL_free(transferBufferContainer->backingBuffers[i]); + VULKAN_INTERNAL_QueueDestroyBuffer(renderer, transferBufferContainer->bufferHandles[i]->vulkanBuffer); + SDL_free(transferBufferContainer->bufferHandles[i]); } /* Containers are just client handles, so we can free immediately */ - SDL_free(transferBufferContainer->backingBuffers); + SDL_free(transferBufferContainer->bufferHandles); SDL_free(transferBufferContainer); SDL_UnlockMutex(renderer->disposeLock); @@ -7433,7 +7483,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { - hash.colorTargetDescriptions[i].format = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->vulkanTexture->format; + hash.colorTargetDescriptions[i].format = ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture->format; hash.colorTargetDescriptions[i].clearColor = colorAttachmentInfos[i].clearColor; hash.colorTargetDescriptions[i].loadOp = colorAttachmentInfos[i].loadOp; hash.colorTargetDescriptions[i].storeOp = colorAttachmentInfos[i].storeOp; @@ -7442,7 +7492,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass( hash.colorAttachmentSampleCount = REFRESH_SAMPLECOUNT_1; if (colorAttachmentCount > 0) { - texture = ((VulkanTextureContainer*) colorAttachmentInfos[0].texture)->vulkanTexture; + texture = ((VulkanTextureHandle*) colorAttachmentInfos[0].texture)->vulkanTexture; if (texture->msaaTex != NULL) { hash.colorAttachmentSampleCount = texture->msaaTex->sampleCount; @@ -7461,7 +7511,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass( } else { - hash.depthStencilTargetDescription.format = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->vulkanTexture->format; + hash.depthStencilTargetDescription.format = ((VulkanTextureHandle*) depthStencilAttachmentInfo->texture)->vulkanTexture->format; hash.depthStencilTargetDescription.loadOp = depthStencilAttachmentInfo->loadOp; hash.depthStencilTargetDescription.storeOp = depthStencilAttachmentInfo->storeOp; hash.depthStencilTargetDescription.stencilLoadOp = depthStencilAttachmentInfo->stencilLoadOp; @@ -7529,7 +7579,7 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( for (i = 0; i < colorAttachmentCount; i += 1) { - texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->vulkanTexture; + texture = ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture; renderTarget = VULKAN_INTERNAL_FetchRenderTarget( renderer, @@ -7565,7 +7615,7 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( } else { - texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->vulkanTexture; + texture = ((VulkanTextureHandle*) depthStencilAttachmentInfo->texture)->vulkanTexture; renderTarget = VULKAN_INTERNAL_FetchRenderTarget( renderer, texture, @@ -7601,7 +7651,7 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( for (i = 0; i < colorAttachmentCount; i += 1) { - texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->vulkanTexture; + texture = ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture; renderTarget = VULKAN_INTERNAL_FetchRenderTarget( renderer, @@ -7635,7 +7685,7 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( if (depthStencilAttachmentInfo != NULL) { - texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->vulkanTexture; + texture = ((VulkanTextureHandle*) depthStencilAttachmentInfo->texture)->vulkanTexture; renderTarget = VULKAN_INTERNAL_FetchRenderTarget( renderer, texture, @@ -7783,7 +7833,7 @@ static void VULKAN_BeginRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { - texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->vulkanTexture; + texture = ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture; w = texture->dimensions.width >> colorAttachmentInfos[i].level; h = texture->dimensions.height >> colorAttachmentInfos[i].level; @@ -7800,7 +7850,7 @@ static void VULKAN_BeginRenderPass( if (depthStencilAttachmentInfo != NULL) { - texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->vulkanTexture; + texture = ((VulkanTextureHandle*) depthStencilAttachmentInfo->texture)->vulkanTexture; w = texture->dimensions.width >> depthStencilAttachmentInfo->level; h = texture->dimensions.height >> depthStencilAttachmentInfo->level; @@ -7841,7 +7891,7 @@ static void VULKAN_BeginRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { - texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->vulkanTexture; + texture = ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture; VULKAN_INTERNAL_ImageMemoryBarrier( renderer, @@ -7868,7 +7918,7 @@ static void VULKAN_BeginRenderPass( if (depthStencilAttachmentInfo != NULL) { - texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->vulkanTexture; + texture = ((VulkanTextureHandle*) depthStencilAttachmentInfo->texture)->vulkanTexture; depthAspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT; if (IsStencilFormat(texture->format)) @@ -7908,7 +7958,7 @@ static void VULKAN_BeginRenderPass( clearValues[i].color.float32[2] = colorAttachmentInfos[i].clearColor.z; clearValues[i].color.float32[3] = colorAttachmentInfos[i].clearColor.w; - texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->vulkanTexture; + texture = ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture; if (texture->msaaTex != NULL) { clearValues[i+1].color.float32[0] = colorAttachmentInfos[i].clearColor.x; @@ -7950,13 +8000,13 @@ static void VULKAN_BeginRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { vulkanCommandBuffer->renderPassColorTargetTextures[i] = - ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->vulkanTexture; + ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture; } vulkanCommandBuffer->renderPassColorTargetCount = colorAttachmentCount; if (depthStencilAttachmentInfo != NULL) { - vulkanCommandBuffer->renderPassDepthTexture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->vulkanTexture; + vulkanCommandBuffer->renderPassDepthTexture = ((VulkanTextureHandle*) depthStencilAttachmentInfo->texture)->vulkanTexture; } /* Set sensible default viewport state */ @@ -8124,7 +8174,7 @@ static void VULKAN_BindVertexBuffers( for (i = 0; i < bindingCount; i += 1) { - currentVulkanBuffer = ((VulkanBufferContainer*) pBuffers[i])->vulkanBuffer; + currentVulkanBuffer = ((VulkanBufferHandle*) pBuffers[i])->vulkanBuffer; buffers[i] = currentVulkanBuffer->buffer; VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, currentVulkanBuffer); } @@ -8149,7 +8199,7 @@ static void VULKAN_BindIndexBuffer( ) { VulkanRenderer* renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanBuffer* vulkanBuffer = ((VulkanBufferContainer*) gpuBuffer)->vulkanBuffer; + VulkanBuffer* vulkanBuffer = ((VulkanBufferHandle*) gpuBuffer)->vulkanBuffer; VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanBuffer); @@ -8222,7 +8272,7 @@ static void VULKAN_BindComputeBuffers( for (i = 0; i < computePipeline->pipelineLayout->bufferDescriptorSetCache->bindingCount; i += 1) { - currentVulkanBuffer = ((VulkanBufferContainer*) pBuffers[i])->vulkanBuffer; + currentVulkanBuffer = ((VulkanBufferHandle*) pBuffers[i])->vulkanBuffer; descriptorBufferInfos[i].buffer = currentVulkanBuffer->buffer; descriptorBufferInfos[i].offset = 0; @@ -8270,7 +8320,7 @@ static void VULKAN_BindComputeTextures( for (i = 0; i < computePipeline->pipelineLayout->imageDescriptorSetCache->bindingCount; i += 1) { - currentTexture = ((VulkanTextureContainer*) pTextures[i])->vulkanTexture; + currentTexture = ((VulkanTextureHandle*) pTextures[i])->vulkanTexture; descriptorImageInfos[i].imageView = currentTexture->view; descriptorImageInfos[i].sampler = VK_NULL_HANDLE; descriptorImageInfos[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; @@ -8406,74 +8456,107 @@ static void VULKAN_EndComputePass( vulkanCommandBuffer->currentComputePipeline = NULL; } -static void VULKAN_INTERNAL_DiscardActiveTransferBuffer( +static void VULKAN_INTERNAL_DiscardActiveBuffer( VulkanRenderer *renderer, - VulkanTransferBufferContainer *transferBufferContainer + VulkanBufferContainer *bufferContainer ) { - VulkanBufferContainer *transferBuffer; + VulkanBufferHandle *bufferHandle; uint32_t i; - transferBufferContainer->activeBuffer->vulkanBuffer->preserveContentsOnDefrag = 0; - /* If a previously-discarded buffer is available, we can use that. */ - for (i = 0; i < transferBufferContainer->bufferCount; i += 1) + for (i = 0; i < bufferContainer->bufferCount; i += 1) { - transferBuffer = transferBufferContainer->backingBuffers[i]; - if (SDL_AtomicGet(&transferBuffer->vulkanBuffer->referenceCount) == 0) + bufferHandle = bufferContainer->bufferHandles[i]; + if (SDL_AtomicGet(&bufferHandle->vulkanBuffer->referenceCount) == 0) { - transferBufferContainer->activeBuffer = transferBuffer; + bufferContainer->activeBufferHandle = bufferHandle; return; } } - /* No buffer is available, generate a new one. */ - transferBufferContainer->activeBuffer = VULKAN_INTERNAL_CreateBufferContainer( + /* No buffer handle is available, generate a new one. */ + bufferContainer->activeBufferHandle = VULKAN_INTERNAL_CreateBufferHandle( renderer, - transferBufferContainer->sizeInBytes, + bufferContainer->activeBufferHandle->vulkanBuffer->size, RESOURCE_ACCESS_NONE, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - 1, - 1, - 0, - 0, - 0 + bufferContainer->activeBufferHandle->vulkanBuffer->usage, + bufferContainer->activeBufferHandle->vulkanBuffer->requireHostVisible, + bufferContainer->activeBufferHandle->vulkanBuffer->preferHostLocal, + bufferContainer->activeBufferHandle->vulkanBuffer->preferDeviceLocal ); EXPAND_ARRAY_IF_NEEDED( - transferBufferContainer->backingBuffers, - VulkanBufferContainer*, - transferBufferContainer->bufferCount + 1, - transferBufferContainer->bufferCapacity, - transferBufferContainer->bufferCapacity * 2 + bufferContainer->bufferHandles, + VulkanBufferHandle*, + bufferContainer->bufferCount + 1, + bufferContainer->bufferCapacity, + bufferContainer->bufferCapacity * 2 ); - transferBufferContainer->backingBuffers[ - transferBufferContainer->bufferCount - ] = transferBufferContainer->activeBuffer; - transferBufferContainer->bufferCount += 1; + bufferContainer->bufferHandles[ + bufferContainer->bufferCount + ] = bufferContainer->activeBufferHandle; + bufferContainer->bufferCount += 1; } -static void VULKAN_SetData( +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_CreateTexture( + + ); + + 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, Refresh_TransferBuffer *transferBuffer, Refresh_BufferCopy *copyParams, - Refresh_SetDataOptions option + Refresh_TransferOptions option ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VulkanTransferBufferContainer *transferBufferContainer = (VulkanTransferBufferContainer*) transferBuffer; + VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; - if (option == REFRESH_SETDATAOPTIONS_SAFEDISCARD && SDL_AtomicGet(&transferBufferContainer->activeBuffer->vulkanBuffer->referenceCount) > 0) + if (option == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0) { - VULKAN_INTERNAL_DiscardActiveTransferBuffer( + VULKAN_INTERNAL_DiscardActiveBuffer( renderer, transferBufferContainer ); } uint8_t *bufferPointer = - transferBufferContainer->activeBuffer->vulkanBuffer->usedRegion->allocation->mapPointer + - transferBufferContainer->activeBuffer->vulkanBuffer->usedRegion->resourceOffset + + transferBufferContainer->activeBufferHandle->vulkanBuffer->usedRegion->allocation->mapPointer + + transferBufferContainer->activeBufferHandle->vulkanBuffer->usedRegion->resourceOffset + copyParams->dstOffset; SDL_memcpy( @@ -8483,15 +8566,15 @@ static void VULKAN_SetData( ); } -static void VULKAN_GetData( +static void VULKAN_GetTransferData( Refresh_Renderer *driverData, Refresh_TransferBuffer *transferBuffer, void* data, Refresh_BufferCopy *copyParams ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VulkanTransferBufferContainer *transferBufferContainer = (VulkanTransferBufferContainer*) transferBuffer; - VulkanBuffer *vulkanBuffer = transferBufferContainer->activeBuffer->vulkanBuffer; + VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; + VulkanBuffer *vulkanBuffer = transferBufferContainer->activeBufferHandle->vulkanBuffer; uint8_t *bufferPointer = vulkanBuffer->usedRegion->allocation->mapPointer + @@ -8503,8 +8586,6 @@ static void VULKAN_GetData( bufferPointer, copyParams->size ); - - vulkanBuffer->preserveContentsOnDefrag = 0; } static void VULKAN_BeginCopyPass( @@ -8523,33 +8604,42 @@ static void VULKAN_UploadToTexture( Refresh_CommandBuffer *commandBuffer, Refresh_TransferBuffer *transferBuffer, Refresh_TextureSlice *textureSlice, - Refresh_BufferImageCopy *copyParams + Refresh_BufferImageCopy *copyParams, + Refresh_CopyOptions option ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTransferBufferContainer *transferBufferContainer = (VulkanTransferBufferContainer*) transferBuffer; - VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) textureSlice->texture)->vulkanTexture; + VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; + VulkanTextureContainer *vulkanTextureContainer = (VulkanTextureContainer*) textureSlice->texture; VkBufferImageCopy imageCopy; + if (option == REFRESH_COPYOPTIONS_SAFEDISCARD && SDL_AtomicGet(&vulkanTextureContainer->activeTextureHandle->vulkanTexture->referenceCount) > 0) + { + VULKAN_INTERNAL_DiscardActiveTexture( + renderer, + vulkanTextureContainer + ); + } + VULKAN_INTERNAL_BufferMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_READ, - transferBufferContainer->activeBuffer->vulkanBuffer + transferBufferContainer->activeBufferHandle->vulkanBuffer ); VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_WRITE, - vulkanTexture->aspectFlags, + vulkanTextureContainer->activeTextureHandle->vulkanTexture->aspectFlags, 0, - vulkanTexture->layerCount, + vulkanTextureContainer->activeTextureHandle->vulkanTexture->layerCount, 0, - vulkanTexture->levelCount, + vulkanTextureContainer->activeTextureHandle->vulkanTexture->levelCount, 0, - vulkanTexture->image, - &vulkanTexture->resourceAccessType + vulkanTextureContainer->activeTextureHandle->vulkanTexture->image, + &vulkanTextureContainer->activeTextureHandle->vulkanTexture->resourceAccessType ); imageCopy.imageExtent.width = textureSlice->w; @@ -8558,7 +8648,7 @@ static void VULKAN_UploadToTexture( imageCopy.imageOffset.x = textureSlice->x; imageCopy.imageOffset.y = textureSlice->y; imageCopy.imageOffset.z = textureSlice->z; - imageCopy.imageSubresource.aspectMask = vulkanTexture->aspectFlags; + imageCopy.imageSubresource.aspectMask = vulkanTextureContainer->activeTextureHandle->vulkanTexture->aspectFlags; imageCopy.imageSubresource.baseArrayLayer = textureSlice->baseLayer; imageCopy.imageSubresource.layerCount = textureSlice->layerCount; imageCopy.imageSubresource.mipLevel = textureSlice->mipLevel; @@ -8568,16 +8658,16 @@ static void VULKAN_UploadToTexture( renderer->vkCmdCopyBufferToImage( vulkanCommandBuffer->commandBuffer, - transferBufferContainer->activeBuffer->vulkanBuffer->buffer, - vulkanTexture->image, - AccessMap[vulkanTexture->resourceAccessType].imageLayout, + transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer, + vulkanTextureContainer->activeTextureHandle->vulkanTexture->image, + AccessMap[vulkanTextureContainer->activeTextureHandle->vulkanTexture->resourceAccessType].imageLayout, 1, &imageCopy ); - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBuffer->vulkanBuffer); - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTexture); - VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, vulkanTexture); + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer); + VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTextureContainer->activeTextureHandle->vulkanTexture); + VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, vulkanTextureContainer->activeTextureHandle->vulkanTexture); } static void VULKAN_UploadToBuffer( @@ -8585,19 +8675,20 @@ static void VULKAN_UploadToBuffer( Refresh_CommandBuffer *commandBuffer, Refresh_TransferBuffer *transferBuffer, Refresh_GpuBuffer *gpuBuffer, - Refresh_BufferCopy *copyParams + Refresh_BufferCopy *copyParams, + Refresh_CopyOptions option ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTransferBufferContainer *transferBufferContainer = (VulkanTransferBufferContainer*) transferBuffer; - VulkanBuffer *vulkanGpuBuffer = ((VulkanBufferContainer*) gpuBuffer)->vulkanBuffer; + VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; + VulkanBuffer *vulkanGpuBuffer = ((VulkanBufferHandle*) gpuBuffer)->vulkanBuffer; VkBufferCopy bufferCopy; VULKAN_INTERNAL_BufferMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_READ, - transferBufferContainer->activeBuffer->vulkanBuffer + transferBufferContainer->activeBufferHandle->vulkanBuffer ); VULKAN_INTERNAL_BufferMemoryBarrier( @@ -8613,13 +8704,13 @@ static void VULKAN_UploadToBuffer( renderer->vkCmdCopyBuffer( vulkanCommandBuffer->commandBuffer, - transferBufferContainer->activeBuffer->vulkanBuffer->buffer, + transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer, vulkanGpuBuffer->buffer, 1, &bufferCopy ); - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBuffer->vulkanBuffer); + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer); VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanGpuBuffer); VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, vulkanGpuBuffer); } @@ -8633,7 +8724,7 @@ static void VULKAN_DownloadFromTexture( ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) textureSlice->texture)->vulkanTexture; + VulkanTexture *vulkanTexture = ((VulkanTextureHandle*) textureSlice->texture)->vulkanTexture; VulkanTransferBufferContainer *transferBufferContainer = (VulkanTransferBufferContainer*) transferBuffer; VkBufferImageCopy imageCopy; @@ -8698,7 +8789,7 @@ static void VULKAN_DownloadFromBuffer( VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanTransferBufferContainer *transferBufferContainer = (VulkanTransferBufferContainer*) transferBuffer; - VulkanBuffer *vulkanGpuBuffer = ((VulkanBufferContainer*) gpuBuffer)->vulkanBuffer; + VulkanBuffer *vulkanGpuBuffer = ((VulkanBufferHandle*) gpuBuffer)->vulkanBuffer; VkBufferCopy bufferCopy; VULKAN_INTERNAL_BufferMemoryBarrier( @@ -8742,8 +8833,8 @@ static void VULKAN_CopyTextureToTexture( ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTexture *srcTexture = ((VulkanTextureContainer*) source->texture)->vulkanTexture; - VulkanTexture *dstTexture = ((VulkanTextureContainer*) destination->texture)->vulkanTexture; + VulkanTexture *srcTexture = ((VulkanTextureHandle*) source->texture)->vulkanTexture; + VulkanTexture *dstTexture = ((VulkanTextureHandle*) destination->texture)->vulkanTexture; VkImageCopy imageCopy; VULKAN_INTERNAL_ImageMemoryBarrier( @@ -8817,8 +8908,8 @@ static void VULKAN_CopyTextureToBuffer( ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) textureSlice->texture)->vulkanTexture; - VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer*) gpuBuffer)->vulkanBuffer; + VulkanTexture *vulkanTexture = ((VulkanTextureHandle*) textureSlice->texture)->vulkanTexture; + VulkanBuffer *vulkanBuffer = ((VulkanBufferHandle*) gpuBuffer)->vulkanBuffer; VkBufferImageCopy imageCopy; VULKAN_INTERNAL_ImageMemoryBarrier( @@ -8880,8 +8971,8 @@ static void VULKAN_CopyBufferToTexture( ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer*) gpuBuffer)->vulkanBuffer; - VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) textureSlice->texture)->vulkanTexture; + VulkanBuffer *vulkanBuffer = ((VulkanBufferHandle*) gpuBuffer)->vulkanBuffer; + VulkanTexture *vulkanTexture = ((VulkanTextureHandle*) textureSlice->texture)->vulkanTexture; VkBufferImageCopy imageCopy; VULKAN_INTERNAL_BufferMemoryBarrier( @@ -8943,8 +9034,8 @@ static void VULKAN_CopyBufferToBuffer( ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanBuffer *vulkanSrcBuffer = ((VulkanBufferContainer*) source)->vulkanBuffer; - VulkanBuffer *vulkanDstBuffer = ((VulkanBufferContainer*) destination)->vulkanBuffer; + VulkanBuffer *vulkanSrcBuffer = ((VulkanBufferHandle*) source)->vulkanBuffer; + VulkanBuffer *vulkanDstBuffer = ((VulkanBufferHandle*) destination)->vulkanBuffer; VkBufferCopy bufferCopy; VULKAN_INTERNAL_BufferMemoryBarrier( @@ -8986,7 +9077,7 @@ static void VULKAN_GenerateMipmaps( ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) texture)->vulkanTexture; + VulkanTexture *vulkanTexture = ((VulkanTextureHandle*) texture)->vulkanTexture; VulkanResourceAccessType *levelAccessType; VkImageBlit blit; uint32_t level; @@ -9544,7 +9635,7 @@ static Refresh_Texture* VULKAN_AcquireSwapchainTexture( WindowData *windowData; VulkanSwapchainData *swapchainData; VkResult acquireResult = VK_SUCCESS; - VulkanTextureContainer *swapchainTextureContainer = NULL; + VulkanTextureHandle *swapchainTextureContainer = NULL; VulkanPresentData *presentData; windowData = VULKAN_INTERNAL_FetchWindowData(windowHandle); @@ -10348,11 +10439,11 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory( } /* re-point original container to new buffer */ - if (currentRegion->vulkanBuffer->container != NULL) + if (currentRegion->vulkanBuffer->handle != NULL) { - newBuffer->container = currentRegion->vulkanBuffer->container; - newBuffer->container->vulkanBuffer = newBuffer; - currentRegion->vulkanBuffer->container = NULL; + newBuffer->handle = currentRegion->vulkanBuffer->handle; + newBuffer->handle->vulkanBuffer = newBuffer; + currentRegion->vulkanBuffer->handle = NULL; } VULKAN_INTERNAL_QueueDestroyBuffer(renderer, currentRegion->vulkanBuffer); @@ -10464,9 +10555,9 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory( } /* re-point original container to new texture */ - newTexture->container = currentRegion->vulkanTexture->container; - newTexture->container->vulkanTexture = newTexture; - currentRegion->vulkanTexture->container = NULL; + newTexture->handle = currentRegion->vulkanTexture->handle; + newTexture->handle->vulkanTexture = newTexture; + currentRegion->vulkanTexture->handle = NULL; VULKAN_INTERNAL_QueueDestroyTexture(renderer, currentRegion->vulkanTexture); } -- 2.25.1 From 126375c5e3f3ea111a327ddb3f5bd0d13659f14f Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 28 Feb 2024 12:33:22 -0800 Subject: [PATCH 02/16] 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(); -- 2.25.1 From e88580ae649c2a8488aeb26d39cec5d8289a22a4 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 28 Feb 2024 19:09:44 -0800 Subject: [PATCH 03/16] implement resource containers --- include/Refresh.h | 21 +- src/Refresh.c | 12 +- src/Refresh_Driver.h | 6 +- src/Refresh_Driver_Vulkan.c | 775 +++++++++++++++++++++--------------- 4 files changed, 475 insertions(+), 339 deletions(-) diff --git a/include/Refresh.h b/include/Refresh.h index 8ad8888..644c9a6 100644 --- a/include/Refresh.h +++ b/include/Refresh.h @@ -1144,7 +1144,8 @@ REFRESHAPI void Refresh_DownloadFromTexture( Refresh_CommandBuffer *commandBuffer, Refresh_TextureSlice *textureSlice, Refresh_TransferBuffer *transferBuffer, - Refresh_BufferImageCopy *copyParams + Refresh_BufferImageCopy *copyParams, + Refresh_TransferOptions option ); /* Downloads data from a GpuBuffer object. */ @@ -1153,13 +1154,29 @@ REFRESHAPI void Refresh_DownloadFromBuffer( Refresh_CommandBuffer *commandBuffer, Refresh_GpuBuffer *gpuBuffer, Refresh_TransferBuffer *transferBuffer, - Refresh_BufferCopy *copyParams + Refresh_BufferCopy *copyParams, + Refresh_TransferOptions option ); /* GPU-to-GPU copies occur on the GPU timeline, * and you may assume the copy has finished in subsequent commands. */ +/* + * option: + * SAFEDISCARD: + * If the destination resource has been used in a copy command that has not completed, + * the issued copy commands will still be valid at the cost of increased memory usage. + * Otherwise the data will safely overwrite. + * This is a good option to prevent stalls on resources with frequent updates. + * It is not recommended to use this option with large resources. + * + * SAFEOVERWRITE: + * Overwrites the data regardless of whether a copy has been issued. + * This will insert a memory barrier, so it could cause suboptimal performance compared to SAFEDISCARD + * on resources that update frequently across submissions. + */ + /* Performs a texture-to-texture copy. */ REFRESHAPI void Refresh_CopyTextureToTexture( Refresh_Device *device, diff --git a/src/Refresh.c b/src/Refresh.c index ac170a0..986922f 100644 --- a/src/Refresh.c +++ b/src/Refresh.c @@ -820,7 +820,8 @@ void Refresh_DownloadFromTexture( Refresh_CommandBuffer *commandBuffer, Refresh_TextureSlice *textureSlice, Refresh_TransferBuffer *transferBuffer, - Refresh_BufferImageCopy *copyParams + Refresh_BufferImageCopy *copyParams, + Refresh_TransferOptions option ) { NULL_RETURN(device); device->DownloadFromTexture( @@ -828,7 +829,8 @@ void Refresh_DownloadFromTexture( commandBuffer, textureSlice, transferBuffer, - copyParams + copyParams, + option ); } @@ -837,7 +839,8 @@ void Refresh_DownloadFromBuffer( Refresh_CommandBuffer *commandBuffer, Refresh_GpuBuffer *gpuBuffer, Refresh_TransferBuffer *transferBuffer, - Refresh_BufferCopy *copyParams + Refresh_BufferCopy *copyParams, + Refresh_TransferOptions option ) { NULL_RETURN(device); device->DownloadFromBuffer( @@ -845,7 +848,8 @@ void Refresh_DownloadFromBuffer( commandBuffer, gpuBuffer, transferBuffer, - copyParams + copyParams, + option ); } diff --git a/src/Refresh_Driver.h b/src/Refresh_Driver.h index 7629855..6e92761 100644 --- a/src/Refresh_Driver.h +++ b/src/Refresh_Driver.h @@ -460,7 +460,8 @@ struct Refresh_Device Refresh_CommandBuffer *commandBuffer, Refresh_TextureSlice *textureSlice, Refresh_TransferBuffer *transferBuffer, - Refresh_BufferImageCopy *copyParams + Refresh_BufferImageCopy *copyParams, + Refresh_TransferOptions option ); void (*DownloadFromBuffer)( @@ -468,7 +469,8 @@ struct Refresh_Device Refresh_CommandBuffer *commandBuffer, Refresh_GpuBuffer *gpuBuffer, Refresh_TransferBuffer *transferBuffer, - Refresh_BufferCopy *copyParams + Refresh_BufferCopy *copyParams, + Refresh_TransferOptions option ); void (*CopyTextureToTexture)( diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index 930a978..61927a7 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -778,6 +778,12 @@ 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; @@ -797,13 +803,12 @@ struct VulkanTexture uint32_t depth; uint32_t layerCount; uint32_t levelCount; - Refresh_SampleCount sampleCount; /* actual sample account of the texture */ + 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; - 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; @@ -835,12 +840,6 @@ typedef struct VulkanTextureContainer 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 { VkFramebuffer framebuffer; @@ -1034,7 +1033,7 @@ typedef struct RenderPassHash RenderPassColorTargetDescription colorTargetDescriptions[MAX_COLOR_TARGET_BINDINGS]; uint32_t colorAttachmentCount; RenderPassDepthStencilTargetDescription depthStencilTargetDescription; - Refresh_SampleCount colorAttachmentSampleCount; + VkSampleCountFlagBits colorAttachmentSampleCount; } RenderPassHash; typedef struct RenderPassHashMap @@ -1755,6 +1754,15 @@ 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); /* Error Handling */ @@ -1985,24 +1993,24 @@ static inline VkDeviceSize VULKAN_INTERNAL_BytesPerImage( return (width * height * VULKAN_INTERNAL_BytesPerPixel(format)) / (blockSize * blockSize); } -static inline Refresh_SampleCount VULKAN_INTERNAL_GetMaxMultiSampleCount( +static inline VkSampleCountFlagBits VULKAN_INTERNAL_GetMaxMultiSampleCount( VulkanRenderer *renderer, - Refresh_SampleCount multiSampleCount + VkSampleCountFlagBits multiSampleCount ) { VkSampleCountFlags flags = renderer->physicalDeviceProperties.properties.limits.framebufferColorSampleCounts; - Refresh_SampleCount maxSupported = REFRESH_SAMPLECOUNT_1; + VkSampleCountFlagBits maxSupported = VK_SAMPLE_COUNT_1_BIT; if (flags & VK_SAMPLE_COUNT_8_BIT) { - maxSupported = REFRESH_SAMPLECOUNT_8; + maxSupported = VK_SAMPLE_COUNT_8_BIT; } else if (flags & VK_SAMPLE_COUNT_4_BIT) { - maxSupported = REFRESH_SAMPLECOUNT_4; + maxSupported = VK_SAMPLE_COUNT_4_BIT; } else if (flags & VK_SAMPLE_COUNT_2_BIT) { - maxSupported = REFRESH_SAMPLECOUNT_2; + maxSupported = VK_SAMPLE_COUNT_2_BIT; } return SDL_min(multiSampleCount, maxSupported); @@ -3480,23 +3488,20 @@ static void VULKAN_INTERNAL_DestroyTexture( if (isRenderTarget) { + rtIndex = 0; + 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] ); + + rtIndex += 1; } } } @@ -4882,7 +4887,7 @@ static uint8_t VULKAN_INTERNAL_CreateSwapchain( 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->sampleCount = VK_SAMPLE_COUNT_1_BIT; swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->usageFlags = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; @@ -4890,7 +4895,6 @@ static uint8_t VULKAN_INTERNAL_CreateSwapchain( 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, @@ -4898,7 +4902,7 @@ static uint8_t VULKAN_INTERNAL_CreateSwapchain( 0, 0, 0, - REFRESH_SAMPLECOUNT_1, + VK_SAMPLE_COUNT_1_BIT, &swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->renderTargets[0] ); } @@ -5339,7 +5343,7 @@ static void VULKAN_DrawPrimitivesIndirect( ) { VulkanRenderer* renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanBuffer *vulkanBuffer = ((VulkanBufferHandle*) gpuBuffer)->vulkanBuffer; + VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer*) gpuBuffer)->activeBufferHandle->vulkanBuffer; VkDescriptorSet descriptorSets[4]; uint32_t dynamicOffsets[2]; @@ -5373,101 +5377,6 @@ 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, @@ -5475,10 +5384,11 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture( uint32_t depth, uint32_t isCube, uint32_t levelCount, - Refresh_SampleCount sampleCount, + VkSampleCountFlagBits sampleCount, VkFormat format, VkImageAspectFlags aspectMask, - VkImageUsageFlags imageUsageFlags + VkImageUsageFlags imageUsageFlags, + uint8_t isMsaaTexture ) { VkResult vulkanResult; VkImageCreateInfo imageCreateInfo; @@ -5491,7 +5401,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; + uint32_t i, j, k, rtIndex; VulkanTexture *texture = SDL_malloc(sizeof(VulkanTexture)); texture->isCube = 0; @@ -5519,7 +5429,7 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture( imageCreateInfo.extent.depth = depth; imageCreateInfo.mipLevels = levelCount; imageCreateInfo.arrayLayers = layerCount; - imageCreateInfo.samples = sampleCount; + imageCreateInfo.samples = isMsaaTexture ? sampleCount : VK_SAMPLE_COUNT_1_BIT; imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; imageCreateInfo.usage = imageUsageFlags; imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -5608,12 +5518,185 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture( SDL_AtomicSet(&texture->referenceCount, 0); /* these get overwritten if render targets are created */ - texture->renderTargetSampleCount = REFRESH_SAMPLECOUNT_1; texture->renderTargets = NULL; + /* Create render target structures if necessary */ + if (isRenderTarget && !isMsaaTexture) + { + 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->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] + ); + + rtIndex += 1; + } + } + } + } + return texture; } +static VulkanTextureHandle* VULKAN_INTERNAL_CreateTextureHandle( + VulkanRenderer *renderer, + uint32_t width, + uint32_t height, + uint32_t depth, + uint32_t isCube, + uint32_t levelCount, + VkSampleCountFlagBits sampleCount, + VkFormat format, + VkImageAspectFlags aspectMask, + VkImageUsageFlags imageUsageFlags, + uint8_t isMsaaTexture +) { + VulkanTextureHandle *textureHandle; + VulkanTexture *texture; + + texture = VULKAN_INTERNAL_CreateTexture( + renderer, + width, + height, + depth, + isCube, + levelCount, + sampleCount, + format, + aspectMask, + imageUsageFlags, + isMsaaTexture + ); + + if (texture == NULL) + { + Refresh_LogError("Failed to create texture!"); + return NULL; + } + + textureHandle = SDL_malloc(sizeof(VulkanTextureHandle)); + textureHandle->vulkanTexture = texture; + texture->handle = textureHandle; + + return textureHandle; +} + +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, @@ -5685,9 +5768,9 @@ static VkRenderPass VULKAN_INTERNAL_CreateRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { - texture = ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture; + texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->activeTextureHandle->vulkanTexture; - if (texture->renderTargetSampleCount > REFRESH_SAMPLECOUNT_1) + if (texture->sampleCount > VK_SAMPLE_COUNT_1_BIT) { /* Resolve attachment and multisample attachment */ @@ -5720,7 +5803,7 @@ static VkRenderPass VULKAN_INTERNAL_CreateRenderPass( attachmentDescriptions[attachmentDescriptionCount].flags = 0; attachmentDescriptions[attachmentDescriptionCount].format = texture->format; attachmentDescriptions[attachmentDescriptionCount].samples = RefreshToVK_SampleCount[ - texture->renderTargetSampleCount + texture->sampleCount ]; attachmentDescriptions[attachmentDescriptionCount].loadOp = RefreshToVK_LoadOp[ colorAttachmentInfos[i].loadOp @@ -5790,7 +5873,7 @@ static VkRenderPass VULKAN_INTERNAL_CreateRenderPass( } else { - texture = ((VulkanTextureHandle*) depthStencilAttachmentInfo->texture)->vulkanTexture; + texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture; attachmentDescriptions[attachmentDescriptionCount].flags = 0; attachmentDescriptions[attachmentDescriptionCount].format = texture->format; @@ -5825,7 +5908,7 @@ static VkRenderPass VULKAN_INTERNAL_CreateRenderPass( attachmentDescriptionCount += 1; } - if (texture->renderTargetSampleCount > REFRESH_SAMPLECOUNT_1) + if (texture->sampleCount > VK_SAMPLE_COUNT_1_BIT) { subpass.pResolveAttachments = resolveReferences; } @@ -5863,7 +5946,7 @@ static VkRenderPass VULKAN_INTERNAL_CreateRenderPass( static VkRenderPass VULKAN_INTERNAL_CreateTransientRenderPass( VulkanRenderer *renderer, Refresh_GraphicsPipelineAttachmentInfo attachmentInfo, - Refresh_SampleCount sampleCount + VkSampleCountFlagBits sampleCount ) { VkAttachmentDescription attachmentDescriptions[2 * MAX_COLOR_TARGET_BINDINGS + 1]; VkAttachmentReference colorAttachmentReferences[MAX_COLOR_TARGET_BINDINGS]; @@ -5885,7 +5968,7 @@ static VkRenderPass VULKAN_INTERNAL_CreateTransientRenderPass( { attachmentDescription = attachmentInfo.colorAttachmentDescriptions[i]; - if (sampleCount > REFRESH_SAMPLECOUNT_1) + if (sampleCount > VK_SAMPLE_COUNT_1_BIT) { multisampling = 1; @@ -6046,7 +6129,7 @@ static Refresh_GraphicsPipeline* VULKAN_CreateGraphicsPipeline( ) { VkResult vulkanResult; uint32_t i; - Refresh_SampleCount actualSampleCount; + VkSampleCountFlagBits actualSampleCount; VulkanGraphicsPipeline *graphicsPipeline = (VulkanGraphicsPipeline*) SDL_malloc(sizeof(VulkanGraphicsPipeline)); VkGraphicsPipelineCreateInfo vkPipelineCreateInfo; @@ -6088,7 +6171,7 @@ static Refresh_GraphicsPipeline* VULKAN_CreateGraphicsPipeline( actualSampleCount = VULKAN_INTERNAL_GetMaxMultiSampleCount( renderer, - pipelineCreateInfo->multisampleState.multisampleCount + RefreshToVK_SampleCount[pipelineCreateInfo->multisampleState.multisampleCount] ); /* Create a "compatible" render pass */ @@ -6227,7 +6310,7 @@ static Refresh_GraphicsPipeline* VULKAN_CreateGraphicsPipeline( multisampleStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; multisampleStateCreateInfo.pNext = NULL; multisampleStateCreateInfo.flags = 0; - multisampleStateCreateInfo.rasterizationSamples = RefreshToVK_SampleCount[actualSampleCount]; + multisampleStateCreateInfo.rasterizationSamples = actualSampleCount; multisampleStateCreateInfo.sampleShadingEnable = VK_FALSE; multisampleStateCreateInfo.minSampleShading = 1.0f; multisampleStateCreateInfo.pSampleMask = @@ -6689,8 +6772,6 @@ static Refresh_Texture* VULKAN_CreateTexture( VkFormat format; VulkanTextureContainer *container; VulkanTextureHandle *textureHandle; - VulkanTexture *vulkanTexture; - uint32_t i, j, k, rtIndex; if (isDepthFormat) { @@ -6735,67 +6816,26 @@ static Refresh_Texture* VULKAN_CreateTexture( imageAspectFlags = VK_IMAGE_ASPECT_COLOR_BIT; } - vulkanTexture = VULKAN_INTERNAL_CreateTexture( + textureHandle = VULKAN_INTERNAL_CreateTextureHandle( renderer, textureCreateInfo->width, textureCreateInfo->height, textureCreateInfo->depth, textureCreateInfo->isCube, textureCreateInfo->levelCount, - REFRESH_SAMPLECOUNT_1, /* attachments themselves are always sample count 1, have msaaTex in render target */ + RefreshToVK_SampleCount[textureCreateInfo->sampleCount], format, imageAspectFlags, - imageUsageFlags + imageUsageFlags, + 0 ); - if (vulkanTexture == NULL) + if (textureHandle == NULL) { - Refresh_LogInfo("Failed to create texture!"); + Refresh_LogInfo("Failed to create texture container!"); 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)); - textureHandle->vulkanTexture = vulkanTexture; - vulkanTexture->handle = textureHandle; - container = SDL_malloc(sizeof(VulkanTextureContainer)); container->canBeDiscarded = 1; container->activeTextureHandle = textureHandle; @@ -7134,7 +7174,7 @@ static void VULKAN_BindVertexSamplers( for (i = 0; i < samplerCount; i += 1) { - currentTexture = ((VulkanTextureHandle*) pTextures[i])->vulkanTexture; + currentTexture = ((VulkanTextureContainer*) pTextures[i])->activeTextureHandle->vulkanTexture; currentSampler = (VulkanSampler*) pSamplers[i]; descriptorImageInfos[i].imageView = currentTexture->view; descriptorImageInfos[i].sampler = currentSampler->sampler; @@ -7177,7 +7217,7 @@ static void VULKAN_BindFragmentSamplers( for (i = 0; i < samplerCount; i += 1) { - currentTexture = ((VulkanTextureHandle*) pTextures[i])->vulkanTexture; + currentTexture = ((VulkanTextureContainer*) pTextures[i])->activeTextureHandle->vulkanTexture; currentSampler = (VulkanSampler*) pSamplers[i]; descriptorImageInfos[i].imageView = currentTexture->view; descriptorImageInfos[i].sampler = currentSampler->sampler; @@ -7227,14 +7267,19 @@ static void VULKAN_QueueDestroyTexture( Refresh_Texture *texture ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VulkanTextureHandle *vulkanTextureContainer = (VulkanTextureHandle *)texture; - VulkanTexture *vulkanTexture = vulkanTextureContainer->vulkanTexture; + VulkanTextureContainer *vulkanTextureContainer = (VulkanTextureContainer*) texture; + uint32_t i; SDL_LockMutex(renderer->disposeLock); - VULKAN_INTERNAL_QueueDestroyTexture(renderer, vulkanTexture); + for (i = 0; i < vulkanTextureContainer->textureCount; i += 1) + { + VULKAN_INTERNAL_QueueDestroyTexture(renderer, vulkanTextureContainer->textureHandles[i]->vulkanTexture); + SDL_free(vulkanTextureContainer->textureHandles[i]); + } /* Containers are just client handles, so we can destroy immediately */ + SDL_free(vulkanTextureContainer->textureHandles); SDL_free(vulkanTextureContainer); SDL_UnlockMutex(renderer->disposeLock); @@ -7294,14 +7339,19 @@ static void VULKAN_QueueDestroyGpuBuffer( Refresh_GpuBuffer *gpuBuffer ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VulkanBufferHandle *vulkanBufferContainer = (VulkanBufferHandle*) gpuBuffer; - VulkanBuffer *vulkanBuffer = vulkanBufferContainer->vulkanBuffer; + VulkanBufferContainer *vulkanBufferContainer = (VulkanBufferContainer*) gpuBuffer; + uint32_t i; SDL_LockMutex(renderer->disposeLock); - VULKAN_INTERNAL_QueueDestroyBuffer(renderer, vulkanBuffer); + for (i = 0; i < vulkanBufferContainer->bufferCount; i += 1) + { + VULKAN_INTERNAL_QueueDestroyBuffer(renderer, vulkanBufferContainer->bufferHandles[i]->vulkanBuffer); + SDL_free(vulkanBufferContainer->bufferHandles[i]); + } /* Containers are just client handles, so we can free immediately */ + SDL_free(vulkanBufferContainer->bufferHandles); SDL_free(vulkanBufferContainer); SDL_UnlockMutex(renderer->disposeLock); @@ -7411,23 +7461,21 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass( VkRenderPass renderPass; RenderPassHash hash; uint32_t i; - VulkanTexture *texture; SDL_LockMutex(renderer->renderPassFetchLock); for (i = 0; i < colorAttachmentCount; i += 1) { - hash.colorTargetDescriptions[i].format = ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture->format; + hash.colorTargetDescriptions[i].format = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->activeTextureHandle->vulkanTexture->format; hash.colorTargetDescriptions[i].clearColor = colorAttachmentInfos[i].clearColor; hash.colorTargetDescriptions[i].loadOp = colorAttachmentInfos[i].loadOp; hash.colorTargetDescriptions[i].storeOp = colorAttachmentInfos[i].storeOp; } - hash.colorAttachmentSampleCount = REFRESH_SAMPLECOUNT_1; + hash.colorAttachmentSampleCount = VK_SAMPLE_COUNT_1_BIT; if (colorAttachmentCount > 0) { - texture = ((VulkanTextureHandle*) colorAttachmentInfos[0].texture)->vulkanTexture; - hash.colorAttachmentSampleCount = texture->renderTargetSampleCount; + hash.colorAttachmentSampleCount = ((VulkanTextureContainer*) colorAttachmentInfos[0].texture)->activeTextureHandle->vulkanTexture->sampleCount; } hash.colorAttachmentCount = colorAttachmentCount; @@ -7442,7 +7490,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass( } else { - hash.depthStencilTargetDescription.format = ((VulkanTextureHandle*) depthStencilAttachmentInfo->texture)->vulkanTexture->format; + hash.depthStencilTargetDescription.format = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture->format; hash.depthStencilTargetDescription.loadOp = depthStencilAttachmentInfo->loadOp; hash.depthStencilTargetDescription.storeOp = depthStencilAttachmentInfo->storeOp; hash.depthStencilTargetDescription.stencilLoadOp = depthStencilAttachmentInfo->stencilLoadOp; @@ -7510,7 +7558,7 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( for (i = 0; i < colorAttachmentCount; i += 1) { - texture = ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture; + texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->activeTextureHandle->vulkanTexture; renderTarget = VULKAN_INTERNAL_FetchRenderTarget( renderer, @@ -7536,7 +7584,7 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( } else { - texture = ((VulkanTextureHandle*) depthStencilAttachmentInfo->texture)->vulkanTexture; + texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture; renderTarget = VULKAN_INTERNAL_FetchRenderTarget( renderer, texture, @@ -7572,7 +7620,7 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( for (i = 0; i < colorAttachmentCount; i += 1) { - texture = ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture; + texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->activeTextureHandle->vulkanTexture; renderTarget = VULKAN_INTERNAL_FetchRenderTarget( renderer, @@ -7598,7 +7646,7 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( if (depthStencilAttachmentInfo != NULL) { - texture = ((VulkanTextureHandle*) depthStencilAttachmentInfo->texture)->vulkanTexture; + texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture; renderTarget = VULKAN_INTERNAL_FetchRenderTarget( renderer, texture, @@ -7747,7 +7795,7 @@ static void VULKAN_BeginRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { - texture = ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture; + texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->activeTextureHandle->vulkanTexture; w = texture->dimensions.width >> colorAttachmentInfos[i].level; h = texture->dimensions.height >> colorAttachmentInfos[i].level; @@ -7770,7 +7818,7 @@ static void VULKAN_BeginRenderPass( if (depthStencilAttachmentInfo != NULL) { - texture = ((VulkanTextureHandle*) depthStencilAttachmentInfo->texture)->vulkanTexture; + texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture; w = texture->dimensions.width >> depthStencilAttachmentInfo->level; h = texture->dimensions.height >> depthStencilAttachmentInfo->level; @@ -7817,7 +7865,7 @@ static void VULKAN_BeginRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { - texture = ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture; + texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->activeTextureHandle->vulkanTexture; /* Transition the attachment */ VULKAN_INTERNAL_ImageMemoryBarrier( @@ -7834,7 +7882,7 @@ static void VULKAN_BeginRenderPass( &texture->resourceAccessType ); - if (texture->renderTargetSampleCount > REFRESH_SAMPLECOUNT_1) + if (texture->sampleCount > VK_SAMPLE_COUNT_1_BIT) { msaaTexture = VULKAN_INTERNAL_FetchRenderTargetMSAATexture( renderer, @@ -7869,7 +7917,7 @@ static void VULKAN_BeginRenderPass( if (depthStencilAttachmentInfo != NULL) { - texture = ((VulkanTextureHandle*) depthStencilAttachmentInfo->texture)->vulkanTexture; + texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture; depthAspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT; if (IsStencilFormat(texture->format)) @@ -7909,8 +7957,8 @@ static void VULKAN_BeginRenderPass( clearValues[i].color.float32[2] = colorAttachmentInfos[i].clearColor.z; clearValues[i].color.float32[3] = colorAttachmentInfos[i].clearColor.w; - texture = ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture; - if (texture->renderTargetSampleCount > REFRESH_SAMPLECOUNT_1) + texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->activeTextureHandle->vulkanTexture; + if (texture->sampleCount > VK_SAMPLE_COUNT_1_BIT) { clearValues[i+1].color.float32[0] = colorAttachmentInfos[i].clearColor.x; clearValues[i+1].color.float32[1] = colorAttachmentInfos[i].clearColor.y; @@ -7951,14 +7999,13 @@ static void VULKAN_BeginRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { vulkanCommandBuffer->renderPassColorTargetTextures[i] = - ((VulkanTextureHandle*) colorAttachmentInfos[i].texture)->vulkanTexture; + ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->activeTextureHandle->vulkanTexture; } vulkanCommandBuffer->renderPassColorTargetCount = colorAttachmentCount; if (depthStencilAttachmentInfo != NULL) { - vulkanCommandBuffer->renderPassDepthTexture = ((VulkanTextureHandle*) depthStencilAttachmentInfo->texture)->vulkanTexture; - } + vulkanCommandBuffer->renderPassDepthTexture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture; } /* Set sensible default viewport state */ @@ -8125,7 +8172,7 @@ static void VULKAN_BindVertexBuffers( for (i = 0; i < bindingCount; i += 1) { - currentVulkanBuffer = ((VulkanBufferHandle*) pBuffers[i])->vulkanBuffer; + currentVulkanBuffer = ((VulkanBufferContainer*) pBuffers[i])->activeBufferHandle->vulkanBuffer; buffers[i] = currentVulkanBuffer->buffer; VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, currentVulkanBuffer); } @@ -8150,7 +8197,7 @@ static void VULKAN_BindIndexBuffer( ) { VulkanRenderer* renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanBuffer* vulkanBuffer = ((VulkanBufferHandle*) gpuBuffer)->vulkanBuffer; + VulkanBuffer* vulkanBuffer = ((VulkanBufferContainer*) gpuBuffer)->activeBufferHandle->vulkanBuffer; VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanBuffer); @@ -8223,7 +8270,7 @@ static void VULKAN_BindComputeBuffers( for (i = 0; i < computePipeline->pipelineLayout->bufferDescriptorSetCache->bindingCount; i += 1) { - currentVulkanBuffer = ((VulkanBufferHandle*) pBuffers[i])->vulkanBuffer; + currentVulkanBuffer = ((VulkanBufferContainer*) pBuffers[i])->activeBufferHandle->vulkanBuffer; descriptorBufferInfos[i].buffer = currentVulkanBuffer->buffer; descriptorBufferInfos[i].offset = 0; @@ -8271,7 +8318,7 @@ static void VULKAN_BindComputeTextures( for (i = 0; i < computePipeline->pipelineLayout->imageDescriptorSetCache->bindingCount; i += 1) { - currentTexture = ((VulkanTextureHandle*) pTextures[i])->vulkanTexture; + currentTexture = ((VulkanTextureContainer*) pTextures[i])->activeTextureHandle->vulkanTexture; descriptorImageInfos[i].imageView = currentTexture->view; descriptorImageInfos[i].sampler = VK_NULL_HANDLE; descriptorImageInfos[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; @@ -8469,8 +8516,18 @@ static void VULKAN_INTERNAL_DiscardActiveTexture( } /* No texture handle is available, generate a new one. */ - textureContainer->activeTextureHandle = VULKAN_INTERNAL_CreateTexture( - + 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( @@ -8632,9 +8689,17 @@ static void VULKAN_UploadToBuffer( VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; - VulkanBuffer *vulkanGpuBuffer = ((VulkanBufferHandle*) gpuBuffer)->vulkanBuffer; + VulkanBufferContainer *gpuBufferContainer = (VulkanBufferContainer*) gpuBuffer; VkBufferCopy bufferCopy; + if (option == REFRESH_COPYOPTIONS_SAFEDISCARD && SDL_AtomicGet(&gpuBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0) + { + VULKAN_INTERNAL_DiscardActiveBuffer( + renderer, + gpuBufferContainer + ); + } + VULKAN_INTERNAL_BufferMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, @@ -8646,7 +8711,7 @@ static void VULKAN_UploadToBuffer( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_WRITE, - vulkanGpuBuffer + gpuBufferContainer->activeBufferHandle->vulkanBuffer ); bufferCopy.srcOffset = copyParams->srcOffset; @@ -8656,14 +8721,14 @@ static void VULKAN_UploadToBuffer( renderer->vkCmdCopyBuffer( vulkanCommandBuffer->commandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer, - vulkanGpuBuffer->buffer, + gpuBufferContainer->activeBufferHandle->vulkanBuffer->buffer, 1, &bufferCopy ); VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer); - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanGpuBuffer); - VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, vulkanGpuBuffer); + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, gpuBufferContainer->activeBufferHandle->vulkanBuffer); + VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, gpuBufferContainer->activeBufferHandle->vulkanBuffer); } static void VULKAN_DownloadFromTexture( @@ -8671,33 +8736,42 @@ static void VULKAN_DownloadFromTexture( Refresh_CommandBuffer *commandBuffer, Refresh_TextureSlice *textureSlice, Refresh_TransferBuffer *transferBuffer, - Refresh_BufferImageCopy *copyParams + Refresh_BufferImageCopy *copyParams, + Refresh_TransferOptions option ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTexture *vulkanTexture = ((VulkanTextureHandle*) textureSlice->texture)->vulkanTexture; - VulkanTransferBufferContainer *transferBufferContainer = (VulkanTransferBufferContainer*) transferBuffer; + VulkanTextureContainer *vulkanTextureContainer = (VulkanTextureContainer*) textureSlice->texture; + VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; VkBufferImageCopy imageCopy; + if (option == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0) + { + VULKAN_INTERNAL_DiscardActiveBuffer( + renderer, + transferBufferContainer + ); + } + VULKAN_INTERNAL_BufferMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_WRITE, - transferBufferContainer->activeBuffer->vulkanBuffer + transferBufferContainer->activeBufferHandle->vulkanBuffer ); VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_READ, - vulkanTexture->aspectFlags, + vulkanTextureContainer->activeTextureHandle->vulkanTexture->aspectFlags, 0, - vulkanTexture->layerCount, + vulkanTextureContainer->activeTextureHandle->vulkanTexture->layerCount, 0, - vulkanTexture->levelCount, + vulkanTextureContainer->activeTextureHandle->vulkanTexture->levelCount, 0, - vulkanTexture->image, - &vulkanTexture->resourceAccessType + vulkanTextureContainer->activeTextureHandle->vulkanTexture->image, + &vulkanTextureContainer->activeTextureHandle->vulkanTexture->resourceAccessType ); imageCopy.imageExtent.width = textureSlice->w; @@ -8706,7 +8780,7 @@ static void VULKAN_DownloadFromTexture( imageCopy.imageOffset.x = textureSlice->x; imageCopy.imageOffset.y = textureSlice->y; imageCopy.imageOffset.z = textureSlice->z; - imageCopy.imageSubresource.aspectMask = vulkanTexture->aspectFlags; + imageCopy.imageSubresource.aspectMask = vulkanTextureContainer->activeTextureHandle->vulkanTexture->aspectFlags; imageCopy.imageSubresource.baseArrayLayer = textureSlice->baseLayer; imageCopy.imageSubresource.layerCount = textureSlice->layerCount; imageCopy.imageSubresource.mipLevel = textureSlice->mipLevel; @@ -8716,18 +8790,16 @@ static void VULKAN_DownloadFromTexture( renderer->vkCmdCopyImageToBuffer( vulkanCommandBuffer->commandBuffer, - vulkanTexture->image, - AccessMap[vulkanTexture->resourceAccessType].imageLayout, - transferBufferContainer->activeBuffer->vulkanBuffer->buffer, + vulkanTextureContainer->activeTextureHandle->vulkanTexture->image, + AccessMap[vulkanTextureContainer->activeTextureHandle->vulkanTexture->resourceAccessType].imageLayout, + transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer, 1, &imageCopy ); - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBuffer->vulkanBuffer); - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTexture); - VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, vulkanTexture); - - transferBufferContainer->activeBuffer->vulkanBuffer->preserveContentsOnDefrag = 1; + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer); + VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTextureContainer->activeTextureHandle->vulkanTexture); + VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, vulkanTextureContainer->activeTextureHandle->vulkanTexture); } static void VULKAN_DownloadFromBuffer( @@ -8735,26 +8807,35 @@ static void VULKAN_DownloadFromBuffer( Refresh_CommandBuffer *commandBuffer, Refresh_GpuBuffer *gpuBuffer, Refresh_TransferBuffer *transferBuffer, - Refresh_BufferCopy *copyParams + Refresh_BufferCopy *copyParams, + Refresh_TransferOptions option ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTransferBufferContainer *transferBufferContainer = (VulkanTransferBufferContainer*) transferBuffer; - VulkanBuffer *vulkanGpuBuffer = ((VulkanBufferHandle*) gpuBuffer)->vulkanBuffer; + VulkanBufferContainer *gpuBufferContainer = (VulkanBufferContainer*) gpuBuffer; + VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; VkBufferCopy bufferCopy; + if (option == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0) + { + VULKAN_INTERNAL_DiscardActiveBuffer( + renderer, + transferBufferContainer + ); + } + VULKAN_INTERNAL_BufferMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_WRITE, - transferBufferContainer->activeBuffer->vulkanBuffer + transferBufferContainer->activeBufferHandle->vulkanBuffer ); VULKAN_INTERNAL_BufferMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_READ, - vulkanGpuBuffer + gpuBufferContainer->activeBufferHandle->vulkanBuffer ); bufferCopy.srcOffset = copyParams->srcOffset; @@ -8763,43 +8844,50 @@ static void VULKAN_DownloadFromBuffer( renderer->vkCmdCopyBuffer( vulkanCommandBuffer->commandBuffer, - vulkanGpuBuffer->buffer, - transferBufferContainer->activeBuffer->vulkanBuffer->buffer, + gpuBufferContainer->activeBufferHandle->vulkanBuffer->buffer, + transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer, 1, &bufferCopy ); - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBuffer->vulkanBuffer); - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanGpuBuffer); - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanGpuBuffer); - - transferBufferContainer->activeBuffer->vulkanBuffer->preserveContentsOnDefrag = 1; + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer); + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, gpuBufferContainer->activeBufferHandle->vulkanBuffer); + VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, gpuBufferContainer->activeBufferHandle->vulkanBuffer); } static void VULKAN_CopyTextureToTexture( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_TextureSlice *source, - Refresh_TextureSlice *destination + Refresh_TextureSlice *destination, + Refresh_CopyOptions option ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTexture *srcTexture = ((VulkanTextureHandle*) source->texture)->vulkanTexture; - VulkanTexture *dstTexture = ((VulkanTextureHandle*) destination->texture)->vulkanTexture; + VulkanTextureContainer *srcContainer = (VulkanTextureContainer*) source->texture; + VulkanTextureContainer *dstContainer = (VulkanTextureContainer*) destination->texture; VkImageCopy imageCopy; + if (option == REFRESH_COPYOPTIONS_SAFEDISCARD && SDL_AtomicGet(&dstContainer->activeTextureHandle->vulkanTexture->referenceCount) > 0) + { + VULKAN_INTERNAL_DiscardActiveTexture( + renderer, + dstContainer + ); + } + VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_READ, VK_IMAGE_ASPECT_COLOR_BIT, 0, - srcTexture->layerCount, + srcContainer->activeTextureHandle->vulkanTexture->layerCount, 0, - srcTexture->levelCount, + srcContainer->activeTextureHandle->vulkanTexture->levelCount, 0, - srcTexture->image, - &srcTexture->resourceAccessType + srcContainer->activeTextureHandle->vulkanTexture->image, + &srcContainer->activeTextureHandle->vulkanTexture->resourceAccessType ); VULKAN_INTERNAL_ImageMemoryBarrier( @@ -8808,25 +8896,25 @@ static void VULKAN_CopyTextureToTexture( RESOURCE_ACCESS_TRANSFER_WRITE, VK_IMAGE_ASPECT_COLOR_BIT, 0, - dstTexture->layerCount, + dstContainer->activeTextureHandle->vulkanTexture->layerCount, 0, - dstTexture->levelCount, + dstContainer->activeTextureHandle->vulkanTexture->levelCount, 0, - dstTexture->image, - &dstTexture->resourceAccessType + dstContainer->activeTextureHandle->vulkanTexture->image, + &dstContainer->activeTextureHandle->vulkanTexture->resourceAccessType ); imageCopy.srcOffset.x = source->x; imageCopy.srcOffset.y = source->y; imageCopy.srcOffset.z = source->z; - imageCopy.srcSubresource.aspectMask = srcTexture->aspectFlags; + imageCopy.srcSubresource.aspectMask = srcContainer->activeTextureHandle->vulkanTexture->aspectFlags; imageCopy.srcSubresource.baseArrayLayer = source->baseLayer; imageCopy.srcSubresource.layerCount = source->layerCount; imageCopy.srcSubresource.mipLevel = source->mipLevel; imageCopy.dstOffset.x = destination->x; imageCopy.dstOffset.y = destination->y; imageCopy.dstOffset.z = destination->z; - imageCopy.dstSubresource.aspectMask = dstTexture->aspectFlags; + imageCopy.dstSubresource.aspectMask = dstContainer->activeTextureHandle->vulkanTexture->aspectFlags; imageCopy.dstSubresource.baseArrayLayer = destination->baseLayer; imageCopy.dstSubresource.layerCount = destination->layerCount; imageCopy.dstSubresource.mipLevel = destination->mipLevel; @@ -8836,18 +8924,18 @@ static void VULKAN_CopyTextureToTexture( renderer->vkCmdCopyImage( vulkanCommandBuffer->commandBuffer, - srcTexture->image, - AccessMap[srcTexture->resourceAccessType].imageLayout, - dstTexture->image, - AccessMap[dstTexture->resourceAccessType].imageLayout, + srcContainer->activeTextureHandle->vulkanTexture->image, + AccessMap[srcContainer->activeTextureHandle->vulkanTexture->resourceAccessType].imageLayout, + dstContainer->activeTextureHandle->vulkanTexture->image, + AccessMap[dstContainer->activeTextureHandle->vulkanTexture->resourceAccessType].imageLayout, 1, &imageCopy ); - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, srcTexture); - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, dstTexture); - VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, srcTexture); - VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, dstTexture); + 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); } static void VULKAN_CopyTextureToBuffer( @@ -8855,33 +8943,42 @@ static void VULKAN_CopyTextureToBuffer( Refresh_CommandBuffer *commandBuffer, Refresh_TextureSlice *textureSlice, Refresh_GpuBuffer *gpuBuffer, - Refresh_BufferImageCopy *copyParams + Refresh_BufferImageCopy *copyParams, + Refresh_CopyOptions option ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTexture *vulkanTexture = ((VulkanTextureHandle*) textureSlice->texture)->vulkanTexture; - VulkanBuffer *vulkanBuffer = ((VulkanBufferHandle*) gpuBuffer)->vulkanBuffer; + VulkanTextureContainer *textureContainer = (VulkanTextureContainer*) textureSlice->texture; + VulkanBufferContainer *bufferContainer = (VulkanBufferContainer*) gpuBuffer; VkBufferImageCopy imageCopy; + if (option == REFRESH_COPYOPTIONS_SAFEDISCARD && SDL_AtomicGet(&bufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0) + { + VULKAN_INTERNAL_DiscardActiveBuffer( + renderer, + bufferContainer + ); + } + VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_READ, - vulkanTexture->aspectFlags, + textureContainer->activeTextureHandle->vulkanTexture->aspectFlags, 0, - vulkanTexture->layerCount, + textureContainer->activeTextureHandle->vulkanTexture->layerCount, 0, - vulkanTexture->levelCount, + textureContainer->activeTextureHandle->vulkanTexture->levelCount, 0, - vulkanTexture->image, - &vulkanTexture->resourceAccessType + textureContainer->activeTextureHandle->vulkanTexture->image, + &textureContainer->activeTextureHandle->vulkanTexture->resourceAccessType ); VULKAN_INTERNAL_BufferMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_WRITE, - vulkanBuffer + bufferContainer->activeBufferHandle->vulkanBuffer ); imageCopy.imageExtent.width = textureSlice->w; @@ -8890,7 +8987,7 @@ static void VULKAN_CopyTextureToBuffer( imageCopy.imageOffset.x = textureSlice->x; imageCopy.imageOffset.y = textureSlice->y; imageCopy.imageOffset.z = textureSlice->z; - imageCopy.imageSubresource.aspectMask = vulkanTexture->aspectFlags; + imageCopy.imageSubresource.aspectMask = textureContainer->activeTextureHandle->vulkanTexture->aspectFlags; imageCopy.imageSubresource.baseArrayLayer = textureSlice->baseLayer; imageCopy.imageSubresource.layerCount = textureSlice->layerCount; imageCopy.imageSubresource.mipLevel = textureSlice->mipLevel; @@ -8900,17 +8997,17 @@ static void VULKAN_CopyTextureToBuffer( renderer->vkCmdCopyImageToBuffer( vulkanCommandBuffer->commandBuffer, - vulkanTexture->image, - AccessMap[vulkanTexture->resourceAccessType].imageLayout, - vulkanBuffer->buffer, + textureContainer->activeTextureHandle->vulkanTexture->image, + AccessMap[textureContainer->activeTextureHandle->vulkanTexture->resourceAccessType].imageLayout, + bufferContainer->activeBufferHandle->vulkanBuffer->buffer, 1, &imageCopy ); - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanBuffer); - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTexture); - VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, vulkanBuffer); - VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, vulkanTexture); + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, bufferContainer->activeBufferHandle->vulkanBuffer); + VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, textureContainer->activeTextureHandle->vulkanTexture); + VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, bufferContainer->activeBufferHandle->vulkanBuffer); + VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, textureContainer->activeTextureHandle->vulkanTexture); } static void VULKAN_CopyBufferToTexture( @@ -8918,33 +9015,42 @@ static void VULKAN_CopyBufferToTexture( Refresh_CommandBuffer *commandBuffer, Refresh_GpuBuffer *gpuBuffer, Refresh_TextureSlice *textureSlice, - Refresh_BufferImageCopy *copyParams + Refresh_BufferImageCopy *copyParams, + Refresh_CopyOptions option ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanBuffer *vulkanBuffer = ((VulkanBufferHandle*) gpuBuffer)->vulkanBuffer; - VulkanTexture *vulkanTexture = ((VulkanTextureHandle*) textureSlice->texture)->vulkanTexture; + VulkanBufferContainer *bufferContainer = (VulkanBufferContainer*) gpuBuffer; + VulkanTextureContainer *textureContainer = (VulkanTextureContainer*) textureSlice->texture; VkBufferImageCopy imageCopy; + if (option == REFRESH_COPYOPTIONS_SAFEDISCARD && SDL_AtomicGet(&textureContainer->activeTextureHandle->vulkanTexture->referenceCount) > 0) + { + VULKAN_INTERNAL_DiscardActiveTexture( + renderer, + textureContainer + ); + } + VULKAN_INTERNAL_BufferMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_READ, - vulkanBuffer + bufferContainer->activeBufferHandle->vulkanBuffer ); VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_WRITE, - vulkanTexture->aspectFlags, + textureContainer->activeTextureHandle->vulkanTexture->aspectFlags, 0, - vulkanTexture->layerCount, + textureContainer->activeTextureHandle->vulkanTexture->layerCount, 0, - vulkanTexture->levelCount, + textureContainer->activeTextureHandle->vulkanTexture->levelCount, 0, - vulkanTexture->image, - &vulkanTexture->resourceAccessType + textureContainer->activeTextureHandle->vulkanTexture->image, + &textureContainer->activeTextureHandle->vulkanTexture->resourceAccessType ); imageCopy.imageExtent.width = textureSlice->w; @@ -8953,7 +9059,7 @@ static void VULKAN_CopyBufferToTexture( imageCopy.imageOffset.x = textureSlice->x; imageCopy.imageOffset.y = textureSlice->y; imageCopy.imageOffset.z = textureSlice->z; - imageCopy.imageSubresource.aspectMask = vulkanTexture->aspectFlags; + imageCopy.imageSubresource.aspectMask = textureContainer->activeTextureHandle->vulkanTexture->aspectFlags; imageCopy.imageSubresource.baseArrayLayer = textureSlice->baseLayer; imageCopy.imageSubresource.layerCount = textureSlice->layerCount; imageCopy.imageSubresource.mipLevel = textureSlice->mipLevel; @@ -8963,17 +9069,17 @@ static void VULKAN_CopyBufferToTexture( renderer->vkCmdCopyBufferToImage( vulkanCommandBuffer->commandBuffer, - vulkanBuffer->buffer, - vulkanTexture->image, - AccessMap[vulkanTexture->resourceAccessType].imageLayout, + bufferContainer->activeBufferHandle->vulkanBuffer->buffer, + textureContainer->activeTextureHandle->vulkanTexture->image, + AccessMap[textureContainer->activeTextureHandle->vulkanTexture->resourceAccessType].imageLayout, 1, &imageCopy ); - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanBuffer); - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTexture); - VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, vulkanBuffer); - VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, vulkanTexture); + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, bufferContainer->activeBufferHandle->vulkanBuffer); + VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, textureContainer->activeTextureHandle->vulkanTexture); + VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, bufferContainer->activeBufferHandle->vulkanBuffer); + VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, textureContainer->activeTextureHandle->vulkanTexture); } static void VULKAN_CopyBufferToBuffer( @@ -8981,26 +9087,35 @@ static void VULKAN_CopyBufferToBuffer( Refresh_CommandBuffer *commandBuffer, Refresh_GpuBuffer *source, Refresh_GpuBuffer *destination, - Refresh_BufferCopy *copyParams + Refresh_BufferCopy *copyParams, + Refresh_CopyOptions option ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanBuffer *vulkanSrcBuffer = ((VulkanBufferHandle*) source)->vulkanBuffer; - VulkanBuffer *vulkanDstBuffer = ((VulkanBufferHandle*) destination)->vulkanBuffer; + VulkanBufferContainer *srcContainer = (VulkanBufferContainer*) source; + VulkanBufferContainer *dstContainer = (VulkanBufferContainer*) destination; VkBufferCopy bufferCopy; + if (option == REFRESH_COPYOPTIONS_SAFEDISCARD && SDL_AtomicGet(&dstContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0) + { + VULKAN_INTERNAL_DiscardActiveBuffer( + renderer, + dstContainer + ); + } + VULKAN_INTERNAL_BufferMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_READ, - vulkanSrcBuffer + srcContainer->activeBufferHandle->vulkanBuffer ); VULKAN_INTERNAL_BufferMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_TRANSFER_WRITE, - vulkanDstBuffer + dstContainer->activeBufferHandle->vulkanBuffer ); bufferCopy.srcOffset = copyParams->srcOffset; @@ -9009,16 +9124,16 @@ static void VULKAN_CopyBufferToBuffer( renderer->vkCmdCopyBuffer( vulkanCommandBuffer->commandBuffer, - vulkanSrcBuffer->buffer, - vulkanDstBuffer->buffer, + srcContainer->activeBufferHandle->vulkanBuffer->buffer, + dstContainer->activeBufferHandle->vulkanBuffer->buffer, 1, &bufferCopy ); - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanSrcBuffer); - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanDstBuffer); - VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, vulkanSrcBuffer); - VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, vulkanDstBuffer); + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, srcContainer->activeBufferHandle->vulkanBuffer); + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, dstContainer->activeBufferHandle->vulkanBuffer); + VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, srcContainer->activeBufferHandle->vulkanBuffer); + VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, dstContainer->activeBufferHandle->vulkanBuffer); } static void VULKAN_GenerateMipmaps( @@ -9028,7 +9143,7 @@ static void VULKAN_GenerateMipmaps( ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTexture *vulkanTexture = ((VulkanTextureHandle*) texture)->vulkanTexture; + VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) texture)->activeTextureHandle->vulkanTexture; VulkanResourceAccessType *levelAccessType; VkImageBlit blit; uint32_t level; @@ -9586,7 +9701,7 @@ static Refresh_Texture* VULKAN_AcquireSwapchainTexture( WindowData *windowData; VulkanSwapchainData *swapchainData; VkResult acquireResult = VK_SUCCESS; - VulkanTextureHandle *swapchainTextureContainer = NULL; + VulkanTextureContainer *swapchainTextureContainer = NULL; VulkanPresentData *presentData; windowData = VULKAN_INTERNAL_FetchWindowData(windowHandle); @@ -9666,8 +9781,8 @@ static Refresh_Texture* VULKAN_AcquireSwapchainTexture( 0, 1, 0, - swapchainTextureContainer->vulkanTexture->image, - &swapchainTextureContainer->vulkanTexture->resourceAccessType + swapchainTextureContainer->activeTextureHandle->vulkanTexture->image, + &swapchainTextureContainer->activeTextureHandle->vulkanTexture->resourceAccessType ); /* Set up present struct */ @@ -10335,8 +10450,7 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory( currentRegion->vulkanBuffer->requireHostVisible, currentRegion->vulkanBuffer->preferHostLocal, currentRegion->vulkanBuffer->preferDeviceLocal, - 0, - currentRegion->vulkanBuffer->preserveContentsOnDefrag + 0 ); if (newBuffer == NULL) @@ -10348,10 +10462,8 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory( originalResourceAccessType = currentRegion->vulkanBuffer->resourceAccessType; /* Copy buffer contents if necessary */ - if ( - originalResourceAccessType != RESOURCE_ACCESS_NONE && - currentRegion->vulkanBuffer->preserveContentsOnDefrag - ) { + if (originalResourceAccessType != RESOURCE_ACCESS_NONE) + { VULKAN_INTERNAL_BufferMemoryBarrier( renderer, commandBuffer->commandBuffer, @@ -10413,7 +10525,8 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory( currentRegion->vulkanTexture->sampleCount, currentRegion->vulkanTexture->format, currentRegion->vulkanTexture->aspectFlags, - currentRegion->vulkanTexture->usageFlags + currentRegion->vulkanTexture->usageFlags, + 0 ); if (newTexture == NULL) -- 2.25.1 From 75128355ecce6bb9d2d5affbacd4d41361a4dd73 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 28 Feb 2024 19:57:43 -0800 Subject: [PATCH 04/16] misc fixes --- src/Refresh_Driver_Vulkan.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index 61927a7..41d2e91 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -3544,10 +3544,13 @@ static void VULKAN_INTERNAL_DestroyRenderTarget( NULL ); - VULKAN_INTERNAL_DestroyTexture( - renderer, - renderTarget->msaaTex - ); + if (renderTarget->msaaTex != NULL) + { + VULKAN_INTERNAL_DestroyTexture( + renderer, + renderTarget->msaaTex + ); + } } static void VULKAN_INTERNAL_DestroyBuffer( @@ -5706,7 +5709,7 @@ static uint32_t VULKAN_INTERNAL_GetRenderTargetIndex( return (level * texture->depth * texture->layerCount) + (layer * texture->depth) + - texture->depth; + depth; } static VulkanRenderTarget* VULKAN_INTERNAL_FetchRenderTarget( @@ -5802,9 +5805,7 @@ static VkRenderPass VULKAN_INTERNAL_CreateRenderPass( attachmentDescriptions[attachmentDescriptionCount].flags = 0; attachmentDescriptions[attachmentDescriptionCount].format = texture->format; - attachmentDescriptions[attachmentDescriptionCount].samples = RefreshToVK_SampleCount[ - texture->sampleCount - ]; + attachmentDescriptions[attachmentDescriptionCount].samples = texture->sampleCount; attachmentDescriptions[attachmentDescriptionCount].loadOp = RefreshToVK_LoadOp[ colorAttachmentInfos[i].loadOp ]; @@ -5877,9 +5878,8 @@ static VkRenderPass VULKAN_INTERNAL_CreateRenderPass( attachmentDescriptions[attachmentDescriptionCount].flags = 0; attachmentDescriptions[attachmentDescriptionCount].format = texture->format; - attachmentDescriptions[attachmentDescriptionCount].samples = RefreshToVK_SampleCount[ - texture->sampleCount - ]; + attachmentDescriptions[attachmentDescriptionCount].samples = texture->sampleCount; + attachmentDescriptions[attachmentDescriptionCount].loadOp = RefreshToVK_LoadOp[ depthStencilAttachmentInfo->loadOp ]; @@ -5996,9 +5996,8 @@ static VkRenderPass VULKAN_INTERNAL_CreateTransientRenderPass( attachmentDescriptions[attachmentDescriptionCount].format = RefreshToVK_SurfaceFormat[ attachmentDescription.format ]; - attachmentDescriptions[attachmentDescriptionCount].samples = RefreshToVK_SampleCount[ - sampleCount - ]; + attachmentDescriptions[attachmentDescriptionCount].samples = sampleCount; + attachmentDescriptions[attachmentDescriptionCount].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachmentDescriptions[attachmentDescriptionCount].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; @@ -6061,9 +6060,8 @@ static VkRenderPass VULKAN_INTERNAL_CreateTransientRenderPass( renderer, attachmentInfo.depthStencilFormat ); - attachmentDescriptions[attachmentDescriptionCount].samples = RefreshToVK_SampleCount[ - sampleCount - ]; + attachmentDescriptions[attachmentDescriptionCount].samples = sampleCount; + attachmentDescriptions[attachmentDescriptionCount].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachmentDescriptions[attachmentDescriptionCount].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; @@ -6844,6 +6842,7 @@ static Refresh_Texture* VULKAN_CreateTexture( container->textureHandles = SDL_malloc( container->textureCapacity * sizeof(VulkanTextureHandle*) ); + container->textureHandles[0] = container->activeTextureHandle; return (Refresh_Texture*) container; } -- 2.25.1 From d568810fa0dd75a91a3c399ad05102aed1aaa66f Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 28 Feb 2024 22:16:08 -0800 Subject: [PATCH 05/16] more misc fixes --- src/Refresh_Driver_Vulkan.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index 41d2e91..6ad120f 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -3482,11 +3482,8 @@ static void VULKAN_INTERNAL_DestroyTexture( VulkanTexture* 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) + if (texture->renderTargets != NULL) { rtIndex = 0; @@ -5432,7 +5429,7 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture( imageCreateInfo.extent.depth = depth; imageCreateInfo.mipLevels = levelCount; imageCreateInfo.arrayLayers = layerCount; - imageCreateInfo.samples = isMsaaTexture ? sampleCount : VK_SAMPLE_COUNT_1_BIT; + imageCreateInfo.samples = isMsaaTexture || IsDepthFormat(format) ? sampleCount : VK_SAMPLE_COUNT_1_BIT; imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; imageCreateInfo.usage = imageUsageFlags; imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -8867,7 +8864,7 @@ static void VULKAN_CopyTextureToTexture( VulkanTextureContainer *dstContainer = (VulkanTextureContainer*) destination->texture; VkImageCopy imageCopy; - if (option == REFRESH_COPYOPTIONS_SAFEDISCARD && 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, @@ -9023,7 +9020,7 @@ static void VULKAN_CopyBufferToTexture( VulkanTextureContainer *textureContainer = (VulkanTextureContainer*) textureSlice->texture; VkBufferImageCopy imageCopy; - if (option == REFRESH_COPYOPTIONS_SAFEDISCARD && 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, -- 2.25.1 From 8e04b0d1c9be4d719d2c0d929069175776f4ad26 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Thu, 29 Feb 2024 10:44:40 -0800 Subject: [PATCH 06/16] 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 -- 2.25.1 From 721854921d9d61fbef68e3392bc283f7ce5f8e7a Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Thu, 29 Feb 2024 17:17:49 -0800 Subject: [PATCH 07/16] 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 */ -- 2.25.1 From eeccea8ce8f197bca4527cb7b03b23f6b733713a Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Thu, 29 Feb 2024 23:53:35 -0800 Subject: [PATCH 08/16] TextureSlice and TextureRegion API --- include/Refresh.h | 27 ++--- src/Refresh.c | 24 ++-- src/Refresh_Driver.h | 12 +- src/Refresh_Driver_Vulkan.c | 226 ++++++++++++++---------------------- 4 files changed, 118 insertions(+), 171 deletions(-) diff --git a/include/Refresh.h b/include/Refresh.h index 0c635b7..5e80203 100644 --- a/include/Refresh.h +++ b/include/Refresh.h @@ -386,13 +386,18 @@ typedef struct Refresh_TextureSlice Refresh_Texture *texture; uint32_t mipLevel; uint32_t layer; +} Refresh_TextureSlice; + +typedef struct Refresh_TextureRegion +{ + Refresh_TextureSlice textureSlice; uint32_t x; uint32_t y; uint32_t z; uint32_t w; uint32_t h; uint32_t d; -} Refresh_TextureSlice; +} Refresh_TextureRegion; typedef struct Refresh_BufferImageCopy { @@ -580,9 +585,7 @@ typedef struct Refresh_GraphicsPipelineCreateInfo typedef struct Refresh_ColorAttachmentInfo { - Refresh_Texture *texture; - uint32_t layer; - uint32_t level; + Refresh_TextureSlice textureSlice; Refresh_Vec4 clearColor; /* Can be ignored by RenderPass */ Refresh_LoadOp loadOp; Refresh_StoreOp storeOp; @@ -591,9 +594,7 @@ typedef struct Refresh_ColorAttachmentInfo typedef struct Refresh_DepthStencilAttachmentInfo { - Refresh_Texture *texture; - uint32_t layer; - uint32_t level; + Refresh_TextureSlice textureSlice; Refresh_DepthStencilValue depthStencilClearValue; /* Can be ignored by RenderPass */ Refresh_LoadOp loadOp; Refresh_StoreOp storeOp; @@ -1111,7 +1112,7 @@ REFRESHAPI void Refresh_UploadToTexture( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, Refresh_TransferBuffer *transferBuffer, - Refresh_TextureSlice *textureSlice, + Refresh_TextureRegion *textureRegion, Refresh_BufferImageCopy *copyParams, Refresh_CopyOptions option ); @@ -1136,7 +1137,7 @@ REFRESHAPI void Refresh_UploadToBuffer( REFRESHAPI void Refresh_DownloadFromTexture( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice *textureSlice, + Refresh_TextureRegion *textureRegion, Refresh_TransferBuffer *transferBuffer, Refresh_BufferImageCopy *copyParams, Refresh_TransferOptions option @@ -1175,8 +1176,8 @@ REFRESHAPI void Refresh_DownloadFromBuffer( REFRESHAPI void Refresh_CopyTextureToTexture( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice *source, - Refresh_TextureSlice *destination, + Refresh_TextureRegion *source, + Refresh_TextureRegion *destination, Refresh_CopyOptions option ); @@ -1184,7 +1185,7 @@ REFRESHAPI void Refresh_CopyTextureToTexture( REFRESHAPI void Refresh_CopyTextureToBuffer( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice *textureSlice, + Refresh_TextureRegion *textureRegion, Refresh_GpuBuffer *gpuBuffer, Refresh_BufferImageCopy *copyParams, Refresh_CopyOptions option @@ -1195,7 +1196,7 @@ REFRESHAPI void Refresh_CopyBufferToTexture( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, Refresh_GpuBuffer *gpuBuffer, - Refresh_TextureSlice *textureSlice, + Refresh_TextureRegion *textureRegion, Refresh_BufferImageCopy *copyParams, Refresh_CopyOptions option ); diff --git a/src/Refresh.c b/src/Refresh.c index 3a1ce54..d6292c8 100644 --- a/src/Refresh.c +++ b/src/Refresh.c @@ -779,7 +779,7 @@ void Refresh_UploadToTexture( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, Refresh_TransferBuffer *transferBuffer, - Refresh_TextureSlice *textureSlice, + Refresh_TextureRegion *textureRegion, Refresh_BufferImageCopy *copyParams, Refresh_CopyOptions option ) { @@ -788,7 +788,7 @@ void Refresh_UploadToTexture( device->driverData, commandBuffer, transferBuffer, - textureSlice, + textureRegion, copyParams, option ); @@ -816,7 +816,7 @@ void Refresh_UploadToBuffer( void Refresh_DownloadFromTexture( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice *textureSlice, + Refresh_TextureRegion *textureRegion, Refresh_TransferBuffer *transferBuffer, Refresh_BufferImageCopy *copyParams, Refresh_TransferOptions option @@ -825,7 +825,7 @@ void Refresh_DownloadFromTexture( device->DownloadFromTexture( device->driverData, commandBuffer, - textureSlice, + textureRegion, transferBuffer, copyParams, option @@ -854,16 +854,16 @@ void Refresh_DownloadFromBuffer( void Refresh_CopyTextureToTexture( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice *sourceTextureSlice, - Refresh_TextureSlice *destinationTextureSlice, + Refresh_TextureRegion *source, + Refresh_TextureRegion *destination, Refresh_CopyOptions option ) { NULL_RETURN(device); device->CopyTextureToTexture( device->driverData, commandBuffer, - sourceTextureSlice, - destinationTextureSlice, + source, + destination, option ); } @@ -871,7 +871,7 @@ void Refresh_CopyTextureToTexture( void Refresh_CopyTextureToBuffer( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice *textureSlice, + Refresh_TextureRegion *textureRegion, Refresh_GpuBuffer *gpuBuffer, Refresh_BufferImageCopy *copyParameters, Refresh_CopyOptions option @@ -880,7 +880,7 @@ void Refresh_CopyTextureToBuffer( device->CopyTextureToBuffer( device->driverData, commandBuffer, - textureSlice, + textureRegion, gpuBuffer, copyParameters, option @@ -891,7 +891,7 @@ void Refresh_CopyBufferToTexture( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, Refresh_GpuBuffer *gpuBuffer, - Refresh_TextureSlice *textureSlice, + Refresh_TextureRegion *textureRegion, Refresh_BufferImageCopy *copyParams, Refresh_CopyOptions option ) { @@ -900,7 +900,7 @@ void Refresh_CopyBufferToTexture( device->driverData, commandBuffer, gpuBuffer, - textureSlice, + textureRegion, copyParams, option ); diff --git a/src/Refresh_Driver.h b/src/Refresh_Driver.h index 3aa3bce..38f7f69 100644 --- a/src/Refresh_Driver.h +++ b/src/Refresh_Driver.h @@ -440,7 +440,7 @@ struct Refresh_Device Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_TransferBuffer *transferBuffer, - Refresh_TextureSlice *textureSlice, + Refresh_TextureRegion *textureSlice, Refresh_BufferImageCopy *copyParams, Refresh_CopyOptions option ); @@ -457,7 +457,7 @@ struct Refresh_Device void (*DownloadFromTexture)( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice *textureSlice, + Refresh_TextureRegion *textureSlice, Refresh_TransferBuffer *transferBuffer, Refresh_BufferImageCopy *copyParams, Refresh_TransferOptions option @@ -475,15 +475,15 @@ struct Refresh_Device void (*CopyTextureToTexture)( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice *source, - Refresh_TextureSlice *destination, + Refresh_TextureRegion *source, + Refresh_TextureRegion *destination, Refresh_CopyOptions option ); void (*CopyTextureToBuffer)( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice *textureSlice, + Refresh_TextureRegion *textureSlice, Refresh_GpuBuffer *gpuBuffer, Refresh_BufferImageCopy *copyParams, Refresh_CopyOptions option @@ -493,7 +493,7 @@ struct Refresh_Device Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_GpuBuffer *gpuBuffer, - Refresh_TextureSlice *textureSlice, + Refresh_TextureRegion *textureSlice, Refresh_BufferImageCopy *copyParams, Refresh_CopyOptions option ); diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index 028468f..08d5bba 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -5577,6 +5577,10 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture( { imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_3D; } + else if (layerCount > 1) + { + imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + } else { imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; @@ -5789,7 +5793,7 @@ static VkRenderPass VULKAN_INTERNAL_CreateRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { - texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->activeTextureHandle->vulkanTexture; + texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].textureSlice.texture)->activeTextureHandle->vulkanTexture; if (texture->sampleCount > VK_SAMPLE_COUNT_1_BIT) { @@ -5892,7 +5896,7 @@ static VkRenderPass VULKAN_INTERNAL_CreateRenderPass( } else { - texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture; + texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->textureSlice.texture)->activeTextureHandle->vulkanTexture; attachmentDescriptions[attachmentDescriptionCount].flags = 0; attachmentDescriptions[attachmentDescriptionCount].format = texture->format; @@ -7490,7 +7494,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass( for (i = 0; i < colorAttachmentCount; i += 1) { - hash.colorTargetDescriptions[i].format = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->activeTextureHandle->vulkanTexture->format; + hash.colorTargetDescriptions[i].format = ((VulkanTextureContainer*) colorAttachmentInfos[i].textureSlice.texture)->activeTextureHandle->vulkanTexture->format; hash.colorTargetDescriptions[i].clearColor = colorAttachmentInfos[i].clearColor; hash.colorTargetDescriptions[i].loadOp = colorAttachmentInfos[i].loadOp; hash.colorTargetDescriptions[i].storeOp = colorAttachmentInfos[i].storeOp; @@ -7499,7 +7503,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass( hash.colorAttachmentSampleCount = VK_SAMPLE_COUNT_1_BIT; if (colorAttachmentCount > 0) { - hash.colorAttachmentSampleCount = ((VulkanTextureContainer*) colorAttachmentInfos[0].texture)->activeTextureHandle->vulkanTexture->sampleCount; + hash.colorAttachmentSampleCount = ((VulkanTextureContainer*) colorAttachmentInfos[0].textureSlice.texture)->activeTextureHandle->vulkanTexture->sampleCount; } hash.colorAttachmentCount = colorAttachmentCount; @@ -7514,7 +7518,7 @@ static VkRenderPass VULKAN_INTERNAL_FetchRenderPass( } else { - hash.depthStencilTargetDescription.format = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture->format; + hash.depthStencilTargetDescription.format = ((VulkanTextureContainer*) depthStencilAttachmentInfo->textureSlice.texture)->activeTextureHandle->vulkanTexture->format; hash.depthStencilTargetDescription.loadOp = depthStencilAttachmentInfo->loadOp; hash.depthStencilTargetDescription.storeOp = depthStencilAttachmentInfo->storeOp; hash.depthStencilTargetDescription.stencilLoadOp = depthStencilAttachmentInfo->stencilLoadOp; @@ -7567,7 +7571,6 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( VkResult result; VkImageView imageViewAttachments[2 * MAX_COLOR_TARGET_BINDINGS + 1]; FramebufferHash hash; - VulkanTexture *texture; VulkanTextureSlice *textureSlice; uint32_t attachmentCount = 0; uint32_t i; @@ -7582,12 +7585,7 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( 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 - ); + textureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&colorAttachmentInfos[i].textureSlice); hash.colorAttachmentViews[i] = textureSlice->view; @@ -7603,12 +7601,7 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( } else { - texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture; - textureSlice = VULKAN_INTERNAL_FetchTextureSlice( - texture, - depthStencilAttachmentInfo->layer, - depthStencilAttachmentInfo->level - ); + textureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&depthStencilAttachmentInfo->textureSlice); hash.depthStencilAttachmentView = textureSlice->view; } @@ -7637,12 +7630,7 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( 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 - ); + textureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&colorAttachmentInfos[i].textureSlice); imageViewAttachments[attachmentCount] = textureSlice->view; @@ -7660,12 +7648,7 @@ static VulkanFramebuffer* VULKAN_INTERNAL_FetchFramebuffer( if (depthStencilAttachmentInfo != NULL) { - texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture; - textureSlice = VULKAN_INTERNAL_FetchTextureSlice( - texture, - depthStencilAttachmentInfo->layer, - depthStencilAttachmentInfo->level - ); + textureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&depthStencilAttachmentInfo->textureSlice); imageViewAttachments[attachmentCount] = textureSlice->view; @@ -7792,8 +7775,6 @@ static void VULKAN_BeginRenderPass( VulkanTextureContainer *textureContainer; VulkanTextureSlice *textureSlice; - VulkanTexture *texture; - VulkanTexture *msaaTexture = NULL; uint32_t w, h; VkClearValue *clearValues; uint32_t clearCount = colorAttachmentCount; @@ -7808,12 +7789,8 @@ 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 - ); + textureContainer = (VulkanTextureContainer*) colorAttachmentInfos[i].textureSlice.texture; + textureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&colorAttachmentInfos[i].textureSlice); if ( colorAttachmentInfos[i].safeDiscard && @@ -7825,17 +7802,12 @@ static void VULKAN_BeginRenderPass( renderer, textureContainer ); + textureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&colorAttachmentInfos[i].textureSlice); } - 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; + w = textureSlice->parent->dimensions.width >> colorAttachmentInfos[i].textureSlice.mipLevel; + h = textureSlice->parent->dimensions.height >> colorAttachmentInfos[i].textureSlice.mipLevel; /* The framebuffer cannot be larger than the smallest attachment. */ @@ -7858,12 +7830,8 @@ static void VULKAN_BeginRenderPass( if (depthStencilAttachmentInfo != NULL) { - textureContainer = (VulkanTextureContainer*) depthStencilAttachmentInfo->texture; - textureSlice = VULKAN_INTERNAL_FetchTextureSlice( - textureContainer->activeTextureHandle->vulkanTexture, - depthStencilAttachmentInfo->layer, - depthStencilAttachmentInfo->level - ); + textureContainer = (VulkanTextureContainer*) depthStencilAttachmentInfo->textureSlice.texture; + textureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&depthStencilAttachmentInfo->textureSlice); if ( depthStencilAttachmentInfo->safeDiscard && @@ -7876,17 +7844,11 @@ static void VULKAN_BeginRenderPass( renderer, textureContainer ); + textureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&depthStencilAttachmentInfo->textureSlice); } - 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; + w = textureSlice->parent->dimensions.width >> depthStencilAttachmentInfo->textureSlice.mipLevel; + h = textureSlice->parent->dimensions.height >> depthStencilAttachmentInfo->textureSlice.mipLevel; /* The framebuffer cannot be larger than the smallest attachment. */ @@ -7933,12 +7895,7 @@ 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 - ); + textureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&colorAttachmentInfos[i].textureSlice); vulkanCommandBuffer->renderPassColorTargetTextureSlices[i] = textureSlice; @@ -7950,20 +7907,14 @@ static void VULKAN_BeginRenderPass( textureSlice ); - if (texture->sampleCount > VK_SAMPLE_COUNT_1_BIT) + if (textureSlice->msaaTex != NULL) { - msaaTexture = VULKAN_INTERNAL_FetchMSAATexture( - texture, - colorAttachmentInfos[i].layer, - colorAttachmentInfos[i].level - ); - /* Transition the multisample attachment */ VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, RESOURCE_ACCESS_COLOR_ATTACHMENT_WRITE, - &msaaTexture->slices[0] + &textureSlice->msaaTex->slices[0] ); clearCount += 1; @@ -7979,18 +7930,13 @@ static void VULKAN_BeginRenderPass( if (depthStencilAttachmentInfo != NULL) { - texture = ((VulkanTextureContainer*) depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture; - textureSlice = VULKAN_INTERNAL_FetchTextureSlice( - texture, - depthStencilAttachmentInfo->layer, - depthStencilAttachmentInfo->level - ); + textureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&depthStencilAttachmentInfo->textureSlice); vulkanCommandBuffer->renderPassDepthTextureSlice = textureSlice; depthAspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT; - if (IsStencilFormat(texture->format)) + if (IsStencilFormat(textureSlice->parent->format)) { depthAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT; } @@ -8020,8 +7966,9 @@ static void VULKAN_BeginRenderPass( clearValues[i].color.float32[2] = colorAttachmentInfos[i].clearColor.z; clearValues[i].color.float32[3] = colorAttachmentInfos[i].clearColor.w; - texture = ((VulkanTextureContainer*) colorAttachmentInfos[i].texture)->activeTextureHandle->vulkanTexture; - if (texture->sampleCount > VK_SAMPLE_COUNT_1_BIT) + textureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&colorAttachmentInfos[i].textureSlice); + + if (textureSlice->parent->sampleCount > VK_SAMPLE_COUNT_1_BIT) { clearValues[i+1].color.float32[0] = colorAttachmentInfos[i].clearColor.x; clearValues[i+1].color.float32[1] = colorAttachmentInfos[i].clearColor.y; @@ -8580,18 +8527,18 @@ static void VULKAN_UploadToTexture( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_TransferBuffer *transferBuffer, - Refresh_TextureSlice *textureSlice, + Refresh_TextureRegion *textureRegion, Refresh_BufferImageCopy *copyParams, Refresh_CopyOptions option ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; - VulkanTextureContainer *vulkanTextureContainer = (VulkanTextureContainer*) textureSlice->texture; + VulkanTextureContainer *vulkanTextureContainer = (VulkanTextureContainer*) textureRegion->textureSlice.texture; VulkanTextureSlice *vulkanTextureSlice; VkBufferImageCopy imageCopy; - vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(textureSlice); + vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); if ( option == REFRESH_COPYOPTIONS_SAFEDISCARD && @@ -8603,7 +8550,7 @@ static void VULKAN_UploadToTexture( vulkanTextureContainer ); - vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(textureSlice); + vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); } VULKAN_INTERNAL_BufferMemoryBarrier( @@ -8620,16 +8567,16 @@ static void VULKAN_UploadToTexture( vulkanTextureSlice ); - imageCopy.imageExtent.width = textureSlice->w; - imageCopy.imageExtent.height = textureSlice->h; - imageCopy.imageExtent.depth = textureSlice->d; - imageCopy.imageOffset.x = textureSlice->x; - imageCopy.imageOffset.y = textureSlice->y; - imageCopy.imageOffset.z = textureSlice->z; + imageCopy.imageExtent.width = textureRegion->w; + imageCopy.imageExtent.height = textureRegion->h; + imageCopy.imageExtent.depth = textureRegion->d; + imageCopy.imageOffset.x = textureRegion->x; + imageCopy.imageOffset.y = textureRegion->y; + imageCopy.imageOffset.z = textureRegion->z; imageCopy.imageSubresource.aspectMask = vulkanTextureSlice->parent->aspectFlags; - imageCopy.imageSubresource.baseArrayLayer = textureSlice->layer; + imageCopy.imageSubresource.baseArrayLayer = textureRegion->textureSlice.layer; imageCopy.imageSubresource.layerCount = 1; - imageCopy.imageSubresource.mipLevel = textureSlice->mipLevel; + imageCopy.imageSubresource.mipLevel = textureRegion->textureSlice.mipLevel; imageCopy.bufferOffset = copyParams->bufferOffset; imageCopy.bufferRowLength = copyParams->bufferStride; imageCopy.bufferImageHeight = copyParams->bufferImageHeight; @@ -8706,7 +8653,7 @@ static void VULKAN_UploadToBuffer( static void VULKAN_DownloadFromTexture( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice *textureSlice, + Refresh_TextureRegion *textureRegion, Refresh_TransferBuffer *transferBuffer, Refresh_BufferImageCopy *copyParams, Refresh_TransferOptions option @@ -8717,7 +8664,7 @@ static void VULKAN_DownloadFromTexture( VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; VkBufferImageCopy imageCopy; - vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(textureSlice); + vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); if ( option == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && @@ -8727,6 +8674,7 @@ static void VULKAN_DownloadFromTexture( renderer, transferBufferContainer ); + vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); } VULKAN_INTERNAL_BufferMemoryBarrier( @@ -8743,16 +8691,16 @@ static void VULKAN_DownloadFromTexture( vulkanTextureSlice ); - imageCopy.imageExtent.width = textureSlice->w; - imageCopy.imageExtent.height = textureSlice->h; - imageCopy.imageExtent.depth = textureSlice->d; - imageCopy.imageOffset.x = textureSlice->x; - imageCopy.imageOffset.y = textureSlice->y; - imageCopy.imageOffset.z = textureSlice->z; + imageCopy.imageExtent.width = textureRegion->w; + imageCopy.imageExtent.height = textureRegion->h; + imageCopy.imageExtent.depth = textureRegion->d; + imageCopy.imageOffset.x = textureRegion->x; + imageCopy.imageOffset.y = textureRegion->y; + imageCopy.imageOffset.z = textureRegion->z; imageCopy.imageSubresource.aspectMask = vulkanTextureSlice->parent->aspectFlags; - imageCopy.imageSubresource.baseArrayLayer = textureSlice->layer; + imageCopy.imageSubresource.baseArrayLayer = textureRegion->textureSlice.layer; imageCopy.imageSubresource.layerCount = 1; - imageCopy.imageSubresource.mipLevel = textureSlice->mipLevel; + imageCopy.imageSubresource.mipLevel = textureRegion->textureSlice.mipLevel; imageCopy.bufferOffset = copyParams->bufferOffset; imageCopy.bufferRowLength = copyParams->bufferStride; imageCopy.bufferImageHeight = copyParams->bufferImageHeight; @@ -8829,20 +8777,19 @@ static void VULKAN_DownloadFromBuffer( static void VULKAN_CopyTextureToTexture( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice *source, - Refresh_TextureSlice *destination, + Refresh_TextureRegion *source, + Refresh_TextureRegion *destination, Refresh_CopyOptions option ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTextureContainer *srcContainer = (VulkanTextureContainer*) source->texture; - VulkanTextureContainer *dstContainer = (VulkanTextureContainer*) destination->texture; + VulkanTextureContainer *dstContainer = (VulkanTextureContainer*) destination->textureSlice.texture; VulkanTextureSlice *srcSlice; VulkanTextureSlice *dstSlice; VkImageCopy imageCopy; - srcSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(source); - dstSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(destination); + srcSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&source->textureSlice); + dstSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&destination->textureSlice); if ( option == REFRESH_COPYOPTIONS_SAFEDISCARD && @@ -8853,7 +8800,7 @@ static void VULKAN_CopyTextureToTexture( renderer, dstContainer ); - dstSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(destination); + dstSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&destination->textureSlice); } VULKAN_INTERNAL_ImageMemoryBarrier( @@ -8874,16 +8821,16 @@ static void VULKAN_CopyTextureToTexture( imageCopy.srcOffset.y = source->y; imageCopy.srcOffset.z = source->z; imageCopy.srcSubresource.aspectMask = srcSlice->parent->aspectFlags; - imageCopy.srcSubresource.baseArrayLayer = source->layer; + imageCopy.srcSubresource.baseArrayLayer = source->textureSlice.layer; imageCopy.srcSubresource.layerCount = 1; - imageCopy.srcSubresource.mipLevel = source->mipLevel; + imageCopy.srcSubresource.mipLevel = source->textureSlice.mipLevel; imageCopy.dstOffset.x = destination->x; imageCopy.dstOffset.y = destination->y; imageCopy.dstOffset.z = destination->z; imageCopy.dstSubresource.aspectMask = dstSlice->parent->aspectFlags; - imageCopy.dstSubresource.baseArrayLayer = destination->layer; + imageCopy.dstSubresource.baseArrayLayer = destination->textureSlice.layer; imageCopy.dstSubresource.layerCount = 1; - imageCopy.dstSubresource.mipLevel = destination->mipLevel; + imageCopy.dstSubresource.mipLevel = destination->textureSlice.mipLevel; imageCopy.extent.width = source->w; imageCopy.extent.height = source->h; imageCopy.extent.depth = source->d; @@ -8907,19 +8854,18 @@ static void VULKAN_CopyTextureToTexture( static void VULKAN_CopyTextureToBuffer( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice *textureSlice, + Refresh_TextureRegion *textureRegion, Refresh_GpuBuffer *gpuBuffer, Refresh_BufferImageCopy *copyParams, Refresh_CopyOptions option ) { 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); + vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); if ( option == REFRESH_COPYOPTIONS_SAFEDISCARD && @@ -8945,16 +8891,16 @@ static void VULKAN_CopyTextureToBuffer( bufferContainer->activeBufferHandle->vulkanBuffer ); - imageCopy.imageExtent.width = textureSlice->w; - imageCopy.imageExtent.height = textureSlice->h; - imageCopy.imageExtent.depth = textureSlice->d; - imageCopy.imageOffset.x = textureSlice->x; - imageCopy.imageOffset.y = textureSlice->y; - imageCopy.imageOffset.z = textureSlice->z; + imageCopy.imageExtent.width = textureRegion->w; + imageCopy.imageExtent.height = textureRegion->h; + imageCopy.imageExtent.depth = textureRegion->d; + imageCopy.imageOffset.x = textureRegion->x; + imageCopy.imageOffset.y = textureRegion->y; + imageCopy.imageOffset.z = textureRegion->z; imageCopy.imageSubresource.aspectMask = vulkanTextureSlice->parent->aspectFlags; - imageCopy.imageSubresource.baseArrayLayer = textureSlice->layer; + imageCopy.imageSubresource.baseArrayLayer = textureRegion->textureSlice.layer; imageCopy.imageSubresource.layerCount = 1; - imageCopy.imageSubresource.mipLevel = textureSlice->mipLevel; + imageCopy.imageSubresource.mipLevel = textureRegion->textureSlice.mipLevel; imageCopy.bufferOffset = copyParams->bufferOffset; imageCopy.bufferRowLength = copyParams->bufferStride; imageCopy.bufferImageHeight = copyParams->bufferImageHeight; @@ -8978,18 +8924,18 @@ static void VULKAN_CopyBufferToTexture( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, Refresh_GpuBuffer *gpuBuffer, - Refresh_TextureSlice *textureSlice, + Refresh_TextureRegion *textureRegion, Refresh_BufferImageCopy *copyParams, Refresh_CopyOptions option ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanBufferContainer *bufferContainer = (VulkanBufferContainer*) gpuBuffer; - VulkanTextureContainer *textureContainer = (VulkanTextureContainer*) textureSlice->texture; + VulkanTextureContainer *textureContainer = (VulkanTextureContainer*) textureRegion->textureSlice.texture; VulkanTextureSlice *vulkanTextureSlice; VkBufferImageCopy imageCopy; - vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(textureSlice); + vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); if ( option == REFRESH_COPYOPTIONS_SAFEDISCARD && @@ -9000,7 +8946,7 @@ static void VULKAN_CopyBufferToTexture( renderer, textureContainer ); - vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(textureSlice); + vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); } VULKAN_INTERNAL_BufferMemoryBarrier( @@ -9017,16 +8963,16 @@ static void VULKAN_CopyBufferToTexture( vulkanTextureSlice ); - imageCopy.imageExtent.width = textureSlice->w; - imageCopy.imageExtent.height = textureSlice->h; - imageCopy.imageExtent.depth = textureSlice->d; - imageCopy.imageOffset.x = textureSlice->x; - imageCopy.imageOffset.y = textureSlice->y; - imageCopy.imageOffset.z = textureSlice->z; + imageCopy.imageExtent.width = textureRegion->w; + imageCopy.imageExtent.height = textureRegion->h; + imageCopy.imageExtent.depth = textureRegion->d; + imageCopy.imageOffset.x = textureRegion->x; + imageCopy.imageOffset.y = textureRegion->y; + imageCopy.imageOffset.z = textureRegion->z; imageCopy.imageSubresource.aspectMask = vulkanTextureSlice->parent->aspectFlags; - imageCopy.imageSubresource.baseArrayLayer = textureSlice->layer; + imageCopy.imageSubresource.baseArrayLayer = textureRegion->textureSlice.layer; imageCopy.imageSubresource.layerCount = 1; - imageCopy.imageSubresource.mipLevel = textureSlice->mipLevel; + imageCopy.imageSubresource.mipLevel = textureRegion->textureSlice.mipLevel; imageCopy.bufferOffset = copyParams->bufferOffset; imageCopy.bufferRowLength = copyParams->bufferStride; imageCopy.bufferImageHeight = copyParams->bufferImageHeight; -- 2.25.1 From b64bf06c7b376ef7010332b5727d25a0746b83ee Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Fri, 1 Mar 2024 12:39:33 -0800 Subject: [PATCH 09/16] restructure binding APIs --- include/Refresh.h | 191 +++++++++---- src/Refresh.c | 68 ++--- src/Refresh_Driver.h | 34 +-- src/Refresh_Driver_Vulkan.c | 556 +++++++++++++++++++----------------- 4 files changed, 470 insertions(+), 379 deletions(-) diff --git a/include/Refresh.h b/include/Refresh.h index 5e80203..62eb51d 100644 --- a/include/Refresh.h +++ b/include/Refresh.h @@ -333,11 +333,11 @@ typedef enum Refresh_TransferOptions REFRESH_TRANSFEROPTIONS_OVERWRITE } Refresh_TransferOptions; -typedef enum Refresh_CopyOptions +typedef enum Refresh_WriteOptions { - REFRESH_COPYOPTIONS_SAFEDISCARD, - REFRESH_COPYOPTIONS_SAFEOVERWRITE -} Refresh_CopyOptions; + REFRESH_WRITEOPTIONS_SAFEDISCARD, + REFRESH_WRITEOPTIONS_SAFEOVERWRITE +} Refresh_WriteOptions; typedef enum Refresh_Backend { @@ -583,26 +583,91 @@ typedef struct Refresh_GraphicsPipelineCreateInfo /* Render pass structures */ +/* These structures define how textures will be read/written in a render pass. + * + * loadOp: Determines what is done with the texture slice at the beginning of the render pass. + * + * LOAD: + * Loads the texture slice. + * + * CLEAR: + * Clears the texture slice to a single color. + * + * DONT_CARE: + * The driver will do whatever it wants with the texture slice memory. + * This is a good option if you know that every single pixel will be touched in the render pass. + * + * storeOp: Determines what is done with the texture slice at the end of the render pass. + * + * STORE: + * Stores the results of the render pass in the texture slice. + * + * DONT_CARE: + * The driver will do whatever it wants with the texture slice memory. + * This is often a good option for depth/stencil textures. + * + * + * writeOption is ignored if loadOp is LOAD and is implicitly assumed to be SAFEOVERWRITE. + * Interleaving LOAD and SAFEDISCARD successively on the same texture (not slice!) is undefined behavior. + * + * writeOption: + * SAFEDISCARD: + * If this texture slice has been used in commands that have not completed, + * those commands will still be valid at the cost of increased memory usage. + * You may NOT assume that any of the previous texture data is retained. + * If the texture slice was not in use, this option is equivalent to SAFEOVERWRITE. + * This is a good option to prevent stalls when frequently reusing a texture slice in rendering. + * + * SAFEOVERWRITE: + * Overwrites the data safely using a GPU memory barrier. + */ + typedef struct Refresh_ColorAttachmentInfo { Refresh_TextureSlice textureSlice; - Refresh_Vec4 clearColor; /* Can be ignored by RenderPass */ + Refresh_Vec4 clearColor; /* Can be ignored by RenderPass if CLEAR is not used */ Refresh_LoadOp loadOp; Refresh_StoreOp storeOp; - uint8_t safeDiscard; /* ignored if loadOp is LOAD */ + Refresh_WriteOptions writeOption; } Refresh_ColorAttachmentInfo; typedef struct Refresh_DepthStencilAttachmentInfo { Refresh_TextureSlice textureSlice; - Refresh_DepthStencilValue depthStencilClearValue; /* Can be ignored by RenderPass */ + Refresh_DepthStencilValue depthStencilClearValue; /* Can be ignored by RenderPass if CLEAR is not used */ Refresh_LoadOp loadOp; Refresh_StoreOp storeOp; Refresh_LoadOp stencilLoadOp; Refresh_StoreOp stencilStoreOp; - uint8_t safeDiscard; /* ignored if either loadOp or stencilLoadOp is LOAD*/ + Refresh_WriteOptions writeOption; } Refresh_DepthStencilAttachmentInfo; +/* Binding structs */ + +typedef struct Refresh_BufferBinding +{ + Refresh_GpuBuffer *gpuBuffer; + uint32_t offset; +} Refresh_BufferBinding; + +typedef struct Refresh_TextureSamplerBinding +{ + Refresh_Texture *texture; + Refresh_Sampler *sampler; +} Refresh_TextureSamplerBinding; + +typedef struct Refresh_ComputeBufferBinding +{ + Refresh_GpuBuffer *gpuBuffer; + Refresh_WriteOptions writeOption; +} Refresh_ComputeBufferBinding; + +typedef struct Refresh_ComputeTextureBinding +{ + Refresh_TextureSlice textureSlice; + Refresh_WriteOptions writeOption; +} Refresh_ComputeTextureBinding; + /* Functions */ /* Logging */ @@ -828,49 +893,43 @@ REFRESHAPI void Refresh_BindVertexBuffers( Refresh_CommandBuffer *commandBuffer, uint32_t firstBinding, uint32_t bindingCount, - Refresh_GpuBuffer **pBuffers, - uint64_t *pOffsets + Refresh_BufferBinding *pBindings ); /* Binds an index buffer for use with subsequent draw calls. */ REFRESHAPI void Refresh_BindIndexBuffer( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, - Refresh_GpuBuffer *gpuBuffer, - uint64_t offset, + Refresh_BufferBinding *pBinding, Refresh_IndexElementSize indexElementSize ); /* Sets textures/samplers for use with the currently bound vertex shader. * * NOTE: - * The length of the passed arrays must be equal to the number + * The length of the bindings array must be equal to the number * of sampler bindings specified by the pipeline. * - * textures: A pointer to an array of textures. - * samplers: A pointer to an array of samplers. + * pBindings: A pointer to an array of TextureSamplerBindings. */ REFRESHAPI void Refresh_BindVertexSamplers( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, - Refresh_Texture **pTextures, - Refresh_Sampler **pSamplers + Refresh_TextureSamplerBinding *pBindings ); /* Sets textures/samplers for use with the currently bound fragment shader. * * NOTE: - * The length of the passed arrays must be equal to the number + * The length of the bindings array must be equal to the number * of sampler bindings specified by the pipeline. * - * textures: A pointer to an array of textures. - * samplers: A pointer to an array of samplers. + * pBindings: A pointer to an array of TextureSamplerBindings. */ REFRESHAPI void Refresh_BindFragmentSamplers( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, - Refresh_Texture **pTextures, - Refresh_Sampler **pSamplers + Refresh_TextureSamplerBinding *pBindings ); /* Pushes vertex shader uniforms to the device. @@ -991,26 +1050,28 @@ REFRESHAPI void Refresh_BindComputePipeline( /* Binds buffers for use with the currently bound compute pipeline. * - * pBuffers: An array of buffers to bind. - * Length must be equal to the number of buffers - * specified by the compute pipeline. + * pBindings: + * An array of ComputeBufferBinding structs. + * Length must be equal to the number of buffers + * specified by the compute pipeline. */ REFRESHAPI void Refresh_BindComputeBuffers( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, - Refresh_GpuBuffer **pBuffers + Refresh_ComputeBufferBinding *pBindings ); /* Binds textures for use with the currently bound compute pipeline. * - * pTextureSlices: An array of texture slices to bind. - * Length must be equal to the number of buffers + * pBindings: + * An array of ComputeTextureBinding structs. + * Length must be equal to the number of textures * specified by the compute pipeline. */ REFRESHAPI void Refresh_BindComputeTextures( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice **pTextureSlices + Refresh_ComputeTextureBinding *pBindings ); /* Pushes compute shader params to the device. @@ -1054,15 +1115,17 @@ REFRESHAPI void Refresh_EndComputePass( /* Immediately copies data from a pointer into a TransferBuffer. * - * option: + * transferOption: * SAFEDISCARD: - * If this TransferBuffer has been used in a copy command that has not completed, - * the issued copy commands will still be valid at the cost of increased memory usage. - * Otherwise the data will overwrite. + * If this TransferBuffer has been used in commands that have not completed, + * the issued commands will still be valid at the cost of increased memory usage. + * You may NOT assume that any of the previous data is retained. + * If the TransferBuffer was not in use, this option is equivalent to OVERWRITE. + * This is a good option to prevent stalls when frequently updating data. * It is not recommended to use this option with large TransferBuffers. * * OVERWRITE: - * Overwrites the data regardless of whether a copy has been issued. + * Overwrites the data regardless of whether a command has been issued. * Use this option with great care, as it can cause data races to occur! */ REFRESHAPI void Refresh_SetTransferData( @@ -1070,7 +1133,7 @@ REFRESHAPI void Refresh_SetTransferData( void* data, Refresh_TransferBuffer *transferBuffer, Refresh_BufferCopy *copyParams, - Refresh_TransferOptions option + Refresh_TransferOptions transferOption ); /* Immediately copies data from a TransferBuffer into a pointer. */ @@ -1095,16 +1158,17 @@ REFRESHAPI void Refresh_BeginCopyPass( */ /* - * option: + * writeOption: * SAFEDISCARD: - * If this TransferBuffer has been used in a copy command that has not completed, - * the issued copy commands will still be valid at the cost of increased memory usage. - * Otherwise the data will overwrite. + * If the destination resource has been used in commands that have not completed, + * the issued commands will still be valid at the cost of increased memory usage. + * You may NOT assume that any of the previous data is retained. + * If the destination resource was not in use, this option is equivalent to SAFEOVERWRITE. + * This is a good option to prevent stalls on resources with frequent updates. * It is not recommended to use this option with large resources. * - * OVERWRITE: - * Overwrites the data regardless of whether a copy has been issued. - * Use this option with great care, as it can cause data races to occur! + * SAFEOVERWRITE: + * Overwrites the data safely using a GPU memory barrier. */ /* Uploads data from a TransferBuffer to a texture. */ @@ -1114,7 +1178,7 @@ REFRESHAPI void Refresh_UploadToTexture( Refresh_TransferBuffer *transferBuffer, Refresh_TextureRegion *textureRegion, Refresh_BufferImageCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ); /* Uploads data from a TransferBuffer to a GpuBuffer. */ @@ -1124,7 +1188,7 @@ REFRESHAPI void Refresh_UploadToBuffer( Refresh_TransferBuffer *transferBuffer, Refresh_GpuBuffer *gpuBuffer, Refresh_BufferCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ); /* GPU-to-CPU copies occur on the GPU timeline. @@ -1133,6 +1197,20 @@ REFRESHAPI void Refresh_UploadToBuffer( * until the command buffer has finished execution. */ +/* + * transferOption: + * SAFEDISCARD: + * If this TransferBuffer has been used in commands that have not completed, + * the issued commands will still be valid at the cost of increased memory usage. + * You may NOT assume that any of the previous data is retained. + * If the TransferBuffer was not in use, this option is equivalent to OVERWRITE. + * It is not recommended to use this option with large TransferBuffers. + * + * OVERWRITE: + * Overwrites the data regardless of whether a command has been issued. + * Use this option with great care, as it can cause data races to occur! + */ + /* Downloads data from a texture to a TransferBuffer. */ REFRESHAPI void Refresh_DownloadFromTexture( Refresh_Device *device, @@ -1140,7 +1218,7 @@ REFRESHAPI void Refresh_DownloadFromTexture( Refresh_TextureRegion *textureRegion, Refresh_TransferBuffer *transferBuffer, Refresh_BufferImageCopy *copyParams, - Refresh_TransferOptions option + Refresh_TransferOptions transferOption ); /* Downloads data from a GpuBuffer object. */ @@ -1150,7 +1228,7 @@ REFRESHAPI void Refresh_DownloadFromBuffer( Refresh_GpuBuffer *gpuBuffer, Refresh_TransferBuffer *transferBuffer, Refresh_BufferCopy *copyParams, - Refresh_TransferOptions option + Refresh_TransferOptions transferOption ); /* GPU-to-GPU copies occur on the GPU timeline, @@ -1158,18 +1236,17 @@ REFRESHAPI void Refresh_DownloadFromBuffer( */ /* - * option: + * writeOption: * SAFEDISCARD: - * If the destination resource has been used in a copy command that has not completed, - * the issued copy commands will still be valid at the cost of increased memory usage. - * Otherwise the data will safely overwrite. + * If the destination resource has been used in commands that have not completed, + * the issued commands will still be valid at the cost of increased memory usage. + * You may NOT assume that any of the previous data is retained. + * If the destination resource was not in use, this option is equivalent to SAFEOVERWRITE. * This is a good option to prevent stalls on resources with frequent updates. * It is not recommended to use this option with large resources. * * SAFEOVERWRITE: - * Overwrites the data regardless of whether a copy has been issued. - * This will insert a memory barrier, so it could cause suboptimal performance compared to SAFEDISCARD - * on resources that update frequently across submissions. + * Overwrites the data safely using a GPU memory barrier. */ /* Performs a texture-to-texture copy. */ @@ -1178,7 +1255,7 @@ REFRESHAPI void Refresh_CopyTextureToTexture( Refresh_CommandBuffer *commandBuffer, Refresh_TextureRegion *source, Refresh_TextureRegion *destination, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ); /* Copies image data from a texture slice into a buffer. */ @@ -1188,7 +1265,7 @@ REFRESHAPI void Refresh_CopyTextureToBuffer( Refresh_TextureRegion *textureRegion, Refresh_GpuBuffer *gpuBuffer, Refresh_BufferImageCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ); /* Copies data from a buffer to a texture slice. */ @@ -1198,7 +1275,7 @@ REFRESHAPI void Refresh_CopyBufferToTexture( Refresh_GpuBuffer *gpuBuffer, Refresh_TextureRegion *textureRegion, Refresh_BufferImageCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ); /* Copies data from a buffer to a buffer. */ @@ -1208,7 +1285,7 @@ REFRESHAPI void Refresh_CopyBufferToBuffer( Refresh_GpuBuffer *source, Refresh_GpuBuffer *destination, Refresh_BufferCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ); /* Generate mipmaps for the given texture. */ diff --git a/src/Refresh.c b/src/Refresh.c index d6292c8..08cdfb4 100644 --- a/src/Refresh.c +++ b/src/Refresh.c @@ -461,8 +461,7 @@ void Refresh_BindVertexBuffers( Refresh_CommandBuffer *commandBuffer, uint32_t firstBinding, uint32_t bindingCount, - Refresh_GpuBuffer **pBuffers, - uint64_t *pOffsets + Refresh_BufferBinding *pBindings ) { NULL_RETURN(device); device->BindVertexBuffers( @@ -470,24 +469,21 @@ void Refresh_BindVertexBuffers( commandBuffer, firstBinding, bindingCount, - pBuffers, - pOffsets + pBindings ); } void Refresh_BindIndexBuffer( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, - Refresh_GpuBuffer *gpuBuffer, - uint64_t offset, + Refresh_BufferBinding *pBinding, Refresh_IndexElementSize indexElementSize ) { NULL_RETURN(device); device->BindIndexBuffer( device->driverData, commandBuffer, - gpuBuffer, - offset, + pBinding, indexElementSize ); } @@ -495,30 +491,26 @@ void Refresh_BindIndexBuffer( void Refresh_BindVertexSamplers( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, - Refresh_Texture **pTextures, - Refresh_Sampler **pSamplers + Refresh_TextureSamplerBinding *pBindings ) { NULL_RETURN(device); device->BindVertexSamplers( device->driverData, commandBuffer, - pTextures, - pSamplers + pBindings ); } void Refresh_BindFragmentSamplers( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, - Refresh_Texture **pTextures, - Refresh_Sampler **pSamplers + Refresh_TextureSamplerBinding *pBindings ) { NULL_RETURN(device); device->BindFragmentSamplers( device->driverData, commandBuffer, - pTextures, - pSamplers + pBindings ); } @@ -662,26 +654,26 @@ void Refresh_BindComputePipeline( void Refresh_BindComputeBuffers( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, - Refresh_GpuBuffer **pBuffers + Refresh_ComputeBufferBinding *pBindings ) { NULL_RETURN(device); device->BindComputeBuffers( device->driverData, commandBuffer, - pBuffers + pBindings ); } void Refresh_BindComputeTextures( Refresh_Device *device, Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice **pTextureSlices + Refresh_ComputeTextureBinding *pBindings ) { NULL_RETURN(device); device->BindComputeTextures( device->driverData, commandBuffer, - pTextureSlices + pBindings ); } @@ -735,7 +727,7 @@ void Refresh_SetTransferData( void* data, Refresh_TransferBuffer *transferBuffer, Refresh_BufferCopy *copyParams, - Refresh_TransferOptions option + Refresh_TransferOptions transferOption ) { NULL_RETURN(device); device->SetTransferData( @@ -743,7 +735,7 @@ void Refresh_SetTransferData( data, transferBuffer, copyParams, - option + transferOption ); } @@ -781,7 +773,7 @@ void Refresh_UploadToTexture( Refresh_TransferBuffer *transferBuffer, Refresh_TextureRegion *textureRegion, Refresh_BufferImageCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ) { NULL_RETURN(device); device->UploadToTexture( @@ -790,7 +782,7 @@ void Refresh_UploadToTexture( transferBuffer, textureRegion, copyParams, - option + writeOption ); } @@ -800,7 +792,7 @@ void Refresh_UploadToBuffer( Refresh_TransferBuffer *transferBuffer, Refresh_GpuBuffer *gpuBuffer, Refresh_BufferCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ) { NULL_RETURN(device); device->UploadToBuffer( @@ -809,7 +801,7 @@ void Refresh_UploadToBuffer( transferBuffer, gpuBuffer, copyParams, - option + writeOption ); } @@ -819,7 +811,7 @@ void Refresh_DownloadFromTexture( Refresh_TextureRegion *textureRegion, Refresh_TransferBuffer *transferBuffer, Refresh_BufferImageCopy *copyParams, - Refresh_TransferOptions option + Refresh_TransferOptions transferOption ) { NULL_RETURN(device); device->DownloadFromTexture( @@ -828,7 +820,7 @@ void Refresh_DownloadFromTexture( textureRegion, transferBuffer, copyParams, - option + transferOption ); } @@ -838,7 +830,7 @@ void Refresh_DownloadFromBuffer( Refresh_GpuBuffer *gpuBuffer, Refresh_TransferBuffer *transferBuffer, Refresh_BufferCopy *copyParams, - Refresh_TransferOptions option + Refresh_TransferOptions transferOption ) { NULL_RETURN(device); device->DownloadFromBuffer( @@ -847,7 +839,7 @@ void Refresh_DownloadFromBuffer( gpuBuffer, transferBuffer, copyParams, - option + transferOption ); } @@ -856,7 +848,7 @@ void Refresh_CopyTextureToTexture( Refresh_CommandBuffer *commandBuffer, Refresh_TextureRegion *source, Refresh_TextureRegion *destination, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ) { NULL_RETURN(device); device->CopyTextureToTexture( @@ -864,7 +856,7 @@ void Refresh_CopyTextureToTexture( commandBuffer, source, destination, - option + writeOption ); } @@ -874,7 +866,7 @@ void Refresh_CopyTextureToBuffer( Refresh_TextureRegion *textureRegion, Refresh_GpuBuffer *gpuBuffer, Refresh_BufferImageCopy *copyParameters, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ) { NULL_RETURN(device); device->CopyTextureToBuffer( @@ -883,7 +875,7 @@ void Refresh_CopyTextureToBuffer( textureRegion, gpuBuffer, copyParameters, - option + writeOption ); } @@ -893,7 +885,7 @@ void Refresh_CopyBufferToTexture( Refresh_GpuBuffer *gpuBuffer, Refresh_TextureRegion *textureRegion, Refresh_BufferImageCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ) { NULL_RETURN(device); device->CopyBufferToTexture( @@ -902,7 +894,7 @@ void Refresh_CopyBufferToTexture( gpuBuffer, textureRegion, copyParams, - option + writeOption ); } @@ -912,7 +904,7 @@ void Refresh_CopyBufferToBuffer( Refresh_GpuBuffer *source, Refresh_GpuBuffer *destination, Refresh_BufferCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ) { NULL_RETURN(device); device->CopyBufferToBuffer( @@ -921,7 +913,7 @@ void Refresh_CopyBufferToBuffer( source, destination, copyParams, - option + writeOption ); } diff --git a/src/Refresh_Driver.h b/src/Refresh_Driver.h index 38f7f69..a7d58c7 100644 --- a/src/Refresh_Driver.h +++ b/src/Refresh_Driver.h @@ -289,30 +289,26 @@ struct Refresh_Device Refresh_CommandBuffer *commandBuffer, uint32_t firstBinding, uint32_t bindingCount, - Refresh_GpuBuffer **pBuffers, - uint64_t *pOffsets + Refresh_BufferBinding *pBindings ); void (*BindIndexBuffer)( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_GpuBuffer *gpuBuffer, - uint64_t offset, + Refresh_BufferBinding *pBinding, Refresh_IndexElementSize indexElementSize ); void (*BindVertexSamplers)( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_Texture **pTextures, - Refresh_Sampler **pSamplers + Refresh_TextureSamplerBinding *pBindings ); void (*BindFragmentSamplers)( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_Texture **pTextures, - Refresh_Sampler **pSamplers + Refresh_TextureSamplerBinding *pBindings ); void (*PushVertexShaderUniforms)( @@ -383,13 +379,13 @@ struct Refresh_Device void (*BindComputeBuffers)( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_GpuBuffer **pBuffers + Refresh_ComputeBufferBinding *pBindings ); void (*BindComputeTextures)( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice **pTextureSlices + Refresh_ComputeTextureBinding *pBindings ); void (*PushComputeShaderUniforms)( @@ -419,7 +415,7 @@ struct Refresh_Device void* data, Refresh_TransferBuffer *transferBuffer, Refresh_BufferCopy *copyParams, - Refresh_TransferOptions option + Refresh_TransferOptions transferOption ); void (*GetTransferData)( @@ -442,7 +438,7 @@ struct Refresh_Device Refresh_TransferBuffer *transferBuffer, Refresh_TextureRegion *textureSlice, Refresh_BufferImageCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ); void (*UploadToBuffer)( @@ -451,7 +447,7 @@ struct Refresh_Device Refresh_TransferBuffer *transferBuffer, Refresh_GpuBuffer *gpuBuffer, Refresh_BufferCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ); void (*DownloadFromTexture)( @@ -460,7 +456,7 @@ struct Refresh_Device Refresh_TextureRegion *textureSlice, Refresh_TransferBuffer *transferBuffer, Refresh_BufferImageCopy *copyParams, - Refresh_TransferOptions option + Refresh_TransferOptions transferOption ); void (*DownloadFromBuffer)( @@ -469,7 +465,7 @@ struct Refresh_Device Refresh_GpuBuffer *gpuBuffer, Refresh_TransferBuffer *transferBuffer, Refresh_BufferCopy *copyParams, - Refresh_TransferOptions option + Refresh_TransferOptions transferOption ); void (*CopyTextureToTexture)( @@ -477,7 +473,7 @@ struct Refresh_Device Refresh_CommandBuffer *commandBuffer, Refresh_TextureRegion *source, Refresh_TextureRegion *destination, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ); void (*CopyTextureToBuffer)( @@ -486,7 +482,7 @@ struct Refresh_Device Refresh_TextureRegion *textureSlice, Refresh_GpuBuffer *gpuBuffer, Refresh_BufferImageCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ); void (*CopyBufferToTexture)( @@ -495,7 +491,7 @@ struct Refresh_Device Refresh_GpuBuffer *gpuBuffer, Refresh_TextureRegion *textureSlice, Refresh_BufferImageCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ); void (*CopyBufferToBuffer)( @@ -504,7 +500,7 @@ struct Refresh_Device Refresh_GpuBuffer *source, Refresh_GpuBuffer *destination, Refresh_BufferCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ); void (*GenerateMipmaps)( diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index 08d5bba..c899c80 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -5712,6 +5712,49 @@ static VulkanTextureHandle* VULKAN_INTERNAL_CreateTextureHandle( return textureHandle; } +static void VULKAN_INTERNAL_DiscardActiveBuffer( + VulkanRenderer *renderer, + VulkanBufferContainer *bufferContainer +) { + VulkanBufferHandle *bufferHandle; + uint32_t i; + + /* If a previously-discarded buffer is available, we can use that. */ + for (i = 0; i < bufferContainer->bufferCount; i += 1) + { + bufferHandle = bufferContainer->bufferHandles[i]; + if (SDL_AtomicGet(&bufferHandle->vulkanBuffer->referenceCount) == 0) + { + bufferContainer->activeBufferHandle = bufferHandle; + return; + } + } + + /* No buffer handle is available, generate a new one. */ + bufferContainer->activeBufferHandle = VULKAN_INTERNAL_CreateBufferHandle( + renderer, + bufferContainer->activeBufferHandle->vulkanBuffer->size, + RESOURCE_ACCESS_NONE, + bufferContainer->activeBufferHandle->vulkanBuffer->usage, + bufferContainer->activeBufferHandle->vulkanBuffer->requireHostVisible, + bufferContainer->activeBufferHandle->vulkanBuffer->preferHostLocal, + bufferContainer->activeBufferHandle->vulkanBuffer->preferDeviceLocal + ); + + EXPAND_ARRAY_IF_NEEDED( + bufferContainer->bufferHandles, + VulkanBufferHandle*, + bufferContainer->bufferCount + 1, + bufferContainer->bufferCapacity, + bufferContainer->bufferCapacity * 2 + ); + + bufferContainer->bufferHandles[ + bufferContainer->bufferCount + ] = bufferContainer->activeBufferHandle; + bufferContainer->bufferCount += 1; +} + static void VULKAN_INTERNAL_DiscardActiveTexture( VulkanRenderer *renderer, VulkanTextureContainer *textureContainer @@ -7172,98 +7215,6 @@ static VkDescriptorSet VULKAN_INTERNAL_FetchDescriptorSet( return descriptorSet; } -static void VULKAN_BindVertexSamplers( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_Texture **pTextures, - Refresh_Sampler **pSamplers -) { - VulkanRenderer* renderer = (VulkanRenderer*) driverData; - VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanGraphicsPipeline *graphicsPipeline = vulkanCommandBuffer->currentGraphicsPipeline; - - VulkanTexture *currentTexture; - VulkanSampler *currentSampler; - uint32_t i, samplerCount, sliceIndex; - VkDescriptorImageInfo descriptorImageInfos[MAX_TEXTURE_SAMPLERS]; - - if (graphicsPipeline->pipelineLayout->vertexSamplerDescriptorSetCache == NULL) - { - return; - } - - samplerCount = graphicsPipeline->pipelineLayout->vertexSamplerDescriptorSetCache->bindingCount; - - for (i = 0; i < samplerCount; i += 1) - { - currentTexture = ((VulkanTextureContainer*) pTextures[i])->activeTextureHandle->vulkanTexture; - currentSampler = (VulkanSampler*) pSamplers[i]; - descriptorImageInfos[i].imageView = currentTexture->view; - descriptorImageInfos[i].sampler = currentSampler->sampler; - descriptorImageInfos[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - 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( - renderer, - vulkanCommandBuffer, - graphicsPipeline->pipelineLayout->vertexSamplerDescriptorSetCache, - descriptorImageInfos, - NULL - ); -} - -static void VULKAN_BindFragmentSamplers( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_Texture **pTextures, - Refresh_Sampler **pSamplers -) { - VulkanRenderer* renderer = (VulkanRenderer*) driverData; - VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanGraphicsPipeline *graphicsPipeline = vulkanCommandBuffer->currentGraphicsPipeline; - - VulkanTexture *currentTexture; - VulkanSampler *currentSampler; - uint32_t i, samplerCount, sliceIndex; - VkDescriptorImageInfo descriptorImageInfos[MAX_TEXTURE_SAMPLERS]; - - if (graphicsPipeline->pipelineLayout->fragmentSamplerDescriptorSetCache == NULL) - { - return; - } - - samplerCount = graphicsPipeline->pipelineLayout->fragmentSamplerDescriptorSetCache->bindingCount; - - for (i = 0; i < samplerCount; i += 1) - { - currentTexture = ((VulkanTextureContainer*) pTextures[i])->activeTextureHandle->vulkanTexture; - currentSampler = (VulkanSampler*) pSamplers[i]; - descriptorImageInfos[i].imageView = currentTexture->view; - descriptorImageInfos[i].sampler = currentSampler->sampler; - descriptorImageInfos[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - - 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( - renderer, - vulkanCommandBuffer, - graphicsPipeline->pipelineLayout->fragmentSamplerDescriptorSetCache, - descriptorImageInfos, - NULL - ); -} - static void VULKAN_INTERNAL_QueueDestroyTexture( VulkanRenderer *renderer, VulkanTexture *vulkanTexture @@ -7793,7 +7744,7 @@ static void VULKAN_BeginRenderPass( textureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&colorAttachmentInfos[i].textureSlice); if ( - colorAttachmentInfos[i].safeDiscard && + colorAttachmentInfos[i].writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD && colorAttachmentInfos[i].loadOp != REFRESH_LOADOP_LOAD && textureContainer->canBeDiscarded && SDL_AtomicGet(&textureSlice->referenceCount) > 0 @@ -7805,7 +7756,6 @@ static void VULKAN_BeginRenderPass( textureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&colorAttachmentInfos[i].textureSlice); } - w = textureSlice->parent->dimensions.width >> colorAttachmentInfos[i].textureSlice.mipLevel; h = textureSlice->parent->dimensions.height >> colorAttachmentInfos[i].textureSlice.mipLevel; @@ -7834,7 +7784,7 @@ static void VULKAN_BeginRenderPass( textureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&depthStencilAttachmentInfo->textureSlice); if ( - depthStencilAttachmentInfo->safeDiscard && + depthStencilAttachmentInfo->writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD && depthStencilAttachmentInfo->loadOp != REFRESH_LOADOP_LOAD && depthStencilAttachmentInfo->stencilLoadOp != REFRESH_LOADOP_LOAD && textureContainer->canBeDiscarded && @@ -8031,6 +7981,197 @@ static void VULKAN_BeginRenderPass( ); } +static void VULKAN_BindGraphicsPipeline( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_GraphicsPipeline *graphicsPipeline +) { + VulkanRenderer* renderer = (VulkanRenderer*) driverData; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + VulkanGraphicsPipeline* pipeline = (VulkanGraphicsPipeline*) graphicsPipeline; + + /* bind dummy sets if necessary */ + if (pipeline->pipelineLayout->vertexSamplerDescriptorSetCache == NULL) + { + vulkanCommandBuffer->vertexSamplerDescriptorSet = renderer->emptyVertexSamplerDescriptorSet; + } + + if (pipeline->pipelineLayout->fragmentSamplerDescriptorSetCache == NULL) + { + vulkanCommandBuffer->fragmentSamplerDescriptorSet = renderer->emptyFragmentSamplerDescriptorSet; + } + + renderer->vkCmdBindPipeline( + vulkanCommandBuffer->commandBuffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, + pipeline->pipeline + ); + + vulkanCommandBuffer->currentGraphicsPipeline = pipeline; + + VULKAN_INTERNAL_TrackGraphicsPipeline(renderer, vulkanCommandBuffer, pipeline); + + renderer->vkCmdSetViewport( + vulkanCommandBuffer->commandBuffer, + 0, + 1, + &vulkanCommandBuffer->currentViewport + ); + + renderer->vkCmdSetScissor( + vulkanCommandBuffer->commandBuffer, + 0, + 1, + &vulkanCommandBuffer->currentScissor + ); +} + +static void VULKAN_BindVertexBuffers( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + Refresh_BufferBinding *pBindings +) { + VulkanRenderer* renderer = (VulkanRenderer*) driverData; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + VulkanBuffer *currentVulkanBuffer; + VkBuffer *buffers = SDL_stack_alloc(VkBuffer, bindingCount); + VkDeviceSize *offsets = SDL_stack_alloc(VkDeviceSize, bindingCount); + uint32_t i; + + for (i = 0; i < bindingCount; i += 1) + { + currentVulkanBuffer = ((VulkanBufferContainer*) pBindings[i].gpuBuffer)->activeBufferHandle->vulkanBuffer; + buffers[i] = currentVulkanBuffer->buffer; + offsets[i] = (VkDeviceSize) pBindings[i].offset; + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, currentVulkanBuffer); + } + + renderer->vkCmdBindVertexBuffers( + vulkanCommandBuffer->commandBuffer, + firstBinding, + bindingCount, + buffers, + offsets + ); + + SDL_stack_free(buffers); + SDL_stack_free(offsets); +} + +static void VULKAN_BindIndexBuffer( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_BufferBinding *pBinding, + Refresh_IndexElementSize indexElementSize +) { + VulkanRenderer* renderer = (VulkanRenderer*) driverData; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + VulkanBuffer* vulkanBuffer = ((VulkanBufferContainer*) pBinding->gpuBuffer)->activeBufferHandle->vulkanBuffer; + + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanBuffer); + + renderer->vkCmdBindIndexBuffer( + vulkanCommandBuffer->commandBuffer, + vulkanBuffer->buffer, + (VkDeviceSize) pBinding->offset, + RefreshToVK_IndexType[indexElementSize] + ); +} + +static void VULKAN_BindVertexSamplers( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_TextureSamplerBinding *pBindings +) { + VulkanRenderer* renderer = (VulkanRenderer*) driverData; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + VulkanGraphicsPipeline *graphicsPipeline = vulkanCommandBuffer->currentGraphicsPipeline; + + VulkanTexture *currentTexture; + VulkanSampler *currentSampler; + uint32_t i, samplerCount, sliceIndex; + VkDescriptorImageInfo descriptorImageInfos[MAX_TEXTURE_SAMPLERS]; + + if (graphicsPipeline->pipelineLayout->vertexSamplerDescriptorSetCache == NULL) + { + return; + } + + samplerCount = graphicsPipeline->pipelineLayout->vertexSamplerDescriptorSetCache->bindingCount; + + for (i = 0; i < samplerCount; i += 1) + { + currentTexture = ((VulkanTextureContainer*) pBindings[i].texture)->activeTextureHandle->vulkanTexture; + currentSampler = (VulkanSampler*) pBindings[i].sampler; + + descriptorImageInfos[i].imageView = currentTexture->view; + descriptorImageInfos[i].sampler = currentSampler->sampler; + descriptorImageInfos[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + 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( + renderer, + vulkanCommandBuffer, + graphicsPipeline->pipelineLayout->vertexSamplerDescriptorSetCache, + descriptorImageInfos, + NULL + ); +} + +static void VULKAN_BindFragmentSamplers( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_TextureSamplerBinding *pBindings +) { + VulkanRenderer* renderer = (VulkanRenderer*) driverData; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + VulkanGraphicsPipeline *graphicsPipeline = vulkanCommandBuffer->currentGraphicsPipeline; + + VulkanTexture *currentTexture; + VulkanSampler *currentSampler; + uint32_t i, samplerCount, sliceIndex; + VkDescriptorImageInfo descriptorImageInfos[MAX_TEXTURE_SAMPLERS]; + + if (graphicsPipeline->pipelineLayout->fragmentSamplerDescriptorSetCache == NULL) + { + return; + } + + samplerCount = graphicsPipeline->pipelineLayout->fragmentSamplerDescriptorSetCache->bindingCount; + + for (i = 0; i < samplerCount; i += 1) + { + currentTexture = ((VulkanTextureContainer*) pBindings[i].texture)->activeTextureHandle->vulkanTexture; + currentSampler = (VulkanSampler*) pBindings[i].sampler; + + descriptorImageInfos[i].imageView = currentTexture->view; + descriptorImageInfos[i].sampler = currentSampler->sampler; + descriptorImageInfos[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + 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( + renderer, + vulkanCommandBuffer, + graphicsPipeline->pipelineLayout->fragmentSamplerDescriptorSetCache, + descriptorImageInfos, + NULL + ); +} + static void VULKAN_EndRenderPass( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer @@ -8089,104 +8230,6 @@ static void VULKAN_EndRenderPass( vulkanCommandBuffer->currentGraphicsPipeline = NULL; } -static void VULKAN_BindGraphicsPipeline( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_GraphicsPipeline *graphicsPipeline -) { - VulkanRenderer* renderer = (VulkanRenderer*) driverData; - VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanGraphicsPipeline* pipeline = (VulkanGraphicsPipeline*) graphicsPipeline; - - /* bind dummy sets if necessary */ - if (pipeline->pipelineLayout->vertexSamplerDescriptorSetCache == NULL) - { - vulkanCommandBuffer->vertexSamplerDescriptorSet = renderer->emptyVertexSamplerDescriptorSet; - } - - if (pipeline->pipelineLayout->fragmentSamplerDescriptorSetCache == NULL) - { - vulkanCommandBuffer->fragmentSamplerDescriptorSet = renderer->emptyFragmentSamplerDescriptorSet; - } - - renderer->vkCmdBindPipeline( - vulkanCommandBuffer->commandBuffer, - VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeline->pipeline - ); - - vulkanCommandBuffer->currentGraphicsPipeline = pipeline; - - VULKAN_INTERNAL_TrackGraphicsPipeline(renderer, vulkanCommandBuffer, pipeline); - - renderer->vkCmdSetViewport( - vulkanCommandBuffer->commandBuffer, - 0, - 1, - &vulkanCommandBuffer->currentViewport - ); - - renderer->vkCmdSetScissor( - vulkanCommandBuffer->commandBuffer, - 0, - 1, - &vulkanCommandBuffer->currentScissor - ); -} - -static void VULKAN_BindVertexBuffers( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - uint32_t firstBinding, - uint32_t bindingCount, - Refresh_GpuBuffer **pBuffers, - uint64_t *pOffsets -) { - VulkanRenderer* renderer = (VulkanRenderer*) driverData; - VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanBuffer *currentVulkanBuffer; - VkBuffer *buffers = SDL_stack_alloc(VkBuffer, bindingCount); - uint32_t i; - - for (i = 0; i < bindingCount; i += 1) - { - currentVulkanBuffer = ((VulkanBufferContainer*) pBuffers[i])->activeBufferHandle->vulkanBuffer; - buffers[i] = currentVulkanBuffer->buffer; - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, currentVulkanBuffer); - } - - renderer->vkCmdBindVertexBuffers( - vulkanCommandBuffer->commandBuffer, - firstBinding, - bindingCount, - buffers, - pOffsets - ); - - SDL_stack_free(buffers); -} - -static void VULKAN_BindIndexBuffer( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_GpuBuffer *gpuBuffer, - uint64_t offset, - Refresh_IndexElementSize indexElementSize -) { - VulkanRenderer* renderer = (VulkanRenderer*) driverData; - VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanBuffer* vulkanBuffer = ((VulkanBufferContainer*) gpuBuffer)->activeBufferHandle->vulkanBuffer; - - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanBuffer); - - renderer->vkCmdBindIndexBuffer( - vulkanCommandBuffer->commandBuffer, - vulkanBuffer->buffer, - offset, - RefreshToVK_IndexType[indexElementSize] - ); -} - static void VULKAN_BeginComputePass( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer @@ -8231,12 +8274,13 @@ static void VULKAN_BindComputePipeline( static void VULKAN_BindComputeBuffers( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_GpuBuffer **pBuffers + Refresh_ComputeBufferBinding *pBindings ) { VulkanRenderer* renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanComputePipeline *computePipeline = vulkanCommandBuffer->currentComputePipeline; + VulkanBufferContainer *bufferContainer; VulkanBuffer *currentVulkanBuffer; VkDescriptorBufferInfo descriptorBufferInfos[MAX_BUFFER_BINDINGS]; uint32_t i; @@ -8248,11 +8292,19 @@ static void VULKAN_BindComputeBuffers( for (i = 0; i < computePipeline->pipelineLayout->bufferDescriptorSetCache->bindingCount; i += 1) { - currentVulkanBuffer = ((VulkanBufferContainer*) pBuffers[i])->activeBufferHandle->vulkanBuffer; + bufferContainer = (VulkanBufferContainer*) pBindings[i].gpuBuffer; + currentVulkanBuffer = bufferContainer->activeBufferHandle->vulkanBuffer; - descriptorBufferInfos[i].buffer = currentVulkanBuffer->buffer; - descriptorBufferInfos[i].offset = 0; - descriptorBufferInfos[i].range = currentVulkanBuffer->size; + if ( + pBindings[i].writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD && + SDL_AtomicGet(&bufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 + ) { + VULKAN_INTERNAL_DiscardActiveBuffer( + renderer, + bufferContainer + ); + currentVulkanBuffer = bufferContainer->activeBufferHandle->vulkanBuffer; + } VULKAN_INTERNAL_BufferMemoryBarrier( renderer, @@ -8261,6 +8313,10 @@ static void VULKAN_BindComputeBuffers( currentVulkanBuffer ); + descriptorBufferInfos[i].buffer = currentVulkanBuffer->buffer; + descriptorBufferInfos[i].offset = 0; + descriptorBufferInfos[i].range = currentVulkanBuffer->size; + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, currentVulkanBuffer); VULKAN_INTERNAL_TrackComputeBuffer(renderer, vulkanCommandBuffer, currentVulkanBuffer); } @@ -8278,12 +8334,12 @@ static void VULKAN_BindComputeBuffers( static void VULKAN_BindComputeTextures( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice **pTextureSlices + Refresh_ComputeTextureBinding *pBindings ) { VulkanRenderer* renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; VulkanComputePipeline *computePipeline = vulkanCommandBuffer->currentComputePipeline; - + VulkanTextureContainer *currentTextureContainer; VulkanTextureSlice *currentTextureSlice; VkDescriptorImageInfo descriptorImageInfos[MAX_TEXTURE_SAMPLERS]; uint32_t i; @@ -8295,10 +8351,19 @@ static void VULKAN_BindComputeTextures( for (i = 0; i < computePipeline->pipelineLayout->imageDescriptorSetCache->bindingCount; i += 1) { - currentTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(pTextureSlices[i]); - descriptorImageInfos[i].imageView = currentTextureSlice->view; - descriptorImageInfos[i].sampler = VK_NULL_HANDLE; - descriptorImageInfos[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; + currentTextureContainer = (VulkanTextureContainer*) pBindings[i].textureSlice.texture; + currentTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&pBindings[i].textureSlice); + + if ( + pBindings[i].writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD && + SDL_AtomicGet(¤tTextureSlice->referenceCount) > 0 + ) { + VULKAN_INTERNAL_DiscardActiveTexture( + renderer, + currentTextureContainer + ); + currentTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&pBindings[i].textureSlice); + } VULKAN_INTERNAL_ImageMemoryBarrier( renderer, @@ -8307,6 +8372,10 @@ static void VULKAN_BindComputeTextures( currentTextureSlice ); + descriptorImageInfos[i].imageView = currentTextureSlice->view; + descriptorImageInfos[i].sampler = VK_NULL_HANDLE; + descriptorImageInfos[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; + VULKAN_INTERNAL_TrackTextureSlice(renderer, vulkanCommandBuffer, currentTextureSlice); VULKAN_INTERNAL_TrackComputeTextureSlice(renderer, vulkanCommandBuffer, currentTextureSlice); } @@ -8415,61 +8484,18 @@ static void VULKAN_EndComputePass( vulkanCommandBuffer->currentComputePipeline = NULL; } -static void VULKAN_INTERNAL_DiscardActiveBuffer( - VulkanRenderer *renderer, - VulkanBufferContainer *bufferContainer -) { - VulkanBufferHandle *bufferHandle; - uint32_t i; - - /* If a previously-discarded buffer is available, we can use that. */ - for (i = 0; i < bufferContainer->bufferCount; i += 1) - { - bufferHandle = bufferContainer->bufferHandles[i]; - if (SDL_AtomicGet(&bufferHandle->vulkanBuffer->referenceCount) == 0) - { - bufferContainer->activeBufferHandle = bufferHandle; - return; - } - } - - /* No buffer handle is available, generate a new one. */ - bufferContainer->activeBufferHandle = VULKAN_INTERNAL_CreateBufferHandle( - renderer, - bufferContainer->activeBufferHandle->vulkanBuffer->size, - RESOURCE_ACCESS_NONE, - bufferContainer->activeBufferHandle->vulkanBuffer->usage, - bufferContainer->activeBufferHandle->vulkanBuffer->requireHostVisible, - bufferContainer->activeBufferHandle->vulkanBuffer->preferHostLocal, - bufferContainer->activeBufferHandle->vulkanBuffer->preferDeviceLocal - ); - - EXPAND_ARRAY_IF_NEEDED( - bufferContainer->bufferHandles, - VulkanBufferHandle*, - bufferContainer->bufferCount + 1, - bufferContainer->bufferCapacity, - bufferContainer->bufferCapacity * 2 - ); - - bufferContainer->bufferHandles[ - bufferContainer->bufferCount - ] = bufferContainer->activeBufferHandle; - bufferContainer->bufferCount += 1; -} - static void VULKAN_SetTransferData( Refresh_Renderer *driverData, void* data, Refresh_TransferBuffer *transferBuffer, Refresh_BufferCopy *copyParams, - Refresh_TransferOptions option + Refresh_TransferOptions transferOption ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer*) transferBuffer; if ( - option == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && + transferOption == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 ) { VULKAN_INTERNAL_DiscardActiveBuffer( @@ -8529,7 +8555,7 @@ static void VULKAN_UploadToTexture( Refresh_TransferBuffer *transferBuffer, Refresh_TextureRegion *textureRegion, Refresh_BufferImageCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; @@ -8541,7 +8567,7 @@ static void VULKAN_UploadToTexture( vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); if ( - option == REFRESH_COPYOPTIONS_SAFEDISCARD && + writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD && vulkanTextureContainer->canBeDiscarded && SDL_AtomicGet(&vulkanTextureSlice->referenceCount) > 0 ) { @@ -8601,7 +8627,7 @@ static void VULKAN_UploadToBuffer( Refresh_TransferBuffer *transferBuffer, Refresh_GpuBuffer *gpuBuffer, Refresh_BufferCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; @@ -8610,7 +8636,7 @@ static void VULKAN_UploadToBuffer( VkBufferCopy bufferCopy; if ( - option == REFRESH_COPYOPTIONS_SAFEDISCARD && + writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD && SDL_AtomicGet(&gpuBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 ) { VULKAN_INTERNAL_DiscardActiveBuffer( @@ -8656,7 +8682,7 @@ static void VULKAN_DownloadFromTexture( Refresh_TextureRegion *textureRegion, Refresh_TransferBuffer *transferBuffer, Refresh_BufferImageCopy *copyParams, - Refresh_TransferOptions option + Refresh_TransferOptions transferOption ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; @@ -8667,7 +8693,7 @@ static void VULKAN_DownloadFromTexture( vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); if ( - option == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && + transferOption == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 ) { VULKAN_INTERNAL_DiscardActiveBuffer( @@ -8725,7 +8751,7 @@ static void VULKAN_DownloadFromBuffer( Refresh_GpuBuffer *gpuBuffer, Refresh_TransferBuffer *transferBuffer, Refresh_BufferCopy *copyParams, - Refresh_TransferOptions option + Refresh_TransferOptions transferOption ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; @@ -8734,7 +8760,7 @@ static void VULKAN_DownloadFromBuffer( VkBufferCopy bufferCopy; if ( - option == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && + transferOption == REFRESH_TRANSFEROPTIONS_SAFEDISCARD && SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 ) { VULKAN_INTERNAL_DiscardActiveBuffer( @@ -8779,7 +8805,7 @@ static void VULKAN_CopyTextureToTexture( Refresh_CommandBuffer *commandBuffer, Refresh_TextureRegion *source, Refresh_TextureRegion *destination, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; @@ -8792,7 +8818,7 @@ static void VULKAN_CopyTextureToTexture( dstSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&destination->textureSlice); if ( - option == REFRESH_COPYOPTIONS_SAFEDISCARD && + writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD && dstContainer->canBeDiscarded && SDL_AtomicGet(&dstSlice->referenceCount) > 0 ) { @@ -8857,7 +8883,7 @@ static void VULKAN_CopyTextureToBuffer( Refresh_TextureRegion *textureRegion, Refresh_GpuBuffer *gpuBuffer, Refresh_BufferImageCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; @@ -8868,7 +8894,7 @@ static void VULKAN_CopyTextureToBuffer( vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); if ( - option == REFRESH_COPYOPTIONS_SAFEDISCARD && + writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD && SDL_AtomicGet(&bufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 ) { VULKAN_INTERNAL_DiscardActiveBuffer( @@ -8926,7 +8952,7 @@ static void VULKAN_CopyBufferToTexture( Refresh_GpuBuffer *gpuBuffer, Refresh_TextureRegion *textureRegion, Refresh_BufferImageCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; @@ -8938,7 +8964,7 @@ static void VULKAN_CopyBufferToTexture( vulkanTextureSlice = VULKAN_INTERNAL_RefreshToVulkanTextureSlice(&textureRegion->textureSlice); if ( - option == REFRESH_COPYOPTIONS_SAFEDISCARD && + writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD && textureContainer->canBeDiscarded && SDL_AtomicGet(&vulkanTextureSlice->referenceCount) > 0 ) { @@ -8998,7 +9024,7 @@ static void VULKAN_CopyBufferToBuffer( Refresh_GpuBuffer *source, Refresh_GpuBuffer *destination, Refresh_BufferCopy *copyParams, - Refresh_CopyOptions option + Refresh_WriteOptions writeOption ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; @@ -9007,7 +9033,7 @@ static void VULKAN_CopyBufferToBuffer( VkBufferCopy bufferCopy; if ( - option == REFRESH_COPYOPTIONS_SAFEDISCARD && + writeOption == REFRESH_WRITEOPTIONS_SAFEDISCARD && SDL_AtomicGet(&dstContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0 ) { VULKAN_INTERNAL_DiscardActiveBuffer( -- 2.25.1 From a3249404bc9e8951c9e83b2f363df6015ca25c00 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Fri, 1 Mar 2024 13:10:44 -0800 Subject: [PATCH 10/16] clarify writeOption behavior --- include/Refresh.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/Refresh.h b/include/Refresh.h index 62eb51d..8626533 100644 --- a/include/Refresh.h +++ b/include/Refresh.h @@ -588,7 +588,7 @@ typedef struct Refresh_GraphicsPipelineCreateInfo * loadOp: Determines what is done with the texture slice at the beginning of the render pass. * * LOAD: - * Loads the texture slice. + * Loads the data currently in the texture slice. * * CLEAR: * Clears the texture slice to a single color. @@ -613,7 +613,7 @@ typedef struct Refresh_GraphicsPipelineCreateInfo * writeOption: * SAFEDISCARD: * If this texture slice has been used in commands that have not completed, - * those commands will still be valid at the cost of increased memory usage. + * this option will prevent a data dependency at the cost of increased memory usage. * You may NOT assume that any of the previous texture data is retained. * If the texture slice was not in use, this option is equivalent to SAFEOVERWRITE. * This is a good option to prevent stalls when frequently reusing a texture slice in rendering. @@ -1161,7 +1161,7 @@ REFRESHAPI void Refresh_BeginCopyPass( * writeOption: * SAFEDISCARD: * If the destination resource has been used in commands that have not completed, - * the issued commands will still be valid at the cost of increased memory usage. + * this option will prevent a data dependency at the cost of increased memory usage. * You may NOT assume that any of the previous data is retained. * If the destination resource was not in use, this option is equivalent to SAFEOVERWRITE. * This is a good option to prevent stalls on resources with frequent updates. @@ -1239,7 +1239,7 @@ REFRESHAPI void Refresh_DownloadFromBuffer( * writeOption: * SAFEDISCARD: * If the destination resource has been used in commands that have not completed, - * the issued commands will still be valid at the cost of increased memory usage. + * this option will prevent a data dependency at the cost of increased memory usage. * You may NOT assume that any of the previous data is retained. * If the destination resource was not in use, this option is equivalent to SAFEOVERWRITE. * This is a good option to prevent stalls on resources with frequent updates. -- 2.25.1 From 42d62d423ae602d57f85c0b9daddecdd00b4eb1f Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Fri, 1 Mar 2024 15:38:18 -0800 Subject: [PATCH 11/16] limit max frames in flight --- src/Refresh_Driver_Vulkan.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index c899c80..cc4d589 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -80,6 +80,7 @@ typedef struct VulkanExtensions #define UBO_BUFFER_SIZE 16777216 /* 16MB */ #define MAX_UBO_SECTION_SIZE 4096 /* 4KB */ #define DESCRIPTOR_POOL_STARTING_SIZE 128 +#define MAX_FRAMES_IN_FLIGHT 3 #define WINDOW_DATA "Refresh_VulkanWindowData" #define IDENTITY_SWIZZLE \ @@ -875,6 +876,8 @@ typedef struct VulkanSwapchainData /* Synchronization primitives */ VkSemaphore imageAvailableSemaphore; VkSemaphore renderFinishedSemaphore; + + uint32_t submissionsInFlight; } VulkanSwapchainData; typedef struct WindowData @@ -4639,6 +4642,7 @@ static uint8_t VULKAN_INTERNAL_CreateSwapchain( uint32_t i; swapchainData = SDL_malloc(sizeof(VulkanSwapchainData)); + swapchainData->submissionsInFlight = 0; /* Each swapchain must have its own surface. */ @@ -9616,6 +9620,12 @@ static Refresh_Texture* VULKAN_AcquireSwapchainTexture( swapchainData = windowData->swapchainData; + /* Drop frames if too many submissions in flight */ + if (swapchainData->submissionsInFlight >= MAX_FRAMES_IN_FLIGHT) + { + return NULL; + } + /* Window is claimed but swapchain is invalid! */ if (swapchainData == NULL) { @@ -10057,6 +10067,11 @@ static void VULKAN_INTERNAL_CleanCommandBuffer( /* Reset presentation data */ + for (i = 0; i < commandBuffer->presentDataCount; i += 1) + { + commandBuffer->presentDatas[i].windowData->swapchainData->submissionsInFlight -= 1; + } + commandBuffer->presentDataCount = 0; commandBuffer->waitSemaphoreCount = 0; commandBuffer->signalSemaphoreCount = 0; @@ -10255,6 +10270,10 @@ static void VULKAN_Submit( presentData->windowData ); } + else + { + presentData->windowData->swapchainData->submissionsInFlight += 1; + } } /* Check if we can perform any cleanups */ -- 2.25.1 From 9d04bca2e29fc0a3ab995480ab4e7885d5dce116 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Fri, 1 Mar 2024 15:47:25 -0800 Subject: [PATCH 12/16] use powers of 2 for allocation sizes --- src/Refresh_Driver_Vulkan.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index cc4d589..58696bd 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -1,4 +1,4 @@ -/* Refresh - XNA-inspired 3D Graphics Library with modern capabilities +/* Refresh - XNA-inspired 3D Graphics Library with modern capabilities * * Copyright (c) 2020 Evan Hemsley * @@ -74,11 +74,11 @@ typedef struct VulkanExtensions /* Defines */ -#define STARTING_ALLOCATION_SIZE 64000000 /* 64MB */ -#define MAX_ALLOCATION_SIZE 256000000 /* 256MB */ -#define ALLOCATION_INCREMENT 16000000 /* 16MB */ -#define UBO_BUFFER_SIZE 16777216 /* 16MB */ -#define MAX_UBO_SECTION_SIZE 4096 /* 4KB */ +#define STARTING_ALLOCATION_SIZE 67108864 /* 64MiB */ +#define MAX_ALLOCATION_SIZE 268435456 /* 256MiB */ +#define ALLOCATION_INCREMENT 16777216 /* 16MiB */ +#define UBO_BUFFER_SIZE 16777216 /* 16MiB */ +#define MAX_UBO_SECTION_SIZE 4096 /* 4KiB */ #define DESCRIPTOR_POOL_STARTING_SIZE 128 #define MAX_FRAMES_IN_FLIGHT 3 #define WINDOW_DATA "Refresh_VulkanWindowData" -- 2.25.1 From 0994ac152ed2be478d15a9dc5c800335f6faa961 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Fri, 1 Mar 2024 15:47:36 -0800 Subject: [PATCH 13/16] do not create msaa textures for depth targets --- src/Refresh_Driver_Vulkan.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index 58696bd..9753c82 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -1,4 +1,4 @@ -/* Refresh - XNA-inspired 3D Graphics Library with modern capabilities +/* Refresh - XNA-inspired 3D Graphics Library with modern capabilities * * Copyright (c) 2020 Evan Hemsley * @@ -5648,8 +5648,12 @@ static VulkanTexture* VULKAN_INTERNAL_CreateTexture( texture->slices[sliceIndex].msaaTex = NULL; SDL_AtomicSet(&texture->slices[sliceIndex].referenceCount, 0); - if (sampleCount > VK_SAMPLE_COUNT_1_BIT && isRenderTarget && !isMsaaTexture) - { + if ( + sampleCount > VK_SAMPLE_COUNT_1_BIT && + isRenderTarget && + !IsDepthFormat(texture->format) && + !isMsaaTexture + ) { texture->slices[sliceIndex].msaaTex = VULKAN_INTERNAL_CreateTexture( renderer, texture->dimensions.width, -- 2.25.1 From 2c77bf96d9c8f58a76f879a21f81ed6b6d8655e2 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Sat, 2 Mar 2024 00:56:46 -0800 Subject: [PATCH 14/16] restructure allocation strategy for small allocations --- src/Refresh_Driver_Vulkan.c | 192 ++++++++++++++++++++---------------- 1 file changed, 108 insertions(+), 84 deletions(-) diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index 9753c82..6be59f9 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -74,11 +74,11 @@ typedef struct VulkanExtensions /* Defines */ -#define STARTING_ALLOCATION_SIZE 67108864 /* 64MiB */ -#define MAX_ALLOCATION_SIZE 268435456 /* 256MiB */ -#define ALLOCATION_INCREMENT 16777216 /* 16MiB */ -#define UBO_BUFFER_SIZE 16777216 /* 16MiB */ -#define MAX_UBO_SECTION_SIZE 4096 /* 4KiB */ +#define SMALL_ALLOCATION_THRESHOLD 1048576 /* 1 MiB */ +#define SMALL_ALLOCATION_SIZE 16777216 /* 16 MiB */ +#define LARGE_ALLOCATION_INCREMENT 67108864 /* 64 MiB */ +#define UBO_BUFFER_SIZE 16777216 /* 16 MiB */ +#define MAX_UBO_SECTION_SIZE 4096 /* 4 KiB */ #define DESCRIPTOR_POOL_STARTING_SIZE 128 #define MAX_FRAMES_IN_FLIGHT 3 #define WINDOW_DATA "Refresh_VulkanWindowData" @@ -424,7 +424,6 @@ typedef struct VulkanMemoryUsedRegion typedef struct VulkanMemorySubAllocator { uint32_t memoryTypeIndex; - VkDeviceSize nextAllocationSize; VulkanMemoryAllocation **allocations; uint32_t allocationCount; VulkanMemoryFreeRegion **sortedFreeRegions; @@ -2626,13 +2625,15 @@ static uint8_t VULKAN_INTERNAL_BindResourceMemory( VulkanMemoryAllocation *allocation; VulkanMemorySubAllocator *allocator; VulkanMemoryFreeRegion *region; + VulkanMemoryFreeRegion *selectedRegion; VulkanMemoryUsedRegion *usedRegion; VkDeviceSize requiredSize, allocationSize; VkDeviceSize alignedOffset; uint32_t newRegionSize, newRegionOffset; uint8_t shouldAllocDedicated = forceDedicated; - uint8_t isHostVisible, allocationResult; + uint8_t isHostVisible, smallAllocation, allocationResult; + int32_t i; isHostVisible = (renderer->memoryProperties.memoryTypes[memoryTypeIndex].propertyFlags & @@ -2640,6 +2641,7 @@ static uint8_t VULKAN_INTERNAL_BindResourceMemory( allocator = &renderer->memoryAllocator->subAllocators[memoryTypeIndex]; requiredSize = memoryRequirements->memoryRequirements.size; + smallAllocation = requiredSize < SMALL_ALLOCATION_THRESHOLD; if ( (buffer == VK_NULL_HANDLE && image == VK_NULL_HANDLE) || (buffer != VK_NULL_HANDLE && image != VK_NULL_HANDLE) ) @@ -2650,90 +2652,113 @@ static uint8_t VULKAN_INTERNAL_BindResourceMemory( SDL_LockMutex(renderer->allocatorLock); - /* find the largest free region and use it */ - if (!shouldAllocDedicated && allocator->sortedFreeRegionCount > 0) + selectedRegion = NULL; + + if (!shouldAllocDedicated) { - region = allocator->sortedFreeRegions[0]; - allocation = region->allocation; - - alignedOffset = VULKAN_INTERNAL_NextHighestAlignment( - region->offset, - memoryRequirements->memoryRequirements.alignment - ); - - if (alignedOffset + requiredSize <= region->offset + region->size) + for (i = allocator->sortedFreeRegionCount - 1; i >= 0; i -= 1) { - usedRegion = VULKAN_INTERNAL_NewMemoryUsedRegion( - renderer, - allocation, + region = allocator->sortedFreeRegions[i]; + + if (smallAllocation && region->allocation->size != SMALL_ALLOCATION_SIZE) + { + /* region is not in a small allocation */ + continue; + } + + if (!smallAllocation && region->allocation->size == SMALL_ALLOCATION_SIZE) + { + /* allocation is not small and current region is in a small allocation */ + continue; + } + + alignedOffset = VULKAN_INTERNAL_NextHighestAlignment( region->offset, - requiredSize + (alignedOffset - region->offset), - alignedOffset, - resourceSize, memoryRequirements->memoryRequirements.alignment ); - usedRegion->isBuffer = buffer != VK_NULL_HANDLE; - - newRegionSize = region->size - ((alignedOffset - region->offset) + requiredSize); - newRegionOffset = alignedOffset + requiredSize; - - /* remove and add modified region to re-sort */ - VULKAN_INTERNAL_RemoveMemoryFreeRegion(renderer, region); - - /* if size is 0, no need to re-insert */ - if (newRegionSize != 0) + if (alignedOffset + requiredSize <= region->offset + region->size) { - VULKAN_INTERNAL_NewMemoryFreeRegion( - renderer, - allocation, - newRegionOffset, - newRegionSize - ); + selectedRegion = region; + break; } - - SDL_UnlockMutex(renderer->allocatorLock); - - if (buffer != VK_NULL_HANDLE) - { - if (!VULKAN_INTERNAL_BindBufferMemory( - renderer, - usedRegion, - alignedOffset, - buffer - )) { - VULKAN_INTERNAL_RemoveMemoryUsedRegion( - renderer, - usedRegion - ); - - return 0; - } - } - else if (image != VK_NULL_HANDLE) - { - if (!VULKAN_INTERNAL_BindImageMemory( - renderer, - usedRegion, - alignedOffset, - image - )) { - VULKAN_INTERNAL_RemoveMemoryUsedRegion( - renderer, - usedRegion - ); - - return 0; - } - } - - *pMemoryUsedRegion = usedRegion; - return 1; } } - /* No suitable free regions exist, allocate a new memory region */ + if (selectedRegion != NULL) + { + region = selectedRegion; + allocation = region->allocation; + usedRegion = VULKAN_INTERNAL_NewMemoryUsedRegion( + renderer, + allocation, + region->offset, + requiredSize + (alignedOffset - region->offset), + alignedOffset, + resourceSize, + memoryRequirements->memoryRequirements.alignment + ); + + usedRegion->isBuffer = buffer != VK_NULL_HANDLE; + + newRegionSize = region->size - ((alignedOffset - region->offset) + requiredSize); + newRegionOffset = alignedOffset + requiredSize; + + /* remove and add modified region to re-sort */ + VULKAN_INTERNAL_RemoveMemoryFreeRegion(renderer, region); + + /* if size is 0, no need to re-insert */ + if (newRegionSize != 0) + { + VULKAN_INTERNAL_NewMemoryFreeRegion( + renderer, + allocation, + newRegionOffset, + newRegionSize + ); + } + + SDL_UnlockMutex(renderer->allocatorLock); + + if (buffer != VK_NULL_HANDLE) + { + if (!VULKAN_INTERNAL_BindBufferMemory( + renderer, + usedRegion, + alignedOffset, + buffer + )) { + VULKAN_INTERNAL_RemoveMemoryUsedRegion( + renderer, + usedRegion + ); + + return 0; + } + } + else if (image != VK_NULL_HANDLE) + { + if (!VULKAN_INTERNAL_BindImageMemory( + renderer, + usedRegion, + alignedOffset, + image + )) { + VULKAN_INTERNAL_RemoveMemoryUsedRegion( + renderer, + usedRegion + ); + + return 0; + } + } + + *pMemoryUsedRegion = usedRegion; + return 1; + } + + /* No suitable free regions exist, allocate a new memory region */ if ( !shouldAllocDedicated && renderer->allocationsToDefragCount == 0 && @@ -2747,15 +2772,15 @@ static uint8_t VULKAN_INTERNAL_BindResourceMemory( { allocationSize = requiredSize; } - else if (requiredSize > allocator->nextAllocationSize) + else if (requiredSize > SMALL_ALLOCATION_THRESHOLD) { - /* allocate a page of required size aligned to ALLOCATION_INCREMENT increments */ + /* allocate a page of required size aligned to LARGE_ALLOCATION_INCREMENT increments */ allocationSize = - VULKAN_INTERNAL_NextHighestAlignment(requiredSize, ALLOCATION_INCREMENT); + VULKAN_INTERNAL_NextHighestAlignment(requiredSize, LARGE_ALLOCATION_INCREMENT); } else { - allocationSize = allocator->nextAllocationSize; + allocationSize = SMALL_ALLOCATION_SIZE; } allocationResult = VULKAN_INTERNAL_AllocateMemory( @@ -11543,7 +11568,6 @@ static Refresh_Device* VULKAN_CreateDevice( for (i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) { renderer->memoryAllocator->subAllocators[i].memoryTypeIndex = i; - renderer->memoryAllocator->subAllocators[i].nextAllocationSize = STARTING_ALLOCATION_SIZE; renderer->memoryAllocator->subAllocators[i].allocations = NULL; renderer->memoryAllocator->subAllocators[i].allocationCount = 0; renderer->memoryAllocator->subAllocators[i].sortedFreeRegions = SDL_malloc( -- 2.25.1 From 2585ee7696c04958ed21f8d6a81e0f17ddae1c31 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Sat, 2 Mar 2024 01:02:57 -0800 Subject: [PATCH 15/16] remove some unused functions and vars --- src/Refresh_Driver_Vulkan.c | 67 ------------------------------------- 1 file changed, 67 deletions(-) diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index 6be59f9..676129d 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -1986,15 +1986,6 @@ static inline uint32_t VULKAN_INTERNAL_TextureBlockSize( } } -static inline VkDeviceSize VULKAN_INTERNAL_BytesPerImage( - uint32_t width, - uint32_t height, - VkFormat format -) { - uint32_t blockSize = VULKAN_INTERNAL_TextureBlockSize(format); - return (width * height * VULKAN_INTERNAL_BytesPerPixel(format)) / (blockSize * blockSize); -} - static inline VkSampleCountFlagBits VULKAN_INTERNAL_GetMaxMultiSampleCount( VulkanRenderer *renderer, VkSampleCountFlagBits multiSampleCount @@ -3222,39 +3213,6 @@ static void VULKAN_INTERNAL_ImageMemoryBarrier( 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 */ #define ADD_TO_ARRAY_UNIQUE(resource, type, array, count, capacity) \ @@ -4393,20 +4351,6 @@ static VulkanTextureSlice* VULKAN_INTERNAL_FetchTextureSlice( ]; } -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 ) { @@ -6861,9 +6805,6 @@ 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; @@ -7765,7 +7706,6 @@ static void VULKAN_BeginRenderPass( uint32_t multisampleAttachmentCount = 0; uint32_t totalColorAttachmentCount = 0; uint32_t i; - VkImageAspectFlags depthAspectFlags; Refresh_Viewport defaultViewport; Refresh_Rect defaultScissor; uint32_t framebufferWidth = UINT32_MAX; @@ -7917,13 +7857,6 @@ static void VULKAN_BeginRenderPass( vulkanCommandBuffer->renderPassDepthTextureSlice = textureSlice; - depthAspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT; - - if (IsStencilFormat(textureSlice->parent->format)) - { - depthAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT; - } - VULKAN_INTERNAL_ImageMemoryBarrier( renderer, vulkanCommandBuffer->commandBuffer, -- 2.25.1 From 007ac6db952dc4d646c92ad31ca957e57765fc18 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Sat, 2 Mar 2024 01:04:30 -0800 Subject: [PATCH 16/16] remove unused functions --- src/Refresh_Driver_Vulkan.c | 92 ------------------------------------- 1 file changed, 92 deletions(-) diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index 676129d..7ce1014 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -1894,98 +1894,6 @@ static inline uint8_t IsStencilFormat(VkFormat format) } } -static inline uint32_t VULKAN_INTERNAL_BytesPerPixel(VkFormat format) -{ - switch (format) - { - case VK_FORMAT_R8_UNORM: - case VK_FORMAT_R8_UINT: - return 1; - case VK_FORMAT_R5G6B5_UNORM_PACK16: - case VK_FORMAT_B4G4R4A4_UNORM_PACK16: - case VK_FORMAT_A1R5G5B5_UNORM_PACK16: - case VK_FORMAT_R16_SFLOAT: - case VK_FORMAT_R8G8_SNORM: - case VK_FORMAT_R8G8_UINT: - case VK_FORMAT_R16_UINT: - case VK_FORMAT_D16_UNORM: - return 2; - case VK_FORMAT_D16_UNORM_S8_UINT: - return 3; - case VK_FORMAT_R8G8B8A8_UNORM: - case VK_FORMAT_B8G8R8A8_UNORM: - case VK_FORMAT_R32_SFLOAT: - case VK_FORMAT_R16G16_UNORM: - case VK_FORMAT_R16G16_SFLOAT: - case VK_FORMAT_R8G8B8A8_SNORM: - case VK_FORMAT_A2R10G10B10_UNORM_PACK32: - case VK_FORMAT_R8G8B8A8_UINT: - case VK_FORMAT_R16G16_UINT: - case VK_FORMAT_D32_SFLOAT: - return 4; - case VK_FORMAT_D32_SFLOAT_S8_UINT: - return 5; - case VK_FORMAT_R16G16B16A16_SFLOAT: - case VK_FORMAT_R16G16B16A16_UNORM: - case VK_FORMAT_R32G32_SFLOAT: - case VK_FORMAT_R16G16B16A16_UINT: - case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: - return 8; - case VK_FORMAT_R32G32B32A32_SFLOAT: - case VK_FORMAT_BC2_UNORM_BLOCK: - case VK_FORMAT_BC3_UNORM_BLOCK: - case VK_FORMAT_BC7_UNORM_BLOCK: - return 16; - default: - Refresh_LogError("Texture format not recognized!"); - return 0; - } -} - -static inline uint32_t VULKAN_INTERNAL_TextureBlockSize( - VkFormat format -) { - switch (format) - { - case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: - case VK_FORMAT_BC2_UNORM_BLOCK: - case VK_FORMAT_BC3_UNORM_BLOCK: - case VK_FORMAT_BC7_UNORM_BLOCK: - return 4; - case VK_FORMAT_R8G8B8A8_UNORM: - case VK_FORMAT_B8G8R8A8_UNORM: - case VK_FORMAT_R5G6B5_UNORM_PACK16: - case VK_FORMAT_A1R5G5B5_UNORM_PACK16: - case VK_FORMAT_B4G4R4A4_UNORM_PACK16: - case VK_FORMAT_A2R10G10B10_UNORM_PACK32: - case VK_FORMAT_R16G16_UNORM: - case VK_FORMAT_R16G16B16A16_UNORM: - case VK_FORMAT_R8_UNORM: - case VK_FORMAT_R8G8_SNORM: - case VK_FORMAT_R8G8B8A8_SNORM: - case VK_FORMAT_R16_SFLOAT: - case VK_FORMAT_R16G16_SFLOAT: - case VK_FORMAT_R16G16B16A16_SFLOAT: - case VK_FORMAT_R32_SFLOAT: - case VK_FORMAT_R32G32_SFLOAT: - case VK_FORMAT_R32G32B32A32_SFLOAT: - case VK_FORMAT_R8_UINT: - case VK_FORMAT_R8G8_UINT: - case VK_FORMAT_R8G8B8A8_UINT: - case VK_FORMAT_R16_UINT: - case VK_FORMAT_R16G16_UINT: - case VK_FORMAT_R16G16B16A16_UINT: - case VK_FORMAT_D16_UNORM: - case VK_FORMAT_D32_SFLOAT: - case VK_FORMAT_D16_UNORM_S8_UINT: - case VK_FORMAT_D32_SFLOAT_S8_UINT: - return 1; - default: - Refresh_LogError("Unrecognized texture format!"); - return 0; - } -} - static inline VkSampleCountFlagBits VULKAN_INTERNAL_GetMaxMultiSampleCount( VulkanRenderer *renderer, VkSampleCountFlagBits multiSampleCount -- 2.25.1