| // | |
| // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| // | |
| // CollectVariables_test.cpp: | |
| // Some tests for shader inspection | |
| // | |
| #include "angle_gl.h" | |
| #include "gtest/gtest.h" | |
| #include "GLSLANG/ShaderLang.h" | |
| namespace sh | |
| { | |
| TEST(ShaderVariableTest, FindInfoByMappedName) | |
| { | |
| // struct A { | |
| // float x[2]; | |
| // vec3 y; | |
| // }; | |
| // struct B { | |
| // A a[3]; | |
| // }; | |
| // B uni[2]; | |
| ShaderVariable uni; | |
| uni.arraySize = 2; | |
| uni.name = "uni"; | |
| uni.mappedName = "m_uni"; | |
| uni.structName = "B"; | |
| { | |
| ShaderVariable a; | |
| a.arraySize = 3; | |
| a.name = "a"; | |
| a.mappedName = "m_a"; | |
| a.structName = "A"; | |
| { | |
| ShaderVariable x(GL_FLOAT, 2); | |
| x.name = "x"; | |
| x.mappedName = "m_x"; | |
| a.fields.push_back(x); | |
| ShaderVariable y(GL_FLOAT_VEC3, 0); | |
| y.name = "y"; | |
| y.mappedName = "m_y"; | |
| a.fields.push_back(y); | |
| } | |
| uni.fields.push_back(a); | |
| } | |
| const ShaderVariable *leafVar = NULL; | |
| std::string originalFullName; | |
| std::string mappedFullName = "wrongName"; | |
| EXPECT_FALSE(uni.findInfoByMappedName( | |
| mappedFullName, &leafVar, &originalFullName)); | |
| mappedFullName = "m_uni"; | |
| EXPECT_TRUE(uni.findInfoByMappedName( | |
| mappedFullName, &leafVar, &originalFullName)); | |
| EXPECT_EQ(&uni, leafVar); | |
| EXPECT_STREQ("uni", originalFullName.c_str()); | |
| mappedFullName = "m_uni[0].m_a[1].wrongName"; | |
| EXPECT_FALSE(uni.findInfoByMappedName( | |
| mappedFullName, &leafVar, &originalFullName)); | |
| mappedFullName = "m_uni[0].m_a[1].m_x"; | |
| EXPECT_TRUE(uni.findInfoByMappedName( | |
| mappedFullName, &leafVar, &originalFullName)); | |
| EXPECT_EQ(&(uni.fields[0].fields[0]), leafVar); | |
| EXPECT_STREQ("uni[0].a[1].x", originalFullName.c_str()); | |
| mappedFullName = "m_uni[0].m_a[1].m_x[0]"; | |
| EXPECT_TRUE(uni.findInfoByMappedName( | |
| mappedFullName, &leafVar, &originalFullName)); | |
| EXPECT_EQ(&(uni.fields[0].fields[0]), leafVar); | |
| EXPECT_STREQ("uni[0].a[1].x[0]", originalFullName.c_str()); | |
| mappedFullName = "m_uni[0].m_a[1].m_y"; | |
| EXPECT_TRUE(uni.findInfoByMappedName( | |
| mappedFullName, &leafVar, &originalFullName)); | |
| EXPECT_EQ(&(uni.fields[0].fields[1]), leafVar); | |
| EXPECT_STREQ("uni[0].a[1].y", originalFullName.c_str()); | |
| } | |
| TEST(ShaderVariableTest, IsSameUniformWithDifferentFieldOrder) | |
| { | |
| // struct A { | |
| // float x; | |
| // float y; | |
| // }; | |
| // uniform A uni; | |
| Uniform vx_a; | |
| vx_a.arraySize = 0; | |
| vx_a.name = "uni"; | |
| vx_a.mappedName = "m_uni"; | |
| vx_a.structName = "A"; | |
| { | |
| ShaderVariable x(GL_FLOAT, 0); | |
| x.name = "x"; | |
| x.mappedName = "m_x"; | |
| vx_a.fields.push_back(x); | |
| ShaderVariable y(GL_FLOAT, 0); | |
| y.name = "y"; | |
| y.mappedName = "m_y"; | |
| vx_a.fields.push_back(y); | |
| } | |
| // struct A { | |
| // float y; | |
| // float x; | |
| // }; | |
| // uniform A uni; | |
| Uniform fx_a; | |
| fx_a.arraySize = 0; | |
| fx_a.name = "uni"; | |
| fx_a.mappedName = "m_uni"; | |
| fx_a.structName = "A"; | |
| { | |
| ShaderVariable y(GL_FLOAT, 0); | |
| y.name = "y"; | |
| y.mappedName = "m_y"; | |
| fx_a.fields.push_back(y); | |
| ShaderVariable x(GL_FLOAT, 0); | |
| x.name = "x"; | |
| x.mappedName = "m_x"; | |
| fx_a.fields.push_back(x); | |
| } | |
| EXPECT_FALSE(vx_a.isSameUniformAtLinkTime(fx_a)); | |
| } | |
| TEST(ShaderVariableTest, IsSameUniformWithDifferentStructNames) | |
| { | |
| // struct A { | |
| // float x; | |
| // float y; | |
| // }; | |
| // uniform A uni; | |
| Uniform vx_a; | |
| vx_a.arraySize = 0; | |
| vx_a.name = "uni"; | |
| vx_a.mappedName = "m_uni"; | |
| vx_a.structName = "A"; | |
| { | |
| ShaderVariable x(GL_FLOAT, 0); | |
| x.name = "x"; | |
| x.mappedName = "m_x"; | |
| vx_a.fields.push_back(x); | |
| ShaderVariable y(GL_FLOAT, 0); | |
| y.name = "y"; | |
| y.mappedName = "m_y"; | |
| vx_a.fields.push_back(y); | |
| } | |
| // struct B { | |
| // float x; | |
| // float y; | |
| // }; | |
| // uniform B uni; | |
| Uniform fx_a; | |
| fx_a.arraySize = 0; | |
| fx_a.name = "uni"; | |
| fx_a.mappedName = "m_uni"; | |
| { | |
| ShaderVariable x(GL_FLOAT, 0); | |
| x.name = "x"; | |
| x.mappedName = "m_x"; | |
| fx_a.fields.push_back(x); | |
| ShaderVariable y(GL_FLOAT, 0); | |
| y.name = "y"; | |
| y.mappedName = "m_y"; | |
| fx_a.fields.push_back(y); | |
| } | |
| fx_a.structName = "B"; | |
| EXPECT_FALSE(vx_a.isSameUniformAtLinkTime(fx_a)); | |
| fx_a.structName = "A"; | |
| EXPECT_TRUE(vx_a.isSameUniformAtLinkTime(fx_a)); | |
| fx_a.structName = ""; | |
| EXPECT_FALSE(vx_a.isSameUniformAtLinkTime(fx_a)); | |
| } | |
| TEST(ShaderVariableTest, IsSameVaryingWithDifferentInvariance) | |
| { | |
| // invariant varying float vary; | |
| Varying vx; | |
| vx.type = GL_FLOAT; | |
| vx.arraySize = 0; | |
| vx.precision = GL_MEDIUM_FLOAT; | |
| vx.name = "vary"; | |
| vx.mappedName = "m_vary"; | |
| vx.staticUse = true; | |
| vx.isInvariant = true; | |
| // varying float vary; | |
| Varying fx; | |
| fx.type = GL_FLOAT; | |
| fx.arraySize = 0; | |
| fx.precision = GL_MEDIUM_FLOAT; | |
| fx.name = "vary"; | |
| fx.mappedName = "m_vary"; | |
| fx.staticUse = true; | |
| fx.isInvariant = false; | |
| EXPECT_FALSE(vx.isSameVaryingAtLinkTime(fx)); | |
| // invariant varying float vary; | |
| fx.isInvariant = true; | |
| EXPECT_TRUE(vx.isSameVaryingAtLinkTime(fx)); | |
| } | |
| // Test that using invariant varyings doesn't trigger a double delete. | |
| TEST(ShaderVariableTest, InvariantDoubleDeleteBug) | |
| { | |
| ShBuiltInResources resources; | |
| ShInitBuiltInResources(&resources); | |
| ShHandle compiler = ShConstructCompiler(GL_VERTEX_SHADER, SH_GLES2_SPEC, SH_GLSL_OUTPUT, &resources); | |
| EXPECT_NE(static_cast<ShHandle>(0), compiler); | |
| const char *program[] = | |
| { | |
| "attribute vec4 position;\n" | |
| "varying float v;\n" | |
| "invariant v;\n" | |
| "void main() {\n" | |
| " v = 1.0;\n" | |
| " gl_Position = position;\n" | |
| "}" | |
| }; | |
| EXPECT_TRUE(ShCompile(compiler, program, 1, SH_OBJECT_CODE)); | |
| EXPECT_TRUE(ShCompile(compiler, program, 1, SH_OBJECT_CODE)); | |
| ShDestruct(compiler); | |
| } | |
| } // namespace sh |