292 {
293
296 const bool useStepStorageBuffer = useStorageBuffers && hasStepUniforms;
297 const bool useShadingStorageBuffer = useStorageBuffers &&
step->performsShading();
298 const bool useGradientStorageBuffer = useStorageBuffers && (fSnippetRequirementFlags
300
303 "in",
304 useShadingStorageBuffer,
305 defineLocalCoordsVarying);
306
307
308
309
310
311 const ResourceBindingRequirements& bindingReqs = caps->resourceBindingRequirements();
312 if (hasStepUniforms) {
313 if (useStepStorageBuffer) {
315 } else {
317 bindingReqs.fUniformBufferLayout,
319 renderStepUniformTotalBytes);
320 }
321 }
322
323 bool wrotePaintColor = false;
324 if (useShadingStorageBuffer) {
326 fRootNodes,
327 numPaintUniforms,
328 &wrotePaintColor);
330 } else {
332 bindingReqs.fUniformBufferLayout,
333 fRootNodes,
334 numPaintUniforms,
335 paintUniformsTotalBytes,
336 &wrotePaintColor);
337 }
338
339 if (useGradientStorageBuffer) {
340 SkASSERT(caps->storageBufferSupport());
341
342
343
344
345 int binding = bindingReqs.fSeparateTextureAndSamplerBinding ? 3 : 5;
347 "layout (binding=%d) readonly buffer FSGradientBuffer {\n"
348 " float %s[];\n"
349 "};\n", binding, caps->shaderCaps()->fFloatBufferArrayName);
350 *hasGradientBuffer = true;
351 }
352
353 {
354 int binding = 0;
356 if (
step->hasTextures()) {
357 preamble +=
step->texturesAndSamplersSkSL(bindingReqs, &binding);
358 }
359
360
361 if (numTexturesAndSamplersUsed) {
362 *numTexturesAndSamplersUsed = binding;
363 }
364 }
365
366 if (
step->emitsPrimitiveColor()) {
367
368
369 preamble += "half4 primitiveColor;";
370 }
371
372
373
374
375 emit_preambles(*this, fRootNodes, "", &preamble);
376
377 std::string mainBody = "void main() {";
378
379
380 mainBody += "half4 initialColor = half4(0);";
381
382 if (useShadingStorageBuffer) {
384 "%s = %s.y;\n",
387 }
388
389 if (
step->emitsPrimitiveColor()) {
390 mainBody +=
step->fragmentColorSkSL();
391 }
392
393
394
395 const ShaderNode* clipShaderNode = nullptr;
396
397
398
399 static constexpr char kUnusedDstColor[] = "half4(1)";
400 static constexpr char kUnusedLocalCoords[] = "float2(0)";
401 ShaderSnippet::Args
args = {
"initialColor",
402 kUnusedDstColor,
404 for (const ShaderNode* node : fRootNodes) {
407 clipShaderNode = node;
408 continue;
409 }
410
411
414 args.fPriorStageOutput = emit_glue_code_for_entry(*
this, node,
args, &mainBody);
415 }
416 }
417
420 args.fPriorStageOutput.c_str(),
421 writeSwizzle.asString().c_str());
422 }
423
424 const char* outColor =
args.fPriorStageOutput.c_str();
427 if (useStepStorageBuffer) {
429 "uint stepSsboIndex = %s.x;\n",
432 }
433
434 mainBody += "half4 outputCoverage = half4(1);";
435 mainBody +=
step->fragmentCoverageSkSL();
436
437 if (clipShaderNode) {
438 std::string clipShaderOutput =
439 emit_glue_code_for_entry(*
this, clipShaderNode,
args, &mainBody);
441 }
442
443
444 BlendFormula coverageBlendFormula =
449
451
452
453
454
455
459
460
461
462
463
464 mainBody +=
465 "if (all(lessThanEqual(outputCoverage.rgb, half3(0)))) {"
466 "discard;"
467 "}";
468 }
469
470
472 &mainBody,
473 "sk_FragColor = %s * outputCoverage + surfaceColor * (1.0 - outputCoverage);",
474 outColor);
477 &mainBody,
478 "half3 lerpRGB = mix(surfaceColor.aaa, %s.aaa, outputCoverage.rgb);"
479 "sk_FragColor.a = max(max(lerpRGB.r, lerpRGB.g), lerpRGB.b);",
480 outColor);
481 }
482
483 } else {
484 fBlendInfo = {coverageBlendFormula.equation(),
485 coverageBlendFormula.srcCoeff(),
486 coverageBlendFormula.dstCoeff(),
488 coverageBlendFormula.modifiesDst()};
489
491 mainBody += "outputCoverage.a = max(max(outputCoverage.r, "
492 "outputCoverage.g), "
493 "outputCoverage.b);";
494 }
496 &mainBody, coverageBlendFormula.primaryOutput(), "sk_FragColor", outColor);
497 if (coverageBlendFormula.hasSecondaryOutput()) {
499 coverageBlendFormula.secondaryOutput(),
500 "sk_SecondaryFragColor",
501 outColor);
502 }
503 }
504
505 } else {
507 }
508 mainBody += "}\n";
509
510 return preamble + "\n" + mainBody;
511}
static int step(int x, SkScalar min, SkScalar max)
constexpr SkPMColor4f SK_PMColor4fTRANSPARENT
static constexpr Swizzle RGBA()
static const char * ssboIndicesVarying()
const char * ssboIndex() const
bool needsLocalCoords() const
bool needsSurfaceColor() const
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
std::string void appendf(std::string *str, const char *fmt,...) SK_PRINTF_LIKE(2
std::string EmitPaintParamsUniforms(int bufferID, const Layout layout, SkSpan< const ShaderNode * > nodes, int *numUniforms, int *uniformsTotalBytes, bool *wrotePaintColor)
std::string EmitTexturesAndSamplers(const ResourceBindingRequirements &bindingReqs, SkSpan< const ShaderNode * > nodes, int *binding)
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)
void append_color_output(std::string *mainBody, BlendFormula::OutputType outputType, const char *outColor, const char *inColor)
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)