diff --git a/src/rendering/vulkan/renderer/vk_postprocess.cpp b/src/rendering/vulkan/renderer/vk_postprocess.cpp index 8d5c8a9d7..62b31b5b1 100644 --- a/src/rendering/vulkan/renderer/vk_postprocess.cpp +++ b/src/rendering/vulkan/renderer/vk_postprocess.cpp @@ -347,7 +347,7 @@ VkPPTexture::VkPPTexture(PPTexture *texture) PipelineBarrier barrier0; barrier0.addImage(Image.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT); - barrier0.execute(fb->GetUploadCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + barrier0.execute(fb->GetTransferCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); void *data = Staging->Map(0, totalsize); memcpy(data, texture->Data.get(), totalsize); @@ -359,18 +359,26 @@ VkPPTexture::VkPPTexture(PPTexture *texture) region.imageExtent.depth = 1; region.imageExtent.width = texture->Width; region.imageExtent.height = texture->Height; - fb->GetUploadCommands()->copyBufferToImage(Staging->buffer, Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + fb->GetTransferCommands()->copyBufferToImage(Staging->buffer, Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); PipelineBarrier barrier1; barrier1.addImage(Image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT); - barrier1.execute(fb->GetUploadCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + barrier1.execute(fb->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); Layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + if (fb->device->transferFamily != fb->device->graphicsFamily) + { + PipelineBarrier transfer; + transfer.addQueueTransfer(fb->device->transferFamily, fb->device->graphicsFamily, Image.get(), Layout); + transfer.execute(fb->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + transfer.execute(fb->GetPreDrawCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + } } else { PipelineBarrier barrier; barrier.addImage(Image.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT); - barrier.execute(fb->GetUploadCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + barrier.execute(fb->GetPreDrawCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); Layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; } } diff --git a/src/rendering/vulkan/system/vk_buffers.cpp b/src/rendering/vulkan/system/vk_buffers.cpp index c5a3d780d..493bd8762 100644 --- a/src/rendering/vulkan/system/vk_buffers.cpp +++ b/src/rendering/vulkan/system/vk_buffers.cpp @@ -42,7 +42,15 @@ void VKBuffer::SetData(size_t size, const void *data, bool staticdata) memcpy(dst, data, size); mStaging->Unmap(); - fb->GetUploadCommands()->copyBuffer(mStaging.get(), mBuffer.get()); + fb->GetTransferCommands()->copyBuffer(mStaging.get(), mBuffer.get()); + + if (fb->device->transferFamily != fb->device->graphicsFamily) + { + PipelineBarrier transfer; + transfer.addQueueTransfer(fb->device->transferFamily, fb->device->graphicsFamily, mBuffer.get(), VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_SHADER_READ_BIT); + transfer.execute(fb->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + transfer.execute(fb->GetPreDrawCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + } } else { @@ -78,7 +86,22 @@ void VKBuffer::SetSubData(size_t offset, size_t size, const void *data) memcpy(dst, data, size); mStaging->Unmap(); - fb->GetUploadCommands()->copyBuffer(mStaging.get(), mBuffer.get(), offset, offset, size); + if (fb->device->transferFamily != fb->device->graphicsFamily) + { + PipelineBarrier transfer; + transfer.addQueueTransfer(fb->device->graphicsFamily, fb->device->transferFamily, mBuffer.get(), VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_SHADER_READ_BIT, 0); + transfer.execute(fb->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + } + + fb->GetTransferCommands()->copyBuffer(mStaging.get(), mBuffer.get(), offset, offset, size); + + if (fb->device->transferFamily != fb->device->graphicsFamily) + { + PipelineBarrier transfer; + transfer.addQueueTransfer(fb->device->transferFamily, fb->device->graphicsFamily, mBuffer.get(), VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_SHADER_READ_BIT); + transfer.execute(fb->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + transfer.execute(fb->GetPreDrawCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + } } else { diff --git a/src/rendering/vulkan/system/vk_builders.h b/src/rendering/vulkan/system/vk_builders.h index 49fc0a8b7..3d9201697 100644 --- a/src/rendering/vulkan/system/vk_builders.h +++ b/src/rendering/vulkan/system/vk_builders.h @@ -292,6 +292,8 @@ public: void addBuffer(VulkanBuffer *buffer, VkDeviceSize offset, VkDeviceSize size, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); void addImage(VulkanImage *image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1); void addImage(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1); + void addQueueTransfer(int srcFamily, int dstFamily, VulkanBuffer *buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask); + void addQueueTransfer(int srcFamily, int dstFamily, VulkanImage *image, VkImageLayout layout, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1); void execute(VulkanCommandBuffer *commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags = 0); @@ -301,6 +303,24 @@ private: FixedSizeVector imageMemoryBarriers; }; +class QueueSubmit +{ +public: + QueueSubmit(); + + void addCommandBuffer(VulkanCommandBuffer *buffer); + void addWait(VkPipelineStageFlags waitStageMask, VulkanSemaphore *semaphore); + void addSignal(VulkanSemaphore *semaphore); + void execute(VulkanDevice *device, VkQueue queue, VulkanFence *fence = nullptr); + +private: + VkSubmitInfo submitInfo = {}; + FixedSizeVector waitSemaphores; + FixedSizeVector waitStages; + FixedSizeVector signalSemaphores; + FixedSizeVector commandBuffers; +}; + class WriteDescriptors { public: @@ -1140,6 +1160,37 @@ inline void PipelineBarrier::addImage(VkImage image, VkImageLayout oldLayout, Vk imageMemoryBarriers.push_back(barrier); } +inline void PipelineBarrier::addQueueTransfer(int srcFamily, int dstFamily, VulkanBuffer *buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) +{ + VkBufferMemoryBarrier barrier = { }; + barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + barrier.srcAccessMask = srcAccessMask; + barrier.dstAccessMask = dstAccessMask; + barrier.srcQueueFamilyIndex = srcFamily; + barrier.dstQueueFamilyIndex = dstFamily; + barrier.buffer = buffer->buffer; + barrier.offset = 0; + barrier.size = buffer->size; + bufferMemoryBarriers.push_back(barrier); +} + +inline void PipelineBarrier::addQueueTransfer(int srcFamily, int dstFamily, VulkanImage *image, VkImageLayout layout, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount) +{ + VkImageMemoryBarrier barrier = { }; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.oldLayout = layout; + barrier.newLayout = layout; + barrier.srcQueueFamilyIndex = srcFamily; + barrier.dstQueueFamilyIndex = dstFamily; + barrier.image = image->image; + barrier.subresourceRange.aspectMask = aspectMask; + barrier.subresourceRange.baseMipLevel = baseMipLevel; + barrier.subresourceRange.levelCount = levelCount; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + imageMemoryBarriers.push_back(barrier); +} + inline void PipelineBarrier::execute(VulkanCommandBuffer *commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags) { commandBuffer->pipelineBarrier( @@ -1151,6 +1202,44 @@ inline void PipelineBarrier::execute(VulkanCommandBuffer *commandBuffer, VkPipel ///////////////////////////////////////////////////////////////////////////// +inline QueueSubmit::QueueSubmit() +{ + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; +} + +inline void QueueSubmit::addCommandBuffer(VulkanCommandBuffer *buffer) +{ + commandBuffers.push_back(buffer->buffer); + submitInfo.pCommandBuffers = commandBuffers.data(); + submitInfo.commandBufferCount = (uint32_t)commandBuffers.size(); +} + +inline void QueueSubmit::addWait(VkPipelineStageFlags waitStageMask, VulkanSemaphore *semaphore) +{ + waitStages.push_back(waitStageMask); + waitSemaphores.push_back(semaphore->semaphore); + + submitInfo.pWaitDstStageMask = waitStages.data(); + submitInfo.pWaitSemaphores = waitSemaphores.data(); + submitInfo.waitSemaphoreCount = (uint32_t)waitSemaphores.size(); +} + +inline void QueueSubmit::addSignal(VulkanSemaphore *semaphore) +{ + signalSemaphores.push_back(semaphore->semaphore); + submitInfo.pSignalSemaphores = signalSemaphores.data(); + submitInfo.signalSemaphoreCount = (uint32_t)signalSemaphores.size(); +} + +inline void QueueSubmit::execute(VulkanDevice *device, VkQueue queue, VulkanFence *fence) +{ + VkResult result = vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, fence ? fence->fence : VK_NULL_HANDLE); + if (result < VK_SUCCESS) + throw std::runtime_error("Failed to submit command buffer"); +} + +///////////////////////////////////////////////////////////////////////////// + inline void WriteDescriptors::addBuffer(VulkanDescriptorSet *descriptorSet, int binding, VkDescriptorType type, VulkanBuffer *buffer) { addBuffer(descriptorSet, binding, type, buffer, 0, buffer->size); diff --git a/src/rendering/vulkan/system/vk_framebuffer.cpp b/src/rendering/vulkan/system/vk_framebuffer.cpp index 1ad33cebe..ca667e5d3 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/rendering/vulkan/system/vk_framebuffer.cpp @@ -118,8 +118,10 @@ void VulkanFrameBuffer::InitializeState() uniformblockalignment = (unsigned int)device->PhysicalDevice.Properties.limits.minUniformBufferOffsetAlignment; maxuniformblock = device->PhysicalDevice.Properties.limits.maxUniformBufferRange; - mUploadSemaphore.reset(new VulkanSemaphore(device)); + mTransferSemaphore.reset(new VulkanSemaphore(device)); + mPreDrawSemaphore.reset(new VulkanSemaphore(device)); mGraphicsCommandPool.reset(new VulkanCommandPool(device, device->graphicsFamily)); + mTransferCommandPool.reset(new VulkanCommandPool(device, device->transferFamily)); mScreenBuffers.reset(new VkRenderBuffers()); mSaveBuffers.reset(new VkRenderBuffers()); @@ -206,7 +208,8 @@ void VulkanFrameBuffer::Update() vkResetFences(device->device, 1, &mRenderFinishedFence->fence); mDrawCommands.reset(); - mUploadCommands.reset(); + mTransferCommands.reset(); + mPreDrawCommands.reset(); DeleteFrameObjects(); Finish.Unclock(); @@ -224,62 +227,50 @@ void VulkanFrameBuffer::DeleteFrameObjects() void VulkanFrameBuffer::SubmitCommands(bool finish) { + if (mTransferCommands) + { + mTransferCommands->end(); + + QueueSubmit submit; + submit.addCommandBuffer(mTransferCommands.get()); + submit.addSignal(mTransferSemaphore.get()); + submit.execute(device, device->transferQueue); + } + + if (mPreDrawCommands) + { + mPreDrawCommands->end(); + + QueueSubmit submit; + submit.addCommandBuffer(mPreDrawCommands.get()); + if (mTransferCommands) + submit.addWait(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, mTransferSemaphore.get()); + submit.addSignal(mPreDrawSemaphore.get()); + submit.execute(device, device->graphicsQueue); + } + mDrawCommands->end(); - if (mUploadCommands) + QueueSubmit submit; + submit.addCommandBuffer(mDrawCommands.get()); + if (mPreDrawCommands) + submit.addWait(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, mPreDrawSemaphore.get()); + else if (mTransferCommands) + submit.addWait(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, mTransferSemaphore.get()); + if (finish) { - mUploadCommands->end(); - - // Submit upload commands immediately - VkSubmitInfo submitInfo = {}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &mUploadCommands->buffer; - submitInfo.signalSemaphoreCount = 1; - submitInfo.pSignalSemaphores = &mUploadSemaphore->semaphore; - VkResult result = vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE); - if (result < VK_SUCCESS) - I_FatalError("Failed to submit command buffer! Error %d\n", result); - - // Wait for upload commands to finish, then submit render commands - VkSemaphore waitSemaphores[] = { mUploadSemaphore->semaphore, mSwapChainImageAvailableSemaphore->semaphore }; - VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; - submitInfo.waitSemaphoreCount = finish ? 2 : 1; - submitInfo.pWaitSemaphores = waitSemaphores; - submitInfo.pWaitDstStageMask = waitStages; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &mDrawCommands->buffer; - submitInfo.signalSemaphoreCount = finish ? 1 : 0; - submitInfo.pSignalSemaphores = &mRenderFinishedSemaphore->semaphore; - result = vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, mRenderFinishedFence->fence); - if (result < VK_SUCCESS) - I_FatalError("Failed to submit command buffer! Error %d\n", result); - } - else - { - VkSemaphore waitSemaphores[] = { mSwapChainImageAvailableSemaphore->semaphore }; - VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; - - VkSubmitInfo submitInfo = {}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.waitSemaphoreCount = finish ? 1 : 0; - submitInfo.pWaitSemaphores = waitSemaphores; - submitInfo.pWaitDstStageMask = waitStages; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &mDrawCommands->buffer; - submitInfo.signalSemaphoreCount = finish ? 1 : 0; - submitInfo.pSignalSemaphores = &mRenderFinishedSemaphore->semaphore; - VkResult result = vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, mRenderFinishedFence->fence); - if (result < VK_SUCCESS) - I_FatalError("Failed to submit command buffer! Error %d\n", result); + submit.addWait(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, mSwapChainImageAvailableSemaphore.get()); + submit.addSignal(mRenderFinishedSemaphore.get()); } + submit.execute(device, device->graphicsQueue, mRenderFinishedFence.get()); if (!finish) { vkWaitForFences(device->device, 1, &mRenderFinishedFence->fence, VK_TRUE, std::numeric_limits::max()); vkResetFences(device->device, 1, &mRenderFinishedFence->fence); mDrawCommands.reset(); - mUploadCommands.reset(); + mTransferCommands.reset(); + mPreDrawCommands.reset(); DeleteFrameObjects(); } } @@ -794,15 +785,26 @@ void VulkanFrameBuffer::Draw2D() ::Draw2D(&m2DDrawer, *mRenderState); } -VulkanCommandBuffer *VulkanFrameBuffer::GetUploadCommands() +VulkanCommandBuffer *VulkanFrameBuffer::GetTransferCommands() { - if (!mUploadCommands) + if (!mTransferCommands) { - mUploadCommands = mGraphicsCommandPool->createBuffer(); - mUploadCommands->SetDebugName("VulkanFrameBuffer.mUploadCommands"); - mUploadCommands->begin(); + mTransferCommands = mTransferCommandPool->createBuffer(); + mTransferCommands->SetDebugName("VulkanFrameBuffer.mTransferCommands"); + mTransferCommands->begin(); } - return mUploadCommands.get(); + return mTransferCommands.get(); +} + +VulkanCommandBuffer *VulkanFrameBuffer::GetPreDrawCommands() +{ + if (!mPreDrawCommands) + { + mPreDrawCommands = mGraphicsCommandPool->createBuffer(); + mPreDrawCommands->SetDebugName("VulkanFrameBuffer.mPreDrawCommands"); + mPreDrawCommands->begin(); + } + return mPreDrawCommands.get(); } VulkanCommandBuffer *VulkanFrameBuffer::GetDrawCommands() diff --git a/src/rendering/vulkan/system/vk_framebuffer.h b/src/rendering/vulkan/system/vk_framebuffer.h index 6a169ec48..692606305 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.h +++ b/src/rendering/vulkan/system/vk_framebuffer.h @@ -25,7 +25,8 @@ public: std::unique_ptr swapChain; uint32_t presentImageIndex = 0; - VulkanCommandBuffer *GetUploadCommands(); + VulkanCommandBuffer *GetTransferCommands(); + VulkanCommandBuffer *GetPreDrawCommands(); VulkanCommandBuffer *GetDrawCommands(); VkShaderManager *GetShaderManager() { return mShaderManager.get(); } VkSamplerManager *GetSamplerManager() { return mSamplerManager.get(); } @@ -114,9 +115,12 @@ private: std::unique_ptr mPostprocess; std::unique_ptr mRenderPassManager; std::unique_ptr mGraphicsCommandPool; - std::unique_ptr mUploadCommands; + std::unique_ptr mTransferCommandPool; + std::unique_ptr mTransferCommands; + std::unique_ptr mPreDrawCommands; std::unique_ptr mDrawCommands; - std::unique_ptr mUploadSemaphore; + std::unique_ptr mTransferSemaphore; + std::unique_ptr mPreDrawSemaphore; std::unique_ptr mRenderState; std::unique_ptr mSwapChainImageAvailableSemaphore; diff --git a/src/rendering/vulkan/textures/vk_hwtexture.cpp b/src/rendering/vulkan/textures/vk_hwtexture.cpp index 45591e9c4..10dacecc4 100644 --- a/src/rendering/vulkan/textures/vk_hwtexture.cpp +++ b/src/rendering/vulkan/textures/vk_hwtexture.cpp @@ -195,7 +195,7 @@ void VkHardwareTexture::CreateImage(FTexture *tex, int translation, int flags) mImageView = viewbuilder.create(fb->device); mImageView->SetDebugName("VkHardwareTexture.mImageView"); - auto cmdbuffer = fb->GetUploadCommands(); + auto cmdbuffer = fb->GetPreDrawCommands(); PipelineBarrier imageTransition; imageTransition.addImage(mImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 0, VK_ACCESS_SHADER_READ_BIT); @@ -231,7 +231,7 @@ void VkHardwareTexture::CreateTexture(int w, int h, int pixelsize, VkFormat form mImageView = viewbuilder.create(fb->device); mImageView->SetDebugName("VkHardwareTexture.mImageView"); - auto cmdbuffer = fb->GetUploadCommands(); + auto cmdbuffer = fb->GetTransferCommands(); PipelineBarrier imageTransition0; imageTransition0.addImage(mImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT); @@ -289,6 +289,15 @@ void VkHardwareTexture::GenerateMipmaps(VulkanImage *image, VulkanCommandBuffer PipelineBarrier barrier2; barrier2.addImage(image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, i - 1); barrier2.execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + auto fb = GetVulkanFrameBuffer(); + if (fb->device->transferFamily != fb->device->graphicsFamily) + { + PipelineBarrier transfer; + transfer.addQueueTransfer(fb->device->transferFamily, fb->device->graphicsFamily, image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_ASPECT_COLOR_BIT, 0, GetMipLevels(image->width, image->height)); + transfer.execute(fb->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + transfer.execute(fb->GetPreDrawCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + } } int VkHardwareTexture::GetMipLevels(int w, int h) @@ -326,7 +335,7 @@ void VkHardwareTexture::AllocateBuffer(int w, int h, int texelsize) mImageView = viewbuilder.create(fb->device); mImageView->SetDebugName("VkHardwareTexture.mImageView"); - auto cmdbuffer = fb->GetUploadCommands(); + auto cmdbuffer = fb->GetPreDrawCommands(); PipelineBarrier imageTransition; imageTransition.addImage(mImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, mImageLayout, 0, VK_ACCESS_SHADER_READ_BIT);