2323#include " VulkanShader.h"
2424#include " VulkanCommandRecording.h"
2525#include " VulkanSampler.h"
26+ #include " VulkanBarrier.h"
2627
2728// disable ImGui warnings
2829#pragma warning( push )
@@ -422,7 +423,7 @@ void RenderBackend::renderFrame(const bool presentToScreen) {
422423 auto & swapchainPresentImage = m_images[m_swapchainInputImageHandle.index ];
423424 const auto & transitionToPresentBarrier = createImageBarriers (swapchainPresentImage,
424425 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 0 , 1 );
425- barriersCommand (currentCommandBuffer, transitionToPresentBarrier, std::vector<VkBufferMemoryBarrier> {});
426+ issueBarriersCommand (currentCommandBuffer, transitionToPresentBarrier, std::vector<VkBufferMemoryBarrier> {});
426427
427428 auto res = vkEndCommandBuffer (currentCommandBuffer);
428429 assert (res == VK_SUCCESS);
@@ -702,8 +703,8 @@ struct ImageHandleDecoded {
702703
703704ImageHandleDecoded decodeImageHandle (const ImageHandle handle) {
704705 ImageHandleDecoded decoded;
705- decoded.isTempImage = bool (handle.index >> 31 ); // first bit indicates if image is temp
706- decoded.index = handle.index & 0x7FFFFFFF ; // mask out first bit for index
706+ decoded.isTempImage = bool (handle.index >> 31 ); // first bit indicates if image is temp
707+ decoded.index = handle.index & 0x7FFFFFFF ; // mask out first bit for index
707708 return decoded;
708709}
709710
@@ -733,11 +734,11 @@ std::vector<RenderPassBarriers> RenderBackend::createRenderPassBarriers() {
733734 const RenderPassResources& resources = execution.resources ;
734735 RenderPassBarriers barriers;
735736
736- // storage images
737+ // storage images
737738 for (const ImageResource& storageImage : resources.storageImages ) {
738739 Image& image = getImageRef (storageImage.image );
739740
740- // check if any mip levels need a layout transition
741+ // check if any mip levels need a layout transition
741742 const VkImageLayout requiredLayout = VK_IMAGE_LAYOUT_GENERAL;
742743 bool needsLayoutTransition = false ;
743744 for (const auto & layout : image.layoutPerMip ) {
@@ -746,8 +747,8 @@ std::vector<RenderPassBarriers> RenderBackend::createRenderPassBarriers() {
746747 }
747748 }
748749
749- // check if image already has a barrier
750- // can happen if same image is used as two storage image when accessing different mips
750+ // check if image already has a barrier
751+ // can happen if same image is used as two storage image when accessing different mips
751752 bool hasBarrierAlready = false ;
752753 for (const auto & barrier : barriers.imageBarriers ) {
753754 if (barrier.image == image.vulkanHandle ) {
@@ -764,10 +765,10 @@ std::vector<RenderPassBarriers> RenderBackend::createRenderPassBarriers() {
764765 image.currentlyWriting = true ;
765766 }
766767
767- // sampled images
768+ // sampled images
768769 for (const ImageResource& sampledImage : resources.sampledImages ) {
769770
770- // use general layout if image is used as a storage image too
771+ // use general layout if image is used as a storage image too
771772 bool isUsedAsStorageImage = false ;
772773 {
773774 for (const ImageResource& storageImage : resources.storageImages ) {
@@ -783,7 +784,7 @@ std::vector<RenderPassBarriers> RenderBackend::createRenderPassBarriers() {
783784
784785 Image& image = getImageRef (sampledImage.image );
785786
786- // check if any mip levels need a layout transition
787+ // check if any mip levels need a layout transition
787788 VkImageLayout requiredLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
788789
789790 bool needsLayoutTransition = false ;
@@ -800,14 +801,14 @@ std::vector<RenderPassBarriers> RenderBackend::createRenderPassBarriers() {
800801 }
801802 }
802803
803- // attachments
804+ // attachments
804805 if (executionEntry.type == RenderPassType::Graphic) {
805806 const GraphicPassExecution graphicExecutionInfo = m_graphicPassExecutions[executionEntry.index ];
806807
807808 for (const RenderTarget& target : graphicExecutionInfo.targets ) {
808809 Image& image = getImageRef (target.image );
809810
810- // check if any mip levels need a layout transition
811+ // check if any mip levels need a layout transition
811812 const VkImageLayout requiredLayout = isVulkanDepthFormat (image.format ) ?
812813 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
813814
@@ -830,18 +831,18 @@ std::vector<RenderPassBarriers> RenderBackend::createRenderPassBarriers() {
830831 }
831832 }
832833
833- // storage buffer barriers
834+ // storage buffer barriers
834835 for (const auto & bufferResource : resources.storageBuffers ) {
835- StorageBufferHandle handle = bufferResource.buffer ;
836- Buffer& buffer = m_storageBuffers[handle.index ];
837- const bool needsBarrier = buffer.isBeingWritten ;
838- if (needsBarrier) {
839- VkBufferMemoryBarrier barrier = createBufferBarrier (buffer, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
840- barriers.memoryBarriers .push_back (barrier);
841- }
836+ StorageBufferHandle handle = bufferResource.buffer ;
837+ Buffer& buffer = m_storageBuffers[handle.index ];
838+ const bool needsBarrier = buffer.isBeingWritten ;
839+ if (needsBarrier) {
840+ VkBufferMemoryBarrier barrier = createBufferBarrier (buffer, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
841+ barriers.memoryBarriers .push_back (barrier);
842+ }
842843
843- // update writing state
844- buffer.isBeingWritten = !bufferResource.readOnly ;
844+ // update writing state
845+ buffer.isBeingWritten = !bufferResource.readOnly ;
845846 }
846847 barrierList.push_back (barriers);
847848 }
@@ -881,7 +882,7 @@ void RenderBackend::submitGraphicPass(const GraphicPassExecution& execution,
881882 timeQuery.name = pass.graphicPassDesc .name ;
882883 timeQuery.startQuery = issueTimestampQuery (commandBuffer, m_frameIndexMod2);
883884
884- barriersCommand (commandBuffer, barriers.imageBarriers , barriers.memoryBarriers );
885+ issueBarriersCommand (commandBuffer, barriers.imageBarriers , barriers.memoryBarriers );
885886
886887 const glm::ivec2 resolution = getResolutionFromRenderTargets (execution.targets );
887888 const auto beginInfo = createBeginInfo (resolution.x , resolution.y , pass.vulkanRenderPass ,
@@ -921,7 +922,7 @@ void RenderBackend::submitComputePass(const ComputePassExecution& execution,
921922 timeQuery.name = pass.computePassDesc .name ;
922923 timeQuery.startQuery = issueTimestampQuery (commandBuffer, m_frameIndexMod2);
923924
924- barriersCommand (commandBuffer, barriers.imageBarriers , barriers.memoryBarriers );
925+ issueBarriersCommand (commandBuffer, barriers.imageBarriers , barriers.memoryBarriers );
925926
926927 vkCmdBindPipeline (commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pass.pipeline );
927928
@@ -1477,7 +1478,7 @@ void RenderBackend::manualImageLayoutTransition(Image& image, const VkImageLayou
14771478 const auto transitionCmdBuffer = beginOneTimeUseCommandBuffer ();
14781479 const auto newLayoutBarriers = createImageBarriers (image, newLayout,
14791480 VK_ACCESS_TRANSFER_WRITE_BIT, 0 , (uint32_t )image.viewPerMip .size ());
1480- barriersCommand (transitionCmdBuffer, newLayoutBarriers, std::vector<VkBufferMemoryBarrier> {});
1481+ issueBarriersCommand (transitionCmdBuffer, newLayoutBarriers, std::vector<VkBufferMemoryBarrier> {});
14811482
14821483 auto res = vkEndCommandBuffer (transitionCmdBuffer);
14831484 checkVulkanResult (res);
@@ -1566,7 +1567,7 @@ Buffer RenderBackend::createBufferInternal(const VkDeviceSize size, const std::v
15661567
15671568VkImageSubresourceLayers RenderBackend::createSubresourceLayers (const Image& image, const uint32_t mipLevel) {
15681569 VkImageSubresourceLayers layers;
1569- layers.aspectMask = isVulkanDepthFormat (image.format ) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT ;
1570+ layers.aspectMask = getVkImageAspectFlags (image.format );
15701571 layers.mipLevel = mipLevel;
15711572 layers.baseArrayLayer = 0 ;
15721573 layers.layerCount = 1 ;
@@ -1660,7 +1661,7 @@ void RenderBackend::transferDataIntoImage(Image& target, const void* data, const
16601661 const auto toTransferDstBarrier = createImageBarriers (target, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
16611662 VK_ACCESS_TRANSFER_READ_BIT, 0 , (uint32_t )target.viewPerMip .size ());
16621663
1663- barriersCommand (copyBuffer, toTransferDstBarrier, std::vector<VkBufferMemoryBarrier> {});
1664+ issueBarriersCommand (copyBuffer, toTransferDstBarrier, std::vector<VkBufferMemoryBarrier> {});
16641665 }
16651666
16661667
@@ -1745,7 +1746,7 @@ void RenderBackend::generateMipChain(Image& image, const VkImageLayout newLayout
17451746 const auto dstBarriers = createImageBarriers (image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, srcMip + 1 , 1 ); // dst
17461747 barriers.insert (barriers.end (), dstBarriers.begin (), dstBarriers.end ());
17471748
1748- barriersCommand (blitCmdBuffer, barriers, std::vector<VkBufferMemoryBarrier> {});
1749+ issueBarriersCommand (blitCmdBuffer, barriers, std::vector<VkBufferMemoryBarrier> {});
17491750
17501751 // blit operation
17511752 blitInfo.srcSubresource = createSubresourceLayers (image, srcMip );
@@ -1766,7 +1767,7 @@ void RenderBackend::generateMipChain(Image& image, const VkImageLayout newLayout
17661767
17671768 // bring image into new layout
17681769 const auto newLayoutBarriers = createImageBarriers (image, newLayout, VK_ACCESS_TRANSFER_WRITE_BIT, 0 , (uint32_t )image.viewPerMip .size ());
1769- barriersCommand (blitCmdBuffer, newLayoutBarriers, std::vector<VkBufferMemoryBarrier> {});
1770+ issueBarriersCommand (blitCmdBuffer, newLayoutBarriers, std::vector<VkBufferMemoryBarrier> {});
17701771
17711772 // end recording
17721773 auto res = vkEndCommandBuffer (blitCmdBuffer);
@@ -2398,76 +2399,27 @@ bool validateAttachmentFormatsAreCompatible(const ImageFormat a, const ImageForm
23982399 return imageFormatToVkAspectFlagBits (a) == imageFormatToVkAspectFlagBits (b);
23992400}
24002401
2401- void RenderBackend::barriersCommand (const VkCommandBuffer commandBuffer,
2402- const std::vector<VkImageMemoryBarrier>& imageBarriers, const std::vector<VkBufferMemoryBarrier>& memoryBarriers) {
2403-
2404- vkCmdPipelineBarrier (commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0 , 0 , nullptr ,
2405- (uint32_t )memoryBarriers.size (), memoryBarriers.data (), (uint32_t )imageBarriers.size (), imageBarriers.data ());
2406- }
2407-
24082402std::vector<VkImageMemoryBarrier> RenderBackend::createImageBarriers (Image& image, const VkImageLayout newLayout,
24092403 const VkAccessFlags dstAccess, const uint32_t baseMip, const uint32_t mipLevels) {
24102404
2411- VkImageAspectFlags aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;
2412- const bool isDepthImage = isVulkanDepthFormat (image.format );
2413- if (isDepthImage) {
2414- aspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT;
2415- }
2416-
24172405 std::vector<VkImageMemoryBarrier> barriers;
2418-
2419- const uint32_t layerCount = computeImageLayerCount (image.desc .type );
2420-
2421- // first barrier
2422- VkImageMemoryBarrier firstBarrier;
2423- firstBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
2424- firstBarrier.pNext = nullptr ;
2425- firstBarrier.srcAccessMask = image.currentAccess ;
2426- firstBarrier.dstAccessMask = dstAccess;
2427- firstBarrier.oldLayout = image.layoutPerMip [baseMip];
2428- firstBarrier.newLayout = newLayout;
2429- firstBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
2430- firstBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
2431- firstBarrier.image = image.vulkanHandle ;
2432- firstBarrier.subresourceRange .aspectMask = aspectFlags;
2433- firstBarrier.subresourceRange .baseMipLevel = baseMip;
2434- firstBarrier.subresourceRange .levelCount = 1 ;
2435- firstBarrier.subresourceRange .baseArrayLayer = 0 ;
2436- firstBarrier.subresourceRange .layerCount = layerCount;
2406+ const VkImageMemoryBarrier firstBarrier = createImageBarrier (image, dstAccess, newLayout, baseMip);
24372407 barriers.push_back (firstBarrier);
24382408
24392409 // add subsequent mip level barriers
2440- for (uint32_t i = 1 ; i < mipLevels; i ++) {
2410+ for (uint32_t mipOffset = 1 ; mipOffset < mipLevels; mipOffset ++) {
24412411
2442- // same mip layout: extens subresource range
2443- uint32_t mipLevel = baseMip + i ;
2444- if (image. layoutPerMip [mipLevel] == barriers. back (). oldLayout ) {
2412+ uint32_t mipLevel = baseMip + mipOffset;
2413+ const bool canExtendLastBarrier = image. layoutPerMip [mipLevel] == barriers. back (). oldLayout ;
2414+ if (canExtendLastBarrier ) {
24452415 barriers.back ().subresourceRange .levelCount ++;
24462416 }
2447-
2448- // different mip layout: new barrier
24492417 else {
2450- VkImageMemoryBarrier barrier;
2451- barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
2452- barrier.pNext = nullptr ;
2453- barrier.srcAccessMask = image.currentAccess ;
2454- barrier.dstAccessMask = dstAccess;
2455- barrier.oldLayout = image.layoutPerMip [mipLevel];
2456- barrier.newLayout = newLayout;
2457- barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
2458- barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
2459- barrier.image = image.vulkanHandle ;
2460- barrier.subresourceRange .aspectMask = aspectFlags;
2461- barrier.subresourceRange .baseMipLevel = mipLevel;
2462- barrier.subresourceRange .levelCount = 1 ;
2463- barrier.subresourceRange .baseArrayLayer = 0 ;
2464- barrier.subresourceRange .layerCount = layerCount;
2465-
2418+ const VkImageMemoryBarrier barrier = createImageBarrier (image, dstAccess, newLayout, mipLevel);
24662419 barriers.push_back (barrier);
24672420 }
24682421 }
24692422
2470- // update image properties
24712423 for (uint32_t i = baseMip; i < baseMip + mipLevels; i++) {
24722424 image.layoutPerMip [i] = newLayout;
24732425 }
@@ -2477,20 +2429,6 @@ std::vector<VkImageMemoryBarrier> RenderBackend::createImageBarriers(Image& imag
24772429 return barriers;
24782430}
24792431
2480- VkBufferMemoryBarrier RenderBackend::createBufferBarrier (const Buffer& buffer, const VkAccessFlagBits srcAccess, const VkAccessFlagBits dstAccess) {
2481- VkBufferMemoryBarrier barrier;
2482- barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
2483- barrier.pNext = nullptr ;
2484- barrier.srcAccessMask = srcAccess;
2485- barrier.srcAccessMask = dstAccess;
2486- barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
2487- barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
2488- barrier.buffer = buffer.vulkanHandle ;
2489- barrier.offset = 0 ;
2490- barrier.size = buffer.size ;
2491- return barrier;
2492- }
2493-
24942432VkQueryPool RenderBackend::createQueryPool (const VkQueryType queryType, const uint32_t queryCount) {
24952433
24962434 VkQueryPoolCreateInfo createInfo;
0 commit comments