[sksl] Disallow boolean uniforms
Booleans and structs/interface blocks that transitively contain a boolean member are no longer allowed to be used as a uniform. This is because SPIR-V and WGSL currently disallow OpTypeBool in host-shareable storage classes. Change-Id: I10315c7f261ff10a07636265968a91d9c421da55 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/542776 Reviewed-by: Brian Osman <brianosman@google.com> Reviewed-by: John Stiles <johnstiles@google.com> Commit-Queue: Arman Uguray <armansito@google.com>
This commit is contained in:
parent
3aed21ce0e
commit
bd969a089d
@ -80,6 +80,7 @@ sksl_error_tests = [
|
||||
"/sksl/errors/InvalidOutParams.rts",
|
||||
"/sksl/errors/InvalidToken.rts",
|
||||
"/sksl/errors/InvalidUnary.rts",
|
||||
"/sksl/errors/InvalidUniformTypes.sksl",
|
||||
"/sksl/errors/InVarWithInitializerExpression.sksl",
|
||||
"/sksl/errors/LayoutInFunctions.sksl",
|
||||
"/sksl/errors/LayoutInInterfaceBlock.sksl",
|
||||
|
41
resources/sksl/errors/InvalidUniformTypes.sksl
Normal file
41
resources/sksl/errors/InvalidUniformTypes.sksl
Normal file
@ -0,0 +1,41 @@
|
||||
uniform short s;
|
||||
uniform short2 s2;
|
||||
uniform short3 s3;
|
||||
uniform short4 s4;
|
||||
|
||||
uniform bool b;
|
||||
uniform bool2 b2;
|
||||
uniform bool3 b3;
|
||||
uniform bool4 b4;
|
||||
|
||||
// Structs and interface blocks are valid SkSL uniforms but their member types are restricted.
|
||||
struct InvalidStruct1 {
|
||||
float f; // valid
|
||||
bool b; // invalid
|
||||
};
|
||||
|
||||
struct InvalidStruct2 {
|
||||
InvalidStruct1 s;
|
||||
};
|
||||
|
||||
uniform InvalidStruct1 st1;
|
||||
uniform InvalidStruct2 st2;
|
||||
|
||||
uniform invalidBlock {
|
||||
float f; // valid
|
||||
bool b; // invalid
|
||||
} ib;
|
||||
|
||||
half4 main(float2 coords) {
|
||||
return half4(0);
|
||||
}
|
||||
|
||||
/*%%*
|
||||
variables of type 'bool' may not be uniform
|
||||
variables of type 'bool2' may not be uniform
|
||||
variables of type 'bool3' may not be uniform
|
||||
variables of type 'bool4' may not be uniform
|
||||
variables of type 'bool' may not be uniform
|
||||
variables of type 'bool' may not be uniform
|
||||
variables of type 'bool' may not be uniform
|
||||
*%%*/
|
@ -1,11 +1,11 @@
|
||||
/*#pragma settings UnfoldShortCircuitAsTernary*/
|
||||
|
||||
uniform bool x;
|
||||
uniform bool y;
|
||||
uniform int i;
|
||||
uniform int j;
|
||||
|
||||
void main() {
|
||||
bool x = bool(i);
|
||||
bool y = bool(j);
|
||||
bool andXY = x && y;
|
||||
bool orXY = x || y;
|
||||
bool combo = (x && y) || (x || y);
|
||||
|
@ -15,7 +15,57 @@
|
||||
#include "src/sksl/SkSLThreadContext.h"
|
||||
|
||||
namespace SkSL {
|
||||
namespace {
|
||||
|
||||
static bool check_valid_uniform_type(Position pos,
|
||||
const Type* t,
|
||||
const Context& context,
|
||||
bool topLevel = true) {
|
||||
const Type& ct = t->componentType();
|
||||
|
||||
// In RuntimeEffects we only allow a restricted set of types, namely shader/blender/colorFilter,
|
||||
// 32-bit signed integers, 16-bit and 32-bit floats, and their composites.
|
||||
{
|
||||
bool error = false;
|
||||
if (ProgramConfig::IsRuntimeEffect(context.fConfig->fKind)) {
|
||||
if (t->isEffectChild() ||
|
||||
((t->isScalar() || t->isVector()) && ct.isSigned() && ct.bitWidth() == 32) ||
|
||||
((t->isScalar() || t->isVector() || t->isMatrix()) && ct.isFloat())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Everything else is an error.
|
||||
error = true;
|
||||
}
|
||||
|
||||
// We disallow boolean uniforms in SkSL since they are not well supported by backend
|
||||
// platforms and drivers.
|
||||
if (error || (ct.isBoolean() && (t->isScalar() || t->isVector()))) {
|
||||
context.fErrors->error(
|
||||
pos, "variables of type '" + t->displayName() + "' may not be uniform");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// In non-RTE SkSL we allow structs and interface blocks to be uniforms but we must make sure
|
||||
// their fields are allowed.
|
||||
if (t->isStruct()) {
|
||||
for (const Type::Field& field : t->fields()) {
|
||||
if (!check_valid_uniform_type(
|
||||
field.fPosition, field.fType, context, /*topLevel=*/false)) {
|
||||
// Emit a "caused by" line only for the top-level uniform type and not for any
|
||||
// nested structs.
|
||||
if (topLevel) {
|
||||
context.fErrors->error(pos, "caused by:");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<Statement> VarDeclaration::clone() const {
|
||||
// Cloning a VarDeclaration is inherently problematic, as we normally expect a one-to-one
|
||||
@ -85,23 +135,13 @@ void VarDeclaration::ErrorCheck(const Context& context,
|
||||
if ((modifiers.fFlags & Modifiers::kIn_Flag) && (modifiers.fFlags & Modifiers::kUniform_Flag)) {
|
||||
context.fErrors->error(pos, "'in uniform' variables not permitted");
|
||||
}
|
||||
if ((modifiers.fFlags & Modifiers::kUniform_Flag)) {
|
||||
check_valid_uniform_type(pos, baseType, context);
|
||||
}
|
||||
if (ProgramConfig::IsRuntimeEffect(context.fConfig->fKind)) {
|
||||
if (modifiers.fFlags & Modifiers::kIn_Flag) {
|
||||
context.fErrors->error(pos, "'in' variables not permitted in runtime effects");
|
||||
}
|
||||
if (modifiers.fFlags & Modifiers::kUniform_Flag) {
|
||||
auto validUniformType = [](const Type& t) {
|
||||
const Type& ct = t.componentType();
|
||||
return t.isEffectChild() ||
|
||||
((t.isScalar() || t.isVector()) && ct.isSigned() && ct.bitWidth() == 32) ||
|
||||
((t.isScalar() || t.isVector() || t.isMatrix()) && ct.isFloat());
|
||||
};
|
||||
if (!validUniformType(*baseType)) {
|
||||
context.fErrors->error(
|
||||
pos,
|
||||
"variables of type '" + baseType->displayName() + "' may not be uniform");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (baseType->isEffectChild() && !(modifiers.fFlags & Modifiers::kUniform_Flag)) {
|
||||
context.fErrors->error(pos,
|
||||
|
33
tests/sksl/errors/InvalidUniformTypes.glsl
Normal file
33
tests/sksl/errors/InvalidUniformTypes.glsl
Normal file
@ -0,0 +1,33 @@
|
||||
### Compilation failed:
|
||||
|
||||
error: 6: variables of type 'bool' may not be uniform
|
||||
uniform bool b;
|
||||
^^^^^^^^^^^^^^^
|
||||
error: 7: variables of type 'bool2' may not be uniform
|
||||
uniform bool2 b2;
|
||||
^^^^^^^^^^^^^^^^
|
||||
error: 8: variables of type 'bool3' may not be uniform
|
||||
uniform bool3 b3;
|
||||
^^^^^^^^^^^^^^^^
|
||||
error: 9: variables of type 'bool4' may not be uniform
|
||||
uniform bool4 b4;
|
||||
^^^^^^^^^^^^^^^^
|
||||
error: 14: variables of type 'bool' may not be uniform
|
||||
bool b; // invalid
|
||||
^^^^^^
|
||||
error: 21: caused by:
|
||||
uniform InvalidStruct1 st1;
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
error: 14: variables of type 'bool' may not be uniform
|
||||
bool b; // invalid
|
||||
^^^^^^
|
||||
error: 22: caused by:
|
||||
uniform InvalidStruct2 st2;
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
error: 26: variables of type 'bool' may not be uniform
|
||||
bool b; // invalid
|
||||
^^^^^^^
|
||||
error: 24: caused by:
|
||||
uniform invalidBlock {
|
||||
^^^^^^^^^^^^
|
||||
10 errors
|
@ -1,10 +1,10 @@
|
||||
#version 400
|
||||
out vec4 sk_FragColor;
|
||||
uniform bool x;
|
||||
uniform bool y;
|
||||
uniform int i;
|
||||
uniform int j;
|
||||
void main() {
|
||||
bool x = bool(i);
|
||||
bool y = bool(j);
|
||||
bool andXY = x ? y : false;
|
||||
bool orXY = x ? true : y;
|
||||
bool combo = (x ? y : false) ? true : (x ? true : y);
|
||||
|
@ -1,10 +1,10 @@
|
||||
|
||||
out vec4 sk_FragColor;
|
||||
uniform bool x;
|
||||
uniform bool y;
|
||||
uniform int i;
|
||||
uniform int j;
|
||||
void main() {
|
||||
bool x = bool(i);
|
||||
bool y = bool(j);
|
||||
bool andXY = x && y;
|
||||
bool orXY = x || y;
|
||||
bool combo = x && y || (x || y);
|
||||
|
Loading…
Reference in New Issue
Block a user