[Impeller] iOS/macOS: Only wait for command scheduling prior to present (flutter/engine#40781)

This commit is contained in:
Brandon DeRosier
2023-03-30 17:41:14 -07:00
committed by GitHub
parent f06d79cea2
commit 2b0d541321
5 changed files with 27 additions and 27 deletions

View File

@@ -167,27 +167,6 @@ bool CommandBufferMTL::OnSubmitCommands(CompletionCallback callback) {
[buffer_ commit];
#if (FML_OS_MACOSX || FML_OS_IOS_SIMULATOR)
// We're using waitUntilScheduled on macOS and iOS simulator to force a hard
// barrier between the execution of different command buffers. This forces all
// renderable texture access to be synchronous (i.e. a write from a previous
// command buffer will not get scheduled to happen at the same time as a read
// in a future command buffer).
//
// Metal hazard tracks shared memory resources by default, and we don't need
// to do any additional work to synchronize access to MTLTextures and
// MTLBuffers on iOS devices with UMA. However, shared textures are disallowed
// on macOS according to the documentation:
// https://developer.apple.com/documentation/metal/mtlstoragemode/shared
// And so this is a stopgap solution that has been present in Impeller since
// multi-pass rendering/SaveLayer support was first set up.
//
// TODO(bdero): Remove this for all targets once a solution for resource
// tracking that works everywhere is established:
// https://github.com/flutter/flutter/issues/120406
[buffer_ waitUntilScheduled];
#endif
buffer_ = nil;
return true;
}

View File

@@ -64,6 +64,8 @@ class ContextMTL final : public Context,
// |Context|
bool UpdateOffscreenLayerPixelFormat(PixelFormat format) override;
id<MTLCommandBuffer> CreateMTLCommandBuffer() const;
private:
id<MTLDevice> device_ = nullptr;
id<MTLCommandQueue> command_queue_ = nullptr;

View File

@@ -291,4 +291,8 @@ bool ContextMTL::UpdateOffscreenLayerPixelFormat(PixelFormat format) {
return true;
}
id<MTLCommandBuffer> ContextMTL::CreateMTLCommandBuffer() const {
return [command_queue_ commandBuffer];
}
} // namespace impeller

View File

@@ -43,9 +43,12 @@ class SurfaceMTL final : public Surface {
id<MTLDrawable> drawable() const { return drawable_; }
private:
std::weak_ptr<Context> context_;
id<MTLDrawable> drawable_ = nil;
SurfaceMTL(const RenderTarget& target, id<MTLDrawable> drawable);
SurfaceMTL(const std::weak_ptr<Context>& context,
const RenderTarget& target,
id<MTLDrawable> drawable);
// |Surface|
bool Present() const override;

View File

@@ -6,6 +6,7 @@
#include "flutter/fml/trace_event.h"
#include "impeller/base/validation.h"
#include "impeller/renderer/backend/metal/context_mtl.h"
#include "impeller/renderer/backend/metal/formats_mtl.h"
#include "impeller/renderer/backend/metal/texture_mtl.h"
#include "impeller/renderer/render_target.h"
@@ -111,12 +112,14 @@ std::unique_ptr<SurfaceMTL> SurfaceMTL::WrapCurrentMetalLayerDrawable(
render_target_desc.SetStencilAttachment(stencil0);
// The constructor is private. So make_unique may not be used.
return std::unique_ptr<SurfaceMTL>(
new SurfaceMTL(render_target_desc, current_drawable));
return std::unique_ptr<SurfaceMTL>(new SurfaceMTL(
context->weak_from_this(), render_target_desc, current_drawable));
}
SurfaceMTL::SurfaceMTL(const RenderTarget& target, id<MTLDrawable> drawable)
: Surface(target), drawable_(drawable) {}
SurfaceMTL::SurfaceMTL(const std::weak_ptr<Context>& context,
const RenderTarget& target,
id<MTLDrawable> drawable)
: Surface(target), context_(context), drawable_(drawable) {}
// |Surface|
SurfaceMTL::~SurfaceMTL() = default;
@@ -127,7 +130,16 @@ bool SurfaceMTL::Present() const {
return false;
}
[drawable_ present];
auto context = context_.lock();
if (!context) {
return false;
}
id<MTLCommandBuffer> command_buffer =
ContextMTL::Cast(context.get())->CreateMTLCommandBuffer();
[command_buffer presentDrawable:drawable_];
[command_buffer commit];
return true;
}
#pragma GCC diagnostic pop