blob: cf55ed74cb454816ced7110957ab79c61c2e25dc [file] [log] [blame]
joshualitt30ba4362014-08-21 20:18:45 -07001/*
2 * Copyright 2014 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
egdaniel2d721d32015-11-11 13:06:05 -08008#ifndef GrGLSLFragmentShaderBuilder_DEFINED
9#define GrGLSLFragmentShaderBuilder_DEFINED
joshualitt47bb3822014-10-07 16:43:25 -070010
Brian Salomon096b0912019-08-14 16:56:13 -040011#include "src/gpu/GrBlend.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/gpu/GrProcessor.h"
Ethan Nicholasc6dce5a2019-07-24 16:51:36 -040013#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/gpu/glsl/GrGLSLShaderBuilder.h"
egdaniel7dc4bd02015-10-29 07:57:01 -070015
egdaniel574a4c12015-11-02 06:22:44 -080016class GrRenderTarget;
egdaniel8dcdedc2015-11-11 06:27:20 -080017class GrGLSLVarying;
joshualitt74077b92014-10-24 11:26:03 -070018
joshualittb0a8a372014-09-23 09:50:21 -070019/*
cdalton85285412016-02-18 12:37:07 -080020 * This class is used by fragment processors to build their fragment code.
joshualittb0a8a372014-09-23 09:50:21 -070021 */
Brian Salomonffd15ea2020-07-01 16:48:20 -040022class GrGLSLFPFragmentBuilder : virtual public GrGLSLShaderBuilder {
joshualittb0a8a372014-09-23 09:50:21 -070023public:
Brian Salomonffd15ea2020-07-01 16:48:20 -040024 /** Appease the compiler; the derived class initializes GrGLSLShaderBuilder. */
25 GrGLSLFPFragmentBuilder() : GrGLSLShaderBuilder(nullptr) {
Michael Ludwig45191342020-03-24 12:29:39 -040026 // Suppress unused warning error
27 (void) fDummyPadding;
28 }
joshualitt47bb3822014-10-07 16:43:25 -070029
Chris Daltond7291ba2019-03-07 14:17:03 -070030 /**
31 * Returns the variable name that holds the array of sample offsets from pixel center to each
32 * sample location. Before this is called, a processor must have advertised that it will use
33 * CustomFeatures::kSampleLocations.
34 */
35 virtual const char* sampleOffsets() = 0;
36
Chris Dalton0dffbab2019-03-27 13:08:50 -060037 enum class ScopeFlags {
38 // Every fragment will always execute this code, and will do it exactly once.
39 kTopLevel = 0,
40 // Either all fragments in a given primitive, or none, will execute this code.
41 kInsidePerPrimitiveBranch = (1 << 0),
42 // Any given fragment may or may not execute this code.
43 kInsidePerPixelBranch = (1 << 1),
44 // This code will be executed more than once.
45 kInsideLoop = (1 << 2)
Robert Phillips7f861922018-01-30 13:13:42 +000046 };
47
48 /**
Chris Daltond31b5e72019-02-26 18:02:16 -070049 * Subtracts multisample coverage by AND-ing the sample mask with the provided "mask".
50 * Sample N corresponds to bit "1 << N".
51 *
52 * If the given scope is "kTopLevel" and the sample mask has not yet been modified, this method
53 * assigns the sample mask in place rather than pre-initializing it to ~0 then AND-ing it.
54 *
55 * Requires MSAA and GLSL support for sample variables.
56 */
Chris Dalton0dffbab2019-03-27 13:08:50 -060057 virtual void maskOffMultisampleCoverage(const char* mask, ScopeFlags) = 0;
58
59 /**
60 * Turns off coverage at each sample where the implicit function fn > 0.
61 *
62 * The provided "fn" value represents the implicit function at pixel center. We then approximate
63 * the implicit at each sample by riding the gradient, "grad", linearly from pixel center to
64 * each sample location.
65 *
66 * If "grad" is null, we approximate the gradient using HW derivatives.
67 *
68 * Requires MSAA and GLSL support for sample variables. Also requires HW derivatives if not
69 * providing a gradient.
70 */
71 virtual void applyFnToMultisampleMask(const char* fn, const char* grad, ScopeFlags) = 0;
Chris Daltond31b5e72019-02-26 18:02:16 -070072
Brian Salomonf3178a52020-04-16 10:37:55 -040073 SkString writeProcessorFunction(GrGLSLFragmentProcessor*, GrGLSLFragmentProcessor::EmitArgs&);
Ethan Nicholasf7b88202017-09-18 14:10:39 -040074
75 virtual void forceHighPrecision() = 0;
Michael Ludwig45191342020-03-24 12:29:39 -040076
77private:
Brian Salomonf3178a52020-04-16 10:37:55 -040078 /**
79 * These are called before/after calling emitCode on a child proc to update mangling.
80 */
81 virtual void onBeforeChildProcEmitCode() = 0;
82 virtual void onAfterChildProcEmitCode() = 0;
83
84 virtual const SkString& getMangleString() const = 0;
85
Michael Ludwig45191342020-03-24 12:29:39 -040086 // WARNING: LIke GrRenderTargetProxy, changes to this can cause issues in ASAN. This is caused
Michael Ludwigcc848b52020-07-22 16:36:49 -040087 // by GrGLSLProgramBuilder's GrTBlockLists requiring 16 byte alignment, but since
Michael Ludwig45191342020-03-24 12:29:39 -040088 // GrGLSLFragmentShaderBuilder has a virtual diamond hierarchy, ASAN requires all this pointers
89 // to start aligned, even though clang is already correctly offsetting the individual fields
90 // that require the larger alignment. In the current world, this extra padding is sufficient to
91 // correctly initialize GrGLSLXPFragmentBuilder second.
Brian Salomonffd15ea2020-07-01 16:48:20 -040092 char fDummyPadding[4] = {};
cdalton85285412016-02-18 12:37:07 -080093};
94
Chris Dalton0dffbab2019-03-27 13:08:50 -060095GR_MAKE_BITFIELD_CLASS_OPS(GrGLSLFPFragmentBuilder::ScopeFlags);
96
cdalton85285412016-02-18 12:37:07 -080097/*
cdalton85285412016-02-18 12:37:07 -080098 * This class is used by Xfer processors to build their fragment code.
99 */
Brian Salomonffd15ea2020-07-01 16:48:20 -0400100class GrGLSLXPFragmentBuilder : virtual public GrGLSLShaderBuilder {
cdalton85285412016-02-18 12:37:07 -0800101public:
Brian Salomonffd15ea2020-07-01 16:48:20 -0400102 /** Appease the compiler; the derived class initializes GrGLSLShaderBuilder. */
103 GrGLSLXPFragmentBuilder() : GrGLSLShaderBuilder(nullptr) {}
cdalton85285412016-02-18 12:37:07 -0800104
105 virtual bool hasCustomColorOutput() const = 0;
106 virtual bool hasSecondaryOutput() const = 0;
107
108 /** Returns the variable name that holds the color of the destination pixel. This may be nullptr
109 * if no effect advertised that it will read the destination. */
joshualittb0a8a372014-09-23 09:50:21 -0700110 virtual const char* dstColor() = 0;
111
cdalton8917d622015-05-06 13:40:21 -0700112 /** Adds any necessary layout qualifiers in order to legalize the supplied blend equation with
113 this shader. It is only legal to call this method with an advanced blend equation, and only
114 if these equations are supported. */
115 virtual void enableAdvancedBlendEquationIfNeeded(GrBlendEquation) = 0;
joshualittb0a8a372014-09-23 09:50:21 -0700116};
117
cdalton85285412016-02-18 12:37:07 -0800118/*
119 * This class implements the various fragment builder interfaces.
120 */
Chris Dalton60283612018-02-14 13:38:14 -0700121class GrGLSLFragmentShaderBuilder : public GrGLSLFPFragmentBuilder, public GrGLSLXPFragmentBuilder {
joshualitt30ba4362014-08-21 20:18:45 -0700122public:
Robert Phillips7f861922018-01-30 13:13:42 +0000123 /** Returns a nonzero key for a surface's origin. This should only be called if a processor will
124 use the fragment position and/or sample locations. */
125 static uint8_t KeyForSurfaceOrigin(GrSurfaceOrigin);
126
cdalton28f45b92016-03-07 13:58:26 -0800127 GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program);
joshualitt30ba4362014-08-21 20:18:45 -0700128
cdalton85285412016-02-18 12:37:07 -0800129 // GrGLSLFPFragmentBuilder interface.
Chris Daltond7291ba2019-03-07 14:17:03 -0700130 const char* sampleOffsets() override;
Chris Dalton0dffbab2019-03-27 13:08:50 -0600131 void maskOffMultisampleCoverage(const char* mask, ScopeFlags) override;
132 void applyFnToMultisampleMask(const char* fn, const char* grad, ScopeFlags) override;
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400133 void forceHighPrecision() override { fForceHighPrecision = true; }
cdalton85285412016-02-18 12:37:07 -0800134
135 // GrGLSLXPFragmentBuilder interface.
Michael Ludwig45191342020-03-24 12:29:39 -0400136 bool hasCustomColorOutput() const override { return SkToBool(fCustomColorOutput); }
cdalton85285412016-02-18 12:37:07 -0800137 bool hasSecondaryOutput() const override { return fHasSecondaryOutput; }
138 const char* dstColor() override;
cdalton8917d622015-05-06 13:40:21 -0700139 void enableAdvancedBlendEquationIfNeeded(GrBlendEquation) override;
140
joshualitt74077b92014-10-24 11:26:03 -0700141private:
Chris Daltond7291ba2019-03-07 14:17:03 -0700142 using CustomFeatures = GrProcessor::CustomFeatures;
143
Brian Salomonf3178a52020-04-16 10:37:55 -0400144 // GrGLSLFPFragmentBuilder private interface.
145 void onBeforeChildProcEmitCode() override;
146 void onAfterChildProcEmitCode() override;
147 const SkString& getMangleString() const override { return fMangleString; }
148
joshualitt47bb3822014-10-07 16:43:25 -0700149 // Private public interface, used by GrGLProgramBuilder to build a fragment shader
joshualitt47bb3822014-10-07 16:43:25 -0700150 void enableCustomOutput();
151 void enableSecondaryOutput();
152 const char* getPrimaryColorOutputName() const;
153 const char* getSecondaryColorOutputName() const;
Brian Salomondc092132018-04-04 10:14:16 -0400154 bool primaryColorOutputIsInOut() const;
joshualitt47bb3822014-10-07 16:43:25 -0700155
cdalton87332102016-02-26 12:22:02 -0800156#ifdef SK_DEBUG
egdaniel57d3b032015-11-13 11:57:27 -0800157 // As GLSLProcessors emit code, there are some conditions we need to verify. We use the below
joshualitt47bb3822014-10-07 16:43:25 -0700158 // state to track this. The reset call is called per processor emitted.
Chris Daltond7291ba2019-03-07 14:17:03 -0700159 bool fHasReadDstColorThisStage_DebugOnly = false;
160 CustomFeatures fUsedProcessorFeaturesThisStage_DebugOnly = CustomFeatures::kNone;
161 CustomFeatures fUsedProcessorFeaturesAllStages_DebugOnly = CustomFeatures::kNone;
162
163 void debugOnly_resetPerStageVerification() {
164 fHasReadDstColorThisStage_DebugOnly = false;
165 fUsedProcessorFeaturesThisStage_DebugOnly = CustomFeatures::kNone;
joshualitt47bb3822014-10-07 16:43:25 -0700166 }
cdalton87332102016-02-26 12:22:02 -0800167#endif
joshualitt30ba4362014-08-21 20:18:45 -0700168
ethannicholas5961bc92016-10-12 06:39:56 -0700169 static const char* DeclaredColorOutputName() { return "sk_FragColor"; }
egdaniel8dcdedc2015-11-11 06:27:20 -0800170 static const char* DeclaredSecondaryColorOutputName() { return "fsSecondaryColorOut"; }
171
cdalton28f45b92016-03-07 13:58:26 -0800172 GrSurfaceOrigin getSurfaceOrigin() const;
joshualitt74077b92014-10-24 11:26:03 -0700173
egdaniel574a4c12015-11-02 06:22:44 -0800174 void onFinalize() override;
joshualitt30ba4362014-08-21 20:18:45 -0700175
egdaniel138c2632016-08-17 10:59:00 -0700176 static const char* kDstColorName;
joshualitt47bb3822014-10-07 16:43:25 -0700177
cdalton85285412016-02-18 12:37:07 -0800178 /*
179 * State that tracks which child proc in the proc tree is currently emitting code. This is
180 * used to update the fMangleString, which is used to mangle the names of uniforms and functions
181 * emitted by the proc. fSubstageIndices is a stack: its count indicates how many levels deep
182 * we are in the tree, and its second-to-last value is the index of the child proc at that
183 * level which is currently emitting code. For example, if fSubstageIndices = [3, 1, 2, 0], that
184 * means we're currently emitting code for the base proc's 3rd child's 1st child's 2nd child.
185 */
186 SkTArray<int> fSubstageIndices;
187
188 /*
189 * The mangle string is used to mangle the names of uniforms/functions emitted by the child
190 * procs so no duplicate uniforms/functions appear in the generated shader program. The mangle
191 * string is simply based on fSubstageIndices. For example, if fSubstageIndices = [3, 1, 2, 0],
192 * then the manglestring will be "_c3_c1_c2", and any uniform/function emitted by that proc will
193 * have "_c3_c1_c2" appended to its name, which can be interpreted as "base proc's 3rd child's
194 * 1st child's 2nd child".
195 */
196 SkString fMangleString;
197
Michael Ludwig45191342020-03-24 12:29:39 -0400198 GrShaderVar* fCustomColorOutput = nullptr;
199
Chris Daltond7291ba2019-03-07 14:17:03 -0700200 bool fSetupFragPosition = false;
Chris Daltond7291ba2019-03-07 14:17:03 -0700201 bool fHasSecondaryOutput = false;
Chris Dalton0dffbab2019-03-27 13:08:50 -0600202 bool fHasModifiedSampleMask = false;
Chris Daltond7291ba2019-03-07 14:17:03 -0700203 bool fForceHighPrecision = false;
joshualittfe1233c2014-10-07 12:16:35 -0700204
egdanielfa896322016-01-13 12:19:30 -0800205 friend class GrGLSLProgramBuilder;
joshualitt47bb3822014-10-07 16:43:25 -0700206 friend class GrGLProgramBuilder;
Ethan Nicholas8f352ce2021-03-17 14:12:20 -0400207 friend class GrVkPipelineStateBuilder;
joshualitt30ba4362014-08-21 20:18:45 -0700208};
209
210#endif