From b64bf06c7b376ef7010332b5727d25a0746b83ee Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Fri, 1 Mar 2024 12:39:33 -0800 Subject: [PATCH] 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(