Refactor separable varying location info to be stored in GrGLProgram subclass

Refactor separable varying location info to be stored in GrGLProgram
subclass GrGLProgram instead of storing it in GrGLPathProcessor.

Separable varyings are exactly analoguous to uniforms: they are inputs
to the shader program. Shader compile-time information about uniforms is gathered to
GrGLProgramBuilder. This information is the converted to link-time
information, uniform locations, when constructing the program. Separable
varyings need to have same lifetime model.

This is needed in the future to support path rendering in Chromium. The
Chromium pseudo-extension will expose program fragment input binding
function similar to uniform binding function. Thus the separable varying
locations need to be decided and bound before link, e.g. before
GrGLProgram is created. This will be achieved in further patches by
overloading GrGLProgramBuilder::bindProgramResourceLocations() in
GrGLNvprProgramBuilder.

BUG=chromium:344330

Review URL: https://codereview.chromium.org/1186113007
This commit is contained in:
kkinnunen 2015-06-29 23:01:28 -07:00 committed by Commit bot
parent e04edd8c86
commit 7aedda57f8
16 changed files with 380 additions and 163 deletions

View File

@ -295,6 +295,10 @@
'<(skia_src_path)/gpu/gl/GrGLNameAllocator.h',
'<(skia_src_path)/gpu/gl/GrGLNoOpInterface.cpp',
'<(skia_src_path)/gpu/gl/GrGLNoOpInterface.h',
'<(skia_src_path)/gpu/gl/GrGLPathProgram.cpp',
'<(skia_src_path)/gpu/gl/GrGLPathProgram.h',
'<(skia_src_path)/gpu/gl/GrGLPathProgramDataManager.cpp',
'<(skia_src_path)/gpu/gl/GrGLPathProgramDataManager.h',
'<(skia_src_path)/gpu/gl/GrGLPath.cpp',
'<(skia_src_path)/gpu/gl/GrGLPath.h',
'<(skia_src_path)/gpu/gl/GrGLPathProcessor.cpp',
@ -331,6 +335,8 @@
'<(skia_src_path)/gpu/gl/GrGLXferProcessor.h',
# Files for building GLSL shaders
'<(skia_src_path)/gpu/gl/builders/GrGLPathProgramBuilder.cpp',
'<(skia_src_path)/gpu/gl/builders/GrGLPathProgramBuilder.h',
'<(skia_src_path)/gpu/gl/builders/GrGLProgramBuilder.cpp',
'<(skia_src_path)/gpu/gl/builders/GrGLProgramBuilder.h',
'<(skia_src_path)/gpu/gl/builders/GrGLShaderBuilder.cpp',

View File

@ -71,16 +71,11 @@ void GrGLPathProcessor::emitTransforms(GrGLGPBuilder* pb, const TransformsIn& ti
coordTransforms[t]->getMatrix().hasPerspective() ? kVec3f_GrSLType :
kVec2f_GrSLType;
SkString strVaryingName("MatrixCoord");
strVaryingName.appendf("_%i_%i", i, t);
GrGLVertToFrag v(varyingType);
pb->addVarying(strVaryingName.c_str(), &v);
SeparableVaryingInfo& varyingInfo = fSeparableVaryingInfos.push_back();
varyingInfo.fVariable = pb->getFragmentShaderBuilder()->fInputs.back();
varyingInfo.fLocation = fSeparableVaryingInfos.count() - 1;
varyingInfo.fType = varyingType;
fInstalledTransforms[i][t].fHandle = ShaderVarHandle(varyingInfo.fLocation);
fInstalledTransforms[i][t].fHandle =
pb->addSeparableVarying(strVaryingName.c_str(), &v).toShaderBuilderIndex();
fInstalledTransforms[i][t].fType = varyingType;
SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords,
@ -89,25 +84,11 @@ void GrGLPathProcessor::emitTransforms(GrGLGPBuilder* pb, const TransformsIn& ti
}
}
void GrGLPathProcessor::resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId) {
int count = fSeparableVaryingInfos.count();
for (int i = 0; i < count; ++i) {
GrGLint location;
GR_GL_CALL_RET(gpu->glInterface(),
location,
GetProgramResourceLocation(programId,
GR_GL_FRAGMENT_INPUT,
fSeparableVaryingInfos[i].fVariable.c_str()));
fSeparableVaryingInfos[i].fLocation = location;
}
}
void GrGLPathProcessor::setTransformData(
const GrPrimitiveProcessor& primProc,
const GrGLPathProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& coordTransforms,
GrGLPathRendering* glpr,
GrGLuint programID) {
const SkTArray<const GrCoordTransform*, true>& coordTransforms) {
const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
SkSTArray<2, Transform, true>& transforms = fInstalledTransforms[index];
int numTransforms = transforms.count();
@ -119,15 +100,10 @@ void GrGLPathProcessor::setTransformData(
continue;
}
transforms[t].fCurrentValue = transform;
const SeparableVaryingInfo& fragmentInput =
fSeparableVaryingInfos[transforms[t].fHandle.handle()];
SkASSERT(transforms[t].fType == kVec2f_GrSLType ||
transforms[t].fType == kVec3f_GrSLType);
unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3;
glpr->setProgramPathFragmentInputTransform(programID,
fragmentInput.fLocation,
GR_GL_OBJECT_LINEAR,
components,
transform);
pdman.setPathFragmentInputTransform(transforms[t].fHandle.handle(), components, transform);
}
}

