1 // 2 // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 // CollectVariables_test.cpp: 7 // Some tests for shader inspection 8 // 9 10 #include "angle_gl.h" 11 #include "gtest/gtest.h" 12 #include "GLSLANG/ShaderLang.h" 13 #include "compiler/translator/TranslatorGLSL.h" 14 15 #define EXPECT_GLENUM_EQ(expected, actual) \ 16 EXPECT_EQ(static_cast<GLenum>(expected), static_cast<GLenum>(actual)) 17 18 class CollectVariablesTest : public testing::Test 19 { 20 public: 21 CollectVariablesTest(GLenum shaderType) 22 : mShaderType(shaderType) 23 {} 24 25 protected: 26 virtual void SetUp() 27 { 28 ShBuiltInResources resources; 29 ShInitBuiltInResources(&resources); 30 resources.MaxDrawBuffers = 8; 31 32 mTranslator = new TranslatorGLSL(mShaderType, SH_GLES2_SPEC); 33 ASSERT_TRUE(mTranslator->Init(resources)); 34 } 35 36 virtual void TearDown() 37 { 38 delete mTranslator; 39 } 40 41 GLenum mShaderType; 42 TranslatorGLSL *mTranslator; 43 }; 44 45 class CollectVertexVariablesTest : public CollectVariablesTest 46 { 47 public: 48 CollectVertexVariablesTest() : CollectVariablesTest(GL_VERTEX_SHADER) {} 49 }; 50 51 class CollectFragmentVariablesTest : public CollectVariablesTest 52 { 53 public: 54 CollectFragmentVariablesTest() : CollectVariablesTest(GL_FRAGMENT_SHADER) {} 55 }; 56 57 TEST_F(CollectFragmentVariablesTest, SimpleOutputVar) 58 { 59 const std::string &shaderString = 60 "#version 300 es\n" 61 "precision mediump float;\n" 62 "out vec4 out_fragColor;\n" 63 "void main() {\n" 64 " out_fragColor = vec4(1.0);\n" 65 "}\n"; 66 67 const char *shaderStrings[] = { shaderString.c_str() }; 68 ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES)); 69 70 const std::vector<sh::Attribute> &outputVariables = mTranslator->getOutputVariables(); 71 ASSERT_EQ(1u, outputVariables.size()); 72 73 const sh::Attribute &outputVariable = outputVariables[0]; 74 75 EXPECT_EQ(0u, outputVariable.arraySize); 76 EXPECT_EQ(-1, outputVariable.location); 77 EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable.precision); 78 EXPECT_TRUE(outputVariable.staticUse); 79 EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable.type); 80 EXPECT_EQ("out_fragColor", outputVariable.name); 81 } 82 83 TEST_F(CollectFragmentVariablesTest, LocationOutputVar) 84 { 85 const std::string &shaderString = 86 "#version 300 es\n" 87 "precision mediump float;\n" 88 "layout(location=5) out vec4 out_fragColor;\n" 89 "void main() {\n" 90 " out_fragColor = vec4(1.0);\n" 91 "}\n"; 92 93 const char *shaderStrings[] = { shaderString.c_str() }; 94 ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES)); 95 96 const std::vector<sh::Attribute> &outputVariables = mTranslator->getOutputVariables(); 97 ASSERT_EQ(1u, outputVariables.size()); 98 99 const sh::Attribute &outputVariable = outputVariables[0]; 100 101 EXPECT_EQ(0u, outputVariable.arraySize); 102 EXPECT_EQ(5, outputVariable.location); 103 EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable.precision); 104 EXPECT_TRUE(outputVariable.staticUse); 105 EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable.type); 106 EXPECT_EQ("out_fragColor", outputVariable.name); 107 } 108 109 TEST_F(CollectVertexVariablesTest, LocationAttribute) 110 { 111 const std::string &shaderString = 112 "#version 300 es\n" 113 "layout(location=5) in vec4 in_Position;\n" 114 "void main() {\n" 115 " gl_Position = in_Position;\n" 116 "}\n"; 117 118 const char *shaderStrings[] = { shaderString.c_str() }; 119 ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES)); 120 121 const std::vector<sh::Attribute> &attributes = mTranslator->getAttributes(); 122 ASSERT_EQ(1u, attributes.size()); 123 124 const sh::Attribute &attribute = attributes[0]; 125 126 EXPECT_EQ(0u, attribute.arraySize); 127 EXPECT_EQ(5, attribute.location); 128 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, attribute.precision); 129 EXPECT_TRUE(attribute.staticUse); 130 EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, attribute.type); 131 EXPECT_EQ("in_Position", attribute.name); 132 } 133 134 TEST_F(CollectVertexVariablesTest, SimpleInterfaceBlock) 135 { 136 const std::string &shaderString = 137 "#version 300 es\n" 138 "uniform b {\n" 139 " float f;\n" 140 "};" 141 "void main() {\n" 142 " gl_Position = vec4(f, 0.0, 0.0, 1.0);\n" 143 "}\n"; 144 145 const char *shaderStrings[] = { shaderString.c_str() }; 146 ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES)); 147 148 const std::vector<sh::InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks(); 149 ASSERT_EQ(1u, interfaceBlocks.size()); 150 151 const sh::InterfaceBlock &interfaceBlock = interfaceBlocks[0]; 152 153 EXPECT_EQ(0u, interfaceBlock.arraySize); 154 EXPECT_FALSE(interfaceBlock.isRowMajorLayout); 155 EXPECT_EQ(sh::BLOCKLAYOUT_SHARED, interfaceBlock.layout); 156 EXPECT_EQ("b", interfaceBlock.name); 157 EXPECT_TRUE(interfaceBlock.staticUse); 158 159 ASSERT_EQ(1u, interfaceBlock.fields.size()); 160 161 const sh::InterfaceBlockField &field = interfaceBlock.fields[0]; 162 163 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision); 164 EXPECT_TRUE(field.staticUse); 165 EXPECT_GLENUM_EQ(GL_FLOAT, field.type); 166 EXPECT_EQ("f", field.name); 167 EXPECT_FALSE(field.isRowMajorLayout); 168 EXPECT_TRUE(field.fields.empty()); 169 } 170 171 TEST_F(CollectVertexVariablesTest, SimpleInstancedInterfaceBlock) 172 { 173 const std::string &shaderString = 174 "#version 300 es\n" 175 "uniform b {\n" 176 " float f;\n" 177 "} blockInstance;" 178 "void main() {\n" 179 " gl_Position = vec4(blockInstance.f, 0.0, 0.0, 1.0);\n" 180 "}\n"; 181 182 const char *shaderStrings[] = { shaderString.c_str() }; 183 ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES)); 184 185 const std::vector<sh::InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks(); 186 ASSERT_EQ(1u, interfaceBlocks.size()); 187 188 const sh::InterfaceBlock &interfaceBlock = interfaceBlocks[0]; 189 190 EXPECT_EQ(0u, interfaceBlock.arraySize); 191 EXPECT_FALSE(interfaceBlock.isRowMajorLayout); 192 EXPECT_EQ(sh::BLOCKLAYOUT_SHARED, interfaceBlock.layout); 193 EXPECT_EQ("b", interfaceBlock.name); 194 EXPECT_TRUE(interfaceBlock.staticUse); 195 196 ASSERT_EQ(1u, interfaceBlock.fields.size()); 197 198 const sh::InterfaceBlockField &field = interfaceBlock.fields[0]; 199 200 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision); 201 EXPECT_TRUE(field.staticUse); 202 EXPECT_GLENUM_EQ(GL_FLOAT, field.type); 203 EXPECT_EQ("b.f", field.name); 204 EXPECT_FALSE(field.isRowMajorLayout); 205 EXPECT_TRUE(field.fields.empty()); 206 } 207 208 TEST_F(CollectVertexVariablesTest, StructInterfaceBlock) 209 { 210 const std::string &shaderString = 211 "#version 300 es\n" 212 "struct st { float f; };" 213 "uniform b {\n" 214 " st s;\n" 215 "};" 216 "void main() {\n" 217 " gl_Position = vec4(s.f, 0.0, 0.0, 1.0);\n" 218 "}\n"; 219 220 const char *shaderStrings[] = { shaderString.c_str() }; 221 ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES)); 222 223 const std::vector<sh::InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks(); 224 ASSERT_EQ(1u, interfaceBlocks.size()); 225 226 const sh::InterfaceBlock &interfaceBlock = interfaceBlocks[0]; 227 228 EXPECT_EQ(0u, interfaceBlock.arraySize); 229 EXPECT_FALSE(interfaceBlock.isRowMajorLayout); 230 EXPECT_EQ(sh::BLOCKLAYOUT_SHARED, interfaceBlock.layout); 231 EXPECT_EQ("b", interfaceBlock.name); 232 EXPECT_TRUE(interfaceBlock.staticUse); 233 234 ASSERT_EQ(1u, interfaceBlock.fields.size()); 235 236 const sh::InterfaceBlockField &field = interfaceBlock.fields[0]; 237 238 EXPECT_TRUE(field.isStruct()); 239 EXPECT_TRUE(field.staticUse); 240 EXPECT_EQ("s", field.name); 241 EXPECT_FALSE(field.isRowMajorLayout); 242 243 const sh::ShaderVariable &member = field.fields[0]; 244 245 // NOTE: we don't currently mark struct members as statically used or not 246 EXPECT_FALSE(member.isStruct()); 247 EXPECT_EQ("f", member.name); 248 EXPECT_GLENUM_EQ(GL_FLOAT, member.type); 249 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision); 250 } 251 252 TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock) 253 { 254 const std::string &shaderString = 255 "#version 300 es\n" 256 "struct st { float f; };" 257 "uniform b {\n" 258 " st s;\n" 259 "} instanceName;" 260 "void main() {\n" 261 " gl_Position = vec4(instanceName.s.f, 0.0, 0.0, 1.0);\n" 262 "}\n"; 263 264 const char *shaderStrings[] = { shaderString.c_str() }; 265 ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES)); 266 267 const std::vector<sh::InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks(); 268 ASSERT_EQ(1u, interfaceBlocks.size()); 269 270 const sh::InterfaceBlock &interfaceBlock = interfaceBlocks[0]; 271 272 EXPECT_EQ(0u, interfaceBlock.arraySize); 273 EXPECT_FALSE(interfaceBlock.isRowMajorLayout); 274 EXPECT_EQ(sh::BLOCKLAYOUT_SHARED, interfaceBlock.layout); 275 EXPECT_EQ("b", interfaceBlock.name); 276 EXPECT_TRUE(interfaceBlock.staticUse); 277 278 ASSERT_EQ(1u, interfaceBlock.fields.size()); 279 280 const sh::InterfaceBlockField &field = interfaceBlock.fields[0]; 281 282 EXPECT_TRUE(field.isStruct()); 283 EXPECT_TRUE(field.staticUse); 284 EXPECT_EQ("b.s", field.name); 285 EXPECT_FALSE(field.isRowMajorLayout); 286 287 const sh::ShaderVariable &member = field.fields[0]; 288 289 // NOTE: we don't currently mark struct members as statically used or not 290 EXPECT_FALSE(member.isStruct()); 291 EXPECT_EQ("f", member.name); 292 EXPECT_GLENUM_EQ(GL_FLOAT, member.type); 293 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision); 294 } 295 296 TEST_F(CollectVertexVariablesTest, NestedStructRowMajorInterfaceBlock) 297 { 298 const std::string &shaderString = 299 "#version 300 es\n" 300 "struct st { mat2 m; };" 301 "layout(row_major) uniform b {\n" 302 " st s;\n" 303 "};" 304 "void main() {\n" 305 " gl_Position = vec4(s.m);\n" 306 "}\n"; 307 308 const char *shaderStrings[] = { shaderString.c_str() }; 309 ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES)); 310 311 const std::vector<sh::InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks(); 312 ASSERT_EQ(1u, interfaceBlocks.size()); 313 314 const sh::InterfaceBlock &interfaceBlock = interfaceBlocks[0]; 315 316 EXPECT_EQ(0u, interfaceBlock.arraySize); 317 EXPECT_TRUE(interfaceBlock.isRowMajorLayout); 318 EXPECT_EQ(sh::BLOCKLAYOUT_SHARED, interfaceBlock.layout); 319 EXPECT_EQ("b", interfaceBlock.name); 320 EXPECT_TRUE(interfaceBlock.staticUse); 321 322 ASSERT_EQ(1u, interfaceBlock.fields.size()); 323 324 const sh::InterfaceBlockField &field = interfaceBlock.fields[0]; 325 326 EXPECT_TRUE(field.isStruct()); 327 EXPECT_TRUE(field.staticUse); 328 EXPECT_EQ("s", field.name); 329 EXPECT_TRUE(field.isRowMajorLayout); 330 331 const sh::ShaderVariable &member = field.fields[0]; 332 333 // NOTE: we don't currently mark struct members as statically used or not 334 EXPECT_FALSE(member.isStruct()); 335 EXPECT_EQ("m", member.name); 336 EXPECT_GLENUM_EQ(GL_FLOAT_MAT2, member.type); 337 EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision); 338 } 339