aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/gpu/gl/GrGLUniformHandler.cpp12
-rw-r--r--src/gpu/glsl/GrGLSLProgramBuilder.cpp14
-rw-r--r--src/gpu/glsl/GrGLSLUniformHandler.h9
-rw-r--r--src/gpu/glsl/GrGLSLVertexGeoBuilder.cpp12
-rw-r--r--src/gpu/vk/GrVkUniformHandler.cpp2
-rw-r--r--src/sksl/README3
-rw-r--r--src/sksl/SkSLCompiler.cpp19
-rw-r--r--src/sksl/SkSLCompiler.h3
-rw-r--r--src/sksl/SkSLIRGenerator.cpp89
-rw-r--r--src/sksl/SkSLIRGenerator.h10
-rw-r--r--tests/SkSLGLSLTest.cpp67
11 files changed, 209 insertions, 31 deletions
diff --git a/src/gpu/gl/GrGLUniformHandler.cpp b/src/gpu/gl/GrGLUniformHandler.cpp
index b3b4b9f6b5..39392f996b 100644
--- a/src/gpu/gl/GrGLUniformHandler.cpp
+++ b/src/gpu/gl/GrGLUniformHandler.cpp
@@ -10,10 +10,19 @@
#include "gl/GrGLCaps.h"
#include "gl/GrGLGpu.h"
#include "gl/builders/GrGLProgramBuilder.h"
+#include "SkSLCompiler.h"
#define GL_CALL(X) GR_GL_CALL(this->glGpu()->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->glGpu()->glInterface(), R, X)
+bool valid_name(const char* name) {
+ // disallow unknown names that start with "sk_"
+ if (!strncmp(name, GR_NO_MANGLE_PREFIX, strlen(GR_NO_MANGLE_PREFIX))) {
+ return !strcmp(name, SkSL::Compiler::RTADJUST_NAME);
+ }
+ return true;
+}
+
GrGLSLUniformHandler::UniformHandle GrGLUniformHandler::internalAddUniformArray(
uint32_t visibility,
GrSLType type,
@@ -23,6 +32,7 @@ GrGLSLUniformHandler::UniformHandle GrGLUniformHandler::internalAddUniformArray(
int arrayCount,
const char** outName) {
SkASSERT(name && strlen(name));
+ SkASSERT(valid_name(name));
SkASSERT(0 != visibility);
SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
@@ -36,7 +46,7 @@ GrGLSLUniformHandler::UniformHandle GrGLUniformHandler::internalAddUniformArray(
// uniform view matrix, they should upload the view matrix in their setData along with regular
// uniforms.
char prefix = 'u';
- if ('u' == name[0]) {
+ if ('u' == name[0] || !strncmp(name, GR_NO_MANGLE_PREFIX, strlen(GR_NO_MANGLE_PREFIX))) {
prefix = '\0';
}
fProgramBuilder->nameVariable(uni.fVariable.accessName(), prefix, name, mangleName);
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index 118b904540..04ebc6ad8e 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -15,6 +15,7 @@
#include "glsl/GrGLSLGeometryProcessor.h"
#include "glsl/GrGLSLVarying.h"
#include "glsl/GrGLSLXferProcessor.h"
+#include "SkSLCompiler.h"
const int GrGLSLProgramBuilder::kVarsPerBlock = 8;
@@ -74,13 +75,16 @@ void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr
this->nameExpression(outputCoverage, "outputCoverage");
SkASSERT(!fUniformHandles.fRTAdjustmentUni.isValid());
- GrShaderFlags rtAdjustVisibility = kVertex_GrShaderFlag;
+ GrShaderFlags rtAdjustVisibility;
if (proc.willUseGeoShader()) {
- rtAdjustVisibility |= kGeometry_GrShaderFlag;
+ rtAdjustVisibility = kGeometry_GrShaderFlag;
+ } else {
+ rtAdjustVisibility = kVertex_GrShaderFlag;
}
- fUniformHandles.fRTAdjustmentUni = this->uniformHandler()->addUniform(rtAdjustVisibility,
- kFloat4_GrSLType,
- "rtAdjustment");
+ fUniformHandles.fRTAdjustmentUni = this->uniformHandler()->addUniform(
+ rtAdjustVisibility,
+ kFloat4_GrSLType,
+ SkSL::Compiler::RTADJUST_NAME);
const char* rtAdjustName =
this->uniformHandler()->getUniformCStr(fUniformHandles.fRTAdjustmentUni);
diff --git a/src/gpu/glsl/GrGLSLUniformHandler.h b/src/gpu/glsl/GrGLSLUniformHandler.h
index e1511c2578..662486eebe 100644
--- a/src/gpu/glsl/GrGLSLUniformHandler.h
+++ b/src/gpu/glsl/GrGLSLUniformHandler.h
@@ -12,6 +12,9 @@
#include "GrShaderVar.h"
#include "GrSwizzle.h"
+// variable names beginning with this prefix will not be mangled
+#define GR_NO_MANGLE_PREFIX "sk_"
+
class GrGLSLProgramBuilder;
class GrGLSLUniformHandler {
@@ -51,7 +54,8 @@ public:
int arrayCount,
const char** outName = nullptr) {
SkASSERT(!GrSLTypeIsCombinedSamplerType(type));
- return this->internalAddUniformArray(visibility, type, precision, name, true, arrayCount,
+ bool mangle = strncmp(name, GR_NO_MANGLE_PREFIX, strlen(GR_NO_MANGLE_PREFIX));
+ return this->internalAddUniformArray(visibility, type, precision, name, mangle, arrayCount,
outName);
}
@@ -61,7 +65,8 @@ public:
int arrayCount,
const char** outName = nullptr) {
SkASSERT(!GrSLTypeIsCombinedSamplerType(type));
- return this->internalAddUniformArray(visibility, type, kDefault_GrSLPrecision, name, true,
+ bool mangle = strncmp(name, GR_NO_MANGLE_PREFIX, strlen(GR_NO_MANGLE_PREFIX));
+ return this->internalAddUniformArray(visibility, type, kDefault_GrSLPrecision, name, mangle,
arrayCount, outName);
}
diff --git a/src/gpu/glsl/GrGLSLVertexGeoBuilder.cpp b/src/gpu/glsl/GrGLSLVertexGeoBuilder.cpp
index 1cf85f7249..dba57bb8a5 100644
--- a/src/gpu/glsl/GrGLSLVertexGeoBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLVertexGeoBuilder.cpp
@@ -23,16 +23,14 @@ void GrGLSLVertexGeoBuilder::emitNormalizedSkPosition(SkString* out, const char*
out->appendf("{float2 _posTmp = %s;", devPos);
}
out->appendf("_posTmp = floor(_posTmp) + half2(0.5, 0.5);"
- "sk_Position = float4(_posTmp.x * %s.x + %s.y,"
- "_posTmp.y * %s.z + %s.w, 0, 1);}",
- rtAdjustName, rtAdjustName, rtAdjustName, rtAdjustName);
+ "sk_Position = float4(_posTmp, 0, 1);}");
} else if (kFloat3_GrSLType == devPosType) {
- out->appendf("sk_Position = float4(dot(%s.xz, %s.xy), dot(%s.yz, %s.zw), 0, %s.z);",
- devPos, rtAdjustName, devPos, rtAdjustName, devPos);
+ out->appendf("sk_Position = float4(%s.x , %s.y, 0, %s.z);",
+ devPos, devPos, devPos);
} else {
SkASSERT(kFloat2_GrSLType == devPosType);
- out->appendf("sk_Position = float4(%s.x * %s.x + %s.y, %s.y * %s.z + %s.w, 0, 1);",
- devPos, rtAdjustName, rtAdjustName, devPos, rtAdjustName, rtAdjustName);
+ out->appendf("sk_Position = float4(%s.x , %s.y, 0, 1);",
+ devPos, devPos);
}
}
diff --git a/src/gpu/vk/GrVkUniformHandler.cpp b/src/gpu/vk/GrVkUniformHandler.cpp
index 040926e314..e76cbda959 100644
--- a/src/gpu/vk/GrVkUniformHandler.cpp
+++ b/src/gpu/vk/GrVkUniformHandler.cpp
@@ -203,7 +203,7 @@ GrGLSLUniformHandler::UniformHandle GrVkUniformHandler::internalAddUniformArray(
// uniform view matrix, they should upload the view matrix in their setData along with regular
// uniforms.
char prefix = 'u';
- if ('u' == name[0]) {
+ if ('u' == name[0] || !strncmp(name, GR_NO_MANGLE_PREFIX, strlen(GR_NO_MANGLE_PREFIX))) {
prefix = '\0';
}
fProgramBuilder->nameVariable(uni.fVariable.accessName(), prefix, name, mangleName);
diff --git a/src/sksl/README b/src/sksl/README
index 7c2cf04551..e9e46566a8 100644
--- a/src/sksl/README
+++ b/src/sksl/README
@@ -38,7 +38,8 @@ Differences from GLSL
'do_something_else();', depending on whether that cap is enabled or not.
* no #version statement is required, and it will be ignored if present
* the output color is sk_FragColor (do not declare it)
-* use sk_Position instead of gl_Position
+* use sk_Position instead of gl_Position. sk_Position is in device coordinates
+ rather than normalized coordinates.
* use sk_PointSize instead of gl_PointSize
* use sk_VertexID instead of gl_VertexID
* use sk_InstanceID instead of gl_InstanceID
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index bf321c8e1e..7589da98ee 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -200,7 +200,8 @@ Compiler::Compiler(Flags flags)
fIRGenerator->fSymbolTable->add(skArgsName, std::unique_ptr<Symbol>(skArgs));
std::vector<std::unique_ptr<ProgramElement>> ignored;
- fIRGenerator->convertProgram(SKSL_INCLUDE, strlen(SKSL_INCLUDE), *fTypes, &ignored);
+ fIRGenerator->convertProgram(Program::kFragment_Kind, SKSL_INCLUDE, strlen(SKSL_INCLUDE),
+ *fTypes, &ignored);
fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
if (fErrorCount) {
printf("Unexpected errors: %s\n", fErrorText.c_str());
@@ -1164,19 +1165,19 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex
std::vector<std::unique_ptr<ProgramElement>> elements;
switch (kind) {
case Program::kVertex_Kind:
- fIRGenerator->convertProgram(SKSL_VERT_INCLUDE, strlen(SKSL_VERT_INCLUDE), *fTypes,
- &elements);
+ fIRGenerator->convertProgram(kind, SKSL_VERT_INCLUDE, strlen(SKSL_VERT_INCLUDE),
+ *fTypes, &elements);
break;
case Program::kFragment_Kind:
- fIRGenerator->convertProgram(SKSL_FRAG_INCLUDE, strlen(SKSL_FRAG_INCLUDE), *fTypes,
- &elements);
+ fIRGenerator->convertProgram(kind, SKSL_FRAG_INCLUDE, strlen(SKSL_FRAG_INCLUDE),
+ *fTypes, &elements);
break;
case Program::kGeometry_Kind:
- fIRGenerator->convertProgram(SKSL_GEOM_INCLUDE, strlen(SKSL_GEOM_INCLUDE), *fTypes,
- &elements);
+ fIRGenerator->convertProgram(kind, SKSL_GEOM_INCLUDE, strlen(SKSL_GEOM_INCLUDE),
+ *fTypes, &elements);
break;
case Program::kFragmentProcessor_Kind:
- fIRGenerator->convertProgram(SKSL_FP_INCLUDE, strlen(SKSL_FP_INCLUDE), *fTypes,
+ fIRGenerator->convertProgram(kind, SKSL_FP_INCLUDE, strlen(SKSL_FP_INCLUDE), *fTypes,
&elements);
break;
}
@@ -1188,7 +1189,7 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String tex
}
std::unique_ptr<String> textPtr(new String(std::move(text)));
fSource = textPtr.get();
- fIRGenerator->convertProgram(textPtr->c_str(), textPtr->size(), *fTypes, &elements);
+ fIRGenerator->convertProgram(kind, textPtr->c_str(), textPtr->size(), *fTypes, &elements);
if (!fErrorCount) {
for (auto& element : elements) {
if (element->fKind == ProgramElement::kFunction_Kind) {
diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h
index ca39c8c659..eb2fc45b51 100644
--- a/src/sksl/SkSLCompiler.h
+++ b/src/sksl/SkSLCompiler.h
@@ -45,6 +45,9 @@ class IRGenerator;
*/
class Compiler : public ErrorReporter {
public:
+ static constexpr const char* RTADJUST_NAME = "sk_RTAdjust";
+ static constexpr const char* PERVERTEX_NAME = "sk_PerVertex";
+
enum Flags {
kNone_Flags = 0,
// permits static if/switch statements to be used with non-constant tests. This is used when
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index 019aee8eaa..3388a4758d 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -154,6 +154,9 @@ void IRGenerator::start(const Program::Settings* settings) {
this->pushSymbolTable();
fInvocations = -1;
fInputs.reset();
+ fSkPerVertex = nullptr;
+ fRTAdjust = nullptr;
+ fRTAdjustInterfaceBlock = nullptr;
}
void IRGenerator::finish() {
@@ -171,8 +174,26 @@ std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTStatement& sta
return this->convertBlock((ASTBlock&) statement);
case ASTStatement::kVarDeclaration_Kind:
return this->convertVarDeclarationStatement((ASTVarDeclarationStatement&) statement);
- case ASTStatement::kExpression_Kind:
- return this->convertExpressionStatement((ASTExpressionStatement&) statement);
+ case ASTStatement::kExpression_Kind: {
+ std::unique_ptr<Statement> result =
+ this->convertExpressionStatement((ASTExpressionStatement&) statement);
+ if (fRTAdjust && Program::kGeometry_Kind == fKind) {
+ ASSERT(result->fKind == Statement::kExpression_Kind);
+ Expression& expr = *((ExpressionStatement&) *result).fExpression;
+ if (expr.fKind == Expression::kFunctionCall_Kind) {
+ FunctionCall& fc = (FunctionCall&) expr;
+ if (fc.fFunction.fBuiltin && fc.fFunction.fName == "EmitVertex") {
+ std::vector<std::unique_ptr<Statement>> statements;
+ statements.push_back(getNormalizeSkPositionCode());
+ statements.push_back(std::move(result));
+ return std::unique_ptr<Block>(new Block(statement.fOffset,
+ std::move(statements),
+ fSymbolTable));
+ }
+ }
+ }
+ return result;
+ }
case ASTStatement::kIf_Kind:
return this->convertIf((ASTIfStatement&) statement);
case ASTStatement::kFor_Kind:
@@ -257,6 +278,11 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa
}
auto var = std::unique_ptr<Variable>(new Variable(decl.fOffset, decl.fModifiers,
varDecl.fName, *type, storage));
+ if (var->fName == Compiler::RTADJUST_NAME) {
+ ASSERT(!fRTAdjust);
+ ASSERT(var->fType == *fContext.fFloat4_Type);
+ fRTAdjust = var.get();
+ }
std::unique_ptr<Expression> value;
if (varDecl.fValue) {
value = this->convertExpression(*varDecl.fValue);
@@ -472,6 +498,10 @@ std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(
std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTReturnStatement& r) {
ASSERT(fCurrentFunction);
+ // early returns from a vertex main function will bypass the sk_Position normalization, so
+ // assert that we aren't doing that. It is of course possible to fix this by adding a
+ // normalization before each return, but it will probably never actually be necessary.
+ ASSERT(Program::kVertex_Kind != fKind || !fRTAdjust || "main" != fCurrentFunction->fName);
if (r.fExpression) {
std::unique_ptr<Expression> result = this->convertExpression(*r.fExpression);
if (!result) {
@@ -575,6 +605,40 @@ std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<
return std::unique_ptr<Block>(new Block(-1, std::move(children)));
}
+std::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() {
+ // sk_Position = float4(sk_Position.x * rtAdjust.x + sk_Position.w * rtAdjust.y,
+ // sk_Position.y * rtAdjust.z + sk_Position.w * rtAdjust.w,
+ // 0,
+ // sk_Position.w);
+ ASSERT(fSkPerVertex && fRTAdjust);
+ #define REF(var) std::unique_ptr<Expression>(\
+ new VariableReference(-1, *var, VariableReference::kRead_RefKind))
+ #define FIELD(var, idx) std::unique_ptr<Expression>(\
+ new FieldAccess(REF(var), idx, FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
+ #define POS std::unique_ptr<Expression>(new FieldAccess(REF(fSkPerVertex), 0, \
+ FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
+ #define ADJUST (fRTAdjustInterfaceBlock ? \
+ FIELD(fRTAdjustInterfaceBlock, fRTAdjustFieldIndex) : \
+ REF(fRTAdjust))
+ #define SWIZZLE(expr, field) std::unique_ptr<Expression>(new Swizzle(fContext, expr, { field }))
+ #define OP(left, op, right) std::unique_ptr<Expression>(\
+ new BinaryExpression(-1, left, op, right, *fContext.fFloat_Type))
+ std::vector<std::unique_ptr<Expression>> children;
+ children.push_back(OP(OP(SWIZZLE(POS, 0), Token::STAR, SWIZZLE(ADJUST, 0)),
+ Token::PLUS,
+ OP(SWIZZLE(POS, 3), Token::STAR, SWIZZLE(ADJUST, 1))));
+ children.push_back(OP(OP(SWIZZLE(POS, 1), Token::STAR, SWIZZLE(ADJUST, 2)),
+ Token::PLUS,
+ OP(SWIZZLE(POS, 3), Token::STAR, SWIZZLE(ADJUST, 3))));
+ children.push_back(std::unique_ptr<Expression>(new FloatLiteral(fContext, -1, 0.0)));
+ children.push_back(SWIZZLE(POS, 3));
+ std::unique_ptr<Expression> result = OP(POS, Token::EQ,
+ std::unique_ptr<Expression>(new Constructor(-1,
+ *fContext.fFloat4_Type,
+ std::move(children))));
+ return std::unique_ptr<Statement>(new ExpressionStatement(std::move(result)));
+}
+
void IRGenerator::convertFunction(const ASTFunction& f) {
const Type* returnType = this->convertType(*f.fReturnType);
if (!returnType) {
@@ -691,7 +755,9 @@ void IRGenerator::convertFunction(const ASTFunction& f) {
}
// conservatively assume all user-defined functions have side effects
((Modifiers&) decl->fModifiers).fFlags |= Modifiers::kHasSideEffects_Flag;
-
+ if (Program::kVertex_Kind == fKind && f.fName == "main" && fRTAdjust) {
+ body->fStatements.insert(body->fStatements.end(), this->getNormalizeSkPositionCode());
+ }
fProgramElements->push_back(std::unique_ptr<FunctionDefinition>(
new FunctionDefinition(f.fOffset, *decl, std::move(body))));
}
@@ -702,6 +768,7 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte
AutoSymbolTable table(this);
std::vector<Type::Field> fields;
bool haveRuntimeArray = false;
+ bool foundRTAdjust = false;
for (size_t i = 0; i < intf.fDeclarations.size(); i++) {
std::unique_ptr<VarDeclarations> decl = this->convertVarDeclarations(
*intf.fDeclarations[i],
@@ -716,6 +783,11 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte
"only the last entry in an interface block may be a runtime-sized "
"array");
}
+ if (vd.fVar == fRTAdjust) {
+ foundRTAdjust = true;
+ ASSERT(vd.fVar->fType == *fContext.fFloat4_Type);
+ fRTAdjustFieldIndex = fields.size();
+ }
fields.push_back(Type::Field(vd.fVar->fModifiers, vd.fVar->fName,
&vd.fVar->fType));
if (vd.fValue) {
@@ -769,6 +841,9 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte
Variable* var = new Variable(intf.fOffset, intf.fModifiers,
intf.fInstanceName.fLength ? intf.fInstanceName : intf.fTypeName,
*type, Variable::kGlobal_Storage);
+ if (foundRTAdjust) {
+ fRTAdjustInterfaceBlock = var;
+ }
old->takeOwnership(var);
if (intf.fInstanceName.fLength) {
old->addWithoutOwnership(intf.fInstanceName, var);
@@ -778,6 +853,10 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte
(int) i)));
}
}
+ if (var->fName == Compiler::PERVERTEX_NAME) {
+ ASSERT(!fSkPerVertex);
+ fSkPerVertex = var;
+ }
return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fOffset,
var,
intf.fTypeName,
@@ -2027,10 +2106,12 @@ void IRGenerator::markWrittenTo(const Expression& expr, bool readWrite) {
}
}
-void IRGenerator::convertProgram(const char* text,
+void IRGenerator::convertProgram(Program::Kind kind,
+ const char* text,
size_t length,
SymbolTable& types,
std::vector<std::unique_ptr<ProgramElement>>* out) {
+ fKind = kind;
fProgramElements = out;
Parser parser(text, length, types, fErrors);
std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file();
diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h
index 1df9b65bd0..327fe6fc7a 100644
--- a/src/sksl/SkSLIRGenerator.h
+++ b/src/sksl/SkSLIRGenerator.h
@@ -62,7 +62,8 @@ public:
IRGenerator(const Context* context, std::shared_ptr<SymbolTable> root,
ErrorReporter& errorReporter);
- void convertProgram(const char* text,
+ void convertProgram(Program::Kind kind,
+ const char* text,
size_t length,
SymbolTable& types,
std::vector<std::unique_ptr<ProgramElement>>* result);
@@ -156,12 +157,15 @@ private:
std::unique_ptr<Statement> convertWhile(const ASTWhileStatement& w);
void convertEnum(const ASTEnum& e);
std::unique_ptr<Block> applyInvocationIDWorkaround(std::unique_ptr<Block> main);
+ // returns a statement which converts sk_Position from device to normalized coordinates
+ std::unique_ptr<Statement> getNormalizeSkPositionCode();
void fixRectSampling(std::vector<std::unique_ptr<Expression>>& arguments);
void checkValid(const Expression& expr);
void markWrittenTo(const Expression& expr, bool readWrite);
void getConstantInt(const Expression& value, int64_t* out);
+ Program::Kind fKind;
const FunctionDeclaration* fCurrentFunction;
std::unordered_map<String, Program::Settings::Value> fCapsMap;
std::shared_ptr<SymbolTable> fRootSymbolTable;
@@ -175,6 +179,10 @@ private:
ErrorReporter& fErrors;
int fInvocations;
std::vector<std::unique_ptr<ProgramElement>>* fProgramElements;
+ Variable* fSkPerVertex;
+ Variable* fRTAdjust;
+ Variable* fRTAdjustInterfaceBlock;
+ int fRTAdjustFieldIndex;
friend class AutoSymbolTable;
friend class AutoLoopLevel;
diff --git a/tests/SkSLGLSLTest.cpp b/tests/SkSLGLSLTest.cpp
index 53710c9516..62c5cd6955 100644
--- a/tests/SkSLGLSLTest.cpp
+++ b/tests/SkSLGLSLTest.cpp
@@ -1072,6 +1072,21 @@ DEF_TEST(SkSLFragCoord, r) {
SkSL::Program::kVertex_Kind);
test(r,
+ "in uniform float4 sk_RTAdjust; in float4 pos; void main() { sk_Position = pos; }",
+ *SkSL::ShaderCapsFactory::CannotUseFragCoord(),
+ "#version 400\n"
+ "out vec4 sk_FragCoord_Workaround;\n"
+ "in uniform vec4 sk_RTAdjust;\n"
+ "in vec4 pos;\n"
+ "void main() {\n"
+ " sk_FragCoord_Workaround = (gl_Position = pos);\n"
+ " gl_Position = vec4(gl_Position.x * sk_RTAdjust.x + gl_Position.w * sk_RTAdjust.y, "
+ "gl_Position.y * sk_RTAdjust.z + gl_Position.w * sk_RTAdjust.w, 0.0, "
+ "gl_Position.w);\n"
+ "}\n",
+ SkSL::Program::kVertex_Kind);
+
+ test(r,
"void main() { sk_FragColor.xy = sk_FragCoord.xy; }",
*SkSL::ShaderCapsFactory::CannotUseFragCoord(),
"#version 400\n"
@@ -1739,6 +1754,58 @@ DEF_TEST(SkSLForceHighPrecision, r) {
&inputs);
}
+DEF_TEST(SkSLNormalization, r) {
+ test(r,
+ "uniform float4 sk_RTAdjust; void main() { sk_Position = half4(1); }",
+ *SkSL::ShaderCapsFactory::Default(),
+ "#version 400\n"
+ "uniform vec4 sk_RTAdjust;\n"
+ "void main() {\n"
+ " gl_Position = vec4(1.0);\n"
+ " gl_Position = vec4(gl_Position.x * sk_RTAdjust.x + gl_Position.w * sk_RTAdjust.y, "
+ "gl_Position.y * sk_RTAdjust.z + gl_Position.w * sk_RTAdjust.w, "
+ "0.0, "
+ "gl_Position.w);\n"
+ "}\n",
+ SkSL::Program::kVertex_Kind);
+ test(r,
+ "uniform float4 sk_RTAdjust;"
+ "layout(points) in;"
+ "layout(invocations = 2) in;"
+ "layout(line_strip, max_vertices = 2) out;"
+ "void main() {"
+ "sk_Position = sk_in[0].sk_Position + float4(-0.5, 0, 0, sk_InvocationID);"
+ "EmitVertex();"
+ "sk_Position = sk_in[0].sk_Position + float4(0.5, 0, 0, sk_InvocationID);"
+ "EmitVertex();"
+ "EndPrimitive();"
+ "}",
+ *SkSL::ShaderCapsFactory::GeometryShaderSupport(),
+ "#version 400\n"
+ "uniform vec4 sk_RTAdjust;\n"
+ "layout (points) in ;\n"
+ "layout (invocations = 2) in ;\n"
+ "layout (line_strip, max_vertices = 2) out ;\n"
+ "void main() {\n"
+ " gl_Position = gl_in[0].gl_Position + vec4(-0.5, 0.0, 0.0, float(gl_InvocationID));\n"
+ " {\n"
+ " gl_Position = vec4(gl_Position.x * sk_RTAdjust.x + gl_Position.w * "
+ "sk_RTAdjust.y, gl_Position.y * sk_RTAdjust.z + gl_Position.w * "
+ "sk_RTAdjust.w, 0.0, gl_Position.w);\n"
+ " EmitVertex();\n"
+ " }\n"
+ " gl_Position = gl_in[0].gl_Position + vec4(0.5, 0.0, 0.0, float(gl_InvocationID));\n"
+ " {\n"
+ " gl_Position = vec4(gl_Position.x * sk_RTAdjust.x + gl_Position.w * "
+ "sk_RTAdjust.y, gl_Position.y * sk_RTAdjust.z + gl_Position.w * "
+ "sk_RTAdjust.w, 0.0, gl_Position.w);\n"
+ " EmitVertex();\n"
+ " }\n"
+ " EndPrimitive();\n"
+ "}\n",
+ SkSL::Program::kGeometry_Kind);
+}
+
DEF_TEST(SkSLTernaryLValue, r) {
test(r,
"void main() { half r, g; (true ? r : g) = 1; (false ? r : g) = 0; "