View File

@ -13,6 +13,7 @@
class GrPathProcessor;
class GrGLPathRendering;
class GrGLGpu;
class GrGLPathProgramDataManager;
class GrGLPathProcessor : public GrGLPrimitiveProcessor {
public:
@ -27,6 +28,7 @@ public:
void emitTransforms(GrGLGPBuilder*, const TransformsIn&, TransformsOut*);
void bindSeparableVaryings(GrGLGpu* gpu, GrGLuint programID);
void resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId);
void setData(const GrGLProgramDataManager&,
@ -34,25 +36,15 @@ public:
const GrBatchTracker&) override;
void setTransformData(const GrPrimitiveProcessor&,
const GrGLPathProgramDataManager&,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms,
GrGLPathRendering*,
GrGLuint programID);
const SkTArray<const GrCoordTransform*, true>& transforms);
virtual void didSetData(GrGLPathRendering*) {}
private:
UniformHandle fColorUniform;
GrColor fColor;
struct SeparableVaryingInfo {
GrSLType fType;
GrGLShaderVar fVariable;
GrGLint fLocation;
};
typedef SkSTArray<8, SeparableVaryingInfo, true> SeparableVaryingInfoArray;
SeparableVaryingInfoArray fSeparableVaryingInfos;
typedef GrGLPrimitiveProcessor INHERITED;
};

View File

