Flutter Engine
The Flutter Engine
GrMtlResourceProvider.mm
Go to the documentation of this file.
1/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
19
21
22#if !__has_feature(objc_arc)
23#error This file must be compiled with Arc. Use -fobjc-arc flag
24#endif
25
26GR_NORETAIN_BEGIN
27
29 : fGpu(gpu) {
30 fPipelineStateCache = std::make_unique<PipelineStateCache>(gpu);
31}
32
34 const GrProgramDesc& programDesc,
35 const GrProgramInfo& programInfo,
37 return fPipelineStateCache->refPipelineState(programDesc, programInfo, stat);
38}
39
41 return fPipelineStateCache->precompileShader(key, data);
42}
43
44////////////////////////////////////////////////////////////////////////////////////////////////
45
47 const GrStencilSettings& stencil, GrSurfaceOrigin origin) {
48 GrMtlDepthStencil* depthStencilState;
50 depthStencilState = fDepthStencilStates.find(key);
51 if (!depthStencilState) {
52 depthStencilState = GrMtlDepthStencil::Create(fGpu, stencil, origin);
53 fDepthStencilStates.add(depthStencilState);
54 }
55 SkASSERT(depthStencilState);
56 return depthStencilState;
57}
58
60 GrMtlSampler* sampler;
61 sampler = fSamplers.find(GrMtlSampler::GenerateKey(params));
62 if (!sampler) {
63 sampler = GrMtlSampler::Create(fGpu, params);
64 fSamplers.add(sampler);
65 }
66 SkASSERT(sampler);
67 return sampler;
68}
69
71 MTLPixelFormat colorFormat, int sampleCount, MTLPixelFormat stencilFormat) {
72 if (!fMSAALoadLibrary) {
73 TRACE_EVENT0("skia", TRACE_FUNC);
74
75 std::string shaderText;
76 shaderText.append(
77 "#include <metal_stdlib>\n"
78 "#include <simd/simd.h>\n"
79 "using namespace metal;\n"
80 "\n"
81 "typedef struct {\n"
82 " float4 position [[position]];\n"
83 "} VertexOutput;\n"
84 "\n"
85 "typedef struct {\n"
86 " float4 uPosXform;\n"
87 " uint2 uTextureSize;\n"
88 "} VertexUniforms;\n"
89 "\n"
90 "vertex VertexOutput vertexMain(constant VertexUniforms& uniforms [[buffer(0)]],\n"
91 " uint vertexID [[vertex_id]]) {\n"
92 " VertexOutput out;\n"
93 " float2 position = float2(float(vertexID >> 1), float(vertexID & 1));\n"
94 " out.position.xy = position * uniforms.uPosXform.xy + uniforms.uPosXform.zw;\n"
95 " out.position.zw = float2(0.0, 1.0);\n"
96 " return out;\n"
97 "}\n"
98 "\n"
99 "fragment float4 fragmentMain(VertexOutput in [[stage_in]],\n"
100 " texture2d<half> colorMap [[texture(0)]]) {\n"
101 " uint2 coords = uint2(in.position.x, in.position.y);"
102 " half4 colorSample = colorMap.read(coords);\n"
103 " return float4(colorSample);\n"
104 "}"
105 );
106
107 auto errorHandler = fGpu->getContext()->priv().getShaderErrorHandler();
108 fMSAALoadLibrary = GrCompileMtlShaderLibrary(fGpu, shaderText, errorHandler);
109 if (!fMSAALoadLibrary) {
110 return nullptr;
111 }
112 }
113
114 for (int i = 0; i < fMSAALoadPipelines.size(); ++i) {
115 if (fMSAALoadPipelines[i].fColorFormat == colorFormat &&
116 fMSAALoadPipelines[i].fSampleCount == sampleCount &&
117 fMSAALoadPipelines[i].fStencilFormat == stencilFormat) {
118 return fMSAALoadPipelines[i].fPipeline.get();
119 }
120 }
121
122 auto pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
123
124 pipelineDescriptor.label = @"loadMSAAFromResolve";
125
126 pipelineDescriptor.vertexFunction =
127 [fMSAALoadLibrary newFunctionWithName: @"vertexMain"];
128 pipelineDescriptor.fragmentFunction =
129 [fMSAALoadLibrary newFunctionWithName: @"fragmentMain"];
130
131 auto mtlColorAttachment = [[MTLRenderPipelineColorAttachmentDescriptor alloc] init];
132
133 mtlColorAttachment.pixelFormat = colorFormat;
134 mtlColorAttachment.blendingEnabled = FALSE;
135 mtlColorAttachment.writeMask = MTLColorWriteMaskAll;
136
137 pipelineDescriptor.colorAttachments[0] = mtlColorAttachment;
138 pipelineDescriptor.rasterSampleCount = sampleCount;
139
140 pipelineDescriptor.stencilAttachmentPixelFormat = stencilFormat;
141
142 NSError* error;
143 auto pso =
144 [fGpu->device() newRenderPipelineStateWithDescriptor: pipelineDescriptor
145 error: &error];
146 if (!pso) {
147 SkDebugf("Error creating pipeline: %s\n",
148 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
149 }
150
151 auto renderPipeline = GrMtlRenderPipeline::Make(pso);
152
153 fMSAALoadPipelines.push_back({renderPipeline, colorFormat, sampleCount, stencilFormat});
154 return fMSAALoadPipelines[fMSAALoadPipelines.size()-1].fPipeline.get();
155}
156
158 fMSAALoadLibrary = nil;
159 fMSAALoadPipelines.clear();
160
161 fSamplers.foreach([&](GrMtlSampler* sampler) { sampler->unref(); });
162 fSamplers.reset();
163
164 fDepthStencilStates.foreach([&](GrMtlDepthStencil* stencil) { stencil->unref(); });
165 fDepthStencilStates.reset();
166
167 fPipelineStateCache->release();
168}
169
170////////////////////////////////////////////////////////////////////////////////////////////////
171
173 Entry(GrMtlPipelineState* pipelineState)
174 : fPipelineState(pipelineState) {}
175 Entry(const GrMtlPrecompiledLibraries& precompiledLibraries)
176 : fPipelineState(nullptr)
177 , fPrecompiledLibraries(precompiledLibraries) {}
178
179 std::unique_ptr<GrMtlPipelineState> fPipelineState;
180
181 // TODO: change to one library once we can build that
183};
184
185GrMtlResourceProvider::PipelineStateCache::PipelineStateCache(GrMtlGpu* gpu)
186 : fMap(gpu->getContext()->priv().options().fRuntimeProgramCacheSize)
187 , fGpu(gpu) {}
188
189GrMtlResourceProvider::PipelineStateCache::~PipelineStateCache() {
190 SkASSERT(0 == fMap.count());
191}
192
193void GrMtlResourceProvider::PipelineStateCache::release() {
194 fMap.reset();
195}
196
197GrMtlPipelineState* GrMtlResourceProvider::PipelineStateCache::refPipelineState(
198 const GrProgramDesc& desc,
199 const GrProgramInfo& programInfo,
200 Stats::ProgramCacheResult* statPtr) {
201
202 if (!statPtr) {
203 // If stat is NULL we are using inline compilation rather than through DDL,
204 // so we need to track those stats as well.
206 auto tmp = this->onRefPipelineState(desc, programInfo, &stat);
207 if (!tmp) {
209 } else {
211 }
212 return tmp;
213 } else {
214 return this->onRefPipelineState(desc, programInfo, statPtr);
215 }
216}
217
218GrMtlPipelineState* GrMtlResourceProvider::PipelineStateCache::onRefPipelineState(
219 const GrProgramDesc& desc,
220 const GrProgramInfo& programInfo,
222 *stat = Stats::ProgramCacheResult::kHit;
223 std::unique_ptr<Entry>* entry = fMap.find(desc);
224 if (entry && !(*entry)->fPipelineState) {
225 // We've pre-compiled the MSL shaders but don't yet have the pipelineState
226 const GrMtlPrecompiledLibraries* precompiledLibs = &((*entry)->fPrecompiledLibraries);
227 SkASSERT(precompiledLibs->fVertexLibrary);
228 SkASSERT(precompiledLibs->fFragmentLibrary);
229 (*entry)->fPipelineState.reset(
231 precompiledLibs));
232 if (!(*entry)->fPipelineState) {
233 // Should we purge the precompiled shaders from the cache at this point?
234 SkDEBUGFAIL("Couldn't create pipelineState from precompiled shaders");
236 return nullptr;
237 }
238 // release the libraries
239 (*entry)->fPrecompiledLibraries.fVertexLibrary = nil;
240 (*entry)->fPrecompiledLibraries.fFragmentLibrary = nil;
241
243 *stat = Stats::ProgramCacheResult::kPartial;
244 } else if (!entry) {
245 GrMtlPipelineState* pipelineState(
247 if (!pipelineState) {
249 return nullptr;
250 }
252 entry = fMap.insert(desc, std::make_unique<Entry>(pipelineState));
253 *stat = Stats::ProgramCacheResult::kMiss;
254 return (*entry)->fPipelineState.get();
255 }
256 return (*entry)->fPipelineState.get();
257}
258
259bool GrMtlResourceProvider::PipelineStateCache::precompileShader(const SkData& key,
260 const SkData& data) {
262 if (!GrProgramDesc::BuildFromData(&desc, key.data(), key.size())) {
263 return false;
264 }
265
266 std::unique_ptr<Entry>* entry = fMap.find(desc);
267 if (entry) {
268 // We've already seen/compiled this shader
269 return true;
270 }
271
272 GrMtlPrecompiledLibraries precompiledLibraries;
273 if (!GrMtlPipelineStateBuilder::PrecompileShaders(fGpu, data, &precompiledLibraries)) {
274 return false;
275 }
276
277 fMap.insert(desc, std::make_unique<Entry>(precompiledLibraries));
278 return true;
279
280}
281
282GR_NORETAIN_END
const char * options
id< MTLLibrary > GrCompileMtlShaderLibrary(const GrMtlGpu *gpu, const std::string &msl, GrContextOptions::ShaderErrorHandler *errorHandler)
Definition: GrMtlUtil.mm:52
GrSurfaceOrigin
Definition: GrTypes.h:147
#define SkDEBUGFAIL(message)
Definition: SkAssert.h:118
#define SkASSERT(cond)
Definition: SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
#define TRACE_FUNC
Definition: SkTraceEvent.h:30
GrContextOptions::ShaderErrorHandler * getShaderErrorHandler() const
GrDirectContextPriv priv()
GrDirectContext * getContext()
Definition: GrGpu.h:67
static Key GenerateKey(const GrStencilSettings &, GrSurfaceOrigin)
static GrMtlDepthStencil * Create(const GrMtlGpu *, const GrStencilSettings &, GrSurfaceOrigin)
id< MTLDevice > device() const
Definition: GrMtlGpu.h:49
static GrMtlPipelineState * CreatePipelineState(GrMtlGpu *, const GrProgramDesc &, const GrProgramInfo &, const GrMtlPrecompiledLibraries *precompiledLibs=nullptr)
static bool PrecompileShaders(GrMtlGpu *, const SkData &, GrMtlPrecompiledLibraries *precompiledLibs)
static sk_sp< GrMtlRenderPipeline > Make(id< MTLRenderPipelineState > pso)
Definition: GrMtlPipeline.h:20
const GrMtlRenderPipeline * findOrCreateMSAALoadPipeline(MTLPixelFormat colorFormat, int sampleCount, MTLPixelFormat stencilFormat)
GrMtlPipelineState * findOrCreateCompatiblePipelineState(const GrProgramDesc &, const GrProgramInfo &, GrThreadSafePipelineBuilder::Stats::ProgramCacheResult *stat=nullptr)
bool precompileShader(const SkData &key, const SkData &data)
GrMtlDepthStencil * findOrCreateCompatibleDepthStencilState(const GrStencilSettings &, GrSurfaceOrigin)
GrMtlResourceProvider(GrMtlGpu *gpu)
GrMtlSampler * findOrCreateCompatibleSampler(GrSamplerState)
static Key GenerateKey(GrSamplerState)
Definition: GrMtlSampler.mm:85
static GrMtlSampler * Create(const GrMtlGpu *gpu, GrSamplerState)
Definition: GrMtlSampler.mm:45
static bool BuildFromData(GrProgramDesc *desc, const void *keyData, size_t keyLength)
Definition: GrProgramDesc.h:82
void incNumInlineProgramCacheResult(ProgramCacheResult stat)
Definition: SkData.h:25
T * find(const Key &key) const
void foreach(Fn &&fn)
void add(T *entry)
int size() const
Definition: SkTArray.h:421
const EmbeddedViewParams * params
FlPixelBufferTexturePrivate * priv
const uint8_t uint32_t uint32_t GError ** error
return FALSE
static bool init()
Entry(const GrMtlPrecompiledLibraries &precompiledLibraries)
std::unique_ptr< GrMtlPipelineState > fPipelineState
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131