diff --git a/filament/backend/src/vulkan/VulkanBlitter.cpp b/filament/backend/src/vulkan/VulkanBlitter.cpp index f7268f0d19..93351c59a3 100644 --- a/filament/backend/src/vulkan/VulkanBlitter.cpp +++ b/filament/backend/src/vulkan/VulkanBlitter.cpp @@ -39,8 +39,8 @@ struct BlitterUniforms { }; void VulkanBlitter::blitColor(BlitArgs args) { - const VulkanAttachment src = args.srcTarget->getColor(mContext.currentSurface, args.targetIndex); - const VulkanAttachment dst = args.dstTarget->getColor(mContext.currentSurface, 0); + const VulkanAttachment src = args.srcTarget->getColor(args.targetIndex); + const VulkanAttachment dst = args.dstTarget->getColor(0); const VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT; #if FILAMENT_VULKAN_CHECK_BLIT_FORMAT @@ -58,14 +58,13 @@ void VulkanBlitter::blitColor(BlitArgs args) { } #endif - blitFast(aspect, args.filter, args.srcTarget->getExtent(mContext.currentSurface), src, dst, + blitFast(aspect, args.filter, args.srcTarget->getExtent(), src, dst, args.srcRectPair, args.dstRectPair); } void VulkanBlitter::blitDepth(BlitArgs args) { - VulkanSwapChain* const sc = mContext.currentSurface; - const VulkanAttachment src = args.srcTarget->getDepth(sc); - const VulkanAttachment dst = args.dstTarget->getDepth(sc); + const VulkanAttachment src = args.srcTarget->getDepth(); + const VulkanAttachment dst = args.dstTarget->getDepth(); const VkImageAspectFlags aspect = VK_IMAGE_ASPECT_DEPTH_BIT; #if FILAMENT_VULKAN_CHECK_BLIT_FORMAT @@ -86,12 +85,12 @@ void VulkanBlitter::blitDepth(BlitArgs args) { assert_invariant(src.texture && dst.texture); if (src.texture->samples > 1 && dst.texture->samples == 1) { - blitSlowDepth(aspect, args.filter, args.srcTarget->getExtent(sc), src, dst, args.srcRectPair, + blitSlowDepth(aspect, args.filter, args.srcTarget->getExtent(), src, dst, args.srcRectPair, args.dstRectPair); return; } - blitFast(aspect, args.filter, args.srcTarget->getExtent(sc), src, dst, args.srcRectPair, + blitFast(aspect, args.filter, args.srcTarget->getExtent(), src, dst, args.srcRectPair, args.dstRectPair); } diff --git a/filament/backend/src/vulkan/VulkanContext.h b/filament/backend/src/vulkan/VulkanContext.h index 73030d326b..84721a95c0 100644 --- a/filament/backend/src/vulkan/VulkanContext.h +++ b/filament/backend/src/vulkan/VulkanContext.h @@ -46,7 +46,7 @@ struct VulkanAttachment { VkImageView view; VkDeviceMemory memory; VulkanTexture* texture = nullptr; - VkImageLayout layout; + VkImageLayout layout; // TODO remove uint8_t level; uint16_t layer; }; @@ -90,6 +90,7 @@ struct VulkanContext { bool maintenanceSupported[3] = {}; VulkanPipelineCache::RasterState rasterState; VulkanSwapChain* currentSurface; + Handle defaultRenderTarget; VulkanRenderPass currentRenderPass; VkViewport viewport; VkFormat finalDepthFormat; diff --git a/filament/backend/src/vulkan/VulkanDriver.cpp b/filament/backend/src/vulkan/VulkanDriver.cpp index 6126d19957..d2df7f08b0 100644 --- a/filament/backend/src/vulkan/VulkanDriver.cpp +++ b/filament/backend/src/vulkan/VulkanDriver.cpp @@ -322,6 +322,8 @@ void VulkanDriver::terminate() { delete mContext.commands; delete mContext.emptyTexture; + destruct(mContext.defaultRenderTarget); + mBlitter.shutdown(); // Allow the stage pool and disposer to clean up. @@ -519,10 +521,9 @@ void VulkanDriver::destroyProgram(Handle ph) { } void VulkanDriver::createDefaultRenderTargetR(Handle rth, int) { - auto renderTarget = construct(rth, mContext); - mDisposer.createDisposable(renderTarget, [this, rth] () { - destruct(rth); - }); + assert_invariant(!mContext.defaultRenderTarget); + mContext.defaultRenderTarget = rth; + construct(rth, mContext); } void VulkanDriver::createRenderTargetR(Handle rth, @@ -557,7 +558,10 @@ void VulkanDriver::createRenderTargetR(Handle rth, void VulkanDriver::destroyRenderTarget(Handle rth) { if (rth) { - mDisposer.removeReference(handle_cast(rth)); + if (UTILS_LIKELY(mContext.defaultRenderTarget != rth)) { + VulkanRenderTarget* rt = handle_cast(rth); + mDisposer.removeReference(rt); + } } } @@ -983,9 +987,8 @@ void VulkanDriver::updateSamplerGroup(Handle sbh, void VulkanDriver::beginRenderPass(Handle rth, const RenderPassParams& params) { mCurrentRenderTarget = handle_cast(rth); VulkanRenderTarget* const rt = mCurrentRenderTarget; - VulkanSwapChain* const sc = mContext.currentSurface; - const VkExtent2D extent = rt->getExtent(sc); + const VkExtent2D extent = rt->getExtent(); assert_invariant(extent.width > 0 && extent.height > 0); // Filament has the expectation that the contents of the swap chain are not preserved on the @@ -993,16 +996,16 @@ void VulkanDriver::beginRenderPass(Handle rth, const RenderPassP // passes, due to multiple views. TargetBufferFlags discardStart = params.flags.discardStart; if (rt->isSwapChain()) { + VulkanSwapChain* const sc = mContext.currentSurface; assert_invariant(sc); - VulkanSwapChain& surface = *sc; - if (surface.firstRenderPass) { + if (sc->firstRenderPass) { discardStart |= TargetBufferFlags::COLOR; - surface.firstRenderPass = false; + sc->firstRenderPass = false; } } const VkCommandBuffer cmdbuffer = mContext.commands->get().cmdbuffer; - VulkanAttachment depth = rt->getSamples() == 1 ? rt->getDepth(sc) : rt->getMsaaDepth(); + VulkanAttachment depth = rt->getSamples() == 1 ? rt->getDepth() : rt->getMsaaDepth(); VulkanTexture* depthFeedback = nullptr; VulkanDepthLayout initialDepthLayout = fromVkImageLayout(depth.layout); @@ -1047,7 +1050,7 @@ void VulkanDriver::beginRenderPass(Handle rth, const RenderPassP .subpassMask = uint8_t(params.subpassMask), }; for (int i = 0; i < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; i++) { - const VulkanAttachment& info = rt->getColor(sc, i); + const VulkanAttachment& info = rt->getColor(i); if (info.layout != VK_IMAGE_LAYOUT_UNDEFINED) { rpkey.initialColorLayoutMask |= 1 << i; } @@ -1073,18 +1076,18 @@ void VulkanDriver::beginRenderPass(Handle rth, const RenderPassP .samples = rpkey.samples, }; for (int i = 0; i < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; i++) { - if (rt->getColor(sc, i).format == VK_FORMAT_UNDEFINED) { + if (rt->getColor(i).format == VK_FORMAT_UNDEFINED) { fbkey.color[i] = VK_NULL_HANDLE; fbkey.resolve[i] = VK_NULL_HANDLE; } else if (fbkey.samples == 1) { - fbkey.color[i] = rt->getColor(sc, i).view; + fbkey.color[i] = rt->getColor(i).view; fbkey.resolve[i] = VK_NULL_HANDLE; assert_invariant(fbkey.color[i]); } else { fbkey.color[i] = rt->getMsaaColor(i).view; - VulkanTexture* texture = rt->getColor(sc, i).texture; + VulkanTexture* texture = rt->getColor(i).texture; if (texture && texture->samples == 1) { - fbkey.resolve[i] = rt->getColor(sc, i).view; + fbkey.resolve[i] = rt->getColor(i).view; assert_invariant(fbkey.resolve[i]); } assert_invariant(fbkey.color[i]); @@ -1112,7 +1115,7 @@ void VulkanDriver::beginRenderPass(Handle rth, const RenderPassP mDisposer.acquire(rt); mDisposer.acquire(depth.texture); for (int i = 0; i < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; i++) { - mDisposer.acquire(rt->getColor(sc, i).texture); + mDisposer.acquire(rt->getColor(i).texture); } // Populate the structures required for vkCmdBeginRenderPass. @@ -1126,7 +1129,7 @@ void VulkanDriver::beginRenderPass(Handle rth, const RenderPassP .renderArea = { .offset = {}, .extent = extent } }; - rt->transformClientRectToPlatform(sc, &renderPassInfo.renderArea); + rt->transformClientRectToPlatform(&renderPassInfo.renderArea); VkClearValue clearValues[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT + MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT + 1] = {}; @@ -1165,7 +1168,7 @@ void VulkanDriver::beginRenderPass(Handle rth, const RenderPassP .maxDepth = params.depthRange.far }; - mCurrentRenderTarget->transformClientRectToPlatform(sc, &viewport); + mCurrentRenderTarget->transformClientRectToPlatform(&viewport); vkCmdSetViewport(cmdbuffer, 0, 1, &viewport); mContext.currentRenderPass = { @@ -1188,10 +1191,7 @@ void VulkanDriver::endRenderPass(int) { // and notify the texture wrapper for proper tracking. VulkanTexture* depthFeedbackTexture = mContext.currentRenderPass.depthFeedback; if (depthFeedbackTexture) { - - VulkanSwapChain* const sc = mContext.currentSurface; - const VulkanAttachment& depth = mCurrentRenderTarget->getDepth(sc); - + const VulkanAttachment& depth = mCurrentRenderTarget->getDepth(); depthFeedbackTexture->trackLayout(depth.level, depth.layer, getDefaultImageLayout(TextureUsage::DEPTH_ATTACHMENT)); } @@ -1251,7 +1251,7 @@ void VulkanDriver::nextSubpass(int) { for (uint32_t i = 0; i < VulkanPipelineCache::TARGET_BINDING_COUNT; i++) { if ((1 << i) & mContext.currentRenderPass.subpassMask) { - VulkanAttachment subpassInput = mCurrentRenderTarget->getColor(swapChain, i); + VulkanAttachment subpassInput = mCurrentRenderTarget->getColor(i); VkDescriptorImageInfo info = { .imageView = subpassInput.view, .imageLayout = subpassInput.layout, @@ -1287,6 +1287,10 @@ void VulkanDriver::makeCurrent(Handle drawSch, Handle // Leave early if the swap chain image has already been acquired but not yet presented. if (surf.acquired) { + if (UTILS_LIKELY(mContext.defaultRenderTarget)) { + VulkanRenderTarget* rt = handle_cast(mContext.defaultRenderTarget); + rt->bindToSwapChain(surf); + } return; } @@ -1299,6 +1303,11 @@ void VulkanDriver::makeCurrent(Handle drawSch, Handle // Call vkAcquireNextImageKHR and insert its signal semaphore into the command manager's // dependency chain. surf.acquire(); + + if (UTILS_LIKELY(mContext.defaultRenderTarget)) { + VulkanRenderTarget* rt = handle_cast(mContext.defaultRenderTarget); + rt->bindToSwapChain(surf); + } } void VulkanDriver::commit(Handle sch) { @@ -1425,7 +1434,7 @@ void VulkanDriver::readPixels(Handle src, uint32_t x, uint32_t y uint32_t width, uint32_t height, PixelBufferDescriptor&& pbd) { const VkDevice device = mContext.device; VulkanRenderTarget* srcTarget = handle_cast(src); - VulkanTexture* srcTexture = srcTarget->getColor(mContext.currentSurface, 0).texture; + VulkanTexture* srcTexture = srcTarget->getColor(0).texture; assert_invariant(srcTexture); const VkFormat srcFormat = srcTexture->getVkFormat(); const bool swizzle = srcFormat == VK_FORMAT_B8G8R8A8_UNORM; @@ -1487,7 +1496,7 @@ void VulkanDriver::readPixels(Handle src, uint32_t x, uint32_t y .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, }); - const VulkanAttachment srcAttachment = srcTarget->getColor(mContext.currentSurface, 0); + const VulkanAttachment srcAttachment = srcTarget->getColor(0); VkImageCopy imageCopyRegion = { .srcSubresource = { @@ -1498,7 +1507,7 @@ void VulkanDriver::readPixels(Handle src, uint32_t x, uint32_t y }, .srcOffset = { .x = (int32_t) x, - .y = (int32_t) (srcTarget->getExtent(mContext.currentSurface).height - (height + y)), + .y = (int32_t) (srcTarget->getExtent().height - (height + y)), }, .dstSubresource = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, @@ -1526,7 +1535,7 @@ void VulkanDriver::readPixels(Handle src, uint32_t x, uint32_t y // Perform the copy into the staging area. At this point we know that the src layout is // TRANSFER_SRC_OPTIMAL and the staging area is GENERAL. - vkCmdCopyImage(cmdbuffer, srcTarget->getColor(mContext.currentSurface, 0).image, + vkCmdCopyImage(cmdbuffer, srcTarget->getColor(0).image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingImage, VK_IMAGE_LAYOUT_GENERAL, 1, &imageCopyRegion); @@ -1592,14 +1601,14 @@ void VulkanDriver::blit(TargetBufferFlags buffers, Handle dst, V VkFilter vkfilter = filter == SamplerMagFilter::NEAREST ? VK_FILTER_NEAREST : VK_FILTER_LINEAR; - const VkExtent2D srcExtent = srcTarget->getExtent(mContext.currentSurface); + const VkExtent2D srcExtent = srcTarget->getExtent(); const int32_t srcLeft = std::min(srcRect.left, (int32_t) srcExtent.width); const int32_t srcBottom = std::min(srcRect.bottom, (int32_t) srcExtent.height); const int32_t srcRight = std::min(srcRect.left + srcRect.width, srcExtent.width); const int32_t srcTop = std::min(srcRect.bottom + srcRect.height, srcExtent.height); const VkOffset3D srcOffsets[2] = { { srcLeft, srcBottom, 0 }, { srcRight, srcTop, 1 }}; - const VkExtent2D dstExtent = dstTarget->getExtent(mContext.currentSurface); + const VkExtent2D dstExtent = dstTarget->getExtent(); const int32_t dstLeft = std::min(dstRect.left, (int32_t) dstExtent.width); const int32_t dstBottom = std::min(dstRect.bottom, (int32_t) dstExtent.height); const int32_t dstRight = std::min(dstRect.left + dstRect.width, dstExtent.width); @@ -1817,7 +1826,7 @@ void VulkanDriver::draw(PipelineState pipelineState, Handle r .extent = { (uint32_t)right - x, (uint32_t)top - y } }; - rt->transformClientRectToPlatform(mContext.currentSurface, &scissor); + rt->transformClientRectToPlatform(&scissor); mPipelineCache.bindScissor(cmdbuffer, scissor); // Bind a new pipeline if the pipeline state changed. diff --git a/filament/backend/src/vulkan/VulkanHandles.cpp b/filament/backend/src/vulkan/VulkanHandles.cpp index 15f615a830..b32e44919e 100644 --- a/filament/backend/src/vulkan/VulkanHandles.cpp +++ b/filament/backend/src/vulkan/VulkanHandles.cpp @@ -112,10 +112,17 @@ static VulkanAttachment createAttachment(VulkanContext& context, VulkanAttachmen } // Creates a special "default" render target (i.e. associated with the swap chain) -// Note that the attachment structs are unused in this case in favor of VulkanSwapChain. VulkanRenderTarget::VulkanRenderTarget(VulkanContext& context) : HwRenderTarget(0, 0), mOffscreen(false), mSamples(1) {} +void VulkanRenderTarget::bindToSwapChain(VulkanSwapChain& swapChain) { + assert_invariant(!mOffscreen); + mColor[0] = swapChain.getColorAttachment(); + mDepth = swapChain.getDepthAttachment(); + width = swapChain.clientSize.width; + height = swapChain.clientSize.height; +} + VulkanRenderTarget::VulkanRenderTarget(VulkanContext& context, uint32_t width, uint32_t height, uint8_t samples, VulkanAttachment color[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT], VulkanAttachment depthStencil[2], VulkanStagePool& stagePool) : @@ -209,33 +216,30 @@ VulkanRenderTarget::VulkanRenderTarget(VulkanContext& context, uint32_t width, u VK_IMAGE_ASPECT_DEPTH_BIT); } -void VulkanRenderTarget::transformClientRectToPlatform(VulkanSwapChain* currentSurface, VkRect2D* bounds) const { - const auto& extent = getExtent(currentSurface); +void VulkanRenderTarget::transformClientRectToPlatform(VkRect2D* bounds) const { + const auto& extent = getExtent(); flipVertically(bounds, extent.height); clampToFramebuffer(bounds, extent.width, extent.height); } -void VulkanRenderTarget::transformClientRectToPlatform(VulkanSwapChain* currentSurface, VkViewport* bounds) const { - flipVertically(bounds, getExtent(currentSurface).height); +void VulkanRenderTarget::transformClientRectToPlatform(VkViewport* bounds) const { + flipVertically(bounds, getExtent().height); } -VkExtent2D VulkanRenderTarget::getExtent(VulkanSwapChain* currentSurface) const { - if (mOffscreen) { - return {width, height}; - } - return currentSurface->clientSize; +VkExtent2D VulkanRenderTarget::getExtent() const { + return {width, height}; } -VulkanAttachment VulkanRenderTarget::getColor(VulkanSwapChain* currentSurface, int target) const { - return (mOffscreen || target > 0) ? mColor[target] : currentSurface->getColorAttachment(); +VulkanAttachment VulkanRenderTarget::getColor(int target) const { + return mColor[target]; } VulkanAttachment VulkanRenderTarget::getMsaaColor(int target) const { return mMsaaAttachments[target]; } -VulkanAttachment VulkanRenderTarget::getDepth(VulkanSwapChain* currentSurface) const { - return mOffscreen ? mDepth : currentSurface->getDepthAttachment(); +VulkanAttachment VulkanRenderTarget::getDepth() const { + return mDepth; } VulkanAttachment VulkanRenderTarget::getMsaaDepth() const { diff --git a/filament/backend/src/vulkan/VulkanHandles.h b/filament/backend/src/vulkan/VulkanHandles.h index 13f168aa74..8d2bb59777 100644 --- a/filament/backend/src/vulkan/VulkanHandles.h +++ b/filament/backend/src/vulkan/VulkanHandles.h @@ -53,17 +53,18 @@ struct VulkanRenderTarget : private HwRenderTarget { // Creates a special "default" render target (i.e. associated with the swap chain) explicit VulkanRenderTarget(VulkanContext& context); - void transformClientRectToPlatform(VulkanSwapChain* currentSurface, VkRect2D* bounds) const; - void transformClientRectToPlatform(VulkanSwapChain* currentSurface, VkViewport* bounds) const; - VkExtent2D getExtent(VulkanSwapChain* currentSurface) const; - VulkanAttachment getColor(VulkanSwapChain* currentSurface, int target) const; + void transformClientRectToPlatform(VkRect2D* bounds) const; + void transformClientRectToPlatform(VkViewport* bounds) const; + VkExtent2D getExtent() const; + VulkanAttachment getColor(int target) const; VulkanAttachment getMsaaColor(int target) const; - VulkanAttachment getDepth(VulkanSwapChain* currentSurface) const; + VulkanAttachment getDepth() const; VulkanAttachment getMsaaDepth() const; int getColorTargetCount(const VulkanRenderPass& pass) const; uint8_t getSamples() const { return mSamples; } bool hasDepth() const { return mDepth.format != VK_FORMAT_UNDEFINED; } bool isSwapChain() const { return !mOffscreen; } + void bindToSwapChain(VulkanSwapChain& surf); private: VulkanAttachment mColor[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT] = {};