@ -0,0 +1,52 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrGLPathProgram.h"
#include "GrGLPathProcessor.h"
#include "GrGLGpu.h"
#include "GrPathProcessor.h"
GrGLPathProgram::GrGLPathProgram(GrGLGpu* gpu,
const GrProgramDesc& desc,
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
const SeparableVaryingInfoArray& separableVaryings,
GrGLInstalledGeoProc* primProc,
GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors,
SkTArray<UniformHandle>* passSamplerUniforms)
: INHERITED(gpu, desc, builtinUniforms, programID, uniforms, primProc,
xferProcessor, fragmentProcessors, passSamplerUniforms)
, fPathProgramDataManager(gpu, fProgramID, separableVaryings) {
}
void GrGLPathProgram::didSetData() {
GrGLPathProcessor* pathProc =
static_cast<GrGLPathProcessor*>(fGeometryProcessor.get()->fGLProc.get());
pathProc->didSetData(fGpu->glPathRendering());
}
void GrGLPathProgram::setTransformData(const GrPrimitiveProcessor& primProc,
const GrPendingFragmentStage& proc,
int index,
GrGLInstalledFragProc* ip) {
GrGLPathProcessor* pathProc =
static_cast<GrGLPathProcessor*>(fGeometryProcessor.get()->fGLProc.get());
pathProc->setTransformData(primProc, fPathProgramDataManager, index,
proc.processor()->coordTransforms());
}
void GrGLPathProgram::onSetRenderTargetState(const GrPrimitiveProcessor& primProc,
const GrPipeline& pipeline) {
SkASSERT(!primProc.willUseGeoShader() && primProc.numAttribs() == 0);
const GrRenderTarget* rt = pipeline.getRenderTarget();
SkISize size;
size.set(rt->width(), rt->height());
const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
fGpu->glPathRendering()->setProjectionMatrix(pathProc.viewMatrix(),
size, rt->origin());
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrGLPathProgram_DEFINED
#define GrGLPathProgram_DEFINED
#include "gl/GrGLProgram.h"
#include "gl/GrGLPathProgramDataManager.h"
/*
* The default GrGL programs consist of at the very least a vertex and fragment shader.
* 1.3+ Nvpr ignores the vertex shader, but both require
* specialized methods for setting transform data. NVPR also requires setting the
* projection matrix through a special function call.
*/
class GrGLPathProgram : public GrGLProgram {
protected:
typedef GrGLPathProgramDataManager::SeparableVaryingInfoArray SeparableVaryingInfoArray;
GrGLPathProgram(GrGLGpu*,
const GrProgramDesc&,
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
const SeparableVaryingInfoArray&,
GrGLInstalledGeoProc*,
GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors,
SkTArray<UniformHandle>* passSamplerUniforms);
private:
void didSetData() override;
virtual void setTransformData(const GrPrimitiveProcessor&,
const GrPendingFragmentStage&,
int index,
GrGLInstalledFragProc*) override;
virtual void onSetRenderTargetState(const GrPrimitiveProcessor&, const GrPipeline&);
friend class GrGLPathProgramBuilder;
GrGLPathProgramDataManager fPathProgramDataManager;
typedef GrGLProgram INHERITED;
};
#endif

View File

@ -0,0 +1,48 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "gl/GrGLPathProgramDataManager.h"
#include "gl/GrGLPathRendering.h"
#include "gl/GrGLUniformHandle.h"
#include "gl/GrGLGpu.h"
#include "SkMatrix.h"
GrGLPathProgramDataManager::GrGLPathProgramDataManager(
GrGLGpu* gpu, GrGLuint programID, const SeparableVaryingInfoArray& separableVaryings)
: fGpu(gpu)
, fProgramID(programID) {
int count = separableVaryings.count();
fSeparableVaryings.push_back_n(count);
for (int i = 0; i < count; i++) {
SeparableVarying& separableVarying = fSeparableVaryings[i];
const SeparableVaryingInfo& builderSeparableVarying = separableVaryings[i];
SkASSERT(GrGLShaderVar::kNonArray == builderSeparableVarying.fVariable.getArrayCount() ||
builderSeparableVarying.fVariable.getArrayCount() > 0);
SkDEBUGCODE(
separableVarying.fArrayCount = builderSeparableVarying.fVariable.getArrayCount();
separableVarying.fType = builderSeparableVarying.fVariable.getType();
);
separableVarying.fLocation = builderSeparableVarying.fLocation;
}
}
void GrGLPathProgramDataManager::setPathFragmentInputTransform(SeparableVaryingHandle u,
int components,
const SkMatrix& matrix) const {
const SeparableVarying& fragmentInput =
fSeparableVaryings[u.toProgramDataIndex()];
SkASSERT((components == 2 && fragmentInput.fType == kVec2f_GrSLType) ||
(components == 3 && fragmentInput.fType == kVec3f_GrSLType));
fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgramID,
fragmentInput.fLocation,
GR_GL_OBJECT_LINEAR,
components,
matrix);
}

View File

