aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar egdaniel <egdaniel@google.com>2016-01-13 12:19:30 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2016-01-13 12:19:30 -0800
commitfa8963252e122c5288c8e92b5ecc25a8fea21c3b (patch)
treec817a9c9d07bec4bacebbf336a7549dfa1f5ce05
parentb76afedf11c7fe933954d030048c3222860249e1 (diff)
Move some program building utils from GL to GLSL
-rw-r--r--include/gpu/GrTypesPriv.h29
-rw-r--r--src/gpu/gl/GrGLProgram.cpp43
-rw-r--r--src/gpu/gl/GrGLProgram.h15
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.cpp257
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.h91
-rwxr-xr-xsrc/gpu/glsl/GrGLSLCaps.h1
-rw-r--r--src/gpu/glsl/GrGLSLFragmentShaderBuilder.h1
-rw-r--r--src/gpu/glsl/GrGLSLProgramBuilder.cpp223
-rw-r--r--src/gpu/glsl/GrGLSLProgramBuilder.h65
-rw-r--r--src/gpu/glsl/GrGLSLShaderBuilder.h2
10 files changed, 361 insertions, 366 deletions
diff --git a/include/gpu/GrTypesPriv.h b/include/gpu/GrTypesPriv.h
index 491b23b37b..6a9c44ff9f 100644
--- a/include/gpu/GrTypesPriv.h
+++ b/include/gpu/GrTypesPriv.h
@@ -107,6 +107,35 @@ static inline bool GrSLTypeIsFloatType(GrSLType type) {
GR_STATIC_ASSERT(8 == kSamplerExternal_GrSLType);
GR_STATIC_ASSERT(9 == kGrSLTypeCount);
}
+
+/** Returns the size in bytes for floating point GrSLTypes. For non floating point type returns 0 */
+static inline size_t GrSLTypeSize(GrSLType type) {
+ SkASSERT(GrSLTypeIsFloatType(type));
+ static const size_t kSizes[] = {
+ 0, // kVoid_GrSLType
+ sizeof(float), // kFloat_GrSLType
+ 2 * sizeof(float), // kVec2f_GrSLType
+ 3 * sizeof(float), // kVec3f_GrSLType
+ 4 * sizeof(float), // kVec4f_GrSLType
+ 9 * sizeof(float), // kMat33f_GrSLType
+ 16 * sizeof(float), // kMat44f_GrSLType
+ 0, // kSampler2D_GrSLType
+ 0 // kSamplerExternal_GrSLType
+ };
+ return kSizes[type];
+
+ GR_STATIC_ASSERT(0 == kVoid_GrSLType);
+ GR_STATIC_ASSERT(1 == kFloat_GrSLType);
+ GR_STATIC_ASSERT(2 == kVec2f_GrSLType);
+ GR_STATIC_ASSERT(3 == kVec3f_GrSLType);
+ GR_STATIC_ASSERT(4 == kVec4f_GrSLType);
+ GR_STATIC_ASSERT(5 == kMat33f_GrSLType);
+ GR_STATIC_ASSERT(6 == kMat44f_GrSLType);
+ GR_STATIC_ASSERT(7 == kSampler2D_GrSLType);
+ GR_STATIC_ASSERT(8 == kSamplerExternal_GrSLType);
+ GR_STATIC_ASSERT(9 == kGrSLTypeCount);
+}
+
//////////////////////////////////////////////////////////////////////////////
/**
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index c1f5b37b07..007d9670bc 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -31,15 +31,15 @@ GrGLProgram::GrGLProgram(GrGLGpu* gpu,
GrGLuint programID,
const UniformInfoArray& uniforms,
const VaryingInfoArray& pathProcVaryings,
- GrGLInstalledGeoProc* geometryProcessor,
- GrGLInstalledXferProc* xferProcessor,
- GrGLInstalledFragProcs* fragmentProcessors,
+ GrGLSLPrimitiveProcessor* geometryProcessor,
+ GrGLSLXferProcessor* xferProcessor,
+ const GrGLSLFragProcs& fragmentProcessors,
SkTArray<UniformHandle>* passSamplerUniforms)
: fBuiltinUniformHandles(builtinUniforms)
, fProgramID(programID)
, fGeometryProcessor(geometryProcessor)
, fXferProcessor(xferProcessor)
- , fFragmentProcessors(SkRef(fragmentProcessors))
+ , fFragmentProcessors(fragmentProcessors)
, fDesc(desc)
, fGpu(gpu)
, fProgramDataManager(gpu, programID, uniforms, pathProcVaryings) {
@@ -55,6 +55,9 @@ GrGLProgram::~GrGLProgram() {
if (fProgramID) {
GL_CALL(DeleteProgram(fProgramID));
}
+ for (int i = 0; i < fFragmentProcessors.count(); ++i) {
+ delete fFragmentProcessors[i];
+ }
}
void GrGLProgram::abandon() {
@@ -63,12 +66,9 @@ void GrGLProgram::abandon() {
///////////////////////////////////////////////////////////////////////////////
-template <class Proc>
-static void append_texture_bindings(const Proc* ip,
- const GrProcessor& processor,
+static void append_texture_bindings(const GrProcessor& processor,
SkTArray<const GrTextureAccess*>* textureBindings) {
if (int numTextures = processor.numTextures()) {
- SkASSERT(textureBindings->count() == ip->fSamplersIdx);
const GrTextureAccess** bindings = textureBindings->push_back_n(numTextures);
int i = 0;
do {
@@ -84,37 +84,32 @@ void GrGLProgram::setData(const GrPrimitiveProcessor& primProc,
// we set the textures, and uniforms for installed processors in a generic way, but subclasses
// of GLProgram determine how to set coord transforms
- fGeometryProcessor->fGLProc->setData(fProgramDataManager, primProc);
- append_texture_bindings(fGeometryProcessor.get(), primProc, textureBindings);
+ fGeometryProcessor->setData(fProgramDataManager, primProc);
+ append_texture_bindings(primProc, textureBindings);
this->setFragmentData(primProc, pipeline, textureBindings);
const GrXferProcessor& xp = pipeline.getXferProcessor();
- fXferProcessor->fGLProc->setData(fProgramDataManager, xp);
- append_texture_bindings(fXferProcessor.get(), xp, textureBindings);
+ fXferProcessor->setData(fProgramDataManager, xp);
+ append_texture_bindings(xp, textureBindings);
}
void GrGLProgram::setFragmentData(const GrPrimitiveProcessor& primProc,
const GrPipeline& pipeline,
SkTArray<const GrTextureAccess*>* textureBindings) {
- int numProcessors = fFragmentProcessors->fProcs.count();
+ int numProcessors = fFragmentProcessors.count();
for (int i = 0; i < numProcessors; ++i) {
const GrFragmentProcessor& processor = pipeline.getFragmentProcessor(i);
- fFragmentProcessors->fProcs[i]->fGLProc->setData(fProgramDataManager, processor);
- this->setTransformData(primProc,
- processor,
- i,
- fFragmentProcessors->fProcs[i]);
- append_texture_bindings(fFragmentProcessors->fProcs[i], processor, textureBindings);
+ fFragmentProcessors[i]->setData(fProgramDataManager, processor);
+ this->setTransformData(primProc, processor, i);
+ append_texture_bindings(processor, textureBindings);
}
}
void GrGLProgram::setTransformData(const GrPrimitiveProcessor& primProc,
const GrFragmentProcessor& processor,
- int index,
- GrGLInstalledFragProc* ip) {
- GrGLSLPrimitiveProcessor* gp = fGeometryProcessor.get()->fGLProc.get();
- gp->setTransformData(primProc, fProgramDataManager, index,
- processor.coordTransforms());
+ int index) {
+ fGeometryProcessor->setTransformData(primProc, fProgramDataManager, index,
+ processor.coordTransforms());
}
void GrGLProgram::setRenderTargetState(const GrPrimitiveProcessor& primProc,
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index ad0569817b..22678cb6a3 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -108,9 +108,9 @@ protected:
GrGLuint programID,
const UniformInfoArray&,
const VaryingInfoArray&, // used for NVPR only currently
- GrGLInstalledGeoProc* geometryProcessor,
- GrGLInstalledXferProc* xferProcessor,
- GrGLInstalledFragProcs* fragmentProcessors,
+ GrGLSLPrimitiveProcessor* geometryProcessor,
+ GrGLSLXferProcessor* xferProcessor,
+ const GrGLSLFragProcs& fragmentProcessors,
SkTArray<UniformHandle>* passSamplerUniforms);
// A templated helper to loop over effects, set the transforms(via subclass) and bind textures
@@ -118,8 +118,7 @@ protected:
SkTArray<const GrTextureAccess*>* textureBindings);
void setTransformData(const GrPrimitiveProcessor&,
const GrFragmentProcessor&,
- int index,
- GrGLInstalledFragProc*);
+ int index);
// Helper for setData() that sets the view matrix and loads the render target height uniform
void setRenderTargetState(const GrPrimitiveProcessor&, const GrPipeline&);
@@ -130,9 +129,9 @@ protected:
GrGLuint fProgramID;
// the installed effects
- SkAutoTDelete<GrGLInstalledGeoProc> fGeometryProcessor;
- SkAutoTDelete<GrGLInstalledXferProc> fXferProcessor;
- SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
+ SkAutoTDelete<GrGLSLPrimitiveProcessor> fGeometryProcessor;
+ SkAutoTDelete<GrGLSLXferProcessor> fXferProcessor;
+ GrGLSLFragProcs fFragmentProcessors;
GrProgramDesc fDesc;
GrGLGpu* fGpu;
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<const GrCoordTransform*, true>& 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 <class Proc>
void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
- GrGLSLTextureSampler::TextureSamplerArray* outSamplers,
- GrGLInstalledProc<Proc>* 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<GrGLuint>& shaderIDs) {
GL_CALL(DeleteProgram(programID));
- cleanupShaders(shaderIDs);
+ this->cleanupShaders(shaderIDs);
+ this->cleanupFragmentProcessors();
}
void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& 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 <class Proc>
-struct GrGLInstalledProc {
- SkDEBUGCODE(int fSamplersIdx;)
- SkAutoTDelete<Proc> fGLProc;
-};
-
-typedef GrGLInstalledProc<GrGLSLPrimitiveProcessor> GrGLInstalledGeoProc;
-typedef GrGLInstalledProc<GrGLSLXferProcessor> GrGLInstalledXferProc;
-typedef GrGLInstalledProc<GrGLSLFragmentProcessor> 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 <class Proc>
void emitSamplers(const GrProcessor&,
- GrGLSLTextureSampler::TextureSamplerArray* outSamplers,
- GrGLInstalledProc<Proc>*);
+ 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<GrGLInstalledFragProcs> fFragmentProcessors;
GrGLGpu* fGpu;
- GrGLSLPrimitiveProcessor::TransformsIn fCoordTransforms;
- GrGLSLPrimitiveProcessor::TransformsOut fOutCoords;
typedef GrGLSLUniformHandler::UniformHandle UniformHandle;
SkTArray<UniformHandle> fSamplerUniforms;
diff --git a/src/gpu/glsl/GrGLSLCaps.h b/src/gpu/glsl/GrGLSLCaps.h
index 136bef466c..060539645e 100755
--- a/src/gpu/glsl/GrGLSLCaps.h
+++ b/src/gpu/glsl/GrGLSLCaps.h
@@ -158,6 +158,7 @@ private:
GrSwizzle fConfigOutputSwizzle[kGrPixelConfigCnt];
friend class GrGLCaps; // For initialization.
+ friend class GrVkCaps;
typedef GrShaderCaps INHERITED;
};
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
index a55fdd2860..820cf17ae4 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
@@ -194,6 +194,7 @@ private:
bool fHasReadDstColor;
bool fHasReadFragmentPosition;
+ friend class GrGLSLProgramBuilder;
friend class GrGLProgramBuilder;
typedef GrGLSLXPFragmentBuilder INHERITED;
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index d3ed719fdc..6e0e95f16a 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -7,6 +7,11 @@
#include "glsl/GrGLSLProgramBuilder.h"
+#include "GrPipeline.h"
+#include "glsl/GrGLSLFragmentProcessor.h"
+#include "glsl/GrGLSLGeometryProcessor.h"
+#include "glsl/GrGLSLXferProcessor.h"
+
const int GrGLSLProgramBuilder::kVarsPerBlock = 8;
GrGLSLProgramBuilder::GrGLSLProgramBuilder(const DrawArgs& args)
@@ -14,7 +19,203 @@ GrGLSLProgramBuilder::GrGLSLProgramBuilder(const DrawArgs& args)
, fGS(this)
, fFS(this, args.fDesc->header().fFragPosKey)
, fStageIndex(-1)
- , fArgs(args) {
+ , fArgs(args)
+ , fGeometryProcessor(nullptr)
+ , fXferProcessor(nullptr) {
+}
+
+bool GrGLSLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor,
+ GrGLSLExpr4* inputCoverage,
+ int maxTextures) {
+ // 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();
+
+ for (int i = 0; i < this->pipeline().numFragmentProcessors(); i++) {
+ const GrFragmentProcessor& processor = this->pipeline().getFragmentProcessor(i);
+
+ if (!primProc.hasTransformedLocalCoords()) {
+ SkTArray<const GrCoordTransform*, true>& procCoords = fCoordTransforms.push_back();
+ processor.gatherCoordTransforms(&procCoords);
+ }
+
+ totalTextures += processor.numTextures();
+ if (totalTextures >= maxTextures) {
+ GrCapsDebugf(this->caps(), "Program would use too many texture units\n");
+ return false;
+ }
+ }
+
+ this->emitAndInstallPrimProc(primProc, inputColor, inputCoverage);
+
+ 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 GrGLSLProgramBuilder::emitAndInstallPrimProc(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());
+
+ SkASSERT(!fGeometryProcessor);
+ fGeometryProcessor = proc.createGLSLInstance(*this->glslCaps());
+
+ SkSTArray<4, GrGLSLTextureSampler> samplers(proc.numTextures());
+ this->emitSamplers(proc, &samplers);
+
+ GrGLSLGeometryProcessor::EmitArgs args(&fVS,
+ &fFS,
+ this->varyingHandler(),
+ this->uniformHandler(),
+ this->glslCaps(),
+ proc,
+ outputColor->c_str(),
+ outputCoverage->c_str(),
+ samplers,
+ fCoordTransforms,
+ &fOutCoords);
+ fGeometryProcessor->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(proc);
+
+ fFS.codeAppend("}");
+}
+
+void GrGLSLProgramBuilder::emitAndInstallFragProcs(int procOffset,
+ int numProcs,
+ GrGLSLExpr4* inOut) {
+ for (int i = procOffset; i < numProcs; ++i) {
+ GrGLSLExpr4 output;
+ const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i);
+ this->emitAndInstallFragProc(fp, i, *inOut, &output);
+ *inOut = output;
+ }
+}
+
+// TODO Processors cannot output zeros because an empty string is all 1s
+// the fix is to allow effects to take the GrGLSLExpr4 directly
+void GrGLSLProgramBuilder::emitAndInstallFragProc(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());
+
+ GrGLSLFragmentProcessor* fragProc = fp.createGLSLInstance();
+
+ SkSTArray<4, GrGLSLTextureSampler> samplers(fp.numTextures());
+ this->emitSamplers(fp, &samplers);
+
+ GrGLSLFragmentProcessor::EmitArgs args(&fFS,
+ this->uniformHandler(),
+ this->glslCaps(),
+ fp,
+ output->c_str(),
+ input.isOnes() ? nullptr : input.c_str(),
+ fOutCoords[index],
+ samplers);
+ fragProc->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.push_back(fragProc);
+
+ fFS.codeAppend("}");
+}
+
+void GrGLSLProgramBuilder::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 = 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);
+
+ GrGLSLXferProcessor::EmitArgs args(&fFS,
+ this->uniformHandler(),
+ this->glslCaps(),
+ xp, colorIn.c_str(),
+ ignoresCoverage ? nullptr : coverageIn.c_str(),
+ fFS.getPrimaryColorOutputName(),
+ fFS.getSecondaryColorOutputName(),
+ samplers);
+ fXferProcessor->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 GrGLSLProgramBuilder::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 GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
+ SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
+}
+
+void GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) {
+ SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor());
+}
+
+void GrGLSLProgramBuilder::verify(const GrFragmentProcessor& fp) {
+ SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
}
void GrGLSLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name, bool mangle) {
@@ -32,6 +233,20 @@ void GrGLSLProgramBuilder::nameVariable(SkString* out, char prefix, const char*
}
}
+void GrGLSLProgramBuilder::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;
+}
+
void GrGLSLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
SkString* out) const {
this->uniformHandler()->appendUniformDecls(visibility, out);
@@ -58,3 +273,9 @@ void GrGLSLProgramBuilder::addRTHeightUniform(const char* name, const char** out
name, false, 0, outName);
}
+void GrGLSLProgramBuilder::cleanupFragmentProcessors() {
+ for (int i = 0; i < fFragmentProcessors.count(); ++i) {
+ delete fFragmentProcessors[i];
+ }
+}
+
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.h b/src/gpu/glsl/GrGLSLProgramBuilder.h
index 2a3b48508c..964d320298 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.h
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.h
@@ -12,14 +12,19 @@
#include "GrGpu.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLGeometryShaderBuilder.h"
+#include "glsl/GrGLSLPrimitiveProcessor.h"
#include "glsl/GrGLSLProgramDataManager.h"
#include "glsl/GrGLSLUniformHandler.h"
+#include "glsl/GrGLSLTextureSampler.h"
#include "glsl/GrGLSLVertexShaderBuilder.h"
+#include "glsl/GrGLSLXferProcessor.h"
class GrGLSLCaps;
class GrGLSLShaderVar;
class GrGLSLVaryingHandler;
+typedef SkSTArray<8, GrGLSLFragmentProcessor*, true> GrGLSLFragProcs;
+
class GrGLSLProgramBuilder {
public:
typedef GrGpu::DrawArgs DrawArgs;
@@ -28,6 +33,7 @@ public:
virtual ~GrGLSLProgramBuilder() {}
+ virtual const GrCaps* caps() const = 0;
virtual const GrGLSLCaps* glslCaps() const = 0;
const GrPrimitiveProcessor& primitiveProcessor() const { return *fArgs.fPrimitiveProcessor; }
@@ -76,8 +82,67 @@ public:
BuiltinUniformHandles fUniformHandles;
+ GrGLSLPrimitiveProcessor* fGeometryProcessor;
+ GrGLSLXferProcessor* fXferProcessor;
+ GrGLSLFragProcs fFragmentProcessors;
+
protected:
explicit GrGLSLProgramBuilder(const DrawArgs& args);
+
+ bool emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage, int maxTextures);
+
+ void cleanupFragmentProcessors();
+
+private:
+ // 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(GrGLSLProgramBuilder* pb)
+ : fPB(pb) {
+ fPB->reset();
+ // Each output to the fragment processor gets its own code section
+ fPB->fFS.nextStage();
+ }
+ ~AutoStageAdvance() {}
+ private:
+ GrGLSLProgramBuilder* fPB;
+ };
+
+ // 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);
+
+ void emitAndInstallPrimProc(const GrPrimitiveProcessor&,
+ GrGLSLExpr4* outputColor,
+ GrGLSLExpr4* outputCoverage);
+ void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut);
+ void emitAndInstallFragProc(const GrFragmentProcessor&,
+ int index,
+ const GrGLSLExpr4& input,
+ GrGLSLExpr4* output);
+ 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&);
+
+ virtual void emitSamplers(const GrProcessor& processor,
+ GrGLSLTextureSampler::TextureSamplerArray* outSamplers) = 0;
+
+ GrGLSLPrimitiveProcessor::TransformsIn fCoordTransforms;
+ GrGLSLPrimitiveProcessor::TransformsOut fOutCoords;
};
#endif
diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.h b/src/gpu/glsl/GrGLSLShaderBuilder.h
index 1a8255dbb4..16a0756306 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.h
@@ -191,7 +191,9 @@ protected:
int fCodeIndex;
bool fFinalized;
+ friend class GrGLSLProgramBuilder;
friend class GrGLProgramBuilder;
friend class GrGLPathProgramBuilder; // to access fInputs.
+ friend class GrVkProgramBuilder;
};
#endif