7#include <Foundation/Foundation.h>
8#include <Metal/Metal.h>
10#include "flutter/fml/build_config.h"
11#include "flutter/fml/container.h"
24PipelineLibraryMTL::~PipelineLibraryMTL() =
default;
30 auto descriptor = [[MTLRenderPipelineDescriptor alloc]
init];
31 descriptor.label = @(
desc.GetLabel().c_str());
32 descriptor.rasterSampleCount =
static_cast<NSUInteger
>(
desc.GetSampleCount());
33 bool created_specialized_function =
false;
35 if (
const auto& vertex_descriptor =
desc.GetVertexDescriptor()) {
38 vertex_descriptor->GetStageInputs(),
39 vertex_descriptor->GetStageLayouts())) {
40 descriptor.vertexDescriptor =
45 for (
const auto& item :
desc.GetColorAttachmentDescriptors()) {
46 descriptor.colorAttachments[item.first] =
50 descriptor.depthAttachmentPixelFormat =
52 descriptor.stencilAttachmentPixelFormat =
55 const auto& constants =
desc.GetSpecializationConstants();
56 for (
const auto& entry :
desc.GetStageEntrypoints()) {
57 if (entry.first == ShaderStage::kVertex) {
58 descriptor.vertexFunction =
59 ShaderFunctionMTL::Cast(*entry.second).GetMTLFunction();
61 if (entry.first == ShaderStage::kFragment) {
62 if (constants.empty()) {
63 descriptor.fragmentFunction =
64 ShaderFunctionMTL::Cast(*entry.second).GetMTLFunction();
68 created_specialized_function =
true;
69 ShaderFunctionMTL::Cast(*entry.second)
70 .GetMTLFunctionSpecialized(
72 descriptor.fragmentFunction =
function;
79 if (!created_specialized_function) {
86 auto descriptor = [[MTLComputePipelineDescriptor alloc]
init];
87 descriptor.label = @(
desc.GetLabel().c_str());
88 descriptor.computeFunction =
89 ShaderFunctionMTL::Cast(*
desc.GetStageEntrypoint()).GetMTLFunction();
98 desc.GetDepthStencilAttachmentDescriptor(),
99 desc.GetFrontStencilAttachmentDescriptor(),
100 desc.GetBackStencilAttachmentDescriptor()
102 return [
device newDepthStencilStateWithDescriptor:descriptor];
106bool PipelineLibraryMTL::IsValid()
const {
107 return device_ !=
nullptr;
111PipelineFuture<PipelineDescriptor> PipelineLibraryMTL::GetPipeline(
112 PipelineDescriptor descriptor,
114 if (
auto found = pipelines_.find(descriptor); found != pipelines_.end()) {
115 return found->second;
121 RealizedFuture<std::shared_ptr<Pipeline<PipelineDescriptor>>>(
nullptr)};
124 auto promise = std::make_shared<
125 std::promise<std::shared_ptr<Pipeline<PipelineDescriptor>>>>();
126 auto pipeline_future =
127 PipelineFuture<PipelineDescriptor>{descriptor, promise->get_future()};
128 pipelines_[descriptor] = pipeline_future;
129 auto weak_this = weak_from_this();
131 auto completion_handler =
132 ^(id<MTLRenderPipelineState> _Nullable render_pipeline_state,
133 NSError* _Nullable
error) {
136 << descriptor.GetLabel() <<
" :"
137 <<
error.localizedDescription.UTF8String;
138 promise->set_value(
nullptr);
142 auto strong_this = weak_this.lock();
144 promise->set_value(
nullptr);
148 auto new_pipeline = std::shared_ptr<PipelineMTL>(
new PipelineMTL(
151 render_pipeline_state,
154 promise->set_value(new_pipeline);
157 descriptor, [
device = device_, completion_handler](
158 MTLRenderPipelineDescriptor* descriptor) {
159 [
device newRenderPipelineStateWithDescriptor:descriptor
160 completionHandler:completion_handler];
162 return pipeline_future;
165PipelineFuture<ComputePipelineDescriptor> PipelineLibraryMTL::GetPipeline(
166 ComputePipelineDescriptor descriptor,
168 if (
auto found = compute_pipelines_.find(descriptor);
169 found != compute_pipelines_.end()) {
170 return found->second;
176 RealizedFuture<std::shared_ptr<Pipeline<ComputePipelineDescriptor>>>(
180 auto promise = std::make_shared<
181 std::promise<std::shared_ptr<Pipeline<ComputePipelineDescriptor>>>>();
182 auto pipeline_future = PipelineFuture<ComputePipelineDescriptor>{
183 descriptor, promise->get_future()};
184 compute_pipelines_[descriptor] = pipeline_future;
185 auto weak_this = weak_from_this();
187 auto completion_handler =
188 ^(id<MTLComputePipelineState> _Nullable compute_pipeline_state,
189 MTLComputePipelineReflection* _Nullable reflection,
190 NSError* _Nullable
error) {
193 <<
error.localizedDescription.UTF8String;
194 promise->set_value(
nullptr);
198 auto strong_this = weak_this.lock();
200 VALIDATION_LOG <<
"Library was collected before a pending pipeline "
201 "creation could finish.";
202 promise->set_value(
nullptr);
206 auto new_pipeline = std::shared_ptr<ComputePipelineMTL>(
207 new ComputePipelineMTL(weak_this,
209 compute_pipeline_state
211 promise->set_value(new_pipeline);
217 completionHandler:completion_handler];
218 return pipeline_future;
222void PipelineLibraryMTL::RemovePipelinesWithEntryPoint(
223 std::shared_ptr<const ShaderFunction>
function) {
225 return item->first.GetEntrypointForStage(
function->GetStage())
bool SetStageInputsAndLayout(const std::vector< ShaderStageIOSlot > &inputs, const std::vector< ShaderStageBufferLayout > &layouts)
MTLVertexDescriptor * GetMTLVertexDescriptor() const
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
const uint8_t uint32_t uint32_t GError ** error
#define FML_CHECK(condition)
Dart_NativeFunction function
void erase_if(Collection &container, std::function< bool(typename Collection::iterator)> predicate)
static void GetMTLRenderPipelineDescriptor(const PipelineDescriptor &desc, const Callback &callback)
std::function< void(MTLRenderPipelineDescriptor *)> Callback
static id< MTLDepthStencilState > CreateDepthStencilDescriptor(const PipelineDescriptor &desc, id< MTLDevice > device)
MTLDepthStencilDescriptor * ToMTLDepthStencilDescriptor(std::optional< DepthAttachmentDescriptor > depth, std::optional< StencilAttachmentDescriptor > front, std::optional< StencilAttachmentDescriptor > back)
constexpr MTLPixelFormat ToMTLPixelFormat(PixelFormat format)
static MTLComputePipelineDescriptor * GetMTLComputePipelineDescriptor(const ComputePipelineDescriptor &desc)
MTLRenderPipelineColorAttachmentDescriptor * ToMTLRenderPipelineColorAttachmentDescriptor(ColorAttachmentDescriptor descriptor)