Flutter Engine
The Flutter Engine
ContextUtils.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2021 Google LLC
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
10#include <string>
27#include "src/sksl/SkSLString.h"
28#include "src/sksl/SkSLUtil.h"
29
30namespace skgpu::graphite {
31
32std::tuple<UniquePaintParamsID, const UniformDataBlock*, const TextureDataBlock*> ExtractPaintData(
33 Recorder* recorder,
34 PipelineDataGatherer* gatherer,
36 const Layout layout,
37 const SkM44& local2Dev,
38 const PaintParams& p,
39 const Geometry& geometry,
40 sk_sp<TextureProxy> dstTexture,
41 SkIPoint dstOffset,
42 const SkColorInfo& targetColorInfo) {
43 SkDEBUGCODE(builder->checkReset());
44
45 gatherer->resetWithNewLayout(layout);
46
47 KeyContext keyContext(recorder,
48 local2Dev,
49 targetColorInfo,
50 geometry.isShape() || geometry.isEdgeAAQuad()
53 p.color(),
54 std::move(dstTexture),
55 dstOffset);
56 p.toKey(keyContext, builder, gatherer);
57
59 const UniformDataBlock* uniforms = nullptr;
60 const TextureDataBlock* textures = nullptr;
61 if (paintID.isValid()) {
62 if (gatherer->hasUniforms()) {
63 UniformDataCache* uniformDataCache = recorder->priv().uniformDataCache();
64 uniforms = uniformDataCache->insert(gatherer->finishUniformDataBlock());
65 }
66 if (gatherer->hasTextures()) {
67 TextureDataCache* textureDataCache = recorder->priv().textureDataCache();
68 textures = textureDataCache->insert(gatherer->textureDataBlock());
69 }
70 }
71
72 return { paintID, uniforms, textures };
73}
74
75std::tuple<const UniformDataBlock*, const TextureDataBlock*> ExtractRenderStepData(
76 UniformDataCache* uniformDataCache,
77 TextureDataCache* textureDataCache,
78 PipelineDataGatherer* gatherer,
79 const Layout layout,
80 const RenderStep* step,
81 const DrawParams& params) {
82 gatherer->resetWithNewLayout(layout);
83 step->writeUniformsAndTextures(params, gatherer);
84
85 const UniformDataBlock* uniforms =
86 gatherer->hasUniforms() ? uniformDataCache->insert(gatherer->finishUniformDataBlock())
87 : nullptr;
88 const TextureDataBlock* textures =
89 gatherer->hasTextures() ? textureDataCache->insert(gatherer->textureDataBlock())
90 : nullptr;
91
92 return { uniforms, textures };
93}
94
96 std::optional<SkBlendMode> blendMode,
98 // If the blend mode is absent, this is assumed to be for a runtime blender, for which we always
99 // do a dst read.
100 if (!blendMode || *blendMode > SkBlendMode::kLastCoeffMode) {
101 return caps->getDstReadRequirement();
102 }
103
104 const bool isLCD = coverage == Coverage::kLCD;
105 const bool hasCoverage = coverage != Coverage::kNone;
106 BlendFormula blendFormula = isLCD ? skgpu::GetLCDBlendFormula(*blendMode)
107 : skgpu::GetBlendFormula(false, hasCoverage, *blendMode);
108 if ((blendFormula.hasSecondaryOutput() && !caps->shaderCaps()->fDualSourceBlendingSupport) ||
109 (coverage == Coverage::kLCD && blendMode != SkBlendMode::kSrcOver)) {
110 return caps->getDstReadRequirement();
111 }
112
114}
115
116namespace {
117
118std::string get_uniform_header(int bufferID, const char* name) {
119 std::string result;
120
121 SkSL::String::appendf(&result, "layout (binding=%d) uniform %sUniforms {\n", bufferID, name);
122
123 return result;
124}
125
126std::string get_uniforms(Layout layout,
127 SkSpan<const Uniform> uniforms,
128 int* offset,
129 int manglingSuffix,
130 bool* wrotePaintColor) {
131 std::string result;
132 UniformOffsetCalculator offsetter(layout, *offset);
133
134 std::string uniformName;
135 for (const Uniform& u : uniforms) {
136 uniformName = u.name();
137
138 if (u.isPaintColor() && wrotePaintColor) {
139 if (*wrotePaintColor) {
140 SkSL::String::appendf(&result, " // deduplicated %s\n", u.name());
141 continue;
142 }
143
144 *wrotePaintColor = true;
145 } else {
146 if (manglingSuffix >= 0) {
147 uniformName.append("_");
148 uniformName.append(std::to_string(manglingSuffix));
149 }
150 }
151
153 " layout(offset=%d) %s %s",
154 offsetter.advanceOffset(u.type(), u.count()),
155 SkSLTypeString(u.type()),
156 uniformName.c_str());
157 if (u.count()) {
158 result.append("[");
159 result.append(std::to_string(u.count()));
160 result.append("]");
161 }
162 result.append(";\n");
163 }
164
165 *offset = offsetter.size();
166 return result;
167}
168
169std::string get_node_uniforms(Layout layout,
170 const ShaderNode* node,
171 int* offset,
172 int* numUniforms,
173 bool* wrotePaintColor) {
174 std::string result;
175 SkSpan<const Uniform> uniforms = node->entry()->fUniforms;
176
177 if (!uniforms.empty()) {
178 SkSL::String::appendf(&result, "// %d - %s uniforms\n",
179 node->keyIndex(), node->entry()->fName);
180 result += get_uniforms(layout, uniforms, offset, node->keyIndex(), wrotePaintColor);
181 }
182
183 *numUniforms += uniforms.size();
184 for (const ShaderNode* child : node->children()) {
185 result += get_node_uniforms(layout, child, offset, numUniforms, wrotePaintColor);
186 }
187 return result;
188}
189
190std::string get_ssbo_fields(SkSpan<const Uniform> uniforms,
191 int manglingSuffix,
192 bool* wrotePaintColor) {
193 std::string result;
194
195 std::string uniformName;
196 for (const Uniform& u : uniforms) {
197 uniformName = u.name();
198
199 if (u.isPaintColor() && wrotePaintColor) {
200 if (*wrotePaintColor) {
201 SkSL::String::appendf(&result, " // deduplicated %s\n", u.name());
202 continue;
203 }
204
205 *wrotePaintColor = true;
206 } else {
207 if (manglingSuffix >= 0) {
208 uniformName.append("_");
209 uniformName.append(std::to_string(manglingSuffix));
210 }
211 }
212
213 SkSL::String::appendf(&result, " %s %s", SkSLTypeString(u.type()), uniformName.c_str());
214 if (u.count()) {
215 SkSL::String::appendf(&result, "[%d]", u.count());
216 }
217 result.append(";\n");
218 }
219
220 return result;
221}
222
223std::string get_node_ssbo_fields(const ShaderNode* node, int* numUniforms, bool* wrotePaintColor) {
224 std::string result;
225 SkSpan<const Uniform> uniforms = node->entry()->fUniforms;
226
227 if (!uniforms.empty()) {
228 SkSL::String::appendf(&result, "// %d - %s uniforms\n",
229 node->keyIndex(), node->entry()->fName);
230
231 result += get_ssbo_fields(uniforms, node->keyIndex(), wrotePaintColor);
232 }
233
234 *numUniforms += uniforms.size();
235 for (const ShaderNode* child : node->children()) {
236 result += get_node_ssbo_fields(child, numUniforms, wrotePaintColor);
237 }
238 return result;
239}
240
241std::string get_node_texture_samplers(const ResourceBindingRequirements& bindingReqs,
242 const ShaderNode* node,
243 int* binding) {
244 std::string result;
245 SkSpan<const TextureAndSampler> samplers = node->entry()->fTexturesAndSamplers;
246
247 if (!samplers.empty()) {
248 SkSL::String::appendf(&result, "// %d - %s samplers\n",
249 node->keyIndex(), node->entry()->fName);
250
251 for (const TextureAndSampler& t : samplers) {
252 result += EmitSamplerLayout(bindingReqs, binding);
253 SkSL::String::appendf(&result, " sampler2D %s_%d;\n",
254 t.name(), node->keyIndex());
255 }
256 }
257
258 for (const ShaderNode* child : node->children()) {
259 result += get_node_texture_samplers(bindingReqs, child, binding);
260 }
261 return result;
262}
263
264} // anonymous namespace
265
266std::string EmitPaintParamsUniforms(int bufferID,
267 const Layout layout,
269 int* numUniforms,
270 int* uniformsTotalBytes,
271 bool* wrotePaintColor) {
272 int offset = 0;
273
274 std::string result = get_uniform_header(bufferID, "FS");
275 for (const ShaderNode* n : nodes) {
276 result += get_node_uniforms(layout, n, &offset, numUniforms, wrotePaintColor);
277 }
278 result.append("};\n\n");
279
280 if (!*numUniforms) {
281 // No uniforms were added
282 return {};
283 }
284
285 if (uniformsTotalBytes) {
286 *uniformsTotalBytes = offset;
287 }
288
289 return result;
290}
291
292std::string EmitRenderStepUniforms(int bufferID,
293 const Layout layout,
294 SkSpan<const Uniform> uniforms,
295 int* renderStepUniformsTotalBytes) {
296 int offset = 0;
297
298 std::string result = get_uniform_header(bufferID, "Step");
299 result += get_uniforms(layout, uniforms, &offset, -1, /* wrotePaintColor= */ nullptr);
300 result.append("};\n\n");
301
302 if (renderStepUniformsTotalBytes) {
303 *renderStepUniformsTotalBytes = offset;
304 }
305
306 return result;
307}
308
310 int bufferID,
312 int* numUniforms,
313 bool* wrotePaintColor) {
314
315 std::string result;
316 result += "struct FSUniformData {\n";
317 for (const ShaderNode* n : nodes) {
318 result += get_node_ssbo_fields(n, numUniforms, wrotePaintColor);
319 }
320 result += "};\n\n";
321
322 if (!*numUniforms) {
323 // No uniforms were added
324 return {};
325 }
326
328 "layout (binding=%d) readonly buffer FSUniforms {\n"
329 " FSUniformData fsUniformData[];\n"
330 "};\n",
331 bufferID);
332 return result;
333}
334
336 int bufferID,
337 SkSpan<const Uniform> uniforms) {
338
339 std::string result;
340 result += "struct StepUniformData {\n" +
341 get_ssbo_fields(uniforms, -1, /* wrotePaintColor= */ nullptr) +
342 "};\n\n";
343
345 "layout (binding=%d) readonly buffer StepUniforms {\n"
346 " StepUniformData stepUniformData[];\n"
347 "};\n",
348 bufferID);
349 return result;
350}
351
352std::string EmitUniformsFromStorageBuffer(const char* bufferNamePrefix,
353 const char* ssboIndex,
354 SkSpan<const Uniform> uniforms) {
355 std::string result;
356
357 for (const Uniform& u : uniforms) {
358 SkSL::String::appendf(&result, "%s %s", SkSLTypeString(u.type()), u.name());
359 if (u.count()) {
360 SkSL::String::appendf(&result, "[%d]", u.count());
361 }
363 &result, " = %sUniformData[%s].%s;\n", bufferNamePrefix, ssboIndex, u.name());
364 }
365
366 return result;
367}
368
369std::string EmitStorageBufferAccess(const char* bufferNamePrefix,
370 const char* ssboIndex,
371 const char* uniformName) {
372 return SkSL::String::printf("%sUniformData[%s].%s", bufferNamePrefix, ssboIndex, uniformName);
373}
374
377 int* binding) {
378 std::string result;
379 for (const ShaderNode* n : nodes) {
380 result += get_node_texture_samplers(bindingReqs, n, binding);
381 }
382 return result;
383}
384
385std::string EmitSamplerLayout(const ResourceBindingRequirements& bindingReqs, int* binding) {
386 std::string result;
387
388 // If fDistinctIndexRanges is false, then texture and sampler indices may clash with other
389 // resource indices. Graphite assumes that they will be placed in descriptor set (Vulkan) and
390 // bind group (Dawn) index 1.
391 const char* distinctIndexRange = bindingReqs.fDistinctIndexRanges ? "" : "set=1, ";
392
393 if (bindingReqs.fSeparateTextureAndSamplerBinding) {
394 int samplerIndex = (*binding)++;
395 int textureIndex = (*binding)++;
396 result = SkSL::String::printf("layout(webgpu, %ssampler=%d, texture=%d)",
397 distinctIndexRange,
398 samplerIndex,
399 textureIndex);
400 } else {
401 int samplerIndex = (*binding)++;
402 result = SkSL::String::printf("layout(%sbinding=%d)",
403 distinctIndexRange,
404 samplerIndex);
405 }
406 return result;
407}
408
409namespace {
410std::string emit_attributes(SkSpan<const Attribute> vertexAttrs,
411 SkSpan<const Attribute> instanceAttrs) {
412 std::string result;
413
414 int attr = 0;
415 auto add_attrs = [&](SkSpan<const Attribute> attrs) {
416 for (auto a : attrs) {
417 SkSL::String::appendf(&result, " layout(location=%d) in ", attr++);
418 result.append(SkSLTypeString(a.gpuType()));
419 SkSL::String::appendf(&result, " %s;\n", a.name());
420 }
421 };
422
423 if (!vertexAttrs.empty()) {
424 result.append("// vertex attrs\n");
425 add_attrs(vertexAttrs);
426 }
427 if (!instanceAttrs.empty()) {
428 result.append("// instance attrs\n");
429 add_attrs(instanceAttrs);
430 }
431
432 return result;
433}
434} // anonymous namespace
435
436std::string EmitVaryings(const RenderStep* step,
437 const char* direction,
438 bool emitSsboIndicesVarying,
439 bool emitLocalCoordsVarying) {
440 std::string result;
441 int location = 0;
442
443 if (emitSsboIndicesVarying) {
445 " layout(location=%d) %s flat ushort2 %s;\n",
446 location++,
447 direction,
449 }
450
451 if (emitLocalCoordsVarying) {
452 SkSL::String::appendf(&result, " layout(location=%d) %s ", location++, direction);
454 SkSL::String::appendf(&result, " localCoordsVar;\n");
455 }
456
457 for (auto v : step->varyings()) {
458 SkSL::String::appendf(&result, " layout(location=%d) %s ", location++, direction);
459 result.append(SkSLTypeString(v.fType));
460 SkSL::String::appendf(&result, " %s;\n", v.fName);
461 }
462
463 return result;
464}
465
467 const RenderStep* step,
468 bool useStorageBuffers,
469 bool defineLocalCoordsVarying) {
471
472 const bool hasStepUniforms = step->numUniforms() > 0;
473 const bool useStepStorageBuffer = useStorageBuffers && hasStepUniforms;
474 const bool useShadingStorageBuffer = useStorageBuffers && step->performsShading();
475
476 // TODO: To more completely support end-to-end rendering, this will need to be updated so that
477 // the RenderStep shader snippet can produce a device coord, a local coord, and depth.
478 // If the paint combination doesn't need the local coord it can be ignored, otherwise we need
479 // a varying for it. The fragment function's output will need to be updated to have a color and
480 // the depth, or when there's no combination, just the depth. Lastly, we also should add the
481 // static/intrinsic uniform binding point so that we can handle normalizing the device position
482 // produced by the RenderStep automatically.
483
484 // Fixed program header
485 std::string sksl =
486 "layout (binding=0) uniform intrinsicUniforms {\n"
487 " layout(offset=0) float4 rtAdjust;\n"
488 "};\n"
489 "\n";
490
491 if (step->numVertexAttributes() > 0 || step->numInstanceAttributes() > 0) {
492 sksl += emit_attributes(step->vertexAttributes(), step->instanceAttributes());
493 }
494
495 // Uniforms needed by RenderStep
496 // The uniforms are mangled by having their index in 'fEntries' as a suffix (i.e., "_%d")
497 // TODO: replace hard-coded bufferID with the backend's renderstep uniform-buffer index.
498 if (hasStepUniforms) {
499 if (useStepStorageBuffer) {
500 sksl += EmitRenderStepStorageBuffer(/* bufferID= */ 1, step->uniforms());
501 } else {
502 sksl += EmitRenderStepUniforms(/* bufferID= */ 1,
503 bindingReqs.fUniformBufferLayout,
504 step->uniforms(),
505 &result.fRenderStepUniformsTotalBytes);
506 }
507 }
508
509 // Varyings needed by RenderStep
510 sksl += EmitVaryings(step, "out", useShadingStorageBuffer, defineLocalCoordsVarying);
511
512 // Vertex shader function declaration
513 sksl += "void main() {";
514 // Create stepLocalCoords which render steps can write to.
515 sksl += "float2 stepLocalCoords = float2(0);";
516 // Vertex shader body
517 if (useStepStorageBuffer) {
518 // Extract out render step uniforms from SSBO, declaring local variables with the expected
519 // uniform names so that RenderStep SkSL is independent of storage choice.
521 &sksl, "uint stepSsboIndex = %s.x;\n", RenderStep::ssboIndicesAttribute());
522 sksl += EmitUniformsFromStorageBuffer("step", "stepSsboIndex", step->uniforms());
523 }
524
525 sksl += step->vertexSkSL();
526 sksl += "sk_Position = float4(devPosition.xy * rtAdjust.xy + devPosition.ww * rtAdjust.zw,"
527 "devPosition.zw);";
528
529 if (useShadingStorageBuffer) {
530 // Assign SSBO index values to the SSBO index varying.
532 "%s = %s;",
535 }
536
537 if (defineLocalCoordsVarying) {
538 // Assign Render Step's stepLocalCoords to the localCoordsVar varying.
539 sksl += "localCoordsVar = stepLocalCoords;";
540 }
541 sksl += "}";
542
543 result.fSkSL = std::move(sksl);
544 result.fLabel = step->name();
545 if (defineLocalCoordsVarying) {
546 result.fLabel += " (w/ local coords)";
547 }
548
549 return result;
550}
551
553 const ShaderCodeDictionary* dict,
554 const RuntimeEffectDictionary* rteDict,
555 const RenderStep* step,
556 UniquePaintParamsID paintID,
557 bool useStorageBuffers,
558 skgpu::Swizzle writeSwizzle) {
560 if (!paintID.isValid()) {
561 // Depth-only draw so no fragment shader to compile
562 return {};
563 }
564
565 const char* shadingSsboIndex =
566 useStorageBuffers && step->performsShading() ? "shadingSsboIndex" : nullptr;
567 ShaderInfo shaderInfo(paintID, dict, rteDict, shadingSsboIndex);
568
569 result.fSkSL = shaderInfo.toSkSL(caps,
570 step,
571 useStorageBuffers,
572 &result.fNumTexturesAndSamplers,
573 &result.fNumPaintUniforms,
574 &result.fRenderStepUniformsTotalBytes,
575 &result.fPaintUniformsTotalBytes,
576 &result.fHasGradientBuffer,
577 writeSwizzle);
578
579 // Extract blend info after integrating the RenderStep into the final fragment shader in case
580 // that changes the HW blending choice to handle analytic coverage.
581 result.fBlendInfo = shaderInfo.blendInfo();
582 result.fRequiresLocalCoords = shaderInfo.needsLocalCoords();
583 result.fData = {shaderInfo.data()};
584 result.fLabel = writeSwizzle.asString().c_str();
585 result.fLabel += " + ";
586 result.fLabel = step->name();
587 result.fLabel += " + ";
588 result.fLabel += dict->idToString(paintID).c_str();
589
590 return result;
591}
592
594 const RenderPassDesc& renderPassDesc,
595 const RenderStep* renderStep,
596 UniquePaintParamsID paintID) {
597 std::string label = renderPassDesc.toPipelineLabel().c_str(); // includes the write swizzle
598 label += " + ";
599 label += renderStep->name();
600 label += " + ";
601 label += dict->idToString(paintID).c_str(); // will be "(empty)" for depth-only draws
602 return label;
603}
604
605std::string BuildComputeSkSL(const Caps* caps, const ComputeStep* step) {
606 std::string sksl =
607 SkSL::String::printf("layout(local_size_x=%u, local_size_y=%u, local_size_z=%u) in;\n",
608 step->localDispatchSize().fWidth,
609 step->localDispatchSize().fHeight,
610 step->localDispatchSize().fDepth);
611
612 const auto& bindingReqs = caps->resourceBindingRequirements();
613 bool distinctRanges = bindingReqs.fDistinctIndexRanges;
614 bool separateSampler = bindingReqs.fSeparateTextureAndSamplerBinding;
615
616 int index = 0;
617 int texIdx = 0;
618 // NOTE: SkSL Metal codegen always assigns the same binding index to a texture and its sampler.
619 // TODO: This could cause sampler indices to not be tightly packed if the sampler2D declaration
620 // comes after 1 or more storage texture declarations (which don't have samplers). An optional
621 // "layout(msl, sampler=T, texture=T)" syntax to count them separately (like we do for WGSL)
622 // could come in handy here but it's not supported in MSL codegen yet.
623
624 for (const ComputeStep::ResourceDesc& r : step->resources()) {
626 switch (r.fType) {
627 case Type::kUniformBuffer:
628 SkSL::String::appendf(&sksl, "layout(binding=%d) uniform ", index++);
629 sksl += r.fSkSL;
630 break;
631 case Type::kStorageBuffer:
632 case Type::kIndirectBuffer:
633 SkSL::String::appendf(&sksl, "layout(binding=%d) buffer ", index++);
634 sksl += r.fSkSL;
635 break;
636 case Type::kReadOnlyStorageBuffer:
637 SkSL::String::appendf(&sksl, "layout(binding=%d) readonly buffer ", index++);
638 sksl += r.fSkSL;
639 break;
640 case Type::kWriteOnlyStorageTexture:
641 SkSL::String::appendf(&sksl, "layout(binding=%d, rgba8) writeonly texture2D ",
642 distinctRanges ? texIdx++ : index++);
643 sksl += r.fSkSL;
644 break;
645 case Type::kReadOnlyTexture:
646 SkSL::String::appendf(&sksl, "layout(binding=%d, rgba8) readonly texture2D ",
647 distinctRanges ? texIdx++ : index++);
648 sksl += r.fSkSL;
649 break;
650 case Type::kSampledTexture:
651 if (distinctRanges) {
652 SkSL::String::appendf(&sksl, "layout(metal, binding=%d) ", texIdx++);
653 } else if (separateSampler) {
655 &sksl, "layout(webgpu, sampler=%d, texture=%d) ", index, index + 1);
656 index += 2;
657 } else {
658 SkSL::String::appendf(&sksl, "layout(binding=%d) ", index++);
659 }
660 sksl += "sampler2D ";
661 sksl += r.fSkSL;
662 break;
663 }
664 sksl += ";\n";
665 }
666
667 sksl += step->computeSkSL();
668 return sksl;
669}
670
671} // namespace skgpu::graphite
static int step(int x, SkScalar min, SkScalar max)
Definition: BlurTest.cpp:215
@ kLastCoeffMode
last porter duff blend mode
@ kSrcOver
r = s + (1-sa)*d
static bool isLCD(const SkScalerContextRec &rec)
const char * SkSLTypeString(SkSLType t)
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
Definition: SkM44.h:150
constexpr bool empty() const
Definition: SkSpan_impl.h:96
constexpr size_t size() const
Definition: SkSpan_impl.h:95
const char * c_str() const
Definition: SkString.h:133
bool hasSecondaryOutput() const
Definition: BlendFormula.h:66
SkString asString() const
Definition: Swizzle.cpp:46
const ResourceBindingRequirements & resourceBindingRequirements() const
Definition: Caps.h:150
DstReadRequirement getDstReadRequirement() const
Definition: Caps.cpp:152
const SkSL::ShaderCaps * shaderCaps() const
Definition: Caps.h:75
bool isShape() const
Definition: Geometry.h:96
bool isEdgeAAQuad() const
Definition: Geometry.h:99
const T * insert(const T &dataBlock)
UniformDataBlock finishUniformDataBlock()
Definition: PipelineData.h:127
const TextureDataBlock & textureDataBlock()
Definition: PipelineData.h:105
const ShaderCodeDictionary * shaderCodeDictionary() const
Definition: RecorderPriv.h:41
TextureDataCache * textureDataCache()
Definition: RecorderPriv.h:57
UniformDataCache * uniformDataCache()
Definition: RecorderPriv.h:56
static const char * ssboIndicesAttribute()
Definition: Renderer.h:135
const char * name() const
Definition: Renderer.h:116
static const char * ssboIndicesVarying()
Definition: Renderer.h:139
UniquePaintParamsID findOrCreate(PaintParamsKeyBuilder *) SK_EXCLUDES(fSpinLock)
SkString idToString(UniquePaintParamsID id) const
const EmbeddedViewParams * params
struct MyStruct a[10]
GAsyncResult * result
std::string printf(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: SkSLString.cpp:83
std::string void appendf(std::string *str, const char *fmt,...) SK_PRINTF_LIKE(2
Definition: SkSLString.cpp:92
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
VertSkSLInfo BuildVertexSkSL(const ResourceBindingRequirements &bindingReqs, const RenderStep *step, bool useStorageBuffers, bool defineLocalCoordsVarying)
std::string EmitPaintParamsUniforms(int bufferID, const Layout layout, SkSpan< const ShaderNode * > nodes, int *numUniforms, int *uniformsTotalBytes, bool *wrotePaintColor)
std::string BuildComputeSkSL(const Caps *caps, const ComputeStep *step)
std::string EmitStorageBufferAccess(const char *bufferNamePrefix, const char *ssboIndex, const char *uniformName)
DstReadRequirement GetDstReadRequirement(const Caps *caps, std::optional< SkBlendMode > blendMode, Coverage coverage)
std::string EmitTexturesAndSamplers(const ResourceBindingRequirements &bindingReqs, SkSpan< const ShaderNode * > nodes, int *binding)
FragSkSLInfo BuildFragmentSkSL(const Caps *caps, const ShaderCodeDictionary *dict, const RuntimeEffectDictionary *rteDict, const RenderStep *step, UniquePaintParamsID paintID, bool useStorageBuffers, skgpu::Swizzle writeSwizzle)
std::string GetPipelineLabel(const ShaderCodeDictionary *dict, const RenderPassDesc &renderPassDesc, const RenderStep *renderStep, UniquePaintParamsID paintID)
std::string EmitRenderStepStorageBuffer(int bufferID, SkSpan< const Uniform > uniforms)
std::string EmitRenderStepUniforms(int bufferID, const Layout layout, SkSpan< const Uniform > uniforms, int *renderStepUniformsTotalBytes)
std::string EmitVaryings(const RenderStep *step, const char *direction, bool emitSsboIndicesVarying, bool emitLocalCoordsVarying)
std::string EmitPaintParamsStorageBuffer(int bufferID, SkSpan< const ShaderNode * > nodes, int *numUniforms, bool *wrotePaintColor)
std::tuple< const UniformDataBlock *, const TextureDataBlock * > ExtractRenderStepData(UniformDataCache *uniformDataCache, TextureDataCache *textureDataCache, PipelineDataGatherer *gatherer, const Layout layout, const RenderStep *step, const DrawParams &params)
DstReadRequirement
Definition: Caps.h:64
std::string EmitSamplerLayout(const ResourceBindingRequirements &bindingReqs, int *binding)
std::tuple< UniquePaintParamsID, const UniformDataBlock *, const TextureDataBlock * > ExtractPaintData(Recorder *recorder, PipelineDataGatherer *gatherer, PaintParamsKeyBuilder *builder, const Layout layout, const SkM44 &local2Dev, const PaintParams &p, const Geometry &geometry, sk_sp< TextureProxy > dstTexture, SkIPoint dstOffset, const SkColorInfo &targetColorInfo)
std::string EmitUniformsFromStorageBuffer(const char *bufferNamePrefix, const char *ssboIndex, SkSpan< const Uniform > uniforms)
BlendFormula GetBlendFormula(bool isOpaque, bool hasCoverage, SkBlendMode xfermode)
BlendFormula GetLCDBlendFormula(SkBlendMode xfermode)
static SkString to_string(int n)
Definition: nanobench.cpp:119
SeparatedVector2 offset
bool fDualSourceBlendingSupport
Definition: SkSLUtil.h:84