Commit 594e0e14 by Jamie Madill Committed by Commit Bot

Vulkan: Add DS ReadOnly mode to Framebuffer/RP caches.

Allows ANGLE to create Framebuffers and RenderPasses with a read- only depth/stencil layout. Also allows us to transition our Images to this new DepthStencilReadOnly layout. Internal code redesign. No functional change to our command stream. Bug: angleproject:4959 Change-Id: I9b80063bdaec8f5d6c89037e0618c85e1c11b78d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2354280Reviewed-by: 's avatarCharlie Lao <cclao@google.com> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent a13f1061
...@@ -1695,7 +1695,8 @@ void FramebufferVk::updateRenderPassDesc() ...@@ -1695,7 +1695,8 @@ void FramebufferVk::updateRenderPassDesc()
if (depthStencilRenderTarget) if (depthStencilRenderTarget)
{ {
mRenderPassDesc.packDepthStencilAttachment( mRenderPassDesc.packDepthStencilAttachment(
depthStencilRenderTarget->getImageForRenderPass().getFormat().intendedFormatID); depthStencilRenderTarget->getImageForRenderPass().getFormat().intendedFormatID,
vk::ResourceAccess::Write);
} }
} }
......
...@@ -291,6 +291,7 @@ angle::Result InitializeRenderPassFromDesc(vk::Context *context, ...@@ -291,6 +291,7 @@ angle::Result InitializeRenderPassFromDesc(vk::Context *context,
// Pack depth/stencil attachment, if any // Pack depth/stencil attachment, if any
if (desc.hasDepthStencilAttachment()) if (desc.hasDepthStencilAttachment())
{ {
ResourceAccess dsAccess = desc.getDepthStencilAccess();
uint32_t depthStencilIndex = static_cast<uint32_t>(desc.depthStencilAttachmentIndex()); uint32_t depthStencilIndex = static_cast<uint32_t>(desc.depthStencilAttachmentIndex());
uint32_t depthStencilIndexVk = colorAttachmentCount; uint32_t depthStencilIndexVk = colorAttachmentCount;
...@@ -299,7 +300,18 @@ angle::Result InitializeRenderPassFromDesc(vk::Context *context, ...@@ -299,7 +300,18 @@ angle::Result InitializeRenderPassFromDesc(vk::Context *context,
const vk::Format &format = context->getRenderer()->getFormat(formatID); const vk::Format &format = context->getRenderer()->getFormat(formatID);
depthStencilAttachmentRef.attachment = depthStencilIndexVk; depthStencilAttachmentRef.attachment = depthStencilIndexVk;
depthStencilAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
switch (dsAccess)
{
case ResourceAccess::ReadOnly:
depthStencilAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
break;
case ResourceAccess::Write:
depthStencilAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
break;
default:
UNREACHABLE();
}
UnpackAttachmentDesc(&attachmentDescs[depthStencilIndexVk], format, desc.samples(), UnpackAttachmentDesc(&attachmentDescs[depthStencilIndexVk], format, desc.samples(),
ops[depthStencilIndexVk]); ops[depthStencilIndexVk]);
...@@ -466,13 +478,44 @@ void RenderPassDesc::setSamples(GLint samples) ...@@ -466,13 +478,44 @@ void RenderPassDesc::setSamples(GLint samples)
SetBitField(mLogSamples, PackSampleCount(samples)); SetBitField(mLogSamples, PackSampleCount(samples));
} }
// We can use a bit packing trick to combine two states into a smaller number of bits. The first
// state is the "depth stencil access" mode which can be Unused/ReadOnly/Write. Naively the DS
// access would take 2 bits. The color attachment count state can have 9 values: no attachments +
// 1-8 attachments. Naively this would take 4 bits. So our total bit count naively would be 6. We
// can pack into 5 bits simply by treating the combination of the 9*3 values as an enum with 27
// values. 5 bits gives us 32 possible values. Mod and divide allow us to access the two different
// state components of the enum.
enum PackedAttachmentCount : uint8_t
{
NoColor = 0,
ColorMax = NoColor + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS,
NoColorDepthStencilRead = ColorMax + 1,
ColorMaxDepthStencilRead = NoColorDepthStencilRead + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS,
NoColorDepthStencilWrite = ColorMaxDepthStencilRead + 1,
ColorMaxDepthStencilWrite = NoColorDepthStencilWrite + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS,
EnumCount,
};
static_assert(PackedAttachmentCount::EnumCount < angle::Bit<uint8_t>(5), "Bit overflow");
size_t RenderPassDesc::colorAttachmentRange() const
{
return mPackedColorAttachmentRangeAndDSAccess % (PackedAttachmentCount::ColorMax + 1);
}
ResourceAccess RenderPassDesc::getDepthStencilAccess() const
{
return static_cast<ResourceAccess>(mPackedColorAttachmentRangeAndDSAccess /
(PackedAttachmentCount::ColorMax + 1));
}
void RenderPassDesc::packColorAttachment(size_t colorIndexGL, angle::FormatID formatID) void RenderPassDesc::packColorAttachment(size_t colorIndexGL, angle::FormatID formatID)
{ {
ASSERT(colorIndexGL < mAttachmentFormats.size()); ASSERT(colorIndexGL < mAttachmentFormats.size());
static_assert(angle::kNumANGLEFormats < std::numeric_limits<uint8_t>::max(), static_assert(angle::kNumANGLEFormats < std::numeric_limits<uint8_t>::max(),
"Too many ANGLE formats to fit in uint8_t"); "Too many ANGLE formats to fit in uint8_t");
// Force the user to pack the depth/stencil attachment last. // Force the user to pack the depth/stencil attachment last.
ASSERT(mHasDepthStencilAttachment == false); ASSERT(!hasDepthStencilAttachment());
// This function should only be called for enabled GL color attachments. // This function should only be called for enabled GL color attachments.
ASSERT(formatID != angle::FormatID::NONE); ASSERT(formatID != angle::FormatID::NONE);
...@@ -481,7 +524,8 @@ void RenderPassDesc::packColorAttachment(size_t colorIndexGL, angle::FormatID fo ...@@ -481,7 +524,8 @@ void RenderPassDesc::packColorAttachment(size_t colorIndexGL, angle::FormatID fo
// Set color attachment range such that it covers the range from index 0 through last // Set color attachment range such that it covers the range from index 0 through last
// active index. This is the reason why we need depth/stencil to be packed last. // active index. This is the reason why we need depth/stencil to be packed last.
SetBitField(mColorAttachmentRange, std::max<size_t>(mColorAttachmentRange, colorIndexGL + 1)); SetBitField(mPackedColorAttachmentRangeAndDSAccess,
std::max<size_t>(mPackedColorAttachmentRangeAndDSAccess, colorIndexGL + 1));
} }
void RenderPassDesc::packColorAttachmentGap(size_t colorIndexGL) void RenderPassDesc::packColorAttachmentGap(size_t colorIndexGL)
...@@ -490,17 +534,17 @@ void RenderPassDesc::packColorAttachmentGap(size_t colorIndexGL) ...@@ -490,17 +534,17 @@ void RenderPassDesc::packColorAttachmentGap(size_t colorIndexGL)
static_assert(angle::kNumANGLEFormats < std::numeric_limits<uint8_t>::max(), static_assert(angle::kNumANGLEFormats < std::numeric_limits<uint8_t>::max(),
"Too many ANGLE formats to fit in uint8_t"); "Too many ANGLE formats to fit in uint8_t");
// Force the user to pack the depth/stencil attachment last. // Force the user to pack the depth/stencil attachment last.
ASSERT(mHasDepthStencilAttachment == false); ASSERT(!hasDepthStencilAttachment());
// Use NONE as a flag for gaps in GL color attachments. // Use NONE as a flag for gaps in GL color attachments.
uint8_t &packedFormat = mAttachmentFormats[colorIndexGL]; uint8_t &packedFormat = mAttachmentFormats[colorIndexGL];
SetBitField(packedFormat, angle::FormatID::NONE); SetBitField(packedFormat, angle::FormatID::NONE);
} }
void RenderPassDesc::packDepthStencilAttachment(angle::FormatID formatID) void RenderPassDesc::packDepthStencilAttachment(angle::FormatID formatID, ResourceAccess access)
{ {
// Though written as Count, there is only ever a single depth/stencil attachment. ASSERT(access != ResourceAccess::Unused);
ASSERT(mHasDepthStencilAttachment == false); ASSERT(!hasDepthStencilAttachment());
size_t index = depthStencilAttachmentIndex(); size_t index = depthStencilAttachmentIndex();
ASSERT(index < mAttachmentFormats.size()); ASSERT(index < mAttachmentFormats.size());
...@@ -508,7 +552,10 @@ void RenderPassDesc::packDepthStencilAttachment(angle::FormatID formatID) ...@@ -508,7 +552,10 @@ void RenderPassDesc::packDepthStencilAttachment(angle::FormatID formatID)
uint8_t &packedFormat = mAttachmentFormats[index]; uint8_t &packedFormat = mAttachmentFormats[index];
SetBitField(packedFormat, formatID); SetBitField(packedFormat, formatID);
mHasDepthStencilAttachment = true; size_t colorRange = colorAttachmentRange();
size_t offset =
access == ResourceAccess::ReadOnly ? NoColorDepthStencilRead : NoColorDepthStencilWrite;
SetBitField(mPackedColorAttachmentRangeAndDSAccess, colorRange + offset);
} }
void RenderPassDesc::packColorResolveAttachment(size_t colorIndexGL) void RenderPassDesc::packColorResolveAttachment(size_t colorIndexGL)
...@@ -538,14 +585,16 @@ bool RenderPassDesc::isColorAttachmentEnabled(size_t colorIndexGL) const ...@@ -538,14 +585,16 @@ bool RenderPassDesc::isColorAttachmentEnabled(size_t colorIndexGL) const
size_t RenderPassDesc::attachmentCount() const size_t RenderPassDesc::attachmentCount() const
{ {
size_t colorAttachmentCount = 0; size_t colorAttachmentCount = 0;
for (size_t i = 0; i < mColorAttachmentRange; ++i) size_t colorRange = colorAttachmentRange();
for (size_t i = 0; i < colorRange; ++i)
{ {
colorAttachmentCount += isColorAttachmentEnabled(i); colorAttachmentCount += isColorAttachmentEnabled(i);
} }
// Note that there are no gaps in depth/stencil attachments. In fact there is a maximum of 1 of // Note that there are no gaps in depth/stencil attachments. In fact there is a maximum of 1 of
// it. // it.
return colorAttachmentCount + mColorResolveAttachmentMask.count() + mHasDepthStencilAttachment; size_t depthStencilCount = hasDepthStencilAttachment() ? 1 : 0;
return colorAttachmentCount + mColorResolveAttachmentMask.count() + depthStencilCount;
} }
bool operator==(const RenderPassDesc &lhs, const RenderPassDesc &rhs) bool operator==(const RenderPassDesc &lhs, const RenderPassDesc &rhs)
...@@ -1812,7 +1861,7 @@ void FramebufferDesc::update(uint32_t index, ImageViewSubresourceSerial serial) ...@@ -1812,7 +1861,7 @@ void FramebufferDesc::update(uint32_t index, ImageViewSubresourceSerial serial)
mSerials[index] = serial; mSerials[index] = serial;
if (serial.imageViewSerial.valid()) if (serial.imageViewSerial.valid())
{ {
mMaxIndex = std::max(mMaxIndex, index + 1); mMaxIndex = std::max(mMaxIndex, static_cast<uint16_t>(index + 1));
} }
} }
...@@ -1831,6 +1880,11 @@ void FramebufferDesc::updateDepthStencil(ImageViewSubresourceSerial serial) ...@@ -1831,6 +1880,11 @@ void FramebufferDesc::updateDepthStencil(ImageViewSubresourceSerial serial)
update(kFramebufferDescDepthStencilIndex, serial); update(kFramebufferDescDepthStencilIndex, serial);
} }
void FramebufferDesc::updateReadOnlyDepth(bool readOnlyDepth)
{
mReadOnlyDepth = readOnlyDepth;
}
size_t FramebufferDesc::hash() const size_t FramebufferDesc::hash() const
{ {
return angle::ComputeGenericHash(&mSerials, sizeof(mSerials[0]) * (mMaxIndex + 1)); return angle::ComputeGenericHash(&mSerials, sizeof(mSerials[0]) * (mMaxIndex + 1));
...@@ -1838,7 +1892,8 @@ size_t FramebufferDesc::hash() const ...@@ -1838,7 +1892,8 @@ size_t FramebufferDesc::hash() const
void FramebufferDesc::reset() void FramebufferDesc::reset()
{ {
mMaxIndex = 0; mMaxIndex = 0;
mReadOnlyDepth = false;
memset(&mSerials, 0, sizeof(mSerials)); memset(&mSerials, 0, sizeof(mSerials));
} }
...@@ -1849,6 +1904,11 @@ bool FramebufferDesc::operator==(const FramebufferDesc &other) const ...@@ -1849,6 +1904,11 @@ bool FramebufferDesc::operator==(const FramebufferDesc &other) const
return false; return false;
} }
if (mReadOnlyDepth != other.mReadOnlyDepth)
{
return false;
}
size_t validRegionSize = sizeof(mSerials[0]) * mMaxIndex; size_t validRegionSize = sizeof(mSerials[0]) * mMaxIndex;
return memcmp(&mSerials, &other.mSerials, validRegionSize) == 0; return memcmp(&mSerials, &other.mSerials, validRegionSize) == 0;
} }
...@@ -2090,9 +2150,20 @@ angle::Result RenderPassCache::addRenderPass(ContextVk *contextVk, ...@@ -2090,9 +2150,20 @@ angle::Result RenderPassCache::addRenderPass(ContextVk *contextVk,
if (desc.hasDepthStencilAttachment()) if (desc.hasDepthStencilAttachment())
{ {
vk::ResourceAccess dsAccess = desc.getDepthStencilAccess();
vk::ImageLayout imageLayout;
if (dsAccess == vk::ResourceAccess::ReadOnly)
{
imageLayout = vk::ImageLayout::DepthStencilReadOnly;
}
else
{
ASSERT(dsAccess == vk::ResourceAccess::Write);
imageLayout = vk::ImageLayout::DepthStencilAttachment;
}
uint32_t depthStencilIndexVk = colorAttachmentCount; uint32_t depthStencilIndexVk = colorAttachmentCount;
ops.initWithLoadStore(depthStencilIndexVk, vk::ImageLayout::DepthStencilAttachment, ops.initWithLoadStore(depthStencilIndexVk, imageLayout, imageLayout);
vk::ImageLayout::DepthStencilAttachment);
} }
return getRenderPassWithOps(contextVk, serial, desc, ops, renderPassOut); return getRenderPassWithOps(contextVk, serial, desc, ops, renderPassOut);
......
...@@ -59,6 +59,13 @@ using RefCountedSamplerYcbcrConversion = RefCounted<SamplerYcbcrConversion>; ...@@ -59,6 +59,13 @@ using RefCountedSamplerYcbcrConversion = RefCounted<SamplerYcbcrConversion>;
// Enable struct padding warnings for the code below since it is used in caches. // Enable struct padding warnings for the code below since it is used in caches.
ANGLE_ENABLE_STRUCT_PADDING_WARNINGS ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
enum ResourceAccess
{
Unused,
ReadOnly,
Write,
};
class alignas(4) RenderPassDesc final class alignas(4) RenderPassDesc final
{ {
public: public:
...@@ -73,18 +80,22 @@ class alignas(4) RenderPassDesc final ...@@ -73,18 +80,22 @@ class alignas(4) RenderPassDesc final
void packColorAttachmentGap(size_t colorIndexGL); void packColorAttachmentGap(size_t colorIndexGL);
// The caller must pack the depth/stencil attachment last, which is packed right after the color // The caller must pack the depth/stencil attachment last, which is packed right after the color
// attachments (including gaps), i.e. with an index starting from |colorAttachmentRange()|. // attachments (including gaps), i.e. with an index starting from |colorAttachmentRange()|.
void packDepthStencilAttachment(angle::FormatID angleFormatID); void packDepthStencilAttachment(angle::FormatID angleFormatID, ResourceAccess access);
// Indicate that a color attachment should have a corresponding resolve attachment. // Indicate that a color attachment should have a corresponding resolve attachment.
void packColorResolveAttachment(size_t colorIndexGL); void packColorResolveAttachment(size_t colorIndexGL);
size_t hash() const; size_t hash() const;
// Color attachments are in [0, colorAttachmentRange()), with possible gaps. // Color attachments are in [0, colorAttachmentRange()), with possible gaps.
size_t colorAttachmentRange() const { return mColorAttachmentRange; } size_t colorAttachmentRange() const;
size_t depthStencilAttachmentIndex() const { return colorAttachmentRange(); } size_t depthStencilAttachmentIndex() const { return colorAttachmentRange(); }
bool isColorAttachmentEnabled(size_t colorIndexGL) const; bool isColorAttachmentEnabled(size_t colorIndexGL) const;
bool hasDepthStencilAttachment() const { return mHasDepthStencilAttachment; } bool hasDepthStencilAttachment() const
{
return getDepthStencilAccess() != ResourceAccess::Unused;
}
ResourceAccess getDepthStencilAccess() const;
bool hasColorResolveAttachment(size_t colorIndexGL) const bool hasColorResolveAttachment(size_t colorIndexGL) const
{ {
return mColorResolveAttachmentMask.test(colorIndexGL); return mColorResolveAttachmentMask.test(colorIndexGL);
...@@ -107,8 +118,12 @@ class alignas(4) RenderPassDesc final ...@@ -107,8 +118,12 @@ class alignas(4) RenderPassDesc final
private: private:
// Store log(samples), to be able to store it in 3 bits. // Store log(samples), to be able to store it in 3 bits.
uint8_t mLogSamples : 3; uint8_t mLogSamples : 3;
uint8_t mColorAttachmentRange : 4;
uint8_t mHasDepthStencilAttachment : 1; // Color attachment count has 9 values: from 0-8 valid attachments. The depths/stencil
// attachment can have 3 values: no depth stencil, read only, and writable depth/stencil.
// We can pack these 9*3 = 27 possible values in 5 bits.
uint8_t mPackedColorAttachmentRangeAndDSAccess : 5;
// Whether each color attachment has a corresponding resolve attachment. Color resolve // Whether each color attachment has a corresponding resolve attachment. Color resolve
// attachments can be used to optimize resolve through glBlitFramebuffer() as well as support // attachments can be used to optimize resolve through glBlitFramebuffer() as well as support
// GL_EXT_multisampled_render_to_texture and GL_EXT_multisampled_render_to_texture2. // GL_EXT_multisampled_render_to_texture and GL_EXT_multisampled_render_to_texture2.
...@@ -900,6 +915,7 @@ class FramebufferDesc ...@@ -900,6 +915,7 @@ class FramebufferDesc
void updateColor(uint32_t index, ImageViewSubresourceSerial serial); void updateColor(uint32_t index, ImageViewSubresourceSerial serial);
void updateColorResolve(uint32_t index, ImageViewSubresourceSerial serial); void updateColorResolve(uint32_t index, ImageViewSubresourceSerial serial);
void updateDepthStencil(ImageViewSubresourceSerial serial); void updateDepthStencil(ImageViewSubresourceSerial serial);
void updateReadOnlyDepth(bool readOnlyDepth);
size_t hash() const; size_t hash() const;
void reset(); void reset();
...@@ -911,7 +927,8 @@ class FramebufferDesc ...@@ -911,7 +927,8 @@ class FramebufferDesc
void update(uint32_t index, ImageViewSubresourceSerial serial); void update(uint32_t index, ImageViewSubresourceSerial serial);
// Note: this is an exclusive index. If there is one index it will be "1". // Note: this is an exclusive index. If there is one index it will be "1".
uint32_t mMaxIndex; uint16_t mMaxIndex;
uint16_t mReadOnlyDepth;
FramebufferAttachmentArray<ImageViewSubresourceSerial> mSerials; FramebufferAttachmentArray<ImageViewSubresourceSerial> mSerials;
}; };
......
...@@ -344,6 +344,20 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -344,6 +344,20 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
}, },
}, },
{ {
ImageLayout::DepthStencilReadOnly,
{
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
kAllShadersPipelineStageFlags | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
kAllShadersPipelineStageFlags | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
// Transition to: all reads and writes must happen after barrier.
VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
// Transition from: all writes must finish before barrier.
0,
BarrierType::ReadOnly,
PipelineStage::EarlyFragmentTest,
},
},
{
ImageLayout::DepthStencilAttachment, ImageLayout::DepthStencilAttachment,
{ {
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
...@@ -902,7 +916,7 @@ void CommandBufferHelper::addCommandDiagnostics(ContextVk *contextVk) ...@@ -902,7 +916,7 @@ void CommandBufferHelper::addCommandDiagnostics(ContextVk *contextVk)
if (mIsRenderPassCommandBuffer) if (mIsRenderPassCommandBuffer)
{ {
size_t attachmentCount = mRenderPassDesc.attachmentCount(); size_t attachmentCount = mRenderPassDesc.attachmentCount();
size_t depthStencilAttachmentCount = mRenderPassDesc.hasDepthStencilAttachment(); size_t depthStencilAttachmentCount = mRenderPassDesc.hasDepthStencilAttachment() ? 1 : 0;
size_t colorAttachmentCount = attachmentCount - depthStencilAttachmentCount; size_t colorAttachmentCount = attachmentCount - depthStencilAttachmentCount;
std::string loadOps, storeOps; std::string loadOps, storeOps;
......
...@@ -1074,6 +1074,7 @@ enum class ImageLayout ...@@ -1074,6 +1074,7 @@ enum class ImageLayout
AllGraphicsShadersReadOnly, AllGraphicsShadersReadOnly,
AllGraphicsShadersWrite, AllGraphicsShadersWrite,
ColorAttachment, ColorAttachment,
DepthStencilReadOnly,
DepthStencilAttachment, DepthStencilAttachment,
Present, Present,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment