Skip to content

Commit

Permalink
[Impeller] Use MSAA attachments for offscreen passes (flutter#35648)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdero authored Aug 24, 2022
1 parent 59a61b2 commit 55c461f
Show file tree
Hide file tree
Showing 16 changed files with 189 additions and 27 deletions.
7 changes: 6 additions & 1 deletion impeller/entity/contents/content_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,12 @@ std::shared_ptr<Texture> ContentContext::MakeSubpass(
SubpassCallback subpass_callback) const {
auto context = GetContext();

auto subpass_target = RenderTarget::CreateOffscreen(*context, texture_size);
RenderTarget subpass_target;
if (context->SupportsOffscreenMSAA()) {
subpass_target = RenderTarget::CreateOffscreenMSAA(*context, texture_size);
} else {
subpass_target = RenderTarget::CreateOffscreen(*context, texture_size);
}
auto subpass_texture = subpass_target.GetRenderTargetTexture();
if (!subpass_texture) {
return nullptr;
Expand Down
51 changes: 36 additions & 15 deletions impeller/entity/entity_pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,18 @@ EntityPass* EntityPass::AddSubpass(std::unique_ptr<EntityPass> pass) {
bool EntityPass::Render(ContentContext& renderer,
RenderTarget render_target) const {
if (reads_from_pass_texture_) {
auto offscreen_target = RenderTarget::CreateOffscreen(
*renderer.GetContext(), render_target.GetRenderTargetSize(),
"EntityPass", //
StorageMode::kDevicePrivate, LoadAction::kClear, StoreAction::kStore,
StorageMode::kDevicePrivate, LoadAction::kClear, StoreAction::kStore);
auto offscreen_target = RenderTarget::CreateOffscreenMSAA(
*renderer.GetContext(), // context
render_target.GetRenderTargetSize(), // size
"EntityPass", // label
StorageMode::kDevicePrivate, // color_storage_mode
StorageMode::kDevicePrivate, // color_resolve_storage_mode
LoadAction::kClear, // color_load_action
StoreAction::kStoreAndMultisampleResolve, // color_store_action
StorageMode::kDevicePrivate, // stencil_storage_mode
LoadAction::kClear, // stencil_load_action
StoreAction::kStore // stencil_store_action
);
if (!OnRender(renderer, offscreen_target.GetRenderTargetSize(),
offscreen_target, Point(), Point(), 0)) {
return false;
Expand Down Expand Up @@ -285,17 +292,31 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(

RenderTarget subpass_target;
if (subpass->reads_from_pass_texture_) {
subpass_target = RenderTarget::CreateOffscreen(
*renderer.GetContext(), ISize::Ceil(subpass_coverage->size),
"EntityPass", StorageMode::kDevicePrivate, LoadAction::kClear,
StoreAction::kStore, StorageMode::kDevicePrivate, LoadAction::kClear,
StoreAction::kStore);
subpass_target = RenderTarget::CreateOffscreenMSAA(
*renderer.GetContext(), // context
ISize::Ceil(subpass_coverage->size), // size
"EntityPass", // label
StorageMode::kDevicePrivate, // color_storage_mode
StorageMode::kDevicePrivate, // color_resolve_storage_mode
LoadAction::kClear, // color_load_action
StoreAction::kStoreAndMultisampleResolve, // color_store_action
StorageMode::kDevicePrivate, // stencil_storage_mode
LoadAction::kClear, // stencil_load_action
StoreAction::kStore // stencil_store_action
);
} else {
subpass_target = RenderTarget::CreateOffscreen(
*renderer.GetContext(), ISize::Ceil(subpass_coverage->size),
"EntityPass", StorageMode::kDevicePrivate, LoadAction::kClear,
StoreAction::kStore, StorageMode::kDeviceTransient,
LoadAction::kClear, StoreAction::kDontCare);
subpass_target = RenderTarget::CreateOffscreenMSAA(
*renderer.GetContext(), // context
ISize::Ceil(subpass_coverage->size), // size
"EntityPass", // label
StorageMode::kDevicePrivate, // color_storage_mode
StorageMode::kDevicePrivate, // color_resolve_storage_mode
LoadAction::kClear, // color_load_action
StoreAction::kStoreAndMultisampleResolve, // color_store_action
StorageMode::kDeviceTransient, // stencil_storage_mode
LoadAction::kClear, // stencil_load_action
StoreAction::kDontCare // stencil_store_action
);
}

auto subpass_texture = subpass_target.GetRenderTargetTexture();
Expand Down
3 changes: 1 addition & 2 deletions impeller/entity/inline_pass_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ std::shared_ptr<Texture> InlinePassContext::GetTexture() {
if (!IsValid()) {
return nullptr;
}
auto color0 = render_target_.GetColorAttachments().find(0)->second;
return color0.resolve_texture ? color0.resolve_texture : color0.texture;
return render_target_.GetRenderTargetTexture();
}

bool InlinePassContext::EndPass() {
Expand Down
5 changes: 5 additions & 0 deletions impeller/renderer/backend/gles/context_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,9 @@ bool ContextGLES::HasThreadingRestrictions() const {
return true;
}

// |Context|
bool ContextGLES::SupportsOffscreenMSAA() const {
return false;
}

} // namespace impeller
3 changes: 3 additions & 0 deletions impeller/renderer/backend/gles/context_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ class ContextGLES final : public Context,
// |Context|
bool HasThreadingRestrictions() const override;

// |Context|
bool SupportsOffscreenMSAA() const override;

FML_DISALLOW_COPY_AND_ASSIGN(ContextGLES);
};

Expand Down
3 changes: 3 additions & 0 deletions impeller/renderer/backend/metal/context_mtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ class ContextMTL final : public Context,
// |Context|
std::shared_ptr<WorkQueue> GetWorkQueue() const override;

// |Context|
bool SupportsOffscreenMSAA() const override;

std::shared_ptr<CommandBuffer> CreateCommandBufferInQueue(
id<MTLCommandQueue> queue) const;

Expand Down
5 changes: 5 additions & 0 deletions impeller/renderer/backend/metal/context_mtl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -232,4 +232,9 @@
return device_;
}

// |Context|
bool ContextMTL::SupportsOffscreenMSAA() const {
return true;
}

} // namespace impeller
4 changes: 4 additions & 0 deletions impeller/renderer/backend/metal/formats_mtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@ constexpr MTLStoreAction ToMTLStoreAction(StoreAction action) {
return MTLStoreActionStore;
case StoreAction::kMultisampleResolve:
return MTLStoreActionMultisampleResolve;
case StoreAction::kStoreAndMultisampleResolve:
return MTLStoreActionStoreAndMultisampleResolve;
}
return MTLStoreActionDontCare;
}
Expand All @@ -259,6 +261,8 @@ constexpr StoreAction FromMTLStoreAction(MTLStoreAction action) {
return StoreAction::kStore;
case MTLStoreActionMultisampleResolve:
return StoreAction::kMultisampleResolve;
case MTLStoreActionStoreAndMultisampleResolve:
return StoreAction::kStoreAndMultisampleResolve;
default:
break;
}
Expand Down
14 changes: 8 additions & 6 deletions impeller/renderer/backend/metal/render_pass_mtl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,19 @@
static bool ConfigureResolveTextureAttachment(
const Attachment& desc,
MTLRenderPassAttachmentDescriptor* attachment) {
if (desc.store_action == StoreAction::kMultisampleResolve &&
!desc.resolve_texture) {
bool needs_resolve =
desc.store_action == StoreAction::kMultisampleResolve ||
desc.store_action == StoreAction::kStoreAndMultisampleResolve;

if (needs_resolve && !desc.resolve_texture) {
VALIDATION_LOG << "Resolve store action specified on attachment but no "
"resolve texture was specified.";
return false;
}

if (desc.resolve_texture &&
desc.store_action != StoreAction::kMultisampleResolve) {
VALIDATION_LOG << "Resolve store action specified but there was no "
"resolve attachment.";
if (desc.resolve_texture && !needs_resolve) {
VALIDATION_LOG << "A resolve texture was specified even though the store "
"action doesn't require it.";
return false;
}

Expand Down
4 changes: 4 additions & 0 deletions impeller/renderer/backend/vulkan/context_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -501,4 +501,8 @@ void ContextVK::SetupSwapchain(vk::UniqueSurfaceKHR surface) {
});
}

bool ContextVK::SupportsOffscreenMSAA() const {
return true;
}

} // namespace impeller
3 changes: 3 additions & 0 deletions impeller/renderer/backend/vulkan/context_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ class ContextVK final : public Context, public BackendCast<ContextVK, Context> {
// |Context|
std::shared_ptr<WorkQueue> GetWorkQueue() const override;

// |Context|
bool SupportsOffscreenMSAA() const override;

FML_DISALLOW_COPY_AND_ASSIGN(ContextVK);
};

Expand Down
1 change: 1 addition & 0 deletions impeller/renderer/backend/vulkan/formats_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ constexpr vk::AttachmentStoreOp ToVKAttachmentStoreOp(
case StoreAction::kDontCare:
return vk::AttachmentStoreOp::eDontCare;
case StoreAction::kMultisampleResolve:
case StoreAction::kStoreAndMultisampleResolve:
// TODO (kaushikiska): vulkan doesn't support multisample resolve.
return vk::AttachmentStoreOp::eDontCare;
}
Expand Down
2 changes: 2 additions & 0 deletions impeller/renderer/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class Context : public std::enable_shared_from_this<Context> {

virtual bool HasThreadingRestrictions() const;

virtual bool SupportsOffscreenMSAA() const = 0;

protected:
Context();

Expand Down
2 changes: 2 additions & 0 deletions impeller/renderer/formats.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ enum class StoreAction {
kDontCare,
kStore,
kMultisampleResolve,
kStoreAndMultisampleResolve,
};

constexpr bool CanClearAttachment(LoadAction action) {
Expand All @@ -115,6 +116,7 @@ constexpr bool CanClearAttachment(LoadAction action) {
constexpr bool CanDiscardAttachmentWhenDone(StoreAction action) {
switch (action) {
case StoreAction::kStore:
case StoreAction::kStoreAndMultisampleResolve:
return false;
case StoreAction::kDontCare:
case StoreAction::kMultisampleResolve:
Expand Down
97 changes: 94 additions & 3 deletions impeller/renderer/render_target.cc
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ std::shared_ptr<Texture> RenderTarget::GetRenderTargetTexture() const {
if (found == colors_.end()) {
return nullptr;
}
return found->second.texture;
return found->second.resolve_texture ? found->second.resolve_texture
: found->second.texture;
}

RenderTarget& RenderTarget::SetColorAttachment(ColorAttachment attachment,
Expand Down Expand Up @@ -211,7 +212,7 @@ RenderTarget RenderTarget::CreateOffscreen(const Context& context,
return {};
}

color0.texture->SetLabel(SPrintF("%sColorTexture", label.c_str()));
color0.texture->SetLabel(SPrintF("%s Color Texture", label.c_str()));

StencilAttachment stencil0;
stencil0.load_action = stencil_load_action;
Expand All @@ -224,7 +225,97 @@ RenderTarget RenderTarget::CreateOffscreen(const Context& context,
return {};
}

stencil0.texture->SetLabel(SPrintF("%sStencilTexture", label.c_str()));
stencil0.texture->SetLabel(SPrintF("%s Stencil Texture", label.c_str()));

RenderTarget target;
target.SetColorAttachment(std::move(color0), 0u);
target.SetStencilAttachment(std::move(stencil0));

return target;
}

RenderTarget RenderTarget::CreateOffscreenMSAA(
const Context& context,
ISize size,
std::string label,
StorageMode color_storage_mode,
StorageMode color_resolve_storage_mode,
LoadAction color_load_action,
StoreAction color_store_action,
StorageMode stencil_storage_mode,
LoadAction stencil_load_action,
StoreAction stencil_store_action) {
if (size.IsEmpty()) {
return {};
}

// Create MSAA color texture.

TextureDescriptor color0_tex_desc;
color0_tex_desc.type = TextureType::kTexture2DMultisample;
color0_tex_desc.sample_count = SampleCount::kCount4;
color0_tex_desc.format = PixelFormat::kDefaultColor;
color0_tex_desc.size = size;
color0_tex_desc.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget) |
static_cast<uint64_t>(TextureUsage::kShaderRead);

auto color0_msaa_tex = context.GetResourceAllocator()->CreateTexture(
color_storage_mode, color0_tex_desc);
if (!color0_msaa_tex) {
VALIDATION_LOG << "Could not create multisample color texture.";
return {};
}
color0_msaa_tex->SetLabel(
SPrintF("%s Color Texture (Multisample)", label.c_str()));

// Create color resolve texture.

TextureDescriptor color0_resolve_tex_desc;
color0_resolve_tex_desc.format = PixelFormat::kDefaultColor;
color0_resolve_tex_desc.size = size;
color0_resolve_tex_desc.usage =
static_cast<uint64_t>(TextureUsage::kRenderTarget) |
static_cast<uint64_t>(TextureUsage::kShaderRead);

auto color0_resolve_tex = context.GetResourceAllocator()->CreateTexture(
color_resolve_storage_mode, color0_resolve_tex_desc);
if (!color0_resolve_tex) {
VALIDATION_LOG << "Could not create color texture.";
return {};
}
color0_resolve_tex->SetLabel(SPrintF("%s Color Texture", label.c_str()));

// Color attachment.

ColorAttachment color0;
color0.clear_color = Color::BlackTransparent();
color0.load_action = color_load_action;
color0.store_action = color_store_action;
color0.texture = color0_msaa_tex;
color0.resolve_texture = color0_resolve_tex;

// Create MSAA stencil texture.

TextureDescriptor stencil_tex0;
stencil_tex0.type = TextureType::kTexture2DMultisample;
stencil_tex0.sample_count = SampleCount::kCount4;
stencil_tex0.format = PixelFormat::kDefaultStencil;
stencil_tex0.size = size;
stencil_tex0.usage =
static_cast<TextureUsageMask>(TextureUsage::kRenderTarget);

StencilAttachment stencil0;
stencil0.load_action = stencil_load_action;
stencil0.store_action = stencil_store_action;
stencil0.clear_stencil = 0u;
stencil0.texture = context.GetResourceAllocator()->CreateTexture(
stencil_storage_mode, stencil_tex0);

if (!stencil0.texture) {
return {};
}

stencil0.texture->SetLabel(SPrintF("%s Stencil Texture", label.c_str()));

RenderTarget target;
target.SetColorAttachment(std::move(color0), 0u);
Expand Down
12 changes: 12 additions & 0 deletions impeller/renderer/render_target.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@ class RenderTarget {
LoadAction stencil_load_action = LoadAction::kClear,
StoreAction stencil_store_action = StoreAction::kDontCare);

static RenderTarget CreateOffscreenMSAA(
const Context& context,
ISize size,
std::string label = "Offscreen MSAA",
StorageMode color_storage_mode = StorageMode::kDeviceTransient,
StorageMode color_resolve_storage_mode = StorageMode::kDevicePrivate,
LoadAction color_load_action = LoadAction::kClear,
StoreAction color_store_action = StoreAction::kMultisampleResolve,
StorageMode stencil_storage_mode = StorageMode::kDeviceTransient,
LoadAction stencil_load_action = LoadAction::kClear,
StoreAction stencil_store_action = StoreAction::kDontCare);

RenderTarget();

~RenderTarget();
Expand Down

0 comments on commit 55c461f

Please sign in to comment.