@ -0,0 +1,75 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrGLPathProgramDataManager_DEFINED
#define GrGLPathProgramDataManager_DEFINED
#include "gl/GrGLProgramDataManager.h"
class GrGLPathProgram;
class GrGLPathProgramBuilder;
/** Manages the resources used by a shader program for NVPR rendering.
*/
class GrGLPathProgramDataManager : SkNoncopyable {
public:
class SeparableVaryingHandle : public GrGLProgramDataManager::ShaderResourceHandle {
public:
/*
* Creates a reference to a separable varying of a GrGLShaderBuilder. The ref can be used
* to set the varying with the corresponding GrGLPathProgramDataManager.
*/
static SeparableVaryingHandle CreateFromSeparableVaryingIndex(int i) {
return GrGLPathProgramDataManager::SeparableVaryingHandle(i);
}
SeparableVaryingHandle() { }
bool operator==(const SeparableVaryingHandle& other) {
return other.fValue == fValue;
}
private:
SeparableVaryingHandle(int value) : ShaderResourceHandle(value) { }
int toProgramDataIndex() const { SkASSERT(isValid()); return fValue; }
int toShaderBuilderIndex() const { return toProgramDataIndex(); }
friend class GrGLPathProgramDataManager; // For accessing toProgramDataIndex().
friend class GrGLPathProcessor; // For accessing toShaderBuilderIndex().
};
struct SeparableVaryingInfo {
GrGLShaderVar fVariable;
GrGLint fLocation;
};
// This uses an allocator rather than array so that the GrGLShaderVars don't move in memory
// after they are inserted. Users of GrGLShaderBuilder get refs to the vars and ptrs to their
// name strings. Otherwise, we'd have to hand out copies.
typedef GrTAllocator<SeparableVaryingInfo> SeparableVaryingInfoArray;
GrGLPathProgramDataManager(GrGLGpu*, GrGLuint programID, const SeparableVaryingInfoArray&);
/** Functions for uploading the varying values.
*/
void setPathFragmentInputTransform(SeparableVaryingHandle u,
int components,
const SkMatrix& matrix) const;
private:
enum {
kUnusedSeparableVarying = -1,
};
struct SeparableVarying {
GrGLint fLocation;
SkDEBUGCODE(
GrSLType fType;
int fArrayCount;
);
};
SkTArray<SeparableVarying, true> fSeparableVaryings;
GrGLGpu* fGpu;
GrGLuint fProgramID;
typedef SkNoncopyable INHERITED;
};
#endif

View File

@ -10,6 +10,7 @@
#include "GrPrimitiveProcessor.h"
#include "GrGLProcessor.h"
#include "GrGLPathProgramDataManager.h"
class GrBatchTracker;
class GrPrimitiveProcessor;
@ -20,6 +21,7 @@ public:
virtual ~GrGLPrimitiveProcessor() {}
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
typedef GrGLPathProgramDataManager::SeparableVaryingHandle SeparableVaryingHandle;
typedef GrGLProcessor::TextureSamplerArray TextureSamplerArray;
typedef SkSTArray<2, const GrCoordTransform*, true> ProcCoords;
@ -85,6 +87,10 @@ protected:
SkASSERT(this->isValid());
return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
}
SeparableVaryingHandle convertToSeparableVaryingHandle() {
SkASSERT(this->isValid());
return SeparableVaryingHandle::CreateFromSeparableVaryingIndex(fHandle);
}
private:
int fHandle;

View File

@ -155,43 +155,3 @@ void GrGLProgram::onSetRenderTargetState(const GrPrimitiveProcessor&,
}
}
/////////////////////////////////////////////////////////////////////////////////////////
GrGLNvprProgram::GrGLNvprProgram(GrGLGpu* gpu,
const GrProgramDesc& desc,
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
GrGLInstalledGeoProc* primProc,
GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors,
SkTArray<UniformHandle>* passSamplerUniforms)
: INHERITED(gpu, desc, builtinUniforms, programID, uniforms, primProc,
xferProcessor, fragmentProcessors, passSamplerUniforms) {
}
void GrGLNvprProgram::didSetData() {
GrGLPathProcessor* pathProc =
static_cast<GrGLPathProcessor*>(fGeometryProcessor.get()->fGLProc.get());
pathProc->didSetData(fGpu->glPathRendering());
}
void GrGLNvprProgram::setTransformData(const GrPrimitiveProcessor& primProc,
const GrPendingFragmentStage& proc,
int index,
GrGLInstalledFragProc* ip) {
GrGLPathProcessor* pathProc =
static_cast<GrGLPathProcessor*>(fGeometryProcessor.get()->fGLProc.get());
pathProc->setTransformData(primProc, index, proc.processor()->coordTransforms(),
fGpu->glPathRendering(), fProgramID);
}
void GrGLNvprProgram::onSetRenderTargetState(const GrPrimitiveProcessor& primProc,
const GrPipeline& pipeline) {
SkASSERT(!primProc.willUseGeoShader() && primProc.numAttribs() == 0);
const GrRenderTarget* rt = pipeline.getRenderTarget();
SkISize size;
size.set(rt->width(), rt->height());
const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
fGpu->glPathRendering()->setProjectionMatrix(pathProc.viewMatrix(),
size, rt->origin());
}

