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