1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.1 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Geometry shader tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es31fGeometryShaderTests.hpp" 25 26 #include "gluRenderContext.hpp" 27 #include "gluTextureUtil.hpp" 28 #include "gluObjectWrapper.hpp" 29 #include "gluPixelTransfer.hpp" 30 #include "gluContextInfo.hpp" 31 #include "gluCallLogWrapper.hpp" 32 #include "tcuRenderTarget.hpp" 33 #include "tcuTestLog.hpp" 34 #include "tcuVectorUtil.hpp" 35 #include "tcuImageCompare.hpp" 36 #include "tcuTextureUtil.hpp" 37 #include "glsStateQueryUtil.hpp" 38 39 #include "gluStrUtil.hpp" 40 #include "deStringUtil.hpp" 41 #include "deUniquePtr.hpp" 42 #include "deMemory.h" 43 44 #include "sglrContext.hpp" 45 #include "sglrReferenceContext.hpp" 46 #include "sglrGLContext.hpp" 47 #include "sglrReferenceUtils.hpp" 48 49 #include "glwDefs.hpp" 50 #include "glwEnums.hpp" 51 #include "glwFunctions.hpp" 52 53 #include <algorithm> 54 55 using namespace glw; 56 57 namespace deqp 58 { 59 namespace gles31 60 { 61 namespace Functional 62 { 63 namespace 64 { 65 66 const int TEST_CANVAS_SIZE = 256; 67 68 static const char* const s_commonShaderSourceVertex = "#version 310 es\n" 69 "in highp vec4 a_position;\n" 70 "in highp vec4 a_color;\n" 71 "out highp vec4 v_geom_FragColor;\n" 72 "void main (void)\n" 73 "{\n" 74 " gl_Position = a_position;\n" 75 " gl_PointSize = 1.0;\n" 76 " v_geom_FragColor = a_color;\n" 77 "}\n"; 78 static const char* const s_commonShaderSourceFragment = "#version 310 es\n" 79 "layout(location = 0) out mediump vec4 fragColor;\n" 80 "in mediump vec4 v_frag_FragColor;\n" 81 "void main (void)\n" 82 "{\n" 83 " fragColor = v_frag_FragColor;\n" 84 "}\n"; 85 static const char* const s_expandShaderSourceGeometryBody = "in highp vec4 v_geom_FragColor[];\n" 86 "out highp vec4 v_frag_FragColor;\n" 87 "\n" 88 "void main (void)\n" 89 "{\n" 90 " const highp vec4 offset0 = vec4(-0.07, -0.01, 0.0, 0.0);\n" 91 " const highp vec4 offset1 = vec4( 0.03, -0.03, 0.0, 0.0);\n" 92 " const highp vec4 offset2 = vec4(-0.01, 0.08, 0.0, 0.0);\n" 93 " highp vec4 yoffset = float(gl_PrimitiveIDIn) * vec4(0.02, 0.1, 0.0, 0.0);\n" 94 "\n" 95 " for (highp int ndx = 0; ndx < gl_in.length(); ndx++)\n" 96 " {\n" 97 " gl_Position = gl_in[ndx].gl_Position + offset0 + yoffset;\n" 98 " gl_PrimitiveID = gl_PrimitiveIDIn;\n" 99 " v_frag_FragColor = v_geom_FragColor[ndx];\n" 100 " EmitVertex();\n" 101 "\n" 102 " gl_Position = gl_in[ndx].gl_Position + offset1 + yoffset;\n" 103 " gl_PrimitiveID = gl_PrimitiveIDIn;\n" 104 " v_frag_FragColor = v_geom_FragColor[ndx];\n" 105 " EmitVertex();\n" 106 "\n" 107 " gl_Position = gl_in[ndx].gl_Position + offset2 + yoffset;\n" 108 " gl_PrimitiveID = gl_PrimitiveIDIn;\n" 109 " v_frag_FragColor = v_geom_FragColor[ndx];\n" 110 " EmitVertex();\n" 111 " EndPrimitive();\n" 112 " }\n" 113 "}\n"; 114 115 std::string inputTypeToGLString (rr::GeometryShaderInputType inputType) 116 { 117 switch (inputType) 118 { 119 case rr::GEOMETRYSHADERINPUTTYPE_POINTS: return "points"; 120 case rr::GEOMETRYSHADERINPUTTYPE_LINES: return "lines"; 121 case rr::GEOMETRYSHADERINPUTTYPE_LINES_ADJACENCY: return "lines_adjacency"; 122 case rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES: return "triangles"; 123 case rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES_ADJACENCY: return "triangles_adjacency"; 124 default: 125 DE_ASSERT(DE_FALSE); 126 return "error"; 127 } 128 } 129 130 std::string outputTypeToGLString (rr::GeometryShaderOutputType outputType) 131 { 132 switch (outputType) 133 { 134 case rr::GEOMETRYSHADEROUTPUTTYPE_POINTS: return "points"; 135 case rr::GEOMETRYSHADEROUTPUTTYPE_LINE_STRIP: return "line_strip"; 136 case rr::GEOMETRYSHADEROUTPUTTYPE_TRIANGLE_STRIP: return "triangle_strip"; 137 default: 138 DE_ASSERT(DE_FALSE); 139 return "error"; 140 } 141 } 142 143 std::string primitiveTypeToString(GLenum primitive) 144 { 145 switch (primitive) 146 { 147 case GL_POINTS: return "points"; 148 case GL_LINES: return "lines"; 149 case GL_LINE_LOOP: return "line_loop"; 150 case GL_LINE_STRIP: return "line_strip"; 151 case GL_LINES_ADJACENCY: return "lines_adjacency"; 152 case GL_LINE_STRIP_ADJACENCY: return "line_strip_adjacency"; 153 case GL_TRIANGLES: return "triangles"; 154 case GL_TRIANGLE_STRIP: return "triangle_strip"; 155 case GL_TRIANGLE_FAN: return "triangle_fan"; 156 case GL_TRIANGLES_ADJACENCY: return "triangles_adjacency"; 157 case GL_TRIANGLE_STRIP_ADJACENCY: return "triangle_strip_adjacency"; 158 default: 159 DE_ASSERT(DE_FALSE); 160 return "error"; 161 } 162 } 163 164 struct OutputCountPatternSpec 165 { 166 OutputCountPatternSpec (int count); 167 OutputCountPatternSpec (int count0, int count1); 168 169 std::vector<int> pattern; 170 }; 171 172 OutputCountPatternSpec::OutputCountPatternSpec (int count) 173 { 174 pattern.push_back(count); 175 } 176 177 OutputCountPatternSpec::OutputCountPatternSpec (int count0, int count1) 178 { 179 pattern.push_back(count0); 180 pattern.push_back(count1); 181 } 182 183 class VertexExpanderShader : public sglr::ShaderProgram 184 { 185 public: 186 VertexExpanderShader (rr::GeometryShaderInputType inputType, rr::GeometryShaderOutputType outputType); 187 188 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const; 189 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const; 190 void shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const; 191 192 private: 193 size_t calcOutputVertices (rr::GeometryShaderInputType inputType) const; 194 std::string genGeometrySource (rr::GeometryShaderInputType inputType, rr::GeometryShaderOutputType outputType) const; 195 }; 196 197 VertexExpanderShader::VertexExpanderShader (rr::GeometryShaderInputType inputType, rr::GeometryShaderOutputType outputType) 198 : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration() 199 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT) 200 << sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT) 201 << sglr::pdec::VertexToGeometryVarying(rr::GENERICVECTYPE_FLOAT) 202 << sglr::pdec::GeometryToFragmentVarying(rr::GENERICVECTYPE_FLOAT) 203 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT) 204 << sglr::pdec::VertexSource(s_commonShaderSourceVertex) 205 << sglr::pdec::FragmentSource(s_commonShaderSourceFragment) 206 << sglr::pdec::GeometryShaderDeclaration(inputType, outputType, calcOutputVertices(inputType)) 207 << sglr::pdec::GeometrySource(genGeometrySource(inputType, outputType).c_str())) 208 { 209 } 210 211 void VertexExpanderShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 212 { 213 for (int ndx = 0; ndx < numPackets; ++ndx) 214 { 215 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx); 216 packets[ndx]->pointSize = 1.0f; 217 packets[ndx]->outputs[0] = rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx); 218 } 219 } 220 221 void VertexExpanderShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 222 { 223 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 224 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 225 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx)); 226 } 227 228 void VertexExpanderShader::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const 229 { 230 DE_UNREF(invocationID); 231 232 for (int ndx = 0; ndx < numPackets; ++ndx) 233 for (int verticeNdx = 0; verticeNdx < verticesIn; ++verticeNdx) 234 { 235 const tcu::Vec4 offsets[] = 236 { 237 tcu::Vec4(-0.07f, -0.01f, 0.0f, 0.0f), 238 tcu::Vec4( 0.03f, -0.03f, 0.0f, 0.0f), 239 tcu::Vec4(-0.01f, 0.08f, 0.0f, 0.0f) 240 }; 241 const tcu::Vec4 yoffset = float(packets[ndx].primitiveIDIn) * tcu::Vec4(0.02f, 0.1f, 0, 0); 242 243 // Create new primitive at every input vertice 244 const rr::VertexPacket* vertex = packets[ndx].vertices[verticeNdx]; 245 246 output.EmitVertex(vertex->position + offsets[0] + yoffset, vertex->pointSize, vertex->outputs, packets[ndx].primitiveIDIn); 247 output.EmitVertex(vertex->position + offsets[1] + yoffset, vertex->pointSize, vertex->outputs, packets[ndx].primitiveIDIn); 248 output.EmitVertex(vertex->position + offsets[2] + yoffset, vertex->pointSize, vertex->outputs, packets[ndx].primitiveIDIn); 249 output.EndPrimitive(); 250 } 251 } 252 253 size_t VertexExpanderShader::calcOutputVertices (rr::GeometryShaderInputType inputType) const 254 { 255 switch (inputType) 256 { 257 case rr::GEOMETRYSHADERINPUTTYPE_POINTS: return 1 * 3; 258 case rr::GEOMETRYSHADERINPUTTYPE_LINES: return 2 * 3; 259 case rr::GEOMETRYSHADERINPUTTYPE_LINES_ADJACENCY: return 4 * 3; 260 case rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES: return 3 * 3; 261 case rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES_ADJACENCY: return 6 * 3; 262 default: 263 DE_ASSERT(DE_FALSE); 264 return 0; 265 } 266 } 267 268 std::string VertexExpanderShader::genGeometrySource (rr::GeometryShaderInputType inputType, rr::GeometryShaderOutputType outputType) const 269 { 270 std::ostringstream str; 271 272 str << "#version 310 es\n"; 273 str << "#extension GL_EXT_geometry_shader : require\n"; 274 str << "layout(" << inputTypeToGLString(inputType) << ") in;\n"; 275 str << "layout(" << outputTypeToGLString(outputType) << ", max_vertices = " << calcOutputVertices(inputType) << ") out;"; 276 str << "\n"; 277 str << s_expandShaderSourceGeometryBody; 278 279 return str.str(); 280 } 281 282 class VertexEmitterShader : public sglr::ShaderProgram 283 { 284 public: 285 VertexEmitterShader (int emitCountA, int endCountA, int emitCountB, int endCountB, rr::GeometryShaderOutputType outputType); 286 287 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const; 288 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const; 289 void shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const; 290 291 private: 292 std::string genGeometrySource (int emitCountA, int endCountA, int emitCountB, int endCountB, rr::GeometryShaderOutputType outputType) const; 293 294 int m_emitCountA; 295 int m_endCountA; 296 int m_emitCountB; 297 int m_endCountB; 298 }; 299 300 VertexEmitterShader::VertexEmitterShader (int emitCountA, int endCountA, int emitCountB, int endCountB, rr::GeometryShaderOutputType outputType) 301 : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration() 302 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT) 303 << sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT) 304 << sglr::pdec::VertexToGeometryVarying(rr::GENERICVECTYPE_FLOAT) 305 << sglr::pdec::GeometryToFragmentVarying(rr::GENERICVECTYPE_FLOAT) 306 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT) 307 << sglr::pdec::VertexSource(s_commonShaderSourceVertex) 308 << sglr::pdec::FragmentSource(s_commonShaderSourceFragment) 309 << sglr::pdec::GeometryShaderDeclaration(rr::GEOMETRYSHADERINPUTTYPE_POINTS, outputType, emitCountA + emitCountB) 310 << sglr::pdec::GeometrySource(genGeometrySource(emitCountA, endCountA, emitCountB, endCountB, outputType).c_str())) 311 , m_emitCountA (emitCountA) 312 , m_endCountA (endCountA) 313 , m_emitCountB (emitCountB) 314 , m_endCountB (endCountB) 315 { 316 } 317 318 void VertexEmitterShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 319 { 320 for (int ndx = 0; ndx < numPackets; ++ndx) 321 { 322 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx); 323 packets[ndx]->pointSize = 1.0f; 324 packets[ndx]->outputs[0] = rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx); 325 } 326 } 327 328 void VertexEmitterShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 329 { 330 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 331 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 332 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx)); 333 } 334 335 void VertexEmitterShader::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const 336 { 337 DE_UNREF(verticesIn); 338 DE_UNREF(invocationID); 339 340 for (int ndx = 0; ndx < numPackets; ++ndx) 341 { 342 const tcu::Vec4 positions[] = 343 { 344 tcu::Vec4(-0.5f, 0.5f, 0.0f, 0.0f), 345 tcu::Vec4( 0.0f, 0.1f, 0.0f, 0.0f), 346 tcu::Vec4( 0.5f, 0.5f, 0.0f, 0.0f), 347 tcu::Vec4( 0.7f, -0.2f, 0.0f, 0.0f), 348 tcu::Vec4( 0.2f, 0.2f, 0.0f, 0.0f), 349 tcu::Vec4( 0.4f, -0.3f, 0.0f, 0.0f), 350 }; 351 352 // Create new primitive at this point 353 const rr::VertexPacket* vertex = packets[ndx].vertices[0]; 354 355 for (int i = 0; i < m_emitCountA; ++i) 356 output.EmitVertex(vertex->position + positions[i], vertex->pointSize, vertex->outputs, packets[ndx].primitiveIDIn); 357 358 for (int i = 0; i < m_endCountA; ++i) 359 output.EndPrimitive(); 360 361 for (int i = 0; i < m_emitCountB; ++i) 362 output.EmitVertex(vertex->position + positions[m_emitCountA + i], vertex->pointSize, vertex->outputs, packets[ndx].primitiveIDIn); 363 364 for (int i = 0; i < m_endCountB; ++i) 365 output.EndPrimitive(); 366 } 367 } 368 369 std::string VertexEmitterShader::genGeometrySource (int emitCountA, int endCountA, int emitCountB, int endCountB, rr::GeometryShaderOutputType outputType) const 370 { 371 std::ostringstream str; 372 373 str << "#version 310 es\n"; 374 str << "#extension GL_EXT_geometry_shader : require\n"; 375 str << "layout(points) in;\n"; 376 str << "layout(" << outputTypeToGLString(outputType) << ", max_vertices = " << (emitCountA+emitCountB) << ") out;"; 377 str << "\n"; 378 379 str << "in highp vec4 v_geom_FragColor[];\n" 380 "out highp vec4 v_frag_FragColor;\n" 381 "\n" 382 "void main (void)\n" 383 "{\n" 384 " const highp vec4 position0 = vec4(-0.5, 0.5, 0.0, 0.0);\n" 385 " const highp vec4 position1 = vec4( 0.0, 0.1, 0.0, 0.0);\n" 386 " const highp vec4 position2 = vec4( 0.5, 0.5, 0.0, 0.0);\n" 387 " const highp vec4 position3 = vec4( 0.7, -0.2, 0.0, 0.0);\n" 388 " const highp vec4 position4 = vec4( 0.2, 0.2, 0.0, 0.0);\n" 389 " const highp vec4 position5 = vec4( 0.4, -0.3, 0.0, 0.0);\n" 390 "\n"; 391 392 for (int i = 0; i < emitCountA; ++i) 393 str << " gl_Position = gl_in[0].gl_Position + position" << i << ";\n" 394 " gl_PrimitiveID = gl_PrimitiveIDIn;\n" 395 " v_frag_FragColor = v_geom_FragColor[0];\n" 396 " EmitVertex();\n" 397 "\n"; 398 399 for (int i = 0; i < endCountA; ++i) 400 str << " EndPrimitive();\n"; 401 402 for (int i = 0; i < emitCountB; ++i) 403 str << " gl_Position = gl_in[0].gl_Position + position" << (emitCountA + i) << ";\n" 404 " gl_PrimitiveID = gl_PrimitiveIDIn;\n" 405 " v_frag_FragColor = v_geom_FragColor[0];\n" 406 " EmitVertex();\n" 407 "\n"; 408 409 for (int i = 0; i < endCountB; ++i) 410 str << " EndPrimitive();\n"; 411 412 413 str << "}\n"; 414 415 return str.str(); 416 } 417 418 class VertexVaryingShader : public sglr::ShaderProgram 419 { 420 public: 421 VertexVaryingShader (int vertexOut, int geometryOut); 422 423 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const; 424 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const; 425 void shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const; 426 427 private: 428 static sglr::pdec::ShaderProgramDeclaration genProgramDeclaration (int vertexOut, int geometryOut); 429 430 const int m_vertexOut; 431 const int m_geometryOut; 432 }; 433 434 VertexVaryingShader::VertexVaryingShader (int vertexOut, int geometryOut) 435 : sglr::ShaderProgram (genProgramDeclaration(vertexOut, geometryOut)) 436 , m_vertexOut (vertexOut) 437 , m_geometryOut (geometryOut) 438 { 439 } 440 441 void VertexVaryingShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 442 { 443 // vertex shader is no-op 444 if (m_vertexOut == -1) 445 return; 446 447 for (int ndx = 0; ndx < numPackets; ++ndx) 448 { 449 const tcu::Vec4 color = rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx); 450 451 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx); 452 packets[ndx]->pointSize = 1.0f; 453 454 switch (m_vertexOut) 455 { 456 case 0: 457 break; 458 459 case 1: 460 packets[ndx]->outputs[0] = color; 461 break; 462 463 case 2: 464 packets[ndx]->outputs[0] = color * 0.5f; 465 packets[ndx]->outputs[1] = color.swizzle(2,1,0,3) * 0.5f; 466 break; 467 468 default: 469 DE_ASSERT(DE_FALSE); 470 } 471 } 472 } 473 474 void VertexVaryingShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 475 { 476 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 477 { 478 switch (m_geometryOut) 479 { 480 case 0: 481 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 482 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); 483 break; 484 485 case 1: 486 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 487 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx)); 488 break; 489 490 case 2: 491 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 492 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx) 493 + rr::readTriangleVarying<float>(packets[packetNdx], context, 1, fragNdx).swizzle(1, 0, 2, 3)); 494 break; 495 496 default: 497 DE_ASSERT(DE_FALSE); 498 } 499 } 500 } 501 502 void VertexVaryingShader::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const 503 { 504 DE_UNREF(invocationID); 505 506 const tcu::Vec4 vertexOffset(-0.2f, -0.2f, 0, 0); 507 508 if (m_vertexOut == -1) 509 { 510 // vertex is a no-op 511 const tcu::Vec4 inputColor = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f); 512 rr::GenericVec4 outputs[2]; 513 514 // output color 515 switch (m_geometryOut) 516 { 517 case 0: 518 break; 519 520 case 1: 521 outputs[0] = inputColor; 522 break; 523 524 case 2: 525 outputs[0] = inputColor * 0.5f; 526 outputs[1] = inputColor.swizzle(1, 0, 2, 3) * 0.5f; 527 break; 528 529 default: 530 DE_ASSERT(DE_FALSE); 531 } 532 533 for (int ndx = 0; ndx < numPackets; ++ndx) 534 { 535 output.EmitVertex(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f) + vertexOffset, 1.0f, outputs, packets[ndx].primitiveIDIn); 536 output.EmitVertex(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f) + vertexOffset, 1.0f, outputs, packets[ndx].primitiveIDIn); 537 output.EmitVertex(tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f) + vertexOffset, 1.0f, outputs, packets[ndx].primitiveIDIn); 538 output.EndPrimitive(); 539 } 540 } 541 else 542 { 543 // vertex is not a no-op 544 for (int ndx = 0; ndx < numPackets; ++ndx) 545 { 546 for (int verticeNdx = 0; verticeNdx < verticesIn; ++verticeNdx) 547 { 548 tcu::Vec4 inputColor; 549 rr::GenericVec4 outputs[2]; 550 551 // input color 552 switch (m_vertexOut) 553 { 554 case 0: 555 inputColor = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f); 556 break; 557 558 case 1: 559 inputColor = packets[ndx].vertices[verticeNdx]->outputs[0].get<float>(); 560 break; 561 562 case 2: 563 inputColor = (packets[ndx].vertices[verticeNdx]->outputs[0].get<float>() * 0.5f) 564 + (packets[ndx].vertices[verticeNdx]->outputs[1].get<float>().swizzle(2, 1, 0, 3) * 0.5f); 565 break; 566 567 default: 568 DE_ASSERT(DE_FALSE); 569 } 570 571 // output color 572 switch (m_geometryOut) 573 { 574 case 0: 575 break; 576 577 case 1: 578 outputs[0] = inputColor; 579 break; 580 581 case 2: 582 outputs[0] = inputColor * 0.5f; 583 outputs[1] = inputColor.swizzle(1, 0, 2, 3) * 0.5f; 584 break; 585 586 default: 587 DE_ASSERT(DE_FALSE); 588 } 589 590 output.EmitVertex(packets[ndx].vertices[verticeNdx]->position + vertexOffset, packets[ndx].vertices[verticeNdx]->pointSize, outputs, packets[ndx].primitiveIDIn); 591 } 592 output.EndPrimitive(); 593 } 594 } 595 } 596 597 sglr::pdec::ShaderProgramDeclaration VertexVaryingShader::genProgramDeclaration (int vertexOut, int geometryOut) 598 { 599 sglr::pdec::ShaderProgramDeclaration decl; 600 std::ostringstream vertexSource; 601 std::ostringstream fragmentSource; 602 std::ostringstream geometrySource; 603 604 decl 605 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT) 606 << sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT); 607 608 for (int i = 0; i < vertexOut; ++i) 609 decl << sglr::pdec::VertexToGeometryVarying(rr::GENERICVECTYPE_FLOAT); 610 for (int i = 0; i < geometryOut; ++i) 611 decl << sglr::pdec::GeometryToFragmentVarying(rr::GENERICVECTYPE_FLOAT); 612 613 decl 614 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT) 615 << sglr::pdec::GeometryShaderDeclaration(rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES, rr::GEOMETRYSHADEROUTPUTTYPE_TRIANGLE_STRIP, 3); 616 617 // vertexSource 618 619 vertexSource << "#version 310 es\n" 620 "in highp vec4 a_position;\n" 621 "in highp vec4 a_color;\n"; 622 623 // no-op case? 624 if (vertexOut == -1) 625 { 626 vertexSource << "void main (void)\n" 627 "{\n" 628 "}\n"; 629 } 630 else 631 { 632 for (int i = 0; i < vertexOut; ++i) 633 vertexSource << "out highp vec4 v_geom_" << i << ";\n"; 634 635 vertexSource << "void main (void)\n" 636 "{\n" 637 "\tgl_Position = a_position;\n" 638 "\tgl_PointSize = 1.0;\n"; 639 switch (vertexOut) 640 { 641 case 0: 642 break; 643 644 case 1: 645 vertexSource << "\tv_geom_0 = a_color;\n"; 646 break; 647 648 case 2: 649 vertexSource << "\tv_geom_0 = a_color * 0.5;\n"; 650 vertexSource << "\tv_geom_1 = a_color.zyxw * 0.5;\n"; 651 break; 652 653 default: 654 DE_ASSERT(DE_FALSE); 655 } 656 vertexSource << "}\n"; 657 } 658 659 // fragmentSource 660 661 fragmentSource << "#version 310 es\n" 662 "layout(location = 0) out mediump vec4 fragColor;\n"; 663 664 for (int i = 0; i < geometryOut; ++i) 665 fragmentSource << "in mediump vec4 v_frag_" << i << ";\n"; 666 667 fragmentSource << "void main (void)\n" 668 "{\n"; 669 switch (geometryOut) 670 { 671 case 0: 672 fragmentSource << "\tfragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"; 673 break; 674 675 case 1: 676 fragmentSource << "\tfragColor = v_frag_0;\n"; 677 break; 678 679 case 2: 680 fragmentSource << "\tfragColor = v_frag_0 + v_frag_1.yxzw;\n"; 681 break; 682 683 default: 684 DE_ASSERT(DE_FALSE); 685 } 686 fragmentSource << "}\n"; 687 688 // geometrySource 689 690 geometrySource << "#version 310 es\n" 691 "#extension GL_EXT_geometry_shader : require\n" 692 "layout(triangles) in;\n" 693 "layout(triangle_strip, max_vertices = 3) out;\n"; 694 695 for (int i = 0; i < vertexOut; ++i) 696 geometrySource << "in highp vec4 v_geom_" << i << "[];\n"; 697 for (int i = 0; i < geometryOut; ++i) 698 geometrySource << "out highp vec4 v_frag_" << i << ";\n"; 699 700 geometrySource << "void main (void)\n" 701 "{\n" 702 "\thighp vec4 offset = vec4(-0.2, -0.2, 0.0, 0.0);\n" 703 "\thighp vec4 inputColor;\n\n"; 704 705 for (int vertexNdx = 0; vertexNdx < 3; ++vertexNdx) 706 { 707 if (vertexOut == -1) 708 { 709 // vertex is a no-op 710 geometrySource << "\tinputColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 711 "\tgl_Position = vec4(" << ((vertexNdx==0) ? ("0.0, 0.0") : ((vertexNdx==1) ? ("1.0, 0.0") : ("1.0, 1.0"))) << ", 0.0, 1.0) + offset;\n" 712 "\tgl_PrimitiveID = gl_PrimitiveIDIn;\n"; 713 } 714 else 715 { 716 switch (vertexOut) 717 { 718 case 0: 719 geometrySource << "\tinputColor = vec4(1.0, 0.0, 0.0, 1.0);\n"; 720 break; 721 722 case 1: 723 geometrySource << "\tinputColor = v_geom_0[" << vertexNdx << "];\n"; 724 break; 725 726 case 2: 727 geometrySource << "\tinputColor = v_geom_0[" << vertexNdx << "] * 0.5 + v_geom_1[" << vertexNdx << "].zyxw * 0.5;\n"; 728 break; 729 730 default: 731 DE_ASSERT(DE_FALSE); 732 } 733 geometrySource << "\tgl_Position = gl_in[" << vertexNdx << "].gl_Position + offset;\n" 734 "\tgl_PrimitiveID = gl_PrimitiveIDIn;\n"; 735 } 736 737 switch (geometryOut) 738 { 739 case 0: 740 break; 741 742 case 1: 743 geometrySource << "\tv_frag_0 = inputColor;\n"; 744 break; 745 746 case 2: 747 geometrySource << "\tv_frag_0 = inputColor * 0.5;\n"; 748 geometrySource << "\tv_frag_1 = inputColor.yxzw * 0.5;\n"; 749 break; 750 751 default: 752 DE_ASSERT(DE_FALSE); 753 } 754 755 geometrySource << "\tEmitVertex();\n\n"; 756 } 757 758 geometrySource << "\tEndPrimitive();\n" 759 "}\n"; 760 761 decl 762 << sglr::pdec::VertexSource(vertexSource.str().c_str()) 763 << sglr::pdec::FragmentSource(fragmentSource.str().c_str()) 764 << sglr::pdec::GeometrySource(geometrySource.str().c_str()); 765 return decl; 766 } 767 768 class OutputCountShader : public sglr::ShaderProgram 769 { 770 public: 771 OutputCountShader (const OutputCountPatternSpec& spec); 772 773 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const; 774 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const; 775 void shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const; 776 777 private: 778 std::string genGeometrySource (const OutputCountPatternSpec& spec) const; 779 size_t getPatternEmitCount (const OutputCountPatternSpec& spec) const; 780 781 const int m_patternLength; 782 const int m_patternMaxEmitCount; 783 const OutputCountPatternSpec m_spec; 784 }; 785 786 OutputCountShader::OutputCountShader (const OutputCountPatternSpec& spec) 787 : sglr::ShaderProgram (sglr::pdec::ShaderProgramDeclaration() 788 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT) 789 << sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT) 790 << sglr::pdec::VertexToGeometryVarying(rr::GENERICVECTYPE_FLOAT) 791 << sglr::pdec::GeometryToFragmentVarying(rr::GENERICVECTYPE_FLOAT) 792 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT) 793 << sglr::pdec::VertexSource(s_commonShaderSourceVertex) 794 << sglr::pdec::FragmentSource(s_commonShaderSourceFragment) 795 << sglr::pdec::GeometryShaderDeclaration(rr::GEOMETRYSHADERINPUTTYPE_POINTS, rr::GEOMETRYSHADEROUTPUTTYPE_TRIANGLE_STRIP, getPatternEmitCount(spec)) 796 << sglr::pdec::GeometrySource(genGeometrySource(spec).c_str())) 797 , m_patternLength ((int)spec.pattern.size()) 798 , m_patternMaxEmitCount ((int)getPatternEmitCount(spec)) 799 , m_spec (spec) 800 { 801 } 802 803 void OutputCountShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 804 { 805 for (int ndx = 0; ndx < numPackets; ++ndx) 806 { 807 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx); 808 packets[ndx]->pointSize = 1.0f; 809 packets[ndx]->outputs[0] = rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx); 810 } 811 } 812 813 void OutputCountShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 814 { 815 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 816 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 817 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx)); 818 } 819 820 void OutputCountShader::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const 821 { 822 DE_UNREF(verticesIn); 823 DE_UNREF(invocationID); 824 825 const float rowHeight = 2.0f / (float)m_patternLength; 826 const float colWidth = 2.0f / (float)m_patternMaxEmitCount; 827 828 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 829 { 830 // Create triangle strip at this point 831 const rr::VertexPacket* vertex = packets[packetNdx].vertices[0]; 832 const int emitCount = m_spec.pattern[packets[packetNdx].primitiveIDIn]; 833 834 for (int ndx = 0; ndx < emitCount / 2; ++ndx) 835 { 836 output.EmitVertex(vertex->position + tcu::Vec4(2 * ndx * colWidth, 0.0, 0.0, 0.0), vertex->pointSize, vertex->outputs, packets[packetNdx].primitiveIDIn); 837 output.EmitVertex(vertex->position + tcu::Vec4(2 * ndx * colWidth, rowHeight, 0.0, 0.0), vertex->pointSize, vertex->outputs, packets[packetNdx].primitiveIDIn); 838 } 839 output.EndPrimitive(); 840 } 841 } 842 843 std::string OutputCountShader::genGeometrySource (const OutputCountPatternSpec& spec) const 844 { 845 std::ostringstream str; 846 847 // draw row with a triangle strip, always make rectangles 848 for (int ndx = 0; ndx < (int)spec.pattern.size(); ++ndx) 849 DE_ASSERT(spec.pattern[ndx] % 2 == 0); 850 851 str << "#version 310 es\n"; 852 str << "#extension GL_EXT_geometry_shader : require\n"; 853 str << "layout(points) in;\n"; 854 str << "layout(triangle_strip, max_vertices = " << getPatternEmitCount(spec) << ") out;"; 855 str << "\n"; 856 857 str << "in highp vec4 v_geom_FragColor[];\n" 858 "out highp vec4 v_frag_FragColor;\n" 859 "\n" 860 "void main (void)\n" 861 "{\n" 862 " const highp float rowHeight = 2.0 / float(" << spec.pattern.size() << ");\n" 863 " const highp float colWidth = 2.0 / float(" << getPatternEmitCount(spec) << ");\n" 864 "\n"; 865 866 str << " highp int emitCount = "; 867 for (int ndx = 0; ndx < (int)spec.pattern.size() - 1; ++ndx) 868 str << "(gl_PrimitiveIDIn == " << ndx << ") ? (" << spec.pattern[ndx] << ") : ("; 869 str << spec.pattern[(int)spec.pattern.size() - 1] 870 << ((spec.pattern.size() == 1) ? ("") : (")")) 871 << ";\n"; 872 873 str << " for (highp int ndx = 0; ndx < emitCount / 2; ndx++)\n" 874 " {\n" 875 " gl_Position = gl_in[0].gl_Position + vec4(float(ndx) * 2.0 * colWidth, 0.0, 0.0, 0.0);\n" 876 " v_frag_FragColor = v_geom_FragColor[0];\n" 877 " EmitVertex();\n" 878 "\n" 879 " gl_Position = gl_in[0].gl_Position + vec4(float(ndx) * 2.0 * colWidth, rowHeight, 0.0, 0.0);\n" 880 " v_frag_FragColor = v_geom_FragColor[0];\n" 881 " EmitVertex();\n" 882 " }\n" 883 "}\n"; 884 885 return str.str(); 886 } 887 888 size_t OutputCountShader::getPatternEmitCount (const OutputCountPatternSpec& spec) const 889 { 890 return *std::max_element(spec.pattern.begin(), spec.pattern.end()); 891 } 892 893 class BuiltinVariableShader : public sglr::ShaderProgram 894 { 895 public: 896 enum VariableTest 897 { 898 TEST_POINT_SIZE = 0, 899 TEST_PRIMITIVE_ID_IN, 900 TEST_PRIMITIVE_ID, 901 902 TEST_LAST 903 }; 904 905 BuiltinVariableShader (VariableTest test); 906 907 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const; 908 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const; 909 void shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const; 910 911 static const char* getTestAttributeName (VariableTest test); 912 913 private: 914 std::string genGeometrySource (VariableTest test) const; 915 std::string genVertexSource (VariableTest test) const; 916 std::string genFragmentSource (VariableTest test) const; 917 918 const VariableTest m_test; 919 }; 920 921 BuiltinVariableShader::BuiltinVariableShader (VariableTest test) 922 : sglr::ShaderProgram (sglr::pdec::ShaderProgramDeclaration() 923 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT) 924 << sglr::pdec::VertexAttribute(getTestAttributeName(test), rr::GENERICVECTYPE_FLOAT) 925 << sglr::pdec::VertexToGeometryVarying(rr::GENERICVECTYPE_FLOAT) 926 << sglr::pdec::GeometryToFragmentVarying(rr::GENERICVECTYPE_FLOAT) 927 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT) 928 << sglr::pdec::VertexSource(genVertexSource(test)) 929 << sglr::pdec::FragmentSource(genFragmentSource(test)) 930 << sglr::pdec::GeometryShaderDeclaration(rr::GEOMETRYSHADERINPUTTYPE_POINTS, 931 ((test == TEST_POINT_SIZE) ? (rr::GEOMETRYSHADEROUTPUTTYPE_POINTS) : (rr::GEOMETRYSHADEROUTPUTTYPE_TRIANGLE_STRIP)), 932 ((test == TEST_POINT_SIZE) ? (1) : (3))) 933 << sglr::pdec::GeometrySource(genGeometrySource(test).c_str())) 934 , m_test (test) 935 { 936 } 937 938 void BuiltinVariableShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 939 { 940 for (int ndx = 0; ndx < numPackets; ++ndx) 941 { 942 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx); 943 packets[ndx]->pointSize = 1.0f; 944 packets[ndx]->outputs[0] = rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx); 945 } 946 } 947 948 void BuiltinVariableShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 949 { 950 const tcu::Vec4 red = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f); 951 const tcu::Vec4 green = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f); 952 const tcu::Vec4 blue = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f); 953 const tcu::Vec4 yellow = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f); 954 const tcu::Vec4 colors[4] = { yellow, red, green, blue }; 955 956 if (m_test == TEST_POINT_SIZE || m_test == TEST_PRIMITIVE_ID_IN) 957 { 958 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 959 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 960 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx)); 961 } 962 else if (m_test == TEST_PRIMITIVE_ID) 963 { 964 const tcu::Vec4 color = colors[context.primitiveID % 4]; 965 966 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 967 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 968 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color); 969 } 970 else 971 DE_ASSERT(DE_FALSE); 972 } 973 974 void BuiltinVariableShader::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const 975 { 976 DE_UNREF(verticesIn); 977 DE_UNREF(invocationID); 978 979 const tcu::Vec4 red = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f); 980 const tcu::Vec4 green = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f); 981 const tcu::Vec4 blue = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f); 982 const tcu::Vec4 yellow = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f); 983 const tcu::Vec4 colors[4] = { red, green, blue, yellow }; 984 985 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 986 { 987 const rr::VertexPacket* vertex = packets[packetNdx].vertices[0]; 988 989 if (m_test == TEST_POINT_SIZE) 990 { 991 rr::GenericVec4 fragColor; 992 const float pointSize = vertex->outputs[0].get<float>().x() + 1.0f; 993 994 fragColor = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f); 995 output.EmitVertex(vertex->position, pointSize, &fragColor, packets[packetNdx].primitiveIDIn); 996 } 997 else if (m_test == TEST_PRIMITIVE_ID_IN) 998 { 999 rr::GenericVec4 fragColor; 1000 fragColor = colors[packets[packetNdx].primitiveIDIn % 4]; 1001 1002 output.EmitVertex(vertex->position + tcu::Vec4(0.05f, 0.0f, 0.0f, 0.0f), 1.0f, &fragColor, packets[packetNdx].primitiveIDIn); 1003 output.EmitVertex(vertex->position - tcu::Vec4(0.05f, 0.0f, 0.0f, 0.0f), 1.0f, &fragColor, packets[packetNdx].primitiveIDIn); 1004 output.EmitVertex(vertex->position + tcu::Vec4(0.0f, 0.05f, 0.0f, 0.0f), 1.0f, &fragColor, packets[packetNdx].primitiveIDIn); 1005 } 1006 else if (m_test == TEST_PRIMITIVE_ID) 1007 { 1008 const int primitiveID = (int)deFloatFloor(vertex->outputs[0].get<float>().x()) + 3; 1009 1010 output.EmitVertex(vertex->position + tcu::Vec4(0.05f, 0.0f, 0.0f, 0.0f), 1.0f, vertex->outputs, primitiveID); 1011 output.EmitVertex(vertex->position - tcu::Vec4(0.05f, 0.0f, 0.0f, 0.0f), 1.0f, vertex->outputs, primitiveID); 1012 output.EmitVertex(vertex->position + tcu::Vec4(0.0f, 0.05f, 0.0f, 0.0f), 1.0f, vertex->outputs, primitiveID); 1013 } 1014 else 1015 DE_ASSERT(DE_FALSE); 1016 1017 output.EndPrimitive(); 1018 } 1019 } 1020 1021 const char* BuiltinVariableShader::getTestAttributeName (VariableTest test) 1022 { 1023 switch (test) 1024 { 1025 case TEST_POINT_SIZE: return "a_pointSize"; 1026 case TEST_PRIMITIVE_ID_IN: return ""; 1027 case TEST_PRIMITIVE_ID: return "a_primitiveID"; 1028 default: 1029 DE_ASSERT(DE_FALSE); 1030 return ""; 1031 } 1032 } 1033 1034 std::string BuiltinVariableShader::genGeometrySource (VariableTest test) const 1035 { 1036 std::ostringstream buf; 1037 1038 buf << "#version 310 es\n" 1039 "#extension GL_EXT_geometry_shader : require\n"; 1040 1041 if (test == TEST_POINT_SIZE) 1042 buf << "#extension GL_EXT_geometry_point_size : require\n"; 1043 1044 buf << "layout(points) in;\n"; 1045 1046 if (test == TEST_POINT_SIZE) 1047 buf << "layout(points, max_vertices = 1) out;\n"; 1048 else 1049 buf << "layout(triangle_strip, max_vertices = 3) out;\n"; 1050 1051 if (test == TEST_POINT_SIZE) 1052 buf << "in highp vec4 v_geom_pointSize[];\n"; 1053 else if (test == TEST_PRIMITIVE_ID) 1054 buf << "in highp vec4 v_geom_primitiveID[];\n"; 1055 1056 if (test != TEST_PRIMITIVE_ID) 1057 buf << "out highp vec4 v_frag_FragColor;\n"; 1058 1059 buf << "\n" 1060 "void main (void)\n" 1061 "{\n"; 1062 1063 if (test == TEST_POINT_SIZE) 1064 { 1065 buf << " gl_Position = gl_in[0].gl_Position;\n" 1066 " gl_PointSize = v_geom_pointSize[0].x + 1.0;\n" 1067 " v_frag_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n" 1068 " EmitVertex();\n"; 1069 } 1070 else if (test == TEST_PRIMITIVE_ID_IN) 1071 { 1072 buf << " const highp vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n" 1073 " const highp vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n" 1074 " const highp vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n" 1075 " const highp vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n" 1076 " const highp vec4 colors[4] = vec4[4](red, green, blue, yellow);\n" 1077 "\n" 1078 " gl_Position = gl_in[0].gl_Position + vec4(0.05, 0.0, 0.0, 0.0);\n" 1079 " v_frag_FragColor = colors[gl_PrimitiveIDIn % 4];\n" 1080 " EmitVertex();\n" 1081 "\n" 1082 " gl_Position = gl_in[0].gl_Position - vec4(0.05, 0.0, 0.0, 0.0);\n" 1083 " v_frag_FragColor = colors[gl_PrimitiveIDIn % 4];\n" 1084 " EmitVertex();\n" 1085 "\n" 1086 " gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.05, 0.0, 0.0);\n" 1087 " v_frag_FragColor = colors[gl_PrimitiveIDIn % 4];\n" 1088 " EmitVertex();\n"; 1089 } 1090 else if (test == TEST_PRIMITIVE_ID) 1091 { 1092 buf << " gl_Position = gl_in[0].gl_Position + vec4(0.05, 0.0, 0.0, 0.0);\n" 1093 " gl_PrimitiveID = int(floor(v_geom_primitiveID[0].x)) + 3;\n" 1094 " EmitVertex();\n" 1095 "\n" 1096 " gl_Position = gl_in[0].gl_Position - vec4(0.05, 0.0, 0.0, 0.0);\n" 1097 " gl_PrimitiveID = int(floor(v_geom_primitiveID[0].x)) + 3;\n" 1098 " EmitVertex();\n" 1099 "\n" 1100 " gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.05, 0.0, 0.0);\n" 1101 " gl_PrimitiveID = int(floor(v_geom_primitiveID[0].x)) + 3;\n" 1102 " EmitVertex();\n" 1103 "\n"; 1104 } 1105 else 1106 DE_ASSERT(DE_FALSE); 1107 1108 buf << "}\n"; 1109 1110 return buf.str(); 1111 } 1112 1113 std::string BuiltinVariableShader::genVertexSource (VariableTest test) const 1114 { 1115 std::ostringstream buf; 1116 1117 buf << "#version 310 es\n" 1118 "in highp vec4 a_position;\n"; 1119 1120 if (test == TEST_POINT_SIZE) 1121 buf << "in highp vec4 a_pointSize;\n"; 1122 else if (test == TEST_PRIMITIVE_ID) 1123 buf << "in highp vec4 a_primitiveID;\n"; 1124 1125 if (test == TEST_POINT_SIZE) 1126 buf << "out highp vec4 v_geom_pointSize;\n"; 1127 else if (test == TEST_PRIMITIVE_ID) 1128 buf << "out highp vec4 v_geom_primitiveID;\n"; 1129 1130 buf << "void main (void)\n" 1131 "{\n" 1132 " gl_Position = a_position;\n" 1133 " gl_PointSize = 1.0;\n"; 1134 1135 if (test == TEST_POINT_SIZE) 1136 buf << " v_geom_pointSize = a_pointSize;\n"; 1137 else if (test == TEST_PRIMITIVE_ID) 1138 buf << " v_geom_primitiveID = a_primitiveID;\n"; 1139 1140 buf << "}\n"; 1141 1142 return buf.str(); 1143 } 1144 1145 std::string BuiltinVariableShader::genFragmentSource (VariableTest test) const 1146 { 1147 if (test == TEST_POINT_SIZE || test == TEST_PRIMITIVE_ID_IN) 1148 return s_commonShaderSourceFragment; 1149 else if (test == TEST_PRIMITIVE_ID) 1150 { 1151 return "#version 310 es\n" 1152 "#extension GL_EXT_geometry_shader : require\n" 1153 "layout(location = 0) out mediump vec4 fragColor;\n" 1154 "void main (void)\n" 1155 "{\n" 1156 " const mediump vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n" 1157 " const mediump vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n" 1158 " const mediump vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n" 1159 " const mediump vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n" 1160 " const mediump vec4 colors[4] = vec4[4](yellow, red, green, blue);\n" 1161 " fragColor = colors[gl_PrimitiveID % 4];\n" 1162 "}\n"; 1163 } 1164 else 1165 { 1166 DE_ASSERT(DE_FALSE); 1167 return DE_NULL; 1168 } 1169 } 1170 1171 class VaryingOutputCountShader : public sglr::ShaderProgram 1172 { 1173 public: 1174 enum VaryingSource 1175 { 1176 READ_ATTRIBUTE = 0, 1177 READ_UNIFORM, 1178 READ_TEXTURE, 1179 1180 READ_LAST 1181 }; 1182 1183 enum 1184 { 1185 EMIT_COUNT_VERTEX_0 = 6, 1186 EMIT_COUNT_VERTEX_1 = 0, 1187 EMIT_COUNT_VERTEX_2 = -1, 1188 EMIT_COUNT_VERTEX_3 = 10, 1189 }; 1190 1191 VaryingOutputCountShader (VaryingSource source, int maxEmitCount, bool instanced); 1192 1193 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const; 1194 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const; 1195 void shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const; 1196 1197 static const char* getAttributeName (VaryingSource test); 1198 1199 private: 1200 static std::string genGeometrySource (VaryingSource test, int maxEmitCount, bool instanced); 1201 static std::string genVertexSource (VaryingSource test); 1202 1203 const VaryingSource m_test; 1204 const sglr::UniformSlot& m_sampler; 1205 const sglr::UniformSlot& m_emitCount; 1206 const int m_maxEmitCount; 1207 const bool m_instanced; 1208 }; 1209 1210 VaryingOutputCountShader::VaryingOutputCountShader (VaryingSource source, int maxEmitCount, bool instanced) 1211 : sglr::ShaderProgram (sglr::pdec::ShaderProgramDeclaration() 1212 << sglr::pdec::Uniform("u_sampler", glu::TYPE_SAMPLER_2D) 1213 << sglr::pdec::Uniform("u_emitCount", glu::TYPE_INT_VEC4) 1214 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT) 1215 << sglr::pdec::VertexAttribute(getAttributeName(source), rr::GENERICVECTYPE_FLOAT) 1216 << sglr::pdec::VertexToGeometryVarying(rr::GENERICVECTYPE_FLOAT) 1217 << sglr::pdec::GeometryToFragmentVarying(rr::GENERICVECTYPE_FLOAT) 1218 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT) 1219 << sglr::pdec::VertexSource(genVertexSource(source)) 1220 << sglr::pdec::FragmentSource(s_commonShaderSourceFragment) 1221 << sglr::pdec::GeometryShaderDeclaration(rr::GEOMETRYSHADERINPUTTYPE_POINTS, 1222 rr::GEOMETRYSHADEROUTPUTTYPE_TRIANGLE_STRIP, 1223 maxEmitCount, 1224 (instanced) ? (4) : (1)) 1225 << sglr::pdec::GeometrySource(genGeometrySource(source, maxEmitCount, instanced).c_str())) 1226 , m_test (source) 1227 , m_sampler (getUniformByName("u_sampler")) 1228 , m_emitCount (getUniformByName("u_emitCount")) 1229 , m_maxEmitCount (maxEmitCount) 1230 , m_instanced (instanced) 1231 { 1232 } 1233 1234 void VaryingOutputCountShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 1235 { 1236 for (int ndx = 0; ndx < numPackets; ++ndx) 1237 { 1238 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx); 1239 packets[ndx]->outputs[0] = rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx); 1240 } 1241 } 1242 1243 void VaryingOutputCountShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 1244 { 1245 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 1246 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 1247 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx)); 1248 } 1249 1250 void VaryingOutputCountShader::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const 1251 { 1252 DE_UNREF(verticesIn); 1253 1254 const tcu::Vec4 red = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f); 1255 const tcu::Vec4 green = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f); 1256 const tcu::Vec4 blue = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f); 1257 const tcu::Vec4 yellow = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f); 1258 const tcu::Vec4 colors[4] = { red, green, blue, yellow }; 1259 1260 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 1261 { 1262 const rr::VertexPacket* vertex = packets[packetNdx].vertices[0]; 1263 int emitCount = 0; 1264 tcu::Vec4 color = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f); 1265 1266 if (m_test == READ_ATTRIBUTE) 1267 { 1268 emitCount = (int)vertex->outputs[0].get<float>()[(m_instanced) ? (invocationID) : (0)]; 1269 color = tcu::Vec4((emitCount < 10) ? (0.0f) : (1.0f), (emitCount > 10) ? (0.0f) : (1.0f), 1.0f, 1.0f); 1270 } 1271 else if (m_test == READ_UNIFORM) 1272 { 1273 const int primitiveNdx = (m_instanced) ? (invocationID) : ((int)vertex->outputs[0].get<float>().x()); 1274 1275 DE_ASSERT(primitiveNdx >= 0); 1276 DE_ASSERT(primitiveNdx < 4); 1277 1278 emitCount = m_emitCount.value.i4[primitiveNdx]; 1279 color = colors[primitiveNdx]; 1280 } 1281 else if (m_test == READ_TEXTURE) 1282 { 1283 const int primitiveNdx = (m_instanced) ? (invocationID) : ((int)vertex->outputs[0].get<float>().x()); 1284 const tcu::Vec2 texCoord = tcu::Vec2(1.0f / 8.0f + primitiveNdx / 4.0f, 0.5f); 1285 const tcu::Vec4 texColor = m_sampler.sampler.tex2D->sample(texCoord.x(), texCoord.y(), 0.0f); 1286 1287 DE_ASSERT(primitiveNdx >= 0); 1288 DE_ASSERT(primitiveNdx < 4); 1289 1290 color = colors[primitiveNdx]; 1291 emitCount = 0; 1292 1293 if (texColor.x() > 0.0f) 1294 emitCount += (EMIT_COUNT_VERTEX_0 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_0); 1295 if (texColor.y() > 0.0f) 1296 emitCount += (EMIT_COUNT_VERTEX_1 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_1); 1297 if (texColor.z() > 0.0f) 1298 emitCount += (EMIT_COUNT_VERTEX_2 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_2); 1299 if (texColor.w() > 0.0f) 1300 emitCount += (EMIT_COUNT_VERTEX_3 == -1) ? (m_maxEmitCount) : (EMIT_COUNT_VERTEX_3); 1301 } 1302 else 1303 DE_ASSERT(DE_FALSE); 1304 1305 for (int ndx = 0; ndx < (int)emitCount / 2; ++ndx) 1306 { 1307 const float angle = (float(ndx) + 0.5f) / float(emitCount / 2) * 3.142f; 1308 const tcu::Vec4 basePosition = (m_instanced) ? 1309 (vertex->position + tcu::Vec4(deFloatCos(float(invocationID)), deFloatSin(float(invocationID)), 0.0f, 0.0f) * 0.5f) : 1310 (vertex->position); 1311 const tcu::Vec4 position0 = basePosition + tcu::Vec4(deFloatCos(angle), deFloatSin(angle), 0.0f, 0.0f) * 0.15f; 1312 const tcu::Vec4 position1 = basePosition + tcu::Vec4(deFloatCos(angle), -deFloatSin(angle), 0.0f, 0.0f) * 0.15f; 1313 rr::GenericVec4 fragColor; 1314 1315 fragColor = color; 1316 1317 output.EmitVertex(position0, 0.0f, &fragColor, packets[packetNdx].primitiveIDIn); 1318 output.EmitVertex(position1, 0.0f, &fragColor, packets[packetNdx].primitiveIDIn); 1319 } 1320 1321 output.EndPrimitive(); 1322 } 1323 } 1324 1325 const char* VaryingOutputCountShader::getAttributeName (VaryingSource test) 1326 { 1327 switch (test) 1328 { 1329 case READ_ATTRIBUTE: return "a_emitCount"; 1330 case READ_UNIFORM: return "a_vertexNdx"; 1331 case READ_TEXTURE: return "a_vertexNdx"; 1332 default: 1333 DE_ASSERT(DE_FALSE); 1334 return ""; 1335 } 1336 } 1337 1338 std::string VaryingOutputCountShader::genGeometrySource (VaryingSource test, int maxEmitCount, bool instanced) 1339 { 1340 std::ostringstream buf; 1341 1342 buf << "#version 310 es\n" 1343 "#extension GL_EXT_geometry_shader : require\n" 1344 "layout(points" << ((instanced) ? (",invocations=4") : ("")) << ") in;\n" 1345 "layout(triangle_strip, max_vertices = " << maxEmitCount << ") out;\n"; 1346 1347 if (test == READ_ATTRIBUTE) 1348 buf << "in highp vec4 v_geom_emitCount[];\n"; 1349 else if (test == READ_UNIFORM) 1350 buf << "in highp vec4 v_geom_vertexNdx[];\n" 1351 "uniform highp ivec4 u_emitCount;\n"; 1352 else 1353 buf << "in highp vec4 v_geom_vertexNdx[];\n" 1354 "uniform highp sampler2D u_sampler;\n"; 1355 1356 buf << "out highp vec4 v_frag_FragColor;\n" 1357 "\n" 1358 "void main (void)\n" 1359 "{\n"; 1360 1361 // emit count 1362 1363 if (test == READ_ATTRIBUTE) 1364 { 1365 buf << " highp vec4 attrEmitCounts = v_geom_emitCount[0];\n" 1366 " mediump int emitCount = int(attrEmitCounts[" << ((instanced) ? ("gl_InvocationID") : ("0")) << "]);\n"; 1367 } 1368 else if (test == READ_UNIFORM) 1369 { 1370 buf << " mediump int primitiveNdx = " << ((instanced) ? ("gl_InvocationID") : ("int(v_geom_vertexNdx[0].x)")) << ";\n" 1371 " mediump int emitCount = u_emitCount[primitiveNdx];\n"; 1372 } 1373 else if (test == READ_TEXTURE) 1374 { 1375 buf << " highp float primitiveNdx = " << ((instanced) ? ("float(gl_InvocationID)") : ("v_geom_vertexNdx[0].x")) << ";\n" 1376 " highp vec2 texCoord = vec2(1.0 / 8.0 + primitiveNdx / 4.0, 0.5);\n" 1377 " highp vec4 texColor = texture(u_sampler, texCoord);\n" 1378 " mediump int emitCount = 0;\n" 1379 " if (texColor.x > 0.0)\n" 1380 " emitCount += " << ((EMIT_COUNT_VERTEX_0 == -1) ? (maxEmitCount) : (EMIT_COUNT_VERTEX_0)) << ";\n" 1381 " if (texColor.y > 0.0)\n" 1382 " emitCount += " << ((EMIT_COUNT_VERTEX_1 == -1) ? (maxEmitCount) : (EMIT_COUNT_VERTEX_1)) << ";\n" 1383 " if (texColor.z > 0.0)\n" 1384 " emitCount += " << ((EMIT_COUNT_VERTEX_2 == -1) ? (maxEmitCount) : (EMIT_COUNT_VERTEX_2)) << ";\n" 1385 " if (texColor.w > 0.0)\n" 1386 " emitCount += " << ((EMIT_COUNT_VERTEX_3 == -1) ? (maxEmitCount) : (EMIT_COUNT_VERTEX_3)) << ";\n"; 1387 } 1388 else 1389 DE_ASSERT(DE_FALSE); 1390 1391 // color 1392 1393 if (test == READ_ATTRIBUTE) 1394 { 1395 // We don't want color to be compile time constant 1396 buf << " highp vec4 color = vec4((emitCount < 10) ? (0.0) : (1.0), (emitCount > 10) ? (0.0) : (1.0), 1.0, 1.0);\n"; 1397 } 1398 else if (test == READ_UNIFORM || test == READ_TEXTURE) 1399 { 1400 buf << "\n" 1401 " const highp vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n" 1402 " const highp vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n" 1403 " const highp vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n" 1404 " const highp vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n" 1405 " const highp vec4 colors[4] = vec4[4](red, green, blue, yellow);\n" 1406 " highp vec4 color = colors[int(primitiveNdx)];\n"; 1407 } 1408 else 1409 DE_ASSERT(DE_FALSE); 1410 1411 buf << "\n" 1412 " highp vec4 basePos = " << ((instanced) ? ("gl_in[0].gl_Position + 0.5 * vec4(cos(float(gl_InvocationID)), sin(float(gl_InvocationID)), 0.0, 0.0)") : ("gl_in[0].gl_Position")) << ";\n" 1413 " for (mediump int i = 0; i < emitCount / 2; i++)\n" 1414 " {\n" 1415 " highp float angle = (float(i) + 0.5) / float(emitCount / 2) * 3.142;\n" 1416 " gl_Position = basePos + vec4(cos(angle), sin(angle), 0.0, 0.0) * 0.15;\n" 1417 " v_frag_FragColor = color;\n" 1418 " EmitVertex();\n" 1419 " gl_Position = basePos + vec4(cos(angle), -sin(angle), 0.0, 0.0) * 0.15;\n" 1420 " v_frag_FragColor = color;\n" 1421 " EmitVertex();\n" 1422 " }" 1423 "}\n"; 1424 1425 return buf.str(); 1426 } 1427 1428 std::string VaryingOutputCountShader::genVertexSource (VaryingSource test) 1429 { 1430 std::ostringstream buf; 1431 1432 buf << "#version 310 es\n" 1433 "in highp vec4 a_position;\n"; 1434 1435 if (test == READ_ATTRIBUTE) 1436 { 1437 buf << "in highp vec4 a_emitCount;\n"; 1438 buf << "out highp vec4 v_geom_emitCount;\n"; 1439 } 1440 else if (test == READ_UNIFORM || test == READ_TEXTURE) 1441 { 1442 buf << "in highp vec4 a_vertexNdx;\n"; 1443 buf << "out highp vec4 v_geom_vertexNdx;\n"; 1444 } 1445 1446 buf << "void main (void)\n" 1447 "{\n" 1448 " gl_Position = a_position;\n"; 1449 1450 if (test == READ_ATTRIBUTE) 1451 buf << " v_geom_emitCount = a_emitCount;\n"; 1452 else if (test == READ_UNIFORM || test == READ_TEXTURE) 1453 buf << " v_geom_vertexNdx = a_vertexNdx;\n"; 1454 1455 buf << "}\n"; 1456 1457 return buf.str(); 1458 } 1459 1460 class InvocationCountShader : public sglr::ShaderProgram 1461 { 1462 public: 1463 enum OutputCase 1464 { 1465 CASE_FIXED_OUTPUT_COUNTS = 0, 1466 CASE_DIFFERENT_OUTPUT_COUNTS, 1467 1468 CASE_LAST 1469 }; 1470 1471 InvocationCountShader (int numInvocations, OutputCase testCase); 1472 1473 private: 1474 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const; 1475 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const; 1476 void shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const; 1477 1478 static std::string genGeometrySource (int numInvocations, OutputCase testCase); 1479 static size_t getNumVertices (int numInvocations, OutputCase testCase); 1480 1481 const int m_numInvocations; 1482 const OutputCase m_testCase; 1483 }; 1484 1485 InvocationCountShader::InvocationCountShader (int numInvocations, OutputCase testCase) 1486 : sglr::ShaderProgram (sglr::pdec::ShaderProgramDeclaration() 1487 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT) 1488 << sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT) 1489 << sglr::pdec::VertexToGeometryVarying(rr::GENERICVECTYPE_FLOAT) 1490 << sglr::pdec::GeometryToFragmentVarying(rr::GENERICVECTYPE_FLOAT) 1491 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT) 1492 << sglr::pdec::VertexSource(s_commonShaderSourceVertex) 1493 << sglr::pdec::FragmentSource(s_commonShaderSourceFragment) 1494 << sglr::pdec::GeometryShaderDeclaration(rr::GEOMETRYSHADERINPUTTYPE_POINTS, 1495 rr::GEOMETRYSHADEROUTPUTTYPE_TRIANGLE_STRIP, 1496 getNumVertices(numInvocations, testCase), 1497 numInvocations) 1498 << sglr::pdec::GeometrySource(genGeometrySource(numInvocations, testCase).c_str())) 1499 , m_numInvocations (numInvocations) 1500 , m_testCase (testCase) 1501 { 1502 } 1503 1504 void InvocationCountShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 1505 { 1506 for (int ndx = 0; ndx < numPackets; ++ndx) 1507 { 1508 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx); 1509 packets[ndx]->outputs[0] = rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx); 1510 } 1511 } 1512 1513 void InvocationCountShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 1514 { 1515 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 1516 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 1517 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx)); 1518 } 1519 1520 void InvocationCountShader::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const 1521 { 1522 DE_UNREF(verticesIn); 1523 1524 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 1525 { 1526 const float l_angle = float(invocationID) / float(m_numInvocations) * 5.5f; 1527 const float l_radius = 0.6f; 1528 1529 const rr::VertexPacket* vertex = packets[packetNdx].vertices[0]; 1530 1531 if (m_testCase == CASE_FIXED_OUTPUT_COUNTS) 1532 { 1533 const tcu::Vec4 position0 = vertex->position + tcu::Vec4(deFloatCos(l_angle) * (l_radius - 0.1f), deFloatSin(l_angle) * (l_radius - 0.1f), 0.0f, 0.0f); 1534 const tcu::Vec4 position1 = vertex->position + tcu::Vec4(deFloatCos(l_angle+0.1f) * l_radius, deFloatSin(l_angle+0.1f) * l_radius, 0.0f, 0.0f); 1535 const tcu::Vec4 position2 = vertex->position + tcu::Vec4(deFloatCos(l_angle-0.1f) * l_radius, deFloatSin(l_angle-0.1f) * l_radius, 0.0f, 0.0f); 1536 1537 rr::GenericVec4 tipColor; 1538 rr::GenericVec4 baseColor; 1539 1540 tipColor = tcu::Vec4(1.0, 1.0, 0.0, 1.0) * packets[packetNdx].vertices[0]->outputs[0].get<float>(); 1541 baseColor = tcu::Vec4(1.0, 0.0, 0.0, 1.0) * packets[packetNdx].vertices[0]->outputs[0].get<float>(); 1542 1543 output.EmitVertex(position0, 0.0f, &tipColor, packets[packetNdx].primitiveIDIn); 1544 output.EmitVertex(position1, 0.0f, &baseColor, packets[packetNdx].primitiveIDIn); 1545 output.EmitVertex(position2, 0.0f, &baseColor, packets[packetNdx].primitiveIDIn); 1546 output.EndPrimitive(); 1547 } 1548 else if (m_testCase == CASE_DIFFERENT_OUTPUT_COUNTS) 1549 { 1550 const tcu::Vec4 color = tcu::Vec4(float(invocationID % 2), (((invocationID / 2) % 2) == 0) ? (1.0f) : (0.0f), 1.0f, 1.0f); 1551 const tcu::Vec4 basePosition = vertex->position + tcu::Vec4(deFloatCos(l_angle) * l_radius, deFloatSin(l_angle) * l_radius, 0.0f, 0.0f); 1552 const int numNgonVtx = invocationID + 3; 1553 1554 rr::GenericVec4 outColor; 1555 outColor = color; 1556 1557 for (int ndx = 0; ndx + 1 < numNgonVtx; ndx += 2) 1558 { 1559 const float subAngle = (float(ndx) + 1.0f) / float(numNgonVtx) * 3.141f; 1560 1561 output.EmitVertex(basePosition + tcu::Vec4(deFloatCos(subAngle) * 0.1f, deFloatSin(subAngle) * 0.1f, 0.0f, 0.0f), 0.0f, &outColor, packets[packetNdx].primitiveIDIn); 1562 output.EmitVertex(basePosition + tcu::Vec4(deFloatCos(subAngle) * 0.1f, deFloatSin(subAngle) * -0.1f, 0.0f, 0.0f), 0.0f, &outColor, packets[packetNdx].primitiveIDIn); 1563 } 1564 1565 if ((numNgonVtx % 2) == 1) 1566 output.EmitVertex(basePosition + tcu::Vec4(-0.1f, 0.0f, 0.0f, 0.0f), 0.0f, &outColor, packets[packetNdx].primitiveIDIn); 1567 1568 output.EndPrimitive(); 1569 } 1570 } 1571 } 1572 1573 std::string InvocationCountShader::genGeometrySource (int numInvocations, OutputCase testCase) 1574 { 1575 const int maxVertices = (int)getNumVertices(numInvocations, testCase); 1576 std::ostringstream buf; 1577 1578 buf << "#version 310 es\n" 1579 "#extension GL_EXT_geometry_shader : require\n" 1580 "layout(points, invocations = " << numInvocations << ") in;\n" 1581 "layout(triangle_strip, max_vertices = " << maxVertices << ") out;\n" 1582 "\n" 1583 "in highp vec4 v_geom_FragColor[];\n" 1584 "out highp vec4 v_frag_FragColor;\n" 1585 "\n" 1586 "void main ()\n" 1587 "{\n" 1588 " highp float l_angle = float(gl_InvocationID) / float(" << numInvocations << ") * 5.5;\n" 1589 " highp float l_radius = 0.6;\n" 1590 "\n"; 1591 1592 if (testCase == CASE_FIXED_OUTPUT_COUNTS) 1593 { 1594 buf << " v_frag_FragColor = vec4(1.0, 1.0, 0.0, 1.0) * v_geom_FragColor[0];\n" 1595 " gl_Position = gl_in[0].gl_Position + vec4(cos(l_angle) * (l_radius - 0.1), sin(l_angle) * (l_radius - 0.1), 0.0, 0.0);\n" 1596 " EmitVertex();\n" 1597 "\n" 1598 " v_frag_FragColor = vec4(1.0, 0.0, 0.0, 1.0) * v_geom_FragColor[0];\n" 1599 " gl_Position = gl_in[0].gl_Position + vec4(cos(l_angle+0.1) * l_radius, sin(l_angle+0.1) * l_radius, 0.0, 0.0);\n" 1600 " EmitVertex();\n" 1601 "\n" 1602 " v_frag_FragColor = vec4(1.0, 0.0, 0.0, 1.0) * v_geom_FragColor[0];\n" 1603 " gl_Position = gl_in[0].gl_Position + vec4(cos(l_angle-0.1) * l_radius, sin(l_angle-0.1) * l_radius, 0.0, 0.0);\n" 1604 " EmitVertex();\n"; 1605 } 1606 else if (testCase == CASE_DIFFERENT_OUTPUT_COUNTS) 1607 { 1608 buf << " highp vec4 l_color = vec4(float(gl_InvocationID % 2), (((gl_InvocationID / 2) % 2) == 0) ? (1.0) : (0.0), 1.0, 1.0);\n" 1609 " highp vec4 basePosition = gl_in[0].gl_Position + vec4(cos(l_angle) * l_radius, sin(l_angle) * l_radius, 0.0, 0.0);\n" 1610 " mediump int numNgonVtx = gl_InvocationID + 3;\n" 1611 "\n" 1612 " for (int ndx = 0; ndx + 1 < numNgonVtx; ndx += 2)\n" 1613 " {\n" 1614 " highp float sub_angle = (float(ndx) + 1.0) / float(numNgonVtx) * 3.141;\n" 1615 "\n" 1616 " v_frag_FragColor = l_color;\n" 1617 " gl_Position = basePosition + vec4(cos(sub_angle) * 0.1, sin(sub_angle) * 0.1, 0.0, 0.0);\n" 1618 " EmitVertex();\n" 1619 "\n" 1620 " v_frag_FragColor = l_color;\n" 1621 " gl_Position = basePosition + vec4(cos(sub_angle) * 0.1, sin(sub_angle) * -0.1, 0.0, 0.0);\n" 1622 " EmitVertex();\n" 1623 " }\n" 1624 " if ((numNgonVtx % 2) == 1)\n" 1625 " {\n" 1626 " v_frag_FragColor = l_color;\n" 1627 " gl_Position = basePosition + vec4(-0.1, 0.0, 0.0, 0.0);\n" 1628 " EmitVertex();\n" 1629 " }\n"; 1630 } 1631 else 1632 DE_ASSERT(false); 1633 1634 buf << "}\n"; 1635 1636 return buf.str(); 1637 } 1638 1639 size_t InvocationCountShader::getNumVertices (int numInvocations, OutputCase testCase) 1640 { 1641 switch (testCase) 1642 { 1643 case CASE_FIXED_OUTPUT_COUNTS: return 3; 1644 case CASE_DIFFERENT_OUTPUT_COUNTS: return (size_t)(2 + numInvocations); 1645 default: 1646 DE_ASSERT(false); 1647 return 0; 1648 } 1649 } 1650 1651 class InstancedExpansionShader : public sglr::ShaderProgram 1652 { 1653 public: 1654 InstancedExpansionShader (int numInvocations); 1655 1656 private: 1657 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const; 1658 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const; 1659 void shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const; 1660 1661 static std::string genVertexSource (void); 1662 static std::string genFragmentSource (void); 1663 static std::string genGeometrySource (int numInvocations); 1664 1665 const int m_numInvocations; 1666 }; 1667 1668 InstancedExpansionShader::InstancedExpansionShader (int numInvocations) 1669 : sglr::ShaderProgram (sglr::pdec::ShaderProgramDeclaration() 1670 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT) 1671 << sglr::pdec::VertexAttribute("a_offset", rr::GENERICVECTYPE_FLOAT) 1672 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT) 1673 << sglr::pdec::VertexSource(genVertexSource()) 1674 << sglr::pdec::FragmentSource(genFragmentSource()) 1675 << sglr::pdec::GeometryShaderDeclaration(rr::GEOMETRYSHADERINPUTTYPE_POINTS, 1676 rr::GEOMETRYSHADEROUTPUTTYPE_TRIANGLE_STRIP, 1677 4, 1678 numInvocations) 1679 << sglr::pdec::GeometrySource(genGeometrySource(numInvocations).c_str())) 1680 , m_numInvocations (numInvocations) 1681 { 1682 } 1683 1684 void InstancedExpansionShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 1685 { 1686 for (int ndx = 0; ndx < numPackets; ++ndx) 1687 { 1688 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx) + 1689 rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx); 1690 } 1691 } 1692 1693 void InstancedExpansionShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 1694 { 1695 DE_UNREF(packets); 1696 1697 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 1698 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 1699 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); 1700 } 1701 1702 void InstancedExpansionShader::shadePrimitives (rr::GeometryEmitter& output, int verticesIn, const rr::PrimitivePacket* packets, const int numPackets, int invocationID) const 1703 { 1704 DE_UNREF(verticesIn); 1705 1706 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 1707 { 1708 const rr::VertexPacket* vertex = packets[packetNdx].vertices[0]; 1709 const tcu::Vec4 basePosition = vertex->position; 1710 const float phase = float(invocationID) / float(m_numInvocations) * 6.3f; 1711 const tcu::Vec4 centerPosition = basePosition + tcu::Vec4(deFloatCos(phase), deFloatSin(phase), 0.0f, 0.0f) * 0.1f; 1712 1713 output.EmitVertex(centerPosition + tcu::Vec4( 0.0f, -0.1f, 0.0f, 0.0f), 0.0f, DE_NULL, packets[packetNdx].primitiveIDIn); 1714 output.EmitVertex(centerPosition + tcu::Vec4(-0.05f, 0.0f, 0.0f, 0.0f), 0.0f, DE_NULL, packets[packetNdx].primitiveIDIn); 1715 output.EmitVertex(centerPosition + tcu::Vec4( 0.05f, 0.0f, 0.0f, 0.0f), 0.0f, DE_NULL, packets[packetNdx].primitiveIDIn); 1716 output.EndPrimitive(); 1717 } 1718 } 1719 1720 std::string InstancedExpansionShader::genVertexSource (void) 1721 { 1722 return "#version 310 es\n" 1723 "in highp vec4 a_position;\n" 1724 "in highp vec4 a_offset;\n" 1725 "void main (void)\n" 1726 "{\n" 1727 " gl_Position = a_position + a_offset;\n" 1728 "}\n"; 1729 } 1730 1731 std::string InstancedExpansionShader::genFragmentSource (void) 1732 { 1733 return "#version 310 es\n" 1734 "layout(location = 0) out mediump vec4 fragColor;\n" 1735 "void main (void)\n" 1736 "{\n" 1737 " fragColor = vec4(1.0, 1.0, 1.0, 1.0);\n" 1738 "}\n"; 1739 } 1740 1741 std::string InstancedExpansionShader::genGeometrySource (int numInvocations) 1742 { 1743 std::ostringstream buf; 1744 1745 buf << "#version 310 es\n" 1746 "#extension GL_EXT_geometry_shader : require\n" 1747 "layout(points,invocations=" << numInvocations << ") in;\n" 1748 "layout(triangle_strip, max_vertices = 3) out;\n" 1749 "\n" 1750 "void main (void)\n" 1751 "{\n" 1752 " highp vec4 basePosition = gl_in[0].gl_Position;\n" 1753 " highp float phase = float(gl_InvocationID) / float(" << numInvocations << ") * 6.3;\n" 1754 " highp vec4 centerPosition = basePosition + 0.1 * vec4(cos(phase), sin(phase), 0.0, 0.0);\n" 1755 "\n" 1756 " gl_Position = centerPosition + vec4( 0.00, -0.1, 0.0, 0.0);\n" 1757 " EmitVertex();\n" 1758 " gl_Position = centerPosition + vec4(-0.05, 0.0, 0.0, 0.0);\n" 1759 " EmitVertex();\n" 1760 " gl_Position = centerPosition + vec4( 0.05, 0.0, 0.0, 0.0);\n" 1761 " EmitVertex();\n" 1762 "}\n"; 1763 1764 return buf.str(); 1765 } 1766 1767 class GeometryShaderRenderTest : public TestCase 1768 { 1769 public: 1770 enum Flag 1771 { 1772 FLAG_DRAW_INSTANCED = 1, 1773 FLAG_USE_INDICES = 2, 1774 FLAG_USE_RESTART_INDEX = 4, 1775 }; 1776 1777 GeometryShaderRenderTest (Context& context, const char* name, const char* desc, GLenum inputPrimitives, GLenum outputPrimitives, const char* dataAttributeName, int flags = 0); 1778 virtual ~GeometryShaderRenderTest (void); 1779 1780 void init (void); 1781 void deinit (void); 1782 1783 IterateResult iterate (void); 1784 bool compare (void); 1785 1786 virtual sglr::ShaderProgram& getProgram (void) = 0; 1787 1788 protected: 1789 virtual void genVertexAttribData (void); 1790 void renderWithContext (sglr::Context& ctx, sglr::ShaderProgram& program, tcu::Surface& dstSurface); 1791 virtual void preRender (sglr::Context& ctx, GLuint programID); 1792 virtual void postRender (sglr::Context& ctx, GLuint programID); 1793 1794 int m_numDrawVertices; 1795 int m_numDrawInstances; 1796 int m_vertexAttrDivisor; 1797 1798 const GLenum m_inputPrimitives; 1799 const GLenum m_outputPrimitives; 1800 const char* const m_dataAttributeName; 1801 const int m_flags; 1802 1803 tcu::IVec2 m_viewportSize; 1804 int m_interationCount; 1805 1806 tcu::Surface* m_glResult; 1807 tcu::Surface* m_refResult; 1808 1809 sglr::ReferenceContextBuffers* m_refBuffers; 1810 sglr::ReferenceContext* m_refContext; 1811 sglr::Context* m_glContext; 1812 1813 std::vector<tcu::Vec4> m_vertexPosData; 1814 std::vector<tcu::Vec4> m_vertexAttrData; 1815 std::vector<deUint16> m_indices; 1816 }; 1817 1818 GeometryShaderRenderTest::GeometryShaderRenderTest (Context& context, const char* name, const char* desc, GLenum inputPrimitives, GLenum outputPrimitives, const char* dataAttributeName, int flags) 1819 : TestCase (context, name, desc) 1820 , m_numDrawVertices (0) 1821 , m_numDrawInstances (0) 1822 , m_vertexAttrDivisor (0) 1823 , m_inputPrimitives (inputPrimitives) 1824 , m_outputPrimitives (outputPrimitives) 1825 , m_dataAttributeName (dataAttributeName) 1826 , m_flags (flags) 1827 , m_viewportSize (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE) 1828 , m_interationCount (0) 1829 , m_glResult (DE_NULL) 1830 , m_refResult (DE_NULL) 1831 , m_refBuffers (DE_NULL) 1832 , m_refContext (DE_NULL) 1833 , m_glContext (DE_NULL) 1834 { 1835 // Disallow instanced drawElements 1836 DE_ASSERT(((m_flags & FLAG_DRAW_INSTANCED) == 0) || ((m_flags & FLAG_USE_INDICES) == 0)); 1837 // Disallow restart without indices 1838 DE_ASSERT(!(((m_flags & FLAG_USE_RESTART_INDEX) != 0) && ((m_flags & FLAG_USE_INDICES) == 0))); 1839 } 1840 1841 GeometryShaderRenderTest::~GeometryShaderRenderTest (void) 1842 { 1843 deinit(); 1844 } 1845 1846 void GeometryShaderRenderTest::init (void) 1847 { 1848 // requirements 1849 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 1850 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension"); 1851 1852 // gen resources 1853 { 1854 sglr::ReferenceContextLimits limits; 1855 1856 m_glResult = new tcu::Surface(m_viewportSize.x(), m_viewportSize.y()); 1857 m_refResult = new tcu::Surface(m_viewportSize.x(), m_viewportSize.y()); 1858 1859 m_refBuffers = new sglr::ReferenceContextBuffers(m_context.getRenderTarget().getPixelFormat(), m_context.getRenderTarget().getDepthBits(), 0, m_viewportSize.x(), m_viewportSize.y()); 1860 m_refContext = new sglr::ReferenceContext(limits, m_refBuffers->getColorbuffer(), m_refBuffers->getDepthbuffer(), m_refBuffers->getStencilbuffer()); 1861 m_glContext = new sglr::GLContext(m_context.getRenderContext(), m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS | sglr::GLCONTEXT_LOG_PROGRAMS, tcu::IVec4(0, 0, m_viewportSize.x(), m_viewportSize.y())); 1862 } 1863 } 1864 1865 void GeometryShaderRenderTest::deinit (void) 1866 { 1867 delete m_glResult; 1868 delete m_refResult; 1869 1870 m_glResult = DE_NULL; 1871 m_refResult = DE_NULL; 1872 1873 delete m_refContext; 1874 delete m_glContext; 1875 delete m_refBuffers; 1876 1877 m_refBuffers = DE_NULL; 1878 m_refContext = DE_NULL; 1879 m_glContext = DE_NULL; 1880 } 1881 1882 tcu::TestCase::IterateResult GeometryShaderRenderTest::iterate (void) 1883 { 1884 // init() must be called 1885 DE_ASSERT(m_glContext); 1886 DE_ASSERT(m_refContext); 1887 1888 const int iteration = m_interationCount++; 1889 1890 if (iteration == 0) 1891 { 1892 // Check requirements 1893 const int width = m_context.getRenderTarget().getWidth(); 1894 const int height = m_context.getRenderTarget().getHeight(); 1895 1896 if (width < m_viewportSize.x() || height < m_viewportSize.y()) 1897 throw tcu::NotSupportedError(std::string("Render target size must be at least ") + de::toString(m_viewportSize.x()) + "x" + de::toString(m_viewportSize.y())); 1898 1899 // Gen data 1900 genVertexAttribData(); 1901 1902 return CONTINUE; 1903 } 1904 else if (iteration == 1) 1905 { 1906 // Render 1907 sglr::ShaderProgram& program = getProgram(); 1908 1909 renderWithContext(*m_glContext, program, *m_glResult); 1910 renderWithContext(*m_refContext, program, *m_refResult); 1911 1912 return CONTINUE; 1913 } 1914 else 1915 { 1916 if (compare()) 1917 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1918 else 1919 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed"); 1920 1921 return STOP; 1922 } 1923 } 1924 1925 bool GeometryShaderRenderTest::compare (void) 1926 { 1927 using tcu::TestLog; 1928 1929 if (m_context.getRenderTarget().getNumSamples() > 1) 1930 { 1931 return tcu::fuzzyCompare(m_testCtx.getLog(), "Compare Results", "Compare Results", m_refResult->getAccess(), m_glResult->getAccess(), 0.02f, tcu::COMPARE_LOG_RESULT); 1932 } 1933 else 1934 { 1935 tcu::Surface errorMask (m_viewportSize.x(), m_viewportSize.y()); 1936 const tcu::RGBA green (0, 255, 0, 255); 1937 const tcu::RGBA red (255, 0, 0, 255); 1938 const int colorComponentThreshold = 20; 1939 bool testResult = true; 1940 1941 for (int x = 1; x + 1 < m_viewportSize.x(); ++x) 1942 for (int y = 1; y + 1 < m_viewportSize.y(); ++y) 1943 { 1944 bool found = false; 1945 const tcu::RGBA refcolor = m_refResult->getPixel(x, y); 1946 1947 // Got to find similar pixel near this pixel (3x3 kernel) 1948 for (int dx = -1; dx <= 1; ++dx) 1949 for (int dy = -1; dy <= 1; ++dy) 1950 { 1951 const tcu::RGBA testColor = m_glResult->getPixel(x + dx, y + dy); 1952 const tcu::IVec4 colDiff = tcu::abs(testColor.toIVec() - refcolor.toIVec()); 1953 1954 const int maxColDiff = de::max(de::max(colDiff.x(), colDiff.y()), colDiff.z()); // check RGB channels 1955 1956 if (maxColDiff <= colorComponentThreshold) 1957 found = true; 1958 } 1959 1960 if (!found) 1961 testResult = false; 1962 1963 errorMask.setPixel(x, y, (found) ? (green) : (red)); 1964 } 1965 1966 if (testResult) 1967 { 1968 m_testCtx.getLog() << TestLog::ImageSet("Compare result", "Result of rendering") 1969 << TestLog::Image("Result", "Result", *m_glResult) 1970 << TestLog::EndImageSet; 1971 m_testCtx.getLog() << TestLog::Message << "Image compare ok." << TestLog::EndMessage; 1972 } 1973 else 1974 { 1975 m_testCtx.getLog() << TestLog::ImageSet("Compare result", "Result of rendering") 1976 << TestLog::Image("Result", "Result", *m_glResult) 1977 << TestLog::Image("Reference", "Reference", *m_refResult) 1978 << TestLog::Image("ErrorMask", "Error mask", errorMask) 1979 << TestLog::EndImageSet; 1980 m_testCtx.getLog() << TestLog::Message << "Image compare failed." << TestLog::EndMessage; 1981 } 1982 1983 return testResult; 1984 } 1985 } 1986 1987 void GeometryShaderRenderTest::genVertexAttribData (void) 1988 { 1989 // Create 1 X 2 grid in triangle strip adjacent - order 1990 const float scale = 0.3f; 1991 const tcu::Vec4 offset(-0.5f, -0.2f, 0.0f, 1.0f); 1992 1993 m_vertexPosData.resize(12); 1994 m_vertexPosData[ 0] = tcu::Vec4( 0, 0, 0.0f, 0.0f) * scale + offset; 1995 m_vertexPosData[ 1] = tcu::Vec4(-1, -1, 0.0f, 0.0f) * scale + offset; 1996 m_vertexPosData[ 2] = tcu::Vec4( 0, -1, 0.0f, 0.0f) * scale + offset; 1997 m_vertexPosData[ 3] = tcu::Vec4( 1, 1, 0.0f, 0.0f) * scale + offset; 1998 m_vertexPosData[ 4] = tcu::Vec4( 1, 0, 0.0f, 0.0f) * scale + offset; 1999 m_vertexPosData[ 5] = tcu::Vec4( 0, -2, 0.0f, 0.0f) * scale + offset; 2000 m_vertexPosData[ 6] = tcu::Vec4( 1, -1, 0.0f, 0.0f) * scale + offset; 2001 m_vertexPosData[ 7] = tcu::Vec4( 2, 1, 0.0f, 0.0f) * scale + offset; 2002 m_vertexPosData[ 8] = tcu::Vec4( 2, 0, 0.0f, 0.0f) * scale + offset; 2003 m_vertexPosData[ 9] = tcu::Vec4( 1, -2, 0.0f, 0.0f) * scale + offset; 2004 m_vertexPosData[10] = tcu::Vec4( 2, -1, 0.0f, 0.0f) * scale + offset; 2005 m_vertexPosData[11] = tcu::Vec4( 3, 0, 0.0f, 0.0f) * scale + offset; 2006 2007 // Red and white 2008 m_vertexAttrData.resize(12); 2009 for (int i = 0; i < 12; ++i) 2010 m_vertexAttrData[i] = (i % 2 == 0) ? tcu::Vec4(1, 1, 1, 1) : tcu::Vec4(1, 0, 0, 1); 2011 2012 m_numDrawVertices = 12; 2013 } 2014 2015 void GeometryShaderRenderTest::renderWithContext (sglr::Context& ctx, sglr::ShaderProgram& program, tcu::Surface& dstSurface) 2016 { 2017 #define CHECK_GL_CTX_ERRORS() glu::checkError(ctx.getError(), DE_NULL, __FILE__, __LINE__) 2018 2019 const GLuint programId = ctx.createProgram(&program); 2020 const GLint attrPosLoc = ctx.getAttribLocation(programId, "a_position"); 2021 const GLint attrColLoc = ctx.getAttribLocation(programId, m_dataAttributeName); 2022 GLuint vaoId = 0; 2023 GLuint vertexPosBuf = 0; 2024 GLuint vertexAttrBuf = 0; 2025 GLuint elementArrayBuf = 0; 2026 2027 ctx.genVertexArrays(1, &vaoId); 2028 ctx.bindVertexArray(vaoId); 2029 2030 if (attrPosLoc != -1) 2031 { 2032 ctx.genBuffers(1, &vertexPosBuf); 2033 ctx.bindBuffer(GL_ARRAY_BUFFER, vertexPosBuf); 2034 ctx.bufferData(GL_ARRAY_BUFFER, m_vertexPosData.size() * sizeof(tcu::Vec4), &m_vertexPosData[0], GL_STATIC_DRAW); 2035 ctx.vertexAttribPointer(attrPosLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 2036 ctx.enableVertexAttribArray(attrPosLoc); 2037 } 2038 2039 if (attrColLoc != -1) 2040 { 2041 ctx.genBuffers(1, &vertexAttrBuf); 2042 ctx.bindBuffer(GL_ARRAY_BUFFER, vertexAttrBuf); 2043 ctx.bufferData(GL_ARRAY_BUFFER, m_vertexAttrData.size() * sizeof(tcu::Vec4), &m_vertexAttrData[0], GL_STATIC_DRAW); 2044 ctx.vertexAttribPointer(attrColLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 2045 ctx.enableVertexAttribArray(attrColLoc); 2046 2047 if (m_vertexAttrDivisor) 2048 ctx.vertexAttribDivisor(attrColLoc, m_vertexAttrDivisor); 2049 } 2050 2051 if (m_flags & FLAG_USE_INDICES) 2052 { 2053 ctx.genBuffers(1, &elementArrayBuf); 2054 ctx.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuf); 2055 ctx.bufferData(GL_ELEMENT_ARRAY_BUFFER, m_indices.size() * sizeof(deUint16), &m_indices[0], GL_STATIC_DRAW); 2056 } 2057 2058 ctx.clearColor(0, 0, 0, 1); 2059 ctx.clear(GL_COLOR_BUFFER_BIT); 2060 2061 ctx.viewport(0, 0, m_viewportSize.x(), m_viewportSize.y()); 2062 CHECK_GL_CTX_ERRORS(); 2063 2064 ctx.useProgram(programId); 2065 CHECK_GL_CTX_ERRORS(); 2066 2067 preRender(ctx, programId); 2068 CHECK_GL_CTX_ERRORS(); 2069 2070 if (m_flags & FLAG_USE_RESTART_INDEX) 2071 { 2072 ctx.enable(GL_PRIMITIVE_RESTART_FIXED_INDEX); 2073 CHECK_GL_CTX_ERRORS(); 2074 } 2075 2076 if (m_flags & FLAG_USE_INDICES) 2077 ctx.drawElements(m_inputPrimitives, m_numDrawVertices, GL_UNSIGNED_SHORT, DE_NULL); 2078 else if (m_flags & FLAG_DRAW_INSTANCED) 2079 ctx.drawArraysInstanced(m_inputPrimitives, 0, m_numDrawVertices, m_numDrawInstances); 2080 else 2081 ctx.drawArrays(m_inputPrimitives, 0, m_numDrawVertices); 2082 2083 CHECK_GL_CTX_ERRORS(); 2084 2085 if (m_flags & FLAG_USE_RESTART_INDEX) 2086 { 2087 ctx.disable(GL_PRIMITIVE_RESTART_FIXED_INDEX); 2088 CHECK_GL_CTX_ERRORS(); 2089 } 2090 2091 postRender(ctx, programId); 2092 CHECK_GL_CTX_ERRORS(); 2093 2094 ctx.useProgram(0); 2095 2096 if (attrPosLoc != -1) 2097 ctx.disableVertexAttribArray(attrPosLoc); 2098 if (attrColLoc != -1) 2099 ctx.disableVertexAttribArray(attrColLoc); 2100 2101 if (vertexPosBuf) 2102 ctx.deleteBuffers(1, &vertexPosBuf); 2103 if (vertexAttrBuf) 2104 ctx.deleteBuffers(1, &vertexAttrBuf); 2105 if (elementArrayBuf) 2106 ctx.deleteBuffers(1, &elementArrayBuf); 2107 2108 ctx.deleteVertexArrays(1, &vaoId); 2109 2110 CHECK_GL_CTX_ERRORS(); 2111 2112 ctx.finish(); 2113 ctx.readPixels(dstSurface, 0, 0, m_viewportSize.x(), m_viewportSize.y()); 2114 2115 #undef CHECK_GL_CTX_ERRORS 2116 } 2117 2118 void GeometryShaderRenderTest::preRender (sglr::Context& ctx, GLuint programID) 2119 { 2120 DE_UNREF(ctx); 2121 DE_UNREF(programID); 2122 } 2123 2124 void GeometryShaderRenderTest::postRender (sglr::Context& ctx, GLuint programID) 2125 { 2126 DE_UNREF(ctx); 2127 DE_UNREF(programID); 2128 } 2129 2130 class GeometryExpanderRenderTest : public GeometryShaderRenderTest 2131 { 2132 public: 2133 GeometryExpanderRenderTest (Context& context, const char* name, const char* desc, GLenum inputPrimitives, GLenum outputPrimitives); 2134 virtual ~GeometryExpanderRenderTest (void); 2135 2136 sglr::ShaderProgram& getProgram (void); 2137 2138 private: 2139 VertexExpanderShader m_program; 2140 }; 2141 2142 GeometryExpanderRenderTest::GeometryExpanderRenderTest (Context& context, const char* name, const char* desc, GLenum inputPrimitives, GLenum outputPrimitives) 2143 : GeometryShaderRenderTest (context, name, desc, inputPrimitives, outputPrimitives, "a_color") 2144 , m_program (sglr::rr_util::mapGLGeometryShaderInputType(inputPrimitives), sglr::rr_util::mapGLGeometryShaderOutputType(outputPrimitives)) 2145 { 2146 } 2147 2148 GeometryExpanderRenderTest::~GeometryExpanderRenderTest (void) 2149 { 2150 } 2151 2152 sglr::ShaderProgram& GeometryExpanderRenderTest::getProgram (void) 2153 { 2154 return m_program; 2155 } 2156 2157 class EmitTest : public GeometryShaderRenderTest 2158 { 2159 public: 2160 EmitTest (Context& context, const char* name, const char* desc, int emitCountA, int endCountA, int emitCountB, int endCountB, GLenum outputType); 2161 2162 sglr::ShaderProgram& getProgram (void); 2163 private: 2164 void genVertexAttribData (void); 2165 2166 VertexEmitterShader m_program; 2167 }; 2168 2169 EmitTest::EmitTest (Context& context, const char* name, const char* desc, int emitCountA, int endCountA, int emitCountB, int endCountB, GLenum outputType) 2170 : GeometryShaderRenderTest (context, name, desc, GL_POINTS, outputType, "a_color") 2171 , m_program (emitCountA, endCountA, emitCountB, endCountB, sglr::rr_util::mapGLGeometryShaderOutputType(outputType)) 2172 { 2173 } 2174 2175 sglr::ShaderProgram& EmitTest::getProgram (void) 2176 { 2177 return m_program; 2178 } 2179 2180 void EmitTest::genVertexAttribData (void) 2181 { 2182 m_vertexPosData.resize(1); 2183 m_vertexPosData[0] = tcu::Vec4(0, 0, 0, 1); 2184 2185 m_vertexAttrData.resize(1); 2186 m_vertexAttrData[0] = tcu::Vec4(1, 1, 1, 1); 2187 2188 m_numDrawVertices = 1; 2189 } 2190 2191 class VaryingTest : public GeometryShaderRenderTest 2192 { 2193 public: 2194 VaryingTest (Context& context, const char* name, const char* desc, int vertexOut, int geometryOut); 2195 2196 sglr::ShaderProgram& getProgram (void); 2197 private: 2198 void genVertexAttribData (void); 2199 2200 VertexVaryingShader m_program; 2201 }; 2202 2203 VaryingTest::VaryingTest (Context& context, const char* name, const char* desc, int vertexOut, int geometryOut) 2204 : GeometryShaderRenderTest (context, name, desc, GL_TRIANGLES, GL_TRIANGLE_STRIP, "a_color") 2205 , m_program (vertexOut, geometryOut) 2206 { 2207 } 2208 2209 sglr::ShaderProgram& VaryingTest::getProgram (void) 2210 { 2211 return m_program; 2212 } 2213 2214 void VaryingTest::genVertexAttribData (void) 2215 { 2216 m_vertexPosData.resize(3); 2217 m_vertexPosData[0] = tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f); 2218 m_vertexPosData[1] = tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f); 2219 m_vertexPosData[2] = tcu::Vec4(0.1f, 0.0f, 0.0f, 1.0f); 2220 2221 m_vertexAttrData.resize(3); 2222 m_vertexAttrData[0] = tcu::Vec4(0.7f, 0.4f, 0.6f, 1.0f); 2223 m_vertexAttrData[1] = tcu::Vec4(0.9f, 0.2f, 0.5f, 1.0f); 2224 m_vertexAttrData[2] = tcu::Vec4(0.1f, 0.8f, 0.3f, 1.0f); 2225 2226 m_numDrawVertices = 3; 2227 } 2228 2229 class TriangleStripAdjacencyVertexCountTest : public GeometryExpanderRenderTest 2230 { 2231 public: 2232 TriangleStripAdjacencyVertexCountTest (Context& context, const char* name, const char* desc, int numInputVertices); 2233 2234 private: 2235 void genVertexAttribData (void); 2236 2237 int m_numInputVertices; 2238 }; 2239 2240 TriangleStripAdjacencyVertexCountTest::TriangleStripAdjacencyVertexCountTest (Context& context, const char* name, const char* desc, int numInputVertices) 2241 : GeometryExpanderRenderTest (context, name, desc, GL_TRIANGLE_STRIP_ADJACENCY, GL_TRIANGLE_STRIP) 2242 , m_numInputVertices (numInputVertices) 2243 { 2244 } 2245 2246 void TriangleStripAdjacencyVertexCountTest::genVertexAttribData (void) 2247 { 2248 this->GeometryShaderRenderTest::genVertexAttribData(); 2249 m_numDrawVertices = m_numInputVertices; 2250 } 2251 2252 class NegativeDrawCase : public TestCase 2253 { 2254 public: 2255 NegativeDrawCase (Context& context, const char* name, const char* desc, GLenum inputType, GLenum inputPrimitives); 2256 ~NegativeDrawCase (void); 2257 2258 void init (void); 2259 void deinit (void); 2260 2261 IterateResult iterate (void); 2262 2263 private: 2264 sglr::Context* m_ctx; 2265 VertexExpanderShader* m_program; 2266 GLenum m_inputType; 2267 GLenum m_inputPrimitives; 2268 }; 2269 2270 NegativeDrawCase::NegativeDrawCase (Context& context, const char* name, const char* desc, GLenum inputType, GLenum inputPrimitives) 2271 : TestCase (context, name, desc) 2272 , m_ctx (DE_NULL) 2273 , m_program (DE_NULL) 2274 , m_inputType (inputType) 2275 , m_inputPrimitives (inputPrimitives) 2276 { 2277 } 2278 2279 NegativeDrawCase::~NegativeDrawCase (void) 2280 { 2281 deinit(); 2282 } 2283 2284 void NegativeDrawCase::init (void) 2285 { 2286 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 2287 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension"); 2288 2289 m_ctx = new sglr::GLContext(m_context.getRenderContext(), m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS | sglr::GLCONTEXT_LOG_PROGRAMS, tcu::IVec4(0, 0, 1, 1)); 2290 m_program = new VertexExpanderShader(sglr::rr_util::mapGLGeometryShaderInputType(m_inputType), rr::GEOMETRYSHADEROUTPUTTYPE_POINTS); 2291 } 2292 2293 void NegativeDrawCase::deinit (void) 2294 { 2295 delete m_ctx; 2296 delete m_program; 2297 2298 m_ctx = NULL; 2299 m_program = DE_NULL; 2300 } 2301 2302 NegativeDrawCase::IterateResult NegativeDrawCase::iterate (void) 2303 { 2304 const GLuint programId = m_ctx->createProgram(m_program); 2305 const GLint attrPosLoc = m_ctx->getAttribLocation(programId, "a_position"); 2306 const tcu::Vec4 vertexPosData (0, 0, 0, 1); 2307 2308 GLuint vaoId = 0; 2309 GLuint vertexPosBuf = 0; 2310 GLenum errorCode = 0; 2311 2312 m_ctx->genVertexArrays(1, &vaoId); 2313 m_ctx->bindVertexArray(vaoId); 2314 2315 m_ctx->genBuffers(1, &vertexPosBuf); 2316 m_ctx->bindBuffer(GL_ARRAY_BUFFER, vertexPosBuf); 2317 m_ctx->bufferData(GL_ARRAY_BUFFER, sizeof(tcu::Vec4), vertexPosData.m_data, GL_STATIC_DRAW); 2318 m_ctx->vertexAttribPointer(attrPosLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 2319 m_ctx->enableVertexAttribArray(attrPosLoc); 2320 2321 m_ctx->clearColor(0, 0, 0, 1); 2322 m_ctx->clear(GL_COLOR_BUFFER_BIT); 2323 2324 m_ctx->viewport(0, 0, 1, 1); 2325 2326 m_ctx->useProgram(programId); 2327 2328 // no errors before 2329 glu::checkError(m_ctx->getError(), "", __FILE__, __LINE__); 2330 2331 m_ctx->drawArrays(m_inputPrimitives, 0, 1); 2332 2333 errorCode = m_ctx->getError(); 2334 if (errorCode != GL_INVALID_OPERATION) 2335 { 2336 m_testCtx.getLog() << tcu::TestLog::Message << "Expected GL_INVALID_OPERATION, got " << glu::getErrorStr(errorCode) << tcu::TestLog::EndMessage; 2337 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got wrong error code"); 2338 } 2339 else 2340 { 2341 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2342 } 2343 2344 m_ctx->useProgram(0); 2345 2346 m_ctx->disableVertexAttribArray(attrPosLoc); 2347 m_ctx->deleteBuffers(1, &vertexPosBuf); 2348 2349 m_ctx->deleteVertexArrays(1, &vaoId); 2350 2351 return STOP; 2352 } 2353 2354 class OutputCountCase : public GeometryShaderRenderTest 2355 { 2356 public: 2357 OutputCountCase (Context& context, const char* name, const char* desc, const OutputCountPatternSpec&); 2358 private: 2359 void init (void); 2360 void deinit (void); 2361 2362 sglr::ShaderProgram& getProgram (void); 2363 void genVertexAttribData (void); 2364 2365 const int m_primitiveCount; 2366 OutputCountShader* m_program; 2367 OutputCountPatternSpec m_spec; 2368 }; 2369 2370 OutputCountCase::OutputCountCase (Context& context, const char* name, const char* desc, const OutputCountPatternSpec& spec) 2371 : GeometryShaderRenderTest (context, name, desc, GL_POINTS, GL_TRIANGLE_STRIP, "a_color") 2372 , m_primitiveCount ((int)spec.pattern.size()) 2373 , m_program (DE_NULL) 2374 , m_spec (spec) 2375 { 2376 } 2377 2378 void OutputCountCase::init (void) 2379 { 2380 // Check requirements and adapt to them 2381 { 2382 const int componentsPerVertex = 4 + 4; // vec4 pos, vec4 color 2383 const int testVertices = *std::max_element(m_spec.pattern.begin(), m_spec.pattern.end()); 2384 glw::GLint maxVertices = 0; 2385 glw::GLint maxComponents = 0; 2386 2387 // check the extension before querying anything 2388 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 2389 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension"); 2390 2391 m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &maxVertices); 2392 m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &maxComponents); 2393 2394 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_OUTPUT_VERTICES = " << maxVertices << tcu::TestLog::EndMessage; 2395 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS = " << maxComponents << tcu::TestLog::EndMessage; 2396 m_testCtx.getLog() << tcu::TestLog::Message << "Components per vertex = " << componentsPerVertex << tcu::TestLog::EndMessage; 2397 2398 if (testVertices == -1) 2399 { 2400 // "max vertices"-case 2401 DE_ASSERT((int)m_spec.pattern.size() == 1); 2402 m_spec.pattern[0] = de::min(maxVertices, maxComponents / componentsPerVertex); 2403 2404 // make sure size is dividable by 2, as OutputShader requires 2405 m_spec.pattern[0] = m_spec.pattern[0] & ~0x00000001; 2406 2407 if (m_spec.pattern[0] == 0) 2408 throw tcu::InternalError("Pattern size is invalid."); 2409 } 2410 else 2411 { 2412 // normal case 2413 if (testVertices > maxVertices) 2414 throw tcu::NotSupportedError(de::toString(testVertices) + " output vertices required."); 2415 if (testVertices * componentsPerVertex > maxComponents) 2416 throw tcu::NotSupportedError(de::toString(testVertices * componentsPerVertex) + " output components required."); 2417 } 2418 } 2419 2420 // Log what the test tries to do 2421 2422 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << (int)m_spec.pattern.size() << " row(s).\nOne geometry shader invocation generates one row.\nRow sizes:" << tcu::TestLog::EndMessage; 2423 for (int ndx = 0; ndx < (int)m_spec.pattern.size(); ++ndx) 2424 m_testCtx.getLog() << tcu::TestLog::Message << "Row " << ndx << ": " << m_spec.pattern[ndx] << " vertices." << tcu::TestLog::EndMessage; 2425 2426 // Gen shader 2427 DE_ASSERT(!m_program); 2428 m_program = new OutputCountShader(m_spec); 2429 2430 // Case init 2431 GeometryShaderRenderTest::init(); 2432 } 2433 2434 void OutputCountCase::deinit (void) 2435 { 2436 if (m_program) 2437 { 2438 delete m_program; 2439 m_program = DE_NULL; 2440 } 2441 2442 GeometryShaderRenderTest::deinit(); 2443 } 2444 2445 sglr::ShaderProgram& OutputCountCase::getProgram (void) 2446 { 2447 return *m_program; 2448 } 2449 2450 void OutputCountCase::genVertexAttribData (void) 2451 { 2452 m_vertexPosData.resize(m_primitiveCount); 2453 m_vertexAttrData.resize(m_primitiveCount); 2454 2455 for (int ndx = 0; ndx < m_primitiveCount; ++ndx) 2456 { 2457 m_vertexPosData[ndx] = tcu::Vec4(-1.0f, ((float)ndx) / m_primitiveCount * 2.0f - 1.0f, 0.0f, 1.0f); 2458 m_vertexAttrData[ndx] = (ndx % 2 == 0) ? tcu::Vec4(1, 1, 1, 1) : tcu::Vec4(1, 0, 0, 1); 2459 } 2460 2461 m_numDrawVertices = m_primitiveCount; 2462 } 2463 2464 class BuiltinVariableRenderTest : public GeometryShaderRenderTest 2465 { 2466 public: 2467 BuiltinVariableRenderTest (Context& context, const char* name, const char* desc, BuiltinVariableShader::VariableTest test, int flags = 0); 2468 2469 private: 2470 void init (void); 2471 2472 sglr::ShaderProgram& getProgram (void); 2473 void genVertexAttribData (void); 2474 2475 BuiltinVariableShader m_program; 2476 const BuiltinVariableShader::VariableTest m_test; 2477 }; 2478 2479 BuiltinVariableRenderTest::BuiltinVariableRenderTest (Context& context, const char* name, const char* desc, BuiltinVariableShader::VariableTest test, int flags) 2480 : GeometryShaderRenderTest (context, name, desc, GL_POINTS, GL_POINTS, BuiltinVariableShader::getTestAttributeName(test), flags) 2481 , m_program (test) 2482 , m_test (test) 2483 { 2484 } 2485 2486 void BuiltinVariableRenderTest::init (void) 2487 { 2488 // Requirements 2489 if (m_test == BuiltinVariableShader::TEST_POINT_SIZE) 2490 { 2491 const float requiredPointSize = 5.0f; 2492 2493 tcu::Vec2 range = tcu::Vec2(1.0f, 1.0f); 2494 2495 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_point_size")) 2496 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_point_size extension"); 2497 2498 m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_POINT_SIZE_RANGE, range.getPtr()); 2499 if (range.y() < requiredPointSize) 2500 throw tcu::NotSupportedError("Test case requires point size " + de::toString(requiredPointSize)); 2501 } 2502 2503 // Shader init 2504 GeometryShaderRenderTest::init(); 2505 } 2506 2507 sglr::ShaderProgram& BuiltinVariableRenderTest::getProgram (void) 2508 { 2509 return m_program; 2510 } 2511 2512 void BuiltinVariableRenderTest::genVertexAttribData (void) 2513 { 2514 m_vertexPosData.resize(4); 2515 m_vertexPosData[0] = tcu::Vec4( 0.5f, 0.0f, 0.0f, 1.0f); 2516 m_vertexPosData[1] = tcu::Vec4( 0.0f, 0.5f, 0.0f, 1.0f); 2517 m_vertexPosData[2] = tcu::Vec4(-0.7f, -0.1f, 0.0f, 1.0f); 2518 m_vertexPosData[3] = tcu::Vec4(-0.1f, -0.7f, 0.0f, 1.0f); 2519 2520 m_vertexAttrData.resize(4); 2521 m_vertexAttrData[0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f); 2522 m_vertexAttrData[1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f); 2523 m_vertexAttrData[2] = tcu::Vec4(2.0f, 0.0f, 0.0f, 0.0f); 2524 m_vertexAttrData[3] = tcu::Vec4(3.0f, 0.0f, 0.0f, 0.0f); 2525 2526 // Only used by primitive ID restart test 2527 m_indices.resize(4); 2528 m_indices[0] = 3; 2529 m_indices[1] = 2; 2530 m_indices[2] = 0xFFFF; // restart 2531 m_indices[3] = 1; 2532 2533 m_numDrawVertices = 4; 2534 } 2535 2536 class LayeredRenderCase : public TestCase 2537 { 2538 public: 2539 enum LayeredRenderTargetType 2540 { 2541 TARGET_CUBE = 0, 2542 TARGET_3D, 2543 TARGET_1D_ARRAY, 2544 TARGET_2D_ARRAY, 2545 TARGET_2D_MS_ARRAY, 2546 2547 TARGET_LAST 2548 }; 2549 enum TestType 2550 { 2551 TEST_DEFAULT_LAYER, // !< draw to default layer 2552 TEST_SINGLE_LAYER, // !< draw to single layer 2553 TEST_ALL_LAYERS, // !< draw all layers 2554 TEST_DIFFERENT_LAYERS, // !< draw different content to different layers 2555 TEST_INVOCATION_PER_LAYER, // !< draw to all layers, one invocation per layer 2556 TEST_MULTIPLE_LAYERS_PER_INVOCATION, // !< draw to all layers, multiple invocations write to multiple layers 2557 TEST_LAYER_ID, // !< draw to all layers, verify gl_Layer fragment input 2558 TEST_LAYER_PROVOKING_VERTEX, // !< draw primitive with vertices in different layers, check which layer it was drawn to 2559 2560 TEST_LAST 2561 }; 2562 LayeredRenderCase (Context& context, const char* name, const char* desc, LayeredRenderTargetType target, TestType test); 2563 ~LayeredRenderCase (void); 2564 2565 void init (void); 2566 void deinit (void); 2567 IterateResult iterate (void); 2568 2569 private: 2570 void initTexture (void); 2571 void initFbo (void); 2572 void initRenderShader (void); 2573 void initSamplerShader (void); 2574 2575 std::string genFragmentSource (void) const; 2576 std::string genGeometrySource (void) const; 2577 std::string genSamplerFragmentSource (void) const; 2578 2579 void renderToTexture (void); 2580 void sampleTextureLayer (tcu::Surface& dst, int layer); 2581 bool verifyLayerContent (const tcu::Surface& layer, int layerNdx); 2582 bool verifyImageSingleColoredRow (const tcu::Surface& layer, float rowWidthRatio, const tcu::Vec4& color, bool logging = true); 2583 bool verifyEmptyImage (const tcu::Surface& layer, bool logging = true); 2584 bool verifyProvokingVertexLayers (const tcu::Surface& layer0, const tcu::Surface& layer1); 2585 2586 static int getTargetLayers (LayeredRenderTargetType target); 2587 static glw::GLenum getTargetTextureTarget (LayeredRenderTargetType target); 2588 static tcu::IVec3 getTargetDimensions (LayeredRenderTargetType target); 2589 static tcu::IVec2 getResolveDimensions (LayeredRenderTargetType target); 2590 2591 const LayeredRenderTargetType m_target; 2592 const TestType m_test; 2593 const int m_numLayers; 2594 const int m_targetLayer; 2595 const tcu::IVec2 m_resolveDimensions; 2596 2597 int m_iteration; 2598 bool m_allLayersOk; 2599 2600 glw::GLuint m_texture; 2601 glw::GLuint m_fbo; 2602 glu::ShaderProgram* m_renderShader; 2603 glu::ShaderProgram* m_samplerShader; 2604 2605 glw::GLint m_samplerSamplerLoc; 2606 glw::GLint m_samplerLayerLoc; 2607 2608 glw::GLenum m_provokingVertex; 2609 }; 2610 2611 LayeredRenderCase::LayeredRenderCase (Context& context, const char* name, const char* desc, LayeredRenderTargetType target, TestType test) 2612 : TestCase (context, name, desc) 2613 , m_target (target) 2614 , m_test (test) 2615 , m_numLayers (getTargetLayers(target)) 2616 , m_targetLayer (m_numLayers / 2) 2617 , m_resolveDimensions (getResolveDimensions(target)) 2618 , m_iteration (0) 2619 , m_allLayersOk (true) 2620 , m_texture (0) 2621 , m_fbo (0) 2622 , m_renderShader (DE_NULL) 2623 , m_samplerShader (DE_NULL) 2624 , m_samplerSamplerLoc (-1) 2625 , m_samplerLayerLoc (-1) 2626 , m_provokingVertex (0) 2627 { 2628 } 2629 2630 LayeredRenderCase::~LayeredRenderCase (void) 2631 { 2632 deinit(); 2633 } 2634 2635 void LayeredRenderCase::init (void) 2636 { 2637 // Requirements 2638 2639 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 2640 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension"); 2641 2642 if (m_target == TARGET_2D_MS_ARRAY && !m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array")) 2643 throw tcu::NotSupportedError("Test requires OES_texture_storage_multisample_2d_array extension"); 2644 2645 if (m_context.getRenderTarget().getWidth() < m_resolveDimensions.x() || m_context.getRenderTarget().getHeight() < m_resolveDimensions.y()) 2646 throw tcu::NotSupportedError("Render target size must be at least " + de::toString(m_resolveDimensions.x()) + "x" + de::toString(m_resolveDimensions.y())); 2647 2648 // log what the test tries to do 2649 2650 if (m_test == TEST_DEFAULT_LAYER) 2651 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering to the default layer." << tcu::TestLog::EndMessage; 2652 else if (m_test == TEST_SINGLE_LAYER) 2653 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering to a single layer." << tcu::TestLog::EndMessage; 2654 else if (m_test == TEST_ALL_LAYERS) 2655 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering to all layers." << tcu::TestLog::EndMessage; 2656 else if (m_test == TEST_DIFFERENT_LAYERS) 2657 m_testCtx.getLog() << tcu::TestLog::Message << "Outputting different number of vertices to each layer." << tcu::TestLog::EndMessage; 2658 else if (m_test == TEST_INVOCATION_PER_LAYER) 2659 m_testCtx.getLog() << tcu::TestLog::Message << "Using a different invocation to output to each layer." << tcu::TestLog::EndMessage; 2660 else if (m_test == TEST_MULTIPLE_LAYERS_PER_INVOCATION) 2661 m_testCtx.getLog() << tcu::TestLog::Message << "Outputting to each layer from multiple invocations." << tcu::TestLog::EndMessage; 2662 else if (m_test == TEST_LAYER_ID) 2663 m_testCtx.getLog() << tcu::TestLog::Message << "Using gl_Layer in fragment shader." << tcu::TestLog::EndMessage; 2664 else if (m_test == TEST_LAYER_PROVOKING_VERTEX) 2665 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying LAYER_PROVOKING_VERTEX." << tcu::TestLog::EndMessage; 2666 else 2667 DE_ASSERT(false); 2668 2669 // init resources 2670 2671 initTexture(); 2672 initFbo(); 2673 initRenderShader(); 2674 initSamplerShader(); 2675 } 2676 2677 void LayeredRenderCase::deinit (void) 2678 { 2679 if (m_texture) 2680 { 2681 m_context.getRenderContext().getFunctions().deleteTextures(1, &m_texture); 2682 m_texture = 0; 2683 } 2684 2685 if (m_fbo) 2686 { 2687 m_context.getRenderContext().getFunctions().deleteFramebuffers(1, &m_fbo); 2688 m_fbo = 0; 2689 } 2690 2691 delete m_renderShader; 2692 delete m_samplerShader; 2693 2694 m_renderShader = DE_NULL; 2695 m_samplerShader = DE_NULL; 2696 } 2697 2698 LayeredRenderCase::IterateResult LayeredRenderCase::iterate (void) 2699 { 2700 ++m_iteration; 2701 2702 if (m_iteration == 1) 2703 { 2704 if (m_test == TEST_LAYER_PROVOKING_VERTEX) 2705 { 2706 // which layer the implementation claims to render to 2707 2708 gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint> state; 2709 2710 m_context.getRenderContext().getFunctions().getIntegerv(GL_LAYER_PROVOKING_VERTEX, &state); 2711 GLU_EXPECT_NO_ERROR(m_context.getRenderContext().getFunctions().getError(), "getInteger(GL_LAYER_PROVOKING_VERTEX)"); 2712 2713 if (!state.verifyValidity(m_testCtx)) 2714 return STOP; 2715 2716 m_testCtx.getLog() << tcu::TestLog::Message << "GL_LAYER_PROVOKING_VERTEX = " << glu::getProvokingVertexStr(state) << tcu::TestLog::EndMessage; 2717 2718 if (state != GL_FIRST_VERTEX_CONVENTION && 2719 state != GL_LAST_VERTEX_CONVENTION && 2720 state != GL_UNDEFINED_VERTEX) 2721 { 2722 m_testCtx.getLog() << tcu::TestLog::Message << "getInteger(GL_LAYER_PROVOKING_VERTEX) returned illegal value. Got " << state << tcu::TestLog::EndMessage; 2723 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected provoking vertex value"); 2724 return STOP; 2725 } 2726 2727 m_provokingVertex = (glw::GLenum)state; 2728 } 2729 2730 // render to texture 2731 { 2732 const tcu::ScopedLogSection section(m_testCtx.getLog(), "RenderToTexture", "Render to layered texture"); 2733 2734 // render to layered texture with the geometry shader 2735 renderToTexture(); 2736 } 2737 2738 return CONTINUE; 2739 } 2740 else if (m_test == TEST_LAYER_PROVOKING_VERTEX && m_provokingVertex == GL_UNDEFINED_VERTEX) 2741 { 2742 // Verification requires information from another layers, layers not independent 2743 { 2744 const tcu::ScopedLogSection section (m_testCtx.getLog(), "VerifyLayers", "Verify layers 0 and 1"); 2745 tcu::Surface layer0 (m_resolveDimensions.x(), m_resolveDimensions.y()); 2746 tcu::Surface layer1 (m_resolveDimensions.x(), m_resolveDimensions.y()); 2747 2748 // sample layer to frame buffer 2749 sampleTextureLayer(layer0, 0); 2750 sampleTextureLayer(layer1, 1); 2751 2752 m_allLayersOk &= verifyProvokingVertexLayers(layer0, layer1); 2753 } 2754 2755 // Other layers empty 2756 for (int layerNdx = 2; layerNdx < m_numLayers; ++layerNdx) 2757 { 2758 const tcu::ScopedLogSection section (m_testCtx.getLog(), "VerifyLayer", "Verify layer " + de::toString(layerNdx)); 2759 tcu::Surface layer (m_resolveDimensions.x(), m_resolveDimensions.y()); 2760 2761 // sample layer to frame buffer 2762 sampleTextureLayer(layer, layerNdx); 2763 2764 // verify 2765 m_allLayersOk &= verifyEmptyImage(layer); 2766 } 2767 } 2768 else 2769 { 2770 // Layers independent 2771 2772 const int layerNdx = m_iteration - 2; 2773 const tcu::ScopedLogSection section (m_testCtx.getLog(), "VerifyLayer", "Verify layer " + de::toString(layerNdx)); 2774 tcu::Surface layer (m_resolveDimensions.x(), m_resolveDimensions.y()); 2775 2776 // sample layer to frame buffer 2777 sampleTextureLayer(layer, layerNdx); 2778 2779 // verify 2780 m_allLayersOk &= verifyLayerContent(layer, layerNdx); 2781 2782 if (layerNdx < m_numLayers-1) 2783 return CONTINUE; 2784 } 2785 2786 // last iteration 2787 if (m_allLayersOk) 2788 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2789 else 2790 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Detected invalid layer content"); 2791 2792 return STOP; 2793 } 2794 2795 void LayeredRenderCase::initTexture (void) 2796 { 2797 DE_ASSERT(!m_texture); 2798 2799 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2800 const tcu::IVec3 texSize = getTargetDimensions(m_target); 2801 const tcu::TextureFormat texFormat = glu::mapGLInternalFormat(GL_RGBA8); 2802 const glu::TransferFormat transferFormat = glu::getTransferFormat(texFormat); 2803 2804 gl.genTextures(1, &m_texture); 2805 GLU_EXPECT_NO_ERROR(gl.getError(), "gen texture"); 2806 2807 switch (m_target) 2808 { 2809 case TARGET_CUBE: 2810 m_testCtx.getLog() << tcu::TestLog::Message << "Creating cubemap texture, size = " << texSize.x() << "x" << texSize.y() << tcu::TestLog::EndMessage; 2811 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_texture); 2812 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, texSize.x(), texSize.y(), 0, transferFormat.format, transferFormat.dataType, DE_NULL); 2813 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, texSize.x(), texSize.y(), 0, transferFormat.format, transferFormat.dataType, DE_NULL); 2814 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, texSize.x(), texSize.y(), 0, transferFormat.format, transferFormat.dataType, DE_NULL); 2815 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, texSize.x(), texSize.y(), 0, transferFormat.format, transferFormat.dataType, DE_NULL); 2816 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, texSize.x(), texSize.y(), 0, transferFormat.format, transferFormat.dataType, DE_NULL); 2817 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, texSize.x(), texSize.y(), 0, transferFormat.format, transferFormat.dataType, DE_NULL); 2818 break; 2819 2820 case TARGET_3D: 2821 m_testCtx.getLog() << tcu::TestLog::Message << "Creating 3d texture, size = " << texSize.x() << "x" << texSize.y() << "x" << texSize.z() << tcu::TestLog::EndMessage; 2822 gl.bindTexture(GL_TEXTURE_3D, m_texture); 2823 gl.texImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, texSize.x(), texSize.y(), texSize.z(), 0, transferFormat.format, transferFormat.dataType, DE_NULL); 2824 break; 2825 2826 case TARGET_1D_ARRAY: 2827 m_testCtx.getLog() << tcu::TestLog::Message << "Creating 1d texture array, size = " << texSize.x() << ", layers = " << texSize.y() << tcu::TestLog::EndMessage; 2828 gl.bindTexture(GL_TEXTURE_1D_ARRAY, m_texture); 2829 gl.texImage2D(GL_TEXTURE_1D_ARRAY, 0, GL_RGBA8, texSize.x(), texSize.y(), 0, transferFormat.format, transferFormat.dataType, DE_NULL); 2830 break; 2831 2832 case TARGET_2D_ARRAY: 2833 m_testCtx.getLog() << tcu::TestLog::Message << "Creating 2d texture array, size = " << texSize.x() << "x" << texSize.y() << ", layers = " << texSize.z() << tcu::TestLog::EndMessage; 2834 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_texture); 2835 gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, texSize.x(), texSize.y(), texSize.z(), 0, transferFormat.format, transferFormat.dataType, DE_NULL); 2836 break; 2837 2838 case TARGET_2D_MS_ARRAY: 2839 { 2840 const int numSamples = 2; 2841 2842 int maxSamples = 0; 2843 gl.getIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &maxSamples); 2844 2845 m_testCtx.getLog() << tcu::TestLog::Message << "Creating 2d multisample texture array, size = " << texSize.x() << "x" << texSize.y() << ", layers = " << texSize.z() << ", samples = " << numSamples << tcu::TestLog::EndMessage; 2846 2847 if (numSamples > maxSamples) 2848 throw tcu::NotSupportedError("Test requires " + de::toString(numSamples) + " color texture samples." ); 2849 2850 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, m_texture); 2851 gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, numSamples, GL_RGBA8, texSize.x(), texSize.y(), texSize.z(), GL_TRUE); 2852 break; 2853 } 2854 2855 default: 2856 DE_ASSERT(DE_FALSE); 2857 } 2858 GLU_EXPECT_NO_ERROR(gl.getError(), "tex image"); 2859 2860 // Multisample textures don't use filters 2861 if (getTargetTextureTarget(m_target) != GL_TEXTURE_2D_MULTISAMPLE_ARRAY) 2862 { 2863 gl.texParameteri(getTargetTextureTarget(m_target), GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2864 gl.texParameteri(getTargetTextureTarget(m_target), GL_TEXTURE_MIN_FILTER, GL_NEAREST); 2865 gl.texParameteri(getTargetTextureTarget(m_target), GL_TEXTURE_WRAP_S, GL_REPEAT); 2866 gl.texParameteri(getTargetTextureTarget(m_target), GL_TEXTURE_WRAP_T, GL_REPEAT); 2867 gl.texParameteri(getTargetTextureTarget(m_target), GL_TEXTURE_WRAP_R, GL_REPEAT); 2868 GLU_EXPECT_NO_ERROR(gl.getError(), "tex filter"); 2869 } 2870 } 2871 2872 void LayeredRenderCase::initFbo (void) 2873 { 2874 DE_ASSERT(!m_fbo); 2875 2876 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2877 2878 m_testCtx.getLog() << tcu::TestLog::Message << "Creating FBO" << tcu::TestLog::EndMessage; 2879 2880 gl.genFramebuffers(1, &m_fbo); 2881 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo); 2882 gl.framebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture, 0); 2883 gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 2884 2885 GLU_EXPECT_NO_ERROR(gl.getError(), "setup fbo"); 2886 } 2887 2888 void LayeredRenderCase::initRenderShader (void) 2889 { 2890 const tcu::ScopedLogSection section(m_testCtx.getLog(), "RenderToTextureShader", "Create layered rendering shader program"); 2891 2892 static const char* const positionVertex = "#version 310 es\n" 2893 "void main (void)\n" 2894 "{\n" 2895 " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" 2896 "}\n"; 2897 2898 m_renderShader = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(positionVertex) << glu::FragmentSource(genFragmentSource()) << glu::GeometrySource(genGeometrySource())); 2899 m_testCtx.getLog() << *m_renderShader; 2900 2901 if (!m_renderShader->isOk()) 2902 throw tcu::TestError("failed to build render shader"); 2903 } 2904 2905 void LayeredRenderCase::initSamplerShader (void) 2906 { 2907 const tcu::ScopedLogSection section(m_testCtx.getLog(), "TextureSamplerShader", "Create shader sampler program"); 2908 2909 static const char* const positionVertex = "#version 310 es\n" 2910 "in highp vec4 a_position;\n" 2911 "void main (void)\n" 2912 "{\n" 2913 " gl_Position = a_position;\n" 2914 "}\n"; 2915 2916 m_samplerShader = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 2917 << glu::VertexSource(positionVertex) 2918 << glu::FragmentSource(genSamplerFragmentSource())); 2919 2920 m_testCtx.getLog() << *m_samplerShader; 2921 2922 if (!m_samplerShader->isOk()) 2923 throw tcu::TestError("failed to build sampler shader"); 2924 2925 m_samplerSamplerLoc = m_context.getRenderContext().getFunctions().getUniformLocation(m_samplerShader->getProgram(), "u_sampler"); 2926 if (m_samplerSamplerLoc == -1) 2927 throw tcu::TestError("u_sampler uniform location = -1"); 2928 2929 m_samplerLayerLoc = m_context.getRenderContext().getFunctions().getUniformLocation(m_samplerShader->getProgram(), "u_layer"); 2930 if (m_samplerLayerLoc == -1) 2931 throw tcu::TestError("u_layer uniform location = -1"); 2932 } 2933 2934 std::string LayeredRenderCase::genFragmentSource (void) const 2935 { 2936 static const char* const fragmentLayerIdShader = "#version 310 es\n" 2937 "#extension GL_EXT_geometry_shader : require\n" 2938 "layout(location = 0) out mediump vec4 fragColor;\n" 2939 "void main (void)\n" 2940 "{\n" 2941 " fragColor = vec4(((gl_Layer % 2) == 1) ? 1.0 : 0.5,\n" 2942 " (((gl_Layer / 2) % 2) == 1) ? 1.0 : 0.5,\n" 2943 " (gl_Layer == 0) ? 1.0 : 0.0,\n" 2944 " 1.0);\n" 2945 "}\n"; 2946 2947 if (m_test != TEST_LAYER_ID) 2948 return std::string(s_commonShaderSourceFragment); 2949 else 2950 return std::string(fragmentLayerIdShader); 2951 } 2952 2953 std::string LayeredRenderCase::genGeometrySource (void) const 2954 { 2955 // TEST_DIFFERENT_LAYERS: draw 0 quad to first layer, 1 to second, etc. 2956 // TEST_ALL_LAYERS: draw 1 quad to all layers 2957 // TEST_MULTIPLE_LAYERS_PER_INVOCATION: draw 1 triangle to "current layer" and 1 triangle to another layer 2958 // else: draw 1 quad to some single layer 2959 const int maxVertices = (m_test == TEST_DIFFERENT_LAYERS) ? ((2 + m_numLayers-1) * m_numLayers) : 2960 (m_test == TEST_ALL_LAYERS || m_test == TEST_LAYER_ID) ? (m_numLayers * 4) : 2961 (m_test == TEST_MULTIPLE_LAYERS_PER_INVOCATION) ? (6) : 2962 (m_test == TEST_LAYER_PROVOKING_VERTEX) ? (6) : 2963 (4); 2964 std::ostringstream buf; 2965 2966 buf << "#version 310 es\n" 2967 "#extension GL_EXT_geometry_shader : require\n"; 2968 2969 if (m_test == TEST_INVOCATION_PER_LAYER || m_test == TEST_MULTIPLE_LAYERS_PER_INVOCATION) 2970 buf << "layout(points, invocations=" << m_numLayers << ") in;\n"; 2971 else 2972 buf << "layout(points) in;\n"; 2973 2974 buf << "layout(triangle_strip, max_vertices = " << maxVertices << ") out;\n" 2975 "out highp vec4 v_frag_FragColor;\n" 2976 "\n" 2977 "void main (void)\n" 2978 "{\n"; 2979 2980 if (m_test == TEST_DEFAULT_LAYER) 2981 { 2982 buf << " const highp vec4 white = vec4(1.0, 1.0, 1.0, 1.0);\n\n" 2983 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 2984 " v_frag_FragColor = white;\n" 2985 " EmitVertex();\n\n" 2986 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 2987 " v_frag_FragColor = white;\n" 2988 " EmitVertex();\n\n" 2989 " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n" 2990 " v_frag_FragColor = white;\n" 2991 " EmitVertex();\n\n" 2992 " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n" 2993 " v_frag_FragColor = white;\n" 2994 " EmitVertex();\n"; 2995 } 2996 else if (m_test == TEST_SINGLE_LAYER) 2997 { 2998 buf << " const highp vec4 white = vec4(1.0, 1.0, 1.0, 1.0);\n\n" 2999 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 3000 " gl_Layer = " << m_targetLayer << ";\n" 3001 " v_frag_FragColor = white;\n" 3002 " EmitVertex();\n\n" 3003 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 3004 " gl_Layer = " << m_targetLayer << ";\n" 3005 " v_frag_FragColor = white;\n" 3006 " EmitVertex();\n\n" 3007 " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n" 3008 " gl_Layer = " << m_targetLayer << ";\n" 3009 " v_frag_FragColor = white;\n" 3010 " EmitVertex();\n\n" 3011 " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n" 3012 " gl_Layer = " << m_targetLayer << ";\n" 3013 " v_frag_FragColor = white;\n" 3014 " EmitVertex();\n"; 3015 } 3016 else if (m_test == TEST_ALL_LAYERS || m_test == TEST_LAYER_ID) 3017 { 3018 DE_ASSERT(m_numLayers <= 6); 3019 3020 buf << " const highp vec4 white = vec4(1.0, 1.0, 1.0, 1.0);\n" 3021 " const highp vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n" 3022 " const highp vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n" 3023 " const highp vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n" 3024 " const highp vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n" 3025 " const highp vec4 magenta = vec4(1.0, 0.0, 1.0, 1.0);\n" 3026 " const highp vec4 colors[6] = vec4[6](white, red, green, blue, yellow, magenta);\n\n" 3027 " for (mediump int layerNdx = 0; layerNdx < " << m_numLayers << "; ++layerNdx)\n" 3028 " {\n" 3029 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 3030 " gl_Layer = layerNdx;\n" 3031 " v_frag_FragColor = colors[layerNdx];\n" 3032 " EmitVertex();\n\n" 3033 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 3034 " gl_Layer = layerNdx;\n" 3035 " v_frag_FragColor = colors[layerNdx];\n" 3036 " EmitVertex();\n\n" 3037 " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n" 3038 " gl_Layer = layerNdx;\n" 3039 " v_frag_FragColor = colors[layerNdx];\n" 3040 " EmitVertex();\n\n" 3041 " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n" 3042 " gl_Layer = layerNdx;\n" 3043 " v_frag_FragColor = colors[layerNdx];\n" 3044 " EmitVertex();\n" 3045 " EndPrimitive();\n" 3046 " }\n"; 3047 } 3048 else if (m_test == TEST_DIFFERENT_LAYERS) 3049 { 3050 DE_ASSERT(m_numLayers <= 6); 3051 3052 buf << " const highp vec4 white = vec4(1.0, 1.0, 1.0, 1.0);\n\n" 3053 " for (mediump int layerNdx = 0; layerNdx < " << m_numLayers << "; ++layerNdx)\n" 3054 " {\n" 3055 " for (mediump int colNdx = 0; colNdx <= layerNdx; ++colNdx)\n" 3056 " {\n" 3057 " highp float posX = float(colNdx) / float(" << m_numLayers << ") * 2.0 - 1.0;\n\n" 3058 " gl_Position = vec4(posX, 1.0, 0.0, 1.0);\n" 3059 " gl_Layer = layerNdx;\n" 3060 " v_frag_FragColor = white;\n" 3061 " EmitVertex();\n\n" 3062 " gl_Position = vec4(posX, -1.0, 0.0, 1.0);\n" 3063 " gl_Layer = layerNdx;\n" 3064 " v_frag_FragColor = white;\n" 3065 " EmitVertex();\n" 3066 " }\n" 3067 " EndPrimitive();\n" 3068 " }\n"; 3069 } 3070 else if (m_test == TEST_INVOCATION_PER_LAYER) 3071 { 3072 buf << " const highp vec4 white = vec4(1.0, 1.0, 1.0, 1.0);\n" 3073 " const highp vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n" 3074 " const highp vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n" 3075 " const highp vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n" 3076 " const highp vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n" 3077 " const highp vec4 magenta = vec4(1.0, 0.0, 1.0, 1.0);\n" 3078 " const highp vec4 colors[6] = vec4[6](white, red, green, blue, yellow, magenta);\n" 3079 "\n" 3080 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 3081 " gl_Layer = gl_InvocationID;\n" 3082 " v_frag_FragColor = colors[gl_InvocationID];\n" 3083 " EmitVertex();\n\n" 3084 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 3085 " gl_Layer = gl_InvocationID;\n" 3086 " v_frag_FragColor = colors[gl_InvocationID];\n" 3087 " EmitVertex();\n\n" 3088 " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n" 3089 " gl_Layer = gl_InvocationID;\n" 3090 " v_frag_FragColor = colors[gl_InvocationID];\n" 3091 " EmitVertex();\n\n" 3092 " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n" 3093 " gl_Layer = gl_InvocationID;\n" 3094 " v_frag_FragColor = colors[gl_InvocationID];\n" 3095 " EmitVertex();\n" 3096 " EndPrimitive();\n"; 3097 } 3098 else if (m_test == TEST_MULTIPLE_LAYERS_PER_INVOCATION) 3099 { 3100 buf << " const highp vec4 white = vec4(1.0, 1.0, 1.0, 1.0);\n" 3101 "\n" 3102 " mediump int layerA = gl_InvocationID;\n" 3103 " mediump int layerB = (gl_InvocationID + 1) % " << m_numLayers << ";\n" 3104 " highp float aEnd = float(layerA) / float(" << m_numLayers << ") * 2.0 - 1.0;\n" 3105 " highp float bEnd = float(layerB) / float(" << m_numLayers << ") * 2.0 - 1.0;\n" 3106 "\n" 3107 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 3108 " gl_Layer = layerA;\n" 3109 " v_frag_FragColor = white;\n" 3110 " EmitVertex();\n\n" 3111 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 3112 " gl_Layer = layerA;\n" 3113 " v_frag_FragColor = white;\n" 3114 " EmitVertex();\n\n" 3115 " gl_Position = vec4(aEnd, -1.0, 0.0, 1.0);\n" 3116 " gl_Layer = layerA;\n" 3117 " v_frag_FragColor = white;\n" 3118 " EmitVertex();\n\n" 3119 " EndPrimitive();\n" 3120 "\n" 3121 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 3122 " gl_Layer = layerB;\n" 3123 " v_frag_FragColor = white;\n" 3124 " EmitVertex();\n\n" 3125 " gl_Position = vec4(bEnd, 1.0, 0.0, 1.0);\n" 3126 " gl_Layer = layerB;\n" 3127 " v_frag_FragColor = white;\n" 3128 " EmitVertex();\n\n" 3129 " gl_Position = vec4(bEnd, -1.0, 0.0, 1.0);\n" 3130 " gl_Layer = layerB;\n" 3131 " v_frag_FragColor = white;\n" 3132 " EmitVertex();\n\n" 3133 " EndPrimitive();\n"; 3134 } 3135 else if (m_test == TEST_LAYER_PROVOKING_VERTEX) 3136 { 3137 buf << " const highp vec4 white = vec4(1.0, 1.0, 1.0, 1.0);\n\n" 3138 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 3139 " gl_Layer = 0;\n" 3140 " v_frag_FragColor = white;\n" 3141 " EmitVertex();\n\n" 3142 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 3143 " gl_Layer = 1;\n" 3144 " v_frag_FragColor = white;\n" 3145 " EmitVertex();\n\n" 3146 " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n" 3147 " gl_Layer = 1;\n" 3148 " v_frag_FragColor = white;\n" 3149 " EmitVertex();\n\n" 3150 " EndPrimitive();\n\n" 3151 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 3152 " gl_Layer = 0;\n" 3153 " v_frag_FragColor = white;\n" 3154 " EmitVertex();\n\n" 3155 " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n" 3156 " gl_Layer = 1;\n" 3157 " v_frag_FragColor = white;\n" 3158 " EmitVertex();\n\n" 3159 " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n" 3160 " gl_Layer = 1;\n" 3161 " v_frag_FragColor = white;\n" 3162 " EmitVertex();\n"; 3163 } 3164 else 3165 DE_ASSERT(DE_FALSE); 3166 3167 buf << "}\n"; 3168 3169 return buf.str(); 3170 } 3171 3172 std::string LayeredRenderCase::genSamplerFragmentSource (void) const 3173 { 3174 std::ostringstream buf; 3175 3176 buf << "#version 310 es\n"; 3177 if (m_target == TARGET_2D_MS_ARRAY) 3178 buf << "#extension GL_OES_texture_storage_multisample_2d_array : require\n"; 3179 buf << "layout(location = 0) out mediump vec4 fragColor;\n"; 3180 3181 switch (m_target) 3182 { 3183 case TARGET_CUBE: buf << "uniform highp samplerCube u_sampler;\n"; break; 3184 case TARGET_3D: buf << "uniform highp sampler3D u_sampler;\n"; break; 3185 case TARGET_2D_ARRAY: buf << "uniform highp sampler2DArray u_sampler;\n"; break; 3186 case TARGET_1D_ARRAY: buf << "uniform highp sampler1DArray u_sampler;\n"; break; 3187 case TARGET_2D_MS_ARRAY: buf << "uniform highp sampler2DMSArray u_sampler;\n"; break; 3188 default: 3189 DE_ASSERT(DE_FALSE); 3190 } 3191 3192 buf << "uniform highp int u_layer;\n" 3193 "void main (void)\n" 3194 "{\n"; 3195 3196 switch (m_target) 3197 { 3198 case TARGET_CUBE: 3199 buf << " highp vec2 facepos = 2.0 * gl_FragCoord.xy / vec2(ivec2(" << m_resolveDimensions.x() << ", " << m_resolveDimensions.y() << ")) - vec2(1.0, 1.0);\n" 3200 " if (u_layer == 0)\n" 3201 " fragColor = textureLod(u_sampler, vec3(1.0, -facepos.y, -facepos.x), 0.0);\n" 3202 " else if (u_layer == 1)\n" 3203 " fragColor = textureLod(u_sampler, vec3(-1.0, -facepos.y, facepos.x), 0.0);\n" 3204 " else if (u_layer == 2)\n" 3205 " fragColor = textureLod(u_sampler, vec3(facepos.x, 1.0, facepos.y), 0.0);\n" 3206 " else if (u_layer == 3)\n" 3207 " fragColor = textureLod(u_sampler, vec3(facepos.x, -1.0, -facepos.y), 0.0);\n" 3208 " else if (u_layer == 4)\n" 3209 " fragColor = textureLod(u_sampler, vec3(facepos.x, -facepos.y, 1.0), 0.0);\n" 3210 " else if (u_layer == 5)\n" 3211 " fragColor = textureLod(u_sampler, vec3(-facepos.x, -facepos.y, -1.0), 0.0);\n" 3212 " else\n" 3213 " fragColor = vec4(1.0, 0.0, 1.0, 1.0);\n"; 3214 break; 3215 3216 case TARGET_3D: 3217 case TARGET_2D_ARRAY: 3218 case TARGET_2D_MS_ARRAY: 3219 buf << " highp ivec2 screenpos = ivec2(floor(gl_FragCoord.xy));\n" 3220 " fragColor = texelFetch(u_sampler, ivec3(screenpos, u_layer), 0);\n"; 3221 break; 3222 3223 case TARGET_1D_ARRAY: 3224 buf << " highp ivec2 screenpos = ivec2(floor(gl_FragCoord.xy));\n" 3225 " fragColor = texelFetch(u_sampler, ivec2(screenpos.x, u_layer), 0);\n"; 3226 break; 3227 3228 default: 3229 DE_ASSERT(DE_FALSE); 3230 } 3231 buf << "}\n"; 3232 return buf.str(); 3233 } 3234 3235 void LayeredRenderCase::renderToTexture (void) 3236 { 3237 const tcu::IVec3 texSize = getTargetDimensions(m_target); 3238 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3239 glu::VertexArray vao (m_context.getRenderContext()); 3240 3241 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering to texture" << tcu::TestLog::EndMessage; 3242 3243 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo); 3244 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 3245 gl.clear(GL_COLOR_BUFFER_BIT); 3246 gl.viewport(0, 0, texSize.x(), texSize.y()); 3247 gl.clear(GL_COLOR_BUFFER_BIT); 3248 3249 gl.bindVertexArray(*vao); 3250 gl.useProgram(m_renderShader->getProgram()); 3251 gl.drawArrays(GL_POINTS, 0, 1); 3252 gl.useProgram(0); 3253 gl.bindVertexArray(0); 3254 gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 3255 3256 GLU_EXPECT_NO_ERROR(gl.getError(), "render"); 3257 } 3258 3259 void LayeredRenderCase::sampleTextureLayer (tcu::Surface& dst, int layer) 3260 { 3261 DE_ASSERT(dst.getWidth() == m_resolveDimensions.x()); 3262 DE_ASSERT(dst.getHeight() == m_resolveDimensions.y()); 3263 3264 static const tcu::Vec4 fullscreenQuad[4] = 3265 { 3266 tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), 3267 tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), 3268 tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), 3269 tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), 3270 }; 3271 3272 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3273 const int positionLoc = gl.getAttribLocation(m_samplerShader->getProgram(), "a_position"); 3274 glu::VertexArray vao (m_context.getRenderContext()); 3275 glu::Buffer buf (m_context.getRenderContext()); 3276 3277 m_testCtx.getLog() << tcu::TestLog::Message << "Sampling from texture layer " << layer << tcu::TestLog::EndMessage; 3278 3279 gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f); 3280 gl.clear(GL_COLOR_BUFFER_BIT); 3281 gl.viewport(0, 0, m_resolveDimensions.x(), m_resolveDimensions.y()); 3282 GLU_EXPECT_NO_ERROR(gl.getError(), "clear"); 3283 3284 gl.bindBuffer(GL_ARRAY_BUFFER, *buf); 3285 gl.bufferData(GL_ARRAY_BUFFER, sizeof(fullscreenQuad), fullscreenQuad, GL_STATIC_DRAW); 3286 GLU_EXPECT_NO_ERROR(gl.getError(), "buf"); 3287 3288 gl.bindVertexArray(*vao); 3289 gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 3290 gl.enableVertexAttribArray(positionLoc); 3291 GLU_EXPECT_NO_ERROR(gl.getError(), "setup attribs"); 3292 3293 gl.activeTexture(GL_TEXTURE0); 3294 gl.bindTexture(getTargetTextureTarget(m_target), m_texture); 3295 GLU_EXPECT_NO_ERROR(gl.getError(), "bind texture"); 3296 3297 gl.useProgram(m_samplerShader->getProgram()); 3298 gl.uniform1i(m_samplerLayerLoc, layer); 3299 gl.uniform1i(m_samplerSamplerLoc, 0); 3300 GLU_EXPECT_NO_ERROR(gl.getError(), "setup program"); 3301 3302 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4); 3303 GLU_EXPECT_NO_ERROR(gl.getError(), "draw"); 3304 3305 gl.useProgram(0); 3306 gl.bindVertexArray(0); 3307 GLU_EXPECT_NO_ERROR(gl.getError(), "clean"); 3308 3309 glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess()); 3310 } 3311 3312 bool LayeredRenderCase::verifyLayerContent (const tcu::Surface& layer, int layerNdx) 3313 { 3314 const tcu::Vec4 white = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f); 3315 const tcu::Vec4 red = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f); 3316 const tcu::Vec4 green = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f); 3317 const tcu::Vec4 blue = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f); 3318 const tcu::Vec4 yellow = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f); 3319 const tcu::Vec4 magenta = tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f); 3320 const tcu::Vec4 colors[6] = { white, red, green, blue, yellow, magenta }; 3321 3322 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying layer contents" << tcu::TestLog::EndMessage; 3323 3324 switch (m_test) 3325 { 3326 case TEST_DEFAULT_LAYER: 3327 if (layerNdx == 0) 3328 return verifyImageSingleColoredRow(layer, 0.5f, white); 3329 else 3330 return verifyEmptyImage(layer); 3331 3332 case TEST_SINGLE_LAYER: 3333 if (layerNdx == m_targetLayer) 3334 return verifyImageSingleColoredRow(layer, 0.5f, white); 3335 else 3336 return verifyEmptyImage(layer); 3337 3338 case TEST_ALL_LAYERS: 3339 case TEST_INVOCATION_PER_LAYER: 3340 return verifyImageSingleColoredRow(layer, 0.5f, colors[layerNdx]); 3341 3342 case TEST_DIFFERENT_LAYERS: 3343 case TEST_MULTIPLE_LAYERS_PER_INVOCATION: 3344 if (layerNdx == 0) 3345 return verifyEmptyImage(layer); 3346 else 3347 return verifyImageSingleColoredRow(layer, layerNdx / (float)m_numLayers, white); 3348 3349 case TEST_LAYER_ID: 3350 { 3351 const tcu::Vec4 layerColor((layerNdx % 2 == 1) ? (1.0f) : (0.5f), 3352 ((layerNdx/2) % 2 == 1) ? (1.0f) : (0.5f), 3353 (layerNdx == 0) ? (1.0f) : (0.0f), 3354 1.0f); 3355 return verifyImageSingleColoredRow(layer, 0.5f, layerColor); 3356 } 3357 3358 case TEST_LAYER_PROVOKING_VERTEX: 3359 if (m_provokingVertex == GL_FIRST_VERTEX_CONVENTION) 3360 { 3361 if (layerNdx == 0) 3362 return verifyImageSingleColoredRow(layer, 0.5f, white); 3363 else 3364 return verifyEmptyImage(layer); 3365 } 3366 else if (m_provokingVertex == GL_LAST_VERTEX_CONVENTION) 3367 { 3368 if (layerNdx == 1) 3369 return verifyImageSingleColoredRow(layer, 0.5f, white); 3370 else 3371 return verifyEmptyImage(layer); 3372 } 3373 else 3374 { 3375 DE_ASSERT(false); 3376 return false; 3377 } 3378 3379 default: 3380 DE_ASSERT(DE_FALSE); 3381 return false; 3382 }; 3383 } 3384 3385 bool LayeredRenderCase::verifyImageSingleColoredRow (const tcu::Surface& layer, float rowWidthRatio, const tcu::Vec4& barColor, bool logging) 3386 { 3387 DE_ASSERT(rowWidthRatio > 0.0f); 3388 3389 const int barLength = (int)(rowWidthRatio*layer.getWidth()); 3390 const int barLengthThreshold = 1; 3391 tcu::Surface errorMask (layer.getWidth(), layer.getHeight()); 3392 bool allPixelsOk = true; 3393 3394 if (logging) 3395 m_testCtx.getLog() << tcu::TestLog::Message << "Expecting all pixels with distance less or equal to (about) " << barLength << " pixels from left border to be of color " << barColor.swizzle(0,1,2) << "." << tcu::TestLog::EndMessage; 3396 3397 tcu::clear(errorMask.getAccess(), tcu::RGBA::green.toIVec()); 3398 3399 for (int y = 0; y < layer.getHeight(); ++y) 3400 for (int x = 0; x < layer.getWidth(); ++x) 3401 { 3402 const tcu::RGBA color = layer.getPixel(x, y); 3403 const tcu::RGBA refColor = tcu::RGBA(barColor); 3404 const int threshold = 8; 3405 const bool isBlack = color.getRed() <= threshold || color.getGreen() <= threshold || color.getBlue() <= threshold; 3406 const bool isColor = tcu::allEqual(tcu::lessThan(tcu::abs(color.toIVec().swizzle(0, 1, 2) - refColor.toIVec().swizzle(0, 1, 2)), tcu::IVec3(threshold, threshold, threshold)), tcu::BVec3(true, true, true)); 3407 3408 bool isOk; 3409 3410 if (x <= barLength - barLengthThreshold) 3411 isOk = isColor; 3412 else if (x >= barLength + barLengthThreshold) 3413 isOk = isBlack; 3414 else 3415 isOk = isColor || isBlack; 3416 3417 allPixelsOk &= isOk; 3418 3419 if (!isOk) 3420 errorMask.setPixel(x, y, tcu::RGBA::red); 3421 } 3422 3423 if (allPixelsOk) 3424 { 3425 if (logging) 3426 m_testCtx.getLog() << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage 3427 << tcu::TestLog::ImageSet("LayerContent", "Layer content") 3428 << tcu::TestLog::Image("Layer", "Layer", layer) 3429 << tcu::TestLog::EndImageSet; 3430 return true; 3431 } 3432 else 3433 { 3434 if (logging) 3435 m_testCtx.getLog() << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage 3436 << tcu::TestLog::ImageSet("LayerContent", "Layer content") 3437 << tcu::TestLog::Image("Layer", "Layer", layer) 3438 << tcu::TestLog::Image("ErrorMask", "Errors", errorMask) 3439 << tcu::TestLog::EndImageSet; 3440 return false; 3441 } 3442 3443 if (logging) 3444 m_testCtx.getLog() << tcu::TestLog::Image("LayerContent", "Layer content", layer); 3445 3446 return allPixelsOk; 3447 } 3448 3449 bool LayeredRenderCase::verifyEmptyImage (const tcu::Surface& layer, bool logging) 3450 { 3451 // Expect black 3452 if (logging) 3453 m_testCtx.getLog() << tcu::TestLog::Message << "Expecting empty image" << tcu::TestLog::EndMessage; 3454 3455 for (int y = 0; y < layer.getHeight(); ++y) 3456 for (int x = 0; x < layer.getWidth(); ++x) 3457 { 3458 const tcu::RGBA color = layer.getPixel(x, y); 3459 const int threshold = 8; 3460 const bool isBlack = color.getRed() <= threshold || color.getGreen() <= threshold || color.getBlue() <= threshold; 3461 3462 if (!isBlack) 3463 { 3464 if (logging) 3465 m_testCtx.getLog() << tcu::TestLog::Message 3466 << "Found (at least) one bad pixel at " << x << "," << y << ". Pixel color is not background color." 3467 << tcu::TestLog::EndMessage 3468 << tcu::TestLog::ImageSet("LayerContent", "Layer content") 3469 << tcu::TestLog::Image("Layer", "Layer", layer) 3470 << tcu::TestLog::EndImageSet; 3471 return false; 3472 } 3473 } 3474 3475 if (logging) 3476 m_testCtx.getLog() << tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage; 3477 3478 return true; 3479 } 3480 3481 bool LayeredRenderCase::verifyProvokingVertexLayers (const tcu::Surface& layer0, const tcu::Surface& layer1) 3482 { 3483 const tcu::Vec4 white = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f); 3484 const bool layer0Empty = verifyEmptyImage(layer0, false); 3485 const bool layer1Empty = verifyEmptyImage(layer1, false); 3486 bool error = false; 3487 3488 // Both images could contain something if the quad triangles get assigned to different layers 3489 m_testCtx.getLog() << tcu::TestLog::Message << "Expecting non-empty layers, or non-empty layer." << tcu::TestLog::EndMessage; 3490 3491 if (layer0Empty == true && layer1Empty == true) 3492 { 3493 m_testCtx.getLog() << tcu::TestLog::Message << "Got empty images." << tcu::TestLog::EndMessage; 3494 error = true; 3495 } 3496 3497 // log images always 3498 m_testCtx.getLog() 3499 << tcu::TestLog::ImageSet("LayerContent", "Layer content") 3500 << tcu::TestLog::Image("Layer", "Layer0", layer0) 3501 << tcu::TestLog::Image("Layer", "Layer1", layer1) 3502 << tcu::TestLog::EndImageSet; 3503 3504 if (error) 3505 m_testCtx.getLog() << tcu::TestLog::Message << "Image verification failed." << tcu::TestLog::EndMessage; 3506 else 3507 m_testCtx.getLog() << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage; 3508 3509 return !error; 3510 } 3511 3512 int LayeredRenderCase::getTargetLayers (LayeredRenderTargetType target) 3513 { 3514 switch (target) 3515 { 3516 case TARGET_CUBE: return 6; 3517 case TARGET_3D: return 4; 3518 case TARGET_1D_ARRAY: return 4; 3519 case TARGET_2D_ARRAY: return 4; 3520 case TARGET_2D_MS_ARRAY: return 2; 3521 default: 3522 DE_ASSERT(DE_FALSE); 3523 return 0; 3524 } 3525 } 3526 3527 glw::GLenum LayeredRenderCase::getTargetTextureTarget (LayeredRenderTargetType target) 3528 { 3529 switch (target) 3530 { 3531 case TARGET_CUBE: return GL_TEXTURE_CUBE_MAP; 3532 case TARGET_3D: return GL_TEXTURE_3D; 3533 case TARGET_1D_ARRAY: return GL_TEXTURE_1D_ARRAY; 3534 case TARGET_2D_ARRAY: return GL_TEXTURE_2D_ARRAY; 3535 case TARGET_2D_MS_ARRAY: return GL_TEXTURE_2D_MULTISAMPLE_ARRAY; 3536 default: 3537 DE_ASSERT(DE_FALSE); 3538 return 0; 3539 } 3540 } 3541 3542 tcu::IVec3 LayeredRenderCase::getTargetDimensions (LayeredRenderTargetType target) 3543 { 3544 switch (target) 3545 { 3546 case TARGET_CUBE: return tcu::IVec3(64, 64, 0); 3547 case TARGET_3D: return tcu::IVec3(64, 64, 4); 3548 case TARGET_1D_ARRAY: return tcu::IVec3(64, 4, 0); 3549 case TARGET_2D_ARRAY: return tcu::IVec3(64, 64, 4); 3550 case TARGET_2D_MS_ARRAY: return tcu::IVec3(64, 64, 2); 3551 default: 3552 DE_ASSERT(DE_FALSE); 3553 return tcu::IVec3(0, 0, 0); 3554 } 3555 } 3556 3557 tcu::IVec2 LayeredRenderCase::getResolveDimensions (LayeredRenderTargetType target) 3558 { 3559 switch (target) 3560 { 3561 case TARGET_CUBE: return tcu::IVec2(64, 64); 3562 case TARGET_3D: return tcu::IVec2(64, 64); 3563 case TARGET_1D_ARRAY: return tcu::IVec2(64, 1); 3564 case TARGET_2D_ARRAY: return tcu::IVec2(64, 64); 3565 case TARGET_2D_MS_ARRAY: return tcu::IVec2(64, 64); 3566 default: 3567 DE_ASSERT(DE_FALSE); 3568 return tcu::IVec2(0, 0); 3569 } 3570 } 3571 3572 class VaryingOutputCountCase : public GeometryShaderRenderTest 3573 { 3574 public: 3575 enum ShaderInstancingMode 3576 { 3577 MODE_WITHOUT_INSTANCING = 0, 3578 MODE_WITH_INSTANCING, 3579 3580 MODE_LAST 3581 }; 3582 VaryingOutputCountCase (Context& context, const char* name, const char* desc, VaryingOutputCountShader::VaryingSource test, ShaderInstancingMode mode); 3583 private: 3584 void init (void); 3585 void deinit (void); 3586 void preRender (sglr::Context& ctx, GLuint programID); 3587 3588 sglr::ShaderProgram& getProgram (void); 3589 void genVertexAttribData (void); 3590 void genVertexDataWithoutInstancing (void); 3591 void genVertexDataWithInstancing (void); 3592 3593 VaryingOutputCountShader* m_program; 3594 const VaryingOutputCountShader::VaryingSource m_test; 3595 const ShaderInstancingMode m_mode; 3596 int m_maxEmitCount; 3597 }; 3598 3599 VaryingOutputCountCase::VaryingOutputCountCase (Context& context, const char* name, const char* desc, VaryingOutputCountShader::VaryingSource test, ShaderInstancingMode mode) 3600 : GeometryShaderRenderTest (context, name, desc, GL_POINTS, GL_TRIANGLE_STRIP, VaryingOutputCountShader::getAttributeName(test)) 3601 , m_program (DE_NULL) 3602 , m_test (test) 3603 , m_mode (mode) 3604 , m_maxEmitCount (0) 3605 { 3606 DE_ASSERT(mode < MODE_LAST); 3607 } 3608 3609 void VaryingOutputCountCase::init (void) 3610 { 3611 // Check requirements 3612 3613 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 3614 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension"); 3615 3616 if (m_test == VaryingOutputCountShader::READ_TEXTURE) 3617 { 3618 glw::GLint maxTextures = 0; 3619 3620 m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &maxTextures); 3621 3622 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS = " << maxTextures << tcu::TestLog::EndMessage; 3623 3624 if (maxTextures < 1) 3625 throw tcu::NotSupportedError("Geometry shader texture units required"); 3626 } 3627 3628 // Get max emit count 3629 { 3630 const int componentsPerVertex = 4 + 4; // vec4 pos, vec4 color 3631 glw::GLint maxVertices = 0; 3632 glw::GLint maxComponents = 0; 3633 3634 m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &maxVertices); 3635 m_context.getRenderContext().getFunctions().getIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &maxComponents); 3636 3637 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_OUTPUT_VERTICES = " << maxVertices << tcu::TestLog::EndMessage; 3638 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS = " << maxComponents << tcu::TestLog::EndMessage; 3639 m_testCtx.getLog() << tcu::TestLog::Message << "Components per vertex = " << componentsPerVertex << tcu::TestLog::EndMessage; 3640 3641 if (maxVertices < 256) 3642 throw tcu::TestError("MAX_GEOMETRY_OUTPUT_VERTICES was less than minimum required (256)"); 3643 if (maxComponents < 1024) 3644 throw tcu::TestError("MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS was less than minimum required (1024)"); 3645 3646 m_maxEmitCount = de::min(maxVertices, maxComponents / componentsPerVertex); 3647 } 3648 3649 // Log what the test tries to do 3650 3651 m_testCtx.getLog() 3652 << tcu::TestLog::Message 3653 << "Rendering 4 n-gons with n = " 3654 << ((VaryingOutputCountShader::EMIT_COUNT_VERTEX_0 == -1) ? (m_maxEmitCount) : (VaryingOutputCountShader::EMIT_COUNT_VERTEX_0)) << ", " 3655 << ((VaryingOutputCountShader::EMIT_COUNT_VERTEX_1 == -1) ? (m_maxEmitCount) : (VaryingOutputCountShader::EMIT_COUNT_VERTEX_1)) << ", " 3656 << ((VaryingOutputCountShader::EMIT_COUNT_VERTEX_2 == -1) ? (m_maxEmitCount) : (VaryingOutputCountShader::EMIT_COUNT_VERTEX_2)) << ", and " 3657 << ((VaryingOutputCountShader::EMIT_COUNT_VERTEX_3 == -1) ? (m_maxEmitCount) : (VaryingOutputCountShader::EMIT_COUNT_VERTEX_3)) << ".\n" 3658 << "N is supplied to the geomery shader with " 3659 << ((m_test == VaryingOutputCountShader::READ_ATTRIBUTE) ? ("attribute") : (m_test == VaryingOutputCountShader::READ_UNIFORM) ? ("uniform") : ("texture")) 3660 << tcu::TestLog::EndMessage; 3661 3662 // Gen shader 3663 { 3664 const bool instanced = (m_mode == MODE_WITH_INSTANCING); 3665 3666 DE_ASSERT(!m_program); 3667 m_program = new VaryingOutputCountShader(m_test, m_maxEmitCount, instanced); 3668 } 3669 3670 // Case init 3671 GeometryShaderRenderTest::init(); 3672 } 3673 3674 void VaryingOutputCountCase::deinit (void) 3675 { 3676 if (m_program) 3677 { 3678 delete m_program; 3679 m_program = DE_NULL; 3680 } 3681 3682 GeometryShaderRenderTest::deinit(); 3683 } 3684 3685 void VaryingOutputCountCase::preRender (sglr::Context& ctx, GLuint programID) 3686 { 3687 if (m_test == VaryingOutputCountShader::READ_UNIFORM) 3688 { 3689 const int location = ctx.getUniformLocation(programID, "u_emitCount"); 3690 const deInt32 emitCount[4] = { 6, 0, m_maxEmitCount, 10 }; 3691 3692 if (location == -1) 3693 throw tcu::TestError("uniform location of u_emitCount was -1."); 3694 3695 ctx.uniform4iv(location, 1, emitCount); 3696 } 3697 else if (m_test == VaryingOutputCountShader::READ_TEXTURE) 3698 { 3699 const deUint8 data[4*4] = 3700 { 3701 255, 0, 0, 0, 3702 0, 255, 0, 0, 3703 0, 0, 255, 0, 3704 0, 0, 0, 255, 3705 }; 3706 const int location = ctx.getUniformLocation(programID, "u_sampler"); 3707 GLuint texID = 0; 3708 3709 if (location == -1) 3710 throw tcu::TestError("uniform location of u_sampler was -1."); 3711 ctx.uniform1i(location, 0); 3712 3713 // \note we don't need to explicitly delete the texture, the sglr context will delete it 3714 ctx.genTextures(1, &texID); 3715 ctx.bindTexture(GL_TEXTURE_2D, texID); 3716 ctx.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); 3717 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3718 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3719 } 3720 } 3721 3722 sglr::ShaderProgram& VaryingOutputCountCase::getProgram (void) 3723 { 3724 return *m_program; 3725 } 3726 3727 void VaryingOutputCountCase::genVertexAttribData (void) 3728 { 3729 if (m_mode == MODE_WITHOUT_INSTANCING) 3730 genVertexDataWithoutInstancing(); 3731 else if (m_mode == MODE_WITH_INSTANCING) 3732 genVertexDataWithInstancing(); 3733 else 3734 DE_ASSERT(false); 3735 } 3736 3737 void VaryingOutputCountCase::genVertexDataWithoutInstancing (void) 3738 { 3739 m_numDrawVertices = 4; 3740 3741 m_vertexPosData.resize(4); 3742 m_vertexAttrData.resize(4); 3743 3744 m_vertexPosData[0] = tcu::Vec4( 0.5f, 0.0f, 0.0f, 1.0f); 3745 m_vertexPosData[1] = tcu::Vec4( 0.0f, 0.5f, 0.0f, 1.0f); 3746 m_vertexPosData[2] = tcu::Vec4(-0.7f, -0.1f, 0.0f, 1.0f); 3747 m_vertexPosData[3] = tcu::Vec4(-0.1f, -0.7f, 0.0f, 1.0f); 3748 3749 if (m_test == VaryingOutputCountShader::READ_ATTRIBUTE) 3750 { 3751 m_vertexAttrData[0] = tcu::Vec4(((VaryingOutputCountShader::EMIT_COUNT_VERTEX_0 == -1) ? ((float)m_maxEmitCount) : ((float)VaryingOutputCountShader::EMIT_COUNT_VERTEX_0)), 0.0f, 0.0f, 0.0f); 3752 m_vertexAttrData[1] = tcu::Vec4(((VaryingOutputCountShader::EMIT_COUNT_VERTEX_1 == -1) ? ((float)m_maxEmitCount) : ((float)VaryingOutputCountShader::EMIT_COUNT_VERTEX_1)), 0.0f, 0.0f, 0.0f); 3753 m_vertexAttrData[2] = tcu::Vec4(((VaryingOutputCountShader::EMIT_COUNT_VERTEX_2 == -1) ? ((float)m_maxEmitCount) : ((float)VaryingOutputCountShader::EMIT_COUNT_VERTEX_2)), 0.0f, 0.0f, 0.0f); 3754 m_vertexAttrData[3] = tcu::Vec4(((VaryingOutputCountShader::EMIT_COUNT_VERTEX_3 == -1) ? ((float)m_maxEmitCount) : ((float)VaryingOutputCountShader::EMIT_COUNT_VERTEX_3)), 0.0f, 0.0f, 0.0f); 3755 } 3756 else 3757 { 3758 m_vertexAttrData[0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f); 3759 m_vertexAttrData[1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f); 3760 m_vertexAttrData[2] = tcu::Vec4(2.0f, 0.0f, 0.0f, 0.0f); 3761 m_vertexAttrData[3] = tcu::Vec4(3.0f, 0.0f, 0.0f, 0.0f); 3762 } 3763 } 3764 3765 void VaryingOutputCountCase::genVertexDataWithInstancing (void) 3766 { 3767 m_numDrawVertices = 1; 3768 3769 m_vertexPosData.resize(1); 3770 m_vertexAttrData.resize(1); 3771 3772 m_vertexPosData[0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f); 3773 3774 if (m_test == VaryingOutputCountShader::READ_ATTRIBUTE) 3775 { 3776 const int emitCounts[] = 3777 { 3778 (VaryingOutputCountShader::EMIT_COUNT_VERTEX_0 == -1) ? (m_maxEmitCount) : (VaryingOutputCountShader::EMIT_COUNT_VERTEX_0), 3779 (VaryingOutputCountShader::EMIT_COUNT_VERTEX_1 == -1) ? (m_maxEmitCount) : (VaryingOutputCountShader::EMIT_COUNT_VERTEX_1), 3780 (VaryingOutputCountShader::EMIT_COUNT_VERTEX_2 == -1) ? (m_maxEmitCount) : (VaryingOutputCountShader::EMIT_COUNT_VERTEX_2), 3781 (VaryingOutputCountShader::EMIT_COUNT_VERTEX_3 == -1) ? (m_maxEmitCount) : (VaryingOutputCountShader::EMIT_COUNT_VERTEX_3), 3782 }; 3783 3784 m_vertexAttrData[0] = tcu::Vec4((float)emitCounts[0], (float)emitCounts[1], (float)emitCounts[2], (float)emitCounts[3]); 3785 } 3786 else 3787 { 3788 // not used 3789 m_vertexAttrData[0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f); 3790 } 3791 } 3792 3793 class GeometryProgramQueryCase : public TestCase 3794 { 3795 public: 3796 struct ProgramCase 3797 { 3798 const char* description; 3799 const char* header; 3800 int value; 3801 }; 3802 3803 GeometryProgramQueryCase (Context& context, const char* name, const char* description, glw::GLenum target); 3804 3805 void init (void); 3806 IterateResult iterate (void); 3807 3808 private: 3809 void expectProgramValue (deUint32 program, int value); 3810 void expectQueryError (deUint32 program); 3811 3812 const glw::GLenum m_target; 3813 3814 protected: 3815 std::vector<ProgramCase> m_cases; 3816 }; 3817 3818 GeometryProgramQueryCase::GeometryProgramQueryCase (Context& context, const char* name, const char* description, glw::GLenum target) 3819 : TestCase (context, name, description) 3820 , m_target (target) 3821 { 3822 } 3823 3824 void GeometryProgramQueryCase::init (void) 3825 { 3826 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 3827 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension"); 3828 } 3829 3830 GeometryProgramQueryCase::IterateResult GeometryProgramQueryCase::iterate (void) 3831 { 3832 static const char* const s_vertexSource = "#version 310 es\n" 3833 "void main ()\n" 3834 "{\n" 3835 " gl_Position = vec4(0.0, 0.0, 0.0, 0.0);\n" 3836 "}\n"; 3837 static const char* const s_fragmentSource = "#version 310 es\n" 3838 "layout(location = 0) out mediump vec4 fragColor;\n" 3839 "void main ()\n" 3840 "{\n" 3841 " fragColor = vec4(0.0, 0.0, 0.0, 0.0);\n" 3842 "}\n"; 3843 static const char* const s_geometryBody = "void main ()\n" 3844 "{\n" 3845 " gl_Position = vec4(0.0, 0.0, 0.0, 0.0);\n" 3846 " EmitVertex();\n" 3847 "}\n"; 3848 3849 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 3850 3851 // default cases 3852 for (int ndx = 0; ndx < (int)m_cases.size(); ++ndx) 3853 { 3854 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Case", m_cases[ndx].description); 3855 const std::string geometrySource = m_cases[ndx].header + std::string(s_geometryBody); 3856 const glu::ShaderProgram program (m_context.getRenderContext(), 3857 glu::ProgramSources() 3858 << glu::VertexSource(s_vertexSource) 3859 << glu::FragmentSource(s_fragmentSource) 3860 << glu::GeometrySource(geometrySource)); 3861 3862 m_testCtx.getLog() << program; 3863 expectProgramValue(program.getProgram(), m_cases[ndx].value); 3864 } 3865 3866 // no geometry shader -case (INVALID OP) 3867 { 3868 const tcu::ScopedLogSection section (m_testCtx.getLog(), "NoGeometryShader", "No geometry shader"); 3869 const glu::ShaderProgram program (m_context.getRenderContext(), 3870 glu::ProgramSources() 3871 << glu::VertexSource(s_vertexSource) 3872 << glu::FragmentSource(s_fragmentSource)); 3873 3874 m_testCtx.getLog() << program; 3875 expectQueryError(program.getProgram()); 3876 } 3877 3878 // not linked -case (INVALID OP) 3879 { 3880 const tcu::ScopedLogSection section (m_testCtx.getLog(), "NotLinkedProgram", "Shader program not linked"); 3881 const std::string geometrySource = "#version 310 es\nlayout (triangles) in;\n" + std::string(s_geometryBody); 3882 3883 glu::Shader vertexShader (m_context.getRenderContext(), glu::SHADERTYPE_VERTEX); 3884 glu::Shader fragmentShader (m_context.getRenderContext(), glu::SHADERTYPE_FRAGMENT); 3885 glu::Shader geometryShader (m_context.getRenderContext(), glu::SHADERTYPE_GEOMETRY); 3886 glu::Program program (m_context.getRenderContext()); 3887 3888 const char* const geometrySourceArray[1] = { geometrySource.c_str() }; 3889 3890 vertexShader.setSources(1, &s_vertexSource, DE_NULL); 3891 fragmentShader.setSources(1, &s_fragmentSource, DE_NULL); 3892 geometryShader.setSources(1, geometrySourceArray, DE_NULL); 3893 3894 vertexShader.compile(); 3895 fragmentShader.compile(); 3896 geometryShader.compile(); 3897 3898 if (!vertexShader.getCompileStatus() || 3899 !fragmentShader.getCompileStatus() || 3900 !geometryShader.getCompileStatus()) 3901 throw tcu::TestError("Failed to compile shader"); 3902 3903 program.attachShader(vertexShader.getShader()); 3904 program.attachShader(fragmentShader.getShader()); 3905 program.attachShader(geometryShader.getShader()); 3906 3907 m_testCtx.getLog() << tcu::TestLog::Message << "Creating a program with geometry shader, but not linking it" << tcu::TestLog::EndMessage; 3908 3909 expectQueryError(program.getProgram()); 3910 } 3911 3912 return STOP; 3913 } 3914 3915 void GeometryProgramQueryCase::expectProgramValue (deUint32 program, int value) 3916 { 3917 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3918 gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint> state; 3919 3920 gl.getProgramiv(program, m_target, &state); 3921 GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv"); 3922 3923 m_testCtx.getLog() << tcu::TestLog::Message << glu::getProgramParamStr(m_target) << " = " << state << tcu::TestLog::EndMessage; 3924 3925 if (state != value) 3926 { 3927 m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << value << ", got " << state << tcu::TestLog::EndMessage; 3928 3929 // don't overwrite error 3930 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) 3931 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value"); 3932 } 3933 } 3934 3935 void GeometryProgramQueryCase::expectQueryError (deUint32 program) 3936 { 3937 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3938 glw::GLint dummy; 3939 glw::GLenum errorCode; 3940 3941 m_testCtx.getLog() << tcu::TestLog::Message << "Querying " << glu::getProgramParamStr(m_target) << ", expecting INVALID_OPERATION" << tcu::TestLog::EndMessage; 3942 gl.getProgramiv(program, m_target, &dummy); 3943 3944 errorCode = gl.getError(); 3945 3946 if (errorCode != GL_INVALID_OPERATION) 3947 { 3948 m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected INVALID_OPERATION, got " << glu::getErrorStr(errorCode) << tcu::TestLog::EndMessage; 3949 3950 // don't overwrite error 3951 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) 3952 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected error code"); 3953 } 3954 } 3955 3956 class GeometryShaderInvocationsQueryCase : public GeometryProgramQueryCase 3957 { 3958 public: 3959 GeometryShaderInvocationsQueryCase(Context& context, const char* name, const char* description); 3960 }; 3961 3962 GeometryShaderInvocationsQueryCase::GeometryShaderInvocationsQueryCase(Context& context, const char* name, const char* description) 3963 : GeometryProgramQueryCase(context, name, description, GL_GEOMETRY_SHADER_INVOCATIONS) 3964 { 3965 // 2 normal cases 3966 m_cases.resize(2); 3967 3968 m_cases[0].description = "Default value"; 3969 m_cases[0].header = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (triangles) in;\nlayout (points, max_vertices = 3) out;\n"; 3970 m_cases[0].value = 1; 3971 3972 m_cases[1].description = "Value declared"; 3973 m_cases[1].header = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (triangles, invocations=2) in;\nlayout (points, max_vertices = 3) out;\n"; 3974 m_cases[1].value = 2; 3975 } 3976 3977 class GeometryShaderVerticesQueryCase : public GeometryProgramQueryCase 3978 { 3979 public: 3980 GeometryShaderVerticesQueryCase(Context& context, const char* name, const char* description); 3981 }; 3982 3983 GeometryShaderVerticesQueryCase::GeometryShaderVerticesQueryCase(Context& context, const char* name, const char* description) 3984 : GeometryProgramQueryCase(context, name, description, GL_GEOMETRY_LINKED_VERTICES_OUT_EXT) 3985 { 3986 m_cases.resize(1); 3987 3988 m_cases[0].description = "max_vertices = 1"; 3989 m_cases[0].header = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (triangles) in;\nlayout (points, max_vertices = 1) out;\n"; 3990 m_cases[0].value = 1; 3991 } 3992 3993 class GeometryShaderInputQueryCase : public GeometryProgramQueryCase 3994 { 3995 public: 3996 GeometryShaderInputQueryCase(Context& context, const char* name, const char* description); 3997 }; 3998 3999 GeometryShaderInputQueryCase::GeometryShaderInputQueryCase(Context& context, const char* name, const char* description) 4000 : GeometryProgramQueryCase(context, name, description, GL_GEOMETRY_LINKED_INPUT_TYPE_EXT) 4001 { 4002 m_cases.resize(3); 4003 4004 m_cases[0].description = "Triangles"; 4005 m_cases[0].header = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (triangles) in;\nlayout (points, max_vertices = 3) out;\n"; 4006 m_cases[0].value = GL_TRIANGLES; 4007 4008 m_cases[1].description = "Lines"; 4009 m_cases[1].header = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (lines) in;\nlayout (points, max_vertices = 3) out;\n"; 4010 m_cases[1].value = GL_LINES; 4011 4012 m_cases[2].description = "Points"; 4013 m_cases[2].header = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (points) in;\nlayout (points, max_vertices = 3) out;\n"; 4014 m_cases[2].value = GL_POINTS; 4015 } 4016 4017 class GeometryShaderOutputQueryCase : public GeometryProgramQueryCase 4018 { 4019 public: 4020 GeometryShaderOutputQueryCase(Context& context, const char* name, const char* description); 4021 }; 4022 4023 GeometryShaderOutputQueryCase::GeometryShaderOutputQueryCase(Context& context, const char* name, const char* description) 4024 : GeometryProgramQueryCase(context, name, description, GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT) 4025 { 4026 m_cases.resize(3); 4027 4028 m_cases[0].description = "Triangle strip"; 4029 m_cases[0].header = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (triangles) in;\nlayout (triangle_strip, max_vertices = 3) out;\n"; 4030 m_cases[0].value = GL_TRIANGLE_STRIP; 4031 4032 m_cases[1].description = "Lines"; 4033 m_cases[1].header = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (triangles) in;\nlayout (line_strip, max_vertices = 3) out;\n"; 4034 m_cases[1].value = GL_LINE_STRIP; 4035 4036 m_cases[2].description = "Points"; 4037 m_cases[2].header = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (triangles) in;\nlayout (points, max_vertices = 3) out;\n"; 4038 m_cases[2].value = GL_POINTS; 4039 } 4040 4041 class ImplementationLimitCase : public TestCase 4042 { 4043 public: 4044 ImplementationLimitCase (Context& context, const char* name, const char* description, glw::GLenum target, int minValue); 4045 4046 void init (void); 4047 IterateResult iterate (void); 4048 4049 const glw::GLenum m_target; 4050 const int m_minValue; 4051 }; 4052 4053 ImplementationLimitCase::ImplementationLimitCase (Context& context, const char* name, const char* description, glw::GLenum target, int minValue) 4054 : TestCase (context, name, description) 4055 , m_target (target) 4056 , m_minValue (minValue) 4057 { 4058 } 4059 4060 void ImplementationLimitCase::init (void) 4061 { 4062 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 4063 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension"); 4064 } 4065 4066 ImplementationLimitCase::IterateResult ImplementationLimitCase::iterate (void) 4067 { 4068 gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint> state; 4069 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 4070 4071 gl.enableLogging(true); 4072 gl.glGetIntegerv(m_target, &state); 4073 GLU_EXPECT_NO_ERROR(gl.glGetError(), "getIntegerv()"); 4074 4075 m_testCtx.getLog() << tcu::TestLog::Message << glu::getGettableStateStr(m_target) << " = " << state << tcu::TestLog::EndMessage; 4076 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4077 4078 if (state.verifyValidity(m_testCtx) && state < m_minValue) 4079 { 4080 m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Minimum value = " << m_minValue << ", got " << state << tcu::TestLog::EndMessage; 4081 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got a value less than minimum value"); 4082 } 4083 4084 return STOP; 4085 } 4086 4087 class LayerProvokingVertexQueryCase : public TestCase 4088 { 4089 public: 4090 LayerProvokingVertexQueryCase (Context& context, const char* name, const char* description); 4091 4092 void init (void); 4093 IterateResult iterate (void); 4094 }; 4095 4096 LayerProvokingVertexQueryCase::LayerProvokingVertexQueryCase(Context& context, const char* name, const char* description) 4097 : TestCase(context, name, description) 4098 { 4099 } 4100 4101 void LayerProvokingVertexQueryCase::init (void) 4102 { 4103 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 4104 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension"); 4105 } 4106 4107 LayerProvokingVertexQueryCase::IterateResult LayerProvokingVertexQueryCase::iterate (void) 4108 { 4109 gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint> state; 4110 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 4111 4112 gl.enableLogging(true); 4113 gl.glGetIntegerv(GL_LAYER_PROVOKING_VERTEX, &state); 4114 GLU_EXPECT_NO_ERROR(gl.glGetError(), "getIntegerv(LAYER_PROVOKING_VERTEX)"); 4115 4116 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4117 4118 if (state.verifyValidity(m_testCtx)) 4119 { 4120 m_testCtx.getLog() << tcu::TestLog::Message << "LAYER_PROVOKING_VERTEX = " << glu::getProvokingVertexStr(state) << tcu::TestLog::EndMessage; 4121 4122 if (state != GL_FIRST_VERTEX_CONVENTION && 4123 state != GL_LAST_VERTEX_CONVENTION && 4124 state != GL_UNDEFINED_VERTEX) 4125 { 4126 m_testCtx.getLog() 4127 << tcu::TestLog::Message 4128 << "getInteger(GL_LAYER_PROVOKING_VERTEX) returned illegal value. Got " 4129 << state << "\n" 4130 << "Expected any of {FIRST_VERTEX_CONVENTION, LAST_VERTEX_CONVENTION, UNDEFINED_VERTEX}." 4131 << tcu::TestLog::EndMessage; 4132 4133 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected provoking vertex value"); 4134 } 4135 } 4136 4137 return STOP; 4138 } 4139 4140 class GeometryInvocationCase : public GeometryShaderRenderTest 4141 { 4142 public: 4143 enum OutputCase 4144 { 4145 CASE_FIXED_OUTPUT_COUNTS = 0, 4146 CASE_DIFFERENT_OUTPUT_COUNTS, 4147 4148 CASE_LAST 4149 }; 4150 4151 GeometryInvocationCase (Context& context, const char* name, const char* description, int numInvocations, OutputCase testCase); 4152 ~GeometryInvocationCase (void); 4153 4154 void init (void); 4155 void deinit (void); 4156 4157 private: 4158 sglr::ShaderProgram& getProgram (void); 4159 void genVertexAttribData (void); 4160 4161 static InvocationCountShader::OutputCase mapToShaderCaseType (OutputCase testCase); 4162 4163 const OutputCase m_testCase; 4164 int m_numInvocations; 4165 InvocationCountShader* m_program; 4166 }; 4167 4168 GeometryInvocationCase::GeometryInvocationCase (Context& context, const char* name, const char* description, int numInvocations, OutputCase testCase) 4169 : GeometryShaderRenderTest (context, name, description, GL_POINTS, GL_TRIANGLE_STRIP, "a_color") 4170 , m_testCase (testCase) 4171 , m_numInvocations (numInvocations) 4172 , m_program (DE_NULL) 4173 { 4174 DE_ASSERT(m_testCase < CASE_LAST); 4175 } 4176 4177 GeometryInvocationCase::~GeometryInvocationCase (void) 4178 { 4179 deinit(); 4180 } 4181 4182 void GeometryInvocationCase::init (void) 4183 { 4184 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4185 int maxGeometryShaderInvocations = 0; 4186 int maxComponents = 0; 4187 4188 // requirements 4189 4190 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 4191 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension"); 4192 4193 gl.getIntegerv(GL_MAX_GEOMETRY_SHADER_INVOCATIONS, &maxGeometryShaderInvocations); 4194 GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv(GL_MAX_GEOMETRY_SHADER_INVOCATIONS)"); 4195 4196 gl.getIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &maxComponents); 4197 GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS)"); 4198 4199 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_SHADER_INVOCATIONS = " << maxGeometryShaderInvocations << tcu::TestLog::EndMessage; 4200 4201 // set target num invocations 4202 4203 if (m_numInvocations == -1) 4204 m_numInvocations = maxGeometryShaderInvocations; 4205 else if (maxGeometryShaderInvocations < m_numInvocations) 4206 throw tcu::NotSupportedError("Test requires larger GL_MAX_GEOMETRY_SHADER_INVOCATIONS"); 4207 4208 if (m_testCase == CASE_DIFFERENT_OUTPUT_COUNTS) 4209 { 4210 const int maxEmitCount = m_numInvocations + 2; 4211 const int numComponents = 8; // pos + color 4212 if (maxEmitCount * numComponents > maxComponents) 4213 throw tcu::NotSupportedError("Test requires larger GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS"); 4214 } 4215 4216 // Log what the test tries to do 4217 4218 if (m_testCase == CASE_FIXED_OUTPUT_COUNTS) 4219 { 4220 m_testCtx.getLog() 4221 << tcu::TestLog::Message 4222 << "Rendering triangles in a partial circle formation with a geometry shader. Each triangle is generated by a separate invocation.\n" 4223 << "Drawing 2 points, each generating " << m_numInvocations << " triangles." 4224 << tcu::TestLog::EndMessage; 4225 } 4226 else if (m_testCase == CASE_DIFFERENT_OUTPUT_COUNTS) 4227 { 4228 m_testCtx.getLog() 4229 << tcu::TestLog::Message 4230 << "Rendering n-gons in a partial circle formation with a geometry shader. Each n-gon is generated by a separate invocation.\n" 4231 << "Drawing 2 points, each generating " << m_numInvocations << " n-gons." 4232 << tcu::TestLog::EndMessage; 4233 } 4234 else 4235 DE_ASSERT(false); 4236 4237 // resources 4238 4239 m_program = new InvocationCountShader(m_numInvocations, mapToShaderCaseType(m_testCase)); 4240 4241 GeometryShaderRenderTest::init(); 4242 } 4243 4244 void GeometryInvocationCase::deinit (void) 4245 { 4246 if (m_program) 4247 { 4248 delete m_program; 4249 m_program = DE_NULL; 4250 } 4251 4252 GeometryShaderRenderTest::deinit(); 4253 } 4254 4255 sglr::ShaderProgram& GeometryInvocationCase::getProgram (void) 4256 { 4257 return *m_program; 4258 } 4259 4260 void GeometryInvocationCase::genVertexAttribData (void) 4261 { 4262 m_vertexPosData.resize(2); 4263 m_vertexPosData[0] = tcu::Vec4(0.0f,-0.3f, 0.0f, 1.0f); 4264 m_vertexPosData[1] = tcu::Vec4(0.2f, 0.3f, 0.0f, 1.0f); 4265 4266 m_vertexAttrData.resize(2); 4267 m_vertexAttrData[0] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f); 4268 m_vertexAttrData[1] = tcu::Vec4(0.8f, 0.8f, 0.8f, 1.0f); 4269 m_numDrawVertices = 2; 4270 } 4271 4272 InvocationCountShader::OutputCase GeometryInvocationCase::mapToShaderCaseType (OutputCase testCase) 4273 { 4274 switch (testCase) 4275 { 4276 case CASE_FIXED_OUTPUT_COUNTS: return InvocationCountShader::CASE_FIXED_OUTPUT_COUNTS; 4277 case CASE_DIFFERENT_OUTPUT_COUNTS: return InvocationCountShader::CASE_DIFFERENT_OUTPUT_COUNTS; 4278 default: 4279 DE_ASSERT(false); 4280 return InvocationCountShader::CASE_LAST; 4281 } 4282 } 4283 4284 class DrawInstancedGeometryInstancedCase : public GeometryShaderRenderTest 4285 { 4286 public: 4287 DrawInstancedGeometryInstancedCase (Context& context, const char* name, const char* description, int numInstances, int numInvocations); 4288 ~DrawInstancedGeometryInstancedCase (void); 4289 4290 private: 4291 void init (void); 4292 sglr::ShaderProgram& getProgram (void); 4293 void genVertexAttribData (void); 4294 4295 const int m_numInstances; 4296 const int m_numInvocations; 4297 InstancedExpansionShader m_program; 4298 }; 4299 4300 DrawInstancedGeometryInstancedCase::DrawInstancedGeometryInstancedCase (Context& context, const char* name, const char* description, int numInstances, int numInvocations) 4301 : GeometryShaderRenderTest (context, name, description, GL_POINTS, GL_TRIANGLE_STRIP, "a_offset", FLAG_DRAW_INSTANCED) 4302 , m_numInstances (numInstances) 4303 , m_numInvocations (numInvocations) 4304 , m_program (numInvocations) 4305 { 4306 } 4307 4308 DrawInstancedGeometryInstancedCase::~DrawInstancedGeometryInstancedCase (void) 4309 { 4310 } 4311 4312 void DrawInstancedGeometryInstancedCase::init (void) 4313 { 4314 m_testCtx.getLog() 4315 << tcu::TestLog::Message 4316 << "Rendering a single point with " << m_numInstances << " instances. " 4317 << "Each geometry shader is invoked " << m_numInvocations << " times for each primitive. " 4318 << tcu::TestLog::EndMessage; 4319 4320 GeometryShaderRenderTest::init(); 4321 } 4322 4323 sglr::ShaderProgram& DrawInstancedGeometryInstancedCase::getProgram (void) 4324 { 4325 return m_program; 4326 } 4327 4328 void DrawInstancedGeometryInstancedCase::genVertexAttribData (void) 4329 { 4330 m_numDrawVertices = 1; 4331 m_numDrawInstances = m_numInstances; 4332 m_vertexAttrDivisor = 1; 4333 4334 m_vertexPosData.resize(1); 4335 m_vertexAttrData.resize(8); 4336 4337 m_vertexPosData[0] = tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f); 4338 4339 m_vertexAttrData[0] = tcu::Vec4( 0.5f, 0.0f, 0.0f, 0.0f); 4340 m_vertexAttrData[1] = tcu::Vec4( 0.0f, 0.5f, 0.0f, 0.0f); 4341 m_vertexAttrData[2] = tcu::Vec4(-0.7f, -0.1f, 0.0f, 0.0f); 4342 m_vertexAttrData[3] = tcu::Vec4(-0.1f, -0.7f, 0.0f, 0.0f); 4343 m_vertexAttrData[4] = tcu::Vec4(-0.8f, -0.7f, 0.0f, 0.0f); 4344 m_vertexAttrData[5] = tcu::Vec4(-0.9f, 0.6f, 0.0f, 0.0f); 4345 m_vertexAttrData[6] = tcu::Vec4(-0.8f, 0.3f, 0.0f, 0.0f); 4346 m_vertexAttrData[7] = tcu::Vec4(-0.1f, 0.1f, 0.0f, 0.0f); 4347 4348 DE_ASSERT(m_numInstances <= (int)m_vertexAttrData.size()); 4349 } 4350 4351 class GeometryProgramLimitCase : public TestCase 4352 { 4353 public: 4354 GeometryProgramLimitCase (Context& context, const char* name, const char* description, glw::GLenum apiName, const std::string& glslName, int limit); 4355 4356 private: 4357 void init (void); 4358 IterateResult iterate (void); 4359 4360 const glw::GLenum m_apiName; 4361 const std::string m_glslName; 4362 const int m_limit; 4363 }; 4364 4365 GeometryProgramLimitCase::GeometryProgramLimitCase (Context& context, const char* name, const char* description, glw::GLenum apiName, const std::string& glslName, int limit) 4366 : TestCase (context, name, description) 4367 , m_apiName (apiName) 4368 , m_glslName (glslName) 4369 , m_limit (limit) 4370 { 4371 } 4372 4373 void GeometryProgramLimitCase::init (void) 4374 { 4375 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 4376 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension"); 4377 } 4378 4379 GeometryProgramLimitCase::IterateResult GeometryProgramLimitCase::iterate (void) 4380 { 4381 int limit; 4382 4383 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4384 4385 // query limit 4386 { 4387 gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint> state; 4388 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 4389 4390 gl.enableLogging(true); 4391 gl.glGetIntegerv(m_apiName, &state); 4392 GLU_EXPECT_NO_ERROR(gl.glGetError(), "getIntegerv()"); 4393 4394 m_testCtx.getLog() << tcu::TestLog::Message << glu::getGettableStateStr(m_apiName) << " = " << state << tcu::TestLog::EndMessage; 4395 4396 if (!state.verifyValidity(m_testCtx)) 4397 return STOP; 4398 4399 if (state < m_limit) 4400 { 4401 m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Minimum value = " << m_limit << ", got " << state << tcu::TestLog::EndMessage; 4402 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got a value less than minimum value"); 4403 return STOP; 4404 } 4405 4406 limit = state; 4407 } 4408 4409 // verify limit is the same in GLSL 4410 { 4411 static const char* const vertexSource = "#version 310 es\n" 4412 "void main ()\n" 4413 "{\n" 4414 " gl_Position = vec4(0.0, 0.0, 0.0, 0.0);\n" 4415 "}\n"; 4416 static const char* const fragmentSource = "#version 310 es\n" 4417 "layout(location = 0) out mediump vec4 fragColor;\n" 4418 "void main ()\n" 4419 "{\n" 4420 " fragColor = vec4(0.0, 0.0, 0.0, 0.0);\n" 4421 "}\n"; 4422 const std::string geometrySource = "#version 310 es\n" 4423 "#extension GL_EXT_geometry_shader : require\n" 4424 "layout(points) in;\n" 4425 "layout(points, max_vertices = 1) out;\n" 4426 "void main ()\n" 4427 "{\n" 4428 " // Building the shader will fail if the constant value is not the expected\n" 4429 " const mediump int cArraySize = (gl_" + m_glslName + " == " + de::toString(limit) + ") ? (1) : (-1);\n" 4430 " float[cArraySize] fArray;\n" 4431 " fArray[0] = 0.0f;\n" 4432 " gl_Position = vec4(0.0, 0.0, 0.0, fArray[0]);\n" 4433 " EmitVertex();\n" 4434 "}\n"; 4435 4436 const de::UniquePtr<glu::ShaderProgram> program(new glu::ShaderProgram(m_context.getRenderContext(), 4437 glu::ProgramSources() 4438 << glu::VertexSource(vertexSource) 4439 << glu::FragmentSource(fragmentSource) 4440 << glu::GeometrySource(geometrySource))); 4441 4442 m_testCtx.getLog() << tcu::TestLog::Message << "Building a test shader to verify GLSL constant " << m_glslName << " value." << tcu::TestLog::EndMessage; 4443 m_testCtx.getLog() << *program; 4444 4445 if (!program->isOk()) 4446 { 4447 // compile failed, assume static assert failed 4448 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Shader build failed"); 4449 return STOP; 4450 } 4451 4452 m_testCtx.getLog() << tcu::TestLog::Message << "Build ok" << tcu::TestLog::EndMessage; 4453 } 4454 4455 return STOP; 4456 } 4457 4458 class PrimitivesGeneratedQueryCase : public TestCase 4459 { 4460 public: 4461 enum QueryTest 4462 { 4463 TEST_NO_GEOMETRY = 0, 4464 TEST_NO_AMPLIFICATION, 4465 TEST_AMPLIFICATION, 4466 TEST_PARTIAL_PRIMITIVES, 4467 TEST_INSTANCED, 4468 4469 TEST_LAST 4470 }; 4471 4472 PrimitivesGeneratedQueryCase (Context& context, const char* name, const char* description, QueryTest test); 4473 ~PrimitivesGeneratedQueryCase (void); 4474 4475 private: 4476 void init (void); 4477 void deinit (void); 4478 IterateResult iterate (void); 4479 4480 glu::ShaderProgram* genProgram (void); 4481 4482 const QueryTest m_test; 4483 glu::ShaderProgram* m_program; 4484 }; 4485 4486 PrimitivesGeneratedQueryCase::PrimitivesGeneratedQueryCase (Context& context, const char* name, const char* description, QueryTest test) 4487 : TestCase (context, name, description) 4488 , m_test (test) 4489 , m_program (DE_NULL) 4490 { 4491 DE_ASSERT(m_test < TEST_LAST); 4492 } 4493 4494 PrimitivesGeneratedQueryCase::~PrimitivesGeneratedQueryCase (void) 4495 { 4496 deinit(); 4497 } 4498 4499 void PrimitivesGeneratedQueryCase::init (void) 4500 { 4501 // requirements 4502 4503 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 4504 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension"); 4505 4506 // log what test tries to do 4507 4508 if (m_test == TEST_NO_GEOMETRY) 4509 m_testCtx.getLog() << tcu::TestLog::Message << "Querying PRIMITIVES_GENERATED while rendering without a geometry shader." << tcu::TestLog::EndMessage; 4510 else if (m_test == TEST_NO_AMPLIFICATION) 4511 m_testCtx.getLog() << tcu::TestLog::Message << "Querying PRIMITIVES_GENERATED while rendering with a non-amplifying geometry shader." << tcu::TestLog::EndMessage; 4512 else if (m_test == TEST_AMPLIFICATION) 4513 m_testCtx.getLog() << tcu::TestLog::Message << "Querying PRIMITIVES_GENERATED while rendering with a (3x) amplifying geometry shader." << tcu::TestLog::EndMessage; 4514 else if (m_test == TEST_PARTIAL_PRIMITIVES) 4515 m_testCtx.getLog() << tcu::TestLog::Message << "Querying PRIMITIVES_GENERATED while rendering with a geometry shader that emits also partial primitives." << tcu::TestLog::EndMessage; 4516 else if (m_test == TEST_INSTANCED) 4517 m_testCtx.getLog() << tcu::TestLog::Message << "Querying PRIMITIVES_GENERATED while rendering with a instanced geometry shader." << tcu::TestLog::EndMessage; 4518 else 4519 DE_ASSERT(false); 4520 4521 // resources 4522 4523 m_program = genProgram(); 4524 m_testCtx.getLog() << *m_program; 4525 4526 if (!m_program->isOk()) 4527 throw tcu::TestError("could not build program"); 4528 } 4529 4530 void PrimitivesGeneratedQueryCase::deinit (void) 4531 { 4532 delete m_program; 4533 m_program = DE_NULL; 4534 } 4535 4536 PrimitivesGeneratedQueryCase::IterateResult PrimitivesGeneratedQueryCase::iterate (void) 4537 { 4538 glw::GLuint primitivesGenerated = 0xDEBADBAD; 4539 4540 m_testCtx.getLog() 4541 << tcu::TestLog::Message 4542 << "Drawing 8 points, setting a_one for each to value (1.0, 1.0, 1.0, 1.0)" 4543 << tcu::TestLog::EndMessage; 4544 4545 { 4546 static const tcu::Vec4 vertexData[8*2] = 4547 { 4548 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 4549 tcu::Vec4(0.1f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 4550 tcu::Vec4(0.2f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 4551 tcu::Vec4(0.3f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 4552 tcu::Vec4(0.4f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 4553 tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 4554 tcu::Vec4(0.6f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 4555 tcu::Vec4(0.7f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 4556 }; 4557 4558 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4559 const glu::VertexArray vao (m_context.getRenderContext()); 4560 const glu::Buffer buffer (m_context.getRenderContext()); 4561 const glu::Query query (m_context.getRenderContext()); 4562 const int positionLocation = gl.getAttribLocation(m_program->getProgram(), "a_position"); 4563 const int oneLocation = gl.getAttribLocation(m_program->getProgram(), "a_one"); 4564 4565 gl.bindVertexArray(*vao); 4566 4567 gl.bindBuffer(GL_ARRAY_BUFFER, *buffer); 4568 gl.bufferData(GL_ARRAY_BUFFER, (int)sizeof(vertexData), vertexData, GL_STATIC_DRAW); 4569 4570 gl.vertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 2 * sizeof(tcu::Vec4), DE_NULL); 4571 gl.enableVertexAttribArray(positionLocation); 4572 4573 if (oneLocation != -1) 4574 { 4575 gl.vertexAttribPointer(oneLocation, 4, GL_FLOAT, GL_FALSE, 2 * sizeof(tcu::Vec4), (const tcu::Vec4*)DE_NULL + 1); 4576 gl.enableVertexAttribArray(oneLocation); 4577 } 4578 4579 gl.useProgram(m_program->getProgram()); 4580 4581 GLU_EXPECT_NO_ERROR(gl.getError(), "setup render"); 4582 4583 gl.beginQuery(GL_PRIMITIVES_GENERATED, *query); 4584 gl.drawArrays(GL_POINTS, 0, 8); 4585 gl.endQuery(GL_PRIMITIVES_GENERATED); 4586 4587 GLU_EXPECT_NO_ERROR(gl.getError(), "render and query"); 4588 4589 gl.getQueryObjectuiv(*query, GL_QUERY_RESULT, &primitivesGenerated); 4590 GLU_EXPECT_NO_ERROR(gl.getError(), "get query result"); 4591 } 4592 4593 m_testCtx.getLog() 4594 << tcu::TestLog::Message 4595 << "GL_PRIMITIVES_GENERATED = " << primitivesGenerated 4596 << tcu::TestLog::EndMessage; 4597 4598 { 4599 const deUint32 expectedGenerated = (m_test == TEST_AMPLIFICATION) ? (3*8) : (m_test == TEST_INSTANCED) ? (8*(3+1)) : (8); 4600 4601 if (expectedGenerated == primitivesGenerated) 4602 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4603 else 4604 { 4605 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong result for GL_PRIMITIVES_GENERATED"); 4606 m_testCtx.getLog() 4607 << tcu::TestLog::Message 4608 << "Got unexpected result for GL_PRIMITIVES_GENERATED. Expected " << expectedGenerated << ", got " << primitivesGenerated 4609 << tcu::TestLog::EndMessage; 4610 } 4611 } 4612 4613 return STOP; 4614 } 4615 4616 glu::ShaderProgram* PrimitivesGeneratedQueryCase::genProgram (void) 4617 { 4618 static const char* const vertexSource = "#version 310 es\n" 4619 "in highp vec4 a_position;\n" 4620 "in highp vec4 a_one;\n" 4621 "out highp vec4 v_one;\n" 4622 "void main (void)\n" 4623 "{\n" 4624 " gl_Position = a_position;\n" 4625 " v_one = a_one;\n" 4626 "}\n"; 4627 static const char* const fragmentSource = "#version 310 es\n" 4628 "layout(location = 0) out mediump vec4 fragColor;\n" 4629 "void main (void)\n" 4630 "{\n" 4631 " fragColor = vec4(1.0, 1.0, 1.0, 1.0);\n" 4632 "}\n"; 4633 std::ostringstream geometrySource; 4634 glu::ProgramSources sources; 4635 4636 if (m_test != TEST_NO_GEOMETRY) 4637 { 4638 geometrySource << "#version 310 es\n" 4639 "#extension GL_EXT_geometry_shader : require\n" 4640 "layout(points" << ((m_test == TEST_INSTANCED) ? (", invocations = 3") : ("")) << ") in;\n" 4641 "layout(triangle_strip, max_vertices = 7) out;\n" 4642 "in highp vec4 v_one[];\n" 4643 "void main (void)\n" 4644 "{\n" 4645 " // always taken\n" 4646 " if (v_one[0].x != 0.0)\n" 4647 " {\n" 4648 " gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.1, 0.0, 0.0);\n" 4649 " EmitVertex();\n" 4650 " gl_Position = gl_in[0].gl_Position + vec4(0.1, 0.0, 0.0, 0.0);\n" 4651 " EmitVertex();\n" 4652 " gl_Position = gl_in[0].gl_Position - vec4(0.1, 0.0, 0.0, 0.0);\n" 4653 " EmitVertex();\n" 4654 " EndPrimitive();\n" 4655 " }\n"; 4656 4657 if (m_test == TEST_AMPLIFICATION) 4658 { 4659 geometrySource << "\n" 4660 " // always taken\n" 4661 " if (v_one[0].y != 0.0)\n" 4662 " {\n" 4663 " gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.1, 0.0, 0.0);\n" 4664 " EmitVertex();\n" 4665 " gl_Position = gl_in[0].gl_Position + vec4(0.1, 0.0, 0.0, 0.0);\n" 4666 " EmitVertex();\n" 4667 " gl_Position = gl_in[0].gl_Position - vec4(0.0, 0.1, 0.0, 0.0);\n" 4668 " EmitVertex();\n" 4669 " gl_Position = gl_in[0].gl_Position - vec4(0.1, 0.0, 0.0, 0.0);\n" 4670 " EmitVertex();\n" 4671 " }\n"; 4672 } 4673 else if (m_test == TEST_PARTIAL_PRIMITIVES) 4674 { 4675 geometrySource << "\n" 4676 " // always taken\n" 4677 " if (v_one[0].y != 0.0)\n" 4678 " {\n" 4679 " gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.1, 0.0, 0.0);\n" 4680 " EmitVertex();\n" 4681 " gl_Position = gl_in[0].gl_Position + vec4(0.1, 0.0, 0.0, 0.0);\n" 4682 " EmitVertex();\n" 4683 "\n" 4684 " // never taken\n" 4685 " if (v_one[0].z < 0.0)\n" 4686 " {\n" 4687 " gl_Position = gl_in[0].gl_Position - vec4(0.1, 0.0, 0.0, 0.0);\n" 4688 " EmitVertex();\n" 4689 " }\n" 4690 " }\n"; 4691 } 4692 else if (m_test == TEST_INSTANCED) 4693 { 4694 geometrySource << "\n" 4695 " // taken once\n" 4696 " if (v_one[0].y > float(gl_InvocationID) + 0.5)\n" 4697 " {\n" 4698 " gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.1, 0.0, 0.0);\n" 4699 " EmitVertex();\n" 4700 " gl_Position = gl_in[0].gl_Position + vec4(0.1, 0.0, 0.0, 0.0);\n" 4701 " EmitVertex();\n" 4702 " gl_Position = gl_in[0].gl_Position - vec4(0.1, 0.0, 0.0, 0.0);\n" 4703 " EmitVertex();\n" 4704 " }\n"; 4705 } 4706 4707 geometrySource << "}\n"; 4708 } 4709 4710 sources << glu::VertexSource(vertexSource); 4711 sources << glu::FragmentSource(fragmentSource); 4712 4713 if (!geometrySource.str().empty()) 4714 sources << glu::GeometrySource(geometrySource.str()); 4715 4716 return new glu::ShaderProgram(m_context.getRenderContext(), sources); 4717 } 4718 4719 class GeometryShaderFeartureTestCase : public TestCase 4720 { 4721 public: 4722 GeometryShaderFeartureTestCase (Context& context, const char* name, const char* description); 4723 4724 void init (void); 4725 }; 4726 4727 GeometryShaderFeartureTestCase::GeometryShaderFeartureTestCase (Context& context, const char* name, const char* description) 4728 : TestCase(context, name, description) 4729 { 4730 } 4731 4732 void GeometryShaderFeartureTestCase::init (void) 4733 { 4734 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 4735 throw tcu::NotSupportedError("test requires GL_EXT_geometry_shader extension"); 4736 } 4737 4738 class FramebufferDefaultLayersCase : public GeometryShaderFeartureTestCase 4739 { 4740 public: 4741 FramebufferDefaultLayersCase (Context& context, const char* name, const char* description); 4742 IterateResult iterate (void); 4743 }; 4744 4745 FramebufferDefaultLayersCase::FramebufferDefaultLayersCase (Context& context, const char* name, const char* description) 4746 : GeometryShaderFeartureTestCase(context, name, description) 4747 { 4748 } 4749 4750 FramebufferDefaultLayersCase::IterateResult FramebufferDefaultLayersCase::iterate (void) 4751 { 4752 glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 4753 4754 gl.enableLogging(true); 4755 4756 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4757 4758 { 4759 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Default", "Default value"); 4760 const glu::Framebuffer fbo (m_context.getRenderContext()); 4761 glw::GLint defaultLayers = -1; 4762 4763 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo); 4764 gl.glGetFramebufferParameteriv(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_LAYERS, &defaultLayers); 4765 GLU_EXPECT_NO_ERROR(gl.glGetError(), "getFramebufferParameteriv"); 4766 4767 m_testCtx.getLog() << tcu::TestLog::Message << "GL_FRAMEBUFFER_DEFAULT_LAYERS = " << defaultLayers << tcu::TestLog::EndMessage; 4768 4769 if (defaultLayers != 0) 4770 { 4771 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected 0, got " << defaultLayers << tcu::TestLog::EndMessage; 4772 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid layer count"); 4773 } 4774 } 4775 4776 { 4777 const tcu::ScopedLogSection section (m_testCtx.getLog(), "SetTo12", "Set default layers to 12"); 4778 const glu::Framebuffer fbo (m_context.getRenderContext()); 4779 glw::GLint defaultLayers = -1; 4780 4781 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo); 4782 gl.glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_LAYERS, 12); 4783 gl.glGetFramebufferParameteriv(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_LAYERS, &defaultLayers); 4784 GLU_EXPECT_NO_ERROR(gl.glGetError(), "getFramebufferParameteriv"); 4785 4786 m_testCtx.getLog() << tcu::TestLog::Message << "GL_FRAMEBUFFER_DEFAULT_LAYERS = " << defaultLayers << tcu::TestLog::EndMessage; 4787 4788 if (defaultLayers != 12) 4789 { 4790 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected 12, got " << defaultLayers << tcu::TestLog::EndMessage; 4791 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid layer count"); 4792 } 4793 } 4794 4795 return STOP; 4796 } 4797 4798 class FramebufferAttachmentLayeredCase : public GeometryShaderFeartureTestCase 4799 { 4800 public: 4801 FramebufferAttachmentLayeredCase (Context& context, const char* name, const char* description); 4802 IterateResult iterate (void); 4803 }; 4804 4805 FramebufferAttachmentLayeredCase::FramebufferAttachmentLayeredCase (Context& context, const char* name, const char* description) 4806 : GeometryShaderFeartureTestCase(context, name, description) 4807 { 4808 } 4809 4810 FramebufferAttachmentLayeredCase::IterateResult FramebufferAttachmentLayeredCase::iterate (void) 4811 { 4812 enum CaseType 4813 { 4814 TEXTURE_3D, 4815 TEXTURE_2D_ARRAY, 4816 TEXTURE_CUBE, 4817 TEXTURE_2D_MS_ARRAY, 4818 TEXTURE_3D_LAYER, 4819 TEXTURE_2D_ARRAY_LAYER, 4820 }; 4821 4822 static const struct TextureType 4823 { 4824 const char* name; 4825 const char* description; 4826 bool layered; 4827 CaseType type; 4828 } textureTypes[] = 4829 { 4830 { "3D", "3D texture", true, TEXTURE_3D }, 4831 { "2DArray", "2D array", true, TEXTURE_2D_ARRAY }, 4832 { "Cube", "Cube map", true, TEXTURE_CUBE }, 4833 { "2DMSArray", "2D multisample array", true, TEXTURE_2D_MS_ARRAY }, 4834 { "3DLayer", "3D texture layer ", false, TEXTURE_3D_LAYER }, 4835 { "2DArrayLayer", "2D array layer ", false, TEXTURE_2D_ARRAY_LAYER }, 4836 }; 4837 4838 glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 4839 gl.enableLogging(true); 4840 4841 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4842 4843 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(textureTypes); ++ndx) 4844 { 4845 const tcu::ScopedLogSection section (m_testCtx.getLog(), textureTypes[ndx].name, textureTypes[ndx].description); 4846 const glu::Framebuffer fbo (m_context.getRenderContext()); 4847 const glu::Texture texture (m_context.getRenderContext()); 4848 glw::GLint layered = -1; 4849 4850 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo); 4851 4852 if (textureTypes[ndx].type == TEXTURE_3D || textureTypes[ndx].type == TEXTURE_3D_LAYER) 4853 { 4854 gl.glBindTexture(GL_TEXTURE_3D, *texture); 4855 gl.glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL); 4856 gl.glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4857 gl.glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4858 4859 if (textureTypes[ndx].type == TEXTURE_3D) 4860 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture, 0); 4861 else 4862 gl.glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture, 0, 2); 4863 } 4864 else if (textureTypes[ndx].type == TEXTURE_2D_ARRAY || textureTypes[ndx].type == TEXTURE_2D_ARRAY_LAYER) 4865 { 4866 gl.glBindTexture(GL_TEXTURE_2D_ARRAY, *texture); 4867 gl.glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL); 4868 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4869 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4870 4871 if (textureTypes[ndx].type == TEXTURE_2D_ARRAY) 4872 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture, 0); 4873 else 4874 gl.glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture, 0, 3); 4875 } 4876 else if (textureTypes[ndx].type == TEXTURE_CUBE) 4877 { 4878 gl.glBindTexture(GL_TEXTURE_CUBE_MAP, *texture); 4879 for (int face = 0; face < 6; ++face) 4880 gl.glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA8, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL); 4881 gl.glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4882 gl.glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4883 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture, 0); 4884 } 4885 else if (textureTypes[ndx].type == TEXTURE_2D_MS_ARRAY) 4886 { 4887 // check extension 4888 if (!m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array")) 4889 { 4890 m_testCtx.getLog() << tcu::TestLog::Message << "GL_OES_texture_storage_multisample_2d_array not supported, skipping." << tcu::TestLog::EndMessage; 4891 continue; 4892 } 4893 4894 gl.glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, *texture); 4895 gl.glTexStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 1, GL_RGBA8, 32, 32, 32, GL_FALSE); 4896 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture, 0); 4897 } 4898 4899 GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup attachment"); 4900 4901 gl.glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_LAYERED, &layered); 4902 GLU_EXPECT_NO_ERROR(gl.glGetError(), "getFramebufferParameteriv"); 4903 4904 m_testCtx.getLog() << tcu::TestLog::Message << "GL_FRAMEBUFFER_ATTACHMENT_LAYERED = " << glu::getBooleanStr(layered) << tcu::TestLog::EndMessage; 4905 4906 if (layered != GL_TRUE && layered != GL_FALSE) 4907 { 4908 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected boolean, got " << layered << tcu::TestLog::EndMessage; 4909 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid boolean"); 4910 } 4911 else if ((layered == GL_TRUE) != textureTypes[ndx].layered) 4912 { 4913 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected " << ((textureTypes[ndx].layered) ? ("GL_TRUE") : ("GL_FALSE")) << ", got " << glu::getBooleanStr(layered) << tcu::TestLog::EndMessage; 4914 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid layer count"); 4915 } 4916 } 4917 4918 return STOP; 4919 } 4920 4921 class FramebufferIncompleteLayereTargetsCase : public GeometryShaderFeartureTestCase 4922 { 4923 public: 4924 FramebufferIncompleteLayereTargetsCase (Context& context, const char* name, const char* description); 4925 IterateResult iterate (void); 4926 }; 4927 4928 FramebufferIncompleteLayereTargetsCase::FramebufferIncompleteLayereTargetsCase (Context& context, const char* name, const char* description) 4929 : GeometryShaderFeartureTestCase(context, name, description) 4930 { 4931 } 4932 4933 FramebufferIncompleteLayereTargetsCase::IterateResult FramebufferIncompleteLayereTargetsCase::iterate (void) 4934 { 4935 glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 4936 gl.enableLogging(true); 4937 4938 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4939 4940 { 4941 const tcu::ScopedLogSection section (m_testCtx.getLog(), "LayerAndNonLayer", "Layered and non-layered"); 4942 const glu::Framebuffer fbo (m_context.getRenderContext()); 4943 const glu::Texture texture0 (m_context.getRenderContext()); 4944 const glu::Texture texture1 (m_context.getRenderContext()); 4945 4946 glw::GLint fboStatus; 4947 4948 gl.glBindTexture(GL_TEXTURE_2D_ARRAY, *texture0); 4949 gl.glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL); 4950 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4951 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4952 4953 gl.glBindTexture(GL_TEXTURE_2D_ARRAY, *texture1); 4954 gl.glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL); 4955 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4956 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4957 4958 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo); 4959 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture0, 0); 4960 gl.glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, *texture1, 0, 0); 4961 4962 GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup fbo"); 4963 4964 fboStatus = gl.glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); 4965 m_testCtx.getLog() << tcu::TestLog::Message << "Framebuffer status: " << glu::getFramebufferStatusStr(fboStatus) << tcu::TestLog::EndMessage; 4966 4967 if (fboStatus != GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS) 4968 { 4969 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS, got " << glu::getFramebufferStatusStr(fboStatus) << tcu::TestLog::EndMessage; 4970 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid layer count"); 4971 } 4972 } 4973 4974 { 4975 const tcu::ScopedLogSection section (m_testCtx.getLog(), "DifferentTarget", "Different target"); 4976 const glu::Framebuffer fbo (m_context.getRenderContext()); 4977 const glu::Texture texture0 (m_context.getRenderContext()); 4978 const glu::Texture texture1 (m_context.getRenderContext()); 4979 4980 glw::GLint fboStatus; 4981 4982 gl.glBindTexture(GL_TEXTURE_2D_ARRAY, *texture0); 4983 gl.glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL); 4984 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4985 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4986 4987 gl.glBindTexture(GL_TEXTURE_3D, *texture1); 4988 gl.glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL); 4989 gl.glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4990 gl.glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4991 4992 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo); 4993 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture0, 0); 4994 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, *texture1, 0); 4995 4996 GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup fbo"); 4997 4998 fboStatus = gl.glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); 4999 m_testCtx.getLog() << tcu::TestLog::Message << "Framebuffer status: " << glu::getFramebufferStatusStr(fboStatus) << tcu::TestLog::EndMessage; 5000 5001 if (fboStatus != GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS) 5002 { 5003 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS, got " << glu::getFramebufferStatusStr(fboStatus) << tcu::TestLog::EndMessage; 5004 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid layer count"); 5005 } 5006 } 5007 5008 return STOP; 5009 } 5010 5011 class ReferencedByGeometryShaderCase : public GeometryShaderFeartureTestCase 5012 { 5013 public: 5014 ReferencedByGeometryShaderCase (Context& context, const char* name, const char* description); 5015 IterateResult iterate (void); 5016 }; 5017 5018 ReferencedByGeometryShaderCase::ReferencedByGeometryShaderCase (Context& context, const char* name, const char* description) 5019 : GeometryShaderFeartureTestCase(context, name, description) 5020 { 5021 } 5022 5023 ReferencedByGeometryShaderCase::IterateResult ReferencedByGeometryShaderCase::iterate (void) 5024 { 5025 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5026 5027 { 5028 static const char* const vertexSource = "#version 310 es\n" 5029 "uniform highp vec4 u_position;\n" 5030 "void main (void)\n" 5031 "{\n" 5032 " gl_Position = u_position;\n" 5033 "}\n"; 5034 static const char* const fragmentSource = "#version 310 es\n" 5035 "layout(location = 0) out mediump vec4 fragColor;\n" 5036 "void main (void)\n" 5037 "{\n" 5038 " fragColor = vec4(1.0, 1.0, 1.0, 1.0);\n" 5039 "}\n"; 5040 static const char* const geometrySource = "#version 310 es\n" 5041 "#extension GL_EXT_geometry_shader : require\n" 5042 "layout(points) in;\n" 5043 "layout(points, max_vertices=1) out;\n" 5044 "uniform highp vec4 u_offset;\n" 5045 "void main (void)\n" 5046 "{\n" 5047 " gl_Position = gl_in[0].gl_Position + u_offset;\n" 5048 " EmitVertex();\n" 5049 "}\n"; 5050 5051 const glu::ShaderProgram program(m_context.getRenderContext(), glu::ProgramSources() 5052 << glu::VertexSource(vertexSource) 5053 << glu::FragmentSource(fragmentSource) 5054 << glu::GeometrySource(geometrySource)); 5055 m_testCtx.getLog() << program; 5056 5057 { 5058 const tcu::ScopedLogSection section (m_testCtx.getLog(), "UnreferencedUniform", "Unreferenced uniform u_position"); 5059 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 5060 const deUint32 props[1] = { GL_REFERENCED_BY_GEOMETRY_SHADER }; 5061 deUint32 resourcePos; 5062 glw::GLsizei length = 0; 5063 glw::GLint referenced = 0; 5064 5065 gl.enableLogging(true); 5066 5067 resourcePos = gl.glGetProgramResourceIndex(program.getProgram(), GL_UNIFORM, "u_position"); 5068 m_testCtx.getLog() << tcu::TestLog::Message << "u_position resource index: " << resourcePos << tcu::TestLog::EndMessage; 5069 5070 gl.glGetProgramResourceiv(program.getProgram(), GL_UNIFORM, resourcePos, 1, props, 1, &length, &referenced); 5071 m_testCtx.getLog() << tcu::TestLog::Message << "Query GL_REFERENCED_BY_GEOMETRY_SHADER, got " << length << " value(s), value[0] = " << glu::getBooleanStr(referenced) << tcu::TestLog::EndMessage; 5072 5073 GLU_EXPECT_NO_ERROR(gl.glGetError(), "query resource"); 5074 5075 if (length == 0 || referenced != GL_FALSE) 5076 { 5077 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected GL_FALSE." << tcu::TestLog::EndMessage; 5078 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected value"); 5079 } 5080 } 5081 5082 { 5083 const tcu::ScopedLogSection section (m_testCtx.getLog(), "ReferencedUniform", "Referenced uniform u_offset"); 5084 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 5085 const deUint32 props[1] = { GL_REFERENCED_BY_GEOMETRY_SHADER }; 5086 deUint32 resourcePos; 5087 glw::GLsizei length = 0; 5088 glw::GLint referenced = 0; 5089 5090 gl.enableLogging(true); 5091 5092 resourcePos = gl.glGetProgramResourceIndex(program.getProgram(), GL_UNIFORM, "u_offset"); 5093 m_testCtx.getLog() << tcu::TestLog::Message << "u_offset resource index: " << resourcePos << tcu::TestLog::EndMessage; 5094 5095 gl.glGetProgramResourceiv(program.getProgram(), GL_UNIFORM, resourcePos, 1, props, 1, &length, &referenced); 5096 m_testCtx.getLog() << tcu::TestLog::Message << "Query GL_REFERENCED_BY_GEOMETRY_SHADER, got " << length << " value(s), value[0] = " << glu::getBooleanStr(referenced) << tcu::TestLog::EndMessage; 5097 5098 GLU_EXPECT_NO_ERROR(gl.glGetError(), "query resource"); 5099 5100 if (length == 0 || referenced != GL_TRUE) 5101 { 5102 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected GL_TRUE." << tcu::TestLog::EndMessage; 5103 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected value"); 5104 } 5105 } 5106 } 5107 5108 return STOP; 5109 } 5110 5111 class VertexFeedbackCase : public TestCase 5112 { 5113 public: 5114 enum DrawMethod 5115 { 5116 METHOD_DRAW_ARRAYS = 0, 5117 METHOD_DRAW_ARRAYS_INSTANCED, 5118 METHOD_DRAW_ARRAYS_INDIRECT, 5119 METHOD_DRAW_ELEMENTS, 5120 METHOD_DRAW_ELEMENTS_INSTANCED, 5121 METHOD_DRAW_ELEMENTS_INDIRECT, 5122 5123 METHOD_LAST 5124 }; 5125 enum PrimitiveType 5126 { 5127 PRIMITIVE_LINE_LOOP = 0, 5128 PRIMITIVE_LINE_STRIP, 5129 PRIMITIVE_TRIANGLE_STRIP, 5130 PRIMITIVE_TRIANGLE_FAN, 5131 PRIMITIVE_POINTS, 5132 5133 PRIMITIVE_LAST 5134 }; 5135 5136 VertexFeedbackCase (Context& context, const char* name, const char* description, DrawMethod method, PrimitiveType output); 5137 ~VertexFeedbackCase (void); 5138 private: 5139 void init (void); 5140 void deinit (void); 5141 IterateResult iterate (void); 5142 5143 glu::ShaderProgram* genProgram (void); 5144 deUint32 getOutputPrimitive (void); 5145 deUint32 getBasePrimitive (void); 5146 5147 const DrawMethod m_method; 5148 const PrimitiveType m_output; 5149 5150 deUint32 m_elementBuf; 5151 deUint32 m_arrayBuf; 5152 deUint32 m_offsetBuf; 5153 deUint32 m_feedbackBuf; 5154 deUint32 m_indirectBuffer; 5155 glu::ShaderProgram* m_program; 5156 glu::VertexArray* m_vao; 5157 }; 5158 5159 VertexFeedbackCase::VertexFeedbackCase (Context& context, const char* name, const char* description, DrawMethod method, PrimitiveType output) 5160 : TestCase (context, name, description) 5161 , m_method (method) 5162 , m_output (output) 5163 , m_elementBuf (0) 5164 , m_arrayBuf (0) 5165 , m_offsetBuf (0) 5166 , m_feedbackBuf (0) 5167 , m_indirectBuffer (0) 5168 , m_program (DE_NULL) 5169 , m_vao (DE_NULL) 5170 { 5171 DE_ASSERT(method < METHOD_LAST); 5172 DE_ASSERT(output < PRIMITIVE_LAST); 5173 } 5174 5175 VertexFeedbackCase::~VertexFeedbackCase (void) 5176 { 5177 deinit(); 5178 } 5179 5180 void VertexFeedbackCase::init (void) 5181 { 5182 // requirements 5183 5184 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 5185 throw tcu::NotSupportedError("test requires GL_EXT_geometry_shader extension"); 5186 5187 // log what test tries to do 5188 5189 m_testCtx.getLog() 5190 << tcu::TestLog::Message 5191 << "Testing GL_EXT_geometry_shader transform feedback relaxations.\n" 5192 << "Capturing vertex shader varying, no geometry shader. Invoke with:" 5193 << tcu::TestLog::EndMessage; 5194 5195 switch (m_method) 5196 { 5197 case METHOD_DRAW_ARRAYS: m_testCtx.getLog() << tcu::TestLog::Message << "Draw method: drawArrays" << tcu::TestLog::EndMessage; break; 5198 case METHOD_DRAW_ARRAYS_INSTANCED: m_testCtx.getLog() << tcu::TestLog::Message << "Draw method: drawArraysInstanced" << tcu::TestLog::EndMessage; break; 5199 case METHOD_DRAW_ARRAYS_INDIRECT: m_testCtx.getLog() << tcu::TestLog::Message << "Draw method: drawArraysIndirect" << tcu::TestLog::EndMessage; break; 5200 case METHOD_DRAW_ELEMENTS: m_testCtx.getLog() << tcu::TestLog::Message << "Draw method: drawElements" << tcu::TestLog::EndMessage; break; 5201 case METHOD_DRAW_ELEMENTS_INSTANCED: m_testCtx.getLog() << tcu::TestLog::Message << "Draw method: drawElementsInstanced" << tcu::TestLog::EndMessage; break; 5202 case METHOD_DRAW_ELEMENTS_INDIRECT: m_testCtx.getLog() << tcu::TestLog::Message << "Draw method: drawElementsIndirect" << tcu::TestLog::EndMessage; break; 5203 default: 5204 DE_ASSERT(false); 5205 } 5206 switch (m_output) 5207 { 5208 case PRIMITIVE_LINE_LOOP: m_testCtx.getLog() << tcu::TestLog::Message << "Draw primitive: line loop" << tcu::TestLog::EndMessage; break; 5209 case PRIMITIVE_LINE_STRIP: m_testCtx.getLog() << tcu::TestLog::Message << "Draw primitive: line strip" << tcu::TestLog::EndMessage; break; 5210 case PRIMITIVE_TRIANGLE_STRIP: m_testCtx.getLog() << tcu::TestLog::Message << "Draw primitive: triangle strip" << tcu::TestLog::EndMessage; break; 5211 case PRIMITIVE_TRIANGLE_FAN: m_testCtx.getLog() << tcu::TestLog::Message << "Draw primitive: triangle fan" << tcu::TestLog::EndMessage; break; 5212 case PRIMITIVE_POINTS: m_testCtx.getLog() << tcu::TestLog::Message << "Draw primitive: points" << tcu::TestLog::EndMessage; break; 5213 default: 5214 DE_ASSERT(false); 5215 } 5216 5217 // resources 5218 5219 { 5220 static const deUint16 elementData[] = 5221 { 5222 0, 1, 2, 3, 5223 }; 5224 static const tcu::Vec4 arrayData[] = 5225 { 5226 tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), 5227 tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), 5228 tcu::Vec4(2.0f, 0.0f, 0.0f, 0.0f), 5229 tcu::Vec4(3.0f, 0.0f, 0.0f, 0.0f), 5230 }; 5231 static const tcu::Vec4 offsetData[] = 5232 { 5233 tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), 5234 tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), 5235 tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), 5236 tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), 5237 }; 5238 5239 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5240 const int feedbackSize = 8 * sizeof(float[4]); 5241 5242 m_vao = new glu::VertexArray(m_context.getRenderContext()); 5243 gl.bindVertexArray(**m_vao); 5244 GLU_EXPECT_NO_ERROR(gl.getError(), "set up vao"); 5245 5246 gl.genBuffers(1, &m_elementBuf); 5247 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBuf); 5248 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), &elementData[0], GL_STATIC_DRAW); 5249 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf"); 5250 5251 gl.genBuffers(1, &m_arrayBuf); 5252 gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuf); 5253 gl.bufferData(GL_ARRAY_BUFFER, sizeof(arrayData), &arrayData[0], GL_STATIC_DRAW); 5254 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf"); 5255 5256 gl.genBuffers(1, &m_offsetBuf); 5257 gl.bindBuffer(GL_ARRAY_BUFFER, m_offsetBuf); 5258 gl.bufferData(GL_ARRAY_BUFFER, sizeof(offsetData), &offsetData[0], GL_STATIC_DRAW); 5259 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf"); 5260 5261 gl.genBuffers(1, &m_feedbackBuf); 5262 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_feedbackBuf); 5263 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, feedbackSize, DE_NULL, GL_DYNAMIC_COPY); 5264 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf"); 5265 5266 m_program = genProgram(); 5267 5268 if (!m_program->isOk()) 5269 { 5270 m_testCtx.getLog() << *m_program; 5271 throw tcu::TestError("could not build program"); 5272 } 5273 } 5274 } 5275 5276 void VertexFeedbackCase::deinit (void) 5277 { 5278 if (m_elementBuf) 5279 { 5280 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_elementBuf); 5281 m_elementBuf = 0; 5282 } 5283 5284 if (m_arrayBuf) 5285 { 5286 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_arrayBuf); 5287 m_arrayBuf = 0; 5288 } 5289 5290 if (m_offsetBuf) 5291 { 5292 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_offsetBuf); 5293 m_offsetBuf = 0; 5294 } 5295 5296 if (m_feedbackBuf) 5297 { 5298 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_feedbackBuf); 5299 m_feedbackBuf = 0; 5300 } 5301 5302 if (m_indirectBuffer) 5303 { 5304 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_indirectBuffer); 5305 m_indirectBuffer = 0; 5306 } 5307 5308 delete m_program; 5309 m_program = DE_NULL; 5310 5311 delete m_vao; 5312 m_vao = DE_NULL; 5313 } 5314 5315 VertexFeedbackCase::IterateResult VertexFeedbackCase::iterate (void) 5316 { 5317 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5318 const deUint32 outputPrimitive = getOutputPrimitive(); 5319 const deUint32 basePrimitive = getBasePrimitive(); 5320 5321 const int posLocation = gl.getAttribLocation(m_program->getProgram(), "a_position"); 5322 const int offsetLocation = gl.getAttribLocation(m_program->getProgram(), "a_offset"); 5323 5324 if (posLocation == -1) 5325 throw tcu::TestError("a_position location was -1"); 5326 if (offsetLocation == -1) 5327 throw tcu::TestError("a_offset location was -1"); 5328 5329 gl.useProgram(m_program->getProgram()); 5330 5331 gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuf); 5332 gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 5333 gl.enableVertexAttribArray(posLocation); 5334 5335 gl.bindBuffer(GL_ARRAY_BUFFER, m_offsetBuf); 5336 gl.vertexAttribPointer(offsetLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 5337 gl.enableVertexAttribArray(offsetLocation); 5338 5339 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_feedbackBuf); 5340 GLU_EXPECT_NO_ERROR(gl.getError(), "bind buffer base"); 5341 5342 m_testCtx.getLog() << tcu::TestLog::Message << "Calling BeginTransformFeedback(" << glu::getPrimitiveTypeStr(basePrimitive) << ")" << tcu::TestLog::EndMessage; 5343 gl.beginTransformFeedback(basePrimitive); 5344 GLU_EXPECT_NO_ERROR(gl.getError(), "beginTransformFeedback"); 5345 5346 switch (m_method) 5347 { 5348 case METHOD_DRAW_ARRAYS: 5349 { 5350 m_testCtx.getLog() << tcu::TestLog::Message << "Calling DrawArrays(" << glu::getPrimitiveTypeStr(outputPrimitive) << ", ...)" << tcu::TestLog::EndMessage; 5351 gl.drawArrays(outputPrimitive, 0, 4); 5352 break; 5353 } 5354 5355 case METHOD_DRAW_ARRAYS_INSTANCED: 5356 { 5357 m_testCtx.getLog() << tcu::TestLog::Message << "Calling DrawArraysInstanced(" << glu::getPrimitiveTypeStr(outputPrimitive) << ", ...)" << tcu::TestLog::EndMessage; 5358 gl.vertexAttribDivisor(offsetLocation, 2); 5359 gl.drawArraysInstanced(outputPrimitive, 0, 3, 2); 5360 break; 5361 } 5362 5363 case METHOD_DRAW_ELEMENTS: 5364 { 5365 m_testCtx.getLog() << tcu::TestLog::Message << "Calling DrawElements(" << glu::getPrimitiveTypeStr(outputPrimitive) << ", ...)" << tcu::TestLog::EndMessage; 5366 gl.drawElements(outputPrimitive, 4, GL_UNSIGNED_SHORT, DE_NULL); 5367 break; 5368 } 5369 5370 case METHOD_DRAW_ELEMENTS_INSTANCED: 5371 { 5372 m_testCtx.getLog() << tcu::TestLog::Message << "Calling DrawElementsInstanced(" << glu::getPrimitiveTypeStr(outputPrimitive) << ", ...)" << tcu::TestLog::EndMessage; 5373 gl.drawElementsInstanced(outputPrimitive, 3, GL_UNSIGNED_SHORT, DE_NULL, 2); 5374 break; 5375 } 5376 5377 case METHOD_DRAW_ARRAYS_INDIRECT: 5378 { 5379 struct DrawArraysIndirectCommand 5380 { 5381 deUint32 count; 5382 deUint32 instanceCount; 5383 deUint32 first; 5384 deUint32 reservedMustBeZero; 5385 } params; 5386 5387 DE_STATIC_ASSERT(sizeof(DrawArraysIndirectCommand) == sizeof(deUint32[4])); 5388 5389 params.count = 4; 5390 params.instanceCount = 1; 5391 params.first = 0; 5392 params.reservedMustBeZero = 0; 5393 5394 gl.genBuffers(1, &m_indirectBuffer); 5395 gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_indirectBuffer); 5396 gl.bufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(params), ¶ms, GL_STATIC_DRAW); 5397 5398 m_testCtx.getLog() << tcu::TestLog::Message << "Calling DrawElementsIndirect(" << glu::getPrimitiveTypeStr(outputPrimitive) << ", ...)" << tcu::TestLog::EndMessage; 5399 gl.drawArraysIndirect(outputPrimitive, DE_NULL); 5400 break; 5401 } 5402 5403 case METHOD_DRAW_ELEMENTS_INDIRECT: 5404 { 5405 struct DrawElementsIndirectCommand 5406 { 5407 deUint32 count; 5408 deUint32 instanceCount; 5409 deUint32 firstIndex; 5410 deInt32 baseVertex; 5411 deUint32 reservedMustBeZero; 5412 } params; 5413 5414 DE_STATIC_ASSERT(sizeof(DrawElementsIndirectCommand) == sizeof(deUint32[5])); 5415 5416 params.count = 4; 5417 params.instanceCount = 1; 5418 params.firstIndex = 0; 5419 params.baseVertex = 0; 5420 params.reservedMustBeZero = 0; 5421 5422 gl.genBuffers(1, &m_indirectBuffer); 5423 gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_indirectBuffer); 5424 gl.bufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(params), ¶ms, GL_STATIC_DRAW); 5425 5426 m_testCtx.getLog() << tcu::TestLog::Message << "Calling DrawElementsIndirect(" << glu::getPrimitiveTypeStr(outputPrimitive) << ", ...)" << tcu::TestLog::EndMessage; 5427 gl.drawElementsIndirect(outputPrimitive, GL_UNSIGNED_SHORT, DE_NULL); 5428 break; 5429 } 5430 5431 default: 5432 DE_ASSERT(false); 5433 } 5434 GLU_EXPECT_NO_ERROR(gl.getError(), "draw"); 5435 5436 gl.endTransformFeedback(); 5437 GLU_EXPECT_NO_ERROR(gl.getError(), "endTransformFeedback"); 5438 5439 m_testCtx.getLog() << tcu::TestLog::Message << "No errors." << tcu::TestLog::EndMessage; 5440 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5441 5442 return STOP; 5443 } 5444 5445 glu::ShaderProgram* VertexFeedbackCase::genProgram (void) 5446 { 5447 static const char* const vertexSource = "#version 310 es\n" 5448 "in highp vec4 a_position;\n" 5449 "in highp vec4 a_offset;\n" 5450 "out highp vec4 tf_value;\n" 5451 "void main (void)\n" 5452 "{\n" 5453 " gl_Position = a_position;\n" 5454 " tf_value = a_position + a_offset;\n" 5455 "}\n"; 5456 static const char* const fragmentSource = "#version 310 es\n" 5457 "layout(location = 0) out mediump vec4 fragColor;\n" 5458 "void main (void)\n" 5459 "{\n" 5460 " fragColor = vec4(1.0);\n" 5461 "}\n"; 5462 5463 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 5464 << glu::VertexSource(vertexSource) 5465 << glu::FragmentSource(fragmentSource) 5466 << glu::TransformFeedbackVarying("tf_value") 5467 << glu::TransformFeedbackMode(GL_INTERLEAVED_ATTRIBS)); 5468 } 5469 5470 deUint32 VertexFeedbackCase::getOutputPrimitive (void) 5471 { 5472 switch(m_output) 5473 { 5474 case PRIMITIVE_LINE_LOOP: return GL_LINE_LOOP; 5475 case PRIMITIVE_LINE_STRIP: return GL_LINE_STRIP; 5476 case PRIMITIVE_TRIANGLE_STRIP: return GL_TRIANGLE_STRIP; 5477 case PRIMITIVE_TRIANGLE_FAN: return GL_TRIANGLE_FAN; 5478 case PRIMITIVE_POINTS: return GL_POINTS; 5479 default: 5480 DE_ASSERT(false); 5481 return 0; 5482 } 5483 } 5484 5485 deUint32 VertexFeedbackCase::getBasePrimitive (void) 5486 { 5487 switch(m_output) 5488 { 5489 case PRIMITIVE_LINE_LOOP: return GL_LINES; 5490 case PRIMITIVE_LINE_STRIP: return GL_LINES; 5491 case PRIMITIVE_TRIANGLE_STRIP: return GL_TRIANGLES; 5492 case PRIMITIVE_TRIANGLE_FAN: return GL_TRIANGLES; 5493 case PRIMITIVE_POINTS: return GL_POINTS; 5494 default: 5495 DE_ASSERT(false); 5496 return 0; 5497 } 5498 } 5499 5500 class VertexFeedbackOverflowCase : public TestCase 5501 { 5502 public: 5503 enum Method 5504 { 5505 METHOD_DRAW_ARRAYS = 0, 5506 METHOD_DRAW_ELEMENTS, 5507 }; 5508 5509 VertexFeedbackOverflowCase (Context& context, const char* name, const char* description, Method method); 5510 ~VertexFeedbackOverflowCase (void); 5511 5512 private: 5513 void init (void); 5514 void deinit (void); 5515 IterateResult iterate (void); 5516 glu::ShaderProgram* genProgram (void); 5517 5518 const Method m_method; 5519 5520 deUint32 m_elementBuf; 5521 deUint32 m_arrayBuf; 5522 deUint32 m_feedbackBuf; 5523 glu::ShaderProgram* m_program; 5524 glu::VertexArray* m_vao; 5525 }; 5526 5527 VertexFeedbackOverflowCase::VertexFeedbackOverflowCase (Context& context, const char* name, const char* description, Method method) 5528 : TestCase (context, name, description) 5529 , m_method (method) 5530 , m_elementBuf (0) 5531 , m_arrayBuf (0) 5532 , m_feedbackBuf (0) 5533 , m_program (DE_NULL) 5534 , m_vao (DE_NULL) 5535 { 5536 } 5537 5538 VertexFeedbackOverflowCase::~VertexFeedbackOverflowCase (void) 5539 { 5540 deinit(); 5541 } 5542 5543 void VertexFeedbackOverflowCase::init (void) 5544 { 5545 // requirements 5546 5547 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 5548 throw tcu::NotSupportedError("test requires GL_EXT_geometry_shader extension"); 5549 5550 // log what test tries to do 5551 5552 m_testCtx.getLog() 5553 << tcu::TestLog::Message 5554 << "Testing GL_EXT_geometry_shader transform feedback overflow behavior.\n" 5555 << "Capturing vertex shader varying, rendering 2 triangles. Allocating feedback buffer for 5 vertices." 5556 << tcu::TestLog::EndMessage; 5557 5558 // resources 5559 5560 { 5561 static const deUint16 elementData[] = 5562 { 5563 0, 1, 2, 5564 0, 1, 2, 5565 }; 5566 static const tcu::Vec4 arrayData[] = 5567 { 5568 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 5569 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 5570 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 5571 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 5572 }; 5573 5574 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5575 5576 m_vao = new glu::VertexArray(m_context.getRenderContext()); 5577 gl.bindVertexArray(**m_vao); 5578 GLU_EXPECT_NO_ERROR(gl.getError(), "set up vao"); 5579 5580 if (m_method == METHOD_DRAW_ELEMENTS) 5581 { 5582 gl.genBuffers(1, &m_elementBuf); 5583 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBuf); 5584 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), &elementData[0], GL_STATIC_DRAW); 5585 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf"); 5586 } 5587 5588 gl.genBuffers(1, &m_arrayBuf); 5589 gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuf); 5590 gl.bufferData(GL_ARRAY_BUFFER, sizeof(arrayData), &arrayData[0], GL_STATIC_DRAW); 5591 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf"); 5592 5593 { 5594 const int feedbackCount = 5 * 4; // 5x vec4 5595 const std::vector<float> initialBufferContents (feedbackCount, -1.0f); 5596 5597 m_testCtx.getLog() << tcu::TestLog::Message << "Filling feeback buffer with dummy value (-1.0)." << tcu::TestLog::EndMessage; 5598 5599 gl.genBuffers(1, &m_feedbackBuf); 5600 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_feedbackBuf); 5601 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, (int)(sizeof(float) * initialBufferContents.size()), &initialBufferContents[0], GL_DYNAMIC_COPY); 5602 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf"); 5603 } 5604 5605 m_program = genProgram(); 5606 5607 if (!m_program->isOk()) 5608 { 5609 m_testCtx.getLog() << *m_program; 5610 throw tcu::TestError("could not build program"); 5611 } 5612 } 5613 } 5614 5615 void VertexFeedbackOverflowCase::deinit (void) 5616 { 5617 if (m_elementBuf) 5618 { 5619 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_elementBuf); 5620 m_elementBuf = 0; 5621 } 5622 5623 if (m_arrayBuf) 5624 { 5625 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_arrayBuf); 5626 m_arrayBuf = 0; 5627 } 5628 5629 if (m_feedbackBuf) 5630 { 5631 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_feedbackBuf); 5632 m_feedbackBuf = 0; 5633 } 5634 5635 delete m_program; 5636 m_program = DE_NULL; 5637 5638 delete m_vao; 5639 m_vao = DE_NULL; 5640 } 5641 5642 VertexFeedbackOverflowCase::IterateResult VertexFeedbackOverflowCase::iterate (void) 5643 { 5644 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5645 const int posLocation = gl.getAttribLocation(m_program->getProgram(), "a_position"); 5646 5647 if (posLocation == -1) 5648 throw tcu::TestError("a_position location was -1"); 5649 5650 gl.useProgram(m_program->getProgram()); 5651 5652 gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuf); 5653 gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 5654 gl.enableVertexAttribArray(posLocation); 5655 5656 if (m_method == METHOD_DRAW_ELEMENTS) 5657 { 5658 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBuf); 5659 GLU_EXPECT_NO_ERROR(gl.getError(), "bind buffers"); 5660 } 5661 5662 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_feedbackBuf); 5663 GLU_EXPECT_NO_ERROR(gl.getError(), "bind buffer base"); 5664 5665 m_testCtx.getLog() << tcu::TestLog::Message << "Capturing 2 triangles." << tcu::TestLog::EndMessage; 5666 5667 gl.beginTransformFeedback(GL_TRIANGLES); 5668 5669 if (m_method == METHOD_DRAW_ELEMENTS) 5670 gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL); 5671 else if (m_method == METHOD_DRAW_ARRAYS) 5672 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4); 5673 else 5674 DE_ASSERT(false); 5675 5676 gl.endTransformFeedback(); 5677 GLU_EXPECT_NO_ERROR(gl.getError(), "capture"); 5678 5679 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying final triangle was not partially written to the feedback buffer." << tcu::TestLog::EndMessage; 5680 5681 { 5682 const void* ptr = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(float[4]) * 5, GL_MAP_READ_BIT); 5683 std::vector<float> feedback; 5684 bool error = false; 5685 5686 GLU_EXPECT_NO_ERROR(gl.getError(), "mapBufferRange"); 5687 if (!ptr) 5688 throw tcu::TestError("mapBufferRange returned null"); 5689 5690 feedback.resize(5*4); 5691 deMemcpy(&feedback[0], ptr, sizeof(float[4]) * 5); 5692 5693 if (gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER) != GL_TRUE) 5694 throw tcu::TestError("unmapBuffer returned false"); 5695 5696 // Verify vertices 0 - 2 5697 for (int vertex = 0; vertex < 3; ++vertex) 5698 { 5699 for (int component = 0; component < 4; ++component) 5700 { 5701 if (feedback[vertex*4 + component] != 1.0f) 5702 { 5703 m_testCtx.getLog() 5704 << tcu::TestLog::Message 5705 << "Feedback buffer vertex " << vertex << ", component " << component << ": unexpected value, expected 1.0, got " << feedback[vertex*4 + component] 5706 << tcu::TestLog::EndMessage; 5707 error = true; 5708 } 5709 } 5710 } 5711 5712 // Verify vertices 3 - 4 5713 for (int vertex = 3; vertex < 5; ++vertex) 5714 { 5715 for (int component = 0; component < 4; ++component) 5716 { 5717 if (feedback[vertex*4 + component] != -1.0f) 5718 { 5719 m_testCtx.getLog() 5720 << tcu::TestLog::Message 5721 << "Feedback buffer vertex " << vertex << ", component " << component << ": unexpected value, expected -1.0, got " << feedback[vertex*4 + component] 5722 << tcu::TestLog::EndMessage; 5723 error = true; 5724 } 5725 } 5726 } 5727 5728 if (error) 5729 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Feedback result validation failed"); 5730 else 5731 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5732 } 5733 5734 return STOP; 5735 } 5736 5737 glu::ShaderProgram* VertexFeedbackOverflowCase::genProgram (void) 5738 { 5739 static const char* const vertexSource = "#version 310 es\n" 5740 "in highp vec4 a_position;\n" 5741 "void main (void)\n" 5742 "{\n" 5743 " gl_Position = a_position;\n" 5744 "}\n"; 5745 static const char* const fragmentSource = "#version 310 es\n" 5746 "layout(location = 0) out mediump vec4 fragColor;\n" 5747 "void main (void)\n" 5748 "{\n" 5749 " fragColor = vec4(1.0);\n" 5750 "}\n"; 5751 5752 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 5753 << glu::VertexSource(vertexSource) 5754 << glu::FragmentSource(fragmentSource) 5755 << glu::TransformFeedbackVarying("gl_Position") 5756 << glu::TransformFeedbackMode(GL_INTERLEAVED_ATTRIBS)); 5757 } 5758 5759 } // anonymous 5760 5761 GeometryShaderTests::GeometryShaderTests (Context& context) 5762 : TestCaseGroup(context, "geometry_shading", "Geometry shader tests") 5763 { 5764 } 5765 5766 GeometryShaderTests::~GeometryShaderTests (void) 5767 { 5768 } 5769 5770 void GeometryShaderTests::init (void) 5771 { 5772 struct PrimitiveTestSpec 5773 { 5774 deUint32 primitiveType; 5775 const char* name; 5776 deUint32 outputType; 5777 }; 5778 5779 struct EmitTestSpec 5780 { 5781 deUint32 outputType; 5782 int emitCountA; //!< primitive A emit count 5783 int endCountA; //!< primitive A end count 5784 int emitCountB; //!< 5785 int endCountB; //!< 5786 const char* name; 5787 }; 5788 5789 static const struct LayeredTarget 5790 { 5791 LayeredRenderCase::LayeredRenderTargetType target; 5792 const char* name; 5793 const char* desc; 5794 } layerTargets[] = 5795 { 5796 { LayeredRenderCase::TARGET_CUBE, "cubemap", "cubemap" }, 5797 { LayeredRenderCase::TARGET_3D, "3d", "3D texture" }, 5798 { LayeredRenderCase::TARGET_2D_ARRAY, "2d_array", "2D array texture" }, 5799 { LayeredRenderCase::TARGET_2D_MS_ARRAY, "2d_multisample_array", "2D multisample array texture" }, 5800 }; 5801 5802 tcu::TestCaseGroup* const queryGroup = new tcu::TestCaseGroup(m_testCtx, "query", "Query tests."); 5803 tcu::TestCaseGroup* const basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Basic tests."); 5804 tcu::TestCaseGroup* const inputPrimitiveGroup = new tcu::TestCaseGroup(m_testCtx, "input", "Different input primitives."); 5805 tcu::TestCaseGroup* const conversionPrimitiveGroup = new tcu::TestCaseGroup(m_testCtx, "conversion", "Different input and output primitives."); 5806 tcu::TestCaseGroup* const emitGroup = new tcu::TestCaseGroup(m_testCtx, "emit", "Different emit counts."); 5807 tcu::TestCaseGroup* const varyingGroup = new tcu::TestCaseGroup(m_testCtx, "varying", "Test varyings."); 5808 tcu::TestCaseGroup* const layeredGroup = new tcu::TestCaseGroup(m_testCtx, "layered", "Layered rendering."); 5809 tcu::TestCaseGroup* const instancedGroup = new tcu::TestCaseGroup(m_testCtx, "instanced", "Instanced rendering."); 5810 tcu::TestCaseGroup* const negativeGroup = new tcu::TestCaseGroup(m_testCtx, "negative", "Negative tests."); 5811 tcu::TestCaseGroup* const feedbackGroup = new tcu::TestCaseGroup(m_testCtx, "vertex_transform_feedback", "Transform feedback."); 5812 5813 this->addChild(queryGroup); 5814 this->addChild(basicGroup); 5815 this->addChild(inputPrimitiveGroup); 5816 this->addChild(conversionPrimitiveGroup); 5817 this->addChild(emitGroup); 5818 this->addChild(varyingGroup); 5819 this->addChild(layeredGroup); 5820 this->addChild(instancedGroup); 5821 this->addChild(negativeGroup); 5822 this->addChild(feedbackGroup); 5823 5824 // query test 5825 { 5826 // limits with a corresponding glsl constant 5827 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_input_components", "", GL_MAX_GEOMETRY_INPUT_COMPONENTS, "MaxGeometryInputComponents", 64)); 5828 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_output_components", "", GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, "MaxGeometryOutputComponents", 128)); 5829 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_image_uniforms", "", GL_MAX_GEOMETRY_IMAGE_UNIFORMS, "MaxGeometryImageUniforms", 0)); 5830 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_texture_image_units", "", GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, "MaxGeometryTextureImageUnits", 16)); 5831 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_output_vertices", "", GL_MAX_GEOMETRY_OUTPUT_VERTICES, "MaxGeometryOutputVertices", 256)); 5832 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_total_output_components", "", GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, "MaxGeometryTotalOutputComponents", 1024)); 5833 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_uniform_components", "", GL_MAX_GEOMETRY_UNIFORM_COMPONENTS, "MaxGeometryUniformComponents", 1024)); 5834 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_atomic_counters", "", GL_MAX_GEOMETRY_ATOMIC_COUNTERS, "MaxGeometryAtomicCounters", 0)); 5835 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_atomic_counter_buffers", "", GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS, "MaxGeometryAtomicCounterBuffers", 0)); 5836 5837 // program queries 5838 queryGroup->addChild(new GeometryShaderVerticesQueryCase (m_context, "geometry_linked_vertices_out", "GL_GEOMETRY_LINKED_VERTICES_OUT")); 5839 queryGroup->addChild(new GeometryShaderInputQueryCase (m_context, "geometry_linked_input_type", "GL_GEOMETRY_LINKED_INPUT_TYPE")); 5840 queryGroup->addChild(new GeometryShaderOutputQueryCase (m_context, "geometry_linked_output_type", "GL_GEOMETRY_LINKED_OUTPUT_TYPE")); 5841 queryGroup->addChild(new GeometryShaderInvocationsQueryCase (m_context, "geometry_shader_invocations", "GL_GEOMETRY_SHADER_INVOCATIONS")); 5842 5843 // limits 5844 queryGroup->addChild(new ImplementationLimitCase(m_context, "max_geometry_shader_invocations", "", GL_MAX_GEOMETRY_SHADER_INVOCATIONS, 32)); 5845 queryGroup->addChild(new ImplementationLimitCase(m_context, "max_geometry_uniform_blocks", "", GL_MAX_GEOMETRY_UNIFORM_BLOCKS, 12)); 5846 queryGroup->addChild(new ImplementationLimitCase(m_context, "max_geometry_shader_storage_blocks", "", GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, 0)); 5847 5848 // layer_provoking_vertex_ext 5849 queryGroup->addChild(new LayerProvokingVertexQueryCase(m_context, "layer_provoking_vertex", "GL_LAYER_PROVOKING_VERTEX")); 5850 5851 // primitives_generated 5852 queryGroup->addChild(new PrimitivesGeneratedQueryCase(m_context, "primitives_generated_no_geometry", "PRIMITIVES_GENERATED query with no geometry shader", PrimitivesGeneratedQueryCase::TEST_NO_GEOMETRY)); 5853 queryGroup->addChild(new PrimitivesGeneratedQueryCase(m_context, "primitives_generated_no_amplification", "PRIMITIVES_GENERATED query with non amplifying geometry shader", PrimitivesGeneratedQueryCase::TEST_NO_AMPLIFICATION)); 5854 queryGroup->addChild(new PrimitivesGeneratedQueryCase(m_context, "primitives_generated_amplification", "PRIMITIVES_GENERATED query with amplifying geometry shader", PrimitivesGeneratedQueryCase::TEST_AMPLIFICATION)); 5855 queryGroup->addChild(new PrimitivesGeneratedQueryCase(m_context, "primitives_generated_partial_primitives", "PRIMITIVES_GENERATED query with geometry shader emitting partial primitives", PrimitivesGeneratedQueryCase::TEST_PARTIAL_PRIMITIVES)); 5856 queryGroup->addChild(new PrimitivesGeneratedQueryCase(m_context, "primitives_generated_instanced", "PRIMITIVES_GENERATED query with instanced geometry shader", PrimitivesGeneratedQueryCase::TEST_INSTANCED)); 5857 5858 // fbo 5859 queryGroup->addChild(new ImplementationLimitCase (m_context, "max_framebuffer_layers", "", GL_MAX_FRAMEBUFFER_LAYERS, 256)); 5860 queryGroup->addChild(new FramebufferDefaultLayersCase (m_context, "framebuffer_default_layers", "")); 5861 queryGroup->addChild(new FramebufferAttachmentLayeredCase (m_context, "framebuffer_attachment_layered", "")); 5862 queryGroup->addChild(new FramebufferIncompleteLayereTargetsCase (m_context, "framebuffer_incomplete_layer_targets", "")); 5863 5864 // resource query 5865 queryGroup->addChild(new ReferencedByGeometryShaderCase (m_context, "referenced_by_geometry_shader", "")); 5866 } 5867 5868 // basic tests 5869 { 5870 basicGroup->addChild(new OutputCountCase (m_context, "output_10", "Output 10 vertices", OutputCountPatternSpec(10))); 5871 basicGroup->addChild(new OutputCountCase (m_context, "output_128", "Output 128 vertices", OutputCountPatternSpec(128))); 5872 basicGroup->addChild(new OutputCountCase (m_context, "output_256", "Output 256 vertices", OutputCountPatternSpec(256))); 5873 basicGroup->addChild(new OutputCountCase (m_context, "output_max", "Output max vertices", OutputCountPatternSpec(-1))); 5874 basicGroup->addChild(new OutputCountCase (m_context, "output_10_and_100", "Output 10 and 100 vertices in two invocations", OutputCountPatternSpec(10, 100))); 5875 basicGroup->addChild(new OutputCountCase (m_context, "output_100_and_10", "Output 100 and 10 vertices in two invocations", OutputCountPatternSpec(100, 10))); 5876 basicGroup->addChild(new OutputCountCase (m_context, "output_0_and_128", "Output 0 and 128 vertices in two invocations", OutputCountPatternSpec(0, 128))); 5877 basicGroup->addChild(new OutputCountCase (m_context, "output_128_and_0", "Output 128 and 0 vertices in two invocations", OutputCountPatternSpec(128, 0))); 5878 5879 basicGroup->addChild(new VaryingOutputCountCase (m_context, "output_vary_by_attribute", "Output varying number of vertices", VaryingOutputCountShader::READ_ATTRIBUTE, VaryingOutputCountCase::MODE_WITHOUT_INSTANCING)); 5880 basicGroup->addChild(new VaryingOutputCountCase (m_context, "output_vary_by_uniform", "Output varying number of vertices", VaryingOutputCountShader::READ_UNIFORM, VaryingOutputCountCase::MODE_WITHOUT_INSTANCING)); 5881 basicGroup->addChild(new VaryingOutputCountCase (m_context, "output_vary_by_texture", "Output varying number of vertices", VaryingOutputCountShader::READ_TEXTURE, VaryingOutputCountCase::MODE_WITHOUT_INSTANCING)); 5882 5883 basicGroup->addChild(new BuiltinVariableRenderTest (m_context, "point_size", "test gl_PointSize", BuiltinVariableShader::TEST_POINT_SIZE)); 5884 basicGroup->addChild(new BuiltinVariableRenderTest (m_context, "primitive_id_in", "test gl_PrimitiveIDIn", BuiltinVariableShader::TEST_PRIMITIVE_ID_IN)); 5885 basicGroup->addChild(new BuiltinVariableRenderTest (m_context, "primitive_id_in_restarted","test gl_PrimitiveIDIn with primitive restart", BuiltinVariableShader::TEST_PRIMITIVE_ID_IN, GeometryShaderRenderTest::FLAG_USE_RESTART_INDEX | GeometryShaderRenderTest::FLAG_USE_INDICES)); 5886 basicGroup->addChild(new BuiltinVariableRenderTest (m_context, "primitive_id", "test gl_PrimitiveID", BuiltinVariableShader::TEST_PRIMITIVE_ID)); 5887 } 5888 5889 // input primitives 5890 { 5891 static const PrimitiveTestSpec inputPrimitives[] = 5892 { 5893 { GL_POINTS, "points", GL_POINTS }, 5894 { GL_LINES, "lines", GL_LINE_STRIP }, 5895 { GL_LINE_LOOP, "line_loop", GL_LINE_STRIP }, 5896 { GL_LINE_STRIP, "line_strip", GL_LINE_STRIP }, 5897 { GL_TRIANGLES, "triangles", GL_TRIANGLE_STRIP }, 5898 { GL_TRIANGLE_STRIP, "triangle_strip", GL_TRIANGLE_STRIP }, 5899 { GL_TRIANGLE_FAN, "triangle_fan", GL_TRIANGLE_STRIP }, 5900 { GL_LINES_ADJACENCY, "lines_adjacency", GL_LINE_STRIP }, 5901 { GL_LINE_STRIP_ADJACENCY, "line_strip_adjacency", GL_LINE_STRIP }, 5902 { GL_TRIANGLES_ADJACENCY, "triangles_adjacency", GL_TRIANGLE_STRIP } 5903 }; 5904 5905 tcu::TestCaseGroup* const basicPrimitiveGroup = new tcu::TestCaseGroup(m_testCtx, "basic_primitive", "Different input and output primitives."); 5906 tcu::TestCaseGroup* const triStripAdjacencyGroup = new tcu::TestCaseGroup(m_testCtx, "triangle_strip_adjacency", "Different triangle_strip_adjacency vertex counts."); 5907 5908 // more basic types 5909 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(inputPrimitives); ++ndx) 5910 basicPrimitiveGroup->addChild(new GeometryExpanderRenderTest(m_context, inputPrimitives[ndx].name, inputPrimitives[ndx].name, inputPrimitives[ndx].primitiveType, inputPrimitives[ndx].outputType)); 5911 5912 // triangle strip adjacency with different vtx counts 5913 for (int vtxCount = 0; vtxCount <= 12; ++vtxCount) 5914 { 5915 const std::string name = "vertex_count_" + de::toString(vtxCount); 5916 const std::string desc = "Vertex count is " + de::toString(vtxCount); 5917 5918 triStripAdjacencyGroup->addChild(new TriangleStripAdjacencyVertexCountTest(m_context, name.c_str(), desc.c_str(), vtxCount)); 5919 } 5920 5921 inputPrimitiveGroup->addChild(basicPrimitiveGroup); 5922 inputPrimitiveGroup->addChild(triStripAdjacencyGroup); 5923 } 5924 5925 // different type conversions 5926 { 5927 static const PrimitiveTestSpec conversionPrimitives[] = 5928 { 5929 { GL_TRIANGLES, "triangles_to_points", GL_POINTS }, 5930 { GL_LINES, "lines_to_points", GL_POINTS }, 5931 { GL_POINTS, "points_to_lines", GL_LINE_STRIP }, 5932 { GL_TRIANGLES, "triangles_to_lines", GL_LINE_STRIP }, 5933 { GL_POINTS, "points_to_triangles", GL_TRIANGLE_STRIP }, 5934 { GL_LINES, "lines_to_triangles", GL_TRIANGLE_STRIP } 5935 }; 5936 5937 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(conversionPrimitives); ++ndx) 5938 conversionPrimitiveGroup->addChild(new GeometryExpanderRenderTest(m_context, conversionPrimitives[ndx].name, conversionPrimitives[ndx].name, conversionPrimitives[ndx].primitiveType, conversionPrimitives[ndx].outputType)); 5939 } 5940 5941 // emit different amounts 5942 { 5943 static const EmitTestSpec emitTests[] = 5944 { 5945 { GL_POINTS, 0, 0, 0, 0, "points" }, 5946 { GL_POINTS, 0, 1, 0, 0, "points" }, 5947 { GL_POINTS, 1, 1, 0, 0, "points" }, 5948 { GL_POINTS, 0, 2, 0, 0, "points" }, 5949 { GL_POINTS, 1, 2, 0, 0, "points" }, 5950 { GL_LINE_STRIP, 0, 0, 0, 0, "line_strip" }, 5951 { GL_LINE_STRIP, 0, 1, 0, 0, "line_strip" }, 5952 { GL_LINE_STRIP, 1, 1, 0, 0, "line_strip" }, 5953 { GL_LINE_STRIP, 2, 1, 0, 0, "line_strip" }, 5954 { GL_LINE_STRIP, 0, 2, 0, 0, "line_strip" }, 5955 { GL_LINE_STRIP, 1, 2, 0, 0, "line_strip" }, 5956 { GL_LINE_STRIP, 2, 2, 0, 0, "line_strip" }, 5957 { GL_LINE_STRIP, 2, 2, 2, 0, "line_strip" }, 5958 { GL_TRIANGLE_STRIP, 0, 0, 0, 0, "triangle_strip" }, 5959 { GL_TRIANGLE_STRIP, 0, 1, 0, 0, "triangle_strip" }, 5960 { GL_TRIANGLE_STRIP, 1, 1, 0, 0, "triangle_strip" }, 5961 { GL_TRIANGLE_STRIP, 2, 1, 0, 0, "triangle_strip" }, 5962 { GL_TRIANGLE_STRIP, 3, 1, 0, 0, "triangle_strip" }, 5963 { GL_TRIANGLE_STRIP, 0, 2, 0, 0, "triangle_strip" }, 5964 { GL_TRIANGLE_STRIP, 1, 2, 0, 0, "triangle_strip" }, 5965 { GL_TRIANGLE_STRIP, 2, 2, 0, 0, "triangle_strip" }, 5966 { GL_TRIANGLE_STRIP, 3, 2, 0, 0, "triangle_strip" }, 5967 { GL_TRIANGLE_STRIP, 3, 2, 3, 0, "triangle_strip" }, 5968 }; 5969 5970 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(emitTests); ++ndx) 5971 { 5972 std::string name = std::string(emitTests[ndx].name) + "_emit_" + de::toString(emitTests[ndx].emitCountA) + "_end_" + de::toString(emitTests[ndx].endCountA); 5973 std::string desc = std::string(emitTests[ndx].name) + " output, emit " + de::toString(emitTests[ndx].emitCountA) + " vertices, call EndPrimitive " + de::toString(emitTests[ndx].endCountA) + " times"; 5974 5975 if (emitTests[ndx].emitCountB) 5976 { 5977 name += "_emit_" + de::toString(emitTests[ndx].emitCountB) + "_end_" + de::toString(emitTests[ndx].endCountB); 5978 desc += ", emit " + de::toString(emitTests[ndx].emitCountB) + " vertices, call EndPrimitive " + de::toString(emitTests[ndx].endCountB) + " times"; 5979 } 5980 5981 emitGroup->addChild(new EmitTest(m_context, name.c_str(), desc.c_str(), emitTests[ndx].emitCountA, emitTests[ndx].endCountA, emitTests[ndx].emitCountB, emitTests[ndx].endCountB, emitTests[ndx].outputType)); 5982 } 5983 } 5984 5985 // varying 5986 { 5987 struct VaryingTestSpec 5988 { 5989 int vertexOutputs; 5990 int geometryOutputs; 5991 const char* name; 5992 const char* desc; 5993 }; 5994 5995 static const VaryingTestSpec varyingTests[] = 5996 { 5997 { -1, 1, "vertex_no_op_geometry_out_1", "vertex_no_op_geometry_out_1" }, 5998 { 0, 1, "vertex_out_0_geometry_out_1", "vertex_out_0_geometry_out_1" }, 5999 { 0, 2, "vertex_out_0_geometry_out_2", "vertex_out_0_geometry_out_2" }, 6000 { 1, 0, "vertex_out_1_geometry_out_0", "vertex_out_1_geometry_out_0" }, 6001 { 1, 2, "vertex_out_1_geometry_out_2", "vertex_out_1_geometry_out_2" }, 6002 }; 6003 6004 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(varyingTests); ++ndx) 6005 varyingGroup->addChild(new VaryingTest(m_context, varyingTests[ndx].name, varyingTests[ndx].desc, varyingTests[ndx].vertexOutputs, varyingTests[ndx].geometryOutputs)); 6006 } 6007 6008 // layered 6009 { 6010 static const struct TestType 6011 { 6012 LayeredRenderCase::TestType test; 6013 const char* testPrefix; 6014 const char* descPrefix; 6015 } tests[] = 6016 { 6017 { LayeredRenderCase::TEST_DEFAULT_LAYER, "render_with_default_layer_", "Render to all layers of " }, 6018 { LayeredRenderCase::TEST_SINGLE_LAYER, "render_to_one_", "Render to one layer of " }, 6019 { LayeredRenderCase::TEST_ALL_LAYERS, "render_to_all_", "Render to all layers of " }, 6020 { LayeredRenderCase::TEST_DIFFERENT_LAYERS, "render_different_to_", "Render different data to different layers" }, 6021 { LayeredRenderCase::TEST_LAYER_ID, "fragment_layer_", "Read gl_Layer in fragment shader" }, 6022 { LayeredRenderCase::TEST_LAYER_PROVOKING_VERTEX, "layer_provoking_vertex_", "Verify LAYER_PROVOKING_VERTEX" }, 6023 }; 6024 6025 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx) 6026 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(layerTargets); ++targetNdx) 6027 { 6028 const std::string name = std::string(tests[testNdx].testPrefix) + layerTargets[targetNdx].name; 6029 const std::string desc = std::string(tests[testNdx].descPrefix) + layerTargets[targetNdx].desc; 6030 6031 layeredGroup->addChild(new LayeredRenderCase(m_context, name.c_str(), desc.c_str(), layerTargets[targetNdx].target, tests[testNdx].test)); 6032 } 6033 } 6034 6035 // instanced 6036 { 6037 static const struct InvocationCase 6038 { 6039 const char* name; 6040 int numInvocations; 6041 } invocationCases[] = 6042 { 6043 { "1", 1 }, 6044 { "2", 2 }, 6045 { "8", 8 }, 6046 { "32", 32 }, 6047 { "max", -1 }, 6048 }; 6049 static const int numDrawInstances[] = { 2, 4, 8 }; 6050 static const int numDrawInvocations[] = { 2, 8 }; 6051 6052 // same amount of content to all invocations 6053 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(invocationCases); ++ndx) 6054 instancedGroup->addChild(new GeometryInvocationCase(m_context, 6055 (std::string("geometry_") + invocationCases[ndx].name + "_invocations").c_str(), 6056 (std::string("Geometry shader with ") + invocationCases[ndx].name + " invocation(s)").c_str(), 6057 invocationCases[ndx].numInvocations, 6058 GeometryInvocationCase::CASE_FIXED_OUTPUT_COUNTS)); 6059 6060 // different amount of content to each invocation 6061 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(invocationCases); ++ndx) 6062 if (invocationCases[ndx].numInvocations != 1) 6063 instancedGroup->addChild(new GeometryInvocationCase(m_context, 6064 (std::string("geometry_output_different_") + invocationCases[ndx].name + "_invocations").c_str(), 6065 "Geometry shader invocation(s) with different emit counts", 6066 invocationCases[ndx].numInvocations, 6067 GeometryInvocationCase::CASE_DIFFERENT_OUTPUT_COUNTS)); 6068 6069 // invocation per layer 6070 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(layerTargets); ++targetNdx) 6071 { 6072 const std::string name = std::string("invocation_per_layer_") + layerTargets[targetNdx].name; 6073 const std::string desc = std::string("Render to multiple layers with multiple invocations, one invocation per layer, target ") + layerTargets[targetNdx].desc; 6074 6075 instancedGroup->addChild(new LayeredRenderCase(m_context, name.c_str(), desc.c_str(), layerTargets[targetNdx].target, LayeredRenderCase::TEST_INVOCATION_PER_LAYER)); 6076 } 6077 6078 // multiple layers per invocation 6079 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(layerTargets); ++targetNdx) 6080 { 6081 const std::string name = std::string("multiple_layers_per_invocation_") + layerTargets[targetNdx].name; 6082 const std::string desc = std::string("Render to multiple layers with multiple invocations, multiple layers per invocation, target ") + layerTargets[targetNdx].desc; 6083 6084 instancedGroup->addChild(new LayeredRenderCase(m_context, name.c_str(), desc.c_str(), layerTargets[targetNdx].target, LayeredRenderCase::TEST_MULTIPLE_LAYERS_PER_INVOCATION)); 6085 } 6086 6087 // different invocation output counts depending on {uniform, attrib, texture} 6088 instancedGroup->addChild(new VaryingOutputCountCase(m_context, "invocation_output_vary_by_attribute", "Output varying number of vertices", VaryingOutputCountShader::READ_ATTRIBUTE, VaryingOutputCountCase::MODE_WITH_INSTANCING)); 6089 instancedGroup->addChild(new VaryingOutputCountCase(m_context, "invocation_output_vary_by_uniform", "Output varying number of vertices", VaryingOutputCountShader::READ_UNIFORM, VaryingOutputCountCase::MODE_WITH_INSTANCING)); 6090 instancedGroup->addChild(new VaryingOutputCountCase(m_context, "invocation_output_vary_by_texture", "Output varying number of vertices", VaryingOutputCountShader::READ_TEXTURE, VaryingOutputCountCase::MODE_WITH_INSTANCING)); 6091 6092 // with drawInstanced 6093 for (int instanceNdx = 0; instanceNdx < DE_LENGTH_OF_ARRAY(numDrawInstances); ++instanceNdx) 6094 for (int invocationNdx = 0; invocationNdx < DE_LENGTH_OF_ARRAY(numDrawInvocations); ++invocationNdx) 6095 { 6096 const std::string name = std::string("draw_") + de::toString(numDrawInstances[instanceNdx]) + "_instances_geometry_" + de::toString(numDrawInvocations[invocationNdx]) + "_invocations"; 6097 const std::string desc = std::string("Draw ") + de::toString(numDrawInstances[instanceNdx]) + " instances, with " + de::toString(numDrawInvocations[invocationNdx]) + " geometry shader invocations."; 6098 6099 instancedGroup->addChild(new DrawInstancedGeometryInstancedCase(m_context, name.c_str(), desc.c_str(), numDrawInstances[instanceNdx], numDrawInvocations[invocationNdx])); 6100 } 6101 } 6102 6103 // negative (wrong types) 6104 { 6105 struct PrimitiveToInputTypeConversion 6106 { 6107 GLenum inputType; 6108 GLenum primitiveType; 6109 }; 6110 6111 static const PrimitiveToInputTypeConversion legalConversions[] = 6112 { 6113 { GL_POINTS, GL_POINTS }, 6114 { GL_LINES, GL_LINES }, 6115 { GL_LINES, GL_LINE_LOOP }, 6116 { GL_LINES, GL_LINE_STRIP }, 6117 { GL_LINES_ADJACENCY, GL_LINES_ADJACENCY }, 6118 { GL_LINES_ADJACENCY, GL_LINE_STRIP_ADJACENCY }, 6119 { GL_TRIANGLES, GL_TRIANGLES }, 6120 { GL_TRIANGLES, GL_TRIANGLE_STRIP }, 6121 { GL_TRIANGLES, GL_TRIANGLE_FAN }, 6122 { GL_TRIANGLES_ADJACENCY, GL_TRIANGLES_ADJACENCY }, 6123 { GL_TRIANGLES_ADJACENCY, GL_TRIANGLE_STRIP_ADJACENCY }, 6124 }; 6125 6126 static const GLenum inputTypes[] = 6127 { 6128 GL_POINTS, 6129 GL_LINES, 6130 GL_LINES_ADJACENCY, 6131 GL_TRIANGLES, 6132 GL_TRIANGLES_ADJACENCY 6133 }; 6134 6135 static const GLenum primitiveTypes[] = 6136 { 6137 GL_POINTS, 6138 GL_LINES, 6139 GL_LINE_LOOP, 6140 GL_LINE_STRIP, 6141 GL_LINES_ADJACENCY, 6142 GL_LINE_STRIP_ADJACENCY, 6143 GL_TRIANGLES, 6144 GL_TRIANGLE_STRIP, 6145 GL_TRIANGLE_FAN, 6146 GL_TRIANGLES_ADJACENCY, 6147 GL_TRIANGLE_STRIP_ADJACENCY 6148 }; 6149 6150 for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); ++inputTypeNdx) 6151 for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveTypeNdx) 6152 { 6153 const GLenum inputType = inputTypes[inputTypeNdx]; 6154 const GLenum primitiveType = primitiveTypes[primitiveTypeNdx]; 6155 const std::string name = std::string("type_") + inputTypeToGLString(sglr::rr_util::mapGLGeometryShaderInputType(inputType)) + "_primitive_" + primitiveTypeToString(primitiveType); 6156 const std::string desc = std::string("Shader input type ") + inputTypeToGLString(sglr::rr_util::mapGLGeometryShaderInputType(inputType)) + ", draw primitive type " + primitiveTypeToString(primitiveType); 6157 6158 bool isLegal = false; 6159 6160 for (int legalNdx = 0; legalNdx < DE_LENGTH_OF_ARRAY(legalConversions); ++legalNdx) 6161 if (legalConversions[legalNdx].inputType == inputType && legalConversions[legalNdx].primitiveType == primitiveType) 6162 isLegal = true; 6163 6164 // only illegal 6165 if (!isLegal) 6166 negativeGroup->addChild(new NegativeDrawCase(m_context, name.c_str(), desc.c_str(), inputType, primitiveType)); 6167 } 6168 } 6169 6170 // vertex transform feedback 6171 { 6172 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_line_loop", "Capture line loop lines", VertexFeedbackCase::METHOD_DRAW_ARRAYS, VertexFeedbackCase::PRIMITIVE_LINE_LOOP)); 6173 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_line_strip", "Capture line strip lines", VertexFeedbackCase::METHOD_DRAW_ARRAYS, VertexFeedbackCase::PRIMITIVE_LINE_STRIP)); 6174 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_triangle_strip", "Capture triangle strip triangles", VertexFeedbackCase::METHOD_DRAW_ARRAYS, VertexFeedbackCase::PRIMITIVE_TRIANGLE_STRIP)); 6175 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_triangle_fan", "Capture triangle fan triangles", VertexFeedbackCase::METHOD_DRAW_ARRAYS, VertexFeedbackCase::PRIMITIVE_TRIANGLE_FAN)); 6176 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_draw_arrays", "Capture primitives generated with drawArrays", VertexFeedbackCase::METHOD_DRAW_ARRAYS, VertexFeedbackCase::PRIMITIVE_POINTS)); 6177 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_draw_arrays_instanced", "Capture primitives generated with drawArraysInstanced", VertexFeedbackCase::METHOD_DRAW_ARRAYS_INSTANCED, VertexFeedbackCase::PRIMITIVE_POINTS)); 6178 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_draw_arrays_indirect", "Capture primitives generated with drawArraysIndirect", VertexFeedbackCase::METHOD_DRAW_ARRAYS_INDIRECT, VertexFeedbackCase::PRIMITIVE_POINTS)); 6179 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_draw_elements", "Capture primitives generated with drawElements", VertexFeedbackCase::METHOD_DRAW_ELEMENTS, VertexFeedbackCase::PRIMITIVE_POINTS)); 6180 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_draw_elements_instanced", "Capture primitives generated with drawElementsInstanced", VertexFeedbackCase::METHOD_DRAW_ELEMENTS_INSTANCED, VertexFeedbackCase::PRIMITIVE_POINTS)); 6181 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_draw_elements_indirect", "Capture primitives generated with drawElementsIndirect", VertexFeedbackCase::METHOD_DRAW_ELEMENTS_INDIRECT, VertexFeedbackCase::PRIMITIVE_POINTS)); 6182 6183 feedbackGroup->addChild(new VertexFeedbackOverflowCase(m_context, "capture_vertex_draw_arrays_overflow_single_buffer", "Capture triangles to too small a buffer", VertexFeedbackOverflowCase::METHOD_DRAW_ARRAYS)); 6184 feedbackGroup->addChild(new VertexFeedbackOverflowCase(m_context, "capture_vertex_draw_elements_overflow_single_buffer", "Capture triangles to too small a buffer", VertexFeedbackOverflowCase::METHOD_DRAW_ELEMENTS)); 6185 } 6186 } 6187 6188 } // Functional 6189 } // gles31 6190 } // deqp 6191