1/*
2 * Copyright 2020 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
8#ifndef SkSLSampleUsage_DEFINED
9#define SkSLSampleUsage_DEFINED
10
11#include <string>
12
13namespace SkSL {
14
15/**
16 * Represents all of the ways that a fragment processor is sampled by its parent.
17 */
18struct SampleUsage {
19 enum class Kind {
20 // No sample(child, matrix) call affects the FP.
21 kNone,
22 // The FP is sampled with a matrix whose value is fixed and based only on literals or
23 // uniforms, and thus the transform can be hoisted to the vertex shader (assuming that
24 // its parent can also be hoisted, i.e. not sampled explicitly).
25 kUniform,
26 // The FP is sampled with a non-literal/uniform value, or matrix-sampled multiple times,
27 // and thus the transform cannot be hoisted to the vertex shader.
28 kVariable
29 };
30
31 // Make a SampleUsage that corresponds to no sampling of the child at all
32 SampleUsage() = default;
33
34 // This corresponds to sample(child, color, matrix) calls where every call site in the FP has
35 // the same matrix, and that matrix's value is uniform (some expression only involving literals
36 // and uniform variables).
37 static SampleUsage UniformMatrix(std::string expression, bool hasPerspective = true) {
38 return SampleUsage(Kind::kUniform, std::move(expression), hasPerspective, false, false);
39 }
40
41 // This corresponds to sample(child, color, matrix) where the 3rd argument is an expression that
42 // can't be hoisted to the vertex shader, or where the expression used is not the same at all
43 // call sites in the FP.
44 static SampleUsage VariableMatrix(bool hasPerspective = true) {
45 return SampleUsage(Kind::kVariable, "", hasPerspective, false, false);
46 }
47
48 static SampleUsage Explicit() {
49 return SampleUsage(Kind::kNone, "", false, true, false);
50 }
51
52 static SampleUsage PassThrough() {
53 return SampleUsage(Kind::kNone, "", false, false, true);
54 }
55
56 SampleUsage merge(const SampleUsage& other);
57
58 bool isSampled() const {
59 return this->hasMatrix() || fExplicitCoords || fPassThrough;
60 }
61
62 bool hasMatrix() const { return fKind != Kind::kNone; }
63 bool hasUniformMatrix() const { return fKind == Kind::kUniform; }
64 bool hasVariableMatrix() const { return fKind == Kind::kVariable; }
65
66 Kind fKind = Kind::kNone;
67 // The uniform expression representing the matrix (only valid when kind == kUniform)
68 std::string fExpression;
69 // FIXME: We can expand this to track a more general matrix type to allow for optimizations on
70 // identity or scale+translate matrices too.
71 bool fHasPerspective = false;
72
73 bool fExplicitCoords = false;
74 bool fPassThrough = false;
75
76 SampleUsage(Kind kind,
77 std::string expression,
78 bool hasPerspective,
79 bool explicitCoords,
80 bool passThrough)
81 : fKind(kind)
82 , fExpression(expression)
83 , fHasPerspective(hasPerspective)
84 , fExplicitCoords(explicitCoords)
85 , fPassThrough(passThrough) {}
86
87 std::string constructor(std::string perspectiveExpression) const;
88};
89
90} // namespace SkSL
91
92#endif
93