1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2014 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGeometryProcessor.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSamplingOptions.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/SkSLSampleUsage.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkSafe32.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkMatrixPriv.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/KeyBuilder.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrPipeline.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLProgramBuilder.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLUniformHandler.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLVarying.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/glsl/GrGLSLVertexGeoBuilder.h"
22*c8dee2aaSAndroid Build Coastguard Worker
23*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
24*c8dee2aaSAndroid Build Coastguard Worker #include <queue>
25*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
26*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
27*c8dee2aaSAndroid Build Coastguard Worker
GrGeometryProcessor(ClassID classID)28*c8dee2aaSAndroid Build Coastguard Worker GrGeometryProcessor::GrGeometryProcessor(ClassID classID) : GrProcessor(classID) {}
29*c8dee2aaSAndroid Build Coastguard Worker
textureSampler(int i) const30*c8dee2aaSAndroid Build Coastguard Worker const GrGeometryProcessor::TextureSampler& GrGeometryProcessor::textureSampler(int i) const {
31*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(i >= 0 && i < this->numTextureSamplers());
32*c8dee2aaSAndroid Build Coastguard Worker return this->onTextureSampler(i);
33*c8dee2aaSAndroid Build Coastguard Worker }
34*c8dee2aaSAndroid Build Coastguard Worker
ComputeCoordTransformsKey(const GrFragmentProcessor & fp)35*c8dee2aaSAndroid Build Coastguard Worker uint32_t GrGeometryProcessor::ComputeCoordTransformsKey(const GrFragmentProcessor& fp) {
36*c8dee2aaSAndroid Build Coastguard Worker // This is highly coupled with the code in ProgramImpl::collectTransforms().
37*c8dee2aaSAndroid Build Coastguard Worker uint32_t key = static_cast<uint32_t>(fp.sampleUsage().kind()) << 1;
38*c8dee2aaSAndroid Build Coastguard Worker // This needs to be updated if GP starts specializing varyings on additional matrix types.
39*c8dee2aaSAndroid Build Coastguard Worker if (fp.sampleUsage().hasPerspective()) {
40*c8dee2aaSAndroid Build Coastguard Worker key |= 0b1;
41*c8dee2aaSAndroid Build Coastguard Worker }
42*c8dee2aaSAndroid Build Coastguard Worker return key;
43*c8dee2aaSAndroid Build Coastguard Worker }
44*c8dee2aaSAndroid Build Coastguard Worker
getAttributeKey(skgpu::KeyBuilder * b) const45*c8dee2aaSAndroid Build Coastguard Worker void GrGeometryProcessor::getAttributeKey(skgpu::KeyBuilder* b) const {
46*c8dee2aaSAndroid Build Coastguard Worker b->appendComment("vertex attributes");
47*c8dee2aaSAndroid Build Coastguard Worker fVertexAttributes.addToKey(b);
48*c8dee2aaSAndroid Build Coastguard Worker b->appendComment("instance attributes");
49*c8dee2aaSAndroid Build Coastguard Worker fInstanceAttributes.addToKey(b);
50*c8dee2aaSAndroid Build Coastguard Worker }
51*c8dee2aaSAndroid Build Coastguard Worker
52*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////////////////////////
53*c8dee2aaSAndroid Build Coastguard Worker
clamp_filter(GrTextureType type,GrSamplerState::Filter requestedFilter)54*c8dee2aaSAndroid Build Coastguard Worker static inline GrSamplerState::Filter clamp_filter(GrTextureType type,
55*c8dee2aaSAndroid Build Coastguard Worker GrSamplerState::Filter requestedFilter) {
56*c8dee2aaSAndroid Build Coastguard Worker if (GrTextureTypeHasRestrictedSampling(type)) {
57*c8dee2aaSAndroid Build Coastguard Worker return std::min(requestedFilter, GrSamplerState::Filter::kLinear);
58*c8dee2aaSAndroid Build Coastguard Worker }
59*c8dee2aaSAndroid Build Coastguard Worker return requestedFilter;
60*c8dee2aaSAndroid Build Coastguard Worker }
61*c8dee2aaSAndroid Build Coastguard Worker
TextureSampler(GrSamplerState samplerState,const GrBackendFormat & backendFormat,const skgpu::Swizzle & swizzle)62*c8dee2aaSAndroid Build Coastguard Worker GrGeometryProcessor::TextureSampler::TextureSampler(GrSamplerState samplerState,
63*c8dee2aaSAndroid Build Coastguard Worker const GrBackendFormat& backendFormat,
64*c8dee2aaSAndroid Build Coastguard Worker const skgpu::Swizzle& swizzle) {
65*c8dee2aaSAndroid Build Coastguard Worker this->reset(samplerState, backendFormat, swizzle);
66*c8dee2aaSAndroid Build Coastguard Worker }
67*c8dee2aaSAndroid Build Coastguard Worker
reset(GrSamplerState samplerState,const GrBackendFormat & backendFormat,const skgpu::Swizzle & swizzle)68*c8dee2aaSAndroid Build Coastguard Worker void GrGeometryProcessor::TextureSampler::reset(GrSamplerState samplerState,
69*c8dee2aaSAndroid Build Coastguard Worker const GrBackendFormat& backendFormat,
70*c8dee2aaSAndroid Build Coastguard Worker const skgpu::Swizzle& swizzle) {
71*c8dee2aaSAndroid Build Coastguard Worker fSamplerState = samplerState;
72*c8dee2aaSAndroid Build Coastguard Worker fSamplerState = GrSamplerState(samplerState.wrapModeX(),
73*c8dee2aaSAndroid Build Coastguard Worker samplerState.wrapModeY(),
74*c8dee2aaSAndroid Build Coastguard Worker clamp_filter(backendFormat.textureType(), samplerState.filter()),
75*c8dee2aaSAndroid Build Coastguard Worker samplerState.mipmapMode());
76*c8dee2aaSAndroid Build Coastguard Worker fBackendFormat = backendFormat;
77*c8dee2aaSAndroid Build Coastguard Worker fSwizzle = swizzle;
78*c8dee2aaSAndroid Build Coastguard Worker fIsInitialized = true;
79*c8dee2aaSAndroid Build Coastguard Worker }
80*c8dee2aaSAndroid Build Coastguard Worker
81*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////
82*c8dee2aaSAndroid Build Coastguard Worker
83*c8dee2aaSAndroid Build Coastguard Worker using ProgramImpl = GrGeometryProcessor::ProgramImpl;
84*c8dee2aaSAndroid Build Coastguard Worker
85*c8dee2aaSAndroid Build Coastguard Worker std::tuple<ProgramImpl::FPCoordsMap, GrShaderVar>
emitCode(EmitArgs & args,const GrPipeline & pipeline)86*c8dee2aaSAndroid Build Coastguard Worker ProgramImpl::emitCode(EmitArgs& args, const GrPipeline& pipeline) {
87*c8dee2aaSAndroid Build Coastguard Worker GrGPArgs gpArgs;
88*c8dee2aaSAndroid Build Coastguard Worker this->onEmitCode(args, &gpArgs);
89*c8dee2aaSAndroid Build Coastguard Worker
90*c8dee2aaSAndroid Build Coastguard Worker FPCoordsMap transformMap = this->collectTransforms(args.fVertBuilder,
91*c8dee2aaSAndroid Build Coastguard Worker args.fVaryingHandler,
92*c8dee2aaSAndroid Build Coastguard Worker args.fUniformHandler,
93*c8dee2aaSAndroid Build Coastguard Worker gpArgs.fLocalCoordShader,
94*c8dee2aaSAndroid Build Coastguard Worker gpArgs.fLocalCoordVar,
95*c8dee2aaSAndroid Build Coastguard Worker gpArgs.fPositionVar,
96*c8dee2aaSAndroid Build Coastguard Worker pipeline);
97*c8dee2aaSAndroid Build Coastguard Worker
98*c8dee2aaSAndroid Build Coastguard Worker GrGLSLVertexBuilder* vBuilder = args.fVertBuilder;
99*c8dee2aaSAndroid Build Coastguard Worker // Emit the vertex position to the hardware in the normalized window coordinates it expects.
100*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(SkSLType::kFloat2 == gpArgs.fPositionVar.getType() ||
101*c8dee2aaSAndroid Build Coastguard Worker SkSLType::kFloat3 == gpArgs.fPositionVar.getType());
102*c8dee2aaSAndroid Build Coastguard Worker vBuilder->emitNormalizedSkPosition(gpArgs.fPositionVar.c_str(),
103*c8dee2aaSAndroid Build Coastguard Worker gpArgs.fPositionVar.getType());
104*c8dee2aaSAndroid Build Coastguard Worker if (SkSLType::kFloat2 == gpArgs.fPositionVar.getType()) {
105*c8dee2aaSAndroid Build Coastguard Worker args.fVaryingHandler->setNoPerspective();
106*c8dee2aaSAndroid Build Coastguard Worker }
107*c8dee2aaSAndroid Build Coastguard Worker
108*c8dee2aaSAndroid Build Coastguard Worker return {transformMap, gpArgs.fLocalCoordVar};
109*c8dee2aaSAndroid Build Coastguard Worker }
110*c8dee2aaSAndroid Build Coastguard Worker
collectTransforms(GrGLSLVertexBuilder * vb,GrGLSLVaryingHandler * varyingHandler,GrGLSLUniformHandler * uniformHandler,GrShaderType localCoordsShader,const GrShaderVar & localCoordsVar,const GrShaderVar & positionVar,const GrPipeline & pipeline)111*c8dee2aaSAndroid Build Coastguard Worker ProgramImpl::FPCoordsMap ProgramImpl::collectTransforms(GrGLSLVertexBuilder* vb,
112*c8dee2aaSAndroid Build Coastguard Worker GrGLSLVaryingHandler* varyingHandler,
113*c8dee2aaSAndroid Build Coastguard Worker GrGLSLUniformHandler* uniformHandler,
114*c8dee2aaSAndroid Build Coastguard Worker GrShaderType localCoordsShader,
115*c8dee2aaSAndroid Build Coastguard Worker const GrShaderVar& localCoordsVar,
116*c8dee2aaSAndroid Build Coastguard Worker const GrShaderVar& positionVar,
117*c8dee2aaSAndroid Build Coastguard Worker const GrPipeline& pipeline) {
118*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(localCoordsVar.getType() == SkSLType::kFloat2 ||
119*c8dee2aaSAndroid Build Coastguard Worker localCoordsVar.getType() == SkSLType::kFloat3 ||
120*c8dee2aaSAndroid Build Coastguard Worker localCoordsVar.getType() == SkSLType::kVoid);
121*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(positionVar.getType() == SkSLType::kFloat2 ||
122*c8dee2aaSAndroid Build Coastguard Worker positionVar.getType() == SkSLType::kFloat3 ||
123*c8dee2aaSAndroid Build Coastguard Worker positionVar.getType() == SkSLType::kVoid);
124*c8dee2aaSAndroid Build Coastguard Worker
125*c8dee2aaSAndroid Build Coastguard Worker auto baseLocalCoordFSVar = [&, baseLocalCoordVarying = GrGLSLVarying()]() mutable {
126*c8dee2aaSAndroid Build Coastguard Worker if (localCoordsShader == kFragment_GrShaderType) {
127*c8dee2aaSAndroid Build Coastguard Worker return localCoordsVar;
128*c8dee2aaSAndroid Build Coastguard Worker }
129*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(localCoordsShader == kVertex_GrShaderType);
130*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(SkSLTypeIsFloatType(localCoordsVar.getType()));
131*c8dee2aaSAndroid Build Coastguard Worker if (baseLocalCoordVarying.type() == SkSLType::kVoid) {
132*c8dee2aaSAndroid Build Coastguard Worker // Initialize to the GP provided coordinate
133*c8dee2aaSAndroid Build Coastguard Worker baseLocalCoordVarying = GrGLSLVarying(localCoordsVar.getType());
134*c8dee2aaSAndroid Build Coastguard Worker varyingHandler->addVarying("LocalCoord", &baseLocalCoordVarying);
135*c8dee2aaSAndroid Build Coastguard Worker vb->codeAppendf("%s = %s;\n",
136*c8dee2aaSAndroid Build Coastguard Worker baseLocalCoordVarying.vsOut(),
137*c8dee2aaSAndroid Build Coastguard Worker localCoordsVar.getName().c_str());
138*c8dee2aaSAndroid Build Coastguard Worker }
139*c8dee2aaSAndroid Build Coastguard Worker return baseLocalCoordVarying.fsInVar();
140*c8dee2aaSAndroid Build Coastguard Worker };
141*c8dee2aaSAndroid Build Coastguard Worker
142*c8dee2aaSAndroid Build Coastguard Worker bool canUsePosition = positionVar.getType() != SkSLType::kVoid;
143*c8dee2aaSAndroid Build Coastguard Worker
144*c8dee2aaSAndroid Build Coastguard Worker FPCoordsMap result;
145*c8dee2aaSAndroid Build Coastguard Worker // Performs a pre-order traversal of FP hierarchy rooted at fp and identifies FPs that are
146*c8dee2aaSAndroid Build Coastguard Worker // sampled with a series of matrices applied to local coords. For each such FP a varying is
147*c8dee2aaSAndroid Build Coastguard Worker // added to the varying handler and added to 'result'.
148*c8dee2aaSAndroid Build Coastguard Worker auto liftTransforms = [&, traversalIndex = 0](
149*c8dee2aaSAndroid Build Coastguard Worker auto& self,
150*c8dee2aaSAndroid Build Coastguard Worker const GrFragmentProcessor& fp,
151*c8dee2aaSAndroid Build Coastguard Worker bool hasPerspective,
152*c8dee2aaSAndroid Build Coastguard Worker const GrFragmentProcessor* lastMatrixFP = nullptr,
153*c8dee2aaSAndroid Build Coastguard Worker int lastMatrixTraversalIndex = -1,
154*c8dee2aaSAndroid Build Coastguard Worker BaseCoord baseCoord = BaseCoord::kLocal) mutable -> void {
155*c8dee2aaSAndroid Build Coastguard Worker ++traversalIndex;
156*c8dee2aaSAndroid Build Coastguard Worker if (localCoordsShader == kVertex_GrShaderType) {
157*c8dee2aaSAndroid Build Coastguard Worker switch (fp.sampleUsage().kind()) {
158*c8dee2aaSAndroid Build Coastguard Worker case SkSL::SampleUsage::Kind::kNone:
159*c8dee2aaSAndroid Build Coastguard Worker // This should only happen at the root. Otherwise how did this FP get added?
160*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fp.parent());
161*c8dee2aaSAndroid Build Coastguard Worker break;
162*c8dee2aaSAndroid Build Coastguard Worker case SkSL::SampleUsage::Kind::kPassThrough:
163*c8dee2aaSAndroid Build Coastguard Worker break;
164*c8dee2aaSAndroid Build Coastguard Worker case SkSL::SampleUsage::Kind::kUniformMatrix:
165*c8dee2aaSAndroid Build Coastguard Worker // Update tracking of last matrix and matrix props.
166*c8dee2aaSAndroid Build Coastguard Worker hasPerspective |= fp.sampleUsage().hasPerspective();
167*c8dee2aaSAndroid Build Coastguard Worker lastMatrixFP = &fp;
168*c8dee2aaSAndroid Build Coastguard Worker lastMatrixTraversalIndex = traversalIndex;
169*c8dee2aaSAndroid Build Coastguard Worker break;
170*c8dee2aaSAndroid Build Coastguard Worker case SkSL::SampleUsage::Kind::kFragCoord:
171*c8dee2aaSAndroid Build Coastguard Worker hasPerspective = positionVar.getType() == SkSLType::kFloat3;
172*c8dee2aaSAndroid Build Coastguard Worker lastMatrixFP = nullptr;
173*c8dee2aaSAndroid Build Coastguard Worker lastMatrixTraversalIndex = -1;
174*c8dee2aaSAndroid Build Coastguard Worker baseCoord = BaseCoord::kPosition;
175*c8dee2aaSAndroid Build Coastguard Worker break;
176*c8dee2aaSAndroid Build Coastguard Worker case SkSL::SampleUsage::Kind::kExplicit:
177*c8dee2aaSAndroid Build Coastguard Worker baseCoord = BaseCoord::kNone;
178*c8dee2aaSAndroid Build Coastguard Worker break;
179*c8dee2aaSAndroid Build Coastguard Worker }
180*c8dee2aaSAndroid Build Coastguard Worker } else {
181*c8dee2aaSAndroid Build Coastguard Worker // If the GP doesn't provide an interpolatable local coord then there is no hope to
182*c8dee2aaSAndroid Build Coastguard Worker // lift.
183*c8dee2aaSAndroid Build Coastguard Worker baseCoord = BaseCoord::kNone;
184*c8dee2aaSAndroid Build Coastguard Worker }
185*c8dee2aaSAndroid Build Coastguard Worker
186*c8dee2aaSAndroid Build Coastguard Worker auto& [varyingFSVar, hasCoordsParam] = result[&fp];
187*c8dee2aaSAndroid Build Coastguard Worker hasCoordsParam = fp.usesSampleCoordsDirectly();
188*c8dee2aaSAndroid Build Coastguard Worker
189*c8dee2aaSAndroid Build Coastguard Worker // We add a varying if we're in a chain of matrices multiplied by local or device coords.
190*c8dee2aaSAndroid Build Coastguard Worker // If the coord is the untransformed local coord we add a varying. We don't if it is
191*c8dee2aaSAndroid Build Coastguard Worker // untransformed device coords since it doesn't save us anything over "sk_FragCoord.xy". Of
192*c8dee2aaSAndroid Build Coastguard Worker // course, if the FP doesn't directly use its coords then we don't add a varying.
193*c8dee2aaSAndroid Build Coastguard Worker if (fp.usesSampleCoordsDirectly() &&
194*c8dee2aaSAndroid Build Coastguard Worker (baseCoord == BaseCoord::kLocal ||
195*c8dee2aaSAndroid Build Coastguard Worker (baseCoord == BaseCoord::kPosition && lastMatrixFP && canUsePosition))) {
196*c8dee2aaSAndroid Build Coastguard Worker // Associate the varying with the highest possible node in the FP tree that shares the
197*c8dee2aaSAndroid Build Coastguard Worker // same coordinates so that multiple FPs in a subtree can share. If there are no matrix
198*c8dee2aaSAndroid Build Coastguard Worker // sample nodes on the way up the tree then directly use the local coord.
199*c8dee2aaSAndroid Build Coastguard Worker if (!lastMatrixFP) {
200*c8dee2aaSAndroid Build Coastguard Worker varyingFSVar = baseLocalCoordFSVar();
201*c8dee2aaSAndroid Build Coastguard Worker } else {
202*c8dee2aaSAndroid Build Coastguard Worker // If there is an already a varying that incorporates all matrices from the root to
203*c8dee2aaSAndroid Build Coastguard Worker // lastMatrixFP just use it. Otherwise, we add it.
204*c8dee2aaSAndroid Build Coastguard Worker auto& [varying, inputCoords, varyingIdx] = fTransformVaryingsMap[lastMatrixFP];
205*c8dee2aaSAndroid Build Coastguard Worker if (varying.type() == SkSLType::kVoid) {
206*c8dee2aaSAndroid Build Coastguard Worker varying = GrGLSLVarying(hasPerspective ? SkSLType::kFloat3 : SkSLType::kFloat2);
207*c8dee2aaSAndroid Build Coastguard Worker SkString strVaryingName = SkStringPrintf("TransformedCoords_%d",
208*c8dee2aaSAndroid Build Coastguard Worker lastMatrixTraversalIndex);
209*c8dee2aaSAndroid Build Coastguard Worker varyingHandler->addVarying(strVaryingName.c_str(), &varying);
210*c8dee2aaSAndroid Build Coastguard Worker inputCoords = baseCoord == BaseCoord::kLocal ? localCoordsVar : positionVar;
211*c8dee2aaSAndroid Build Coastguard Worker varyingIdx = lastMatrixTraversalIndex;
212*c8dee2aaSAndroid Build Coastguard Worker }
213*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(varyingIdx == lastMatrixTraversalIndex);
214*c8dee2aaSAndroid Build Coastguard Worker // The FP will use the varying in the fragment shader as its coords.
215*c8dee2aaSAndroid Build Coastguard Worker varyingFSVar = varying.fsInVar();
216*c8dee2aaSAndroid Build Coastguard Worker }
217*c8dee2aaSAndroid Build Coastguard Worker hasCoordsParam = false;
218*c8dee2aaSAndroid Build Coastguard Worker }
219*c8dee2aaSAndroid Build Coastguard Worker
220*c8dee2aaSAndroid Build Coastguard Worker for (int c = 0; c < fp.numChildProcessors(); ++c) {
221*c8dee2aaSAndroid Build Coastguard Worker if (auto* child = fp.childProcessor(c)) {
222*c8dee2aaSAndroid Build Coastguard Worker self(self,
223*c8dee2aaSAndroid Build Coastguard Worker *child,
224*c8dee2aaSAndroid Build Coastguard Worker hasPerspective,
225*c8dee2aaSAndroid Build Coastguard Worker lastMatrixFP,
226*c8dee2aaSAndroid Build Coastguard Worker lastMatrixTraversalIndex,
227*c8dee2aaSAndroid Build Coastguard Worker baseCoord);
228*c8dee2aaSAndroid Build Coastguard Worker // If we have a varying then we never need a param. Otherwise, if one of our
229*c8dee2aaSAndroid Build Coastguard Worker // children takes a non-explicit coord then we'll need our coord.
230*c8dee2aaSAndroid Build Coastguard Worker hasCoordsParam |= varyingFSVar.getType() == SkSLType::kVoid &&
231*c8dee2aaSAndroid Build Coastguard Worker !child->sampleUsage().isExplicit() &&
232*c8dee2aaSAndroid Build Coastguard Worker !child->sampleUsage().isFragCoord() &&
233*c8dee2aaSAndroid Build Coastguard Worker result[child].hasCoordsParam;
234*c8dee2aaSAndroid Build Coastguard Worker }
235*c8dee2aaSAndroid Build Coastguard Worker }
236*c8dee2aaSAndroid Build Coastguard Worker };
237*c8dee2aaSAndroid Build Coastguard Worker
238*c8dee2aaSAndroid Build Coastguard Worker bool hasPerspective = SkSLTypeVecLength(localCoordsVar.getType()) == 3;
239*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) {
240*c8dee2aaSAndroid Build Coastguard Worker liftTransforms(liftTransforms, pipeline.getFragmentProcessor(i), hasPerspective);
241*c8dee2aaSAndroid Build Coastguard Worker }
242*c8dee2aaSAndroid Build Coastguard Worker return result;
243*c8dee2aaSAndroid Build Coastguard Worker }
244*c8dee2aaSAndroid Build Coastguard Worker
emitTransformCode(GrGLSLVertexBuilder * vb,GrGLSLUniformHandler * uniformHandler)245*c8dee2aaSAndroid Build Coastguard Worker void ProgramImpl::emitTransformCode(GrGLSLVertexBuilder* vb, GrGLSLUniformHandler* uniformHandler) {
246*c8dee2aaSAndroid Build Coastguard Worker // Because descendant varyings may be computed using the varyings of ancestor FPs we make
247*c8dee2aaSAndroid Build Coastguard Worker // sure to visit the varyings according to FP pre-order traversal by dumping them into a
248*c8dee2aaSAndroid Build Coastguard Worker // priority queue.
249*c8dee2aaSAndroid Build Coastguard Worker using FPAndInfo = std::tuple<const GrFragmentProcessor*, TransformInfo>;
250*c8dee2aaSAndroid Build Coastguard Worker auto compare = [](const FPAndInfo& a, const FPAndInfo& b) {
251*c8dee2aaSAndroid Build Coastguard Worker return std::get<1>(a).traversalOrder > std::get<1>(b).traversalOrder;
252*c8dee2aaSAndroid Build Coastguard Worker };
253*c8dee2aaSAndroid Build Coastguard Worker std::priority_queue<FPAndInfo, std::vector<FPAndInfo>, decltype(compare)> pq(compare);
254*c8dee2aaSAndroid Build Coastguard Worker std::for_each(fTransformVaryingsMap.begin(), fTransformVaryingsMap.end(), [&pq](auto entry) {
255*c8dee2aaSAndroid Build Coastguard Worker pq.push(entry);
256*c8dee2aaSAndroid Build Coastguard Worker });
257*c8dee2aaSAndroid Build Coastguard Worker for (; !pq.empty(); pq.pop()) {
258*c8dee2aaSAndroid Build Coastguard Worker const auto& [fp, info] = pq.top();
259*c8dee2aaSAndroid Build Coastguard Worker // If we recorded a transform info, its sample matrix must be uniform
260*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fp->sampleUsage().isUniformMatrix());
261*c8dee2aaSAndroid Build Coastguard Worker GrShaderVar uniform = uniformHandler->liftUniformToVertexShader(
262*c8dee2aaSAndroid Build Coastguard Worker *fp->parent(), SkString(SkSL::SampleUsage::MatrixUniformName()));
263*c8dee2aaSAndroid Build Coastguard Worker // Start with this matrix and accumulate additional matrices as we walk up the FP tree
264*c8dee2aaSAndroid Build Coastguard Worker // to either the base coords or an ancestor FP that has an associated varying.
265*c8dee2aaSAndroid Build Coastguard Worker SkString transformExpression = uniform.getName();
266*c8dee2aaSAndroid Build Coastguard Worker
267*c8dee2aaSAndroid Build Coastguard Worker // If we hit an ancestor with a varying on our walk up then save off the varying as the
268*c8dee2aaSAndroid Build Coastguard Worker // input to our accumulated transformExpression. Start off assuming we'll reach the root.
269*c8dee2aaSAndroid Build Coastguard Worker GrShaderVar inputCoords = info.inputCoords;
270*c8dee2aaSAndroid Build Coastguard Worker
271*c8dee2aaSAndroid Build Coastguard Worker for (const auto* base = fp->parent(); base; base = base->parent()) {
272*c8dee2aaSAndroid Build Coastguard Worker if (auto iter = fTransformVaryingsMap.find(base); iter != fTransformVaryingsMap.end()) {
273*c8dee2aaSAndroid Build Coastguard Worker // Can stop here, as this varying already holds all transforms from higher FPs
274*c8dee2aaSAndroid Build Coastguard Worker // We'll apply the residual transformExpression we've accumulated up from our
275*c8dee2aaSAndroid Build Coastguard Worker // starting FP to this varying.
276*c8dee2aaSAndroid Build Coastguard Worker inputCoords = iter->second.varying.vsOutVar();
277*c8dee2aaSAndroid Build Coastguard Worker break;
278*c8dee2aaSAndroid Build Coastguard Worker } else if (base->sampleUsage().isUniformMatrix()) {
279*c8dee2aaSAndroid Build Coastguard Worker // Accumulate any matrices along the path to either the original local/device coords
280*c8dee2aaSAndroid Build Coastguard Worker // or a parent varying. Getting here means this FP was sampled with a uniform matrix
281*c8dee2aaSAndroid Build Coastguard Worker // but all uses of coords below here in the FP hierarchy are beneath additional
282*c8dee2aaSAndroid Build Coastguard Worker // matrix samples and thus this node wasn't assigned a varying.
283*c8dee2aaSAndroid Build Coastguard Worker GrShaderVar parentUniform = uniformHandler->liftUniformToVertexShader(
284*c8dee2aaSAndroid Build Coastguard Worker *base->parent(), SkString(SkSL::SampleUsage::MatrixUniformName()));
285*c8dee2aaSAndroid Build Coastguard Worker transformExpression.appendf(" * %s", parentUniform.getName().c_str());
286*c8dee2aaSAndroid Build Coastguard Worker } else if (base->sampleUsage().isFragCoord()) {
287*c8dee2aaSAndroid Build Coastguard Worker // Our chain of matrices starts here and is based on the device space position.
288*c8dee2aaSAndroid Build Coastguard Worker break;
289*c8dee2aaSAndroid Build Coastguard Worker } else {
290*c8dee2aaSAndroid Build Coastguard Worker // This intermediate FP is just a pass through and doesn't need to be built
291*c8dee2aaSAndroid Build Coastguard Worker // in to the expression, but we must visit its parents in case they add transforms.
292*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(base->sampleUsage().isPassThrough() || !base->sampleUsage().isSampled());
293*c8dee2aaSAndroid Build Coastguard Worker }
294*c8dee2aaSAndroid Build Coastguard Worker }
295*c8dee2aaSAndroid Build Coastguard Worker
296*c8dee2aaSAndroid Build Coastguard Worker SkString inputStr;
297*c8dee2aaSAndroid Build Coastguard Worker if (inputCoords.getType() == SkSLType::kFloat2) {
298*c8dee2aaSAndroid Build Coastguard Worker inputStr = SkStringPrintf("%s.xy1", inputCoords.getName().c_str());
299*c8dee2aaSAndroid Build Coastguard Worker } else {
300*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(inputCoords.getType() == SkSLType::kFloat3);
301*c8dee2aaSAndroid Build Coastguard Worker inputStr = inputCoords.getName();
302*c8dee2aaSAndroid Build Coastguard Worker }
303*c8dee2aaSAndroid Build Coastguard Worker
304*c8dee2aaSAndroid Build Coastguard Worker vb->codeAppend("{\n");
305*c8dee2aaSAndroid Build Coastguard Worker if (info.varying.type() == SkSLType::kFloat2) {
306*c8dee2aaSAndroid Build Coastguard Worker if (vb->getProgramBuilder()->shaderCaps()->fNonsquareMatrixSupport) {
307*c8dee2aaSAndroid Build Coastguard Worker vb->codeAppendf("%s = float3x2(%s) * %s",
308*c8dee2aaSAndroid Build Coastguard Worker info.varying.vsOut(),
309*c8dee2aaSAndroid Build Coastguard Worker transformExpression.c_str(),
310*c8dee2aaSAndroid Build Coastguard Worker inputStr.c_str());
311*c8dee2aaSAndroid Build Coastguard Worker } else {
312*c8dee2aaSAndroid Build Coastguard Worker vb->codeAppendf("%s = (%s * %s).xy",
313*c8dee2aaSAndroid Build Coastguard Worker info.varying.vsOut(),
314*c8dee2aaSAndroid Build Coastguard Worker transformExpression.c_str(),
315*c8dee2aaSAndroid Build Coastguard Worker inputStr.c_str());
316*c8dee2aaSAndroid Build Coastguard Worker }
317*c8dee2aaSAndroid Build Coastguard Worker } else {
318*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(info.varying.type() == SkSLType::kFloat3);
319*c8dee2aaSAndroid Build Coastguard Worker vb->codeAppendf("%s = %s * %s",
320*c8dee2aaSAndroid Build Coastguard Worker info.varying.vsOut(),
321*c8dee2aaSAndroid Build Coastguard Worker transformExpression.c_str(),
322*c8dee2aaSAndroid Build Coastguard Worker inputStr.c_str());
323*c8dee2aaSAndroid Build Coastguard Worker }
324*c8dee2aaSAndroid Build Coastguard Worker vb->codeAppend(";\n");
325*c8dee2aaSAndroid Build Coastguard Worker vb->codeAppend("}\n");
326*c8dee2aaSAndroid Build Coastguard Worker }
327*c8dee2aaSAndroid Build Coastguard Worker // We don't need this map anymore.
328*c8dee2aaSAndroid Build Coastguard Worker fTransformVaryingsMap.clear();
329*c8dee2aaSAndroid Build Coastguard Worker }
330*c8dee2aaSAndroid Build Coastguard Worker
setupUniformColor(GrGLSLFPFragmentBuilder * fragBuilder,GrGLSLUniformHandler * uniformHandler,const char * outputName,UniformHandle * colorUniform)331*c8dee2aaSAndroid Build Coastguard Worker void ProgramImpl::setupUniformColor(GrGLSLFPFragmentBuilder* fragBuilder,
332*c8dee2aaSAndroid Build Coastguard Worker GrGLSLUniformHandler* uniformHandler,
333*c8dee2aaSAndroid Build Coastguard Worker const char* outputName,
334*c8dee2aaSAndroid Build Coastguard Worker UniformHandle* colorUniform) {
335*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(colorUniform);
336*c8dee2aaSAndroid Build Coastguard Worker const char* stagedLocalVarName;
337*c8dee2aaSAndroid Build Coastguard Worker *colorUniform = uniformHandler->addUniform(nullptr,
338*c8dee2aaSAndroid Build Coastguard Worker kFragment_GrShaderFlag,
339*c8dee2aaSAndroid Build Coastguard Worker SkSLType::kHalf4,
340*c8dee2aaSAndroid Build Coastguard Worker "Color",
341*c8dee2aaSAndroid Build Coastguard Worker &stagedLocalVarName);
342*c8dee2aaSAndroid Build Coastguard Worker fragBuilder->codeAppendf("%s = %s;", outputName, stagedLocalVarName);
343*c8dee2aaSAndroid Build Coastguard Worker if (fragBuilder->getProgramBuilder()->shaderCaps()->fMustObfuscateUniformColor) {
344*c8dee2aaSAndroid Build Coastguard Worker fragBuilder->codeAppendf("%s = max(%s, half4(0));", outputName, outputName);
345*c8dee2aaSAndroid Build Coastguard Worker }
346*c8dee2aaSAndroid Build Coastguard Worker }
347*c8dee2aaSAndroid Build Coastguard Worker
SetTransform(const GrGLSLProgramDataManager & pdman,const GrShaderCaps & shaderCaps,const UniformHandle & uniform,const SkMatrix & matrix,SkMatrix * state)348*c8dee2aaSAndroid Build Coastguard Worker void ProgramImpl::SetTransform(const GrGLSLProgramDataManager& pdman,
349*c8dee2aaSAndroid Build Coastguard Worker const GrShaderCaps& shaderCaps,
350*c8dee2aaSAndroid Build Coastguard Worker const UniformHandle& uniform,
351*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& matrix,
352*c8dee2aaSAndroid Build Coastguard Worker SkMatrix* state) {
353*c8dee2aaSAndroid Build Coastguard Worker if (!uniform.isValid() || (state && SkMatrixPriv::CheapEqual(*state, matrix))) {
354*c8dee2aaSAndroid Build Coastguard Worker // No update needed
355*c8dee2aaSAndroid Build Coastguard Worker return;
356*c8dee2aaSAndroid Build Coastguard Worker }
357*c8dee2aaSAndroid Build Coastguard Worker if (state) {
358*c8dee2aaSAndroid Build Coastguard Worker *state = matrix;
359*c8dee2aaSAndroid Build Coastguard Worker }
360*c8dee2aaSAndroid Build Coastguard Worker if (matrix.isScaleTranslate() && !shaderCaps.fReducedShaderMode) {
361*c8dee2aaSAndroid Build Coastguard Worker // ComputeMatrixKey and writeX() assume the uniform is a float4 (can't assert since nothing
362*c8dee2aaSAndroid Build Coastguard Worker // is exposed on a handle, but should be caught lower down).
363*c8dee2aaSAndroid Build Coastguard Worker float values[4] = {matrix.getScaleX(), matrix.getTranslateX(),
364*c8dee2aaSAndroid Build Coastguard Worker matrix.getScaleY(), matrix.getTranslateY()};
365*c8dee2aaSAndroid Build Coastguard Worker pdman.set4fv(uniform, 1, values);
366*c8dee2aaSAndroid Build Coastguard Worker } else {
367*c8dee2aaSAndroid Build Coastguard Worker pdman.setSkMatrix(uniform, matrix);
368*c8dee2aaSAndroid Build Coastguard Worker }
369*c8dee2aaSAndroid Build Coastguard Worker }
370*c8dee2aaSAndroid Build Coastguard Worker
write_passthrough_vertex_position(GrGLSLVertexBuilder * vertBuilder,const GrShaderVar & inPos,GrShaderVar * outPos)371*c8dee2aaSAndroid Build Coastguard Worker static void write_passthrough_vertex_position(GrGLSLVertexBuilder* vertBuilder,
372*c8dee2aaSAndroid Build Coastguard Worker const GrShaderVar& inPos,
373*c8dee2aaSAndroid Build Coastguard Worker GrShaderVar* outPos) {
374*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(inPos.getType() == SkSLType::kFloat3 || inPos.getType() == SkSLType::kFloat2);
375*c8dee2aaSAndroid Build Coastguard Worker SkString outName = vertBuilder->newTmpVarName(inPos.getName().c_str());
376*c8dee2aaSAndroid Build Coastguard Worker outPos->set(inPos.getType(), outName.c_str());
377*c8dee2aaSAndroid Build Coastguard Worker vertBuilder->codeAppendf("float%d %s = %s;",
378*c8dee2aaSAndroid Build Coastguard Worker SkSLTypeVecLength(inPos.getType()),
379*c8dee2aaSAndroid Build Coastguard Worker outName.c_str(),
380*c8dee2aaSAndroid Build Coastguard Worker inPos.getName().c_str());
381*c8dee2aaSAndroid Build Coastguard Worker }
382*c8dee2aaSAndroid Build Coastguard Worker
write_vertex_position(GrGLSLVertexBuilder * vertBuilder,GrGLSLUniformHandler * uniformHandler,const GrShaderCaps & shaderCaps,const GrShaderVar & inPos,const SkMatrix & matrix,const char * matrixName,GrShaderVar * outPos,ProgramImpl::UniformHandle * matrixUniform)383*c8dee2aaSAndroid Build Coastguard Worker static void write_vertex_position(GrGLSLVertexBuilder* vertBuilder,
384*c8dee2aaSAndroid Build Coastguard Worker GrGLSLUniformHandler* uniformHandler,
385*c8dee2aaSAndroid Build Coastguard Worker const GrShaderCaps& shaderCaps,
386*c8dee2aaSAndroid Build Coastguard Worker const GrShaderVar& inPos,
387*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& matrix,
388*c8dee2aaSAndroid Build Coastguard Worker const char* matrixName,
389*c8dee2aaSAndroid Build Coastguard Worker GrShaderVar* outPos,
390*c8dee2aaSAndroid Build Coastguard Worker ProgramImpl::UniformHandle* matrixUniform) {
391*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(inPos.getType() == SkSLType::kFloat3 || inPos.getType() == SkSLType::kFloat2);
392*c8dee2aaSAndroid Build Coastguard Worker SkString outName = vertBuilder->newTmpVarName(inPos.getName().c_str());
393*c8dee2aaSAndroid Build Coastguard Worker
394*c8dee2aaSAndroid Build Coastguard Worker if (matrix.isIdentity() && !shaderCaps.fReducedShaderMode) {
395*c8dee2aaSAndroid Build Coastguard Worker write_passthrough_vertex_position(vertBuilder, inPos, outPos);
396*c8dee2aaSAndroid Build Coastguard Worker return;
397*c8dee2aaSAndroid Build Coastguard Worker }
398*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(matrixUniform);
399*c8dee2aaSAndroid Build Coastguard Worker
400*c8dee2aaSAndroid Build Coastguard Worker bool useCompactTransform = matrix.isScaleTranslate() && !shaderCaps.fReducedShaderMode;
401*c8dee2aaSAndroid Build Coastguard Worker const char* mangledMatrixName;
402*c8dee2aaSAndroid Build Coastguard Worker *matrixUniform = uniformHandler->addUniform(nullptr,
403*c8dee2aaSAndroid Build Coastguard Worker kVertex_GrShaderFlag,
404*c8dee2aaSAndroid Build Coastguard Worker useCompactTransform ? SkSLType::kFloat4
405*c8dee2aaSAndroid Build Coastguard Worker : SkSLType::kFloat3x3,
406*c8dee2aaSAndroid Build Coastguard Worker matrixName,
407*c8dee2aaSAndroid Build Coastguard Worker &mangledMatrixName);
408*c8dee2aaSAndroid Build Coastguard Worker
409*c8dee2aaSAndroid Build Coastguard Worker if (inPos.getType() == SkSLType::kFloat3) {
410*c8dee2aaSAndroid Build Coastguard Worker // A float3 stays a float3 whether or not the matrix adds perspective
411*c8dee2aaSAndroid Build Coastguard Worker if (useCompactTransform) {
412*c8dee2aaSAndroid Build Coastguard Worker vertBuilder->codeAppendf("float3 %s = %s.xz1 * %s + %s.yw0;\n",
413*c8dee2aaSAndroid Build Coastguard Worker outName.c_str(),
414*c8dee2aaSAndroid Build Coastguard Worker mangledMatrixName,
415*c8dee2aaSAndroid Build Coastguard Worker inPos.getName().c_str(),
416*c8dee2aaSAndroid Build Coastguard Worker mangledMatrixName);
417*c8dee2aaSAndroid Build Coastguard Worker } else {
418*c8dee2aaSAndroid Build Coastguard Worker vertBuilder->codeAppendf("float3 %s = %s * %s;\n",
419*c8dee2aaSAndroid Build Coastguard Worker outName.c_str(),
420*c8dee2aaSAndroid Build Coastguard Worker mangledMatrixName,
421*c8dee2aaSAndroid Build Coastguard Worker inPos.getName().c_str());
422*c8dee2aaSAndroid Build Coastguard Worker }
423*c8dee2aaSAndroid Build Coastguard Worker outPos->set(SkSLType::kFloat3, outName.c_str());
424*c8dee2aaSAndroid Build Coastguard Worker return;
425*c8dee2aaSAndroid Build Coastguard Worker }
426*c8dee2aaSAndroid Build Coastguard Worker if (matrix.hasPerspective()) {
427*c8dee2aaSAndroid Build Coastguard Worker // A float2 is promoted to a float3 if we add perspective via the matrix
428*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!useCompactTransform);
429*c8dee2aaSAndroid Build Coastguard Worker vertBuilder->codeAppendf("float3 %s = (%s * %s.xy1);",
430*c8dee2aaSAndroid Build Coastguard Worker outName.c_str(),
431*c8dee2aaSAndroid Build Coastguard Worker mangledMatrixName,
432*c8dee2aaSAndroid Build Coastguard Worker inPos.getName().c_str());
433*c8dee2aaSAndroid Build Coastguard Worker outPos->set(SkSLType::kFloat3, outName.c_str());
434*c8dee2aaSAndroid Build Coastguard Worker return;
435*c8dee2aaSAndroid Build Coastguard Worker }
436*c8dee2aaSAndroid Build Coastguard Worker if (useCompactTransform) {
437*c8dee2aaSAndroid Build Coastguard Worker vertBuilder->codeAppendf("float2 %s = %s.xz * %s + %s.yw;\n",
438*c8dee2aaSAndroid Build Coastguard Worker outName.c_str(),
439*c8dee2aaSAndroid Build Coastguard Worker mangledMatrixName,
440*c8dee2aaSAndroid Build Coastguard Worker inPos.getName().c_str(),
441*c8dee2aaSAndroid Build Coastguard Worker mangledMatrixName);
442*c8dee2aaSAndroid Build Coastguard Worker } else if (shaderCaps.fNonsquareMatrixSupport) {
443*c8dee2aaSAndroid Build Coastguard Worker vertBuilder->codeAppendf("float2 %s = float3x2(%s) * %s.xy1;\n",
444*c8dee2aaSAndroid Build Coastguard Worker outName.c_str(),
445*c8dee2aaSAndroid Build Coastguard Worker mangledMatrixName,
446*c8dee2aaSAndroid Build Coastguard Worker inPos.getName().c_str());
447*c8dee2aaSAndroid Build Coastguard Worker } else {
448*c8dee2aaSAndroid Build Coastguard Worker vertBuilder->codeAppendf("float2 %s = (%s * %s.xy1).xy;\n",
449*c8dee2aaSAndroid Build Coastguard Worker outName.c_str(),
450*c8dee2aaSAndroid Build Coastguard Worker mangledMatrixName,
451*c8dee2aaSAndroid Build Coastguard Worker inPos.getName().c_str());
452*c8dee2aaSAndroid Build Coastguard Worker }
453*c8dee2aaSAndroid Build Coastguard Worker outPos->set(SkSLType::kFloat2, outName.c_str());
454*c8dee2aaSAndroid Build Coastguard Worker }
455*c8dee2aaSAndroid Build Coastguard Worker
WriteOutputPosition(GrGLSLVertexBuilder * vertBuilder,GrGPArgs * gpArgs,const char * posName)456*c8dee2aaSAndroid Build Coastguard Worker void ProgramImpl::WriteOutputPosition(GrGLSLVertexBuilder* vertBuilder,
457*c8dee2aaSAndroid Build Coastguard Worker GrGPArgs* gpArgs,
458*c8dee2aaSAndroid Build Coastguard Worker const char* posName) {
459*c8dee2aaSAndroid Build Coastguard Worker // writeOutputPosition assumes the incoming pos name points to a float2 variable
460*c8dee2aaSAndroid Build Coastguard Worker GrShaderVar inPos(posName, SkSLType::kFloat2);
461*c8dee2aaSAndroid Build Coastguard Worker write_passthrough_vertex_position(vertBuilder, inPos, &gpArgs->fPositionVar);
462*c8dee2aaSAndroid Build Coastguard Worker }
463*c8dee2aaSAndroid Build Coastguard Worker
WriteOutputPosition(GrGLSLVertexBuilder * vertBuilder,GrGLSLUniformHandler * uniformHandler,const GrShaderCaps & shaderCaps,GrGPArgs * gpArgs,const char * posName,const SkMatrix & mat,UniformHandle * viewMatrixUniform)464*c8dee2aaSAndroid Build Coastguard Worker void ProgramImpl::WriteOutputPosition(GrGLSLVertexBuilder* vertBuilder,
465*c8dee2aaSAndroid Build Coastguard Worker GrGLSLUniformHandler* uniformHandler,
466*c8dee2aaSAndroid Build Coastguard Worker const GrShaderCaps& shaderCaps,
467*c8dee2aaSAndroid Build Coastguard Worker GrGPArgs* gpArgs,
468*c8dee2aaSAndroid Build Coastguard Worker const char* posName,
469*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& mat,
470*c8dee2aaSAndroid Build Coastguard Worker UniformHandle* viewMatrixUniform) {
471*c8dee2aaSAndroid Build Coastguard Worker GrShaderVar inPos(posName, SkSLType::kFloat2);
472*c8dee2aaSAndroid Build Coastguard Worker write_vertex_position(vertBuilder,
473*c8dee2aaSAndroid Build Coastguard Worker uniformHandler,
474*c8dee2aaSAndroid Build Coastguard Worker shaderCaps,
475*c8dee2aaSAndroid Build Coastguard Worker inPos,
476*c8dee2aaSAndroid Build Coastguard Worker mat,
477*c8dee2aaSAndroid Build Coastguard Worker "viewMatrix",
478*c8dee2aaSAndroid Build Coastguard Worker &gpArgs->fPositionVar,
479*c8dee2aaSAndroid Build Coastguard Worker viewMatrixUniform);
480*c8dee2aaSAndroid Build Coastguard Worker }
481*c8dee2aaSAndroid Build Coastguard Worker
WriteLocalCoord(GrGLSLVertexBuilder * vertBuilder,GrGLSLUniformHandler * uniformHandler,const GrShaderCaps & shaderCaps,GrGPArgs * gpArgs,GrShaderVar localVar,const SkMatrix & localMatrix,UniformHandle * localMatrixUniform)482*c8dee2aaSAndroid Build Coastguard Worker void ProgramImpl::WriteLocalCoord(GrGLSLVertexBuilder* vertBuilder,
483*c8dee2aaSAndroid Build Coastguard Worker GrGLSLUniformHandler* uniformHandler,
484*c8dee2aaSAndroid Build Coastguard Worker const GrShaderCaps& shaderCaps,
485*c8dee2aaSAndroid Build Coastguard Worker GrGPArgs* gpArgs,
486*c8dee2aaSAndroid Build Coastguard Worker GrShaderVar localVar,
487*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& localMatrix,
488*c8dee2aaSAndroid Build Coastguard Worker UniformHandle* localMatrixUniform) {
489*c8dee2aaSAndroid Build Coastguard Worker write_vertex_position(vertBuilder,
490*c8dee2aaSAndroid Build Coastguard Worker uniformHandler,
491*c8dee2aaSAndroid Build Coastguard Worker shaderCaps,
492*c8dee2aaSAndroid Build Coastguard Worker localVar,
493*c8dee2aaSAndroid Build Coastguard Worker localMatrix,
494*c8dee2aaSAndroid Build Coastguard Worker "localMatrix",
495*c8dee2aaSAndroid Build Coastguard Worker &gpArgs->fLocalCoordVar,
496*c8dee2aaSAndroid Build Coastguard Worker localMatrixUniform);
497*c8dee2aaSAndroid Build Coastguard Worker }
498*c8dee2aaSAndroid Build Coastguard Worker
499*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////
500*c8dee2aaSAndroid Build Coastguard Worker
501*c8dee2aaSAndroid Build Coastguard Worker using Attribute = GrGeometryProcessor::Attribute;
502*c8dee2aaSAndroid Build Coastguard Worker using AttributeSet = GrGeometryProcessor::AttributeSet;
503*c8dee2aaSAndroid Build Coastguard Worker
operator *() const504*c8dee2aaSAndroid Build Coastguard Worker GrGeometryProcessor::Attribute AttributeSet::Iter::operator*() const {
505*c8dee2aaSAndroid Build Coastguard Worker if (fCurr->offset().has_value()) {
506*c8dee2aaSAndroid Build Coastguard Worker return *fCurr;
507*c8dee2aaSAndroid Build Coastguard Worker }
508*c8dee2aaSAndroid Build Coastguard Worker return Attribute(fCurr->name(), fCurr->cpuType(), fCurr->gpuType(), fImplicitOffset);
509*c8dee2aaSAndroid Build Coastguard Worker }
510*c8dee2aaSAndroid Build Coastguard Worker
operator ++()511*c8dee2aaSAndroid Build Coastguard Worker void AttributeSet::Iter::operator++() {
512*c8dee2aaSAndroid Build Coastguard Worker if (fRemaining) {
513*c8dee2aaSAndroid Build Coastguard Worker fRemaining--;
514*c8dee2aaSAndroid Build Coastguard Worker fImplicitOffset += Attribute::AlignOffset(fCurr->size());
515*c8dee2aaSAndroid Build Coastguard Worker fCurr++;
516*c8dee2aaSAndroid Build Coastguard Worker this->skipUninitialized();
517*c8dee2aaSAndroid Build Coastguard Worker }
518*c8dee2aaSAndroid Build Coastguard Worker }
519*c8dee2aaSAndroid Build Coastguard Worker
skipUninitialized()520*c8dee2aaSAndroid Build Coastguard Worker void AttributeSet::Iter::skipUninitialized() {
521*c8dee2aaSAndroid Build Coastguard Worker if (!fRemaining) {
522*c8dee2aaSAndroid Build Coastguard Worker fCurr = nullptr;
523*c8dee2aaSAndroid Build Coastguard Worker } else {
524*c8dee2aaSAndroid Build Coastguard Worker while (!fCurr->isInitialized()) {
525*c8dee2aaSAndroid Build Coastguard Worker ++fCurr;
526*c8dee2aaSAndroid Build Coastguard Worker }
527*c8dee2aaSAndroid Build Coastguard Worker }
528*c8dee2aaSAndroid Build Coastguard Worker }
529*c8dee2aaSAndroid Build Coastguard Worker
initImplicit(const Attribute * attrs,int count)530*c8dee2aaSAndroid Build Coastguard Worker void AttributeSet::initImplicit(const Attribute* attrs, int count) {
531*c8dee2aaSAndroid Build Coastguard Worker fAttributes = attrs;
532*c8dee2aaSAndroid Build Coastguard Worker fRawCount = count;
533*c8dee2aaSAndroid Build Coastguard Worker fCount = 0;
534*c8dee2aaSAndroid Build Coastguard Worker fStride = 0;
535*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < count; ++i) {
536*c8dee2aaSAndroid Build Coastguard Worker if (attrs[i].isInitialized()) {
537*c8dee2aaSAndroid Build Coastguard Worker fCount++;
538*c8dee2aaSAndroid Build Coastguard Worker fStride += Attribute::AlignOffset(attrs[i].size());
539*c8dee2aaSAndroid Build Coastguard Worker }
540*c8dee2aaSAndroid Build Coastguard Worker }
541*c8dee2aaSAndroid Build Coastguard Worker }
542*c8dee2aaSAndroid Build Coastguard Worker
initExplicit(const Attribute * attrs,int count,size_t stride)543*c8dee2aaSAndroid Build Coastguard Worker void AttributeSet::initExplicit(const Attribute* attrs, int count, size_t stride) {
544*c8dee2aaSAndroid Build Coastguard Worker fAttributes = attrs;
545*c8dee2aaSAndroid Build Coastguard Worker fRawCount = count;
546*c8dee2aaSAndroid Build Coastguard Worker fCount = count;
547*c8dee2aaSAndroid Build Coastguard Worker fStride = stride;
548*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(Attribute::AlignOffset(fStride) == fStride);
549*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < count; ++i) {
550*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(attrs[i].isInitialized());
551*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(attrs[i].offset().has_value());
552*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(Attribute::AlignOffset(*attrs[i].offset()) == *attrs[i].offset());
553*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(*attrs[i].offset() + attrs[i].size() <= fStride);
554*c8dee2aaSAndroid Build Coastguard Worker }
555*c8dee2aaSAndroid Build Coastguard Worker }
556*c8dee2aaSAndroid Build Coastguard Worker
addToKey(skgpu::KeyBuilder * b) const557*c8dee2aaSAndroid Build Coastguard Worker void AttributeSet::addToKey(skgpu::KeyBuilder* b) const {
558*c8dee2aaSAndroid Build Coastguard Worker int rawCount = SkAbs32(fRawCount);
559*c8dee2aaSAndroid Build Coastguard Worker b->addBits(16, SkToU16(this->stride()), "stride");
560*c8dee2aaSAndroid Build Coastguard Worker b->addBits(16, rawCount, "attribute count");
561*c8dee2aaSAndroid Build Coastguard Worker size_t implicitOffset = 0;
562*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < rawCount; ++i) {
563*c8dee2aaSAndroid Build Coastguard Worker const Attribute& attr = fAttributes[i];
564*c8dee2aaSAndroid Build Coastguard Worker b->appendComment(attr.isInitialized() ? attr.name() : "unusedAttr");
565*c8dee2aaSAndroid Build Coastguard Worker static_assert(kGrVertexAttribTypeCount < (1 << 8), "");
566*c8dee2aaSAndroid Build Coastguard Worker static_assert(kSkSLTypeCount < (1 << 8), "");
567*c8dee2aaSAndroid Build Coastguard Worker b->addBits(8, attr.isInitialized() ? attr.cpuType() : 0xff, "attrType");
568*c8dee2aaSAndroid Build Coastguard Worker b->addBits(8 , attr.isInitialized() ? static_cast<int>(attr.gpuType()) : 0xff,
569*c8dee2aaSAndroid Build Coastguard Worker "attrGpuType");
570*c8dee2aaSAndroid Build Coastguard Worker int16_t offset = -1;
571*c8dee2aaSAndroid Build Coastguard Worker if (attr.isInitialized()) {
572*c8dee2aaSAndroid Build Coastguard Worker if (attr.offset().has_value()) {
573*c8dee2aaSAndroid Build Coastguard Worker offset = *attr.offset();
574*c8dee2aaSAndroid Build Coastguard Worker } else {
575*c8dee2aaSAndroid Build Coastguard Worker offset = implicitOffset;
576*c8dee2aaSAndroid Build Coastguard Worker implicitOffset += Attribute::AlignOffset(attr.size());
577*c8dee2aaSAndroid Build Coastguard Worker }
578*c8dee2aaSAndroid Build Coastguard Worker }
579*c8dee2aaSAndroid Build Coastguard Worker b->addBits(16, static_cast<uint16_t>(offset), "attrOffset");
580*c8dee2aaSAndroid Build Coastguard Worker }
581*c8dee2aaSAndroid Build Coastguard Worker }
582*c8dee2aaSAndroid Build Coastguard Worker
begin() const583*c8dee2aaSAndroid Build Coastguard Worker AttributeSet::Iter AttributeSet::begin() const { return Iter(fAttributes, fCount); }
end() const584*c8dee2aaSAndroid Build Coastguard Worker AttributeSet::Iter AttributeSet::end() const { return Iter(); }
585