Create GLSLUniformHandler class for gpu backend
[platform/upstream/libSkiaSharp.git] / src / gpu / gl / builders / GrGLProgramBuilder.cpp
1 /*
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
8 #include "GrGLProgramBuilder.h"
9
10 #include "GrAutoLocaleSetter.h"
11 #include "GrCoordTransform.h"
12 #include "GrGLProgramBuilder.h"
13 #include "GrTexture.h"
14 #include "SkRTConf.h"
15 #include "SkTraceEvent.h"
16 #include "gl/GrGLGpu.h"
17 #include "gl/GrGLProgram.h"
18 #include "gl/GrGLSLPrettyPrint.h"
19 #include "gl/builders/GrGLShaderStringBuilder.h"
20 #include "glsl/GrGLSLCaps.h"
21 #include "glsl/GrGLSLFragmentProcessor.h"
22 #include "glsl/GrGLSLGeometryProcessor.h"
23 #include "glsl/GrGLSLProgramDataManager.h"
24 #include "glsl/GrGLSLTextureSampler.h"
25 #include "glsl/GrGLSLXferProcessor.h"
26
27 #define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
28 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
29
30 GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gpu) {
31     GrAutoLocaleSetter als("C");
32
33     // create a builder.  This will be handed off to effects so they can use it to add
34     // uniforms, varyings, textures, etc
35     SkAutoTDelete<GrGLProgramBuilder> builder(new GrGLProgramBuilder(gpu, args));
36
37     GrGLProgramBuilder* pb = builder.get();
38
39     // TODO: Once all stages can handle taking a float or vec4 and correctly handling them we can
40     // seed correctly here
41     GrGLSLExpr4 inputColor;
42     GrGLSLExpr4 inputCoverage;
43
44     if (!pb->emitAndInstallProcs(&inputColor, &inputCoverage)) {
45         return nullptr;
46     }
47
48     return pb->finalize();
49 }
50
51 /////////////////////////////////////////////////////////////////////////////
52
53 GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args)
54     : INHERITED(args)
55     , fGeometryProcessor(nullptr)
56     , fXferProcessor(nullptr)
57     , fGpu(gpu)
58     , fSamplerUniforms(4)
59     , fVaryingHandler(this)
60     , fUniformHandler(this) {
61 }
62
63 const GrGLSLCaps* GrGLProgramBuilder::glslCaps() const {
64     return this->fGpu->ctxInfo().caps()->glslCaps();
65 }
66
67 bool GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) {
68     // First we loop over all of the installed processors and collect coord transforms.  These will
69     // be sent to the GrGLSLPrimitiveProcessor in its emitCode function
70     const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
71     int totalTextures = primProc.numTextures();
72     const int maxTextureUnits = fGpu->glCaps().maxFragmentTextureUnits();
73
74     for (int i = 0; i < this->pipeline().numFragmentProcessors(); i++) {
75         const GrFragmentProcessor& processor = this->pipeline().getFragmentProcessor(i);
76
77         if (!primProc.hasTransformedLocalCoords()) {
78             SkTArray<const GrCoordTransform*, true>& procCoords = fCoordTransforms.push_back();
79             processor.gatherCoordTransforms(&procCoords);
80         }
81
82         totalTextures += processor.numTextures();
83         if (totalTextures >= maxTextureUnits) {
84             GrCapsDebugf(fGpu->caps(), "Program would use too many texture units\n");
85             return false;
86         }
87     }
88
89     this->emitAndInstallProc(primProc, inputColor, inputCoverage);
90
91     fFragmentProcessors.reset(new GrGLInstalledFragProcs);
92     int numProcs = this->pipeline().numFragmentProcessors();
93     this->emitAndInstallFragProcs(0, this->pipeline().numColorFragmentProcessors(), inputColor);
94     this->emitAndInstallFragProcs(this->pipeline().numColorFragmentProcessors(), numProcs,
95                                   inputCoverage);
96     this->emitAndInstallXferProc(*this->pipeline().getXferProcessor(), *inputColor, *inputCoverage,
97                                  this->pipeline().ignoresCoverage());
98     return true;
99 }
100
101 void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset,
102                                                  int numProcs,
103                                                  GrGLSLExpr4* inOut) {
104     for (int i = procOffset; i < numProcs; ++i) {
105         GrGLSLExpr4 output;
106         const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i);
107         this->emitAndInstallProc(fp, i, *inOut, &output);
108         *inOut = output;
109     }
110 }
111
112 void GrGLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseName) {
113     // create var to hold stage result.  If we already have a valid output name, just use that
114     // otherwise create a new mangled one.  This name is only valid if we are reordering stages
115     // and have to tell stage exactly where to put its output.
116     SkString outName;
117     if (output->isValid()) {
118         outName = output->c_str();
119     } else {
120         this->nameVariable(&outName, '\0', baseName);
121     }
122     fFS.codeAppendf("vec4 %s;", outName.c_str());
123     *output = outName;
124 }
125
126 // TODO Processors cannot output zeros because an empty string is all 1s
127 // the fix is to allow effects to take the GrGLSLExpr4 directly
128 void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentProcessor& fp,
129                                             int index,
130                                             const GrGLSLExpr4& input,
131                                             GrGLSLExpr4* output) {
132     // Program builders have a bit of state we need to clear with each effect
133     AutoStageAdvance adv(this);
134     this->nameExpression(output, "output");
135
136     // Enclose custom code in a block to avoid namespace conflicts
137     SkString openBrace;
138     openBrace.printf("{ // Stage %d, %s\n", fStageIndex, fp.name());
139     fFS.codeAppend(openBrace.c_str());
140
141     this->emitAndInstallProc(fp, index, output->c_str(), input.isOnes() ? nullptr : input.c_str());
142
143     fFS.codeAppend("}");
144 }
145
146 void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& proc,
147                                             GrGLSLExpr4* outputColor,
148                                             GrGLSLExpr4* outputCoverage) {
149     // Program builders have a bit of state we need to clear with each effect
150     AutoStageAdvance adv(this);
151     this->nameExpression(outputColor, "outputColor");
152     this->nameExpression(outputCoverage, "outputCoverage");
153
154     // Enclose custom code in a block to avoid namespace conflicts
155     SkString openBrace;
156     openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
157     fFS.codeAppend(openBrace.c_str());
158     fVS.codeAppendf("// Primitive Processor %s\n", proc.name());
159
160     this->emitAndInstallProc(proc, outputColor->c_str(), outputCoverage->c_str());
161
162     fFS.codeAppend("}");
163 }
164
165 void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentProcessor& fp,
166                                             int index,
167                                             const char* outColor,
168                                             const char* inColor) {
169     GrGLInstalledFragProc* ifp = new GrGLInstalledFragProc;
170
171     ifp->fGLProc.reset(fp.createGLSLInstance());
172
173     SkSTArray<4, GrGLSLTextureSampler> samplers(fp.numTextures());
174     this->emitSamplers(fp, &samplers, ifp);
175
176     GrGLSLFragmentProcessor::EmitArgs args(&fFS,
177                                            &fUniformHandler,
178                                            this->glslCaps(),
179                                            fp,
180                                            outColor,
181                                            inColor,
182                                            fOutCoords[index],
183                                            samplers);
184     ifp->fGLProc->emitCode(args);
185
186     // We have to check that effects and the code they emit are consistent, ie if an effect
187     // asks for dst color, then the emit code needs to follow suit
188     verify(fp);
189     fFragmentProcessors->fProcs.push_back(ifp);
190 }
191
192 void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& gp,
193                                             const char* outColor,
194                                             const char* outCoverage) {
195     SkASSERT(!fGeometryProcessor);
196     fGeometryProcessor = new GrGLInstalledGeoProc;
197
198     fGeometryProcessor->fGLProc.reset(gp.createGLSLInstance(*fGpu->glCaps().glslCaps()));
199
200     SkSTArray<4, GrGLSLTextureSampler> samplers(gp.numTextures());
201     this->emitSamplers(gp, &samplers, fGeometryProcessor);
202
203     GrGLSLGeometryProcessor::EmitArgs args(&fVS,
204                                            &fFS,
205                                            &fVaryingHandler,
206                                            &fUniformHandler,
207                                            this->glslCaps(),
208                                            gp,
209                                            outColor,
210                                            outCoverage,
211                                            samplers,
212                                            fCoordTransforms,
213                                            &fOutCoords);
214     fGeometryProcessor->fGLProc->emitCode(args);
215
216     // We have to check that effects and the code they emit are consistent, ie if an effect
217     // asks for dst color, then the emit code needs to follow suit
218     verify(gp);
219 }
220
221 void GrGLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
222                                                 const GrGLSLExpr4& colorIn,
223                                                 const GrGLSLExpr4& coverageIn,
224                                                 bool ignoresCoverage) {
225     // Program builders have a bit of state we need to clear with each effect
226     AutoStageAdvance adv(this);
227
228     SkASSERT(!fXferProcessor);
229     fXferProcessor = new GrGLInstalledXferProc;
230
231     fXferProcessor->fGLProc.reset(xp.createGLSLInstance());
232
233     // Enable dual source secondary output if we have one
234     if (xp.hasSecondaryOutput()) {
235         fFS.enableSecondaryOutput();
236     }
237
238     if (this->glslCaps()->mustDeclareFragmentShaderOutput()) {
239         fFS.enableCustomOutput();
240     }
241
242     SkString openBrace;
243     openBrace.printf("{ // Xfer Processor: %s\n", xp.name());
244     fFS.codeAppend(openBrace.c_str());
245
246     SkSTArray<4, GrGLSLTextureSampler> samplers(xp.numTextures());
247     this->emitSamplers(xp, &samplers, fXferProcessor);
248
249     GrGLSLXferProcessor::EmitArgs args(&fFS,
250                                        &fUniformHandler,
251                                        this->glslCaps(),
252                                        xp, colorIn.c_str(),
253                                        ignoresCoverage ? nullptr : coverageIn.c_str(),
254                                        fFS.getPrimaryColorOutputName(),
255                                        fFS.getSecondaryColorOutputName(),
256                                        samplers);
257     fXferProcessor->fGLProc->emitCode(args);
258
259     // We have to check that effects and the code they emit are consistent, ie if an effect
260     // asks for dst color, then the emit code needs to follow suit
261     verify(xp);
262     fFS.codeAppend("}");
263 }
264
265 void GrGLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
266     SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
267 }
268
269 void GrGLProgramBuilder::verify(const GrXferProcessor& xp) {
270     SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor());
271 }
272
273 void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
274     SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
275 }
276
277 static GrSLType get_sampler_type(const GrTextureAccess& access) {
278     GrGLTexture* glTexture = static_cast<GrGLTexture*>(access.getTexture());
279     if (glTexture->target() == GR_GL_TEXTURE_EXTERNAL) {
280         return kSamplerExternal_GrSLType;
281     } else {
282         SkASSERT(glTexture->target() == GR_GL_TEXTURE_2D);
283         return kSampler2D_GrSLType;
284     }
285 }
286
287 template <class Proc>
288 void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
289                                       GrGLSLTextureSampler::TextureSamplerArray* outSamplers,
290                                       GrGLInstalledProc<Proc>* ip) {
291     SkDEBUGCODE(ip->fSamplersIdx = fSamplerUniforms.count();)
292     int numTextures = processor.numTextures();
293     UniformHandle* localSamplerUniforms = fSamplerUniforms.push_back_n(numTextures);
294     SkString name;
295     for (int t = 0; t < numTextures; ++t) {
296         name.printf("Sampler%d", t);
297         GrSLType samplerType = get_sampler_type(processor.textureAccess(t));
298         localSamplerUniforms[t] =
299             fUniformHandler.addUniform(GrGLSLUniformHandler::kFragment_Visibility,
300                                        samplerType, kDefault_GrSLPrecision,
301                                        name.c_str());
302         SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLSLTextureSampler,
303                                (localSamplerUniforms[t], processor.textureAccess(t)));
304         if (kSamplerExternal_GrSLType == samplerType) {
305             const char* externalFeatureString = this->glslCaps()->externalTextureExtensionString();
306             // We shouldn't ever create a GrGLTexture that requires external sampler type 
307             SkASSERT(externalFeatureString);
308             fFS.addFeature(1 << GrGLSLFragmentShaderBuilder::kExternalTexture_GLSLPrivateFeature,
309                            externalFeatureString);
310         }
311     }
312 }
313
314 bool GrGLProgramBuilder::compileAndAttachShaders(GrGLSLShaderBuilder& shader,
315                                                  GrGLuint programId,
316                                                  GrGLenum type,
317                                                  SkTDArray<GrGLuint>* shaderIds) {
318     GrGLGpu* gpu = this->gpu();
319     GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
320                                                    programId,
321                                                    type,
322                                                    shader.fCompilerStrings.begin(),
323                                                    shader.fCompilerStringLengths.begin(),
324                                                    shader.fCompilerStrings.count(),
325                                                    gpu->stats());
326
327     if (!shaderId) {
328         return false;
329     }
330
331     *shaderIds->append() = shaderId;
332
333     return true;
334 }
335
336 GrGLProgram* GrGLProgramBuilder::finalize() {
337     // verify we can get a program id
338     GrGLuint programID;
339     GL_CALL_RET(programID, CreateProgram());
340     if (0 == programID) {
341         return nullptr;
342     }
343
344     // compile shaders and bind attributes / uniforms
345     SkTDArray<GrGLuint> shadersToDelete;
346     fVS.finalize(GrGLSLUniformHandler::kVertex_Visibility);
347     if (!this->compileAndAttachShaders(fVS, programID, GR_GL_VERTEX_SHADER, &shadersToDelete)) {
348         this->cleanupProgram(programID, shadersToDelete);
349         return nullptr;
350     }
351
352     // NVPR actually requires a vertex shader to compile
353     bool useNvpr = primitiveProcessor().isPathRendering();
354     if (!useNvpr) {
355         const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
356
357         int vaCount = primProc.numAttribs();
358         for (int i = 0; i < vaCount; i++) {
359             GL_CALL(BindAttribLocation(programID, i, primProc.getAttrib(i).fName));
360         }
361     }
362
363     fFS.finalize(GrGLSLUniformHandler::kFragment_Visibility);
364     if (!this->compileAndAttachShaders(fFS, programID, GR_GL_FRAGMENT_SHADER, &shadersToDelete)) {
365         this->cleanupProgram(programID, shadersToDelete);
366         return nullptr;
367     }
368
369     this->bindProgramResourceLocations(programID);
370
371     GL_CALL(LinkProgram(programID));
372
373     // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
374     bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver();
375 #ifdef SK_DEBUG
376     checkLinked = true;
377 #endif
378     if (checkLinked) {
379         checkLinkStatus(programID);
380     }
381     this->resolveProgramResourceLocations(programID);
382
383     this->cleanupShaders(shadersToDelete);
384
385     return this->createProgram(programID);
386 }
387
388 void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
389     fUniformHandler.bindUniformLocations(programID, fGpu->glCaps());
390
391     const GrGLCaps& caps = this->gpu()->glCaps();
392     if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) {
393         GL_CALL(BindFragDataLocation(programID, 0,
394                                      GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
395     }
396     if (fFS.hasSecondaryOutput() && caps.glslCaps()->mustDeclareFragmentShaderOutput()) {
397         GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
398                                   GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
399     }
400
401     // handle NVPR separable varyings
402     if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
403         !fGpu->glPathRendering()->shouldBindFragmentInputs()) {
404         return;
405     }
406     int count = fVaryingHandler.fPathProcVaryingInfos.count();
407     for (int i = 0; i < count; ++i) {
408         GL_CALL(BindFragmentInputLocation(programID, i,
409                                        fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
410         fVaryingHandler.fPathProcVaryingInfos[i].fLocation = i;
411     }
412 }
413
414 bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
415     GrGLint linked = GR_GL_INIT_ZERO;
416     GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
417     if (!linked) {
418         GrGLint infoLen = GR_GL_INIT_ZERO;
419         GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
420         SkAutoMalloc log(sizeof(char)*(infoLen+1));  // outside if for debugger
421         if (infoLen > 0) {
422             // retrieve length even though we don't need it to workaround
423             // bug in chrome cmd buffer param validation.
424             GrGLsizei length = GR_GL_INIT_ZERO;
425             GL_CALL(GetProgramInfoLog(programID,
426                                       infoLen+1,
427                                       &length,
428                                       (char*)log.get()));
429             SkDebugf("%s", (char*)log.get());
430         }
431         SkDEBUGFAIL("Error linking program");
432         GL_CALL(DeleteProgram(programID));
433         programID = 0;
434     }
435     return SkToBool(linked);
436 }
437
438 void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) {
439     fUniformHandler.getUniformLocations(programID, fGpu->glCaps());
440
441     // handle NVPR separable varyings
442     if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
443         !fGpu->glPathRendering()->shouldBindFragmentInputs()) {
444         return;
445     }
446     int count = fVaryingHandler.fPathProcVaryingInfos.count();
447     for (int i = 0; i < count; ++i) {
448         GrGLint location;
449         GL_CALL_RET(location, GetProgramResourceLocation(
450                                        programID,
451                                        GR_GL_FRAGMENT_INPUT,
452                                        fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
453         fVaryingHandler.fPathProcVaryingInfos[i].fLocation = location;
454     }
455 }
456
457 void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
458     GL_CALL(DeleteProgram(programID));
459     cleanupShaders(shaderIDs);
460 }
461 void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
462     for (int i = 0; i < shaderIDs.count(); ++i) {
463       GL_CALL(DeleteShader(shaderIDs[i]));
464     }
465 }
466
467 GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
468     return new GrGLProgram(fGpu,
469                            this->desc(),
470                            fUniformHandles,
471                            programID,
472                            fUniformHandler.fUniforms,
473                            fVaryingHandler.fPathProcVaryingInfos,
474                            fGeometryProcessor,
475                            fXferProcessor,
476                            fFragmentProcessors.get(),
477                            &fSamplerUniforms);
478 }
479
480 ///////////////////////////////////////////////////////////////////////////////////////////////////
481
482 GrGLInstalledFragProcs::~GrGLInstalledFragProcs() {
483     int numProcs = fProcs.count();
484     for (int i = 0; i < numProcs; ++i) {
485         delete fProcs[i];
486     }
487 }