Replace fWillReadFragmentPosition with a bitfield
Replaces fWillReadFragmentPosition on GrProcessor with a "RequiredFeatures" bitfield. This will allow us to add additional built-in features. Completely removes information about reading the fragment position from GrPipeline and GrProcOptInfo. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1734163002 Review URL: https://codereview.chromium.org/1734163002
This commit is contained in:
parent
e5824b90da
commit
87332103c6
@ -79,8 +79,17 @@ public:
|
||||
/** Shortcut for textureAccess(index).texture(); */
|
||||
GrTexture* texture(int index) const { return this->textureAccess(index).getTexture(); }
|
||||
|
||||
/** Will this processor read the fragment position? */
|
||||
bool willReadFragmentPosition() const { return fWillReadFragmentPosition; }
|
||||
/**
|
||||
* Platform specific built-in features that a processor can request for the fragment shader.
|
||||
*/
|
||||
enum RequiredFeatures {
|
||||
kNone_RequiredFeatures = 0,
|
||||
kFragmentPosition_RequiredFeature = 1
|
||||
};
|
||||
|
||||
GR_DECL_BITFIELD_OPS_FRIENDS(RequiredFeatures);
|
||||
|
||||
RequiredFeatures requiredFeatures() const { return fRequiredFeatures; }
|
||||
|
||||
void* operator new(size_t size);
|
||||
void operator delete(void* target);
|
||||
@ -100,7 +109,7 @@ public:
|
||||
uint32_t classID() const { SkASSERT(kIllegalProcessorClassID != fClassID); return fClassID; }
|
||||
|
||||
protected:
|
||||
GrProcessor() : fClassID(kIllegalProcessorClassID), fWillReadFragmentPosition(false) {}
|
||||
GrProcessor() : fClassID(kIllegalProcessorClassID), fRequiredFeatures(kNone_RequiredFeatures) {}
|
||||
|
||||
/**
|
||||
* Subclasses call this from their constructor to register GrTextureAccesses. The processor
|
||||
@ -117,7 +126,11 @@ protected:
|
||||
* position in the FS then it must call this method from its constructor. Otherwise, the
|
||||
* request to access the fragment position will be denied.
|
||||
*/
|
||||
void setWillReadFragmentPosition() { fWillReadFragmentPosition = true; }
|
||||
void setWillReadFragmentPosition() { fRequiredFeatures |= kFragmentPosition_RequiredFeature; }
|
||||
|
||||
void combineRequiredFeatures(const GrProcessor& other) {
|
||||
fRequiredFeatures |= other.fRequiredFeatures;
|
||||
}
|
||||
|
||||
template <typename PROC_SUBCLASS> void initClassID() {
|
||||
static uint32_t kClassID = GenClassID();
|
||||
@ -145,9 +158,11 @@ private:
|
||||
};
|
||||
static int32_t gCurrProcessorClassID;
|
||||
|
||||
bool fWillReadFragmentPosition;
|
||||
RequiredFeatures fRequiredFeatures;
|
||||
|
||||
typedef GrProgramElement INHERITED;
|
||||
};
|
||||
|
||||
GR_MAKE_BITFIELD_OPS(GrProcessor::RequiredFeatures);
|
||||
|
||||
#endif
|
||||
|
@ -96,9 +96,7 @@ int GrFragmentProcessor::registerChildProcessor(const GrFragmentProcessor* child
|
||||
int index = fChildProcessors.count();
|
||||
fChildProcessors.push_back(SkRef(child));
|
||||
|
||||
if (child->willReadFragmentPosition()) {
|
||||
this->setWillReadFragmentPosition();
|
||||
}
|
||||
this->combineRequiredFeatures(*child);
|
||||
|
||||
if (child->usesLocalCoords()) {
|
||||
fUsesLocalCoords = true;
|
||||
|
@ -184,23 +184,14 @@ void GrPipeline::adjustProgramFromOptimizations(const GrPipelineBuilder& pipelin
|
||||
int* firstColorProcessorIdx,
|
||||
int* firstCoverageProcessorIdx) {
|
||||
fIgnoresCoverage = SkToBool(flags & GrXferProcessor::kIgnoreCoverage_OptFlag);
|
||||
fReadsFragPosition = this->getXferProcessor().willReadFragmentPosition();
|
||||
|
||||
if ((flags & GrXferProcessor::kIgnoreColor_OptFlag) ||
|
||||
(flags & GrXferProcessor::kOverrideColor_OptFlag)) {
|
||||
*firstColorProcessorIdx = pipelineBuilder.numColorFragmentProcessors();
|
||||
} else {
|
||||
if (colorPOI.readsFragPosition()) {
|
||||
fReadsFragPosition = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & GrXferProcessor::kIgnoreCoverage_OptFlag) {
|
||||
*firstCoverageProcessorIdx = pipelineBuilder.numCoverageFragmentProcessors();
|
||||
} else {
|
||||
if (coveragePOI.readsFragPosition()) {
|
||||
fReadsFragPosition = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,7 +160,6 @@ public:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool readsFragPosition() const { return fReadsFragPosition; }
|
||||
bool ignoresCoverage() const { return fIgnoresCoverage; }
|
||||
|
||||
private:
|
||||
@ -200,7 +199,6 @@ private:
|
||||
uint32_t fFlags;
|
||||
ProgramXferProcessor fXferProcessor;
|
||||
FragmentProcessorArray fFragmentProcessors;
|
||||
bool fReadsFragPosition;
|
||||
bool fIgnoresCoverage;
|
||||
|
||||
// This value is also the index in fFragmentProcessors where coverage processors begin.
|
||||
|
@ -23,7 +23,7 @@ void GrProcOptInfo::calcWithInitialValues(const GrFragmentProcessor * const proc
|
||||
out.fValidFlags = flags;
|
||||
out.fIsLCDCoverage = isLCD;
|
||||
fInOut.reset(out);
|
||||
this->internalCalc(processors, cnt, false);
|
||||
this->internalCalc(processors, cnt);
|
||||
}
|
||||
|
||||
void GrProcOptInfo::initUsingInvariantOutput(GrInitInvariantOutput invOutput) {
|
||||
@ -31,16 +31,13 @@ void GrProcOptInfo::initUsingInvariantOutput(GrInitInvariantOutput invOutput) {
|
||||
}
|
||||
|
||||
void GrProcOptInfo::completeCalculations(const GrFragmentProcessor * const processors[], int cnt) {
|
||||
this->internalCalc(processors, cnt, false);
|
||||
this->internalCalc(processors, cnt);
|
||||
}
|
||||
|
||||
void GrProcOptInfo::internalCalc(const GrFragmentProcessor* const processors[],
|
||||
int cnt,
|
||||
bool initWillReadFragmentPosition) {
|
||||
void GrProcOptInfo::internalCalc(const GrFragmentProcessor* const processors[], int cnt) {
|
||||
fFirstEffectiveProcessorIndex = 0;
|
||||
fInputColorIsUsed = true;
|
||||
fInputColor = fInOut.color();
|
||||
fReadsFragPosition = initWillReadFragmentPosition;
|
||||
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
const GrFragmentProcessor* processor = processors[i];
|
||||
@ -50,11 +47,6 @@ void GrProcOptInfo::internalCalc(const GrFragmentProcessor* const processors[],
|
||||
if (!fInOut.willUseInputColor()) {
|
||||
fFirstEffectiveProcessorIndex = i;
|
||||
fInputColorIsUsed = false;
|
||||
// Reset these since we don't care if previous stages read these values
|
||||
fReadsFragPosition = initWillReadFragmentPosition;
|
||||
}
|
||||
if (processor->willReadFragmentPosition()) {
|
||||
fReadsFragPosition = true;
|
||||
}
|
||||
if (kRGBA_GrColorComponentFlags == fInOut.validFlags()) {
|
||||
fFirstEffectiveProcessorIndex = i + 1;
|
||||
@ -63,8 +55,6 @@ void GrProcOptInfo::internalCalc(const GrFragmentProcessor* const processors[],
|
||||
// Since we are clearing all previous color stages we are in a state where we have found
|
||||
// zero stages that don't multiply the inputColor.
|
||||
fInOut.resetNonMulStageFound();
|
||||
// Reset these since we don't care if previous stages read these values
|
||||
fReadsFragPosition = initWillReadFragmentPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,6 @@
|
||||
class GrDrawBatch;
|
||||
class GrFragmentProcessor;
|
||||
class GrPrimitiveProcessor;
|
||||
class GrProcessor;
|
||||
|
||||
/**
|
||||
* GrProcOptInfo gathers invariant data from a set of processor stages.It is used to recognize
|
||||
@ -27,8 +26,7 @@ public:
|
||||
: fInOut(0, static_cast<GrColorComponentFlags>(0), false)
|
||||
, fFirstEffectiveProcessorIndex(0)
|
||||
, fInputColorIsUsed(true)
|
||||
, fInputColor(0)
|
||||
, fReadsFragPosition(false) {}
|
||||
, fInputColor(0) {}
|
||||
|
||||
void calcWithInitialValues(const GrFragmentProcessor* const *, int cnt, GrColor startColor,
|
||||
GrColorComponentFlags, bool areCoverageStages, bool isLCD = false);
|
||||
@ -75,19 +73,13 @@ public:
|
||||
*/
|
||||
GrColor inputColorToFirstEffectiveProccesor() const { return fInputColor; }
|
||||
|
||||
/**
|
||||
* Returns true if any of the processor preserved by GrProcOptInfo read the frag position.
|
||||
*/
|
||||
bool readsFragPosition() const { return fReadsFragPosition; }
|
||||
|
||||
private:
|
||||
void internalCalc(const GrFragmentProcessor* const[], int cnt, bool initWillReadFragPosition);
|
||||
void internalCalc(const GrFragmentProcessor* const[], int cnt);
|
||||
|
||||
GrInvariantOutput fInOut;
|
||||
int fFirstEffectiveProcessorIndex;
|
||||
bool fInputColorIsUsed;
|
||||
GrColor fInputColor;
|
||||
bool fReadsFragPosition;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -120,6 +120,7 @@ bool GrGLProgramDescBuilder::Build(GrProgramDesc* desc,
|
||||
glDesc->key().reset();
|
||||
return false;
|
||||
}
|
||||
GrProcessor::RequiredFeatures requiredFeatures = primProc.requiredFeatures();
|
||||
|
||||
for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) {
|
||||
const GrFragmentProcessor& fp = pipeline.getFragmentProcessor(i);
|
||||
@ -127,6 +128,7 @@ bool GrGLProgramDescBuilder::Build(GrProgramDesc* desc,
|
||||
glDesc->key().reset();
|
||||
return false;
|
||||
}
|
||||
requiredFeatures |= fp.requiredFeatures();
|
||||
}
|
||||
|
||||
const GrXferProcessor& xp = pipeline.getXferProcessor();
|
||||
@ -135,6 +137,7 @@ bool GrGLProgramDescBuilder::Build(GrProgramDesc* desc,
|
||||
glDesc->key().reset();
|
||||
return false;
|
||||
}
|
||||
requiredFeatures |= xp.requiredFeatures();
|
||||
|
||||
// --------DO NOT MOVE HEADER ABOVE THIS LINE--------------------------------------------------
|
||||
// Because header is a pointer into the dynamic array, we can't push any new data into the key
|
||||
@ -144,7 +147,7 @@ bool GrGLProgramDescBuilder::Build(GrProgramDesc* desc,
|
||||
// make sure any padding in the header is zeroed.
|
||||
memset(header, 0, kHeaderSize);
|
||||
|
||||
if (pipeline.readsFragPosition()) {
|
||||
if (requiredFeatures & GrProcessor::kFragmentPosition_RequiredFeature) {
|
||||
header->fFragPosKey =
|
||||
GrGLSLFragmentShaderBuilder::KeyForFragmentPosition(pipeline.getRenderTarget());
|
||||
} else {
|
||||
|
@ -74,10 +74,16 @@ GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* p
|
||||
, fHasCustomColorOutput(false)
|
||||
, fCustomColorOutputIndex(-1)
|
||||
, fHasSecondaryOutput(false)
|
||||
, fHasInitializedSampleMask(false)
|
||||
, fHasReadDstColor(false)
|
||||
, fHasReadFragmentPosition(false) {
|
||||
, fHasInitializedSampleMask(false) {
|
||||
fSubstageIndices.push_back(0);
|
||||
#ifdef SK_DEBUG
|
||||
fUsedProcessorFeatures = GrProcessor::kNone_RequiredFeatures;
|
||||
fHasReadDstColor = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GrGLSLFragmentShaderBuilder::hasFragmentPosition() const {
|
||||
return 0 != fProgramBuilder->header().fFragPosKey;
|
||||
}
|
||||
|
||||
bool GrGLSLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
|
||||
@ -123,7 +129,8 @@ SkString GrGLSLFragmentShaderBuilder::ensureFSCoords2D(const GrGLSLTransformedCo
|
||||
}
|
||||
|
||||
const char* GrGLSLFragmentShaderBuilder::fragmentPosition() {
|
||||
fHasReadFragmentPosition = true;
|
||||
SkASSERT(this->hasFragmentPosition());
|
||||
SkDEBUGCODE(fUsedProcessorFeatures |= GrProcessor::kFragmentPosition_RequiredFeature;)
|
||||
|
||||
const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps();
|
||||
// We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
|
||||
@ -212,7 +219,7 @@ void GrGLSLFragmentShaderBuilder::overrideSampleCoverage(const char* mask) {
|
||||
}
|
||||
|
||||
const char* GrGLSLFragmentShaderBuilder::dstColor() {
|
||||
fHasReadDstColor = true;
|
||||
SkDEBUGCODE(fHasReadDstColor = true;)
|
||||
|
||||
const char* override = fProgramBuilder->primitiveProcessor().getDestColorOverride();
|
||||
if (override != nullptr) {
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "GrGLSLShaderBuilder.h"
|
||||
|
||||
#include "GrProcessor.h"
|
||||
#include "glsl/GrGLSLProcessorTypes.h"
|
||||
|
||||
class GrRenderTarget;
|
||||
@ -165,20 +166,24 @@ public:
|
||||
void enableAdvancedBlendEquationIfNeeded(GrBlendEquation) override;
|
||||
|
||||
private:
|
||||
bool hasFragmentPosition() const;
|
||||
|
||||
// Private public interface, used by GrGLProgramBuilder to build a fragment shader
|
||||
void enableCustomOutput();
|
||||
void enableSecondaryOutput();
|
||||
const char* getPrimaryColorOutputName() const;
|
||||
const char* getSecondaryColorOutputName() const;
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
// As GLSLProcessors emit code, there are some conditions we need to verify. We use the below
|
||||
// state to track this. The reset call is called per processor emitted.
|
||||
GrProcessor::RequiredFeatures usedProcessorFeatures() const { return fUsedProcessorFeatures; }
|
||||
bool hasReadDstColor() const { return fHasReadDstColor; }
|
||||
bool hasReadFragmentPosition() const { return fHasReadFragmentPosition; }
|
||||
void reset() {
|
||||
void resetVerification() {
|
||||
fUsedProcessorFeatures = GrProcessor::kNone_RequiredFeatures;
|
||||
fHasReadDstColor = false;
|
||||
fHasReadFragmentPosition = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char* DeclaredColorOutputName() { return "fsColorOut"; }
|
||||
static const char* DeclaredSecondaryColorOutputName() { return "fsSecondaryColorOut"; }
|
||||
@ -226,10 +231,12 @@ private:
|
||||
bool fHasSecondaryOutput;
|
||||
bool fHasInitializedSampleMask;
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
// some state to verify shaders and effects are consistent, this is reset between effects by
|
||||
// the program creator
|
||||
GrProcessor::RequiredFeatures fUsedProcessorFeatures;
|
||||
bool fHasReadDstColor;
|
||||
bool fHasReadFragmentPosition;
|
||||
#endif
|
||||
|
||||
friend class GrGLSLProgramBuilder;
|
||||
friend class GrGLProgramBuilder;
|
||||
|
@ -99,7 +99,7 @@ void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr
|
||||
|
||||
// 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);
|
||||
SkDEBUGCODE(verify(proc);)
|
||||
|
||||
fFS.codeAppend("}");
|
||||
}
|
||||
@ -147,7 +147,7 @@ void GrGLSLProgramBuilder::emitAndInstallFragProc(const GrFragmentProcessor& fp,
|
||||
|
||||
// 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);
|
||||
SkDEBUGCODE(verify(fp);)
|
||||
fFragmentProcessors.push_back(fragProc);
|
||||
|
||||
fFS.codeAppend("}");
|
||||
@ -194,7 +194,7 @@ void GrGLSLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
|
||||
|
||||
// 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);
|
||||
SkDEBUGCODE(verify(xp);)
|
||||
fFS.codeAppend("}");
|
||||
}
|
||||
|
||||
@ -214,17 +214,20 @@ void GrGLSLProgramBuilder::emitFSOutputSwizzle(bool hasSecondaryOutput) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
void GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
|
||||
SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
|
||||
SkASSERT(fFS.usedProcessorFeatures() == gp.requiredFeatures());
|
||||
}
|
||||
|
||||
void GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) {
|
||||
SkASSERT(fFS.usedProcessorFeatures() == xp.requiredFeatures());
|
||||
SkASSERT(fFS.hasReadDstColor() == xp.willReadDstColor());
|
||||
}
|
||||
|
||||
void GrGLSLProgramBuilder::verify(const GrFragmentProcessor& fp) {
|
||||
SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
|
||||
SkASSERT(fFS.usedProcessorFeatures() == fp.requiredFeatures());
|
||||
}
|
||||
#endif
|
||||
|
||||
void GrGLSLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name, bool mangle) {
|
||||
if ('\0' == prefix) {
|
||||
|
@ -105,7 +105,7 @@ private:
|
||||
// fragment shader are cleared.
|
||||
void reset() {
|
||||
this->addStage();
|
||||
fFS.reset();
|
||||
SkDEBUGCODE(fFS.resetVerification();)
|
||||
}
|
||||
void addStage() { fStageIndex++; }
|
||||
|
||||
@ -141,9 +141,11 @@ private:
|
||||
GrPixelLocalStorageState plsState);
|
||||
void emitFSOutputSwizzle(bool hasSecondaryOutput);
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
void verify(const GrPrimitiveProcessor&);
|
||||
void verify(const GrXferProcessor&);
|
||||
void verify(const GrFragmentProcessor&);
|
||||
#endif
|
||||
|
||||
virtual void emitSamplers(const GrProcessor& processor,
|
||||
GrGLSLTextureSampler::TextureSamplerArray* outSamplers) = 0;
|
||||
|
@ -107,6 +107,7 @@ bool GrVkProgramDescBuilder::Build(GrProgramDesc* desc,
|
||||
vkDesc->key().reset();
|
||||
return false;
|
||||
}
|
||||
GrProcessor::RequiredFeatures requiredFeatures = primProc.requiredFeatures();
|
||||
|
||||
for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) {
|
||||
const GrFragmentProcessor& fp = pipeline.getFragmentProcessor(i);
|
||||
@ -114,6 +115,7 @@ bool GrVkProgramDescBuilder::Build(GrProgramDesc* desc,
|
||||
vkDesc->key().reset();
|
||||
return false;
|
||||
}
|
||||
requiredFeatures |= fp.requiredFeatures();
|
||||
}
|
||||
|
||||
const GrXferProcessor& xp = pipeline.getXferProcessor();
|
||||
@ -122,6 +124,7 @@ bool GrVkProgramDescBuilder::Build(GrProgramDesc* desc,
|
||||
vkDesc->key().reset();
|
||||
return false;
|
||||
}
|
||||
requiredFeatures |= xp.requiredFeatures();
|
||||
|
||||
// --------DO NOT MOVE HEADER ABOVE THIS LINE--------------------------------------------------
|
||||
// Because header is a pointer into the dynamic array, we can't push any new data into the key
|
||||
@ -131,7 +134,7 @@ bool GrVkProgramDescBuilder::Build(GrProgramDesc* desc,
|
||||
// make sure any padding in the header is zeroed.
|
||||
memset(header, 0, kHeaderSize);
|
||||
|
||||
if (pipeline.readsFragPosition()) {
|
||||
if (requiredFeatures & GrProcessor::kFragmentPosition_RequiredFeature) {
|
||||
header->fFragPosKey =
|
||||
GrGLSLFragmentShaderBuilder::KeyForFragmentPosition(pipeline.getRenderTarget());
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user