Vulkan: simplify management of "default" render target.

This commit is contained in:
Philip Rideout
2022-02-16 14:31:02 -08:00
parent 9ef3c59698
commit 8c8061a637
5 changed files with 73 additions and 59 deletions

View File

@@ -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);
}

View File

@@ -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<HwRenderTarget> defaultRenderTarget;
VulkanRenderPass currentRenderPass;
VkViewport viewport;
VkFormat finalDepthFormat;

View File

@@ -322,6 +322,8 @@ void VulkanDriver::terminate() {
delete mContext.commands;
delete mContext.emptyTexture;
destruct<VulkanRenderTarget>(mContext.defaultRenderTarget);
mBlitter.shutdown();
// Allow the stage pool and disposer to clean up.
@@ -519,10 +521,9 @@ void VulkanDriver::destroyProgram(Handle<HwProgram> ph) {
}
void VulkanDriver::createDefaultRenderTargetR(Handle<HwRenderTarget> rth, int) {
auto renderTarget = construct<VulkanRenderTarget>(rth, mContext);
mDisposer.createDisposable(renderTarget, [this, rth] () {
destruct<VulkanRenderTarget>(rth);
});
assert_invariant(!mContext.defaultRenderTarget);
mContext.defaultRenderTarget = rth;
construct<VulkanRenderTarget>(rth, mContext);
}
void VulkanDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
@@ -557,7 +558,10 @@ void VulkanDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
void VulkanDriver::destroyRenderTarget(Handle<HwRenderTarget> rth) {
if (rth) {
mDisposer.removeReference(handle_cast<VulkanRenderTarget*>(rth));
if (UTILS_LIKELY(mContext.defaultRenderTarget != rth)) {
VulkanRenderTarget* rt = handle_cast<VulkanRenderTarget*>(rth);
mDisposer.removeReference(rt);
}
}
}
@@ -983,9 +987,8 @@ void VulkanDriver::updateSamplerGroup(Handle<HwSamplerGroup> sbh,
void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassParams& params) {
mCurrentRenderTarget = handle_cast<VulkanRenderTarget*>(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<HwRenderTarget> 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<HwRenderTarget> 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<HwRenderTarget> 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<HwRenderTarget> 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<HwRenderTarget> 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<HwRenderTarget> 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<HwSwapChain> drawSch, Handle<HwSwapChain>
// 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<VulkanRenderTarget*>(mContext.defaultRenderTarget);
rt->bindToSwapChain(surf);
}
return;
}
@@ -1299,6 +1303,11 @@ void VulkanDriver::makeCurrent(Handle<HwSwapChain> drawSch, Handle<HwSwapChain>
// 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<VulkanRenderTarget*>(mContext.defaultRenderTarget);
rt->bindToSwapChain(surf);
}
}
void VulkanDriver::commit(Handle<HwSwapChain> sch) {
@@ -1425,7 +1434,7 @@ void VulkanDriver::readPixels(Handle<HwRenderTarget> src, uint32_t x, uint32_t y
uint32_t width, uint32_t height, PixelBufferDescriptor&& pbd) {
const VkDevice device = mContext.device;
VulkanRenderTarget* srcTarget = handle_cast<VulkanRenderTarget*>(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<HwRenderTarget> 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<HwRenderTarget> 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<HwRenderTarget> 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<HwRenderTarget> 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<HwRenderPrimitive> 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.

View File

@@ -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 {

View File

@@ -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] = {};