aboutsummaryrefslogtreecommitdiffhomepage
path: root/gpu/src/GrGpuGLShaders2.cpp
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-04-19 21:15:09 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-04-19 21:15:09 +0000
commit4be283f3a82895530d1b70372cd48ddb1c663fd8 (patch)
tree6b439eed9d51302125f5448683b6984b7f113f0a /gpu/src/GrGpuGLShaders2.cpp
parentc733996e84cbac28492e133e00c573740a8708c4 (diff)
Adds a build flag for GL to never use vertex attributes that don't have per-vertex values.
Also promotes the ATTRIBUTE_MATRIX flag that was local to cpp files to the public config file. Review URL: http://codereview.appspot.com/4434057/ git-svn-id: http://skia.googlecode.com/svn/trunk@1155 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'gpu/src/GrGpuGLShaders2.cpp')
-rw-r--r--gpu/src/GrGpuGLShaders2.cpp258
1 files changed, 158 insertions, 100 deletions
diff --git a/gpu/src/GrGpuGLShaders2.cpp b/gpu/src/GrGpuGLShaders2.cpp
index 4deecd4279..94b941fc09 100644
--- a/gpu/src/GrGpuGLShaders2.cpp
+++ b/gpu/src/GrGpuGLShaders2.cpp
@@ -22,20 +22,17 @@
#include "GrMemory.h"
#include "GrStringBuilder.h"
-
-#define ATTRIBUTE_MATRIX 0
-
#define PRINT_SHADERS 0
-#define SKIP_CACHE_CHECK true
+#define SKIP_CACHE_CHECK true
#define POS_ATTR_LOCATION 0
#define TEX_ATTR_LOCATION(X) (1 + X)
#define COL_ATTR_LOCATION (2 + GrDrawTarget::kMaxTexCoords)
-#if ATTRIBUTE_MATRIX
-#define VIEWMAT_ATTR_LOCATION (3 + GrDrawTarget::kMaxTexCoords)
-#define TEXMAT_ATTR_LOCATION(X) (6 + GrDrawTarget::kMaxTexCoords + 3 * (X))
-#define BOGUS_MATRIX_UNI_LOCATION 1000
+#if GR_GL_ATTRIBUTE_MATRICES
+ #define VIEWMAT_ATTR_LOCATION (3 + GrDrawTarget::kMaxTexCoords)
+ #define TEXMAT_ATTR_LOCATION(X) (6 + GrDrawTarget::kMaxTexCoords + 3 * (X))
+ #define BOGUS_MATRIX_UNI_LOCATION 1000
#endif
#define GR_UINT32_MAX static_cast<uint32_t>(-1)
@@ -68,6 +65,7 @@ struct GrGpuGLShaders2::StageUniLocations {
struct GrGpuGLShaders2::UniLocations {
GrGLint fViewMatrixUni;
+ GrGLint fColorUni;
StageUniLocations fStages[kNumStages];
};
@@ -90,6 +88,7 @@ struct GrGpuGLShaders2::Program {
// these reflect the current values of uniforms
// (GL uniform values travel with program)
GrMatrix fViewMatrix;
+ GrColor fColor;
GrMatrix fTextureMatrices[kNumStages];
GrScalar fRadial2CenterX1[kNumStages];
GrScalar fRadial2Radius0[kNumStages];
@@ -122,24 +121,23 @@ struct GrGpuGLShaders2::StageDesc {
// must be tightly packed
struct GrGpuGLShaders2::ProgramDesc {
- GrVertexLayout fVertexLayout;
- GR_STATIC_ASSERT(2 == sizeof(GrVertexLayout)); // pack with next field
+ ProgramDesc() {
+ // since we use this as a key we can't have any unitialized padding
+ memset(this, 0, sizeof(ProgramDesc));
+ }
+ GrVertexLayout fVertexLayout; // stripped of bits that don't affect
+ // program generation.
enum {
- kNotPoints_OptFlagBit = 0x1,
- kVertexColorAllOnes_OptFlagBit = 0x2,
- };
- // we're assuming optflags and layout pack into 32 bits
- // VS 2010 seems to require short rather than just unsigned
- // for this to pack
- unsigned short fOptFlags : 16;
+ kNone_ColorType = 0,
+ kAttribute_ColorType = 1,
+ kUniform_ColorType = 2,
+ } fColorType;
+ bool fEmitsPointSize;
StageDesc fStages[kNumStages];
bool operator == (const ProgramDesc& desc) const {
- // keep 4-byte aligned and tightly packed
- GR_STATIC_ASSERT(4 == sizeof(StageDesc));
- GR_STATIC_ASSERT(2 + 2 + 4 * kNumStages == sizeof(ProgramDesc));
return 0 == memcmp(this, &desc, sizeof(ProgramDesc));
}
};
@@ -239,21 +237,29 @@ public:
GrGpuGLShaders2::ProgramCache::HashKey::HashKey() {
}
-static uint32_t ror(uint32_t x) {
+static inline uint32_t ror(uint32_t x) {
return (x >> 8) | (x << 24);
}
-static uint32_t rol(uint32_t x) {
+static inline uint32_t rol(uint32_t x) {
return (x << 8) | (x >> 24);
}
+static inline uint32_t roh(uint32_t x) {
+ return (x << 16) | (x >> 16);
+}
+
+static inline uint32_t swapouter(uint32_t x) {
+ return (x & 0x00ff00) | (x << 24) | (x >> 24);
+}
+
GrGpuGLShaders2::ProgramCache::HashKey::HashKey(const ProgramDesc& desc) {
fDesc = desc;
// if you change the size of the desc, need to update the hash function
- GR_STATIC_ASSERT(12 == sizeof(ProgramDesc));
+ GR_STATIC_ASSERT(20 == sizeof(ProgramDesc));
uint32_t* d = GrTCast<uint32_t*>(&fDesc);
- fHash = d[0] ^ ror(d[1]) ^ rol(d[2]);
+ fHash = d[0] ^ ror(d[1]) ^ rol(d[2]) ^ roh(d[3]) ^ swapouter(d[4]);
}
bool GrGpuGLShaders2::ProgramCache::HashKey::EQ(const Entry& entry,
@@ -289,7 +295,7 @@ struct GrGpuGLShaders2::ShaderCodeSegments {
// for variable names etc
typedef GrSStringBuilder<16> GrTokenString;
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
#define VIEW_MATRIX_NAME "aViewM"
#else
#define VIEW_MATRIX_NAME "uViewM"
@@ -297,6 +303,7 @@ typedef GrSStringBuilder<16> GrTokenString;
#define POS_ATTR_NAME "aPosition"
#define COL_ATTR_NAME "aColor"
+#define COL_UNI_NAME "uColor"
static inline void tex_attr_name(int coordIdx, GrStringBuilder* s) {
*s = "aTexCoord";
@@ -328,7 +335,7 @@ static inline const char* vector_all_coords(int count) {
}
static void tex_matrix_name(int stage, GrStringBuilder* s) {
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
*s = "aTexM";
#else
*s = "uTexM";
@@ -359,12 +366,7 @@ static void radial2_varying_name(int stage, GrStringBuilder* s) {
#include "GrRandom.h"
void GrGpuGLShaders2::ProgramUnitTest() {
- static const int PROG_OPTS[] = {
- 0,
- ProgramDesc::kNotPoints_OptFlagBit,
- ProgramDesc::kVertexColorAllOnes_OptFlagBit,
- ProgramDesc::kNotPoints_OptFlagBit | ProgramDesc::kVertexColorAllOnes_OptFlagBit
- };
+
static const int STAGE_OPTS[] = {
0,
StageDesc::kNoPerspective_OptFlagBit,
@@ -391,6 +393,15 @@ void GrGpuGLShaders2::ProgramUnitTest() {
for (int t = 0; t < NUM_TESTS; ++t) {
pdesc.fVertexLayout = 0;
+ pdesc.fEmitsPointSize = random.nextF() > .5f;
+ float colorType = random.nextF();
+ if (colorType < 1.f / 3.f) {
+ pdesc.fColorType = ProgramDesc::kAttribute_ColorType;
+ } else if (colorType < 2.f / 3.f) {
+ pdesc.fColorType = ProgramDesc::kUniform_ColorType;
+ } else {
+ pdesc.fColorType = ProgramDesc::kNone_ColorType;
+ }
for (int s = 0; s < kNumStages; ++s) {
// enable the stage?
if (random.nextF() > .5f) {
@@ -408,9 +419,8 @@ void GrGpuGLShaders2::ProgramUnitTest() {
}
}
- int x = (int)(random.nextF() * GR_ARRAY_COUNT(PROG_OPTS));
- pdesc.fOptFlags = PROG_OPTS[x];
for (int s = 0; s < kNumStages; ++s) {
+ int x;
pdesc.fStages[s].fEnabled = VertexUsesStage(s, pdesc.fVertexLayout);
x = (int)(random.nextF() * GR_ARRAY_COUNT(STAGE_OPTS));
pdesc.fStages[s].fOptFlags = STAGE_OPTS[x];
@@ -452,7 +462,7 @@ void GrGpuGLShaders2::GenStageCode(int stageNum,
if (desc.fOptFlags & StageDesc::kIdentityMatrix_OptFlagBit) {
varyingDims = coordDims;
} else {
- #if ATTRIBUTE_MATRIX
+ #if GR_GL_ATTRIBUTE_MATRICES
segments->fVSAttrs += "attribute mat3 ";
segments->fVSAttrs += texMName;
segments->fVSAttrs += ";\n";
@@ -691,34 +701,40 @@ void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc,
memset(&program->fUniLocations, 0, sizeof(UniLocations));
- bool haveColor = !(ProgramDesc::kVertexColorAllOnes_OptFlagBit &
- desc.fOptFlags);
-
-#if ATTRIBUTE_MATRIX
- segments.fVSAttrs = "attribute mat3 " VIEW_MATRIX_NAME ";\n";
+#if GR_GL_ATTRIBUTE_MATRICES
+ segments.fVSAttrs += "attribute mat3 " VIEW_MATRIX_NAME ";\n";
#else
- segments.fVSUnis = "uniform mat3 " VIEW_MATRIX_NAME ";\n";
- segments.fVSAttrs = "";
+ segments.fVSUnis += "uniform mat3 " VIEW_MATRIX_NAME ";\n";
#endif
segments.fVSAttrs += "attribute vec2 " POS_ATTR_NAME ";\n";
- if (haveColor) {
- segments.fVSAttrs += "attribute vec4 " COL_ATTR_NAME ";\n";
- segments.fVaryings = "varying vec4 vColor;\n";
- } else {
- segments.fVaryings = "";
- }
- segments.fVSCode = "void main() {\n"
- "\tvec3 pos3 = " VIEW_MATRIX_NAME " * vec3(" POS_ATTR_NAME ", 1);\n"
- "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n";
- if (haveColor) {
+ segments.fVSCode += "void main() {\n"
+ "\tvec3 pos3 = " VIEW_MATRIX_NAME " * vec3(" POS_ATTR_NAME ", 1);\n"
+ "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n";
+
+ // incoming color to current stage being processed.
+ GrTokenString inColor;
+
+ switch (desc.fColorType) {
+ case ProgramDesc::kAttribute_ColorType:
+ segments.fVSAttrs += "attribute vec4 " COL_ATTR_NAME ";\n";
+ segments.fVaryings += "varying vec4 vColor;\n";
segments.fVSCode += "\tvColor = " COL_ATTR_NAME ";\n";
+ inColor = "vColor";
+ break;
+ case ProgramDesc::kUniform_ColorType:
+ segments.fFSUnis += "uniform vec4 " COL_UNI_NAME ";\n";
+ inColor = COL_UNI_NAME;
+ break;
+ case ProgramDesc::kNone_ColorType:
+ inColor = "";
+ break;
}
- if (!(desc.fOptFlags & ProgramDesc::kNotPoints_OptFlagBit)){
+ if (desc.fEmitsPointSize){
segments.fVSCode += "\tgl_PointSize = 1.0;\n";
}
- segments.fFSCode = "void main() {\n";
+ segments.fFSCode += "void main() {\n";
// add texture coordinates that are used to the list of vertex attr decls
GrTokenString texCoordAttrs[kMaxTexCoords];
@@ -752,8 +768,6 @@ void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc,
}
}
- GrTokenString inColor = "vColor";
-
// if we have active stages string them together, feeding the output color
// of each to the next and generating code for each stage.
if (numActiveStages) {
@@ -772,19 +786,18 @@ void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc,
}
GenStageCode(s,
desc.fStages[s],
- haveColor ? inColor.cstr() : NULL,
+ inColor.length() ? inColor.cstr() : NULL,
outColor.cstr(),
stageInCoords[s],
&segments,
&program->fUniLocations.fStages[s]);
++currActiveStage;
inColor = outColor;
- haveColor = true;
}
}
} else {
segments.fFSCode += "\tgl_FragColor = ";
- if (haveColor) {
+ if (inColor.length()) {
segments.fFSCode += inColor;
} else {
segments.fFSCode += "vec4(1,1,1,1)";
@@ -883,7 +896,7 @@ void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc,
}
}
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
// set unis to a bogus value so that checks against -1 before
// flushing will pass.
GR_GL(BindAttribLocation(progID,
@@ -929,15 +942,23 @@ void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc,
}
// Get uniform locations
-#if !ATTRIBUTE_MATRIX
+#if !GR_GL_ATTRIBUTE_MATRICES
program->fUniLocations.fViewMatrixUni =
GR_GL(GetUniformLocation(progID, VIEW_MATRIX_NAME));
GrAssert(-1 != program->fUniLocations.fViewMatrixUni);
#endif
+ if (ProgramDesc::kUniform_ColorType == desc.fColorType) {
+ program->fUniLocations.fColorUni =
+ GR_GL(GetUniformLocation(progID, COL_UNI_NAME));
+ GrAssert(-1 != program->fUniLocations.fColorUni);
+ } else {
+ program->fUniLocations.fColorUni = -1;
+ }
+
for (int s = 0; s < kNumStages; ++s) {
StageUniLocations& locations = program->fUniLocations.fStages[s];
if (desc.fStages[s].fEnabled) {
-#if !ATTRIBUTE_MATRIX
+#if !GR_GL_ATTRIBUTE_MATRICES
if (locations.fTextureMatrixUni) {
GrTokenString texMName;
tex_matrix_name(s, &texMName);
@@ -988,6 +1009,7 @@ void GrGpuGLShaders2::GenProgram(const ProgramDesc& desc,
program->fTextureMatrices[s] = GrMatrix::InvalidMatrix();
program->fRadial2CenterX1[s] = GR_ScalarMax;
program->fRadial2Radius0[s] = -GR_ScalarMax;
+ program->fColor = GrColor_ILLEGAL;
}
program->fViewMatrix = GrMatrix::InvalidMatrix();
}
@@ -997,16 +1019,27 @@ void GrGpuGLShaders2::getProgramDesc(GrPrimitiveType primType, ProgramDesc* desc
// Must initialize all fields or cache will have false negatives!
desc->fVertexLayout = fGeometrySrc.fVertexLayout;
- desc->fOptFlags = 0;
- if (kPoints_PrimitiveType != primType) {
- desc->fOptFlags |= ProgramDesc::kNotPoints_OptFlagBit;
- }
+ desc->fEmitsPointSize = kPoints_PrimitiveType == primType;
+
+ bool requiresAttributeColors = desc->fVertexLayout & kColor_VertexLayoutBit;
+ // fColorType records how colors are specified for the program. Strip
+ // the bit from the layout to avoid false negatives when searching for an
+ // existing program in the cache.
+ desc->fVertexLayout &= ~(kColor_VertexLayoutBit);
+
#if GR_AGGRESSIVE_SHADER_OPTS
- if (!(desc->fVertexLayout & kColor_VertexLayoutBit) &&
- (0xffffffff == fCurrDrawState.fColor)) {
- desc->fOptFlags |= ProgramDesc::kVertexColorAllOnes_OptFlagBit;
- }
+ if (!requiresAttributeColors && (0xffffffff == fCurrDrawState.fColor)) {
+ desc->fColorType = ProgramDesc::kNone_ColorType;
+ } else
#endif
+#if GR_GL_NO_CONSTANT_ATTRIBUTES
+ if (!requiresAttributeColors) {
+ desc->fColorType = ProgramDesc::kUniform_ColorType;
+ } else
+#endif
+ {
+ desc->fColorType = ProgramDesc::kAttribute_ColorType;
+ }
for (int s = 0; s < kNumStages; ++s) {
StageDesc& stage = desc->fStages[s];
@@ -1114,7 +1147,7 @@ GrGpuGLShaders2::~GrGpuGLShaders2() {
}
const GrMatrix& GrGpuGLShaders2::getHWSamplerMatrix(int stage) {
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
return fHWDrawState.fSamplerStates[stage].getMatrix();
#else
return fProgram->fTextureMatrices[stage];
@@ -1122,7 +1155,7 @@ const GrMatrix& GrGpuGLShaders2::getHWSamplerMatrix(int stage) {
}
void GrGpuGLShaders2::recordHWSamplerMatrix(int stage, const GrMatrix& matrix){
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
fHWDrawState.fSamplerStates[stage].setMatrix(matrix);
#else
fProgram->fTextureMatrices[stage] = matrix;
@@ -1165,7 +1198,7 @@ void GrGpuGLShaders2::flushViewMatrix() {
m[GrMatrix::kTransY],
m[GrMatrix::kPersp2]
};
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+0, mt+0));
GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+1, mt+3));
GR_GL(VertexAttrib4fv(VIEWMAT_ATTR_LOCATION+2, mt+6));
@@ -1197,7 +1230,7 @@ void GrGpuGLShaders2::flushTextureMatrix(int stage) {
m[GrMatrix::kTransY],
m[GrMatrix::kPersp2]
};
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+0, mt+0));
GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+1, mt+3));
GR_GL(VertexAttrib4fv(TEXMAT_ATTR_LOCATION(0)+2, mt+6));
@@ -1229,10 +1262,9 @@ void GrGpuGLShaders2::flushRadial2(int stage) {
unis));
}
-void GrGpuGLShaders2::flushProgram(GrPrimitiveType type) {
- ProgramDesc desc;
- getProgramDesc(type, &desc);
- fProgram = fProgramCache->getProgram(desc);
+void GrGpuGLShaders2::flushProgram(GrPrimitiveType type, ProgramDesc* desc) {
+ getProgramDesc(type, desc);
+ fProgram = fProgramCache->getProgram(*desc);
if (fHWProgramID != fProgram->fProgramID) {
GR_GL(UseProgram(fProgram->fProgramID));
@@ -1243,6 +1275,49 @@ void GrGpuGLShaders2::flushProgram(GrPrimitiveType type) {
}
}
+void GrGpuGLShaders2::flushColor(const ProgramDesc& desc) {
+ if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
+ // color will be specified per-vertex as an attribute
+ // invalidate the const vertex attrib color
+ fHWDrawState.fColor = GrColor_ILLEGAL;
+ } else {
+ switch (desc.fColorType) {
+ case ProgramDesc::kAttribute_ColorType:
+ if (fHWDrawState.fColor != fCurrDrawState.fColor) {
+ // OpenGL ES only supports the float varities of glVertexAttrib
+ float c[] = {
+ GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
+ GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
+ GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
+ GrColorUnpackA(fCurrDrawState.fColor) / 255.f
+ };
+ GR_GL(VertexAttrib4fv(COL_ATTR_LOCATION, c));
+ fHWDrawState.fColor = fCurrDrawState.fColor;
+ }
+ break;
+ case ProgramDesc::kUniform_ColorType:
+ if (fProgram->fColor != fCurrDrawState.fColor) {
+ // OpenGL ES only supports the float varities of glVertexAttrib
+ float c[] = {
+ GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
+ GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
+ GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
+ GrColorUnpackA(fCurrDrawState.fColor) / 255.f
+ };
+ GrAssert(-1 != fProgram->fUniLocations.fColorUni);
+ GR_GL(Uniform4fv(fProgram->fUniLocations.fColorUni, 1, c));
+ fProgram->fColor = fCurrDrawState.fColor;
+ }
+ break;
+ case ProgramDesc::kNone_ColorType:
+ GrAssert(0xffffffff == fCurrDrawState.fColor);
+ break;
+ default:
+ GrCrash("Unknown color type.");
+ }
+ }
+}
+
bool GrGpuGLShaders2::flushGraphicsState(GrPrimitiveType type) {
if (!flushGLStateCommon(type)) {
@@ -1252,7 +1327,7 @@ bool GrGpuGLShaders2::flushGraphicsState(GrPrimitiveType type) {
if (fDirtyFlags.fRenderTargetChanged) {
// our coords are in pixel space and the GL matrices map to NDC
// so if the viewport changed, our matrix is now wrong.
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
#else
// we assume all shader matrices may be wrong after viewport changes
@@ -1260,29 +1335,12 @@ bool GrGpuGLShaders2::flushGraphicsState(GrPrimitiveType type) {
#endif
}
- flushProgram(type);
+ ProgramDesc desc;
+ flushProgram(type, &desc);
- if (fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) {
- // invalidate the immediate mode color
- fHWDrawState.fColor = GrColor_ILLEGAL;
- } else {
- if (fHWDrawState.fColor != fCurrDrawState.fColor &&
- (!GR_AGGRESSIVE_SHADER_OPTS || 0xffffffff != fCurrDrawState.fColor)) {
- // avoid pushing the color attrib if the shader will optimize it out
-
- // OpenGL ES only supports the float varities of glVertexAttrib
- float c[] = {
- GrColorUnpackR(fCurrDrawState.fColor) / 255.f,
- GrColorUnpackG(fCurrDrawState.fColor) / 255.f,
- GrColorUnpackB(fCurrDrawState.fColor) / 255.f,
- GrColorUnpackA(fCurrDrawState.fColor) / 255.f
- };
- GR_GL(VertexAttrib4fv(COL_ATTR_LOCATION, c));
- fHWDrawState.fColor = fCurrDrawState.fColor;
- }
- }
+ flushColor(desc);
-#if ATTRIBUTE_MATRIX
+#if GR_GL_ATTRIBUTE_MATRICES
GrMatrix& currViewMatrix = fHWDrawState.fViewMatrix;
#else
GrMatrix& currViewMatrix = fProgram->fViewMatrix;