Calculate stage stats in GrOptDrawState

BUG=skia:
R=bsalomon@google.com

Author: egdaniel@google.com

Review URL: https://codereview.chromium.org/545693004
This commit is contained in:
egdaniel 2014-09-17 08:25:05 -07:00 committed by Commit bot
parent f96ba02513
commit a7dc0a83f0
5 changed files with 92 additions and 62 deletions

View File

@ -44,6 +44,7 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
this->copyEffectiveColorStages(drawState);
this->copyEffectiveCoverageStages(drawState);
this->adjustFromBlendOpts();
this->getStageStats();
};
void GrOptDrawState::adjustFromBlendOpts() {
@ -179,6 +180,41 @@ void GrOptDrawState::copyEffectiveCoverageStages(const GrDrawState& ds) {
}
}
static void get_stage_stats(const GrEffectStage& stage, bool* readsDst, bool* readsFragPosition) {
if (stage.getEffect()->willReadDstColor()) {
*readsDst = true;
}
if (stage.getEffect()->willReadFragmentPosition()) {
*readsFragPosition = true;
}
}
void GrOptDrawState::getStageStats() {
// We will need a local coord attrib if there is one currently set on the optState and we are
// actually generating some effect code
fRequiresLocalCoordAttrib = this->hasLocalCoordAttribute() && this->numTotalStages() > 0;
// if 1 == fVACount then that VA must be position, otherwise it contains some attribute which
// will require a vertexShader
fRequiresVertexShader = fVACount > 1;
fReadsDst = false;
fReadsFragPosition = false;
for (int s = 0; s < this->numColorStages(); ++s) {
const GrEffectStage& stage = this->getColorStage(s);
get_stage_stats(stage, &fReadsDst, &fReadsFragPosition);
}
for (int s = 0; s < this->numCoverageStages(); ++s) {
const GrEffectStage& stage = this->getCoverageStage(s);
get_stage_stats(stage, &fReadsDst, &fReadsFragPosition);
}
if (this->hasGeometryProcessor()) {
const GrEffectStage& stage = *this->getGeometryProcessor();
get_stage_stats(stage, &fReadsDst, &fReadsFragPosition);
SkASSERT(fRequiresVertexShader);
}
}
bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
return this->isEqual(that);
}

View File

@ -23,6 +23,11 @@ public:
bool inputColorIsUsed() const { return fInputColorIsUsed; }
bool inputCoverageIsUsed() const { return fInputCoverageIsUsed; }
bool readsDst() const { return fReadsDst; }
bool readsFragPosition() const { return fReadsFragPosition; }
bool requiresVertexShader() const { return fRequiresVertexShader; }
bool requiresLocalCoordAttrib() const { return fRequiresLocalCoordAttrib; }
private:
/**
* Constructs and optimized drawState out of a GrRODrawState.
@ -61,11 +66,23 @@ private:
*/
void adjustFromBlendOpts();
/**
* Loop over the effect stages to determine various info like what data they will read and what
* shaders they require.
*/
void getStageStats();
// These flags are needed to protect the code from creating an unused uniform color/coverage
// which will cause shader compiler errors.
bool fInputColorIsUsed;
bool fInputCoverageIsUsed;
// These flags give aggregated info on the effect stages that are used when building programs.
bool fReadsDst;
bool fReadsFragPosition;
bool fRequiresVertexShader;
bool fRequiresLocalCoordAttrib;
SkAutoSTArray<4, GrVertexAttrib> fOptVA;
BlendOptFlags fBlendOptFlags;

View File

