Don't let shaders negate samplers
Prior to this change, the OpenGL compiler accepted all "non-struct"
"non-array" types for unary operations (++, --, and -). This ignored
the existence of sampler objects. If someone tried to negate a
sampler, then the compiler would tell the assembler to negate a non-
numerical type.
This change makes it so the GSL compiler only accepts unary operations
on numerical types (including vectors and matrices).
Also added a unittest that makes sure we gracefully fail to compile
bad unary operations.
Bug chromium:910883
Change-Id: Ia69056b31664900c3126cab42ecb8603d1a5d7db
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/32448
Tested-by: Sean Risser <srisser@google.com>
Presubmit-Ready: Sean Risser <srisser@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/OpenGL/compiler/Intermediate.cpp b/src/OpenGL/compiler/Intermediate.cpp
index 9f68dc7..2c47256 100644
--- a/src/OpenGL/compiler/Intermediate.cpp
+++ b/src/OpenGL/compiler/Intermediate.cpp
@@ -497,7 +497,7 @@
case EOpPostDecrement:
case EOpPreDecrement:
case EOpNegative:
- if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
+ if (!child->getType().isScalar() && !child->getType().isVector() && !child->getType().isMatrix())
return 0;
default: break;
}
diff --git a/src/OpenGL/compiler/Types.h b/src/OpenGL/compiler/Types.h
index e031f9b..846b240 100644
--- a/src/OpenGL/compiler/Types.h
+++ b/src/OpenGL/compiler/Types.h
@@ -444,7 +444,7 @@
TInterfaceBlock *getAsInterfaceBlock() const { return isInterfaceBlock() ? getInterfaceBlock() : nullptr; }
bool isVector() const { return primarySize > 1 && !isMatrix(); }
- bool isScalar() const { return primarySize == 1 && !isMatrix() && !structure && !isInterfaceBlock(); }
+ bool isScalar() const { return primarySize == 1 && !isMatrix() && !structure && !isInterfaceBlock() && !IsSampler(getBasicType()); }
bool isRegister() const { return !isMatrix() && !structure && !array && !isInterfaceBlock(); } // Fits in a 4-element register
bool isStruct() const { return structure != 0; }
bool isScalarInt() const { return isScalar() && IsInteger(type); }
diff --git a/tests/GLESUnitTests/unittests.cpp b/tests/GLESUnitTests/unittests.cpp
index f01b93b..45d92ce 100644
--- a/tests/GLESUnitTests/unittests.cpp
+++ b/tests/GLESUnitTests/unittests.cpp
@@ -381,23 +381,26 @@
checkCompiles("", s);
}
- void checkCompileFails(GLuint glShader, std::string source)
+ void checkCompileFails(GLenum glShaderType, std::string source)
{
- GLchar buf[1024];
+ Initialize(3, false);
+
GLint compileStatus = 0;
const char *c_source[1] = { source.c_str() };
+ GLuint glShader = glCreateShader(glShaderType);
glShaderSource(glShader, 1, c_source, nullptr);
glCompileShader(glShader);
- EXPECT_GLENUM_EQ(GL_NONE, glGetError());
+ EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
glGetShaderiv(glShader, GL_COMPILE_STATUS, &compileStatus);
- glGetShaderInfoLog(glShader, sizeof(buf), nullptr, buf);
- EXPECT_EQ(compileStatus, GL_FALSE) << "Compile status: " << std::endl << buf;
+ EXPECT_EQ(compileStatus, GL_FALSE);
glDeleteShader(glShader);
+
+ Uninitialize();
}
void checkCompileFails(std::string s)
@@ -429,8 +432,8 @@
vs = replace(vs, "$INSERT", s);
fs = replace(fs, "$INSERT", s);
- checkCompileFails(glCreateShader(GL_VERTEX_SHADER), vs);
- checkCompileFails(glCreateShader(GL_FRAGMENT_SHADER), fs);
+ checkCompileFails(GL_VERTEX_SHADER, vs);
+ checkCompileFails(GL_FRAGMENT_SHADER, fs);
}
EGLDisplay getDisplay() const { return display; }
@@ -1823,8 +1826,6 @@
// GL_MAX_{VERTEX/FRAGMENT}_UNIFORM_VECTOR.
TEST_F(SwiftShaderTest, CompilerLimits_ArraySize)
{
- Initialize(3, false);
-
checkCompileFails(
"uniform float u_var[100000000];\n"
"float F(float f) { return u_var[2]; }\n");
@@ -1832,8 +1833,35 @@
"struct structType { mediump sampler2D m0; mediump samplerCube m1; }; \n"
"uniform structType u_var[100000000];\n"
"float F(float f) { return texture(u_var[2].m1, vec3(0.0)), vec4(0.26, 1.72, 0.60, 0.12).x; }\n");
+}
- Uninitialize();
+// Test that the compiler rejects negations of things that can't be negated.
+TEST_F(SwiftShaderTest, BadNegation)
+{
+ checkCompileFails(
+ "uniform samplerCube m;\n"
+ "float F (float f) { vec4 ret = texture(-m, vec3(f)); return ret.x; }\n"
+ );
+ checkCompileFails(
+ "uniform sampler2D m[9];\n"
+ "vec4 G (sampler2D X[9]) { return texture(X[0], vec2(0.0f)); }"
+ "float F (float f) { vec4 ret = G(-m); return ret.x; }\n"
+ );
+ checkCompileFails(
+ "struct structType { int a; float b; };\n"
+ "uniform structType m;\n"
+ "float F (float f) { structType n = -m; return f; }\n"
+ );
+ checkCompileFails(
+ "struct structType { int a; float b; };\n"
+ "uniform structType m[4];\n"
+ "float F (float f) { structType n[4] = -m; return f; }\n"
+ );
+ checkCompileFails(
+ "uniform float m[4];\n"
+ "float G (float f[4]) { return f[0]; }\n"
+ "float F (float f) { return G(-m); }\n"
+ );
}
#ifndef EGL_ANGLE_iosurface_client_buffer