Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1886,6 +1886,7 @@ TEST_P(AiksTest, DrawPaintAbsorbsClears) {
ASSERT_EQ(spy->render_passes_.size(), 1llu);
std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
render_pass->EncodeCommands();
}

// This is important to enforce with texture reuse, since cached textures need
Expand All @@ -1911,6 +1912,7 @@ TEST_P(AiksTest,
GetBackend() == PlaygroundBackend::kOpenGLES ? 4llu : 3llu);
std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
render_pass->EncodeCommands();
}

TEST_P(AiksTest, DrawRectAbsorbsClears) {
Expand All @@ -1931,6 +1933,7 @@ TEST_P(AiksTest, DrawRectAbsorbsClears) {
ASSERT_EQ(spy->render_passes_.size(), 1llu);
std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
render_pass->EncodeCommands();
}

TEST_P(AiksTest, DrawRectAbsorbsClearsNegativeRRect) {
Expand All @@ -1951,6 +1954,7 @@ TEST_P(AiksTest, DrawRectAbsorbsClearsNegativeRRect) {
ASSERT_EQ(spy->render_passes_.size(), 1llu);
std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
ASSERT_EQ(render_pass->GetCommands().size(), 2llu);
render_pass->EncodeCommands();
}

TEST_P(AiksTest, DrawRectAbsorbsClearsNegativeRotation) {
Expand All @@ -1971,6 +1975,7 @@ TEST_P(AiksTest, DrawRectAbsorbsClearsNegativeRotation) {
ASSERT_EQ(spy->render_passes_.size(), 1llu);
std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
ASSERT_EQ(render_pass->GetCommands().size(), 1llu);
render_pass->EncodeCommands();
}

TEST_P(AiksTest, DrawRectAbsorbsClearsNegative) {
Expand All @@ -1991,6 +1996,7 @@ TEST_P(AiksTest, DrawRectAbsorbsClearsNegative) {
ASSERT_EQ(spy->render_passes_.size(), 1llu);
std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
ASSERT_EQ(render_pass->GetCommands().size(), 2llu);
render_pass->EncodeCommands();
}

TEST_P(AiksTest, ClipRectElidesNoOpClips) {
Expand All @@ -2015,6 +2021,7 @@ TEST_P(AiksTest, ClipRectElidesNoOpClips) {
ASSERT_EQ(spy->render_passes_.size(), 1llu);
std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
render_pass->EncodeCommands();
}

TEST_P(AiksTest, ClearColorOptimizationDoesNotApplyForBackdropFilters) {
Expand Down
7 changes: 0 additions & 7 deletions impeller/renderer/backend/metal/command_buffer_mtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,6 @@ class CommandBufferMTL final : public CommandBuffer {
// |CommandBuffer|
void OnWaitUntilScheduled() override;

// |CommandBuffer|
bool EncodeAndSubmit(const std::shared_ptr<RenderPass>& render_pass) override;

// |CommandBuffer|
bool EncodeAndSubmit(const std::shared_ptr<BlitPass>& blit_ass,
const std::shared_ptr<Allocator>& allocator) override;

// |CommandBuffer|
std::shared_ptr<RenderPass> OnCreateRenderPass(RenderTarget target) override;

Expand Down
85 changes: 0 additions & 85 deletions impeller/renderer/backend/metal/command_buffer_mtl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

#include "flutter/fml/make_copyable.h"
#include "flutter/fml/synchronization/semaphore.h"
#include "flutter/fml/trace_event.h"

#include "impeller/renderer/backend/metal/blit_pass_mtl.h"
#include "impeller/renderer/backend/metal/compute_pass_mtl.h"
Expand Down Expand Up @@ -183,90 +182,6 @@ static bool LogMTLCommandBufferErrorIfPresent(id<MTLCommandBuffer> buffer) {
return true;
}

bool CommandBufferMTL::EncodeAndSubmit(
const std::shared_ptr<RenderPass>& render_pass) {
TRACE_EVENT0("impeller", "CommandBufferMTL::EncodeAndSubmit");
if (!IsValid() || !render_pass->IsValid()) {
return false;
}
auto context = context_.lock();
if (!context) {
return false;
}
[buffer_ enqueue];
auto buffer = buffer_;
buffer_ = nil;

#ifdef IMPELLER_DEBUG
ContextMTL::Cast(*context).GetGPUTracer()->RecordCmdBuffer(buffer);
#endif // IMPELLER_DEBUG

auto worker_task_runner = ContextMTL::Cast(*context).GetWorkerTaskRunner();
auto mtl_render_pass = static_cast<RenderPassMTL*>(render_pass.get());

// Render command encoder creation has been observed to exceed the stack size
// limit for worker threads, and therefore is intentionally constructed on the
// raster thread.
auto render_command_encoder =
[buffer renderCommandEncoderWithDescriptor:mtl_render_pass->desc_];
if (!render_command_encoder) {
return false;
}

auto task = fml::MakeCopyable(
[render_pass, buffer, render_command_encoder, weak_context = context_]() {
auto context = weak_context.lock();
if (!context) {
[render_command_encoder endEncoding];
return;
}

auto mtl_render_pass = static_cast<RenderPassMTL*>(render_pass.get());
if (!mtl_render_pass->label_.empty()) {
[render_command_encoder setLabel:@(mtl_render_pass->label_.c_str())];
}

auto result = mtl_render_pass->EncodeCommands(
context->GetResourceAllocator(), render_command_encoder);
[render_command_encoder endEncoding];
if (result) {
[buffer commit];
} else {
VALIDATION_LOG << "Failed to encode command buffer";
}
});
worker_task_runner->PostTask(task);
return true;
}

bool CommandBufferMTL::EncodeAndSubmit(
const std::shared_ptr<BlitPass>& blit_pass,
const std::shared_ptr<Allocator>& allocator) {
if (!IsValid() || !blit_pass->IsValid()) {
return false;
}
auto context = context_.lock();
if (!context) {
return false;
}
[buffer_ enqueue];
auto buffer = buffer_;
buffer_ = nil;

auto worker_task_runner = ContextMTL::Cast(*context).GetWorkerTaskRunner();
auto task = fml::MakeCopyable(
[blit_pass, buffer, weak_context = context_, allocator]() {
auto context = weak_context.lock();
if (!blit_pass->EncodeCommands(allocator)) {
VALIDATION_LOG << "Failed to encode blit pass.";
return;
}
[buffer commit];
});
worker_task_runner->PostTask(task);
return true;
}

void CommandBufferMTL::OnWaitUntilScheduled() {}

std::shared_ptr<RenderPass> CommandBufferMTL::OnCreateRenderPass(
Expand Down
3 changes: 0 additions & 3 deletions impeller/renderer/backend/metal/context_mtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,6 @@ class ContextMTL final : public Context,

id<MTLCommandBuffer> CreateMTLCommandBuffer(const std::string& label) const;

const std::shared_ptr<fml::ConcurrentTaskRunner> GetWorkerTaskRunner() const;

std::shared_ptr<const fml::SyncSwitch> GetIsGpuDisabledSyncSwitch() const;

#ifdef IMPELLER_DEBUG
Expand Down Expand Up @@ -122,7 +120,6 @@ class ContextMTL final : public Context,
std::shared_ptr<SamplerLibrary> sampler_library_;
std::shared_ptr<AllocatorMTL> resource_allocator_;
std::shared_ptr<const Capabilities> device_capabilities_;
std::shared_ptr<fml::ConcurrentMessageLoop> raster_message_loop_;
std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch_;
#ifdef IMPELLER_DEBUG
std::shared_ptr<GPUTracerMTL> gpu_tracer_;
Expand Down
27 changes: 1 addition & 26 deletions impeller/renderer/backend/metal/context_mtl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -88,24 +88,6 @@ static bool DeviceSupportsComputeSubgroups(id<MTLDevice> device) {
sync_switch_observer_.reset(new SyncSwitchObserver(*this));
is_gpu_disabled_sync_switch_->AddObserver(sync_switch_observer_.get());

// Worker task runner.
{
raster_message_loop_ = fml::ConcurrentMessageLoop::Create(
std::min(4u, std::thread::hardware_concurrency()));
raster_message_loop_->PostTaskToAllWorkers([]() {
// See https://github.com/flutter/flutter/issues/65752
// Intentionally opt out of QoS for raster task workloads.
[[NSThread currentThread] setThreadPriority:1.0];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get rid of the corresponding Foundation.h header import above?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

sched_param param;
int policy;
pthread_t thread = pthread_self();
if (!pthread_getschedparam(thread, &policy, &param)) {
param.sched_priority = 50;
pthread_setschedparam(thread, policy, &param);
}
});
}

// Setup the shader library.
{
if (shader_libraries == nil) {
Expand Down Expand Up @@ -330,21 +312,14 @@ new ContextMTL(device, command_queue,
}

// |Context|
void ContextMTL::Shutdown() {
raster_message_loop_.reset();
}
void ContextMTL::Shutdown() {}

#ifdef IMPELLER_DEBUG
std::shared_ptr<GPUTracerMTL> ContextMTL::GetGPUTracer() const {
return gpu_tracer_;
}
#endif // IMPELLER_DEBUG

const std::shared_ptr<fml::ConcurrentTaskRunner>
ContextMTL::GetWorkerTaskRunner() const {
return raster_message_loop_->GetTaskRunner();
}

std::shared_ptr<const fml::SyncSwitch> ContextMTL::GetIsGpuDisabledSyncSwitch()
const {
return is_gpu_disabled_sync_switch_;
Expand Down
126 changes: 124 additions & 2 deletions impeller/renderer/backend/metal/render_pass_mtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,64 @@

namespace impeller {

//-----------------------------------------------------------------------------
/// @brief Ensures that bindings on the pass are not redundantly set or
/// updated. Avoids making the driver do additional checks and makes
/// the frame insights during profiling and instrumentation not
/// complain about the same.
///
/// There should be no change to rendering if this caching was
/// absent.
///
struct PassBindingsCache {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to its own TU and rename as PassBindingsCacheMTL.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

explicit PassBindingsCache() {}

~PassBindingsCache() = default;

PassBindingsCache(const PassBindingsCache&) = delete;

PassBindingsCache(PassBindingsCache&&) = delete;

void SetEncoder(id<MTLRenderCommandEncoder> encoder);

void SetRenderPipelineState(id<MTLRenderPipelineState> pipeline);

void SetDepthStencilState(id<MTLDepthStencilState> depth_stencil);

bool SetBuffer(ShaderStage stage,
uint64_t index,
uint64_t offset,
id<MTLBuffer> buffer);

bool SetTexture(ShaderStage stage, uint64_t index, id<MTLTexture> texture);

bool SetSampler(ShaderStage stage,
uint64_t index,
id<MTLSamplerState> sampler);

void SetViewport(const Viewport& viewport);

void SetScissor(const IRect& scissor);

private:
struct BufferOffsetPair {
id<MTLBuffer> buffer = nullptr;
size_t offset = 0u;
};
using BufferMap = std::map<uint64_t, BufferOffsetPair>;
using TextureMap = std::map<uint64_t, id<MTLTexture>>;
using SamplerMap = std::map<uint64_t, id<MTLSamplerState>>;

id<MTLRenderCommandEncoder> encoder_;
id<MTLRenderPipelineState> pipeline_ = nullptr;
id<MTLDepthStencilState> depth_stencil_ = nullptr;
std::map<ShaderStage, BufferMap> buffers_;
std::map<ShaderStage, TextureMap> textures_;
std::map<ShaderStage, SamplerMap> samplers_;
std::optional<Viewport> viewport_;
std::optional<IRect> scissor_;
};

class RenderPassMTL final : public RenderPass {
public:
// |RenderPass|
Expand All @@ -22,14 +80,31 @@ class RenderPassMTL final : public RenderPass {
friend class CommandBufferMTL;

id<MTLCommandBuffer> buffer_ = nil;
id<MTLRenderCommandEncoder> encoder_ = nil;
MTLRenderPassDescriptor* desc_ = nil;
std::string label_;
bool is_metal_trace_active_ = false;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: this

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

bool is_valid_ = false;

PassBindingsCache pass_bindings_;

// Per-command state
size_t instance_count_ = 1u;
size_t base_vertex_ = 0u;
size_t vertex_count_ = 0u;
bool has_valid_pipeline_ = false;
bool has_label_ = false;
BufferView index_buffer_;
PrimitiveType primitive_type_;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default this ivars.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

MTLIndexType index_type_;

RenderPassMTL(std::shared_ptr<const Context> context,
const RenderTarget& target,
id<MTLCommandBuffer> buffer);

// |RenderPass|
void ReserveCommands(size_t command_count) override {}

// |RenderPass|
bool IsValid() const override;

Expand All @@ -39,8 +114,55 @@ class RenderPassMTL final : public RenderPass {
// |RenderPass|
bool OnEncodeCommands(const Context& context) const override;

bool EncodeCommands(const std::shared_ptr<Allocator>& transients_allocator,
id<MTLRenderCommandEncoder> pass) const;
// |RenderPass|
void SetPipeline(
const std::shared_ptr<Pipeline<PipelineDescriptor>>& pipeline) override;

// |RenderPass|
void SetCommandLabel(std::string_view label) override;

// |RenderPass|
void SetStencilReference(uint32_t value) override;

// |RenderPass|
void SetBaseVertex(uint64_t value) override;

// |RenderPass|
void SetViewport(Viewport viewport) override;

// |RenderPass|
void SetScissor(IRect scissor) override;

// |RenderPass|
void SetInstanceCount(size_t count) override;

// |RenderPass|
bool SetVertexBuffer(VertexBuffer buffer) override;

// |RenderPass|
fml::Status Draw() override;

// |RenderPass|
bool BindResource(ShaderStage stage,
DescriptorType type,
const ShaderUniformSlot& slot,
const ShaderMetadata& metadata,
BufferView view) override;

// |RenderPass|
bool BindResource(ShaderStage stage,
DescriptorType type,
const ShaderUniformSlot& slot,
const std::shared_ptr<const ShaderMetadata>& metadata,
BufferView view) override;

// |RenderPass|
bool BindResource(ShaderStage stage,
DescriptorType type,
const SampledImageSlot& slot,
const ShaderMetadata& metadata,
std::shared_ptr<const Texture> texture,
std::shared_ptr<const Sampler> sampler) override;

RenderPassMTL(const RenderPassMTL&) = delete;

Expand Down
Loading