Add $es3 modifier to SkSL.
This modifier is currently allowed on built-in functions only.
The presence of this modifier will be used to indicate intrinsics which
are ES3-specific (and therefore, not allowed in user code under typical
circumstances).
Change-Id: Ice6be8d9d1b2bf0c8f07f2a89f335bb2f90f6681
Bug: skia:12202
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/439057
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/gn/sksl_tests.gni b/gn/sksl_tests.gni
index 45d4225..2649970 100644
--- a/gn/sksl_tests.gni
+++ b/gn/sksl_tests.gni
@@ -76,6 +76,7 @@
"/sksl/errors/MatrixToVectorCastTooSmall.sksl",
"/sksl/errors/MismatchedNumbers.sksl",
"/sksl/errors/ModifiersInStruct.sksl",
+ "/sksl/errors/NoES3ModifierInUserCode.sksl",
"/sksl/errors/OpaqueTypeAssignment.sksl",
"/sksl/errors/OpaqueTypeConstruction.sksl",
"/sksl/errors/OpaqueTypeInArray.sksl",
diff --git a/include/private/SkSLModifiers.h b/include/private/SkSLModifiers.h
index aca2484..8a129b2 100644
--- a/include/private/SkSLModifiers.h
+++ b/include/private/SkSLModifiers.h
@@ -32,6 +32,7 @@
kLowp_Flag = 1 << 9,
kInline_Flag = 1 << 10,
kNoInline_Flag = 1 << 11,
+ kES3_Flag = 1 << 12,
};
Modifiers()
@@ -44,6 +45,9 @@
String description() const {
String result = fLayout.description();
+ if (fFlags & kES3_Flag) {
+ result += "$es3 ";
+ }
if (fFlags & kUniform_Flag) {
result += "uniform ";
}
diff --git a/resources/sksl/errors/NoES3ModifierInUserCode.sksl b/resources/sksl/errors/NoES3ModifierInUserCode.sksl
new file mode 100644
index 0000000..f9ce51b
--- /dev/null
+++ b/resources/sksl/errors/NoES3ModifierInUserCode.sksl
@@ -0,0 +1,2 @@
+$es3 void fn() {}
+
diff --git a/src/sksl/SkSLDSLParser.cpp b/src/sksl/SkSLDSLParser.cpp
index bca062c..debccf6 100644
--- a/src/sksl/SkSLDSLParser.cpp
+++ b/src/sksl/SkSLDSLParser.cpp
@@ -36,6 +36,7 @@
case Token::Kind::TK_HIGHP: return Modifiers::kHighp_Flag;
case Token::Kind::TK_MEDIUMP: return Modifiers::kMediump_Flag;
case Token::Kind::TK_LOWP: return Modifiers::kLowp_Flag;
+ case Token::Kind::TK_ES3: return Modifiers::kES3_Flag;
default: return 0;
}
}
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index d0b1bc0..1e643bd 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -742,6 +742,7 @@
{ Modifiers::kHighp_Flag, "highp" },
{ Modifiers::kMediump_Flag, "mediump" },
{ Modifiers::kLowp_Flag, "lowp" },
+ { Modifiers::kES3_Flag, "$es3" },
};
int modifierFlags = modifiers.fFlags;
@@ -1335,6 +1336,9 @@
*/
CoercionCost IRGenerator::callCost(const FunctionDeclaration& function,
const ExpressionArray& arguments) {
+ if (this->strictES2Mode() && (function.modifiers().fFlags & Modifiers::kES3_Flag)) {
+ return CoercionCost::Impossible();
+ }
if (function.parameters().size() != arguments.size()) {
return CoercionCost::Impossible();
}
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp
index df9b479..316c0fd 100644
--- a/src/sksl/SkSLParser.cpp
+++ b/src/sksl/SkSLParser.cpp
@@ -55,6 +55,7 @@
case Token::Kind::TK_HIGHP: return Modifiers::kHighp_Flag;
case Token::Kind::TK_MEDIUMP: return Modifiers::kMediump_Flag;
case Token::Kind::TK_LOWP: return Modifiers::kLowp_Flag;
+ case Token::Kind::TK_ES3: return Modifiers::kES3_Flag;
default: return 0;
}
}
diff --git a/src/sksl/ir/SkSLFunctionCall.cpp b/src/sksl/ir/SkSLFunctionCall.cpp
index 38f364f..02677d6 100644
--- a/src/sksl/ir/SkSLFunctionCall.cpp
+++ b/src/sksl/ir/SkSLFunctionCall.cpp
@@ -738,6 +738,12 @@
int offset,
const FunctionDeclaration& function,
ExpressionArray arguments) {
+ // Reject ES3 function calls in strict ES2 mode.
+ if (context.fConfig->strictES2Mode() && (function.modifiers().fFlags & Modifiers::kES3_Flag)) {
+ context.errors().error(offset, "call to '" + function.description() + "' is not supported");
+ return nullptr;
+ }
+
// Reject function calls with the wrong number of arguments.
if (function.parameters().size() != arguments.size()) {
String msg = "call to '" + function.name() + "' expected " +
diff --git a/src/sksl/ir/SkSLFunctionDeclaration.cpp b/src/sksl/ir/SkSLFunctionDeclaration.cpp
index 1162b66..7892947 100644
--- a/src/sksl/ir/SkSLFunctionDeclaration.cpp
+++ b/src/sksl/ir/SkSLFunctionDeclaration.cpp
@@ -28,13 +28,15 @@
return kNotIntrinsic;
}
-static bool check_modifiers(const Context& context, int offset, const Modifiers& modifiers) {
- IRGenerator::CheckModifiers(
- context,
- offset,
- modifiers,
- Modifiers::kHasSideEffects_Flag | Modifiers::kInline_Flag | Modifiers::kNoInline_Flag,
- /*permittedLayoutFlags=*/0);
+static bool check_modifiers(const Context& context,
+ int offset,
+ const Modifiers& modifiers,
+ bool isBuiltin) {
+ const int permitted = Modifiers::kHasSideEffects_Flag |
+ Modifiers::kInline_Flag |
+ Modifiers::kNoInline_Flag |
+ (isBuiltin ? Modifiers::kES3_Flag : 0);
+ IRGenerator::CheckModifiers(context, offset, modifiers, permitted, /*permittedLayoutFlags=*/0);
if ((modifiers.fFlags & Modifiers::kInline_Flag) &&
(modifiers.fFlags & Modifiers::kNoInline_Flag)) {
context.errors().error(offset, "functions cannot be both 'inline' and 'noinline'");
@@ -312,7 +314,7 @@
bool isMain = (name == "main");
const FunctionDeclaration* decl = nullptr;
- if (!check_modifiers(context, offset, *modifiers) ||
+ if (!check_modifiers(context, offset, *modifiers, isBuiltin) ||
!check_return_type(context, offset, *returnType, isBuiltin) ||
!check_parameters(context, parameters, isMain, isBuiltin) ||
(isMain && !check_main_signature(context, offset, *returnType, parameters, isBuiltin)) ||
diff --git a/tests/sksl/errors/NoES3ModifierInUserCode.glsl b/tests/sksl/errors/NoES3ModifierInUserCode.glsl
new file mode 100644
index 0000000..5192933
--- /dev/null
+++ b/tests/sksl/errors/NoES3ModifierInUserCode.glsl
@@ -0,0 +1,4 @@
+### Compilation failed:
+
+error: 1: '$es3' is not permitted here
+1 error