View File

@ -152,36 +152,4 @@ protected:
typedef SkRefCnt INHERITED;
};
/*
* Below are slight specializations of the program object for the different types of programs
* The default GrGL programs consist of at the very least a vertex and fragment shader.
* Legacy Nvpr only has a fragment shader, 1.3+ Nvpr ignores the vertex shader, but both require
* specialized methods for setting transform data. Both types of NVPR also require setting the
* projection matrix through a special function call
*/
class GrGLNvprProgram : public GrGLProgram {
protected:
GrGLNvprProgram(GrGLGpu*,
const GrProgramDesc&,
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
GrGLInstalledGeoProc*,
GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors,
SkTArray<UniformHandle>* passSamplerUniforms);
private:
void didSetData() override;
virtual void setTransformData(const GrPrimitiveProcessor&,
const GrPendingFragmentStage&,
int index,
GrGLInstalledFragProc*) override;
virtual void onSetRenderTargetState(const GrPrimitiveProcessor&, const GrPipeline&);
friend class GrGLNvprProgramBuilder;
typedef GrGLProgram INHERITED;
};
#endif

View File

@ -5,7 +5,7 @@
* found in the LICENSE file.
*/
#include "gl/GrGLPathRendering.h"
#include "gl/GrGLProgramDataManager.h"
#include "gl/GrGLUniformHandle.h"
#include "gl/GrGLGpu.h"
#include "SkMatrix.h"

View File

@ -0,0 +1,50 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrGLPathProgramBuilder.h"
#include "gl/GrGLGpu.h"
#include "gl/GrGLPathProgram.h"
#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
GrGLPathProgramBuilder::GrGLPathProgramBuilder(GrGLGpu* gpu, const DrawArgs& args)
: INHERITED(gpu, args)
, fSeparableVaryingInfos(kVarsPerBlock) {
}
GrGLProgram* GrGLPathProgramBuilder::createProgram(GrGLuint programID) {
return SkNEW_ARGS(GrGLPathProgram, (fGpu, this->desc(), fUniformHandles, programID,
fUniforms,
fSeparableVaryingInfos,
fGeometryProcessor,
fXferProcessor, fFragmentProcessors.get(),
&fSamplerUniforms));
}
GrGLProgramBuilder::SeparableVaryingHandle GrGLPathProgramBuilder::addSeparableVarying(
const char* name, GrGLVertToFrag* v, GrSLPrecision fsPrecision) {
this->addVarying(name, v, fsPrecision);
SeparableVaryingInfo& varyingInfo = fSeparableVaryingInfos.push_back();
varyingInfo.fVariable = this->getFragmentShaderBuilder()->fInputs.back();
varyingInfo.fLocation = fSeparableVaryingInfos.count() - 1;
return SeparableVaryingHandle::CreateFromSeparableVaryingIndex(varyingInfo.fLocation);
}
void GrGLPathProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) {
this->INHERITED::resolveProgramResourceLocations(programID);
int count = fSeparableVaryingInfos.count();
for (int i = 0; i < count; ++i) {
GrGLint location;
GL_CALL_RET(location,
GetProgramResourceLocation(programID,
GR_GL_FRAGMENT_INPUT,
fSeparableVaryingInfos[i].fVariable.c_str()));
fSeparableVaryingInfos[i].fLocation = location;
}
}