@ -14,25 +14,11 @@
#include "SkChecksum.h"
bool GrGLProgramDesc::GetEffectKeyAndUpdateStats(const GrEffectStage& stage,
const GrGLCaps& caps,
bool useExplicitLocalCoords,
GrEffectKeyBuilder* b,
uint16_t* effectKeySize,
bool* setTrueIfReadsDst,
bool* setTrueIfReadsPos,
bool* setTrueIfRequiresVertexShader) {
bool GrGLProgramDesc::GetEffectKey(const GrEffectStage& stage, const GrGLCaps& caps,
bool useExplicitLocalCoords, GrEffectKeyBuilder* b,
uint16_t* effectKeySize) {
const GrBackendEffectFactory& factory = stage.getEffect()->getFactory();
const GrEffect& effect = *stage.getEffect();
if (effect.willReadDstColor()) {
*setTrueIfReadsDst = true;
}
if (effect.willReadFragmentPosition()) {
*setTrueIfReadsPos = true;
}
if (effect.requiresVertexShader()) {
*setTrueIfRequiresVertexShader = true;
}
factory.getGLEffectKey(effect, caps, b);
size_t size = b->size();
if (size > SK_MaxU16) {
@ -72,15 +58,7 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
bool requiresColorAttrib = optState.hasColorVertexAttribute();
bool requiresCoverageAttrib = optState.hasCoverageVertexAttribute();
// we only need the local coords if we're actually going to generate effect code
bool requiresLocalCoordAttrib = optState.numTotalStages() > 0 &&
optState.hasLocalCoordAttribute();
bool readsDst = false;
bool readFragPosition = false;
// Provide option for shader programs without vertex shader only when drawing paths.
bool requiresVertexShader = !GrGpu::IsPathRenderingDrawType(drawType);
bool requiresLocalCoordAttrib = optState.requiresLocalCoordAttrib();
int numStages = optState.numTotalStages();
@ -105,18 +83,14 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
GrEffectKeyBuilder b(&desc->fKey);
uint16_t effectKeySize;
uint32_t effectOffset = desc->fKey.count();
effectKeySuccess |= GetEffectKeyAndUpdateStats(
*optState.getGeometryProcessor(), gpu->glCaps(),
requiresLocalCoordAttrib, &b,
&effectKeySize, &readsDst,
&readFragPosition, &requiresVertexShader);
effectKeySuccess |= GetEffectKey(*optState.getGeometryProcessor(), gpu->glCaps(),
requiresLocalCoordAttrib, &b, &effectKeySize);
effectKeySuccess |= (effectOffset <= SK_MaxU16);
offsetAndSize[0] = SkToU16(effectOffset);
offsetAndSize[1] = effectKeySize;
++offsetAndSizeIndex;
*geometryProcessor = optState.getGeometryProcessor();
SkASSERT(requiresVertexShader);
header->fHasGeometryProcessor = true;
}
@ -125,21 +99,16 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
offsetAndSizeIndex * 2 * sizeof(uint16_t));
bool effectRequiresVertexShader = false;
GrEffectKeyBuilder b(&desc->fKey);
uint16_t effectKeySize;
uint32_t effectOffset = desc->fKey.count();
effectKeySuccess |= GetEffectKeyAndUpdateStats(
optState.getColorStage(s), gpu->glCaps(),
requiresLocalCoordAttrib, &b,
&effectKeySize, &readsDst,
&readFragPosition, &effectRequiresVertexShader);
effectKeySuccess |= GetEffectKey(optState.getColorStage(s), gpu->glCaps(),
requiresLocalCoordAttrib, &b, &effectKeySize);
effectKeySuccess |= (effectOffset <= SK_MaxU16);
offsetAndSize[0] = SkToU16(effectOffset);
offsetAndSize[1] = effectKeySize;
++offsetAndSizeIndex;
SkASSERT(!effectRequiresVertexShader);
}
for (int s = 0; s < optState.numCoverageStages(); ++s) {
@ -147,21 +116,16 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
offsetAndSizeIndex * 2 * sizeof(uint16_t));
bool effectRequiresVertexShader = false;
GrEffectKeyBuilder b(&desc->fKey);
uint16_t effectKeySize;
uint32_t effectOffset = desc->fKey.count();
effectKeySuccess |= GetEffectKeyAndUpdateStats(
optState.getCoverageStage(s), gpu->glCaps(),
requiresLocalCoordAttrib, &b,
&effectKeySize, &readsDst,
&readFragPosition, &effectRequiresVertexShader);
effectKeySuccess |= GetEffectKey(optState.getCoverageStage(s), gpu->glCaps(),
requiresLocalCoordAttrib, &b, &effectKeySize);
effectKeySuccess |= (effectOffset <= SK_MaxU16);
offsetAndSize[0] = SkToU16(effectOffset);
offsetAndSize[1] = effectKeySize;
++offsetAndSizeIndex;
SkASSERT(!effectRequiresVertexShader);
}
if (!effectKeySuccess) {
@ -172,7 +136,12 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
// Because header is a pointer into the dynamic array, we can't push any new data into the key
// below here.
header->fRequiresVertexShader = requiresVertexShader || requiresLocalCoordAttrib;
// We will only require a vertex shader if we have more than just the position VA attrib.
// If we have a geom processor we must us a vertex shader and we should not have a geometry
// processor if we are doing path rendering.
SkASSERT(!GrGpu::IsPathRenderingDrawType(drawType) || !optState.requiresVertexShader());
header->fRequiresVertexShader = optState.requiresVertexShader() ||
!GrGpu::IsPathRenderingDrawType(drawType);
header->fEmitsPointSize = GrGpu::kDrawPoints_DrawType == drawType;
// Currently the experimental GS will only work with triangle prims (and it doesn't do anything
@ -206,7 +175,7 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
header->fRequiresVertexShader = true;
}
if (readsDst) {
if (optState.readsDst()) {
SkASSERT(dstCopy || gpu->caps()->dstReadInShaderSupport());
const GrTexture* dstCopyTexture = NULL;
if (dstCopy) {
@ -219,7 +188,7 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
header->fDstReadKey = 0;
}
if (readFragPosition) {
if (optState.readsFragPosition()) {
header->fFragPosKey = GrGLFragmentShaderBuilder::KeyForFragmentPosition(
optState.getRenderTarget(), gpu->glCaps());
} else {
@ -277,7 +246,7 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
header->fCoverageOutput = kSecondaryCoverageISC_CoverageOutput;
separateCoverageFromColor = true;
}
} else if (readsDst &&
} else if (optState.readsDst() &&
kOne_GrBlendCoeff == srcCoeff &&
kZero_GrBlendCoeff == dstCoeff) {
header->fCoverageOutput = kCombineWithDst_CoverageOutput;

View File

@ -201,14 +201,9 @@ private:
KeyHeader* header() { return this->atOffset<KeyHeader, kHeaderOffset>(); }
// Shared code between setRandom() and Build().
static bool GetEffectKeyAndUpdateStats(const GrEffectStage& stage,
const GrGLCaps& caps,
bool useExplicitLocalCoords,
GrEffectKeyBuilder* b,
uint16_t* effectKeySize,
bool* setTrueIfReadsDst,
bool* setTrueIfReadsPos,
bool* setTrueIfRequiresVertexShader);
static bool GetEffectKey(const GrEffectStage& stage, const GrGLCaps& caps,
bool useExplicitLocalCoords, GrEffectKeyBuilder* b,
uint16_t* effectKeySize);
void finalize();

View File

@ -21,6 +21,19 @@
#include "SkRandom.h"
#include "Test.h"
static void get_stage_stats(const GrEffectStage stage, bool* readsDst,
bool* readsFragPosition, bool* requiresVertexShader) {
if (stage.getEffect()->willReadDstColor()) {
*readsDst = true;
}
if (stage.getEffect()->willReadFragmentPosition()) {
*readsFragPosition = true;
}
if (stage.getEffect()->requiresVertexShader()) {
*requiresVertexShader = true;
}
}
bool GrGLProgramDesc::setRandom(SkRandom* random,
const GrGpuGL* gpu,
const GrRenderTarget* dstRenderTarget,
@ -57,11 +70,11 @@ bool GrGLProgramDesc::setRandom(SkRandom* random,
}
GrEffectKeyBuilder b(&fKey);
uint16_t effectKeySize;
if (!GetEffectKeyAndUpdateStats(*stage, gpu->glCaps(), useLocalCoords, &b,
&effectKeySize, &dstRead, &fragPos, &vertexShader)) {
if (!GetEffectKey(*stage, gpu->glCaps(), useLocalCoords, &b, &effectKeySize)) {
fKey.reset();
return false;
}
get_stage_stats(*stage, &dstRead, &fragPos, &vertexShader);
offsetAndSize[0] = effectKeyOffset;
offsetAndSize[1] = effectKeySize;
offset++;
@ -79,11 +92,11 @@ bool GrGLProgramDesc::setRandom(SkRandom* random,
}
GrEffectKeyBuilder b(&fKey);
uint16_t effectKeySize;
if (!GetEffectKeyAndUpdateStats(*stage, gpu->glCaps(), useLocalCoords, &b,
&effectKeySize, &dstRead, &fragPos, &vertexShader)) {
if (!GetEffectKey(*stages[s], gpu->glCaps(), useLocalCoords, &b, &effectKeySize)) {
fKey.reset();
return false;
}
get_stage_stats(*stage, &dstRead, &fragPos, &vertexShader);
offsetAndSize[0] = effectKeyOffset;
offsetAndSize[1] = effectKeySize;
}