Commit 39f0247a by Sean Risser

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/+/32448Tested-by: 's avatarSean Risser <srisser@google.com> Presubmit-Ready: Sean Risser <srisser@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com>
parent 6dd5f335
...@@ -497,7 +497,7 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, con ...@@ -497,7 +497,7 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, con
case EOpPostDecrement: case EOpPostDecrement:
case EOpPreDecrement: case EOpPreDecrement:
case EOpNegative: case EOpNegative:
if (child->getType().getBasicType() == EbtStruct || child->getType().isArray()) if (!child->getType().isScalar() && !child->getType().isVector() && !child->getType().isMatrix())
return 0; return 0;
default: break; default: break;
} }
......
...@@ -444,7 +444,7 @@ public: ...@@ -444,7 +444,7 @@ public:
TInterfaceBlock *getAsInterfaceBlock() const { return isInterfaceBlock() ? getInterfaceBlock() : nullptr; } TInterfaceBlock *getAsInterfaceBlock() const { return isInterfaceBlock() ? getInterfaceBlock() : nullptr; }
bool isVector() const { return primarySize > 1 && !isMatrix(); } 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 isRegister() const { return !isMatrix() && !structure && !array && !isInterfaceBlock(); } // Fits in a 4-element register
bool isStruct() const { return structure != 0; } bool isStruct() const { return structure != 0; }
bool isScalarInt() const { return isScalar() && IsInteger(type); } bool isScalarInt() const { return isScalar() && IsInteger(type); }
......
...@@ -381,23 +381,26 @@ protected: ...@@ -381,23 +381,26 @@ protected:
checkCompiles("", s); 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; GLint compileStatus = 0;
const char *c_source[1] = { source.c_str() }; const char *c_source[1] = { source.c_str() };
GLuint glShader = glCreateShader(glShaderType);
glShaderSource(glShader, 1, c_source, nullptr); glShaderSource(glShader, 1, c_source, nullptr);
glCompileShader(glShader); glCompileShader(glShader);
EXPECT_GLENUM_EQ(GL_NONE, glGetError()); EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
glGetShaderiv(glShader, GL_COMPILE_STATUS, &compileStatus); 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); glDeleteShader(glShader);
Uninitialize();
} }
void checkCompileFails(std::string s) void checkCompileFails(std::string s)
...@@ -429,8 +432,8 @@ protected: ...@@ -429,8 +432,8 @@ protected:
vs = replace(vs, "$INSERT", s); vs = replace(vs, "$INSERT", s);
fs = replace(fs, "$INSERT", s); fs = replace(fs, "$INSERT", s);
checkCompileFails(glCreateShader(GL_VERTEX_SHADER), vs); checkCompileFails(GL_VERTEX_SHADER, vs);
checkCompileFails(glCreateShader(GL_FRAGMENT_SHADER), fs); checkCompileFails(GL_FRAGMENT_SHADER, fs);
} }
EGLDisplay getDisplay() const { return display; } EGLDisplay getDisplay() const { return display; }
...@@ -1823,8 +1826,6 @@ TEST_F(SwiftShaderTest, CompilerLimits_SparseLabels) ...@@ -1823,8 +1826,6 @@ TEST_F(SwiftShaderTest, CompilerLimits_SparseLabels)
// GL_MAX_{VERTEX/FRAGMENT}_UNIFORM_VECTOR. // GL_MAX_{VERTEX/FRAGMENT}_UNIFORM_VECTOR.
TEST_F(SwiftShaderTest, CompilerLimits_ArraySize) TEST_F(SwiftShaderTest, CompilerLimits_ArraySize)
{ {
Initialize(3, false);
checkCompileFails( checkCompileFails(
"uniform float u_var[100000000];\n" "uniform float u_var[100000000];\n"
"float F(float f) { return u_var[2]; }\n"); "float F(float f) { return u_var[2]; }\n");
...@@ -1832,8 +1833,35 @@ TEST_F(SwiftShaderTest, CompilerLimits_ArraySize) ...@@ -1832,8 +1833,35 @@ TEST_F(SwiftShaderTest, CompilerLimits_ArraySize)
"struct structType { mediump sampler2D m0; mediump samplerCube m1; }; \n" "struct structType { mediump sampler2D m0; mediump samplerCube m1; }; \n"
"uniform structType u_var[100000000];\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"); "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 #ifndef EGL_ANGLE_iosurface_client_buffer
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment