Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all 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
9 changes: 9 additions & 0 deletions impeller/renderer/backend/gles/context_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,15 @@ std::shared_ptr<CommandBuffer> ContextGLES::CreateCommandBuffer() const {
new CommandBufferGLES(weak_from_this(), reactor_));
}

// |Context|
bool ContextGLES::WaitUntilCommandsCompleted() {
const auto result = reactor_->React();
if (result) {
reactor_->GetProcTable().Finish();
}
return result;
}

// |Context|
std::shared_ptr<WorkQueue> ContextGLES::GetWorkQueue() const {
return work_queue_;
Expand Down
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 @@ -73,6 +73,9 @@ class ContextGLES final : public Context,
// |Context|
bool SupportsOffscreenMSAA() const override;

// |Context|
bool WaitUntilCommandsCompleted() override;

FML_DISALLOW_COPY_AND_ASSIGN(ContextGLES);
};

Expand Down
3 changes: 2 additions & 1 deletion impeller/renderer/backend/gles/proc_table_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ struct GLProc {
PROC(UseProgram); \
PROC(VertexAttribPointer); \
PROC(Viewport); \
PROC(ReadPixels);
PROC(ReadPixels); \
PROC(Finish);

#define FOR_EACH_IMPELLER_GLES3_PROC(PROC) PROC(BlitFramebuffer);

Expand Down
6 changes: 5 additions & 1 deletion impeller/renderer/backend/metal/command_buffer_mtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,20 @@ namespace impeller {

class CommandBufferMTL final : public CommandBuffer {
public:
using SubmitCallback = std::function<void(id<MTLCommandBuffer>)>;

// |CommandBuffer|
~CommandBufferMTL() override;

private:
friend class ContextMTL;

id<MTLCommandBuffer> buffer_ = nullptr;
SubmitCallback submit_callback_ = nullptr;

CommandBufferMTL(const std::weak_ptr<const Context>& context,
id<MTLCommandQueue> queue);
id<MTLCommandQueue> queue,
SubmitCallback submit_callback);

// |CommandBuffer|
void SetLabel(const std::string& label) const override;
Expand Down
11 changes: 9 additions & 2 deletions impeller/renderer/backend/metal/command_buffer_mtl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,11 @@ static bool LogMTLCommandBufferErrorIfPresent(id<MTLCommandBuffer> buffer) {
}

CommandBufferMTL::CommandBufferMTL(const std::weak_ptr<const Context>& context,
id<MTLCommandQueue> queue)
: CommandBuffer(context), buffer_(CreateCommandBuffer(queue)) {}
id<MTLCommandQueue> queue,
SubmitCallback submit_callback)
: CommandBuffer(context),
buffer_(CreateCommandBuffer(queue)),
submit_callback_(std::move(submit_callback)) {}

CommandBufferMTL::~CommandBufferMTL() = default;

Expand Down Expand Up @@ -164,6 +167,10 @@ static bool LogMTLCommandBufferErrorIfPresent(id<MTLCommandBuffer> buffer) {
}

[buffer_ commit];
if (submit_callback_) {
submit_callback_(buffer_);
}

[buffer_ waitUntilScheduled];
buffer_ = nil;
return true;
Expand Down
4 changes: 4 additions & 0 deletions impeller/renderer/backend/metal/context_mtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class ContextMTL final : public Context,
private:
id<MTLDevice> device_ = nullptr;
id<MTLCommandQueue> command_queue_ = nullptr;
id<MTLCommandBuffer> last_submitted_buffer_ = nullptr;
std::shared_ptr<ShaderLibraryMTL> shader_library_;
std::shared_ptr<PipelineLibraryMTL> pipeline_library_;
std::shared_ptr<SamplerLibrary> sampler_library_;
Expand Down Expand Up @@ -67,6 +68,9 @@ class ContextMTL final : public Context,
// |Context|
std::shared_ptr<CommandBuffer> CreateCommandBuffer() const override;

// |Context|
bool WaitUntilCommandsCompleted() override;

// |Context|
std::shared_ptr<WorkQueue> GetWorkQueue() const override;

Expand Down
27 changes: 25 additions & 2 deletions impeller/renderer/backend/metal/context_mtl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -226,14 +226,37 @@
return nullptr;
}

auto buffer = std::shared_ptr<CommandBufferMTL>(
new CommandBufferMTL(weak_from_this(), queue));
auto weak_this = weak_from_this();
auto buffer = std::shared_ptr<CommandBufferMTL>(new CommandBufferMTL(
weak_this, queue, [weak_this](id<MTLCommandBuffer> buffer) {
auto strong_this = weak_this.lock();
if (strong_this) {
auto& context_mtl =
ContextMTL::Cast(const_cast<Context&>(*strong_this));
context_mtl.last_submitted_buffer_ = buffer;
}
}));
if (!buffer->IsValid()) {
return nullptr;
}
return buffer;
}

// |Context|
bool ContextMTL::WaitUntilCommandsCompleted() {
if (!last_submitted_buffer_) {
return true;
}

if (last_submitted_buffer_.status == MTLCommandBufferStatusCompleted) {
return true;
}

[last_submitted_buffer_ waitUntilCompleted];
last_submitted_buffer_ = nullptr;
return true;
}

std::shared_ptr<Allocator> ContextMTL::GetResourceAllocator() const {
return resource_allocator_;
}
Expand Down
9 changes: 9 additions & 0 deletions impeller/renderer/backend/vulkan/context_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,15 @@ std::shared_ptr<CommandBuffer> ContextVK::CreateCommandBuffer() const {
surface_producer_.get());
}

bool ContextVK::WaitUntilCommandsCompleted() {
auto result = device_->waitIdle();
if (result != vk::Result::eSuccess) {
VALIDATION_LOG << "Failed to wait device idle: " << vk::to_string(result);
return false;
}
return true;
}

vk::Instance ContextVK::GetInstance() const {
return *instance_;
}
Expand Down
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 @@ -136,6 +136,9 @@ class ContextVK final : public Context, public BackendCast<ContextVK, Context> {
// |Context|
std::shared_ptr<CommandBuffer> CreateCommandBuffer() const override;

// |Context|
bool WaitUntilCommandsCompleted() override;

// |Context|
PixelFormat GetColorAttachmentPixelFormat() const override;

Expand Down
2 changes: 2 additions & 0 deletions impeller/renderer/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class Context : public std::enable_shared_from_this<Context> {

virtual std::shared_ptr<CommandBuffer> CreateCommandBuffer() const = 0;

virtual bool WaitUntilCommandsCompleted() = 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this belongs on Context - you want to know when the commands from a particular buffer are completed right?

For example, should this wait for all commands from compute to finish as well?

Copy link
Member Author

@ColdPaleLight ColdPaleLight Nov 17, 2022

Choose a reason for hiding this comment

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

I tried adding a parameter to the SubmitCommands method of CommandBuffer to solve the problem. But I found that in some scenarios, developers can't call SubmitCommands themselves, or even they can't find the Command they want to wait for.

for example

std::shared_ptr<impeller::Image> image =
picture.ToImage(*context, render_target_size);
context->GetContext()->WaitUntilCommandsCompleted();

Copy link
Member Author

Choose a reason for hiding this comment

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

@dnfield Do you have any thoughts on this example of not being able to access the specific CommandsBuffer? Thanks!
Also cc @chinmaygarde

Copy link
Contributor

Choose a reason for hiding this comment

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

When you call EntityPass::Render from AiksContext::Render maybe there could be some parameter like a callback for when the texture is done?

Copy link
Contributor

Choose a reason for hiding this comment

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

EntityPass::Render knows the command buffer, and the command buffer has SubmitCommands(const CompletionCallback& callback).

Copy link
Member Author

@ColdPaleLight ColdPaleLight Nov 19, 2022

Choose a reason for hiding this comment

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

@dnfield Thank you very much! I file a new PR #37772, Any thoughts?


virtual std::shared_ptr<WorkQueue> GetWorkQueue() const = 0;

//----------------------------------------------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions impeller/renderer/renderer_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,8 @@ TEST_P(RendererTest, CanBlitTextureToBuffer) {
if (!buffer->SubmitCommands()) {
return false;
}

context->WaitUntilCommandsCompleted();
}

{
Expand Down
1 change: 1 addition & 0 deletions shell/common/snapshot_controller_impeller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ sk_sp<DlImage> SnapshotControllerImpeller::DoMakeRasterSnapshot(

std::shared_ptr<impeller::Image> image =
picture.ToImage(*context, render_target_size);
context->GetContext()->WaitUntilCommandsCompleted();
if (image) {
return impeller::DlImageImpeller::Make(image->GetTexture());
}
Expand Down