diff --git a/src/Refresh_Driver_Vulkan.c b/src/Refresh_Driver_Vulkan.c index 72f0c10..b4f2f83 100644 --- a/src/Refresh_Driver_Vulkan.c +++ b/src/Refresh_Driver_Vulkan.c @@ -449,7 +449,6 @@ struct VulkanMemoryAllocation uint8_t availableForAllocation; VkDeviceSize freeSpace; VkDeviceSize usedSpace; - uint8_t *mapPointer; SDL_mutex *memoryLock; }; @@ -756,6 +755,7 @@ struct VulkanUniformBufferPool VulkanBuffer *buffer; VkDeviceSize nextAvailableOffset; SDL_mutex *lock; + uint8_t *mapPointer; /* uniform buffers are permanently mapped */ VulkanUniformBuffer **availableBuffers; uint32_t availableBufferCount; @@ -1522,22 +1522,6 @@ typedef struct DescriptorSetData VkDescriptorSet descriptorSet; } DescriptorSetData; -typedef struct VulkanTransferBuffer -{ - VulkanBuffer* buffer; - VkDeviceSize offset; - uint8_t fromPool; -} VulkanTransferBuffer; - -typedef struct VulkanTransferBufferPool -{ - SDL_mutex *lock; - - VulkanTransferBuffer **availableBuffers; - uint32_t availableBufferCount; - uint32_t availableBufferCapacity; -} VulkanTransferBufferPool; - typedef struct VulkanFencePool { SDL_mutex *lock; @@ -1582,10 +1566,6 @@ typedef struct VulkanCommandBuffer VkDescriptorSet bufferDescriptorSet; /* updated by BindComputeBuffers */ VkDescriptorSet imageDescriptorSet; /* updated by BindComputeTextures */ - VulkanTransferBuffer** transferBuffers; - uint32_t transferBufferCount; - uint32_t transferBufferCapacity; - VulkanUniformBuffer **boundUniformBuffers; uint32_t boundUniformBufferCount; uint32_t boundUniformBufferCapacity; @@ -1604,6 +1584,16 @@ typedef struct VulkanCommandBuffer uint32_t boundComputeTextureCount; uint32_t boundComputeTextureCapacity; + /* Keep track of copy resources for memory barriers */ + + VulkanBuffer **copiedGpuBuffers; + uint32_t copiedGpuBufferCount; + uint32_t copiedGpuBufferCapacity; + + VulkanTexture **copiedTextures; + uint32_t copiedTextureCount; + uint32_t copiedTextureCapacity; + /* Viewport/scissor state */ VkViewport currentViewport; @@ -1751,7 +1741,6 @@ typedef struct VulkanRenderer uint32_t submittedCommandBufferCount; uint32_t submittedCommandBufferCapacity; - VulkanTransferBufferPool transferBufferPool; VulkanFencePool fencePool; CommandPoolHashTable commandPoolHashTable; @@ -2578,24 +2567,6 @@ static uint8_t VULKAN_INTERNAL_AllocateMemory( return 0; } - /* persistent mapping for host memory */ - if (isHostVisible) - { - result = renderer->vkMapMemory( - renderer->logicalDevice, - allocation->memory, - 0, - VK_WHOLE_SIZE, - 0, - (void**) &allocation->mapPointer - ); - VULKAN_ERROR_CHECK(result, vkMapMemory, 0) - } - else - { - allocation->mapPointer = NULL; - } - VULKAN_INTERNAL_NewMemoryFreeRegion( renderer, allocation, @@ -3380,6 +3351,64 @@ static void VULKAN_INTERNAL_TrackFramebuffer( ); } +static void VULKAN_INTERNAL_TrackComputeBuffer( + VulkanRenderer *renderer, + VulkanCommandBuffer *commandBuffer, + VulkanBuffer *computeBuffer +) { + TRACK_RESOURCE( + computeBuffer, + VulkanBuffer*, + boundComputeBuffers, + boundComputeBufferCount, + boundComputeBufferCapacity + ); +} + +static void VULKAN_INTERNAL_TrackComputeTexture( + VulkanRenderer *renderer, + VulkanCommandBuffer *commandBuffer, + VulkanTexture *computeTexture +) { + TRACK_RESOURCE( + computeTexture, + VulkanTexture*, + boundComputeTextures, + boundComputeTextureCount, + boundComputeTextureCapacity + ); +} + +/* For tracking Textures used in a copy pass. */ +static void VULKAN_INTERNAL_TrackCopiedTexture( + VulkanRenderer *renderer, + VulkanCommandBuffer *commandBuffer, + VulkanTexture *texture +) { + TRACK_RESOURCE( + texture, + VulkanTexture*, + copiedTextures, + copiedTextureCount, + copiedTextureCapacity + ); +} + +/* For tracking GpuBuffers used in a copy pass. */ +static void VULKAN_INTERNAL_TrackCopiedBuffer( + VulkanRenderer *renderer, + VulkanCommandBuffer *commandBuffer, + VulkanBuffer *buffer +) { + TRACK_RESOURCE( + buffer, + VulkanBuffer*, + copiedGpuBuffers, + copiedGpuBufferCount, + copiedGpuBufferCapacity + ); +} + #undef TRACK_RESOURCE /* Resource Disposal */ @@ -3599,11 +3628,12 @@ static void VULKAN_INTERNAL_DestroyCommandPool( SDL_free(commandBuffer->presentDatas); SDL_free(commandBuffer->waitSemaphores); SDL_free(commandBuffer->signalSemaphores); - SDL_free(commandBuffer->transferBuffers); SDL_free(commandBuffer->boundUniformBuffers); SDL_free(commandBuffer->boundDescriptorSetDatas); SDL_free(commandBuffer->boundComputeBuffers); SDL_free(commandBuffer->boundComputeTextures); + SDL_free(commandBuffer->copiedGpuBuffers); + SDL_free(commandBuffer->copiedTextures); SDL_free(commandBuffer->usedBuffers); SDL_free(commandBuffer->usedTextures); SDL_free(commandBuffer->usedSamplers); @@ -4247,6 +4277,15 @@ static VulkanUniformBufferPool* VULKAN_INTERNAL_CreateUniformBufferPool( uniformBufferPool->descriptorPool.descriptorPoolCount = 0; uniformBufferPool->descriptorPool.descriptorPools = NULL; + renderer->vkMapMemory( + renderer->logicalDevice, + uniformBufferPool->buffer->usedRegion->allocation->memory, + 0, + VK_WHOLE_SIZE, + 0, + (void**) &uniformBufferPool->mapPointer + ); + VULKAN_INTERNAL_AddUniformDescriptorPool(renderer, &uniformBufferPool->descriptorPool); return uniformBufferPool; @@ -4479,6 +4518,11 @@ static void VULKAN_INTERNAL_DestroyUniformBufferPool( SDL_free(uniformBufferPool->availableBuffers[i]); } + renderer->vkUnmapMemory( + renderer->logicalDevice, + uniformBufferPool->buffer->usedRegion->allocation->memory + ); + VULKAN_INTERNAL_DestroyBuffer(renderer, uniformBufferPool->buffer); SDL_DestroyMutex(uniformBufferPool->lock); @@ -5202,15 +5246,6 @@ static void VULKAN_DestroyDevice( SDL_free(renderer->dummyFragmentUniformBuffer); SDL_free(renderer->dummyComputeUniformBuffer); - for (i = 0; i < renderer->transferBufferPool.availableBufferCount; i += 1) - { - VULKAN_INTERNAL_DestroyBuffer(renderer, renderer->transferBufferPool.availableBuffers[i]->buffer); - SDL_free(renderer->transferBufferPool.availableBuffers[i]); - } - - SDL_free(renderer->transferBufferPool.availableBuffers); - SDL_DestroyMutex(renderer->transferBufferPool.lock); - for (i = 0; i < renderer->fencePool.availableFenceCount; i += 1) { renderer->vkDestroyFence(renderer->logicalDevice, renderer->fencePool.availableFences[i], NULL); @@ -5553,7 +5588,7 @@ static void VULKAN_DrawPrimitives( static void VULKAN_DrawPrimitivesIndirect( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_Buffer *buffer, + Refresh_GpuBuffer *buffer, uint32_t offsetInBytes, uint32_t drawCount, uint32_t stride, @@ -5596,104 +5631,6 @@ static void VULKAN_DrawPrimitivesIndirect( VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanBuffer); } -static void VULKAN_DispatchCompute( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - uint32_t groupCountX, - uint32_t groupCountY, - uint32_t groupCountZ, - uint32_t computeParamOffset -) { - VulkanRenderer* renderer = (VulkanRenderer*) driverData; - VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanComputePipeline *computePipeline = vulkanCommandBuffer->currentComputePipeline; - VkDescriptorSet descriptorSets[3]; - VulkanResourceAccessType resourceAccessType = RESOURCE_ACCESS_NONE; - VulkanBuffer *currentComputeBuffer; - VulkanTexture *currentComputeTexture; - uint32_t i; - - descriptorSets[0] = vulkanCommandBuffer->bufferDescriptorSet; - descriptorSets[1] = vulkanCommandBuffer->imageDescriptorSet; - descriptorSets[2] = vulkanCommandBuffer->computeUniformBuffer->descriptorSet; - - renderer->vkCmdBindDescriptorSets( - vulkanCommandBuffer->commandBuffer, - VK_PIPELINE_BIND_POINT_COMPUTE, - computePipeline->pipelineLayout->pipelineLayout, - 0, - 3, - descriptorSets, - 1, - &computeParamOffset - ); - - renderer->vkCmdDispatch( - vulkanCommandBuffer->commandBuffer, - groupCountX, - groupCountY, - groupCountZ - ); - - /* Re-transition buffers after dispatch */ - for (i = 0; i < vulkanCommandBuffer->boundComputeBufferCount; i += 1) - { - currentComputeBuffer = vulkanCommandBuffer->boundComputeBuffers[i]; - - if (currentComputeBuffer->usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) - { - resourceAccessType = RESOURCE_ACCESS_VERTEX_BUFFER; - } - else if (currentComputeBuffer->usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT) - { - resourceAccessType = RESOURCE_ACCESS_INDEX_BUFFER; - } - else if (currentComputeBuffer->usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) - { - resourceAccessType = RESOURCE_ACCESS_INDIRECT_BUFFER; - } - - if (resourceAccessType != RESOURCE_ACCESS_NONE) - { - VULKAN_INTERNAL_BufferMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - resourceAccessType, - currentComputeBuffer - ); - } - } - - vulkanCommandBuffer->boundComputeBufferCount = 0; - - /* Re-transition sampler images after dispatch */ - for (i = 0; i < vulkanCommandBuffer->boundComputeTextureCount; i += 1) - { - currentComputeTexture = vulkanCommandBuffer->boundComputeTextures[i]; - - if (currentComputeTexture->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 - ); - } - } - - vulkanCommandBuffer->boundComputeTextureCount = 0; -} - static VulkanTexture* VULKAN_INTERNAL_CreateTexture( VulkanRenderer *renderer, uint32_t width, @@ -6546,42 +6483,42 @@ static Refresh_GraphicsPipeline* VULKAN_CreateGraphicsPipeline( /* Depth Stencil State */ frontStencilState.failOp = RefreshToVK_StencilOp[ - pipelineCreateInfo->depthStencilState.frontStencilState.failOp + pipelineCreateInfo->depthStencilState.stencilState.failOp ]; frontStencilState.passOp = RefreshToVK_StencilOp[ - pipelineCreateInfo->depthStencilState.frontStencilState.passOp + pipelineCreateInfo->depthStencilState.stencilState.passOp ]; frontStencilState.depthFailOp = RefreshToVK_StencilOp[ - pipelineCreateInfo->depthStencilState.frontStencilState.depthFailOp + pipelineCreateInfo->depthStencilState.stencilState.depthFailOp ]; frontStencilState.compareOp = RefreshToVK_CompareOp[ - pipelineCreateInfo->depthStencilState.frontStencilState.compareOp + pipelineCreateInfo->depthStencilState.stencilState.compareOp ]; frontStencilState.compareMask = - pipelineCreateInfo->depthStencilState.frontStencilState.compareMask; + pipelineCreateInfo->depthStencilState.stencilState.compareMask; frontStencilState.writeMask = - pipelineCreateInfo->depthStencilState.frontStencilState.writeMask; + pipelineCreateInfo->depthStencilState.stencilState.writeMask; frontStencilState.reference = - pipelineCreateInfo->depthStencilState.frontStencilState.reference; + pipelineCreateInfo->depthStencilState.stencilState.reference; backStencilState.failOp = RefreshToVK_StencilOp[ - pipelineCreateInfo->depthStencilState.backStencilState.failOp + pipelineCreateInfo->depthStencilState.stencilState.failOp ]; backStencilState.passOp = RefreshToVK_StencilOp[ - pipelineCreateInfo->depthStencilState.backStencilState.passOp + pipelineCreateInfo->depthStencilState.stencilState.passOp ]; backStencilState.depthFailOp = RefreshToVK_StencilOp[ - pipelineCreateInfo->depthStencilState.backStencilState.depthFailOp + pipelineCreateInfo->depthStencilState.stencilState.depthFailOp ]; backStencilState.compareOp = RefreshToVK_CompareOp[ - pipelineCreateInfo->depthStencilState.backStencilState.compareOp + pipelineCreateInfo->depthStencilState.stencilState.compareOp ]; backStencilState.compareMask = - pipelineCreateInfo->depthStencilState.backStencilState.compareMask; + pipelineCreateInfo->depthStencilState.stencilState.compareMask; backStencilState.writeMask = - pipelineCreateInfo->depthStencilState.backStencilState.writeMask; + pipelineCreateInfo->depthStencilState.stencilState.writeMask; backStencilState.reference = - pipelineCreateInfo->depthStencilState.backStencilState.reference; + pipelineCreateInfo->depthStencilState.stencilState.reference; depthStencilStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; @@ -7079,7 +7016,7 @@ static Refresh_Texture* VULKAN_CreateTexture( return (Refresh_Texture*) container; } -static Refresh_Buffer* VULKAN_CreateBuffer( +static Refresh_GpuBuffer* VULKAN_CreateGpuBuffer( Refresh_Renderer *driverData, Refresh_BufferUsageFlags usageFlags, uint32_t sizeInBytes @@ -7117,7 +7054,7 @@ static Refresh_Buffer* VULKAN_CreateBuffer( resourceAccessType = RESOURCE_ACCESS_INDIRECT_BUFFER; } - return (Refresh_Buffer*) VULKAN_INTERNAL_CreateBufferContainer( + return (Refresh_GpuBuffer*) VULKAN_INTERNAL_CreateBufferContainer( (VulkanRenderer*) driverData, sizeInBytes, resourceAccessType, @@ -7125,677 +7062,47 @@ static Refresh_Buffer* VULKAN_CreateBuffer( ); } -/* Setters */ - -static VulkanTransferBuffer* VULKAN_INTERNAL_AcquireTransferBuffer( - VulkanRenderer *renderer, - VulkanCommandBuffer *commandBuffer, - VkDeviceSize requiredSize, - VkDeviceSize alignment +static Refresh_CpuBuffer* VULKAN_CreateCpuBuffer( + Refresh_Renderer *driverData, + uint32_t sizeInBytes ) { - VkDeviceSize size; - VkDeviceSize offset; - uint32_t i; - VulkanTransferBuffer *transferBuffer; + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VkBufferUsageFlags vulkanUsageFlags = + VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; - /* Search the command buffer's current transfer buffers */ - - for (i = 0; i < commandBuffer->transferBufferCount; i += 1) - { - transferBuffer = commandBuffer->transferBuffers[i]; - offset = transferBuffer->offset + alignment - (transferBuffer->offset % alignment); - - if (offset + requiredSize <= transferBuffer->buffer->size) - { - transferBuffer->offset = offset; - return transferBuffer; - } - } - - /* Nothing fits, can we get a transfer buffer from the pool? */ - - SDL_LockMutex(renderer->transferBufferPool.lock); - - for (i = 0; i < renderer->transferBufferPool.availableBufferCount; i += 1) - { - transferBuffer = renderer->transferBufferPool.availableBuffers[i]; - offset = transferBuffer->offset + alignment - (transferBuffer->offset % alignment); - - if (offset + requiredSize <= transferBuffer->buffer->size) - { - if (commandBuffer->transferBufferCount == commandBuffer->transferBufferCapacity) - { - commandBuffer->transferBufferCapacity *= 2; - commandBuffer->transferBuffers = SDL_realloc( - commandBuffer->transferBuffers, - commandBuffer->transferBufferCapacity * sizeof(VulkanTransferBuffer*) - ); - } - - commandBuffer->transferBuffers[commandBuffer->transferBufferCount] = transferBuffer; - commandBuffer->transferBufferCount += 1; - - renderer->transferBufferPool.availableBuffers[i] = renderer->transferBufferPool.availableBuffers[renderer->transferBufferPool.availableBufferCount - 1]; - renderer->transferBufferPool.availableBufferCount -= 1; - SDL_UnlockMutex(renderer->transferBufferPool.lock); - - transferBuffer->offset = offset; - return transferBuffer; - } - } - - SDL_UnlockMutex(renderer->transferBufferPool.lock); - - /* Nothing fits, so let's create a new transfer buffer */ - - size = TRANSFER_BUFFER_STARTING_SIZE; - - while (size < requiredSize) - { - size *= 2; - } - - transferBuffer = SDL_malloc(sizeof(VulkanTransferBuffer)); - transferBuffer->offset = 0; - transferBuffer->buffer = VULKAN_INTERNAL_CreateBuffer( + VulkanBuffer *vulkanBuffer = VULKAN_INTERNAL_CreateBuffer( renderer, - size, - RESOURCE_ACCESS_TRANSFER_READ_WRITE, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + sizeInBytes, + RESOURCE_ACCESS_NONE, + vulkanUsageFlags, 1, 0, 1 ); - transferBuffer->fromPool = 0; - if (transferBuffer->buffer == NULL) - { - Refresh_LogError("Failed to allocate transfer buffer!"); - SDL_free(transferBuffer); - return NULL; - } - - if (commandBuffer->transferBufferCount == commandBuffer->transferBufferCapacity) - { - commandBuffer->transferBufferCapacity *= 2; - commandBuffer->transferBuffers = SDL_realloc( - commandBuffer->transferBuffers, - commandBuffer->transferBufferCapacity * sizeof(VulkanTransferBuffer*) - ); - } - - commandBuffer->transferBuffers[commandBuffer->transferBufferCount] = transferBuffer; - commandBuffer->transferBufferCount += 1; - - return transferBuffer; + return (Refresh_CpuBuffer*) vulkanBuffer; } -static void VULKAN_SetTextureData( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice *textureSlice, - void *data, - uint32_t dataLengthInBytes -) { - VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) textureSlice->texture)->vulkanTexture; - VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTransferBuffer *transferBuffer; - VkBufferImageCopy imageCopy; - uint8_t *stagingBufferPointer; - uint32_t blockSize = VULKAN_INTERNAL_TextureBlockSize(vulkanTexture->format); - uint32_t bufferRowLength; - uint32_t bufferImageHeight; +/* Setters */ - transferBuffer = VULKAN_INTERNAL_AcquireTransferBuffer( - renderer, - vulkanCommandBuffer, - VULKAN_INTERNAL_BytesPerImage( - textureSlice->rectangle.w, - textureSlice->rectangle.h, - vulkanTexture->format - ), - VULKAN_INTERNAL_BytesPerPixel(vulkanTexture->format) - ); - - if (transferBuffer == NULL) - { - return; - } - - stagingBufferPointer = - transferBuffer->buffer->usedRegion->allocation->mapPointer + - transferBuffer->buffer->usedRegion->resourceOffset + - transferBuffer->offset; - - SDL_memcpy( - stagingBufferPointer, - data, - dataLengthInBytes - ); - - /* TODO: is it worth it to only transition the specific subresource? */ - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_WRITE, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - vulkanTexture->layerCount, - 0, - vulkanTexture->levelCount, - 0, - vulkanTexture->image, - &vulkanTexture->resourceAccessType - ); - - bufferRowLength = SDL_max(blockSize, textureSlice->rectangle.w); - bufferImageHeight = SDL_max(blockSize, textureSlice->rectangle.h); - - imageCopy.imageExtent.width = textureSlice->rectangle.w; - imageCopy.imageExtent.height = textureSlice->rectangle.h; - imageCopy.imageExtent.depth = 1; - imageCopy.imageOffset.x = textureSlice->rectangle.x; - imageCopy.imageOffset.y = textureSlice->rectangle.y; - imageCopy.imageOffset.z = textureSlice->depth; - imageCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageCopy.imageSubresource.baseArrayLayer = textureSlice->layer; - imageCopy.imageSubresource.layerCount = 1; - imageCopy.imageSubresource.mipLevel = textureSlice->level; - imageCopy.bufferOffset = transferBuffer->offset; - imageCopy.bufferRowLength = bufferRowLength; - imageCopy.bufferImageHeight = bufferImageHeight; - - renderer->vkCmdCopyBufferToImage( - vulkanCommandBuffer->commandBuffer, - transferBuffer->buffer->buffer, - vulkanTexture->image, - AccessMap[vulkanTexture->resourceAccessType].imageLayout, - 1, - &imageCopy - ); - - transferBuffer->offset += dataLengthInBytes; - - if (vulkanTexture->usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) - { - /* TODO: is it worth it to only transition the specific subresource? */ - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_ANY_SHADER_READ_SAMPLED_IMAGE, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - vulkanTexture->layerCount, - 0, - vulkanTexture->levelCount, - 0, - vulkanTexture->image, - &vulkanTexture->resourceAccessType - ); - } - - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTexture); -} - -static void VULKAN_SetTextureDataYUV( - Refresh_Renderer *driverData, - Refresh_CommandBuffer* commandBuffer, - Refresh_Texture *y, - Refresh_Texture *u, - Refresh_Texture *v, - uint32_t yWidth, - uint32_t yHeight, - uint32_t uvWidth, - uint32_t uvHeight, - void *yDataPtr, - void *uDataPtr, - void *vDataPtr, - uint32_t yDataLength, - uint32_t uvDataLength, - uint32_t yStride, - uint32_t uvStride -) { - VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VulkanTexture *tex = ((VulkanTextureContainer*) y)->vulkanTexture; - - VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*)commandBuffer; - VulkanTransferBuffer *transferBuffer; - VkBufferImageCopy imageCopy; - uint8_t * stagingBufferPointer; - - transferBuffer = VULKAN_INTERNAL_AcquireTransferBuffer( - renderer, - vulkanCommandBuffer, - yDataLength + uvDataLength, - VULKAN_INTERNAL_BytesPerPixel(tex->format) - ); - - if (transferBuffer == NULL) - { - return; - } - - stagingBufferPointer = - transferBuffer->buffer->usedRegion->allocation->mapPointer + - transferBuffer->buffer->usedRegion->resourceOffset + - transferBuffer->offset; - - /* Initialize values that are the same for Y, U, and V */ - - imageCopy.imageExtent.depth = 1; - imageCopy.imageOffset.x = 0; - imageCopy.imageOffset.y = 0; - imageCopy.imageOffset.z = 0; - imageCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageCopy.imageSubresource.baseArrayLayer = 0; - imageCopy.imageSubresource.layerCount = 1; - imageCopy.imageSubresource.mipLevel = 0; - - /* Y */ - - SDL_memcpy( - stagingBufferPointer, - yDataPtr, - yDataLength - ); - - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_WRITE, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - tex->layerCount, - 0, - tex->levelCount, - 0, - tex->image, - &tex->resourceAccessType - ); - - - imageCopy.imageExtent.width = yWidth; - imageCopy.imageExtent.height = yHeight; - imageCopy.bufferOffset = transferBuffer->offset; - imageCopy.bufferRowLength = yStride; - imageCopy.bufferImageHeight = yHeight; - - renderer->vkCmdCopyBufferToImage( - vulkanCommandBuffer->commandBuffer, - transferBuffer->buffer->buffer, - tex->image, - AccessMap[tex->resourceAccessType].imageLayout, - 1, - &imageCopy - ); - - if (tex->usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) - { - /* TODO: is it worth it to only transition the specific subresource? */ - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_ANY_SHADER_READ_SAMPLED_IMAGE, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - tex->layerCount, - 0, - tex->levelCount, - 0, - tex->image, - &tex->resourceAccessType - ); - } - - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, tex); - - /* These apply to both U and V */ - - imageCopy.imageExtent.width = uvWidth; - imageCopy.imageExtent.height = uvHeight; - imageCopy.bufferRowLength = uvStride; - imageCopy.bufferImageHeight = uvHeight; - - /* U */ - - imageCopy.bufferOffset = transferBuffer->offset + yDataLength; - - tex = ((VulkanTextureContainer*) u)->vulkanTexture; - - SDL_memcpy( - stagingBufferPointer + yDataLength, - uDataPtr, - uvDataLength - ); - - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_WRITE, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - tex->layerCount, - 0, - tex->levelCount, - 0, - tex->image, - &tex->resourceAccessType - ); - - renderer->vkCmdCopyBufferToImage( - vulkanCommandBuffer->commandBuffer, - transferBuffer->buffer->buffer, - tex->image, - AccessMap[tex->resourceAccessType].imageLayout, - 1, - &imageCopy - ); - - if (tex->usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) - { - /* TODO: is it worth it to only transition the specific subresource? */ - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_ANY_SHADER_READ_SAMPLED_IMAGE, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - tex->layerCount, - 0, - tex->levelCount, - 0, - tex->image, - &tex->resourceAccessType - ); - } - - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, tex); - - /* V */ - - imageCopy.bufferOffset = transferBuffer->offset + yDataLength + uvDataLength; - - tex = ((VulkanTextureContainer*) v)->vulkanTexture; - - SDL_memcpy( - stagingBufferPointer + yDataLength + uvDataLength, - vDataPtr, - uvDataLength - ); - - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_WRITE, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - tex->layerCount, - 0, - tex->levelCount, - 0, - tex->image, - &tex->resourceAccessType - ); - - renderer->vkCmdCopyBufferToImage( - vulkanCommandBuffer->commandBuffer, - transferBuffer->buffer->buffer, - tex->image, - AccessMap[tex->resourceAccessType].imageLayout, - 1, - &imageCopy - ); - - transferBuffer->offset += yDataLength + uvDataLength; - - if (tex->usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) - { - /* TODO: is it worth it to only transition the specific subresource? */ - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_ANY_SHADER_READ_SAMPLED_IMAGE, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - tex->layerCount, - 0, - tex->levelCount, - 0, - tex->image, - &tex->resourceAccessType - ); - } - - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, tex); -} - -static void VULKAN_INTERNAL_BlitImage( - VulkanRenderer *renderer, - VulkanCommandBuffer *commandBuffer, - Refresh_TextureSlice *sourceTextureSlice, - Refresh_TextureSlice *destinationTextureSlice, - VkFilter filter -) { - VkImageBlit blit; - VulkanTexture *sourceTexture = ((VulkanTextureContainer*) sourceTextureSlice->texture)->vulkanTexture; - VulkanTexture *destinationTexture = ((VulkanTextureContainer*) destinationTextureSlice->texture)->vulkanTexture; - - VulkanResourceAccessType originalSourceAccessType = sourceTexture->resourceAccessType; - VulkanResourceAccessType originalDestinationAccessType = destinationTexture->resourceAccessType; - - if (originalDestinationAccessType == RESOURCE_ACCESS_NONE) - { - originalDestinationAccessType = RESOURCE_ACCESS_ANY_SHADER_READ_SAMPLED_IMAGE; - } - - /* TODO: is it worth it to only transition the specific subresource? */ - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - commandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_READ, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - sourceTexture->layerCount, - 0, - sourceTexture->levelCount, - 0, - sourceTexture->image, - &sourceTexture->resourceAccessType - ); - - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - commandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_WRITE, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - destinationTexture->layerCount, - 0, - destinationTexture->levelCount, - 0, - destinationTexture->image, - &destinationTexture->resourceAccessType - ); - - blit.srcOffsets[0].x = sourceTextureSlice->rectangle.x; - blit.srcOffsets[0].y = sourceTextureSlice->rectangle.y; - blit.srcOffsets[0].z = sourceTextureSlice->depth; - blit.srcOffsets[1].x = sourceTextureSlice->rectangle.x + sourceTextureSlice->rectangle.w; - blit.srcOffsets[1].y = sourceTextureSlice->rectangle.y + sourceTextureSlice->rectangle.h; - blit.srcOffsets[1].z = 1; - - blit.srcSubresource.mipLevel = sourceTextureSlice->level; - blit.srcSubresource.baseArrayLayer = sourceTextureSlice->layer; - blit.srcSubresource.layerCount = 1; - blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - blit.dstOffsets[0].x = destinationTextureSlice->rectangle.x; - blit.dstOffsets[0].y = destinationTextureSlice->rectangle.y; - blit.dstOffsets[0].z = destinationTextureSlice->depth; - blit.dstOffsets[1].x = destinationTextureSlice->rectangle.x + destinationTextureSlice->rectangle.w; - blit.dstOffsets[1].y = destinationTextureSlice->rectangle.y + destinationTextureSlice->rectangle.h; - blit.dstOffsets[1].z = 1; - - blit.dstSubresource.mipLevel = destinationTextureSlice->level; - blit.dstSubresource.baseArrayLayer = destinationTextureSlice->layer; - blit.dstSubresource.layerCount = 1; - blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - renderer->vkCmdBlitImage( - commandBuffer->commandBuffer, - sourceTexture->image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - destinationTexture->image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - &blit, - filter - ); - - /* TODO: is it worth it to only transition the specific subresource? */ - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - commandBuffer->commandBuffer, - originalSourceAccessType, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - sourceTexture->layerCount, - 0, - sourceTexture->levelCount, - 0, - sourceTexture->image, - &sourceTexture->resourceAccessType - ); - - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - commandBuffer->commandBuffer, - originalDestinationAccessType, - VK_IMAGE_ASPECT_COLOR_BIT, - 0, - destinationTexture->layerCount, - 0, - destinationTexture->levelCount, - 0, - destinationTexture->image, - &destinationTexture->resourceAccessType - ); - - VULKAN_INTERNAL_TrackTexture(renderer, commandBuffer, sourceTexture); - VULKAN_INTERNAL_TrackTexture(renderer, commandBuffer, destinationTexture); -} - -REFRESHAPI void VULKAN_CopyTextureToTexture( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice *sourceTextureSlice, - Refresh_TextureSlice *destinationTextureSlice, - Refresh_Filter filter -) { - VulkanRenderer *renderer = (VulkanRenderer*)driverData; - VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - - VULKAN_INTERNAL_BlitImage( - renderer, - vulkanCommandBuffer, - sourceTextureSlice, - destinationTextureSlice, - RefreshToVK_Filter[filter] - ); -} - -static void VULKAN_INTERNAL_SetBufferData( - VulkanBuffer* vulkanBuffer, - VkDeviceSize offsetInBytes, +static void VULKAN_INTERNAL_SetUniformBufferData( + VulkanUniformBuffer *uniformBuffer, void* data, uint32_t dataLength ) { + uint8_t *dst = + uniformBuffer->pool->mapPointer + + uniformBuffer->pool->buffer->usedRegion->resourceOffset + + uniformBuffer->poolOffset + + uniformBuffer->offset; + SDL_memcpy( - vulkanBuffer->usedRegion->allocation->mapPointer + vulkanBuffer->usedRegion->resourceOffset + offsetInBytes, + dst, data, dataLength ); } -static void VULKAN_SetBufferData( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_Buffer *buffer, - uint32_t offsetInBytes, - void* data, - uint32_t dataLength -) { - VulkanRenderer* renderer = (VulkanRenderer*) driverData; - VulkanCommandBuffer* vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanBuffer* vulkanBuffer = ((VulkanBufferContainer*) buffer)->vulkanBuffer; - VulkanTransferBuffer* transferBuffer; - uint8_t* transferBufferPointer; - VkBufferCopy bufferCopy; - VulkanResourceAccessType accessType = vulkanBuffer->resourceAccessType; - - transferBuffer = VULKAN_INTERNAL_AcquireTransferBuffer( - renderer, - vulkanCommandBuffer, - dataLength, - renderer->physicalDeviceProperties.properties.limits.optimalBufferCopyOffsetAlignment - ); - - if (transferBuffer == NULL) - { - return; - } - - transferBufferPointer = - transferBuffer->buffer->usedRegion->allocation->mapPointer + - transferBuffer->buffer->usedRegion->resourceOffset + - transferBuffer->offset; - - SDL_memcpy( - transferBufferPointer, - data, - dataLength - ); - - VULKAN_INTERNAL_BufferMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_READ, - transferBuffer->buffer - ); - - VULKAN_INTERNAL_BufferMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_WRITE, - vulkanBuffer - ); - - bufferCopy.srcOffset = transferBuffer->offset; - bufferCopy.dstOffset = offsetInBytes; - bufferCopy.size = (VkDeviceSize) dataLength; - - renderer->vkCmdCopyBuffer( - vulkanCommandBuffer->commandBuffer, - transferBuffer->buffer->buffer, - vulkanBuffer->buffer, - 1, - &bufferCopy - ); - - VULKAN_INTERNAL_BufferMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - accessType, - vulkanBuffer - ); - - transferBuffer->offset += dataLength; - - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanBuffer); -} - -/* FIXME: this should return uint64_t */ static uint32_t VULKAN_PushVertexShaderUniforms( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, @@ -7839,9 +7146,8 @@ static uint32_t VULKAN_PushVertexShaderUniforms( offset = vulkanCommandBuffer->vertexUniformBuffer->offset; - VULKAN_INTERNAL_SetBufferData( - vulkanCommandBuffer->vertexUniformBuffer->pool->buffer, - vulkanCommandBuffer->vertexUniformBuffer->poolOffset + vulkanCommandBuffer->vertexUniformBuffer->offset, + VULKAN_INTERNAL_SetUniformBufferData( + vulkanCommandBuffer->vertexUniformBuffer, data, dataLengthInBytes ); @@ -7851,7 +7157,6 @@ static uint32_t VULKAN_PushVertexShaderUniforms( return offset; } -/* FIXME: this should return uint64_t */ static uint32_t VULKAN_PushFragmentShaderUniforms( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, @@ -7883,9 +7188,8 @@ static uint32_t VULKAN_PushFragmentShaderUniforms( offset = vulkanCommandBuffer->fragmentUniformBuffer->offset; - VULKAN_INTERNAL_SetBufferData( - vulkanCommandBuffer->fragmentUniformBuffer->pool->buffer, - vulkanCommandBuffer->fragmentUniformBuffer->poolOffset + vulkanCommandBuffer->fragmentUniformBuffer->offset, + VULKAN_INTERNAL_SetUniformBufferData( + vulkanCommandBuffer->fragmentUniformBuffer, data, dataLengthInBytes ); @@ -7926,9 +7230,8 @@ static uint32_t VULKAN_PushComputeShaderUniforms( offset = vulkanCommandBuffer->computeUniformBuffer->offset; - VULKAN_INTERNAL_SetBufferData( - vulkanCommandBuffer->computeUniformBuffer->pool->buffer, - vulkanCommandBuffer->computeUniformBuffer->poolOffset + vulkanCommandBuffer->computeUniformBuffer->offset, + VULKAN_INTERNAL_SetUniformBufferData( + vulkanCommandBuffer->computeUniformBuffer, data, dataLengthInBytes ); @@ -8153,103 +7456,6 @@ static void VULKAN_BindFragmentSamplers( ); } -static void VULKAN_GetBufferData( - Refresh_Renderer *driverData, - Refresh_Buffer *buffer, - void *data, - uint32_t dataLengthInBytes -) { - VulkanBuffer* vulkanBuffer = ((VulkanBufferContainer*) buffer)->vulkanBuffer; - uint8_t *dataPtr = (uint8_t*) data; - uint8_t *mapPointer; - - mapPointer = - vulkanBuffer->usedRegion->allocation->mapPointer + - vulkanBuffer->usedRegion->resourceOffset; - - SDL_memcpy( - dataPtr, - mapPointer, - dataLengthInBytes - ); -} - -static void VULKAN_CopyTextureToBuffer( - Refresh_Renderer *driverData, - Refresh_CommandBuffer *commandBuffer, - Refresh_TextureSlice *textureSlice, - Refresh_Buffer *buffer -) { - VulkanRenderer *renderer = (VulkanRenderer*) driverData; - VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; - VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) textureSlice->texture)->vulkanTexture; - VulkanBuffer* vulkanBuffer = ((VulkanBufferContainer*) buffer)->vulkanBuffer; - - VulkanResourceAccessType prevResourceAccess; - VkBufferImageCopy imageCopy; - - /* Cache this so we can restore it later */ - prevResourceAccess = vulkanTexture->resourceAccessType; - - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - RESOURCE_ACCESS_TRANSFER_READ, - VK_IMAGE_ASPECT_COLOR_BIT, - textureSlice->layer, - 1, - textureSlice->level, - 1, - 0, - vulkanTexture->image, - &vulkanTexture->resourceAccessType - ); - - /* Save texture data to buffer */ - - imageCopy.imageExtent.width = textureSlice->rectangle.w; - imageCopy.imageExtent.height = textureSlice->rectangle.h; - imageCopy.imageExtent.depth = 1; - imageCopy.bufferRowLength = textureSlice->rectangle.w; - imageCopy.bufferImageHeight = textureSlice->rectangle.h; - imageCopy.imageOffset.x = textureSlice->rectangle.x; - imageCopy.imageOffset.y = textureSlice->rectangle.y; - imageCopy.imageOffset.z = textureSlice->depth; - imageCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imageCopy.imageSubresource.baseArrayLayer = textureSlice->layer; - imageCopy.imageSubresource.layerCount = 1; - imageCopy.imageSubresource.mipLevel = textureSlice->level; - imageCopy.bufferOffset = 0; - - renderer->vkCmdCopyImageToBuffer( - vulkanCommandBuffer->commandBuffer, - vulkanTexture->image, - AccessMap[vulkanTexture->resourceAccessType].imageLayout, - vulkanBuffer->buffer, - 1, - &imageCopy - ); - - /* Restore the image layout */ - - VULKAN_INTERNAL_ImageMemoryBarrier( - renderer, - vulkanCommandBuffer->commandBuffer, - prevResourceAccess, - VK_IMAGE_ASPECT_COLOR_BIT, - textureSlice->layer, - 1, - textureSlice->level, - 1, - 0, - vulkanTexture->image, - &vulkanTexture->resourceAccessType - ); - - VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanBuffer); - VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTexture); -} - static void VULKAN_INTERNAL_QueueDestroyTexture( VulkanRenderer *renderer, VulkanTexture *vulkanTexture @@ -8335,9 +7541,9 @@ static void VULKAN_INTERNAL_QueueDestroyBuffer( SDL_UnlockMutex(renderer->disposeLock); } -static void VULKAN_QueueDestroyBuffer( +static void VULKAN_QueueDestroyGpuBuffer( Refresh_Renderer *driverData, - Refresh_Buffer *buffer + Refresh_GpuBuffer *buffer ) { VulkanRenderer *renderer = (VulkanRenderer*) driverData; VulkanBufferContainer *vulkanBufferContainer = (VulkanBufferContainer*) buffer; @@ -8353,6 +7559,20 @@ static void VULKAN_QueueDestroyBuffer( SDL_UnlockMutex(renderer->disposeLock); } +static void VULKAN_QueueDestroyCpuBuffer( + Refresh_Renderer *driverData, + Refresh_CpuBuffer *buffer +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanBuffer *vulkanBuffer = (VulkanBuffer*) buffer; + + SDL_LockMutex(renderer->disposeLock); + + VULKAN_INTERNAL_QueueDestroyBuffer(renderer, vulkanBuffer); + + SDL_UnlockMutex(renderer->disposeLock); +} + static void VULKAN_QueueDestroyShaderModule( Refresh_Renderer *driverData, Refresh_ShaderModule *shaderModule @@ -9188,7 +8408,7 @@ static void VULKAN_BindVertexBuffers( Refresh_CommandBuffer *commandBuffer, uint32_t firstBinding, uint32_t bindingCount, - Refresh_Buffer **pBuffers, + Refresh_GpuBuffer **pBuffers, uint64_t *pOffsets ) { VulkanRenderer* renderer = (VulkanRenderer*) driverData; @@ -9218,7 +8438,7 @@ static void VULKAN_BindVertexBuffers( static void VULKAN_BindIndexBuffer( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_Buffer *buffer, + Refresh_GpuBuffer *buffer, uint64_t offset, Refresh_IndexElementSize indexElementSize ) { @@ -9236,6 +8456,16 @@ static void VULKAN_BindIndexBuffer( ); } +static void VULKAN_BeginComputePass( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer +) { + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + + vulkanCommandBuffer->boundComputeBufferCount = 0; + vulkanCommandBuffer->boundComputeTextureCount = 0; +} + static void VULKAN_BindComputePipeline( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, @@ -9292,7 +8522,7 @@ static void VULKAN_BindComputePipeline( static void VULKAN_BindComputeBuffers( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_Buffer **pBuffers + Refresh_GpuBuffer **pBuffers ) { VulkanRenderer* renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; @@ -9323,6 +8553,7 @@ static void VULKAN_BindComputeBuffers( ); VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, currentVulkanBuffer); + VULKAN_INTERNAL_TrackComputeBuffer(renderer, vulkanCommandBuffer, currentVulkanBuffer); } vulkanCommandBuffer->bufferDescriptorSet = @@ -9333,24 +8564,13 @@ static void VULKAN_BindComputeBuffers( NULL, descriptorBufferInfos ); - - if (vulkanCommandBuffer->boundComputeBufferCount == vulkanCommandBuffer->boundComputeBufferCapacity) - { - vulkanCommandBuffer->boundComputeBufferCapacity *= 2; - vulkanCommandBuffer->boundComputeBuffers = SDL_realloc( - vulkanCommandBuffer->boundComputeBuffers, - vulkanCommandBuffer->boundComputeBufferCapacity * sizeof(VulkanBuffer*) - ); - } - - vulkanCommandBuffer->boundComputeBuffers[vulkanCommandBuffer->boundComputeBufferCount] = currentVulkanBuffer; - vulkanCommandBuffer->boundComputeBufferCount += 1; } static void VULKAN_BindComputeTextures( Refresh_Renderer *driverData, Refresh_CommandBuffer *commandBuffer, - Refresh_Texture **pTextures + Refresh_Texture **pTextures, + uint32_t **pLevels ) { VulkanRenderer* renderer = (VulkanRenderer*) driverData; VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; @@ -9387,18 +8607,7 @@ static void VULKAN_BindComputeTextures( ); VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, currentTexture); - - if (vulkanCommandBuffer->boundComputeTextureCount == vulkanCommandBuffer->boundComputeTextureCapacity) - { - vulkanCommandBuffer->boundComputeTextureCapacity *= 2; - vulkanCommandBuffer->boundComputeTextures = SDL_realloc( - vulkanCommandBuffer->boundComputeTextures, - vulkanCommandBuffer->boundComputeTextureCapacity * sizeof(VulkanTexture *) - ); - } - - vulkanCommandBuffer->boundComputeTextures[i] = currentTexture; - vulkanCommandBuffer->boundComputeTextureCount += 1; + VULKAN_INTERNAL_TrackComputeTexture(renderer, vulkanCommandBuffer, currentTexture); } vulkanCommandBuffer->imageDescriptorSet = @@ -9411,6 +8620,794 @@ static void VULKAN_BindComputeTextures( ); } +static void VULKAN_DispatchCompute( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + uint32_t groupCountX, + uint32_t groupCountY, + uint32_t groupCountZ, + uint32_t computeParamOffset +) { + VulkanRenderer* renderer = (VulkanRenderer*) driverData; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + VulkanComputePipeline *computePipeline = vulkanCommandBuffer->currentComputePipeline; + VkDescriptorSet descriptorSets[3]; + + descriptorSets[0] = vulkanCommandBuffer->bufferDescriptorSet; + descriptorSets[1] = vulkanCommandBuffer->imageDescriptorSet; + descriptorSets[2] = vulkanCommandBuffer->computeUniformBuffer->descriptorSet; + + renderer->vkCmdBindDescriptorSets( + vulkanCommandBuffer->commandBuffer, + VK_PIPELINE_BIND_POINT_COMPUTE, + computePipeline->pipelineLayout->pipelineLayout, + 0, + 3, + descriptorSets, + 1, + &computeParamOffset + ); + + renderer->vkCmdDispatch( + vulkanCommandBuffer->commandBuffer, + groupCountX, + groupCountY, + groupCountZ + ); +} + +static void VULKAN_EndComputePass( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + VulkanBuffer *currentComputeBuffer; + VulkanTexture *currentComputeTexture; + VulkanResourceAccessType resourceAccessType = RESOURCE_ACCESS_NONE; + uint32_t i; + + /* Re-transition buffers */ + for (i = 0; i < vulkanCommandBuffer->boundComputeBufferCount; i += 1) + { + currentComputeBuffer = vulkanCommandBuffer->boundComputeBuffers[i]; + + if (currentComputeBuffer->usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) + { + resourceAccessType = RESOURCE_ACCESS_VERTEX_BUFFER; + } + else if (currentComputeBuffer->usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT) + { + resourceAccessType = RESOURCE_ACCESS_INDEX_BUFFER; + } + else if (currentComputeBuffer->usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) + { + resourceAccessType = RESOURCE_ACCESS_INDIRECT_BUFFER; + } + + if (resourceAccessType != RESOURCE_ACCESS_NONE) + { + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + resourceAccessType, + currentComputeBuffer + ); + } + } + + /* Re-transition sampler images */ + for (i = 0; i < vulkanCommandBuffer->boundComputeTextureCount; i += 1) + { + currentComputeTexture = vulkanCommandBuffer->boundComputeTextures[i]; + + if (currentComputeTexture->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 + ); + } + } +} + +static void* VULKAN_MapCpuBuffer( + Refresh_Renderer *driverData, + Refresh_CpuBuffer *buffer, + uint32_t offsetInBytes, + uint32_t sizeInBytes +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanBuffer *vulkanBuffer = (VulkanBuffer*) buffer; + VkResult result; + void* mapPointer; + + result = renderer->vkMapMemory( + renderer->logicalDevice, + vulkanBuffer->usedRegion->allocation->memory, + offsetInBytes, + sizeInBytes, + 0, + &mapPointer + ); + VULKAN_ERROR_CHECK(result, vkMapMemory, NULL) + + return mapPointer; +} + +static void VULKAN_UnmapCpuBuffer( + Refresh_Renderer *driverData, + Refresh_CpuBuffer *buffer +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanBuffer *vulkanBuffer = (VulkanBuffer*) buffer; + + renderer->vkUnmapMemory( + renderer->logicalDevice, + vulkanBuffer->usedRegion->allocation->memory + ); +} + +static void VULKAN_BeginCopyPass( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + + vulkanCommandBuffer->copiedGpuBufferCount = 0; + vulkanCommandBuffer->copiedTextureCount = 0; +} + +static void VULKAN_UploadToTexture( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_CpuBuffer *cpuBuffer, + Refresh_TextureSlice *textureSlice, + Refresh_BufferImageCopy *copyParams +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + VulkanBuffer *vulkanCpuBuffer = (VulkanBuffer*) cpuBuffer; + VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) textureSlice->texture)->vulkanTexture; + VkBufferImageCopy imageCopy; + + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_READ, + vulkanCpuBuffer + ); + + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_WRITE, + vulkanTexture->aspectFlags, + 0, + vulkanTexture->layerCount, + 0, + vulkanTexture->levelCount, + 0, + vulkanTexture->image, + &vulkanTexture->resourceAccessType + ); + + 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.imageSubresource.aspectMask = vulkanTexture->aspectFlags; + imageCopy.imageSubresource.baseArrayLayer = textureSlice->baseLayer; + imageCopy.imageSubresource.layerCount = textureSlice->layerCount; + imageCopy.imageSubresource.mipLevel = textureSlice->mipLevel; + imageCopy.bufferOffset = copyParams->bufferOffset; + imageCopy.bufferRowLength = copyParams->bufferStride; + imageCopy.bufferImageHeight = copyParams->bufferImageHeight; + + renderer->vkCmdCopyBufferToImage( + vulkanCommandBuffer->commandBuffer, + vulkanCpuBuffer->buffer, + vulkanTexture->image, + AccessMap[vulkanTexture->resourceAccessType].imageLayout, + 1, + &imageCopy + ); + + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanCpuBuffer); + VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTexture); + VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, vulkanTexture); +} + +static void VULKAN_UploadToBuffer( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_CpuBuffer *cpuBuffer, + Refresh_GpuBuffer *gpuBuffer, + Refresh_BufferCopy *copyParams +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + VulkanBuffer *vulkanCpuBuffer = (VulkanBuffer*) cpuBuffer; + VulkanBuffer *vulkanGpuBuffer = ((VulkanBufferContainer*) gpuBuffer)->vulkanBuffer; + VkBufferCopy bufferCopy; + + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_READ, + vulkanCpuBuffer + ); + + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_WRITE, + vulkanGpuBuffer + ); + + bufferCopy.srcOffset = copyParams->srcOffset; + bufferCopy.dstOffset = copyParams->dstOffset; + bufferCopy.size = copyParams->size; + + renderer->vkCmdCopyBuffer( + vulkanCommandBuffer->commandBuffer, + vulkanCpuBuffer->buffer, + vulkanGpuBuffer->buffer, + 1, + &bufferCopy + ); + + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanCpuBuffer); + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanGpuBuffer); + VULKAN_INTERNAL_TrackCopiedBuffer(renderer, vulkanCommandBuffer, vulkanGpuBuffer); +} + +static void VULKAN_DownloadFromTexture( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_TextureSlice *textureSlice, + Refresh_CpuBuffer *cpuBuffer, + Refresh_BufferImageCopy *copyParams +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) textureSlice->texture)->vulkanTexture; + VulkanBuffer *vulkanCpuBuffer = (VulkanBuffer*) cpuBuffer; + VkBufferImageCopy imageCopy; + + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_WRITE, + vulkanCpuBuffer + ); + + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_READ, + vulkanTexture->aspectFlags, + 0, + vulkanTexture->layerCount, + 0, + vulkanTexture->levelCount, + 0, + vulkanTexture->image, + &vulkanTexture->resourceAccessType + ); + + 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.imageSubresource.aspectMask = vulkanTexture->aspectFlags; + imageCopy.imageSubresource.baseArrayLayer = textureSlice->baseLayer; + imageCopy.imageSubresource.layerCount = textureSlice->layerCount; + imageCopy.imageSubresource.mipLevel = textureSlice->mipLevel; + imageCopy.bufferOffset = copyParams->bufferOffset; + imageCopy.bufferRowLength = copyParams->bufferStride; + imageCopy.bufferImageHeight = copyParams->bufferImageHeight; + + renderer->vkCmdCopyImageToBuffer( + vulkanCommandBuffer->commandBuffer, + vulkanTexture->image, + AccessMap[vulkanTexture->resourceAccessType].imageLayout, + vulkanCpuBuffer->buffer, + 1, + &imageCopy + ); + + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanCpuBuffer); + VULKAN_INTERNAL_TrackTexture(renderer, vulkanCommandBuffer, vulkanTexture); + VULKAN_INTERNAL_TrackCopiedTexture(renderer, vulkanCommandBuffer, vulkanTexture); +} + +static void VULKAN_DownloadFromBuffer( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_GpuBuffer *gpuBuffer, + Refresh_CpuBuffer *cpuBuffer, + Refresh_BufferCopy *copyParams +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + VulkanBuffer *vulkanCpuBuffer = (VulkanBuffer*) cpuBuffer; + VulkanBuffer *vulkanGpuBuffer = ((VulkanBufferContainer*) gpuBuffer)->vulkanBuffer; + VkBufferCopy bufferCopy; + + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_WRITE, + vulkanCpuBuffer + ); + + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_READ, + vulkanGpuBuffer + ); + + bufferCopy.srcOffset = copyParams->srcOffset; + bufferCopy.dstOffset = copyParams->dstOffset; + bufferCopy.size = copyParams->size; + + renderer->vkCmdCopyBuffer( + vulkanCommandBuffer->commandBuffer, + vulkanGpuBuffer->buffer, + vulkanCpuBuffer->buffer, + 1, + &bufferCopy + ); + + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanCpuBuffer); + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanGpuBuffer); + VULKAN_INTERNAL_TrackBuffer(renderer, vulkanCommandBuffer, vulkanGpuBuffer); +} + +static void VULKAN_CopyTextureToTexture( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_TextureSlice *source, + Refresh_TextureSlice *destination +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + VulkanTexture *srcTexture = ((VulkanTextureContainer*) source->texture)->vulkanTexture; + VulkanTexture *dstTexture = ((VulkanTextureContainer*) destination->texture)->vulkanTexture; + VkImageCopy imageCopy; + + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_READ, + VK_IMAGE_ASPECT_COLOR_BIT, + 0, + srcTexture->layerCount, + 0, + srcTexture->levelCount, + 0, + srcTexture->image, + &srcTexture->resourceAccessType + ); + + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_WRITE, + VK_IMAGE_ASPECT_COLOR_BIT, + 0, + dstTexture->layerCount, + 0, + dstTexture->levelCount, + 0, + dstTexture->image, + &dstTexture->resourceAccessType + ); + + imageCopy.srcOffset.x = source->x; + imageCopy.srcOffset.y = source->y; + imageCopy.srcOffset.z = source->z; + imageCopy.srcSubresource.aspectMask = srcTexture->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.baseArrayLayer = destination->baseLayer; + imageCopy.dstSubresource.layerCount = destination->layerCount; + imageCopy.dstSubresource.mipLevel = destination->mipLevel; + imageCopy.extent.width = source->w; + imageCopy.extent.height = source->h; + imageCopy.extent.depth = source->d; + + renderer->vkCmdCopyImage( + vulkanCommandBuffer->commandBuffer, + srcTexture->image, + AccessMap[srcTexture->resourceAccessType].imageLayout, + dstTexture->image, + AccessMap[dstTexture->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); +} + +static void VULKAN_CopyTextureToBuffer( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_TextureSlice *textureSlice, + Refresh_GpuBuffer *buffer, + Refresh_BufferImageCopy *copyParams +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) textureSlice->texture)->vulkanTexture; + VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer*) buffer)->vulkanBuffer; + VkBufferImageCopy imageCopy; + + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_READ, + vulkanTexture->aspectFlags, + 0, + vulkanTexture->layerCount, + 0, + vulkanTexture->levelCount, + 0, + vulkanTexture->image, + &vulkanTexture->resourceAccessType + ); + + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_WRITE, + 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.imageSubresource.aspectMask = vulkanTexture->aspectFlags; + imageCopy.imageSubresource.baseArrayLayer = textureSlice->baseLayer; + imageCopy.imageSubresource.layerCount = textureSlice->layerCount; + imageCopy.imageSubresource.mipLevel = textureSlice->mipLevel; + imageCopy.bufferOffset = copyParams->bufferOffset; + imageCopy.bufferRowLength = copyParams->bufferStride; + imageCopy.bufferImageHeight = copyParams->bufferImageHeight; + + renderer->vkCmdCopyImageToBuffer( + vulkanCommandBuffer->commandBuffer, + vulkanTexture->image, + AccessMap[vulkanTexture->resourceAccessType].imageLayout, + 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); +} + +static void VULKAN_CopyBufferToTexture( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_GpuBuffer *buffer, + Refresh_TextureSlice *textureSlice, + Refresh_BufferImageCopy *copyParams +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer*) buffer)->vulkanBuffer; + VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) textureSlice->texture)->vulkanTexture; + VkBufferImageCopy imageCopy; + + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_READ, + vulkanBuffer + ); + + VULKAN_INTERNAL_ImageMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_WRITE, + vulkanTexture->aspectFlags, + 0, + vulkanTexture->layerCount, + 0, + vulkanTexture->levelCount, + 0, + vulkanTexture->image, + &vulkanTexture->resourceAccessType + ); + + 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.imageSubresource.aspectMask = vulkanTexture->aspectFlags; + imageCopy.imageSubresource.baseArrayLayer = textureSlice->baseLayer; + imageCopy.imageSubresource.layerCount = textureSlice->layerCount; + imageCopy.imageSubresource.mipLevel = textureSlice->mipLevel; + imageCopy.bufferOffset = copyParams->bufferOffset; + imageCopy.bufferRowLength = copyParams->bufferStride; + imageCopy.bufferImageHeight = copyParams->bufferImageHeight; + + renderer->vkCmdCopyBufferToImage( + vulkanCommandBuffer->commandBuffer, + vulkanBuffer->buffer, + vulkanTexture->image, + AccessMap[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); +} + +static void VULKAN_CopyBufferToBuffer( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_GpuBuffer *source, + Refresh_GpuBuffer *destination, + Refresh_BufferCopy *copyParams +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + VulkanBuffer *vulkanSrcBuffer = ((VulkanBufferContainer*) source)->vulkanBuffer; + VulkanBuffer *vulkanDstBuffer = ((VulkanBufferContainer*) destination)->vulkanBuffer; + VkBufferCopy bufferCopy; + + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_READ, + vulkanSrcBuffer + ); + + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + RESOURCE_ACCESS_TRANSFER_WRITE, + vulkanDstBuffer + ); + + bufferCopy.srcOffset = copyParams->srcOffset; + bufferCopy.dstOffset = copyParams->dstOffset; + bufferCopy.size = copyParams->size; + + renderer->vkCmdCopyBuffer( + vulkanCommandBuffer->commandBuffer, + vulkanSrcBuffer->buffer, + vulkanDstBuffer->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); +} + +static void VULKAN_GenerateMipmaps( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer, + Refresh_Texture *texture +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + VulkanTexture *vulkanTexture = ((VulkanTextureContainer*) texture)->vulkanTexture; + VulkanResourceAccessType *levelAccessType; + VkImageBlit blit; + uint32_t 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! */ + for (level = 1; level < vulkanTexture->levelCount; level += 1) + { + 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] + ); + + 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] + ); + + blit.srcOffsets[0].x = 0; + blit.srcOffsets[0].y = 0; + blit.srcOffsets[0].z = 0; + + blit.srcOffsets[1].x = vulkanTexture->dimensions.width >> (level - 1); + blit.srcOffsets[1].y = vulkanTexture->dimensions.height >> (level - 1); + blit.srcOffsets[1].z = 1; + + blit.dstOffsets[0].x = 0; + blit.dstOffsets[0].y = 0; + blit.dstOffsets[0].z = 0; + + blit.dstOffsets[1].x = vulkanTexture->dimensions.width >> level; + blit.dstOffsets[1].y = vulkanTexture->dimensions.height >> level; + blit.dstOffsets[1].z = 1; + + blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.srcSubresource.baseArrayLayer = 0; + blit.srcSubresource.layerCount = vulkanTexture->layerCount; + blit.srcSubresource.mipLevel = level - 1; + + blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + blit.dstSubresource.baseArrayLayer = 0; + blit.dstSubresource.layerCount = vulkanTexture->layerCount; + blit.dstSubresource.mipLevel = level; + + renderer->vkCmdBlitImage( + vulkanCommandBuffer->commandBuffer, + vulkanTexture->image, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + vulkanTexture->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + &blit, + 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( + Refresh_Renderer *driverData, + Refresh_CommandBuffer *commandBuffer +) { + VulkanRenderer *renderer = (VulkanRenderer*) driverData; + VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer*) commandBuffer; + VulkanBuffer *currentBuffer; + VulkanTexture *currentTexture; + VulkanResourceAccessType resourceAccessType = RESOURCE_ACCESS_NONE; + uint32_t i; + + /* Re-transition GpuBuffers */ + for (i = 0; i < vulkanCommandBuffer->copiedGpuBufferCount; i += 1) + { + currentBuffer = vulkanCommandBuffer->copiedGpuBuffers[i]; + + if (currentBuffer->usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) + { + resourceAccessType = RESOURCE_ACCESS_VERTEX_BUFFER; + } + else if (currentBuffer->usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT) + { + resourceAccessType = RESOURCE_ACCESS_INDEX_BUFFER; + } + else if (currentBuffer->usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) + { + resourceAccessType = RESOURCE_ACCESS_INDIRECT_BUFFER; + } + + if (resourceAccessType != RESOURCE_ACCESS_NONE) + { + VULKAN_INTERNAL_BufferMemoryBarrier( + renderer, + vulkanCommandBuffer->commandBuffer, + resourceAccessType, + currentBuffer + ); + } + } + + /* Re-transition textures */ + for (i = 0; i < vulkanCommandBuffer->copiedTextureCount; i += 1) + { + currentTexture = vulkanCommandBuffer->copiedTextures[i]; + + if (currentTexture->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 + ); + } + } +} + static void VULKAN_INTERNAL_AllocateCommandBuffers( VulkanRenderer *renderer, VulkanCommandPool *vulkanCommandPool, @@ -9478,14 +9475,6 @@ static void VULKAN_INTERNAL_AllocateCommandBuffers( commandBuffer->signalSemaphoreCapacity * sizeof(VkSemaphore) ); - /* Transfer buffer tracking */ - - commandBuffer->transferBufferCapacity = 4; - commandBuffer->transferBufferCount = 0; - commandBuffer->transferBuffers = SDL_malloc( - commandBuffer->transferBufferCapacity * sizeof(VulkanTransferBuffer*) - ); - /* Bound buffer tracking */ commandBuffer->boundUniformBufferCapacity = 16; @@ -9516,6 +9505,20 @@ static void VULKAN_INTERNAL_AllocateCommandBuffers( commandBuffer->boundComputeTextureCapacity * sizeof(VulkanTexture*) ); + /* Copy resource tracking */ + + commandBuffer->copiedGpuBufferCapacity = 16; + commandBuffer->copiedGpuBufferCount = 0; + commandBuffer->copiedGpuBuffers = SDL_malloc( + commandBuffer->copiedGpuBufferCapacity * sizeof(VulkanBuffer*) + ); + + commandBuffer->copiedTextureCapacity = 16; + commandBuffer->copiedTextureCount = 0; + commandBuffer->copiedTextures = SDL_malloc( + commandBuffer->copiedTextureCapacity * sizeof(VulkanTexture*) + ); + /* Resource tracking */ commandBuffer->usedBufferCapacity = 4; @@ -10200,30 +10203,6 @@ static void VULKAN_INTERNAL_CleanCommandBuffer( commandBuffer->boundUniformBufferCount = 0; - /* Clean up transfer buffers */ - - for (i = 0; i < commandBuffer->transferBufferCount; i += 1) - { - if (commandBuffer->transferBuffers[i]->fromPool) - { - SDL_LockMutex(renderer->transferBufferPool.lock); - - commandBuffer->transferBuffers[i]->offset = 0; - renderer->transferBufferPool.availableBuffers[renderer->transferBufferPool.availableBufferCount] = commandBuffer->transferBuffers[i]; - renderer->transferBufferPool.availableBufferCount += 1; - - SDL_UnlockMutex(renderer->transferBufferPool.lock); - } - else - { - VULKAN_INTERNAL_QueueDestroyBuffer(renderer, commandBuffer->transferBuffers[i]->buffer); - SDL_free(commandBuffer->transferBuffers[i]); - commandBuffer->transferBuffers[i] = NULL; - } - } - - commandBuffer->transferBufferCount = 0; - /* Bound descriptor sets are now available */ for (i = 0; i < commandBuffer->boundDescriptorSetDataCount; i += 1) @@ -11717,9 +11696,6 @@ static Refresh_Device* VULKAN_CreateDevice( /* Variables: Image Format Detection */ VkImageFormatProperties imageFormatProperties; - /* Variables: Transfer buffer init */ - VulkanTransferBuffer *transferBuffer; - SDL_memset(renderer, '\0', sizeof(VulkanRenderer)); renderer->debugMode = debugMode; @@ -12102,41 +12078,6 @@ static Refresh_Device* VULKAN_CreateDevice( renderer->renderTargetHashArray.count = 0; renderer->renderTargetHashArray.capacity = 0; - /* Initialize transfer buffer pool */ - - renderer->transferBufferPool.lock = SDL_CreateMutex(); - - renderer->transferBufferPool.availableBufferCapacity = 4; - renderer->transferBufferPool.availableBufferCount = 0; - renderer->transferBufferPool.availableBuffers = SDL_malloc( - renderer->transferBufferPool.availableBufferCapacity * sizeof(VulkanTransferBuffer*) - ); - - for (i = 0; i < renderer->transferBufferPool.availableBufferCapacity; i += 1) - { - transferBuffer = SDL_malloc(sizeof(VulkanTransferBuffer)); - transferBuffer->offset = 0; - transferBuffer->fromPool = 1; - transferBuffer->buffer = VULKAN_INTERNAL_CreateBuffer( - renderer, - POOLED_TRANSFER_BUFFER_SIZE, - RESOURCE_ACCESS_TRANSFER_READ_WRITE, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - 1, - 0, - 1 - ); - - if (transferBuffer->buffer == NULL) - { - Refresh_LogError("Failed to allocate transfer buffer!"); - SDL_free(transferBuffer); - } - - renderer->transferBufferPool.availableBuffers[i] = transferBuffer; - renderer->transferBufferPool.availableBufferCount += 1; - } - /* Initialize fence pool */ renderer->fencePool.lock = SDL_CreateMutex();