View File

@ -0,0 +1,31 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrGLPathProgramBuilder_DEFINED
#define GrGLPathProgramBuilder_DEFINED
#include "GrGLProgramBuilder.h"
class GrGLPathProgramBuilder : public GrGLProgramBuilder {
public:
GrGLPathProgramBuilder(GrGLGpu* gpu, const DrawArgs& args);
GrGLProgram* createProgram(GrGLuint programID) override;
SeparableVaryingHandle addSeparableVarying(const char* name, GrGLVertToFrag* v,
GrSLPrecision fsPrecision) override;
void resolveProgramResourceLocations(GrGLuint programID) override;
private:
typedef GrGLPathProgramDataManager::SeparableVaryingInfo SeparableVaryingInfo;
typedef GrGLPathProgramDataManager::SeparableVaryingInfoArray SeparableVaryingInfoArray;
SeparableVaryingInfoArray fSeparableVaryingInfos;
typedef GrGLProgramBuilder INHERITED;
};
#endif

View File

@ -17,6 +17,7 @@
#include "glsl/GrGLSLCaps.h"
#include "GrAutoLocaleSetter.h"
#include "GrCoordTransform.h"
#include "GrGLPathProgramBuilder.h"
#include "GrGLProgramBuilder.h"
#include "GrTexture.h"
#include "SkRTConf.h"
@ -25,32 +26,6 @@
#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
///////////////////////////////////////////////////////////////////////////////////////////////////
class GrGLNvprProgramBuilder : public GrGLProgramBuilder {
public:
GrGLNvprProgramBuilder(GrGLGpu* gpu, const DrawArgs& args)
: INHERITED(gpu, args) {}
GrGLProgram* createProgram(GrGLuint programID) override {
// this is just for nvpr es, which has separable varyings that are plugged in after
// building
GrGLPathProcessor* pathProc =
static_cast<GrGLPathProcessor*>(fGeometryProcessor->fGLProc.get());
pathProc->resolveSeparableVaryings(fGpu, programID);
return SkNEW_ARGS(GrGLNvprProgram, (fGpu, this->desc(), fUniformHandles, programID,
fUniforms, fGeometryProcessor, fXferProcessor,
fFragmentProcessors.get(), &fSamplerUniforms));
}
private:
typedef GrGLProgramBuilder INHERITED;
};
//////////////////////////////////////////////////////////////////////////////
const int GrGLProgramBuilder::kVarsPerBlock = 8;
GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gpu) {
@ -80,7 +55,7 @@ GrGLProgramBuilder* GrGLProgramBuilder::CreateProgramBuilder(const DrawArgs& arg
SkASSERT(gpu->glCaps().shaderCaps()->pathRenderingSupport() &&
!args.fPrimitiveProcessor->willUseGeoShader() &&
args.fPrimitiveProcessor->numAttribs() == 0);
return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, args));
return SkNEW_ARGS(GrGLPathProgramBuilder, (gpu, args));
} else {
return SkNEW_ARGS(GrGLProgramBuilder, (gpu, args));
}
@ -126,6 +101,18 @@ void GrGLProgramBuilder::addPassThroughAttribute(const GrPrimitiveProcessor::Att
fFS.codeAppendf("%s = %s;", output, v.fsIn());
}
GrGLProgramBuilder::SeparableVaryingHandle GrGLProgramBuilder::addSeparableVarying(const char*,
GrGLVertToFrag*,
GrSLPrecision) {
// This call is not used for non-NVPR backends. However, the polymorphism between
// GrPrimitiveProcessor, GrGLPrimitiveProcessor and GrGLProgramBuilder does not allow for
// a system where GrGLPathProcessor would be able to refer to a primitive-specific builder
// that would understand separable varyings. Thus separable varyings need to be present
// early in the inheritance chain of builders.
SkASSERT(false);
return SeparableVaryingHandle();
}
void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) {
if ('\0' == prefix) {
*out = name;
@ -423,11 +410,8 @@ GrGLProgram* GrGLProgramBuilder::finalize() {
return NULL;
}
bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
if (usingBindUniform) {
this->bindUniformLocations(programID);
}
fFS.bindFragmentShaderLocations(programID);
this->bindProgramResourceLocations(programID);
GL_CALL(LinkProgram(programID));
// Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
@ -438,21 +422,24 @@ GrGLProgram* GrGLProgramBuilder::finalize() {
if (checkLinked) {
checkLinkStatus(programID);
}
if (!usingBindUniform) {
this->resolveUniformLocations(programID);
}
this->resolveProgramResourceLocations(programID);
this->cleanupShaders(shadersToDelete);
return this->createProgram(programID);
}
void GrGLProgramBuilder::bindUniformLocations(GrGLuint programID) {
int count = fUniforms.count();
for (int i = 0; i < count; ++i) {
GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str()));
fUniforms[i].fLocation = i;
void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
if (usingBindUniform) {
int count = fUniforms.count();
for (int i = 0; i < count; ++i) {
GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str()));
fUniforms[i].fLocation = i;
}
}
fFS.bindFragmentShaderLocations(programID);
}
bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
@ -479,12 +466,15 @@ bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
return SkToBool(linked);
}
void GrGLProgramBuilder::resolveUniformLocations(GrGLuint programID) {
int count = fUniforms.count();
for (int i = 0; i < count; ++i) {
GrGLint location;
GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
fUniforms[i].fLocation = location;
void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) {
bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
if (!usingBindUniform) {
int count = fUniforms.count();
for (int i = 0; i < count; ++i) {
GrGLint location;
GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
fUniforms[i].fLocation = location;
}
}
}

View File

@ -12,6 +12,7 @@
#include "GrGLGeometryShaderBuilder.h"
#include "GrGLVertexShaderBuilder.h"
#include "../GrGLProgramDataManager.h"
#include "../GrGLPathProgramDataManager.h"
#include "../GrGLUniformHandle.h"
#include "../GrGLPrimitiveProcessor.h"
#include "../GrGLXferProcessor.h"
@ -39,6 +40,7 @@ public:
virtual ~GrGLUniformBuilder() {}
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
typedef GrGLPathProgramDataManager::SeparableVaryingHandle SeparableVaryingHandle;
/** Add a uniform variable to the current program, that has visibility in one or more shaders.
visibility is a bitfield of ShaderVisibility values indicating from which shaders the
@ -154,6 +156,13 @@ public:
virtual void addPassThroughAttribute(const GrGeometryProcessor::Attribute*,
const char* output) = 0;
/*
* Creates a fragment shader varying that can be referred to.
* Comparable to GrGLUniformBuilder::addUniform().
*/
virtual SeparableVaryingHandle addSeparableVarying(
const char* name, GrGLVertToFrag*, GrSLPrecision fsPrecision = kDefault_GrSLPrecision) = 0;
// TODO rename getFragmentBuilder
virtual GrGLFragmentBuilder* getFragmentShaderBuilder() = 0;
virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
@ -252,6 +261,10 @@ public:
void addPassThroughAttribute(const GrPrimitiveProcessor::Attribute*,
const char* output) override;
SeparableVaryingHandle addSeparableVarying(
const char* name,
GrGLVertToFrag*,
GrSLPrecision fsPrecision = kDefault_GrSLPrecision) override;
// Handles for program uniforms (other than per-effect uniforms)
struct BuiltinUniformHandles {
@ -315,9 +328,9 @@ protected:
GrGLInstalledProc<Proc>*);
GrGLProgram* finalize();
void bindUniformLocations(GrGLuint programID);
void bindProgramResourceLocations(GrGLuint programID);
bool checkLinkStatus(GrGLuint programID);
void resolveUniformLocations(GrGLuint programID);
virtual void resolveProgramResourceLocations(GrGLuint programID);
void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);

View File

@ -203,5 +203,6 @@ protected:
bool fFinalized;
friend class GrGLProgramBuilder;
friend class GrGLPathProgramBuilder; // to access fInputs.
};
#endif