Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
compute_pass_mtl.mm
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <Metal/Metal.h>
8#include <memory>
9
10#include "flutter/fml/backtrace.h"
11#include "flutter/fml/closure.h"
12#include "flutter/fml/logging.h"
13#include "flutter/fml/trace_event.h"
14#include "fml/status.h"
26
27namespace impeller {
28
29ComputePassMTL::ComputePassMTL(std::shared_ptr<const Context> context,
30 id<MTLCommandBuffer> buffer)
31 : ComputePass(std::move(context)), buffer_(buffer) {
32 if (!buffer_) {
33 return;
34 }
35 encoder_ = [buffer_ computeCommandEncoderWithDispatchType:
36 MTLDispatchType::MTLDispatchTypeConcurrent];
37 if (!encoder_) {
38 return;
39 }
40 pass_bindings_cache_.SetEncoder(encoder_);
41 is_valid_ = true;
42}
43
44ComputePassMTL::~ComputePassMTL() = default;
45
46bool ComputePassMTL::IsValid() const {
47 return is_valid_;
48}
49
50void ComputePassMTL::OnSetLabel(const std::string& label) {
51#ifdef IMPELLER_DEBUG
52 if (label.empty()) {
53 return;
54 }
55 [encoder_ setLabel:@(label.c_str())];
56#endif // IMPELLER_DEBUG
57}
58
59void ComputePassMTL::SetCommandLabel(std::string_view label) {
60 has_label_ = true;
61 [encoder_ pushDebugGroup:@(label.data())];
62}
63
64// |ComputePass|
65void ComputePassMTL::SetPipeline(
66 const std::shared_ptr<Pipeline<ComputePipelineDescriptor>>& pipeline) {
67 pass_bindings_cache_.SetComputePipelineState(
68 ComputePipelineMTL::Cast(*pipeline).GetMTLComputePipelineState());
69}
70
71// |ComputePass|
72void ComputePassMTL::AddBufferMemoryBarrier() {
73 [encoder_ memoryBarrierWithScope:MTLBarrierScopeBuffers];
74}
75
76// |ComputePass|
77void ComputePassMTL::AddTextureMemoryBarrier() {
78 [encoder_ memoryBarrierWithScope:MTLBarrierScopeTextures];
79}
80
81// |ComputePass|
82bool ComputePassMTL::BindResource(ShaderStage stage,
84 const ShaderUniformSlot& slot,
85 const ShaderMetadata& metadata,
86 BufferView view) {
87 if (!view.buffer) {
88 return false;
89 }
90
91 const std::shared_ptr<const DeviceBuffer>& device_buffer = view.buffer;
92 if (!device_buffer) {
93 return false;
94 }
95
96 id<MTLBuffer> buffer = DeviceBufferMTL::Cast(*device_buffer).GetMTLBuffer();
97 // The Metal call is a void return and we don't want to make it on nil.
98 if (!buffer) {
99 return false;
100 }
101
102 pass_bindings_cache_.SetBuffer(slot.ext_res_0, view.range.offset, buffer);
103 return true;
104}
105
106// |ComputePass|
107bool ComputePassMTL::BindResource(
108 ShaderStage stage,
110 const SampledImageSlot& slot,
111 const ShaderMetadata& metadata,
112 std::shared_ptr<const Texture> texture,
113 const std::unique_ptr<const Sampler>& sampler) {
114 if (!sampler || !texture->IsValid()) {
115 return false;
116 }
117
118 pass_bindings_cache_.SetTexture(slot.texture_index,
119 TextureMTL::Cast(*texture).GetMTLTexture());
120 pass_bindings_cache_.SetSampler(
121 slot.texture_index, SamplerMTL::Cast(*sampler).GetMTLSamplerState());
122 return true;
123}
124
125fml::Status ComputePassMTL::Compute(const ISize& grid_size) {
126 if (grid_size.IsEmpty()) {
128 "Invalid grid size for compute command.");
129 }
130 // TODO(dnfield): use feature detection to support non-uniform threadgroup
131 // sizes.
132 // https://github.com/flutter/flutter/issues/110619
133 auto width = grid_size.width;
134 auto height = grid_size.height;
135
136 auto max_total_threads_per_threadgroup = static_cast<int64_t>(
137 pass_bindings_cache_.GetPipeline().maxTotalThreadsPerThreadgroup);
138
139 // Special case for linear processing.
140 if (height == 1) {
141 int64_t thread_groups = std::max(
142 static_cast<int64_t>(
143 std::ceil(width * 1.0 / max_total_threads_per_threadgroup * 1.0)),
144 1LL);
145 [encoder_
146 dispatchThreadgroups:MTLSizeMake(thread_groups, 1, 1)
147 threadsPerThreadgroup:MTLSizeMake(max_total_threads_per_threadgroup, 1,
148 1)];
149 } else {
150 while (width * height > max_total_threads_per_threadgroup) {
151 width = std::max(1LL, width / 2);
152 height = std::max(1LL, height / 2);
153 }
154
155 auto size = MTLSizeMake(width, height, 1);
156 [encoder_ dispatchThreadgroups:size threadsPerThreadgroup:size];
157 }
158
159#ifdef IMPELLER_DEBUG
160 if (has_label_) {
161 [encoder_ popDebugGroup];
162 }
163 has_label_ = false;
164#endif // IMPELLER_DEBUG
165 return fml::Status();
166}
167
168bool ComputePassMTL::EncodeCommands() const {
169 [encoder_ endEncoding];
170 return true;
171}
172
173} // namespace impeller
Describes the fixed function and programmable aspects of rendering and compute operations performed b...
Definition pipeline.h:49
static const uint8_t buffer[]
FlTexture * texture
Definition ref_ptr.h:256
int32_t height
int32_t width
std::shared_ptr< const DeviceBuffer > buffer
Definition buffer_view.h:16
size_t offset
Definition range.h:15
Metadata required to bind a combined texture and sampler.
size_t texture_index
ext_res_0 is the Metal binding value.
Metadata required to bind a buffer.
size_t ext_res_0
ext_res_0 is the Metal binding value.
Type height
Definition size.h:23
Type width
Definition size.h:22
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
Definition size.h:105