diff --git a/filament/backend/src/vulkan/VulkanBlitter.cpp b/filament/backend/src/vulkan/VulkanBlitter.cpp index a273445c64..384309c0dd 100644 --- a/filament/backend/src/vulkan/VulkanBlitter.cpp +++ b/filament/backend/src/vulkan/VulkanBlitter.cpp @@ -32,11 +32,101 @@ using namespace utils; namespace filament::backend { +namespace { + +inline void blitFast(const VkCommandBuffer cmdbuffer, VkImageAspectFlags aspect, VkFilter filter, + const VkExtent2D srcExtent, VulkanAttachment src, VulkanAttachment dst, + const VkOffset3D srcRect[2], const VkOffset3D dstRect[2]) { + const VkImageBlit blitRegions[1] = {{.srcSubresource = {aspect, src.level, src.layer, 1}, + .srcOffsets = {srcRect[0], srcRect[1]}, + .dstSubresource = {aspect, dst.level, dst.layer, 1}, + .dstOffsets = {dstRect[0], dstRect[1]}}}; + + const VkImageResolve resolveRegions[1] = {{.srcSubresource = {aspect, src.level, src.layer, 1}, + .srcOffset = srcRect[0], + .dstSubresource = {aspect, dst.level, dst.layer, 1}, + .dstOffset = dstRect[0], + .extent = {srcExtent.width, srcExtent.height, 1}}}; + + const VkImageSubresourceRange srcRange = { + .aspectMask = aspect, + .baseMipLevel = src.level, + .levelCount = 1, + .baseArrayLayer = src.layer, + .layerCount = 1, + }; + + const VkImageSubresourceRange dstRange = { + .aspectMask = aspect, + .baseMipLevel = dst.level, + .levelCount = 1, + .baseArrayLayer = dst.layer, + .layerCount = 1, + }; + const VkImageLayout srcLayout = getDefaultImageLayout(src.texture->usage); + transitionImageLayout(cmdbuffer, { + src.getImage(), + srcLayout, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + srcRange, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + 0, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_READ_BIT, + }); + + transitionImageLayout(cmdbuffer, { + dst.getImage(), + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + dstRange, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + 0, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + }); + + if (src.texture->samples > 1 && dst.texture->samples == 1) { + assert_invariant( + aspect != VK_IMAGE_ASPECT_DEPTH_BIT && "Resolve with depth is not yet supported."); + vkCmdResolveImage(cmdbuffer, src.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + dst.getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, resolveRegions); + } else { + vkCmdBlitImage(cmdbuffer, src.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + dst.getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, blitRegions, filter); + } + + VkImageLayout newSrcLayout = getDefaultImageLayout(src.texture->usage); + VkImageLayout const newDestLayout = getDefaultImageLayout(dst.texture->usage); + + // In the case of blitting the depth attachment, we transition the source into GENERAL (for + // sampling) and set the copy as ATTACHMENT_OPTIMAL (to be set as the attachment). + if (any(src.texture->usage & TextureUsage::DEPTH_ATTACHMENT)) { + newSrcLayout = VK_IMAGE_LAYOUT_GENERAL; + } + + transitionImageLayout(cmdbuffer, textureTransitionHelper({ + .image = src.getImage(), + .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + .newLayout = newSrcLayout, + .subresources = srcRange, + })); + + transitionImageLayout(cmdbuffer, textureTransitionHelper({ + .image = dst.getImage(), + .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .newLayout = newDestLayout, + .subresources = dstRange, + })); +} + struct BlitterUniforms { int sampleCount; float inverseSampleCount; }; +}// anonymous namespace + void VulkanBlitter::blitColor(BlitArgs args) { const VulkanAttachment src = args.srcTarget->getColor(args.targetIndex); const VulkanAttachment dst = args.dstTarget->getColor(0); @@ -56,8 +146,8 @@ void VulkanBlitter::blitColor(BlitArgs args) { return; } #endif - - blitFast(aspect, args.filter, args.srcTarget->getExtent(), src, dst, + VkCommandBuffer const cmdbuffer = mContext.commands->get().cmdbuffer; + blitFast(cmdbuffer, aspect, args.filter, args.srcTarget->getExtent(), src, dst, args.srcRectPair, args.dstRectPair); } @@ -88,90 +178,11 @@ void VulkanBlitter::blitDepth(BlitArgs args) { args.dstRectPair); return; } - - blitFast(aspect, args.filter, args.srcTarget->getExtent(), src, dst, args.srcRectPair, + VkCommandBuffer const cmdbuffer = mContext.commands->get().cmdbuffer; + blitFast(cmdbuffer, aspect, args.filter, args.srcTarget->getExtent(), src, dst, args.srcRectPair, args.dstRectPair); } -void VulkanBlitter::blitFast(VkImageAspectFlags aspect, VkFilter filter, - const VkExtent2D srcExtent, VulkanAttachment src, VulkanAttachment dst, - const VkOffset3D srcRect[2], const VkOffset3D dstRect[2]) { - const VkImageBlit blitRegions[1] = {{ - .srcSubresource = { aspect, src.level, src.layer, 1 }, - .srcOffsets = { srcRect[0], srcRect[1] }, - .dstSubresource = { aspect, dst.level, dst.layer, 1 }, - .dstOffsets = { dstRect[0], dstRect[1] } - }}; - - const VkImageResolve resolveRegions[1] = {{ - .srcSubresource = { aspect, src.level, src.layer, 1 }, - .srcOffset = srcRect[0], - .dstSubresource = { aspect, dst.level, dst.layer, 1 }, - .dstOffset = dstRect[0], - .extent = { srcExtent.width, srcExtent.height, 1 } - }}; - - const VkImageSubresourceRange srcRange = { - .aspectMask = aspect, - .baseMipLevel = src.level, - .levelCount = 1, - .baseArrayLayer = src.layer, - .layerCount = 1, - }; - - const VkImageSubresourceRange dstRange = { - .aspectMask = aspect, - .baseMipLevel = dst.level, - .levelCount = 1, - .baseArrayLayer = dst.layer, - .layerCount = 1, - }; - - const VkCommandBuffer cmdbuffer = mContext.commands->get().cmdbuffer; - - const VkImageLayout srcLayout = getDefaultImageLayout(src.texture->usage); - - transitionImageLayout(cmdbuffer, { - src.getImage(), - srcLayout, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - srcRange, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_READ_BIT - }); - - transitionImageLayout(cmdbuffer, { - dst.getImage(), - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - dstRange, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, - }); - - if (src.texture->samples > 1 && dst.texture->samples == 1) { - assert_invariant(aspect != VK_IMAGE_ASPECT_DEPTH_BIT && "Resolve with depth is not yet supported."); - vkCmdResolveImage(cmdbuffer, src.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst.getImage(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, resolveRegions); - } else { - vkCmdBlitImage(cmdbuffer, src.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst.getImage(), - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, blitRegions, filter); - } - - transitionImageLayout(cmdbuffer, blitterTransitionHelper({ - .image = src.getImage(), - .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - .newLayout = srcLayout, - .subresources = srcRange - })); - - transitionImageLayout(cmdbuffer, blitterTransitionHelper({ - .image = dst.getImage(), - .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - .newLayout = getDefaultImageLayout(dst.texture->usage), - .subresources = dstRange, - })); -} void VulkanBlitter::shutdown() noexcept { if (mContext.device) { diff --git a/filament/backend/src/vulkan/VulkanBlitter.h b/filament/backend/src/vulkan/VulkanBlitter.h index f95b53bb36..75e0439d6f 100644 --- a/filament/backend/src/vulkan/VulkanBlitter.h +++ b/filament/backend/src/vulkan/VulkanBlitter.h @@ -53,10 +53,6 @@ public: private: void lazyInit() noexcept; - void blitFast(VkImageAspectFlags aspect, VkFilter filter, const VkExtent2D srcExtent, - VulkanAttachment src, VulkanAttachment dst, const VkOffset3D srcRect[2], - const VkOffset3D dstRect[2]); - void blitSlowDepth(VkImageAspectFlags aspect, VkFilter filter, const VkExtent2D srcExtent, VulkanAttachment src, VulkanAttachment dst, const VkOffset3D srcRect[2], const VkOffset3D dstRect[2]); diff --git a/filament/backend/src/vulkan/VulkanDriver.cpp b/filament/backend/src/vulkan/VulkanDriver.cpp index 76af3124e5..756695eb59 100644 --- a/filament/backend/src/vulkan/VulkanDriver.cpp +++ b/filament/backend/src/vulkan/VulkanDriver.cpp @@ -652,7 +652,26 @@ bool VulkanDriver::isWorkaroundNeeded(Workaround workaround) { // early exit condition is flattened in EASU code return deviceProperties.vendorID == 0x5143; // Qualcomm case Workaround::ALLOW_READ_ONLY_ANCILLARY_FEEDBACK_LOOP: - return true; + // Supporting depth attachment as both sampler and attachment is only possible if we set + // the depth attachment as read-only (e.g. during SSAO pass), however note that the + // store-ops for attachments wrt VkRenderPass only has VK_ATTACHMENT_STORE_OP_DONT_CARE + // and VK_ATTACHMENT_STORE_OP_STORE for versions below 1.3. Only at 1.3 and above do we + // have a true read-only choice VK_ATTACHMENT_STORE_OP_NONE. That means for < 1.3, we + // will trigger a validation sync error if we use the depth attachment also as a + // sampler. See full error below: + // + // SYNC-HAZARD-WRITE-AFTER-READ(ERROR / SPEC): msgNum: 929810911 - Validation Error: + // [ SYNC-HAZARD-WRITE-AFTER-READ ] Object 0: handle = 0x6160000c3680, + // type = VK_OBJECT_TYPE_RENDER_PASS; | MessageID = 0x376bc9df | vkCmdEndRenderPass: + // Hazard WRITE_AFTER_READ in subpass 0 for attachment 1 depth aspect during store with + // storeOp VK_ATTACHMENT_STORE_OP_STORE. Access info (usage: + // SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE, prior_usage: + // SYNC_FRAGMENT_SHADER_SHADER_STORAGE_READ, read_barriers: VK_PIPELINE_STAGE_2_NONE, + // command: vkCmdDrawIndexed, seq_no: 177, reset_no: 1) + // + // Therefore we apply the existing workaround of an extra blit until a better + // resolution. + return false; case Workaround::ADRENO_UNIFORM_ARRAY_CRASH: return false; } @@ -871,39 +890,27 @@ void VulkanDriver::beginRenderPass(Handle rth, const RenderPassP VulkanAttachment depth = rt->getSamples() == 1 ? rt->getDepth() : rt->getMsaaDepth(); VulkanDepthLayout initialDepthLayout = fromVkImageLayout(depth.getLayout()); - VulkanDepthLayout renderPassDepthLayout = - fromVkImageLayout(getDefaultImageLayout(TextureUsage::DEPTH_ATTACHMENT)); - VulkanDepthLayout finalDepthLayout = renderPassDepthLayout; - - // Sometimes we need to permit the shader to sample the depth attachment by transitioning the - // layout of all its subresources to a read-only layout. This is especially crucial for SSAO. - // - // We cannot perform this transition using the render pass because the shaders in this render - // pass might sample from multiple miplevels. - // - // We do not use GENERAL here due to the following validation message: - // - // The Vulkan spec states: Image subresources used as attachments in the current render pass - // must not be accessed in any way other than as an attachment by this command, except for - // cases involving read-only access to depth/stencil attachments as described in the Render - // Pass chapter. - // - // https://vulkan.lunarg.com/doc/view/1.2.182.0/mac/1.2-extensions/vkspec.html#VUID-vkCmdDrawIndexed-None-04584) - // - if (params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH) { - VkImageSubresourceRange range = { - .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT, - .baseMipLevel = 0, - .levelCount = depth.texture->levels, - .baseArrayLayer = 0, - .layerCount = depth.texture->depth, - }; - depth.texture->transitionLayout(cmdbuffer, range, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL); - initialDepthLayout = renderPassDepthLayout = finalDepthLayout = VulkanDepthLayout::READ_ONLY; - } + VulkanDepthLayout renderPassDepthLayout = VulkanDepthLayout::ATTACHMENT; + VulkanDepthLayout finalDepthLayout = VulkanDepthLayout::ATTACHMENT; + TargetBufferFlags clearVal = params.flags.clear; + TargetBufferFlags discardEndVal = params.flags.discardEnd; if (depth.texture) { - depth.texture->trackLayout(depth.level, depth.layer, toVkImageLayout(renderPassDepthLayout)); + if (params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH) { + discardEndVal &= ~TargetBufferFlags::DEPTH; + clearVal &= ~TargetBufferFlags::DEPTH; + } + if (initialDepthLayout != VulkanDepthLayout::ATTACHMENT) { + VkImageSubresourceRange subresources{ + .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT, + .baseMipLevel = 0, + .levelCount = depth.texture->levels, + .baseArrayLayer = 0, + .layerCount = depth.texture->depth, + }; + depth.texture->transitionLayout(cmdbuffer, subresources, + toVkImageLayout(renderPassDepthLayout)); + } } // Create the VkRenderPass or fetch it from cache. @@ -913,9 +920,9 @@ void VulkanDriver::beginRenderPass(Handle rth, const RenderPassP .renderPassDepthLayout = renderPassDepthLayout, .finalDepthLayout = finalDepthLayout, .depthFormat = depth.getFormat(), - .clear = params.flags.clear, + .clear = clearVal, .discardStart = discardStart, - .discardEnd = params.flags.discardEnd, + .discardEnd = discardEndVal, .samples = rt->getSamples(), .subpassMask = uint8_t(params.subpassMask), }; @@ -1070,21 +1077,6 @@ void VulkanDriver::endRenderPass(int) { VulkanRenderTarget* rt = mContext.currentRenderPass.renderTarget; assert_invariant(rt); - // In some cases, depth needs to be transitioned from DEPTH_STENCIL_READ_ONLY_OPTIMAL back to - // GENERAL. We did not do this using the render pass because we need to change multiple mips. - if (mContext.currentRenderPass.params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH) { - const VulkanAttachment& depth = rt->getDepth(); - VkImageSubresourceRange range = { - .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT, - .baseMipLevel = 0, - .levelCount = depth.texture->levels, - .baseArrayLayer = 0, - .layerCount = depth.texture->depth, - }; - depth.texture->transitionLayout(cmdbuffer, range, - getDefaultImageLayout(TextureUsage::DEPTH_ATTACHMENT)); - } - // Since we might soon be sampling from the render target that we just wrote to, we need a // pipeline barrier between framebuffer writes and shader reads. This is a memory barrier rather // than an image barrier. If we were to use image barriers here, we would potentially need to diff --git a/filament/backend/src/vulkan/VulkanFboCache.h b/filament/backend/src/vulkan/VulkanFboCache.h index b8904bddb1..40034e5000 100644 --- a/filament/backend/src/vulkan/VulkanFboCache.h +++ b/filament/backend/src/vulkan/VulkanFboCache.h @@ -30,8 +30,7 @@ namespace filament::backend { // Avoid using VkImageLayout since it requires 4 bytes. enum class VulkanDepthLayout : uint8_t { UNDEFINED, // VK_IMAGE_LAYOUT_UNDEFINED - GENERAL, // VK_IMAGE_LAYOUT_GENERAL - READ_ONLY, // VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL. + ATTACHMENT, // VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL }; // Simple manager for VkFramebuffer and VkRenderPass objects. @@ -134,17 +133,19 @@ private: inline VulkanDepthLayout fromVkImageLayout(VkImageLayout layout) { switch (layout) { - case VK_IMAGE_LAYOUT_GENERAL: return VulkanDepthLayout::GENERAL; - case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: return VulkanDepthLayout::READ_ONLY; - default: return VulkanDepthLayout::UNDEFINED; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + return VulkanDepthLayout::ATTACHMENT; + default: + return VulkanDepthLayout::UNDEFINED; } } inline VkImageLayout toVkImageLayout(VulkanDepthLayout layout) { switch (layout) { - case VulkanDepthLayout::GENERAL: return VK_IMAGE_LAYOUT_GENERAL; - case VulkanDepthLayout::READ_ONLY: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; - default: return VK_IMAGE_LAYOUT_UNDEFINED; + case VulkanDepthLayout::ATTACHMENT: + return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + default: + return VK_IMAGE_LAYOUT_UNDEFINED; } } diff --git a/filament/backend/src/vulkan/VulkanStagePool.cpp b/filament/backend/src/vulkan/VulkanStagePool.cpp index cb4f8b641d..5ef35b1c89 100644 --- a/filament/backend/src/vulkan/VulkanStagePool.cpp +++ b/filament/backend/src/vulkan/VulkanStagePool.cpp @@ -116,7 +116,7 @@ VulkanStageImage const* VulkanStagePool::acquireImage(PixelDataFormat format, Pi // VK_IMAGE_LAYOUT_PREINITIALIZED or VK_IMAGE_LAYOUT_GENERAL layout. Calling // vkGetImageSubresourceLayout for a linear image returns a subresource layout mapping that is // valid for either of those image layouts." - transitionImageLayout(cmdbuffer, blitterTransitionHelper({ + transitionImageLayout(cmdbuffer, textureTransitionHelper({ .image = image->image, .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, .newLayout = VK_IMAGE_LAYOUT_GENERAL, diff --git a/filament/backend/src/vulkan/VulkanUtility.cpp b/filament/backend/src/vulkan/VulkanUtility.cpp index 02ba0f0e6c..1fdc678e09 100644 --- a/filament/backend/src/vulkan/VulkanUtility.cpp +++ b/filament/backend/src/vulkan/VulkanUtility.cpp @@ -632,11 +632,8 @@ VkImageViewType getImageViewType(SamplerType target) { // exceptions for depth and for transient use of specialized layouts, which is why VulkanTexture // tracks actual layout at the subresource level. VkImageLayout getDefaultImageLayout(TextureUsage usage) { - // Filament sometimes samples from depth while it is bound to the current render target, (e.g. - // SSAO does this while depth writes are disabled) so let's keep it simple and use GENERAL for - // all depth textures. if (any(usage & TextureUsage::DEPTH_ATTACHMENT)) { - return VK_IMAGE_LAYOUT_GENERAL; + return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; } // Filament sometimes samples from one miplevel while writing to another level in the same @@ -676,29 +673,8 @@ void transitionImageLayout(VkCommandBuffer cmdbuffer, VulkanLayoutTransition tra nullptr, 1, &barrier); } -VulkanLayoutTransition blitterTransitionHelper(VulkanLayoutTransition transition) { - switch (transition.newLayout) { - case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: - case VK_IMAGE_LAYOUT_GENERAL: - transition.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - transition.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - transition.srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - transition.dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - break; - - case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: - default: - transition.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - transition.dstAccessMask = 0; - transition.srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - transition.dstStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - break; - } - return transition; -} - VulkanLayoutTransition textureTransitionHelper(VulkanLayoutTransition transition) { + const bool isTransferSrc = transition.oldLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; switch (transition.newLayout) { case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: transition.srcAccessMask = 0; @@ -714,13 +690,20 @@ VulkanLayoutTransition textureTransitionHelper(VulkanLayoutTransition transition break; case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: case VK_IMAGE_LAYOUT_GENERAL: - case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: - transition.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + transition.srcAccessMask + = isTransferSrc ? VK_ACCESS_TRANSFER_READ_BIT : VK_ACCESS_TRANSFER_WRITE_BIT; transition.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; transition.srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; transition.dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break; - + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + transition.srcAccessMask + = isTransferSrc ? VK_ACCESS_TRANSFER_READ_BIT : VK_ACCESS_TRANSFER_WRITE_BIT; + transition.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT + | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + transition.srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; + transition.dstStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + break; // We support PRESENT as a target layout to allow blitting from the swap chain. // See also SwapChain::makePresentable(). case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: @@ -765,7 +748,6 @@ bool isDepthFormat(VkFormat format) { static uint32_t mostSignificantBit(uint32_t x) { return 1ul << (31ul - utils::clz(x)); } uint8_t reduceSampleCount(uint8_t sampleCount, VkSampleCountFlags mask) { - assert_invariant(utils::popcount(sampleCount) == 1); if (sampleCount & mask) { return sampleCount; } diff --git a/filament/backend/src/vulkan/VulkanUtility.h b/filament/backend/src/vulkan/VulkanUtility.h index 9caa9d256b..44f9a454c8 100644 --- a/filament/backend/src/vulkan/VulkanUtility.h +++ b/filament/backend/src/vulkan/VulkanUtility.h @@ -56,11 +56,6 @@ VkShaderStageFlags getShaderStageFlags(ShaderStageFlags stageFlags); void transitionImageLayout(VkCommandBuffer cmdbuffer, VulkanLayoutTransition transition); // Helper function for populating barrier fields based on the desired image layout. -// This logic is specific to blitting. -VulkanLayoutTransition blitterTransitionHelper(VulkanLayoutTransition transition); - -// Helper function for populating barrier fields based on the desired image layout. -// This logic is specific to texturing. VulkanLayoutTransition textureTransitionHelper(VulkanLayoutTransition transition); bool equivalent(const VkRect2D& a, const VkRect2D& b);