Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 28 additions & 29 deletions filament/backend/src/vulkan/VulkanDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -944,28 +944,23 @@ void VulkanDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
}
}

VulkanAttachment depthStencil[2] = {};
if (depth.handle) {
depthStencil[0] = {
.texture = resource_ptr<VulkanTexture>::cast(&mResourceManager, depth.handle),
.level = depth.level,
VulkanAttachment depthStencil;
// In VK you can only have one depth/stencil attachment on a RT.
// This can be a depth only, stencil only or depth and stencil combined.
// You cannot have separate depth and stencil attachment (unless you use Dynamic Rendering)
if (depth.handle || stencil.handle) {
assert_invariant(!depth.handle || !stencil.handle || (depth.handle == stencil.handle));
// We assume that we have depth only attachment or that depth and stencil come in the depth attachment
Comment thread
jorgeag-google marked this conversation as resolved.
// Except in the case there is a stencil only attachment
TargetBufferInfo depthStencilBuffer = depth.handle ? depth : stencil;

depthStencil = {
.texture = resource_ptr<VulkanTexture>::cast(&mResourceManager, depthStencilBuffer.handle),
.level = depthStencilBuffer.level,
.layerCount = layerCount,
.layer = (uint8_t) depth.layer,
.layer = (uint8_t) depthStencilBuffer.layer,
};
UTILS_UNUSED_IN_RELEASE VkExtent2D extent = depthStencil[0].getExtent2D();
tmin = { std::min(tmin.x, extent.width), std::min(tmin.y, extent.height) };
tmax = { std::max(tmax.x, extent.width), std::max(tmax.y, extent.height) };
attachmentCount++;
}

if (stencil.handle) {
depthStencil[1] = {
.texture = resource_ptr<VulkanTexture>::cast(&mResourceManager, stencil.handle),
.level = stencil.level,
.layerCount = layerCount,
.layer = (uint8_t) stencil.layer,
};
UTILS_UNUSED_IN_RELEASE VkExtent2D extent = depthStencil[1].getExtent2D();
UTILS_UNUSED_IN_RELEASE VkExtent2D extent = depthStencil.getExtent2D();
tmin = { std::min(tmin.x, extent.width), std::min(tmin.y, extent.height) };
tmax = { std::max(tmax.x, extent.width), std::max(tmax.y, extent.height) };
attachmentCount++;
Expand Down Expand Up @@ -1969,9 +1964,9 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
assert_invariant(rt == mDefaultRenderTarget || extent.width > 0 && extent.height > 0);

#if FVK_ENABLED(FVK_DEBUG_TEXTURE)
if (rt->hasDepth()) {
auto depth = rt->getDepth();
depth.texture->print();
if (rt->hasDepthStencil()) {
auto depthStencil = rt->getDepthStencil();
depthStencil.texture->print();
}
#endif

Expand All @@ -1986,15 +1981,19 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
VkRect2D const scissor{ .offset = { 0, 0 }, .extent = extent };
vkCmdSetScissor(cmdbuffer, 0, 1, &scissor);

VulkanLayout currentDepthLayout = VulkanLayout::UNDEFINED;
VulkanLayout currentDepthStencilLayout = VulkanLayout::UNDEFINED;
TargetBufferFlags clearVal = params.flags.clear;
TargetBufferFlags discardEndVal = params.flags.discardEnd;
if (rt->hasDepth()) {
if (rt->hasDepthStencil()) {
if (params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH) {
discardEndVal &= ~TargetBufferFlags::DEPTH;
clearVal &= ~TargetBufferFlags::DEPTH;
}
Comment thread
jorgeag-google marked this conversation as resolved.
currentDepthLayout = VulkanLayout::DEPTH_ATTACHMENT;
if (params.readOnlyDepthStencil & RenderPassParams::READONLY_STENCIL) {
discardEndVal &= ~TargetBufferFlags::STENCIL;
clearVal &= ~TargetBufferFlags::STENCIL;
}
currentDepthStencilLayout = VulkanLayout::DEPTH_STENCIL_ATTACHMENT;
}


Expand All @@ -2004,7 +2003,7 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
rpkey.clear = clearVal;
rpkey.discardStart = discardStart;
rpkey.discardEnd = discardEndVal;
rpkey.initialDepthLayout = currentDepthLayout;
rpkey.initialDepthStencilLayout = currentDepthStencilLayout;
rpkey.subpassMask = uint8_t(params.subpassMask);

fvkmemory::resource_ptr<VulkanRenderPass> renderPass =
Expand Down Expand Up @@ -2070,9 +2069,9 @@ void VulkanDriver::beginRenderPass(Handle<HwRenderTarget> rth, const RenderPassP
renderPassInfo.clearValueCount++;
}
}
if (fbkey.depth) {
if (fbkey.depthStencil) {
VkClearValue &clearValue = clearValues[renderPassInfo.clearValueCount++];
clearValue.depthStencil = {(float) params.clearDepth, 0};
clearValue.depthStencil = {(float) params.clearDepth, params.clearStencil};
}
renderPassInfo.pClearValues = &clearValues[0];
}
Expand Down
53 changes: 29 additions & 24 deletions filament/backend/src/vulkan/VulkanFboCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ namespace filament::backend {

bool VulkanFboCache::RenderPassEq::operator()(const RenderPassKey& k1,
const RenderPassKey& k2) const {
if (k1.initialDepthLayout != k2.initialDepthLayout) return false;
if (k1.initialDepthStencilLayout != k2.initialDepthStencilLayout) return false;
for (int i = 0; i < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; i++) {
if (k1.colorFormat[i] != k2.colorFormat[i]) return false;
}
if (k1.depthFormat != k2.depthFormat) return false;
if (k1.depthStencilFormat != k2.depthStencilFormat) return false;
if (k1.clear != k2.clear) return false;
if (k1.discardStart != k2.discardStart) return false;
if (k1.discardEnd != k2.discardEnd) return false;
Expand All @@ -55,7 +55,7 @@ bool VulkanFboCache::FboKeyEqualFn::operator()(const FboKey& k1, const FboKey& k
if (k1.height != k2.height) return false;
if (k1.layers != k2.layers) return false;
if (k1.samples != k2.samples) return false;
if (k1.depth != k2.depth) return false;
if (k1.depthStencil != k2.depthStencil) return false;
for (int i = 0; i < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; i++) {
if (k1.color[i] != k2.color[i]) return false;
if (k1.resolve[i] != k2.resolve[i]) return false;
Expand Down Expand Up @@ -96,8 +96,8 @@ fvkmemory::resource_ptr<VulkanFramebuffer> VulkanFboCache::getFramebuffer(FboKey
attachments[attachmentCount++] = attachment;
}
}
if (config.depth) {
attachments[attachmentCount++] = config.depth;
if (config.depthStencil) {
attachments[attachmentCount++] = config.depthStencil;
}

#if FVK_ENABLED(FVK_DEBUG_FBO_CACHE)
Expand Down Expand Up @@ -151,26 +151,27 @@ fvkmemory::resource_ptr<VulkanRenderPass> VulkanFboCache::getRenderPass(
VkAttachmentReference inputAttachmentRef[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT] = {};
VkAttachmentReference colorAttachmentRefs[2][MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT] = {};
VkAttachmentReference resolveAttachmentRef[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT] = {};
VkAttachmentReference depthAttachmentRef = {};
VkAttachmentReference depthStencilAttachmentRef = {};

const bool hasDepth = config.depthFormat != VK_FORMAT_UNDEFINED;
const bool hasDepthOrStencil = fvkutils::isVkDepthFormat(config.depthStencilFormat) ||
fvkutils::isVkStencilFormat(config.depthStencilFormat);

VkSubpassDescription subpasses[2] = {{
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.pInputAttachments = nullptr,
.pColorAttachments = colorAttachmentRefs[0],
.pResolveAttachments = resolveAttachmentRef,
.pDepthStencilAttachment = hasDepth ? &depthAttachmentRef : nullptr
.pDepthStencilAttachment = hasDepthOrStencil ? &depthStencilAttachmentRef : nullptr
},
{
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.pInputAttachments = inputAttachmentRef,
.pColorAttachments = colorAttachmentRefs[1],
.pResolveAttachments = resolveAttachmentRef,
.pDepthStencilAttachment = hasDepth ? &depthAttachmentRef : nullptr
.pDepthStencilAttachment = hasDepthOrStencil ? &depthStencilAttachmentRef : nullptr
}};

// The attachment list contains: Color Attachments, Resolve Attachments, and Depth Attachment.
// The attachment list contains: Color Attachments, Resolve Attachments, and Depth/Stencil Attachment.
// For simplicity, create an array that can hold the maximum possible number of attachments.
// Note that this needs to have the same ordering as the corollary array in getFramebuffer.
VkAttachmentDescription attachments[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT + MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT + 1] = {};
Expand Down Expand Up @@ -310,22 +311,26 @@ fvkmemory::resource_ptr<VulkanRenderPass> VulkanFboCache::getRenderPass(
};
}

// Populate the Depth Attachment.
if (hasDepth) {
const bool clear = any(config.clear & TargetBufferFlags::DEPTH);
const bool discardStart = any(config.discardStart & TargetBufferFlags::DEPTH);
const bool discardEnd = any(config.discardEnd & TargetBufferFlags::DEPTH);
depthAttachmentRef.layout = fvkutils::getVkLayout(VulkanLayout::DEPTH_ATTACHMENT);
depthAttachmentRef.attachment = attachmentIndex;
// Populate the Depth/Stencil Attachment.
if (hasDepthOrStencil) {
const bool clearDepth = any(config.clear & TargetBufferFlags::DEPTH);
const bool discardStartDepth = any(config.discardStart & TargetBufferFlags::DEPTH);
const bool discardEndDepth = any(config.discardEnd & TargetBufferFlags::DEPTH);
const bool clearStencil = any(config.clear & TargetBufferFlags::STENCIL);
const bool discardStartStencil = any(config.discardStart & TargetBufferFlags::STENCIL);
const bool discardEndStencil = any(config.discardEnd & TargetBufferFlags::STENCIL);

depthStencilAttachmentRef.layout = fvkutils::getVkLayout(VulkanLayout::DEPTH_STENCIL_ATTACHMENT);
depthStencilAttachmentRef.attachment = attachmentIndex;
attachments[attachmentIndex++] = {
.format = config.depthFormat,
.format = config.depthStencilFormat,
.samples = (VkSampleCountFlagBits) config.samples,
.loadOp = clear ? kClear : (discardStart ? kDontCare : kKeep),
.storeOp = discardEnd ? kDisableStore : kEnableStore,
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
.initialLayout = fvkutils::getVkLayout(config.initialDepthLayout),
.finalLayout = fvkutils::getVkLayout(FINAL_DEPTH_ATTACHMENT_LAYOUT),
.loadOp = clearDepth ? kClear : (discardStartDepth ? kDontCare : kKeep),
.storeOp = discardEndDepth ? kDisableStore : kEnableStore,
.stencilLoadOp = clearStencil ? kClear : (discardStartStencil ? kDontCare : kKeep),
.stencilStoreOp = discardEndStencil ? kDisableStore : kEnableStore,
.initialLayout = fvkutils::getVkLayout(config.initialDepthStencilLayout),
.finalLayout = fvkutils::getVkLayout(FINAL_DEPTH_STENCIL_ATTACHMENT_LAYOUT),
};
}
renderPassInfo.attachmentCount = attachmentIndex;
Expand Down
8 changes: 4 additions & 4 deletions filament/backend/src/vulkan/VulkanFboCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,18 @@ class VulkanFboCache {
public:
constexpr static VulkanLayout FINAL_COLOR_ATTACHMENT_LAYOUT = VulkanLayout::COLOR_ATTACHMENT;
constexpr static VulkanLayout FINAL_RESOLVE_ATTACHMENT_LAYOUT = VulkanLayout::COLOR_ATTACHMENT;
constexpr static VulkanLayout FINAL_DEPTH_ATTACHMENT_LAYOUT = VulkanLayout::DEPTH_ATTACHMENT;
constexpr static VulkanLayout FINAL_DEPTH_STENCIL_ATTACHMENT_LAYOUT = VulkanLayout::DEPTH_STENCIL_ATTACHMENT;

// RenderPassKey is a small POD representing the immutable state that is used to construct
// a VkRenderPass. It is hashed and used as a lookup key.
struct alignas(8) RenderPassKey {
VkFormat colorFormat[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT]; // 32 bytes
VkFormat depthFormat; // 4 bytes
VkFormat depthStencilFormat; // 4 bytes
TargetBufferFlags clear; // 4 bytes
TargetBufferFlags discardStart; // 4 bytes
TargetBufferFlags discardEnd; // 4 bytes

VulkanLayout initialDepthLayout; // 1 byte
VulkanLayout initialDepthStencilLayout; // 1 byte
uint8_t samples; // 1 byte
uint8_t needsResolveMask; // 1 byte
uint8_t usesLazilyAllocatedMemory; // 1 byte
Expand Down Expand Up @@ -86,7 +86,7 @@ class VulkanFboCache {
uint16_t samples; // 2 bytes
VkImageView color[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT]; // 64 bytes
VkImageView resolve[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT]; // 64 bytes
VkImageView depth; // 8 bytes
VkImageView depthStencil; // 8 bytes
};
struct FboVal {
fvkmemory::resource_ptr<VulkanFramebuffer> handle;
Expand Down
45 changes: 22 additions & 23 deletions filament/backend/src/vulkan/VulkanHandles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,13 +287,13 @@ void VulkanRenderTarget::bindSwapChain(fvkmemory::resource_ptr<VulkanSwapChain>
if (swapchain->getDepth()) {
VulkanAttachment depth = createSwapchainAttachment(swapchain->getDepth());
mInfo->attachments.push_back(depth);
mInfo->depthIndex = 1;
mInfo->depthStencilIndex = 1;

rpkey.depthFormat = depth.getFormat();
fbkey.depth = depth.getImageView();
rpkey.depthStencilFormat = depth.getFormat();
fbkey.depthStencil = depth.getImageView();
} else {
rpkey.depthFormat = VK_FORMAT_UNDEFINED;
fbkey.depth = VK_NULL_HANDLE;
rpkey.depthStencilFormat = VK_FORMAT_UNDEFINED;
fbkey.depthStencil = VK_NULL_HANDLE;
}
mInfo->colors.set(0);
}
Expand All @@ -307,12 +307,11 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica
VulkanContext const& context, fvkmemory::ResourceManager* resourceManager,
VmaAllocator allocator, VulkanCommands* commands, uint32_t width, uint32_t height,
uint8_t samples, VulkanAttachment color[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT],
VulkanAttachment depthStencil[2], VulkanStagePool& stagePool, uint8_t layerCount)
VulkanAttachment depthStencil, VulkanStagePool& stagePool, uint8_t layerCount)
: HwRenderTarget(width, height),
mOffscreen(true),
mProtected(false),
mInfo(std::make_unique<Auxiliary>()) {
auto& depth = depthStencil[0];

// Constrain the sample count according to both kinds of sample count masks obtained from
// VkPhysicalDeviceProperties. This is consistent with the VulkanTexture constructor.
Expand All @@ -322,7 +321,7 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica

auto& rpkey = mInfo->rpkey;
rpkey.samples = samples;
rpkey.depthFormat = depth.getFormat();
rpkey.depthStencilFormat = depthStencil.getFormat();
rpkey.viewCount = layerCount;

auto& fbkey = mInfo->fbkey;
Expand Down Expand Up @@ -383,27 +382,27 @@ VulkanRenderTarget::VulkanRenderTarget(VkDevice device, VkPhysicalDevice physica
attachments.insert(attachments.end(), msaaAttachments.begin(), msaaAttachments.end());
}

if (depth.texture) {
auto depthTexture = depth.texture;
mInfo->depthIndex = (uint8_t) attachments.size();
attachments.push_back(depth);
fbkey.depth = depth.getImageView();
if (depthStencil.texture) {
auto depthStencilTexture = depthStencil.texture;
mInfo->depthStencilIndex = (uint8_t) attachments.size();
attachments.push_back(depthStencil);
fbkey.depthStencil = depthStencil.getImageView();
if (samples > 1) {
mInfo->msaaDepthIndex = mInfo->depthIndex;
if (depthTexture->samples == 1) {
mInfo->msaaDepthStencilIndex = mInfo->depthStencilIndex;
if (depthStencilTexture->samples == 1) {
// MSAA depth texture must have the mipmap count of 1
uint8_t const msLevel = 1;
// Create sidecar MSAA texture for the depth attachment if it does not already
// exist.
auto msaaTexture = initMsaaTexture(depthTexture, device, physicalDevice, context,
auto msaaTexture = initMsaaTexture(depthStencilTexture, device, physicalDevice, context,
allocator, commands, resourceManager, msLevel, samples, stagePool);
mInfo->msaaDepthIndex = (uint8_t) attachments.size();
mInfo->msaaDepthStencilIndex = (uint8_t) attachments.size();
VulkanAttachment msaaAttachment = {
.texture = msaaTexture,
.layerCount = layerCount,
};
attachments.push_back(msaaAttachment);
fbkey.depth = msaaAttachment.getImageView();
fbkey.depthStencil = msaaAttachment.getImageView();
}
}
}
Expand Down Expand Up @@ -460,11 +459,11 @@ void VulkanRenderTarget::emitBarriersBeginRenderPass(VulkanCommandBuffer& comman
barrier(attachments[i], VulkanLayout::COLOR_ATTACHMENT);
}
}
if (mInfo->depthIndex != Auxiliary::UNDEFINED_INDEX) {
barrier(attachments[mInfo->depthIndex], VulkanLayout::DEPTH_ATTACHMENT);
if (mInfo->depthStencilIndex != Auxiliary::UNDEFINED_INDEX) {
barrier(attachments[mInfo->depthStencilIndex], VulkanLayout::DEPTH_STENCIL_ATTACHMENT);
}
if (mInfo->msaaDepthIndex != Auxiliary::UNDEFINED_INDEX) {
barrier(attachments[mInfo->msaaDepthIndex], VulkanLayout::DEPTH_ATTACHMENT);
if (mInfo->msaaDepthStencilIndex != Auxiliary::UNDEFINED_INDEX) {
barrier(attachments[mInfo->msaaDepthStencilIndex], VulkanLayout::DEPTH_STENCIL_ATTACHMENT);
}
}

Expand All @@ -478,7 +477,7 @@ void VulkanRenderTarget::emitBarriersEndRenderPass(VulkanCommandBuffer& commands
bool const isDepth = attachment.isDepth();
auto texture = attachment.texture;
if (isDepth) {
texture->setLayout(range, VulkanFboCache::FINAL_DEPTH_ATTACHMENT_LAYOUT);
texture->setLayout(range, VulkanFboCache::FINAL_DEPTH_STENCIL_ATTACHMENT_LAYOUT);
if (!texture->transitionLayout(&commands, range, VulkanLayout::DEPTH_SAMPLER)) {
texture->attachmentToSamplerBarrier(&commands, range);
}
Expand Down
Loading
Loading