Add a workaround for platforms with broken geo shader invocations
BUG=skia: Change-Id: I9105b65b522d9ffac5a90ca7126bfd4ae88f8069 Reviewed-on: https://skia-review.googlesource.com/8422 Reviewed-by: Greg Daniel <egdaniel@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Chris Dalton <csmartdalton@google.com>
This commit is contained in:
parent
e14349a754
commit
2e777ead12
@ -176,6 +176,9 @@ public:
|
||||
|
||||
bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; }
|
||||
|
||||
// On MacBook, geometry shaders break if they have more than one invocation.
|
||||
bool mustImplementGSInvocationsWithLoop() const { return fMustImplementGSInvocationsWithLoop; }
|
||||
|
||||
// Returns the string of an extension that must be enabled in the shader to support
|
||||
// derivatives. If nullptr is returned then no extension needs to be enabled. Before calling
|
||||
// this function, the caller should check that shaderDerivativeSupport exists.
|
||||
@ -304,6 +307,7 @@ private:
|
||||
bool fMustForceNegatedAtanParamToFloat : 1;
|
||||
bool fAtan2ImplementedAsAtanYOverX : 1;
|
||||
bool fRequiresLocalOutputColorForFBFetch : 1;
|
||||
bool fMustImplementGSInvocationsWithLoop : 1;
|
||||
|
||||
PrecisionInfo fFloatPrecisions[kGrShaderTypeCount][kGrSLPrecisionCount];
|
||||
int fPixelLocalStorageSize;
|
||||
|
@ -58,6 +58,7 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
|
||||
fMustForceNegatedAtanParamToFloat = false;
|
||||
fAtan2ImplementedAsAtanYOverX = false;
|
||||
fRequiresLocalOutputColorForFBFetch = false;
|
||||
fMustImplementGSInvocationsWithLoop = false;
|
||||
fFlatInterpolationSupport = false;
|
||||
fNoPerspectiveInterpolationSupport = false;
|
||||
fMultisampleInterpolationSupport = false;
|
||||
@ -144,6 +145,8 @@ SkString GrShaderCaps::dump() const {
|
||||
"YES" : "NO"));
|
||||
r.appendf("Must use local out color for FBFetch: %s\n", (fRequiresLocalOutputColorForFBFetch ?
|
||||
"YES" : "NO"));
|
||||
r.appendf("Must implement geo shader invocations with loop : %s\n",
|
||||
(fMustImplementGSInvocationsWithLoop ? "YES" : "NO"));
|
||||
r.appendf("Flat interpolation support: %s\n", (fFlatInterpolationSupport ? "YES" : "NO"));
|
||||
r.appendf("No perspective interpolation support: %s\n", (fNoPerspectiveInterpolationSupport ?
|
||||
"YES" : "NO"));
|
||||
|
@ -870,6 +870,13 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo) {
|
||||
if (shaderCaps->fFBFetchSupport && kQualcomm_GrGLVendor == ctxInfo.vendor()) {
|
||||
shaderCaps->fRequiresLocalOutputColorForFBFetch = true;
|
||||
}
|
||||
|
||||
#ifdef SK_BUILD_FOR_MAC
|
||||
// On at least some MacBooks, geometry shaders fall apart if we use more than one invocation. To
|
||||
// work around this, we always use a single invocation and wrap the shader in a loop. The long-
|
||||
// term plan for this WAR is for it to eventually be baked into SkSL.
|
||||
shaderCaps->fMustImplementGSInvocationsWithLoop = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GrGLCaps::hasPathRenderingSupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
|
||||
|
@ -35,22 +35,39 @@ static const char* output_type_name(GrGLSLGeometryBuilder::OutputType out) {
|
||||
|
||||
GrGLSLGeometryBuilder::GrGLSLGeometryBuilder(GrGLSLProgramBuilder* program)
|
||||
: INHERITED(program)
|
||||
, fIsConfigured(false) {
|
||||
, fNumInvocations(0) {
|
||||
}
|
||||
|
||||
void GrGLSLGeometryBuilder::configure(InputType inputType, OutputType outputType, int maxVertices,
|
||||
int numInvocations) {
|
||||
SkASSERT(!fIsConfigured);
|
||||
SkASSERT(!this->isConfigured());
|
||||
fNumInvocations = numInvocations;
|
||||
if (this->getProgramBuilder()->shaderCaps()->mustImplementGSInvocationsWithLoop()) {
|
||||
maxVertices *= numInvocations;
|
||||
numInvocations = 1;
|
||||
}
|
||||
this->addLayoutQualifier(input_type_name(inputType), kIn_InterfaceQualifier);
|
||||
this->addLayoutQualifier(SkStringPrintf("invocations = %i", numInvocations).c_str(),
|
||||
kIn_InterfaceQualifier);
|
||||
this->addLayoutQualifier(output_type_name(outputType), kOut_InterfaceQualifier);
|
||||
this->addLayoutQualifier(SkStringPrintf("max_vertices = %i", maxVertices).c_str(),
|
||||
kOut_InterfaceQualifier);
|
||||
fIsConfigured = true;
|
||||
}
|
||||
|
||||
void GrGLSLGeometryBuilder::onFinalize() {
|
||||
SkASSERT(fIsConfigured);
|
||||
SkASSERT(this->isConfigured());
|
||||
fProgramBuilder->varyingHandler()->getGeomDecls(&this->inputs(), &this->outputs());
|
||||
GrShaderVar sk_InvocationID("sk_InvocationID", kInt_GrSLType);
|
||||
this->declareGlobal(sk_InvocationID);
|
||||
SkASSERT(sk_InvocationID.getName() == SkString("sk_InvocationID"));
|
||||
if (this->getProgramBuilder()->shaderCaps()->mustImplementGSInvocationsWithLoop()) {
|
||||
SkString invokeFn;
|
||||
this->emitFunction(kVoid_GrSLType, "invoke", 0, nullptr, this->code().c_str(), &invokeFn);
|
||||
this->code().printf("for (sk_InvocationID = 0; sk_InvocationID < %i; ++sk_InvocationID) {"
|
||||
"%s();"
|
||||
"EndPrimitive();"
|
||||
"}", fNumInvocations, invokeFn.c_str());
|
||||
} else {
|
||||
this->codePrependf("sk_InvocationID = gl_InvocationID;");
|
||||
}
|
||||
}
|
||||
|
@ -31,11 +31,12 @@ public:
|
||||
};
|
||||
|
||||
void configure(InputType, OutputType, int maxVertices, int numInvocations = 1);
|
||||
bool isConfigured() const { return fNumInvocations; }
|
||||
|
||||
private:
|
||||
void onFinalize() override;
|
||||
|
||||
bool fIsConfigured;
|
||||
int fNumInvocations;
|
||||
|
||||
friend class GrGLProgramBuilder;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user