From fa8963252e122c5288c8e92b5ecc25a8fea21c3b Mon Sep 17 00:00:00 2001 From: egdaniel Date: Wed, 13 Jan 2016 12:19:30 -0800 Subject: Move some program building utils from GL to GLSL BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1535603006 Review URL: https://codereview.chromium.org/1535603006 --- src/gpu/gl/builders/GrGLProgramBuilder.cpp | 257 ++--------------------------- src/gpu/gl/builders/GrGLProgramBuilder.h | 91 +--------- 2 files changed, 15 insertions(+), 333 deletions(-) (limited to 'src/gpu/gl/builders') diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp index 4360f7858d..4503d1a197 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp +++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp @@ -42,7 +42,10 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gp GrGLSLExpr4 inputColor; GrGLSLExpr4 inputCoverage; - if (!pb->emitAndInstallProcs(&inputColor, &inputCoverage)) { + if (!pb->emitAndInstallProcs(&inputColor, + &inputCoverage, + gpu->glCaps().maxFragmentTextureUnits())) { + pb->cleanupFragmentProcessors(); return nullptr; } @@ -53,243 +56,18 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gp GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args) : INHERITED(args) - , fGeometryProcessor(nullptr) - , fXferProcessor(nullptr) , fGpu(gpu) , fSamplerUniforms(4) , fVaryingHandler(this) , fUniformHandler(this) { } -const GrGLSLCaps* GrGLProgramBuilder::glslCaps() const { - return this->fGpu->ctxInfo().caps()->glslCaps(); -} - -bool GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) { - // First we loop over all of the installed processors and collect coord transforms. These will - // be sent to the GrGLSLPrimitiveProcessor in its emitCode function - const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); - int totalTextures = primProc.numTextures(); - const int maxTextureUnits = fGpu->glCaps().maxFragmentTextureUnits(); - - for (int i = 0; i < this->pipeline().numFragmentProcessors(); i++) { - const GrFragmentProcessor& processor = this->pipeline().getFragmentProcessor(i); - - if (!primProc.hasTransformedLocalCoords()) { - SkTArray& procCoords = fCoordTransforms.push_back(); - processor.gatherCoordTransforms(&procCoords); - } - - totalTextures += processor.numTextures(); - if (totalTextures >= maxTextureUnits) { - GrCapsDebugf(fGpu->caps(), "Program would use too many texture units\n"); - return false; - } - } - - this->emitAndInstallProc(primProc, inputColor, inputCoverage); - - fFragmentProcessors.reset(new GrGLInstalledFragProcs); - int numProcs = this->pipeline().numFragmentProcessors(); - this->emitAndInstallFragProcs(0, this->pipeline().numColorFragmentProcessors(), inputColor); - this->emitAndInstallFragProcs(this->pipeline().numColorFragmentProcessors(), numProcs, - inputCoverage); - this->emitAndInstallXferProc(this->pipeline().getXferProcessor(), *inputColor, *inputCoverage, - this->pipeline().ignoresCoverage()); - this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSecondaryOutput()); - return true; -} - -void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, - int numProcs, - GrGLSLExpr4* inOut) { - for (int i = procOffset; i < numProcs; ++i) { - GrGLSLExpr4 output; - const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i); - this->emitAndInstallProc(fp, i, *inOut, &output); - *inOut = output; - } -} - -void GrGLProgramBuilder::nameExpression(GrGLSLExpr4* output, const char* baseName) { - // create var to hold stage result. If we already have a valid output name, just use that - // otherwise create a new mangled one. This name is only valid if we are reordering stages - // and have to tell stage exactly where to put its output. - SkString outName; - if (output->isValid()) { - outName = output->c_str(); - } else { - this->nameVariable(&outName, '\0', baseName); - } - fFS.codeAppendf("vec4 %s;", outName.c_str()); - *output = outName; -} - -// TODO Processors cannot output zeros because an empty string is all 1s -// the fix is to allow effects to take the GrGLSLExpr4 directly -void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentProcessor& fp, - int index, - const GrGLSLExpr4& input, - GrGLSLExpr4* output) { - // Program builders have a bit of state we need to clear with each effect - AutoStageAdvance adv(this); - this->nameExpression(output, "output"); - - // Enclose custom code in a block to avoid namespace conflicts - SkString openBrace; - openBrace.printf("{ // Stage %d, %s\n", fStageIndex, fp.name()); - fFS.codeAppend(openBrace.c_str()); - - this->emitAndInstallProc(fp, index, output->c_str(), input.isOnes() ? nullptr : input.c_str()); - - fFS.codeAppend("}"); -} - -void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& proc, - GrGLSLExpr4* outputColor, - GrGLSLExpr4* outputCoverage) { - // Program builders have a bit of state we need to clear with each effect - AutoStageAdvance adv(this); - this->nameExpression(outputColor, "outputColor"); - this->nameExpression(outputCoverage, "outputCoverage"); - - // Enclose custom code in a block to avoid namespace conflicts - SkString openBrace; - openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name()); - fFS.codeAppend(openBrace.c_str()); - fVS.codeAppendf("// Primitive Processor %s\n", proc.name()); - - this->emitAndInstallProc(proc, outputColor->c_str(), outputCoverage->c_str()); - - fFS.codeAppend("}"); -} - -void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentProcessor& fp, - int index, - const char* outColor, - const char* inColor) { - GrGLInstalledFragProc* ifp = new GrGLInstalledFragProc; - - ifp->fGLProc.reset(fp.createGLSLInstance()); - - SkSTArray<4, GrGLSLTextureSampler> samplers(fp.numTextures()); - this->emitSamplers(fp, &samplers, ifp); - - GrGLSLFragmentProcessor::EmitArgs args(&fFS, - &fUniformHandler, - this->glslCaps(), - fp, - outColor, - inColor, - fOutCoords[index], - samplers); - ifp->fGLProc->emitCode(args); - - // We have to check that effects and the code they emit are consistent, ie if an effect - // asks for dst color, then the emit code needs to follow suit - verify(fp); - fFragmentProcessors->fProcs.push_back(ifp); +const GrCaps* GrGLProgramBuilder::caps() const { + return fGpu->caps(); } -void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& gp, - const char* outColor, - const char* outCoverage) { - SkASSERT(!fGeometryProcessor); - fGeometryProcessor = new GrGLInstalledGeoProc; - - fGeometryProcessor->fGLProc.reset(gp.createGLSLInstance(*fGpu->glCaps().glslCaps())); - - SkSTArray<4, GrGLSLTextureSampler> samplers(gp.numTextures()); - this->emitSamplers(gp, &samplers, fGeometryProcessor); - - GrGLSLGeometryProcessor::EmitArgs args(&fVS, - &fFS, - &fVaryingHandler, - &fUniformHandler, - this->glslCaps(), - gp, - outColor, - outCoverage, - samplers, - fCoordTransforms, - &fOutCoords); - fGeometryProcessor->fGLProc->emitCode(args); - - // We have to check that effects and the code they emit are consistent, ie if an effect - // asks for dst color, then the emit code needs to follow suit - verify(gp); -} - -void GrGLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp, - const GrGLSLExpr4& colorIn, - const GrGLSLExpr4& coverageIn, - bool ignoresCoverage) { - // Program builders have a bit of state we need to clear with each effect - AutoStageAdvance adv(this); - - SkASSERT(!fXferProcessor); - fXferProcessor = new GrGLInstalledXferProc; - - fXferProcessor->fGLProc.reset(xp.createGLSLInstance()); - - // Enable dual source secondary output if we have one - if (xp.hasSecondaryOutput()) { - fFS.enableSecondaryOutput(); - } - - if (this->glslCaps()->mustDeclareFragmentShaderOutput()) { - fFS.enableCustomOutput(); - } - - SkString openBrace; - openBrace.printf("{ // Xfer Processor: %s\n", xp.name()); - fFS.codeAppend(openBrace.c_str()); - - SkSTArray<4, GrGLSLTextureSampler> samplers(xp.numTextures()); - this->emitSamplers(xp, &samplers, fXferProcessor); - - GrGLSLXferProcessor::EmitArgs args(&fFS, - &fUniformHandler, - this->glslCaps(), - xp, colorIn.c_str(), - ignoresCoverage ? nullptr : coverageIn.c_str(), - fFS.getPrimaryColorOutputName(), - fFS.getSecondaryColorOutputName(), - samplers); - fXferProcessor->fGLProc->emitCode(args); - - // We have to check that effects and the code they emit are consistent, ie if an effect - // asks for dst color, then the emit code needs to follow suit - verify(xp); - fFS.codeAppend("}"); -} - -void GrGLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) { - // Swizzle the fragment shader outputs if necessary. - GrSwizzle swizzle; - swizzle.setFromKey(this->desc().header().fOutputSwizzle); - if (swizzle != GrSwizzle::RGBA()) { - fFS.codeAppendf("%s = %s.%s;", fFS.getPrimaryColorOutputName(), - fFS.getPrimaryColorOutputName(), - swizzle.c_str()); - if (hasSecondaryOutput) { - fFS.codeAppendf("%s = %s.%s;", fFS.getSecondaryColorOutputName(), - fFS.getSecondaryColorOutputName(), - swizzle.c_str()); - } - } -} - -void GrGLProgramBuilder::verify(const GrPrimitiveProcessor& gp) { - SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition()); -} - -void GrGLProgramBuilder::verify(const GrXferProcessor& xp) { - SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor()); -} - -void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) { - SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition()); +const GrGLSLCaps* GrGLProgramBuilder::glslCaps() const { + return fGpu->ctxInfo().caps()->glslCaps(); } static GrSLType get_sampler_type(const GrTextureAccess& access) { @@ -302,11 +80,8 @@ static GrSLType get_sampler_type(const GrTextureAccess& access) { } } -template void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, - GrGLSLTextureSampler::TextureSamplerArray* outSamplers, - GrGLInstalledProc* ip) { - SkDEBUGCODE(ip->fSamplersIdx = fSamplerUniforms.count();) + GrGLSLTextureSampler::TextureSamplerArray* outSamplers) { int numTextures = processor.numTextures(); UniformHandle* localSamplerUniforms = fSamplerUniforms.push_back_n(numTextures); SkString name; @@ -356,6 +131,7 @@ GrGLProgram* GrGLProgramBuilder::finalize() { GrGLuint programID; GL_CALL_RET(programID, CreateProgram()); if (0 == programID) { + this->cleanupFragmentProcessors(); return nullptr; } @@ -474,7 +250,8 @@ void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) { void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray& shaderIDs) { GL_CALL(DeleteProgram(programID)); - cleanupShaders(shaderIDs); + this->cleanupShaders(shaderIDs); + this->cleanupFragmentProcessors(); } void GrGLProgramBuilder::cleanupShaders(const SkTDArray& shaderIDs) { for (int i = 0; i < shaderIDs.count(); ++i) { @@ -491,15 +268,7 @@ GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) { fVaryingHandler.fPathProcVaryingInfos, fGeometryProcessor, fXferProcessor, - fFragmentProcessors.get(), + fFragmentProcessors, &fSamplerUniforms); } -/////////////////////////////////////////////////////////////////////////////////////////////////// - -GrGLInstalledFragProcs::~GrGLInstalledFragProcs() { - int numProcs = fProcs.count(); - for (int i = 0; i < numProcs; ++i) { - delete fProcs[i]; - } -} diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h index 70cfad5633..20879253ca 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.h +++ b/src/gpu/gl/builders/GrGLProgramBuilder.h @@ -12,42 +12,14 @@ #include "gl/GrGLProgramDataManager.h" #include "gl/GrGLUniformHandler.h" #include "gl/GrGLVaryingHandler.h" -#include "glsl/GrGLSLPrimitiveProcessor.h" #include "glsl/GrGLSLProgramBuilder.h" #include "glsl/GrGLSLProgramDataManager.h" -#include "glsl/GrGLSLTextureSampler.h" -#include "glsl/GrGLSLXferProcessor.h" class GrFragmentProcessor; class GrGLContextInfo; class GrGLSLShaderBuilder; class GrGLSLCaps; -/** - * The below struct represent processors installed in programs. - */ -template -struct GrGLInstalledProc { - SkDEBUGCODE(int fSamplersIdx;) - SkAutoTDelete fGLProc; -}; - -typedef GrGLInstalledProc GrGLInstalledGeoProc; -typedef GrGLInstalledProc GrGLInstalledXferProc; -typedef GrGLInstalledProc GrGLInstalledFragProc; - -struct GrGLInstalledFragProcs : public SkRefCnt { - virtual ~GrGLInstalledFragProcs(); - SkSTArray<8, GrGLInstalledFragProc*, true> fProcs; -}; - -/* - * Please note - no diamond problems because of virtual inheritance. Also, both base classes - * are pure virtual with no data members. This is the base class for program building. - * Subclasses are nearly identical but each has their own way of emitting transforms. State for - * each of the elements of the shader pipeline, ie vertex, fragment, geometry, etc, lives in those - * respective builders -*/ class GrGLProgramBuilder : public GrGLSLProgramBuilder { public: /** Generates a shader program. @@ -59,6 +31,7 @@ public: */ static GrGLProgram* CreateProgram(const DrawArgs&, GrGLGpu*); + const GrCaps* caps() const override; const GrGLSLCaps* glslCaps() const override; GrGLGpu* gpu() const { return fGpu; } @@ -66,41 +39,8 @@ public: private: GrGLProgramBuilder(GrGLGpu*, const DrawArgs&); - // Generates a possibly mangled name for a stage variable and writes it to the fragment shader. - // If GrGLSLExpr4 has a valid name then it will use that instead - void nameExpression(GrGLSLExpr4*, const char* baseName); - bool emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage); - void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut); - void emitAndInstallProc(const GrFragmentProcessor&, - int index, - const GrGLSLExpr4& input, - GrGLSLExpr4* output); - - void emitAndInstallProc(const GrPrimitiveProcessor&, - GrGLSLExpr4* outputColor, - GrGLSLExpr4* outputCoverage); - - // these emit functions help to keep the createAndEmitProcessors template general - void emitAndInstallProc(const GrFragmentProcessor&, - int index, - const char* outColor, - const char* inColor); - void emitAndInstallProc(const GrPrimitiveProcessor&, - const char* outColor, - const char* outCoverage); - void emitAndInstallXferProc(const GrXferProcessor&, - const GrGLSLExpr4& colorIn, - const GrGLSLExpr4& coverageIn, - bool ignoresCoverage); - void emitFSOutputSwizzle(bool hasSecondaryOutput); - - void verify(const GrPrimitiveProcessor&); - void verify(const GrXferProcessor&); - void verify(const GrFragmentProcessor&); - template void emitSamplers(const GrProcessor&, - GrGLSLTextureSampler::TextureSamplerArray* outSamplers, - GrGLInstalledProc*); + GrGLSLTextureSampler::TextureSamplerArray* outSamplers) override; bool compileAndAttachShaders(GrGLSLShaderBuilder& shader, GrGLuint programId, @@ -120,35 +60,8 @@ private: const GrGLSLUniformHandler* uniformHandler() const override { return &fUniformHandler; } GrGLSLVaryingHandler* varyingHandler() override { return &fVaryingHandler; } - // reset is called by program creator between each processor's emit code. It increments the - // stage offset for variable name mangling, and also ensures verfication variables in the - // fragment shader are cleared. - void reset() { - this->addStage(); - fFS.reset(); - } - void addStage() { fStageIndex++; } - - class AutoStageAdvance { - public: - AutoStageAdvance(GrGLProgramBuilder* pb) - : fPB(pb) { - fPB->reset(); - // Each output to the fragment processor gets its own code section - fPB->fFS.nextStage(); - } - ~AutoStageAdvance() {} - private: - GrGLProgramBuilder* fPB; - }; - - GrGLInstalledGeoProc* fGeometryProcessor; - GrGLInstalledXferProc* fXferProcessor; - SkAutoTUnref fFragmentProcessors; GrGLGpu* fGpu; - GrGLSLPrimitiveProcessor::TransformsIn fCoordTransforms; - GrGLSLPrimitiveProcessor::TransformsOut fOutCoords; typedef GrGLSLUniformHandler::UniformHandle UniformHandle; SkTArray fSamplerUniforms; -- cgit v1.2.3