Commit 887b1346 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Add resolve/unresolve counters

With this change, render-pass-related counters are calculated at render pass creation time and stored alongside the render pass handle (and serial) in the render pass cache. On every use, the render pass' counters are accumulated over the global counters. Additionally, this change adds MSRTT resolve and unresolve counters to render pass counters. Bug: angleproject:4836 Change-Id: If15a789e5a7d66c7ea5a2315bc76fe045ce57491 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2444099 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 102074d1
...@@ -56,8 +56,7 @@ class DynamicDescriptorPool; ...@@ -56,8 +56,7 @@ class DynamicDescriptorPool;
class ImageHelper; class ImageHelper;
enum class ImageLayout; enum class ImageLayout;
using RenderPassAndSerial = ObjectAndSerial<RenderPass>; using PipelineAndSerial = ObjectAndSerial<Pipeline>;
using PipelineAndSerial = ObjectAndSerial<Pipeline>;
using RefCountedDescriptorSetLayout = RefCounted<DescriptorSetLayout>; using RefCountedDescriptorSetLayout = RefCounted<DescriptorSetLayout>;
using RefCountedPipelineLayout = RefCounted<PipelineLayout>; using RefCountedPipelineLayout = RefCounted<PipelineLayout>;
...@@ -114,6 +113,7 @@ template <typename T> ...@@ -114,6 +113,7 @@ template <typename T>
using FramebufferAttachmentArray = std::array<T, kMaxFramebufferAttachments>; using FramebufferAttachmentArray = std::array<T, kMaxFramebufferAttachments>;
template <typename T> template <typename T>
using FramebufferAttachmentsVector = angle::FixedVector<T, kMaxFramebufferAttachments>; using FramebufferAttachmentsVector = angle::FixedVector<T, kMaxFramebufferAttachments>;
using FramebufferAttachmentMask = angle::BitSet<kMaxFramebufferAttachments>;
constexpr size_t kMaxFramebufferNonResolveAttachments = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1; constexpr size_t kMaxFramebufferNonResolveAttachments = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1;
template <typename T> template <typename T>
...@@ -1139,6 +1139,31 @@ class SamplerHelper final : angle::NonCopyable ...@@ -1139,6 +1139,31 @@ class SamplerHelper final : angle::NonCopyable
using RefCountedSampler = RefCounted<SamplerHelper>; using RefCountedSampler = RefCounted<SamplerHelper>;
using SamplerBinding = BindingPointer<SamplerHelper>; using SamplerBinding = BindingPointer<SamplerHelper>;
class RenderPassHelper final : angle::NonCopyable
{
public:
RenderPassHelper();
~RenderPassHelper();
RenderPassHelper(RenderPassHelper &&other);
RenderPassHelper &operator=(RenderPassHelper &&other);
void destroy(VkDevice device);
const RenderPass &getRenderPass() const;
RenderPass &getRenderPass();
void updateSerial(Serial serial);
const RenderPassPerfCounters &getPerfCounters() const;
RenderPassPerfCounters &getPerfCounters();
private:
RenderPass mRenderPass;
Serial mSerial;
RenderPassPerfCounters mPerfCounters;
};
} // namespace vk } // namespace vk
} // namespace rx } // namespace rx
...@@ -1235,20 +1260,27 @@ class RenderPassCache final : angle::NonCopyable ...@@ -1235,20 +1260,27 @@ class RenderPassCache final : angle::NonCopyable
// Find the first element and return it. // Find the first element and return it.
innerCache.begin()->second.updateSerial(serial); innerCache.begin()->second.updateSerial(serial);
*renderPassOut = &innerCache.begin()->second.get(); *renderPassOut = &innerCache.begin()->second.getRenderPass();
return angle::Result::Continue; return angle::Result::Continue;
} }
return addRenderPass(contextVk, serial, desc, renderPassOut); return addRenderPass(contextVk, serial, desc, renderPassOut);
} }
angle::Result getRenderPassWithOps(vk::Context *context, angle::Result getRenderPassWithOps(ContextVk *contextVk,
Serial serial, Serial serial,
const vk::RenderPassDesc &desc, const vk::RenderPassDesc &desc,
const vk::AttachmentOpsArray &attachmentOps, const vk::AttachmentOpsArray &attachmentOps,
vk::RenderPass **renderPassOut); vk::RenderPass **renderPassOut);
private: private:
angle::Result getRenderPassWithOpsImpl(ContextVk *contextVk,
Serial serial,
const vk::RenderPassDesc &desc,
const vk::AttachmentOpsArray &attachmentOps,
bool updatePerfCounters,
vk::RenderPass **renderPassOut);
angle::Result addRenderPass(ContextVk *contextVk, angle::Result addRenderPass(ContextVk *contextVk,
Serial serial, Serial serial,
const vk::RenderPassDesc &desc, const vk::RenderPassDesc &desc,
...@@ -1256,7 +1288,7 @@ class RenderPassCache final : angle::NonCopyable ...@@ -1256,7 +1288,7 @@ class RenderPassCache final : angle::NonCopyable
// Use a two-layer caching scheme. The top level matches the "compatible" RenderPass elements. // Use a two-layer caching scheme. The top level matches the "compatible" RenderPass elements.
// The second layer caches the attachment load/store ops and initial/final layout. // The second layer caches the attachment load/store ops and initial/final layout.
using InnerCache = std::unordered_map<vk::AttachmentOpsArray, vk::RenderPassAndSerial>; using InnerCache = std::unordered_map<vk::AttachmentOpsArray, vk::RenderPassHelper>;
using OuterCache = std::unordered_map<vk::RenderPassDesc, InnerCache>; using OuterCache = std::unordered_map<vk::RenderPassDesc, InnerCache>;
OuterCache mPayload; OuterCache mPayload;
......
...@@ -1032,19 +1032,6 @@ void CommandBufferHelper::endRenderPass(ContextVk *contextVk) ...@@ -1032,19 +1032,6 @@ void CommandBufferHelper::endRenderPass(ContextVk *contextVk)
// Ensure we don't write to a read-only RenderPass. (ReadOnly -> !Write) // Ensure we don't write to a read-only RenderPass. (ReadOnly -> !Write)
ASSERT(!mReadOnlyDepthStencilMode || mDepthAccess != ResourceAccess::Write); ASSERT(!mReadOnlyDepthStencilMode || mDepthAccess != ResourceAccess::Write);
// Fill out perf counters
PerfCounters &counters = contextVk->getPerfCounters();
counters.depthClears += dsOps.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
counters.depthLoads += dsOps.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
counters.depthStores += dsOps.storeOp == VK_ATTACHMENT_STORE_OP_STORE ? 1 : 0;
counters.stencilClears += dsOps.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR ? 1 : 0;
counters.stencilLoads += dsOps.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD ? 1 : 0;
counters.stencilStores += dsOps.stencilStoreOp == VK_ATTACHMENT_STORE_OP_STORE ? 1 : 0;
counters.readOnlyDepthStencilRenderPasses +=
static_cast<ImageLayout>(dsOps.finalLayout) == vk::ImageLayout::DepthStencilReadOnly ? 1
: 0;
} }
void CommandBufferHelper::beginTransformFeedback(size_t validBufferCount, void CommandBufferHelper::beginTransformFeedback(size_t validBufferCount,
......
...@@ -1215,7 +1215,7 @@ class CommandBufferHelper : angle::NonCopyable ...@@ -1215,7 +1215,7 @@ class CommandBufferHelper : angle::NonCopyable
enum class ImageLayout enum class ImageLayout
{ {
Undefined = 0, Undefined = 0,
// Framebuffer attachment layouts are placed first, so they could fit in fewer bits in // Framebuffer attachment layouts are placed first, so they can fit in fewer bits in
// PackedAttachmentOpsDesc. // PackedAttachmentOpsDesc.
ColorAttachment, ColorAttachment,
DepthStencilReadOnly, DepthStencilReadOnly,
......
...@@ -773,6 +773,27 @@ class ResourceSerialFactory final : angle::NonCopyable ...@@ -773,6 +773,27 @@ class ResourceSerialFactory final : angle::NonCopyable
}; };
// Performance and resource counters. // Performance and resource counters.
struct RenderPassPerfCounters
{
// load/storeOps. Includes ops for resolve attachment. Maximum value = 2.
uint8_t depthClears;
uint8_t depthLoads;
uint8_t depthStores;
uint8_t stencilClears;
uint8_t stencilLoads;
uint8_t stencilStores;
// Number of unresolve and resolve operations. Maximum value for color =
// gl::IMPLEMENTATION_MAX_DRAW_BUFFERS and for depth/stencil = 1 each.
uint8_t colorAttachmentUnresolves;
uint8_t colorAttachmentResolves;
uint8_t depthAttachmentUnresolves;
uint8_t depthAttachmentResolves;
uint8_t stencilAttachmentUnresolves;
uint8_t stencilAttachmentResolves;
// Whether the depth/stencil attachment is using a read-only layout.
uint8_t readOnlyDepthStencil;
};
struct PerfCounters struct PerfCounters
{ {
uint32_t primaryBuffers; uint32_t primaryBuffers;
...@@ -786,6 +807,12 @@ struct PerfCounters ...@@ -786,6 +807,12 @@ struct PerfCounters
uint32_t stencilClears; uint32_t stencilClears;
uint32_t stencilLoads; uint32_t stencilLoads;
uint32_t stencilStores; uint32_t stencilStores;
uint32_t colorAttachmentUnresolves;
uint32_t depthAttachmentUnresolves;
uint32_t stencilAttachmentUnresolves;
uint32_t colorAttachmentResolves;
uint32_t depthAttachmentResolves;
uint32_t stencilAttachmentResolves;
uint32_t readOnlyDepthStencilRenderPasses; uint32_t readOnlyDepthStencilRenderPasses;
}; };
......
...@@ -94,15 +94,6 @@ class VulkanPerformanceCounterTest : public ANGLETest ...@@ -94,15 +94,6 @@ class VulkanPerformanceCounterTest : public ANGLETest
expected->stencilStores = counters.stencilStores + incrementalStencilStores; expected->stencilStores = counters.stencilStores + incrementalStencilStores;
} }
void setAndIncrementLoadCountersForInvalidateTest(const rx::vk::PerfCounters &counters,
uint32_t incrementalDepthLoads,
uint32_t incrementalStencilLoads,
rx::vk::PerfCounters *expected)
{
expected->depthLoads = counters.depthLoads + incrementalDepthLoads;
expected->stencilLoads = counters.stencilLoads + incrementalStencilLoads;
}
void compareDepthStencilCountersForInvalidateTest(const rx::vk::PerfCounters &counters, void compareDepthStencilCountersForInvalidateTest(const rx::vk::PerfCounters &counters,
const rx::vk::PerfCounters &expected) const rx::vk::PerfCounters &expected)
{ {
...@@ -114,12 +105,60 @@ class VulkanPerformanceCounterTest : public ANGLETest ...@@ -114,12 +105,60 @@ class VulkanPerformanceCounterTest : public ANGLETest
EXPECT_EQ(expected.stencilStores, counters.stencilStores); EXPECT_EQ(expected.stencilStores, counters.stencilStores);
} }
void setAndIncrementLoadCountersForInvalidateTest(const rx::vk::PerfCounters &counters,
uint32_t incrementalDepthLoads,
uint32_t incrementalStencilLoads,
rx::vk::PerfCounters *expected)
{
expected->depthLoads = counters.depthLoads + incrementalDepthLoads;
expected->stencilLoads = counters.stencilLoads + incrementalStencilLoads;
}
void compareLoadCountersForInvalidateTest(const rx::vk::PerfCounters &counters, void compareLoadCountersForInvalidateTest(const rx::vk::PerfCounters &counters,
const rx::vk::PerfCounters &expected) const rx::vk::PerfCounters &expected)
{ {
EXPECT_EQ(expected.depthLoads, counters.depthLoads); EXPECT_EQ(expected.depthLoads, counters.depthLoads);
EXPECT_EQ(expected.stencilLoads, counters.stencilLoads); EXPECT_EQ(expected.stencilLoads, counters.stencilLoads);
} }
void setExpectedCountersForUnresolveResolveTest(const rx::vk::PerfCounters &counters,
uint32_t incrementalColorAttachmentUnresolves,
uint32_t incrementalDepthAttachmentUnresolves,
uint32_t incrementalStencilAttachmentUnresolves,
uint32_t incrementalColorAttachmentResolves,
uint32_t incrementalDepthAttachmentResolves,
uint32_t incrementalStencilAttachmentResolves,
rx::vk::PerfCounters *expected)
{
expected->colorAttachmentUnresolves =
counters.colorAttachmentUnresolves + incrementalColorAttachmentUnresolves;
expected->depthAttachmentUnresolves =
counters.depthAttachmentUnresolves + incrementalDepthAttachmentUnresolves;
expected->stencilAttachmentUnresolves =
counters.stencilAttachmentUnresolves + incrementalStencilAttachmentUnresolves;
expected->colorAttachmentResolves =
counters.colorAttachmentResolves + incrementalColorAttachmentResolves;
expected->depthAttachmentResolves =
counters.depthAttachmentResolves + incrementalDepthAttachmentResolves;
expected->stencilAttachmentResolves =
counters.stencilAttachmentResolves + incrementalStencilAttachmentResolves;
}
void compareCountersForUnresolveResolveTest(const rx::vk::PerfCounters &counters,
const rx::vk::PerfCounters &expected)
{
EXPECT_EQ(expected.colorAttachmentUnresolves, counters.colorAttachmentUnresolves);
EXPECT_EQ(expected.depthAttachmentUnresolves, counters.depthAttachmentUnresolves);
if (counters.stencilAttachmentUnresolves != 0)
{
// Allow stencil unresolves to be 0. If VK_EXT_shader_stencil_export is not supported,
// stencil unresolve is impossible.
EXPECT_EQ(expected.stencilAttachmentUnresolves, counters.stencilAttachmentUnresolves);
}
EXPECT_EQ(expected.colorAttachmentResolves, counters.colorAttachmentResolves);
EXPECT_EQ(expected.depthAttachmentResolves, counters.depthAttachmentResolves);
EXPECT_EQ(expected.stencilAttachmentResolves, counters.stencilAttachmentResolves);
}
}; };
class VulkanPerformanceCounterTest_ES31 : public VulkanPerformanceCounterTest class VulkanPerformanceCounterTest_ES31 : public VulkanPerformanceCounterTest
...@@ -1700,11 +1739,19 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilRenderbufferShou ...@@ -1700,11 +1739,19 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilRenderbufferShou
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture")); ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
const rx::vk::PerfCounters &counters = hackANGLE(); const rx::vk::PerfCounters &counters = hackANGLE();
uint32_t expectedDepthClearCount = counters.depthClears + 1; rx::vk::PerfCounters expected;
uint32_t expectedDepthLoadCount = counters.depthLoads;
uint32_t expectedStencilClearCount = counters.stencilClears + 1; // This test creates 4 render passes. In the first render pass, color, depth and stencil are
uint32_t expectedStencilLoadCountMin = counters.stencilLoads; // cleared. In the following render passes, they must be loaded. However, given that the
uint32_t expectedStencilLoadCountMax = counters.stencilLoads + 4; // attachments are multisampled-render-to-texture, loads are done through an unresolve
// operation. All 4 render passes resolve the attachments.
// Expect rpCount+4, depth(Clears+1, Loads+3, Stores+3), stencil(Clears+1, Load+3, Stores+3).
// Note that the Loads and Stores are from the resolve attachments.
setExpectedCountersForInvalidateTest(counters, 4, 1, 3, 3, 1, 3, 3, &expected);
// Additionally, expect 4 resolves and 3 unresolves.
setExpectedCountersForUnresolveResolveTest(counters, 3, 3, 3, 4, 4, 4, &expected);
GLFramebuffer FBO; GLFramebuffer FBO;
glBindFramebuffer(GL_FRAMEBUFFER, FBO); glBindFramebuffer(GL_FRAMEBUFFER, FBO);
...@@ -1733,11 +1780,11 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilRenderbufferShou ...@@ -1733,11 +1780,11 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilRenderbufferShou
glBindTexture(GL_TEXTURE_2D, copyTex); glBindTexture(GL_TEXTURE_2D, copyTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
// Set viewport and clear depth // Set viewport and clear color, depth and stencil
glViewport(0, 0, kSize, kSize); glViewport(0, 0, kSize, kSize);
glClearDepthf(1); glClearDepthf(1);
glClearStencil(0x55); glClearStencil(0x55);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// If depth is not cleared to 1, rendering would fail. // If depth is not cleared to 1, rendering would fail.
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
...@@ -1793,11 +1840,8 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilRenderbufferShou ...@@ -1793,11 +1840,8 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilRenderbufferShou
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
// Verify the counters // Verify the counters
EXPECT_EQ(counters.depthClears, expectedDepthClearCount); compareLoadCountersForInvalidateTest(counters, expected);
EXPECT_EQ(counters.depthLoads, expectedDepthLoadCount); compareCountersForUnresolveResolveTest(counters, expected);
EXPECT_EQ(counters.stencilClears, expectedStencilClearCount);
EXPECT_GE(counters.stencilLoads, expectedStencilLoadCountMin);
EXPECT_LE(counters.stencilLoads, expectedStencilLoadCountMax);
// Verify that copies were done correctly. // Verify that copies were done correctly.
GLFramebuffer verifyFBO; GLFramebuffer verifyFBO;
......
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