[Impeller] cache render target properties on Render Pass. (flutter/engine#48323)

Otherwise we do three hashmap lookups everything we call OptionsFromPass(AndEntity) in a contents.

## Before
16 / 392 = 4%

![image](https://github.com/flutter/engine/assets/8975114/cf02778c-22da-4849-a98a-75bac7536284)

## After
6/ 458 = 1.3%

![image](https://github.com/flutter/engine/assets/8975114/13b58267-a25a-483d-a632-55f505070996)
This commit is contained in:
Jonah Williams 2023-11-22 11:16:11 -08:00 committed by GitHub
parent 2faace2ef2
commit c453bac49b
4 changed files with 61 additions and 6 deletions

View File

@ -19,11 +19,9 @@ namespace impeller {
ContentContextOptions OptionsFromPass(const RenderPass& pass) {
ContentContextOptions opts;
opts.sample_count = pass.GetRenderTarget().GetSampleCount();
opts.color_attachment_pixel_format =
pass.GetRenderTarget().GetRenderTargetPixelFormat();
opts.has_stencil_attachment =
pass.GetRenderTarget().GetStencilAttachment().has_value();
opts.sample_count = pass.GetSampleCount();
opts.color_attachment_pixel_format = pass.GetRenderTargetPixelFormat();
opts.has_stencil_attachment = pass.HasStencilAttachment();
return opts;
}

View File

@ -9,6 +9,10 @@ namespace impeller {
RenderPass::RenderPass(std::weak_ptr<const Context> context,
const RenderTarget& target)
: context_(std::move(context)),
sample_count_(target.GetSampleCount()),
pixel_format_(target.GetRenderTargetPixelFormat()),
has_stencil_attachment_(target.GetStencilAttachment().has_value()),
render_target_size_(target.GetRenderTargetSize()),
render_target_(target),
transients_buffer_() {
auto strong_context = context_.lock();
@ -23,12 +27,24 @@ RenderPass::~RenderPass() {
}
}
SampleCount RenderPass::GetSampleCount() const {
return sample_count_;
}
PixelFormat RenderPass::GetRenderTargetPixelFormat() const {
return pixel_format_;
}
bool RenderPass::HasStencilAttachment() const {
return has_stencil_attachment_;
}
const RenderTarget& RenderPass::GetRenderTarget() const {
return render_target_;
}
ISize RenderPass::GetRenderTargetSize() const {
return render_target_.GetRenderTargetSize();
return render_target_size_;
}
HostBuffer& RenderPass::GetTransientsBuffer() {

View File

@ -6,6 +6,7 @@
#include <string>
#include "impeller/core/formats.h"
#include "impeller/renderer/command.h"
#include "impeller/renderer/command_buffer.h"
#include "impeller/renderer/render_target.h"
@ -71,8 +72,29 @@ class RenderPass {
///
const std::vector<Command>& GetCommands() const { return commands_; }
//----------------------------------------------------------------------------
/// @brief The sample count of the attached render target.
SampleCount GetSampleCount() const;
//----------------------------------------------------------------------------
/// @brief The pixel format of the attached render target.
PixelFormat GetRenderTargetPixelFormat() const;
//----------------------------------------------------------------------------
/// @brief Whether the render target has an stencil attachment.
bool HasStencilAttachment() const;
protected:
const std::weak_ptr<const Context> context_;
// The following properties: sample_count, pixel_format,
// has_stencil_attachment, and render_target_size are cached on the
// RenderTarget to speed up numerous lookups during rendering. This is safe as
// the RenderTarget itself is copied into the RenderTarget and only exposed as
// a const reference.
const SampleCount sample_count_;
const PixelFormat pixel_format_;
const bool has_stencil_attachment_;
const ISize render_target_size_;
const RenderTarget render_target_;
std::shared_ptr<HostBuffer> transients_buffer_;
std::vector<Command> commands_;

View File

@ -1273,6 +1273,25 @@ TEST_P(RendererTest, CanPreAllocateCommands) {
EXPECT_EQ(render_pass->GetCommands().capacity(), 100u);
}
TEST_P(RendererTest, CanLookupRenderTargetProperties) {
auto context = GetContext();
auto cmd_buffer = context->CreateCommandBuffer();
auto render_target_cache = std::make_shared<RenderTargetAllocator>(
GetContext()->GetResourceAllocator());
auto render_target =
RenderTarget::CreateOffscreen(*context, *render_target_cache, {100, 100});
auto render_pass = cmd_buffer->CreateRenderPass(render_target);
EXPECT_EQ(render_pass->GetSampleCount(), render_target.GetSampleCount());
EXPECT_EQ(render_pass->GetRenderTargetPixelFormat(),
render_target.GetRenderTargetPixelFormat());
EXPECT_EQ(render_pass->HasStencilAttachment(),
render_target.GetStencilAttachment().has_value());
EXPECT_EQ(render_pass->GetRenderTargetSize(),
render_target.GetRenderTargetSize());
}
} // namespace testing
} // namespace impeller