skslc now automatically turns on derivatives support
BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=3569 Change-Id: I211f4a80ced951a0d2f29763f85fe75a5daccff7 Reviewed-on: https://skia-review.googlesource.com/3569 Reviewed-by: Ben Wagner <benjaminwagner@google.com>
This commit is contained in:
parent
4f2a88cdf0
commit
311742bd0e
@ -463,8 +463,6 @@ private:
|
||||
diegp.fInPosition->fName,
|
||||
args.fFPCoordTransformHandler);
|
||||
|
||||
SkAssertResult(fragBuilder->enableFeature(
|
||||
GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||
// for outer curve
|
||||
fragBuilder->codeAppendf("vec2 scaledOffset = %s.xy;", offsets0.fsIn());
|
||||
fragBuilder->codeAppend("float test = dot(scaledOffset, scaledOffset) - 1.0;");
|
||||
|
@ -579,8 +579,6 @@ public:
|
||||
qe.localMatrix(),
|
||||
args.fFPCoordTransformHandler);
|
||||
|
||||
SkAssertResult(fragBuilder->enableFeature(
|
||||
GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||
fragBuilder->codeAppendf("float edgeAlpha;");
|
||||
|
||||
// keep the derivative instructions outside the conditional
|
||||
|
@ -339,8 +339,6 @@ public:
|
||||
GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
|
||||
SkAssertResult(fsBuilder->enableFeature(
|
||||
GrGLSLFragmentShaderBuilder::kPixelLocalStorage_GLSLFeature));
|
||||
SkAssertResult(fsBuilder->enableFeature(
|
||||
GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||
fsBuilder->declAppendf(GR_GL_PLS_PATH_DATA_DECL);
|
||||
// Compute four subsamples, each shifted a quarter pixel along x and y from
|
||||
// gl_FragCoord. The oriented box positioning of the subsamples is of course not
|
||||
@ -522,8 +520,6 @@ public:
|
||||
GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
|
||||
SkAssertResult(fsBuilder->enableFeature(
|
||||
GrGLSLFragmentShaderBuilder::kPixelLocalStorage_GLSLFeature));
|
||||
SkAssertResult(fsBuilder->enableFeature(
|
||||
GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||
static const int QUAD_ARGS = 2;
|
||||
GrGLSLShaderVar inQuadArgs[QUAD_ARGS] = {
|
||||
GrGLSLShaderVar("dot", kFloat_GrSLType, 0, kHigh_GrSLPrecision),
|
||||
|
@ -136,8 +136,6 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
|
||||
switch (fEdgeType) {
|
||||
case kHairlineAA_GrProcessorEdgeType: {
|
||||
SkAssertResult(fragBuilder->enableFeature(
|
||||
GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||
fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
|
||||
fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
|
||||
fragBuilder->codeAppendf("%s = 2.0 * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
|
||||
@ -165,8 +163,6 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
break;
|
||||
}
|
||||
case kFillAA_GrProcessorEdgeType: {
|
||||
SkAssertResult(fragBuilder->enableFeature(
|
||||
GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||
fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
|
||||
fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
|
||||
fragBuilder->codeAppendf("%s ="
|
||||
@ -374,8 +370,6 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
|
||||
switch (fEdgeType) {
|
||||
case kHairlineAA_GrProcessorEdgeType: {
|
||||
SkAssertResult(fragBuilder->enableFeature(
|
||||
GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||
fragBuilder->codeAppendf("vec2 duvdx = dFdx(%s.xy);", v.fsIn());
|
||||
fragBuilder->codeAppendf("vec2 duvdy = dFdy(%s.xy);", v.fsIn());
|
||||
fragBuilder->codeAppendf("vec2 gF = vec2(2.0 * %s.x * duvdx.x - duvdx.y,"
|
||||
@ -390,8 +384,6 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
break;
|
||||
}
|
||||
case kFillAA_GrProcessorEdgeType: {
|
||||
SkAssertResult(fragBuilder->enableFeature(
|
||||
GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||
fragBuilder->codeAppendf("vec2 duvdx = dFdx(%s.xy);", v.fsIn());
|
||||
fragBuilder->codeAppendf("vec2 duvdy = dFdy(%s.xy);", v.fsIn());
|
||||
fragBuilder->codeAppendf("vec2 gF = vec2(2.0 * %s.x * duvdx.x - duvdx.y,"
|
||||
@ -592,8 +584,6 @@ void GrGLCubicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
|
||||
switch (fEdgeType) {
|
||||
case kHairlineAA_GrProcessorEdgeType: {
|
||||
SkAssertResult(fragBuilder->enableFeature(
|
||||
GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||
fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
|
||||
fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
|
||||
fragBuilder->codeAppendf("%s = 3.0 * %s.x * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
|
||||
@ -620,8 +610,6 @@ void GrGLCubicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
|
||||
break;
|
||||
}
|
||||
case kFillAA_GrProcessorEdgeType: {
|
||||
SkAssertResult(fragBuilder->enableFeature(
|
||||
GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||
fragBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
|
||||
fragBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
|
||||
fragBuilder->codeAppendf("%s ="
|
||||
|
@ -35,8 +35,6 @@ public:
|
||||
const GrDistanceFieldA8TextGeoProc& dfTexEffect =
|
||||
args.fGP.cast<GrDistanceFieldA8TextGeoProc>();
|
||||
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
SkAssertResult(fragBuilder->enableFeature(
|
||||
GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||
|
||||
GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
|
||||
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
|
||||
@ -313,8 +311,6 @@ public:
|
||||
const GrDistanceFieldPathGeoProc& dfTexEffect = args.fGP.cast<GrDistanceFieldPathGeoProc>();
|
||||
|
||||
GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
SkAssertResult(fragBuilder->enableFeature(
|
||||
GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||
|
||||
GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
|
||||
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
|
||||
@ -610,9 +606,6 @@ public:
|
||||
|
||||
// add frag shader code
|
||||
|
||||
SkAssertResult(fragBuilder->enableFeature(
|
||||
GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||
|
||||
// create LCD offset adjusted by inverse of transform
|
||||
// Use highp to work around aliasing issues
|
||||
fragBuilder->appendPrecisionModifier(kHigh_GrSLPrecision);
|
||||
|
@ -85,6 +85,10 @@ SkSL::GLCaps GrGLSkSLCapsForContext(const GrGLContext& context) {
|
||||
result.fIsCoreProfile = caps->isCoreProfile();
|
||||
result.fUsesPrecisionModifiers = glslCaps->usesPrecisionModifiers();
|
||||
result.fMustDeclareFragmentShaderOutput = glslCaps->mustDeclareFragmentShaderOutput();
|
||||
result.fShaderDerivativeSupport = glslCaps->shaderDerivativeSupport();
|
||||
if (glslCaps->shaderDerivativeExtensionString()) {
|
||||
result.fShaderDerivativeExtensionString = glslCaps->shaderDerivativeExtensionString();
|
||||
}
|
||||
result.fCanUseMinAndAbsTogether = glslCaps->canUseMinAndAbsTogether();
|
||||
result.fMustForceNegatedAtanParamToFloat = glslCaps->mustForceNegatedAtanParamToFloat();
|
||||
return result;
|
||||
|
@ -96,14 +96,6 @@ GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* p
|
||||
bool GrGLSLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
|
||||
const GrGLSLCaps& glslCaps = *fProgramBuilder->glslCaps();
|
||||
switch (feature) {
|
||||
case kStandardDerivatives_GLSLFeature:
|
||||
if (!glslCaps.shaderDerivativeSupport()) {
|
||||
return false;
|
||||
}
|
||||
if (const char* extension = glslCaps.shaderDerivativeExtensionString()) {
|
||||
this->addFeature(1 << kStandardDerivatives_GLSLFeature, extension);
|
||||
}
|
||||
return true;
|
||||
case kPixelLocalStorage_GLSLFeature:
|
||||
if (glslCaps.pixelLocalStorageSize() <= 0) {
|
||||
return false;
|
||||
|
@ -29,8 +29,7 @@ public:
|
||||
* if code is added that uses one of these features without calling enableFeature()
|
||||
*/
|
||||
enum GLSLFeature {
|
||||
kStandardDerivatives_GLSLFeature = kLastGLSLPrivateFeature + 1,
|
||||
kPixelLocalStorage_GLSLFeature,
|
||||
kPixelLocalStorage_GLSLFeature = kLastGLSLPrivateFeature + 1,
|
||||
kMultisampleInterpolation_GLSLFeature
|
||||
};
|
||||
|
||||
|
@ -1408,7 +1408,6 @@ void GLSLInstanceProcessor::BackendMultisample::onEmitCode(GrGLSLVertexBuilder*,
|
||||
if (arcTest && fBatchInfo.fHasPerspective) {
|
||||
// The non-perspective version accounts for fwidth() in the vertex shader.
|
||||
// We make sure to take the derivative here, before a neighbor pixel may early accept.
|
||||
f->enableFeature(GrGLSLPPFragmentBuilder::kStandardDerivatives_GLSLFeature);
|
||||
f->appendPrecisionModifier(kHigh_GrSLPrecision);
|
||||
f->codeAppendf("vec2 arcTest = %s - 0.5 * fwidth(%s);",
|
||||
fArcTest.fsIn(), fArcTest.fsIn());
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "ir/SkSLIntLiteral.h"
|
||||
#include "ir/SkSLModifiersDeclaration.h"
|
||||
#include "ir/SkSLSymbolTable.h"
|
||||
#include "ir/SkSLUnresolvedFunction.h"
|
||||
#include "ir/SkSLVarDeclarations.h"
|
||||
#include "SkMutex.h"
|
||||
|
||||
@ -135,6 +136,7 @@ Compiler::Compiler()
|
||||
Modifiers::Flag ignored1;
|
||||
std::vector<std::unique_ptr<ProgramElement>> ignored2;
|
||||
this->internalConvertProgram(SKSL_INCLUDE, &ignored1, &ignored2);
|
||||
fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
|
||||
ASSERT(!fErrorCount);
|
||||
}
|
||||
|
||||
@ -393,10 +395,11 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, std::strin
|
||||
this->internalConvertProgram(SKSL_FRAG_INCLUDE, &ignored, &elements);
|
||||
break;
|
||||
}
|
||||
fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
|
||||
Modifiers::Flag defaultPrecision;
|
||||
this->internalConvertProgram(text, &defaultPrecision, &elements);
|
||||
auto result = std::unique_ptr<Program>(new Program(kind, defaultPrecision, std::move(elements),
|
||||
fIRGenerator->fSymbolTable));;
|
||||
fIRGenerator->fSymbolTable));
|
||||
fIRGenerator->popSymbolTable();
|
||||
this->writeErrorCount();
|
||||
return result;
|
||||
|
@ -150,7 +150,7 @@ void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherEx
|
||||
}
|
||||
|
||||
void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
if (!fCaps.fCanUseMinAndAbsTogether && c.fFunction.fName == "min") {
|
||||
if (!fCaps.fCanUseMinAndAbsTogether && c.fFunction.fName == "min" && c.fFunction.fBuiltin) {
|
||||
ASSERT(c.fArguments.size() == 2);
|
||||
if (is_abs(*c.fArguments[0])) {
|
||||
this->writeMinAbsHack(*c.fArguments[0], *c.fArguments[1]);
|
||||
@ -164,7 +164,8 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
}
|
||||
}
|
||||
if (fCaps.fMustForceNegatedAtanParamToFloat && c.fFunction.fName == "atan" &&
|
||||
c.fArguments.size() == 2 && c.fArguments[1]->fKind == Expression::kPrefix_Kind) {
|
||||
c.fFunction.fBuiltin && c.fArguments.size() == 2 &&
|
||||
c.fArguments[1]->fKind == Expression::kPrefix_Kind) {
|
||||
const PrefixExpression& p = (PrefixExpression&) *c.fArguments[1];
|
||||
if (p.fOperator == Token::MINUS) {
|
||||
this->write("atan(");
|
||||
@ -175,6 +176,12 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!fFoundDerivatives && fCaps.fShaderDerivativeExtensionString != "" &&
|
||||
(c.fFunction.fName == "dFdx" || c.fFunction.fName == "dFdy") && c.fFunction.fBuiltin) {
|
||||
ASSERT(fCaps.fShaderDerivativeSupport);
|
||||
fHeader << "#extension " << fCaps.fShaderDerivativeExtensionString << " : require\n";
|
||||
fFoundDerivatives = true;
|
||||
}
|
||||
this->write(c.fFunction.fName + "(");
|
||||
const char* separator = "";
|
||||
for (const auto& arg : c.fArguments) {
|
||||
@ -578,7 +585,7 @@ void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
|
||||
|
||||
void GLSLCodeGenerator::generateCode(const Program& program, std::ostream& out) {
|
||||
ASSERT(fOut == nullptr);
|
||||
fOut = &out;
|
||||
fOut = &fHeader;
|
||||
fProgramKind = program.fKind;
|
||||
this->write("#version " + to_string(fCaps.fVersion));
|
||||
if (fCaps.fStandard == GLCaps::kGLES_Standard && fCaps.fVersion >= 300) {
|
||||
@ -610,6 +617,8 @@ void GLSLCodeGenerator::generateCode(const Program& program, std::ostream& out)
|
||||
}
|
||||
this->writeLine(" float;");
|
||||
}
|
||||
std::stringstream body;
|
||||
fOut = &body;
|
||||
for (const auto& e : program.fElements) {
|
||||
switch (e->fKind) {
|
||||
case ProgramElement::kExtension_Kind:
|
||||
@ -649,6 +658,9 @@ void GLSLCodeGenerator::generateCode(const Program& program, std::ostream& out)
|
||||
}
|
||||
}
|
||||
fOut = nullptr;
|
||||
|
||||
out << fHeader.str();
|
||||
out << body.str();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -45,20 +45,25 @@ namespace SkSL {
|
||||
#define kLast_Capability SpvCapabilityMultiViewport
|
||||
|
||||
struct GLCaps {
|
||||
int fVersion;
|
||||
GLCaps() {}
|
||||
|
||||
int fVersion = 400;
|
||||
enum {
|
||||
kGL_Standard,
|
||||
kGLES_Standard
|
||||
} fStandard;
|
||||
bool fIsCoreProfile;
|
||||
bool fUsesPrecisionModifiers;
|
||||
bool fMustDeclareFragmentShaderOutput;
|
||||
} fStandard = kGL_Standard;
|
||||
bool fIsCoreProfile = false;
|
||||
bool fUsesPrecisionModifiers = false;
|
||||
bool fMustDeclareFragmentShaderOutput = false;
|
||||
bool fShaderDerivativeSupport = true;
|
||||
// extension string to enable derivative support, or null if unnecessary
|
||||
std::string fShaderDerivativeExtensionString;
|
||||
// The Tegra3 compiler will sometimes never return if we have min(abs(x), y)
|
||||
bool fCanUseMinAndAbsTogether;
|
||||
bool fCanUseMinAndAbsTogether = true;
|
||||
// On Intel GPU there is an issue where it misinterprets an atan argument (second argument only,
|
||||
// apparently) of the form "-<expr>" as an int, so we rewrite it as "-1.0 * <expr>" to avoid
|
||||
// this problem
|
||||
bool fMustForceNegatedAtanParamToFloat;
|
||||
bool fMustForceNegatedAtanParamToFloat = false;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -89,11 +94,7 @@ public:
|
||||
|
||||
GLSLCodeGenerator(const Context* context, GLCaps caps)
|
||||
: fContext(*context)
|
||||
, fCaps(caps)
|
||||
, fOut(nullptr)
|
||||
, fVarCount(0)
|
||||
, fIndentation(0)
|
||||
, fAtLineStart(true) {}
|
||||
, fCaps(caps) {}
|
||||
|
||||
void generateCode(const Program& program, std::ostream& out) override;
|
||||
|
||||
@ -176,16 +177,19 @@ private:
|
||||
|
||||
const Context& fContext;
|
||||
const GLCaps fCaps;
|
||||
std::ostream* fOut;
|
||||
std::ostream* fOut = nullptr;
|
||||
std::stringstream fHeader;
|
||||
std::string fFunctionHeader;
|
||||
Program::Kind fProgramKind;
|
||||
int fVarCount;
|
||||
int fIndentation;
|
||||
bool fAtLineStart;
|
||||
int fVarCount = 0;
|
||||
int fIndentation = 0;
|
||||
bool fAtLineStart = false;
|
||||
// Keeps track of which struct types we have written. Given that we are unlikely to ever write
|
||||
// more than one or two structs per shader, a simple linear search will be faster than anything
|
||||
// fancier.
|
||||
std::vector<const Type*> fWrittenStructs;
|
||||
// true if we have run into usages of dFdx / dFdy
|
||||
bool fFoundDerivatives = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -16,18 +16,6 @@ bool endsWith(const std::string& s, const std::string& ending) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static SkSL::GLCaps default_caps() {
|
||||
return {
|
||||
400,
|
||||
SkSL::GLCaps::kGL_Standard,
|
||||
false, // isCoreProfile
|
||||
false, // usesPrecisionModifiers;
|
||||
false, // mustDeclareFragmentShaderOutput
|
||||
true, // canUseMinAndAbsTogether
|
||||
false // mustForceNegatedAtanParamToFloat
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Very simple standalone executable to facilitate testing.
|
||||
*/
|
||||
@ -69,7 +57,7 @@ int main(int argc, const char** argv) {
|
||||
} else if (endsWith(name, ".glsl")) {
|
||||
std::ofstream out(argv[2], std::ofstream::binary);
|
||||
SkSL::Compiler compiler;
|
||||
if (!compiler.toGLSL(kind, text, default_caps(), out)) {
|
||||
if (!compiler.toGLSL(kind, text, SkSL::GLCaps(), out)) {
|
||||
printf("%s", compiler.errorText().c_str());
|
||||
exit(3);
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ struct FunctionDeclaration : public Symbol {
|
||||
std::vector<const Variable*> parameters, const Type& returnType)
|
||||
: INHERITED(position, kFunctionDeclaration_Kind, std::move(name))
|
||||
, fDefined(false)
|
||||
, fBuiltin(false)
|
||||
, fParameters(std::move(parameters))
|
||||
, fReturnType(returnType) {}
|
||||
|
||||
@ -55,6 +56,7 @@ struct FunctionDeclaration : public Symbol {
|
||||
}
|
||||
|
||||
mutable bool fDefined;
|
||||
bool fBuiltin;
|
||||
const std::vector<const Variable*> fParameters;
|
||||
const Type& fReturnType;
|
||||
|
||||
|
@ -97,4 +97,22 @@ void SymbolTable::addWithoutOwnership(const std::string& name, const Symbol* sym
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SymbolTable::markAllFunctionsBuiltin() {
|
||||
for (const auto& pair : fSymbols) {
|
||||
switch (pair.second->fKind) {
|
||||
case Symbol::kFunctionDeclaration_Kind:
|
||||
((FunctionDeclaration&) *pair.second).fBuiltin = true;
|
||||
break;
|
||||
case Symbol::kUnresolvedFunction_Kind:
|
||||
for (auto& f : ((UnresolvedFunction&) *pair.second).fFunctions) {
|
||||
((FunctionDeclaration*) f)->fBuiltin = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -39,6 +39,8 @@ public:
|
||||
|
||||
Symbol* takeOwnership(Symbol* s);
|
||||
|
||||
void markAllFunctionsBuiltin();
|
||||
|
||||
const std::shared_ptr<SymbolTable> fParent;
|
||||
|
||||
private:
|
||||
|
@ -27,15 +27,7 @@ static void test(skiatest::Reporter* r, const char* src, SkSL::GLCaps caps, cons
|
||||
}
|
||||
|
||||
static SkSL::GLCaps default_caps() {
|
||||
return {
|
||||
400,
|
||||
SkSL::GLCaps::kGL_Standard,
|
||||
false, // isCoreProfile
|
||||
false, // usesPrecisionModifiers;
|
||||
false, // mustDeclareFragmentShaderOutput
|
||||
true, // canUseMinAndAbsTogether
|
||||
false // mustForceNegatedAtanParamToFloat
|
||||
};
|
||||
return SkSL::GLCaps();
|
||||
}
|
||||
|
||||
DEF_TEST(SkSLHelloWorld, r) {
|
||||
@ -387,3 +379,30 @@ DEF_TEST(SkSLArrayConstructors, r) {
|
||||
"vec2 test2[] = vec2[](vec2(1.0, 2.0), vec2(3.0, 4.0));\n"
|
||||
"mat4 test3[] = mat4[]();\n");
|
||||
}
|
||||
|
||||
DEF_TEST(SkSLDerivatives, r) {
|
||||
test(r,
|
||||
"void main() { float x = dFdx(1); }",
|
||||
default_caps(),
|
||||
"#version 400\n"
|
||||
"void main() {\n"
|
||||
" float x = dFdx(1.0);\n"
|
||||
"}\n");
|
||||
SkSL::GLCaps caps = default_caps();
|
||||
caps.fShaderDerivativeExtensionString = "GL_OES_standard_derivatives";
|
||||
test(r,
|
||||
"void main() { float x = 1; }",
|
||||
caps,
|
||||
"#version 400\n"
|
||||
"void main() {\n"
|
||||
" float x = 1.0;\n"
|
||||
"}\n");
|
||||
test(r,
|
||||
"void main() { float x = dFdx(1); }",
|
||||
caps,
|
||||
"#version 400\n"
|
||||
"#extension GL_OES_standard_derivatives : require\n"
|
||||
"void main() {\n"
|
||||
" float x = dFdx(1.0);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user