Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit cd4b8cc

Browse files
author
Jonah Williams
authored
[Impeller] correct multisample resolve/store configuration for Vulkan. (#51740)
Added tests for #50374 This makes RenderDoc replays work a whole lot better since all of the offscreen textures aren't cleared with DONT CARE. Fixes flutter/flutter#142947
1 parent b3516c4 commit cd4b8cc

File tree

3 files changed

+70
-14
lines changed

3 files changed

+70
-14
lines changed

impeller/renderer/backend/vulkan/formats_vk.h

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,18 +311,39 @@ constexpr vk::AttachmentLoadOp ToVKAttachmentLoadOp(LoadAction load_action) {
311311
FML_UNREACHABLE();
312312
}
313313

314-
constexpr vk::AttachmentStoreOp ToVKAttachmentStoreOp(
315-
StoreAction store_action) {
314+
constexpr vk::AttachmentStoreOp ToVKAttachmentStoreOp(StoreAction store_action,
315+
bool is_resolve_texture) {
316316
switch (store_action) {
317317
case StoreAction::kStore:
318+
// Both MSAA and resolve textures need to be stored. A resolve is NOT
319+
// performed.
318320
return vk::AttachmentStoreOp::eStore;
319321
case StoreAction::kDontCare:
322+
// Both MSAA and resolve textures can be discarded. A resolve is NOT
323+
// performed.
320324
return vk::AttachmentStoreOp::eDontCare;
321325
case StoreAction::kMultisampleResolve:
326+
// The resolve texture is stored but the MSAA texture can be discarded. A
327+
// resolve IS performed.
328+
return is_resolve_texture ? vk::AttachmentStoreOp::eStore
329+
: vk::AttachmentStoreOp::eDontCare;
322330
case StoreAction::kStoreAndMultisampleResolve:
323-
return vk::AttachmentStoreOp::eDontCare;
331+
// Both MSAA and resolve textures need to be stored. A resolve IS
332+
// performed.
333+
return vk::AttachmentStoreOp::eStore;
324334
}
335+
FML_UNREACHABLE();
336+
}
325337

338+
constexpr bool StoreActionPerformsResolve(StoreAction store_action) {
339+
switch (store_action) {
340+
case StoreAction::kDontCare:
341+
case StoreAction::kStore:
342+
return false;
343+
case StoreAction::kMultisampleResolve:
344+
case StoreAction::kStoreAndMultisampleResolve:
345+
return true;
346+
}
326347
FML_UNREACHABLE();
327348
}
328349

impeller/renderer/backend/vulkan/render_pass_builder_vk.cc

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
#include "impeller/renderer/backend/vulkan/render_pass_builder_vk.h"
66

7-
#include <algorithm>
87
#include <vector>
98

109
#include "impeller/renderer/backend/vulkan/formats_vk.h"
@@ -37,16 +36,20 @@ RenderPassBuilderVK& RenderPassBuilderVK::SetColorAttachment(
3736
desc.format = ToVKImageFormat(format);
3837
desc.samples = ToVKSampleCount(sample_count);
3938
desc.loadOp = ToVKAttachmentLoadOp(load_action);
40-
desc.storeOp = ToVKAttachmentStoreOp(store_action);
39+
desc.storeOp = ToVKAttachmentStoreOp(store_action, false);
4140
desc.stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
4241
desc.stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
4342
desc.initialLayout = vk::ImageLayout::eGeneral;
4443
desc.finalLayout = vk::ImageLayout::eGeneral;
4544
colors_[index] = desc;
4645

47-
desc.samples = vk::SampleCountFlagBits::e1;
48-
resolves_[index] = desc;
49-
46+
if (StoreActionPerformsResolve(store_action)) {
47+
desc.storeOp = ToVKAttachmentStoreOp(store_action, true);
48+
desc.samples = vk::SampleCountFlagBits::e1;
49+
resolves_[index] = desc;
50+
} else {
51+
resolves_.erase(index);
52+
}
5053
return *this;
5154
}
5255

@@ -59,7 +62,7 @@ RenderPassBuilderVK& RenderPassBuilderVK::SetDepthStencilAttachment(
5962
desc.format = ToVKImageFormat(format);
6063
desc.samples = ToVKSampleCount(sample_count);
6164
desc.loadOp = ToVKAttachmentLoadOp(load_action);
62-
desc.storeOp = ToVKAttachmentStoreOp(store_action);
65+
desc.storeOp = ToVKAttachmentStoreOp(store_action, false);
6366
desc.stencilLoadOp = desc.loadOp; // Not separable in Impeller.
6467
desc.stencilStoreOp = desc.storeOp; // Not separable in Impeller.
6568
desc.initialLayout = vk::ImageLayout::eUndefined;
@@ -79,7 +82,7 @@ RenderPassBuilderVK& RenderPassBuilderVK::SetStencilAttachment(
7982
desc.loadOp = vk::AttachmentLoadOp::eDontCare;
8083
desc.storeOp = vk::AttachmentStoreOp::eDontCare;
8184
desc.stencilLoadOp = ToVKAttachmentLoadOp(load_action);
82-
desc.stencilStoreOp = ToVKAttachmentStoreOp(store_action);
85+
desc.stencilStoreOp = ToVKAttachmentStoreOp(store_action, false);
8386
desc.initialLayout = vk::ImageLayout::eUndefined;
8487
desc.finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
8588
depth_stencil_ = desc;
@@ -88,8 +91,6 @@ RenderPassBuilderVK& RenderPassBuilderVK::SetStencilAttachment(
8891

8992
vk::UniqueRenderPass RenderPassBuilderVK::Build(
9093
const vk::Device& device) const {
91-
FML_DCHECK(colors_.size() == resolves_.size());
92-
9394
// This must be less than `VkPhysicalDeviceLimits::maxColorAttachments` but we
9495
// are not checking.
9596
const auto color_attachments_count =
@@ -110,12 +111,12 @@ vk::UniqueRenderPass RenderPassBuilderVK::Build(
110111
color_refs[color.first] = color_ref;
111112
attachments.push_back(color.second);
112113

113-
if (color.second.samples != vk::SampleCountFlagBits::e1) {
114+
if (auto found = resolves_.find(color.first); found != resolves_.end()) {
114115
vk::AttachmentReference resolve_ref;
115116
resolve_ref.attachment = attachments.size();
116117
resolve_ref.layout = vk::ImageLayout::eGeneral;
117118
resolve_refs[color.first] = resolve_ref;
118-
attachments.push_back(resolves_.at(color.first));
119+
attachments.push_back(found->second);
119120
}
120121
}
121122

impeller/renderer/backend/vulkan/render_pass_builder_vk_unittests.cc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,5 +99,39 @@ TEST(RenderPassBuilder, CreatesRenderPassWithOnlyStencil) {
9999
EXPECT_EQ(depth_stencil.stencilStoreOp, vk::AttachmentStoreOp::eDontCare);
100100
}
101101

102+
TEST(RenderPassBuilder, CreatesMSAAResolveWithCorrectStore) {
103+
RenderPassBuilderVK builder = RenderPassBuilderVK();
104+
auto const context = MockVulkanContextBuilder().Build();
105+
106+
// Create an MSAA color attachment.
107+
builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
108+
SampleCount::kCount4, LoadAction::kClear,
109+
StoreAction::kMultisampleResolve);
110+
111+
auto render_pass = builder.Build(context->GetDevice());
112+
113+
EXPECT_TRUE(!!render_pass);
114+
115+
auto maybe_color = builder.GetColorAttachments().find(0u);
116+
ASSERT_NE(maybe_color, builder.GetColorAttachments().end());
117+
auto color = maybe_color->second;
118+
119+
// MSAA Texture.
120+
EXPECT_EQ(color.initialLayout, vk::ImageLayout::eGeneral);
121+
EXPECT_EQ(color.finalLayout, vk::ImageLayout::eGeneral);
122+
EXPECT_EQ(color.loadOp, vk::AttachmentLoadOp::eClear);
123+
EXPECT_EQ(color.storeOp, vk::AttachmentStoreOp::eDontCare);
124+
125+
auto maybe_resolve = builder.GetResolves().find(0u);
126+
ASSERT_NE(maybe_resolve, builder.GetResolves().end());
127+
auto resolve = maybe_resolve->second;
128+
129+
// MSAA Resolve Texture.
130+
EXPECT_EQ(resolve.initialLayout, vk::ImageLayout::eGeneral);
131+
EXPECT_EQ(resolve.finalLayout, vk::ImageLayout::eGeneral);
132+
EXPECT_EQ(resolve.loadOp, vk::AttachmentLoadOp::eClear);
133+
EXPECT_EQ(resolve.storeOp, vk::AttachmentStoreOp::eStore);
134+
}
135+
102136
} // namespace testing
103137
} // namespace impeller

0 commit comments

Comments
 (0)