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\n" 3882 "#extension GL_EXT_geometry_shader : require\n" 3883 "layout (triangles) in;\n" 3884 "layout (points, max_vertices = 3) out;\n" 3885 + std::string(s_geometryBody); 3886 3887 3888 glu::Shader vertexShader (m_context.getRenderContext(), glu::SHADERTYPE_VERTEX); 3889 glu::Shader fragmentShader (m_context.getRenderContext(), glu::SHADERTYPE_FRAGMENT); 3890 glu::Shader geometryShader (m_context.getRenderContext(), glu::SHADERTYPE_GEOMETRY); 3891 glu::Program program (m_context.getRenderContext()); 3892 3893 const char* const geometrySourceArray[1] = { geometrySource.c_str() }; 3894 3895 vertexShader.setSources(1, &s_vertexSource, DE_NULL); 3896 fragmentShader.setSources(1, &s_fragmentSource, DE_NULL); 3897 geometryShader.setSources(1, geometrySourceArray, DE_NULL); 3898 3899 vertexShader.compile(); 3900 fragmentShader.compile(); 3901 geometryShader.compile(); 3902 3903 if (!vertexShader.getCompileStatus() || 3904 !fragmentShader.getCompileStatus() || 3905 !geometryShader.getCompileStatus()) 3906 throw tcu::TestError("Failed to compile shader"); 3907 3908 program.attachShader(vertexShader.getShader()); 3909 program.attachShader(fragmentShader.getShader()); 3910 program.attachShader(geometryShader.getShader()); 3911 3912 m_testCtx.getLog() << tcu::TestLog::Message << "Creating a program with geometry shader, but not linking it" << tcu::TestLog::EndMessage; 3913 3914 expectQueryError(program.getProgram()); 3915 } 3916 3917 return STOP; 3918 } 3919 3920 void GeometryProgramQueryCase::expectProgramValue (deUint32 program, int value) 3921 { 3922 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3923 gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint> state; 3924 3925 gl.getProgramiv(program, m_target, &state); 3926 GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv"); 3927 3928 m_testCtx.getLog() << tcu::TestLog::Message << glu::getProgramParamStr(m_target) << " = " << state << tcu::TestLog::EndMessage; 3929 3930 if (state != value) 3931 { 3932 m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << value << ", got " << state << tcu::TestLog::EndMessage; 3933 3934 // don't overwrite error 3935 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) 3936 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value"); 3937 } 3938 } 3939 3940 void GeometryProgramQueryCase::expectQueryError (deUint32 program) 3941 { 3942 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 3943 glw::GLint dummy; 3944 glw::GLenum errorCode; 3945 3946 m_testCtx.getLog() << tcu::TestLog::Message << "Querying " << glu::getProgramParamStr(m_target) << ", expecting INVALID_OPERATION" << tcu::TestLog::EndMessage; 3947 gl.getProgramiv(program, m_target, &dummy); 3948 3949 errorCode = gl.getError(); 3950 3951 if (errorCode != GL_INVALID_OPERATION) 3952 { 3953 m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected INVALID_OPERATION, got " << glu::getErrorStr(errorCode) << tcu::TestLog::EndMessage; 3954 3955 // don't overwrite error 3956 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) 3957 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected error code"); 3958 } 3959 } 3960 3961 class GeometryShaderInvocationsQueryCase : public GeometryProgramQueryCase 3962 { 3963 public: 3964 GeometryShaderInvocationsQueryCase(Context& context, const char* name, const char* description); 3965 }; 3966 3967 GeometryShaderInvocationsQueryCase::GeometryShaderInvocationsQueryCase(Context& context, const char* name, const char* description) 3968 : GeometryProgramQueryCase(context, name, description, GL_GEOMETRY_SHADER_INVOCATIONS) 3969 { 3970 // 2 normal cases 3971 m_cases.resize(2); 3972 3973 m_cases[0].description = "Default value"; 3974 m_cases[0].header = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (triangles) in;\nlayout (points, max_vertices = 3) out;\n"; 3975 m_cases[0].value = 1; 3976 3977 m_cases[1].description = "Value declared"; 3978 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"; 3979 m_cases[1].value = 2; 3980 } 3981 3982 class GeometryShaderVerticesQueryCase : public GeometryProgramQueryCase 3983 { 3984 public: 3985 GeometryShaderVerticesQueryCase(Context& context, const char* name, const char* description); 3986 }; 3987 3988 GeometryShaderVerticesQueryCase::GeometryShaderVerticesQueryCase(Context& context, const char* name, const char* description) 3989 : GeometryProgramQueryCase(context, name, description, GL_GEOMETRY_LINKED_VERTICES_OUT_EXT) 3990 { 3991 m_cases.resize(1); 3992 3993 m_cases[0].description = "max_vertices = 1"; 3994 m_cases[0].header = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (triangles) in;\nlayout (points, max_vertices = 1) out;\n"; 3995 m_cases[0].value = 1; 3996 } 3997 3998 class GeometryShaderInputQueryCase : public GeometryProgramQueryCase 3999 { 4000 public: 4001 GeometryShaderInputQueryCase(Context& context, const char* name, const char* description); 4002 }; 4003 4004 GeometryShaderInputQueryCase::GeometryShaderInputQueryCase(Context& context, const char* name, const char* description) 4005 : GeometryProgramQueryCase(context, name, description, GL_GEOMETRY_LINKED_INPUT_TYPE_EXT) 4006 { 4007 m_cases.resize(3); 4008 4009 m_cases[0].description = "Triangles"; 4010 m_cases[0].header = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (triangles) in;\nlayout (points, max_vertices = 3) out;\n"; 4011 m_cases[0].value = GL_TRIANGLES; 4012 4013 m_cases[1].description = "Lines"; 4014 m_cases[1].header = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (lines) in;\nlayout (points, max_vertices = 3) out;\n"; 4015 m_cases[1].value = GL_LINES; 4016 4017 m_cases[2].description = "Points"; 4018 m_cases[2].header = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (points) in;\nlayout (points, max_vertices = 3) out;\n"; 4019 m_cases[2].value = GL_POINTS; 4020 } 4021 4022 class GeometryShaderOutputQueryCase : public GeometryProgramQueryCase 4023 { 4024 public: 4025 GeometryShaderOutputQueryCase(Context& context, const char* name, const char* description); 4026 }; 4027 4028 GeometryShaderOutputQueryCase::GeometryShaderOutputQueryCase(Context& context, const char* name, const char* description) 4029 : GeometryProgramQueryCase(context, name, description, GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT) 4030 { 4031 m_cases.resize(3); 4032 4033 m_cases[0].description = "Triangle strip"; 4034 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"; 4035 m_cases[0].value = GL_TRIANGLE_STRIP; 4036 4037 m_cases[1].description = "Lines"; 4038 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"; 4039 m_cases[1].value = GL_LINE_STRIP; 4040 4041 m_cases[2].description = "Points"; 4042 m_cases[2].header = "#version 310 es\n#extension GL_EXT_geometry_shader : require\nlayout (triangles) in;\nlayout (points, max_vertices = 3) out;\n"; 4043 m_cases[2].value = GL_POINTS; 4044 } 4045 4046 class ImplementationLimitCase : public TestCase 4047 { 4048 public: 4049 ImplementationLimitCase (Context& context, const char* name, const char* description, glw::GLenum target, int minValue); 4050 4051 void init (void); 4052 IterateResult iterate (void); 4053 4054 const glw::GLenum m_target; 4055 const int m_minValue; 4056 }; 4057 4058 ImplementationLimitCase::ImplementationLimitCase (Context& context, const char* name, const char* description, glw::GLenum target, int minValue) 4059 : TestCase (context, name, description) 4060 , m_target (target) 4061 , m_minValue (minValue) 4062 { 4063 } 4064 4065 void ImplementationLimitCase::init (void) 4066 { 4067 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 4068 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension"); 4069 } 4070 4071 ImplementationLimitCase::IterateResult ImplementationLimitCase::iterate (void) 4072 { 4073 gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint> state; 4074 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 4075 4076 gl.enableLogging(true); 4077 gl.glGetIntegerv(m_target, &state); 4078 GLU_EXPECT_NO_ERROR(gl.glGetError(), "getIntegerv()"); 4079 4080 m_testCtx.getLog() << tcu::TestLog::Message << glu::getGettableStateStr(m_target) << " = " << state << tcu::TestLog::EndMessage; 4081 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4082 4083 if (state.verifyValidity(m_testCtx) && state < m_minValue) 4084 { 4085 m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Minimum value = " << m_minValue << ", got " << state << tcu::TestLog::EndMessage; 4086 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got a value less than minimum value"); 4087 } 4088 4089 return STOP; 4090 } 4091 4092 class LayerProvokingVertexQueryCase : public TestCase 4093 { 4094 public: 4095 LayerProvokingVertexQueryCase (Context& context, const char* name, const char* description); 4096 4097 void init (void); 4098 IterateResult iterate (void); 4099 }; 4100 4101 LayerProvokingVertexQueryCase::LayerProvokingVertexQueryCase(Context& context, const char* name, const char* description) 4102 : TestCase(context, name, description) 4103 { 4104 } 4105 4106 void LayerProvokingVertexQueryCase::init (void) 4107 { 4108 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 4109 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension"); 4110 } 4111 4112 LayerProvokingVertexQueryCase::IterateResult LayerProvokingVertexQueryCase::iterate (void) 4113 { 4114 gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint> state; 4115 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 4116 4117 gl.enableLogging(true); 4118 gl.glGetIntegerv(GL_LAYER_PROVOKING_VERTEX, &state); 4119 GLU_EXPECT_NO_ERROR(gl.glGetError(), "getIntegerv(LAYER_PROVOKING_VERTEX)"); 4120 4121 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4122 4123 if (state.verifyValidity(m_testCtx)) 4124 { 4125 m_testCtx.getLog() << tcu::TestLog::Message << "LAYER_PROVOKING_VERTEX = " << glu::getProvokingVertexStr(state) << tcu::TestLog::EndMessage; 4126 4127 if (state != GL_FIRST_VERTEX_CONVENTION && 4128 state != GL_LAST_VERTEX_CONVENTION && 4129 state != GL_UNDEFINED_VERTEX) 4130 { 4131 m_testCtx.getLog() 4132 << tcu::TestLog::Message 4133 << "getInteger(GL_LAYER_PROVOKING_VERTEX) returned illegal value. Got " 4134 << state << "\n" 4135 << "Expected any of {FIRST_VERTEX_CONVENTION, LAST_VERTEX_CONVENTION, UNDEFINED_VERTEX}." 4136 << tcu::TestLog::EndMessage; 4137 4138 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected provoking vertex value"); 4139 } 4140 } 4141 4142 return STOP; 4143 } 4144 4145 class GeometryInvocationCase : public GeometryShaderRenderTest 4146 { 4147 public: 4148 enum OutputCase 4149 { 4150 CASE_FIXED_OUTPUT_COUNTS = 0, 4151 CASE_DIFFERENT_OUTPUT_COUNTS, 4152 4153 CASE_LAST 4154 }; 4155 4156 GeometryInvocationCase (Context& context, const char* name, const char* description, int numInvocations, OutputCase testCase); 4157 ~GeometryInvocationCase (void); 4158 4159 void init (void); 4160 void deinit (void); 4161 4162 private: 4163 sglr::ShaderProgram& getProgram (void); 4164 void genVertexAttribData (void); 4165 4166 static InvocationCountShader::OutputCase mapToShaderCaseType (OutputCase testCase); 4167 4168 const OutputCase m_testCase; 4169 int m_numInvocations; 4170 InvocationCountShader* m_program; 4171 }; 4172 4173 GeometryInvocationCase::GeometryInvocationCase (Context& context, const char* name, const char* description, int numInvocations, OutputCase testCase) 4174 : GeometryShaderRenderTest (context, name, description, GL_POINTS, GL_TRIANGLE_STRIP, "a_color") 4175 , m_testCase (testCase) 4176 , m_numInvocations (numInvocations) 4177 , m_program (DE_NULL) 4178 { 4179 DE_ASSERT(m_testCase < CASE_LAST); 4180 } 4181 4182 GeometryInvocationCase::~GeometryInvocationCase (void) 4183 { 4184 deinit(); 4185 } 4186 4187 void GeometryInvocationCase::init (void) 4188 { 4189 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4190 int maxGeometryShaderInvocations = 0; 4191 int maxComponents = 0; 4192 4193 // requirements 4194 4195 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 4196 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension"); 4197 4198 gl.getIntegerv(GL_MAX_GEOMETRY_SHADER_INVOCATIONS, &maxGeometryShaderInvocations); 4199 GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv(GL_MAX_GEOMETRY_SHADER_INVOCATIONS)"); 4200 4201 gl.getIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &maxComponents); 4202 GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS)"); 4203 4204 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_SHADER_INVOCATIONS = " << maxGeometryShaderInvocations << tcu::TestLog::EndMessage; 4205 4206 // set target num invocations 4207 4208 if (m_numInvocations == -1) 4209 m_numInvocations = maxGeometryShaderInvocations; 4210 else if (maxGeometryShaderInvocations < m_numInvocations) 4211 throw tcu::NotSupportedError("Test requires larger GL_MAX_GEOMETRY_SHADER_INVOCATIONS"); 4212 4213 if (m_testCase == CASE_DIFFERENT_OUTPUT_COUNTS) 4214 { 4215 const int maxEmitCount = m_numInvocations + 2; 4216 const int numComponents = 8; // pos + color 4217 if (maxEmitCount * numComponents > maxComponents) 4218 throw tcu::NotSupportedError("Test requires larger GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS"); 4219 } 4220 4221 // Log what the test tries to do 4222 4223 if (m_testCase == CASE_FIXED_OUTPUT_COUNTS) 4224 { 4225 m_testCtx.getLog() 4226 << tcu::TestLog::Message 4227 << "Rendering triangles in a partial circle formation with a geometry shader. Each triangle is generated by a separate invocation.\n" 4228 << "Drawing 2 points, each generating " << m_numInvocations << " triangles." 4229 << tcu::TestLog::EndMessage; 4230 } 4231 else if (m_testCase == CASE_DIFFERENT_OUTPUT_COUNTS) 4232 { 4233 m_testCtx.getLog() 4234 << tcu::TestLog::Message 4235 << "Rendering n-gons in a partial circle formation with a geometry shader. Each n-gon is generated by a separate invocation.\n" 4236 << "Drawing 2 points, each generating " << m_numInvocations << " n-gons." 4237 << tcu::TestLog::EndMessage; 4238 } 4239 else 4240 DE_ASSERT(false); 4241 4242 // resources 4243 4244 m_program = new InvocationCountShader(m_numInvocations, mapToShaderCaseType(m_testCase)); 4245 4246 GeometryShaderRenderTest::init(); 4247 } 4248 4249 void GeometryInvocationCase::deinit (void) 4250 { 4251 if (m_program) 4252 { 4253 delete m_program; 4254 m_program = DE_NULL; 4255 } 4256 4257 GeometryShaderRenderTest::deinit(); 4258 } 4259 4260 sglr::ShaderProgram& GeometryInvocationCase::getProgram (void) 4261 { 4262 return *m_program; 4263 } 4264 4265 void GeometryInvocationCase::genVertexAttribData (void) 4266 { 4267 m_vertexPosData.resize(2); 4268 m_vertexPosData[0] = tcu::Vec4(0.0f,-0.3f, 0.0f, 1.0f); 4269 m_vertexPosData[1] = tcu::Vec4(0.2f, 0.3f, 0.0f, 1.0f); 4270 4271 m_vertexAttrData.resize(2); 4272 m_vertexAttrData[0] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f); 4273 m_vertexAttrData[1] = tcu::Vec4(0.8f, 0.8f, 0.8f, 1.0f); 4274 m_numDrawVertices = 2; 4275 } 4276 4277 InvocationCountShader::OutputCase GeometryInvocationCase::mapToShaderCaseType (OutputCase testCase) 4278 { 4279 switch (testCase) 4280 { 4281 case CASE_FIXED_OUTPUT_COUNTS: return InvocationCountShader::CASE_FIXED_OUTPUT_COUNTS; 4282 case CASE_DIFFERENT_OUTPUT_COUNTS: return InvocationCountShader::CASE_DIFFERENT_OUTPUT_COUNTS; 4283 default: 4284 DE_ASSERT(false); 4285 return InvocationCountShader::CASE_LAST; 4286 } 4287 } 4288 4289 class DrawInstancedGeometryInstancedCase : public GeometryShaderRenderTest 4290 { 4291 public: 4292 DrawInstancedGeometryInstancedCase (Context& context, const char* name, const char* description, int numInstances, int numInvocations); 4293 ~DrawInstancedGeometryInstancedCase (void); 4294 4295 private: 4296 void init (void); 4297 sglr::ShaderProgram& getProgram (void); 4298 void genVertexAttribData (void); 4299 4300 const int m_numInstances; 4301 const int m_numInvocations; 4302 InstancedExpansionShader m_program; 4303 }; 4304 4305 DrawInstancedGeometryInstancedCase::DrawInstancedGeometryInstancedCase (Context& context, const char* name, const char* description, int numInstances, int numInvocations) 4306 : GeometryShaderRenderTest (context, name, description, GL_POINTS, GL_TRIANGLE_STRIP, "a_offset", FLAG_DRAW_INSTANCED) 4307 , m_numInstances (numInstances) 4308 , m_numInvocations (numInvocations) 4309 , m_program (numInvocations) 4310 { 4311 } 4312 4313 DrawInstancedGeometryInstancedCase::~DrawInstancedGeometryInstancedCase (void) 4314 { 4315 } 4316 4317 void DrawInstancedGeometryInstancedCase::init (void) 4318 { 4319 m_testCtx.getLog() 4320 << tcu::TestLog::Message 4321 << "Rendering a single point with " << m_numInstances << " instances. " 4322 << "Each geometry shader is invoked " << m_numInvocations << " times for each primitive. " 4323 << tcu::TestLog::EndMessage; 4324 4325 GeometryShaderRenderTest::init(); 4326 } 4327 4328 sglr::ShaderProgram& DrawInstancedGeometryInstancedCase::getProgram (void) 4329 { 4330 return m_program; 4331 } 4332 4333 void DrawInstancedGeometryInstancedCase::genVertexAttribData (void) 4334 { 4335 m_numDrawVertices = 1; 4336 m_numDrawInstances = m_numInstances; 4337 m_vertexAttrDivisor = 1; 4338 4339 m_vertexPosData.resize(1); 4340 m_vertexAttrData.resize(8); 4341 4342 m_vertexPosData[0] = tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f); 4343 4344 m_vertexAttrData[0] = tcu::Vec4( 0.5f, 0.0f, 0.0f, 0.0f); 4345 m_vertexAttrData[1] = tcu::Vec4( 0.0f, 0.5f, 0.0f, 0.0f); 4346 m_vertexAttrData[2] = tcu::Vec4(-0.7f, -0.1f, 0.0f, 0.0f); 4347 m_vertexAttrData[3] = tcu::Vec4(-0.1f, -0.7f, 0.0f, 0.0f); 4348 m_vertexAttrData[4] = tcu::Vec4(-0.8f, -0.7f, 0.0f, 0.0f); 4349 m_vertexAttrData[5] = tcu::Vec4(-0.9f, 0.6f, 0.0f, 0.0f); 4350 m_vertexAttrData[6] = tcu::Vec4(-0.8f, 0.3f, 0.0f, 0.0f); 4351 m_vertexAttrData[7] = tcu::Vec4(-0.1f, 0.1f, 0.0f, 0.0f); 4352 4353 DE_ASSERT(m_numInstances <= (int)m_vertexAttrData.size()); 4354 } 4355 4356 class GeometryProgramLimitCase : public TestCase 4357 { 4358 public: 4359 GeometryProgramLimitCase (Context& context, const char* name, const char* description, glw::GLenum apiName, const std::string& glslName, int limit); 4360 4361 private: 4362 void init (void); 4363 IterateResult iterate (void); 4364 4365 const glw::GLenum m_apiName; 4366 const std::string m_glslName; 4367 const int m_limit; 4368 }; 4369 4370 GeometryProgramLimitCase::GeometryProgramLimitCase (Context& context, const char* name, const char* description, glw::GLenum apiName, const std::string& glslName, int limit) 4371 : TestCase (context, name, description) 4372 , m_apiName (apiName) 4373 , m_glslName (glslName) 4374 , m_limit (limit) 4375 { 4376 } 4377 4378 void GeometryProgramLimitCase::init (void) 4379 { 4380 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 4381 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension"); 4382 } 4383 4384 GeometryProgramLimitCase::IterateResult GeometryProgramLimitCase::iterate (void) 4385 { 4386 int limit; 4387 4388 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4389 4390 // query limit 4391 { 4392 gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint> state; 4393 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 4394 4395 gl.enableLogging(true); 4396 gl.glGetIntegerv(m_apiName, &state); 4397 GLU_EXPECT_NO_ERROR(gl.glGetError(), "getIntegerv()"); 4398 4399 m_testCtx.getLog() << tcu::TestLog::Message << glu::getGettableStateStr(m_apiName) << " = " << state << tcu::TestLog::EndMessage; 4400 4401 if (!state.verifyValidity(m_testCtx)) 4402 return STOP; 4403 4404 if (state < m_limit) 4405 { 4406 m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Minimum value = " << m_limit << ", got " << state << tcu::TestLog::EndMessage; 4407 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got a value less than minimum value"); 4408 return STOP; 4409 } 4410 4411 limit = state; 4412 } 4413 4414 // verify limit is the same in GLSL 4415 { 4416 static const char* const vertexSource = "#version 310 es\n" 4417 "void main ()\n" 4418 "{\n" 4419 " gl_Position = vec4(0.0, 0.0, 0.0, 0.0);\n" 4420 "}\n"; 4421 static const char* const fragmentSource = "#version 310 es\n" 4422 "layout(location = 0) out mediump vec4 fragColor;\n" 4423 "void main ()\n" 4424 "{\n" 4425 " fragColor = vec4(0.0, 0.0, 0.0, 0.0);\n" 4426 "}\n"; 4427 const std::string geometrySource = "#version 310 es\n" 4428 "#extension GL_EXT_geometry_shader : require\n" 4429 "layout(points) in;\n" 4430 "layout(points, max_vertices = 1) out;\n" 4431 "void main ()\n" 4432 "{\n" 4433 " // Building the shader will fail if the constant value is not the expected\n" 4434 " const mediump int cArraySize = (gl_" + m_glslName + " == " + de::toString(limit) + ") ? (1) : (-1);\n" 4435 " float[cArraySize] fArray;\n" 4436 " fArray[0] = 0.0f;\n" 4437 " gl_Position = vec4(0.0, 0.0, 0.0, fArray[0]);\n" 4438 " EmitVertex();\n" 4439 "}\n"; 4440 4441 const de::UniquePtr<glu::ShaderProgram> program(new glu::ShaderProgram(m_context.getRenderContext(), 4442 glu::ProgramSources() 4443 << glu::VertexSource(vertexSource) 4444 << glu::FragmentSource(fragmentSource) 4445 << glu::GeometrySource(geometrySource))); 4446 4447 m_testCtx.getLog() << tcu::TestLog::Message << "Building a test shader to verify GLSL constant " << m_glslName << " value." << tcu::TestLog::EndMessage; 4448 m_testCtx.getLog() << *program; 4449 4450 if (!program->isOk()) 4451 { 4452 // compile failed, assume static assert failed 4453 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Shader build failed"); 4454 return STOP; 4455 } 4456 4457 m_testCtx.getLog() << tcu::TestLog::Message << "Build ok" << tcu::TestLog::EndMessage; 4458 } 4459 4460 return STOP; 4461 } 4462 4463 class PrimitivesGeneratedQueryCase : public TestCase 4464 { 4465 public: 4466 enum QueryTest 4467 { 4468 TEST_NO_GEOMETRY = 0, 4469 TEST_NO_AMPLIFICATION, 4470 TEST_AMPLIFICATION, 4471 TEST_PARTIAL_PRIMITIVES, 4472 TEST_INSTANCED, 4473 4474 TEST_LAST 4475 }; 4476 4477 PrimitivesGeneratedQueryCase (Context& context, const char* name, const char* description, QueryTest test); 4478 ~PrimitivesGeneratedQueryCase (void); 4479 4480 private: 4481 void init (void); 4482 void deinit (void); 4483 IterateResult iterate (void); 4484 4485 glu::ShaderProgram* genProgram (void); 4486 4487 const QueryTest m_test; 4488 glu::ShaderProgram* m_program; 4489 }; 4490 4491 PrimitivesGeneratedQueryCase::PrimitivesGeneratedQueryCase (Context& context, const char* name, const char* description, QueryTest test) 4492 : TestCase (context, name, description) 4493 , m_test (test) 4494 , m_program (DE_NULL) 4495 { 4496 DE_ASSERT(m_test < TEST_LAST); 4497 } 4498 4499 PrimitivesGeneratedQueryCase::~PrimitivesGeneratedQueryCase (void) 4500 { 4501 deinit(); 4502 } 4503 4504 void PrimitivesGeneratedQueryCase::init (void) 4505 { 4506 // requirements 4507 4508 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 4509 throw tcu::NotSupportedError("Geometry shader tests require GL_EXT_geometry_shader extension"); 4510 4511 // log what test tries to do 4512 4513 if (m_test == TEST_NO_GEOMETRY) 4514 m_testCtx.getLog() << tcu::TestLog::Message << "Querying PRIMITIVES_GENERATED while rendering without a geometry shader." << tcu::TestLog::EndMessage; 4515 else if (m_test == TEST_NO_AMPLIFICATION) 4516 m_testCtx.getLog() << tcu::TestLog::Message << "Querying PRIMITIVES_GENERATED while rendering with a non-amplifying geometry shader." << tcu::TestLog::EndMessage; 4517 else if (m_test == TEST_AMPLIFICATION) 4518 m_testCtx.getLog() << tcu::TestLog::Message << "Querying PRIMITIVES_GENERATED while rendering with a (3x) amplifying geometry shader." << tcu::TestLog::EndMessage; 4519 else if (m_test == TEST_PARTIAL_PRIMITIVES) 4520 m_testCtx.getLog() << tcu::TestLog::Message << "Querying PRIMITIVES_GENERATED while rendering with a geometry shader that emits also partial primitives." << tcu::TestLog::EndMessage; 4521 else if (m_test == TEST_INSTANCED) 4522 m_testCtx.getLog() << tcu::TestLog::Message << "Querying PRIMITIVES_GENERATED while rendering with a instanced geometry shader." << tcu::TestLog::EndMessage; 4523 else 4524 DE_ASSERT(false); 4525 4526 // resources 4527 4528 m_program = genProgram(); 4529 m_testCtx.getLog() << *m_program; 4530 4531 if (!m_program->isOk()) 4532 throw tcu::TestError("could not build program"); 4533 } 4534 4535 void PrimitivesGeneratedQueryCase::deinit (void) 4536 { 4537 delete m_program; 4538 m_program = DE_NULL; 4539 } 4540 4541 PrimitivesGeneratedQueryCase::IterateResult PrimitivesGeneratedQueryCase::iterate (void) 4542 { 4543 glw::GLuint primitivesGenerated = 0xDEBADBAD; 4544 4545 m_testCtx.getLog() 4546 << tcu::TestLog::Message 4547 << "Drawing 8 points, setting a_one for each to value (1.0, 1.0, 1.0, 1.0)" 4548 << tcu::TestLog::EndMessage; 4549 4550 { 4551 static const tcu::Vec4 vertexData[8*2] = 4552 { 4553 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 4554 tcu::Vec4(0.1f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 4555 tcu::Vec4(0.2f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 4556 tcu::Vec4(0.3f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 4557 tcu::Vec4(0.4f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 4558 tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 4559 tcu::Vec4(0.6f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 4560 tcu::Vec4(0.7f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 4561 }; 4562 4563 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 4564 const glu::VertexArray vao (m_context.getRenderContext()); 4565 const glu::Buffer buffer (m_context.getRenderContext()); 4566 const glu::Query query (m_context.getRenderContext()); 4567 const int positionLocation = gl.getAttribLocation(m_program->getProgram(), "a_position"); 4568 const int oneLocation = gl.getAttribLocation(m_program->getProgram(), "a_one"); 4569 4570 gl.bindVertexArray(*vao); 4571 4572 gl.bindBuffer(GL_ARRAY_BUFFER, *buffer); 4573 gl.bufferData(GL_ARRAY_BUFFER, (int)sizeof(vertexData), vertexData, GL_STATIC_DRAW); 4574 4575 gl.vertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 2 * sizeof(tcu::Vec4), DE_NULL); 4576 gl.enableVertexAttribArray(positionLocation); 4577 4578 if (oneLocation != -1) 4579 { 4580 gl.vertexAttribPointer(oneLocation, 4, GL_FLOAT, GL_FALSE, 2 * sizeof(tcu::Vec4), (const tcu::Vec4*)DE_NULL + 1); 4581 gl.enableVertexAttribArray(oneLocation); 4582 } 4583 4584 gl.useProgram(m_program->getProgram()); 4585 4586 GLU_EXPECT_NO_ERROR(gl.getError(), "setup render"); 4587 4588 gl.beginQuery(GL_PRIMITIVES_GENERATED, *query); 4589 gl.drawArrays(GL_POINTS, 0, 8); 4590 gl.endQuery(GL_PRIMITIVES_GENERATED); 4591 4592 GLU_EXPECT_NO_ERROR(gl.getError(), "render and query"); 4593 4594 gl.getQueryObjectuiv(*query, GL_QUERY_RESULT, &primitivesGenerated); 4595 GLU_EXPECT_NO_ERROR(gl.getError(), "get query result"); 4596 } 4597 4598 m_testCtx.getLog() 4599 << tcu::TestLog::Message 4600 << "GL_PRIMITIVES_GENERATED = " << primitivesGenerated 4601 << tcu::TestLog::EndMessage; 4602 4603 { 4604 const deUint32 expectedGenerated = (m_test == TEST_AMPLIFICATION) ? (3*8) : (m_test == TEST_INSTANCED) ? (8*(3+1)) : (8); 4605 4606 if (expectedGenerated == primitivesGenerated) 4607 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4608 else 4609 { 4610 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong result for GL_PRIMITIVES_GENERATED"); 4611 m_testCtx.getLog() 4612 << tcu::TestLog::Message 4613 << "Got unexpected result for GL_PRIMITIVES_GENERATED. Expected " << expectedGenerated << ", got " << primitivesGenerated 4614 << tcu::TestLog::EndMessage; 4615 } 4616 } 4617 4618 return STOP; 4619 } 4620 4621 glu::ShaderProgram* PrimitivesGeneratedQueryCase::genProgram (void) 4622 { 4623 static const char* const vertexSource = "#version 310 es\n" 4624 "in highp vec4 a_position;\n" 4625 "in highp vec4 a_one;\n" 4626 "out highp vec4 v_one;\n" 4627 "void main (void)\n" 4628 "{\n" 4629 " gl_Position = a_position;\n" 4630 " v_one = a_one;\n" 4631 "}\n"; 4632 static const char* const fragmentSource = "#version 310 es\n" 4633 "layout(location = 0) out mediump vec4 fragColor;\n" 4634 "void main (void)\n" 4635 "{\n" 4636 " fragColor = vec4(1.0, 1.0, 1.0, 1.0);\n" 4637 "}\n"; 4638 std::ostringstream geometrySource; 4639 glu::ProgramSources sources; 4640 4641 if (m_test != TEST_NO_GEOMETRY) 4642 { 4643 geometrySource << "#version 310 es\n" 4644 "#extension GL_EXT_geometry_shader : require\n" 4645 "layout(points" << ((m_test == TEST_INSTANCED) ? (", invocations = 3") : ("")) << ") in;\n" 4646 "layout(triangle_strip, max_vertices = 7) out;\n" 4647 "in highp vec4 v_one[];\n" 4648 "void main (void)\n" 4649 "{\n" 4650 " // always taken\n" 4651 " if (v_one[0].x != 0.0)\n" 4652 " {\n" 4653 " gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.1, 0.0, 0.0);\n" 4654 " EmitVertex();\n" 4655 " gl_Position = gl_in[0].gl_Position + vec4(0.1, 0.0, 0.0, 0.0);\n" 4656 " EmitVertex();\n" 4657 " gl_Position = gl_in[0].gl_Position - vec4(0.1, 0.0, 0.0, 0.0);\n" 4658 " EmitVertex();\n" 4659 " EndPrimitive();\n" 4660 " }\n"; 4661 4662 if (m_test == TEST_AMPLIFICATION) 4663 { 4664 geometrySource << "\n" 4665 " // always taken\n" 4666 " if (v_one[0].y != 0.0)\n" 4667 " {\n" 4668 " gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.1, 0.0, 0.0);\n" 4669 " EmitVertex();\n" 4670 " gl_Position = gl_in[0].gl_Position + vec4(0.1, 0.0, 0.0, 0.0);\n" 4671 " EmitVertex();\n" 4672 " gl_Position = gl_in[0].gl_Position - vec4(0.0, 0.1, 0.0, 0.0);\n" 4673 " EmitVertex();\n" 4674 " gl_Position = gl_in[0].gl_Position - vec4(0.1, 0.0, 0.0, 0.0);\n" 4675 " EmitVertex();\n" 4676 " }\n"; 4677 } 4678 else if (m_test == TEST_PARTIAL_PRIMITIVES) 4679 { 4680 geometrySource << "\n" 4681 " // always taken\n" 4682 " if (v_one[0].y != 0.0)\n" 4683 " {\n" 4684 " gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.1, 0.0, 0.0);\n" 4685 " EmitVertex();\n" 4686 " gl_Position = gl_in[0].gl_Position + vec4(0.1, 0.0, 0.0, 0.0);\n" 4687 " EmitVertex();\n" 4688 "\n" 4689 " // never taken\n" 4690 " if (v_one[0].z < 0.0)\n" 4691 " {\n" 4692 " gl_Position = gl_in[0].gl_Position - vec4(0.1, 0.0, 0.0, 0.0);\n" 4693 " EmitVertex();\n" 4694 " }\n" 4695 " }\n"; 4696 } 4697 else if (m_test == TEST_INSTANCED) 4698 { 4699 geometrySource << "\n" 4700 " // taken once\n" 4701 " if (v_one[0].y > float(gl_InvocationID) + 0.5)\n" 4702 " {\n" 4703 " gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.1, 0.0, 0.0);\n" 4704 " EmitVertex();\n" 4705 " gl_Position = gl_in[0].gl_Position + vec4(0.1, 0.0, 0.0, 0.0);\n" 4706 " EmitVertex();\n" 4707 " gl_Position = gl_in[0].gl_Position - vec4(0.1, 0.0, 0.0, 0.0);\n" 4708 " EmitVertex();\n" 4709 " }\n"; 4710 } 4711 4712 geometrySource << "}\n"; 4713 } 4714 4715 sources << glu::VertexSource(vertexSource); 4716 sources << glu::FragmentSource(fragmentSource); 4717 4718 if (!geometrySource.str().empty()) 4719 sources << glu::GeometrySource(geometrySource.str()); 4720 4721 return new glu::ShaderProgram(m_context.getRenderContext(), sources); 4722 } 4723 4724 class GeometryShaderFeartureTestCase : public TestCase 4725 { 4726 public: 4727 GeometryShaderFeartureTestCase (Context& context, const char* name, const char* description); 4728 4729 void init (void); 4730 }; 4731 4732 GeometryShaderFeartureTestCase::GeometryShaderFeartureTestCase (Context& context, const char* name, const char* description) 4733 : TestCase(context, name, description) 4734 { 4735 } 4736 4737 void GeometryShaderFeartureTestCase::init (void) 4738 { 4739 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 4740 throw tcu::NotSupportedError("test requires GL_EXT_geometry_shader extension"); 4741 } 4742 4743 class FramebufferDefaultLayersCase : public GeometryShaderFeartureTestCase 4744 { 4745 public: 4746 FramebufferDefaultLayersCase (Context& context, const char* name, const char* description); 4747 IterateResult iterate (void); 4748 }; 4749 4750 FramebufferDefaultLayersCase::FramebufferDefaultLayersCase (Context& context, const char* name, const char* description) 4751 : GeometryShaderFeartureTestCase(context, name, description) 4752 { 4753 } 4754 4755 FramebufferDefaultLayersCase::IterateResult FramebufferDefaultLayersCase::iterate (void) 4756 { 4757 glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 4758 4759 gl.enableLogging(true); 4760 4761 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4762 4763 { 4764 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Default", "Default value"); 4765 const glu::Framebuffer fbo (m_context.getRenderContext()); 4766 glw::GLint defaultLayers = -1; 4767 4768 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo); 4769 gl.glGetFramebufferParameteriv(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_LAYERS, &defaultLayers); 4770 GLU_EXPECT_NO_ERROR(gl.glGetError(), "getFramebufferParameteriv"); 4771 4772 m_testCtx.getLog() << tcu::TestLog::Message << "GL_FRAMEBUFFER_DEFAULT_LAYERS = " << defaultLayers << tcu::TestLog::EndMessage; 4773 4774 if (defaultLayers != 0) 4775 { 4776 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected 0, got " << defaultLayers << tcu::TestLog::EndMessage; 4777 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid layer count"); 4778 } 4779 } 4780 4781 { 4782 const tcu::ScopedLogSection section (m_testCtx.getLog(), "SetTo12", "Set default layers to 12"); 4783 const glu::Framebuffer fbo (m_context.getRenderContext()); 4784 glw::GLint defaultLayers = -1; 4785 4786 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo); 4787 gl.glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_LAYERS, 12); 4788 gl.glGetFramebufferParameteriv(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_LAYERS, &defaultLayers); 4789 GLU_EXPECT_NO_ERROR(gl.glGetError(), "getFramebufferParameteriv"); 4790 4791 m_testCtx.getLog() << tcu::TestLog::Message << "GL_FRAMEBUFFER_DEFAULT_LAYERS = " << defaultLayers << tcu::TestLog::EndMessage; 4792 4793 if (defaultLayers != 12) 4794 { 4795 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected 12, got " << defaultLayers << tcu::TestLog::EndMessage; 4796 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid layer count"); 4797 } 4798 } 4799 4800 return STOP; 4801 } 4802 4803 class FramebufferAttachmentLayeredCase : public GeometryShaderFeartureTestCase 4804 { 4805 public: 4806 FramebufferAttachmentLayeredCase (Context& context, const char* name, const char* description); 4807 IterateResult iterate (void); 4808 }; 4809 4810 FramebufferAttachmentLayeredCase::FramebufferAttachmentLayeredCase (Context& context, const char* name, const char* description) 4811 : GeometryShaderFeartureTestCase(context, name, description) 4812 { 4813 } 4814 4815 FramebufferAttachmentLayeredCase::IterateResult FramebufferAttachmentLayeredCase::iterate (void) 4816 { 4817 enum CaseType 4818 { 4819 TEXTURE_3D, 4820 TEXTURE_2D_ARRAY, 4821 TEXTURE_CUBE, 4822 TEXTURE_2D_MS_ARRAY, 4823 TEXTURE_3D_LAYER, 4824 TEXTURE_2D_ARRAY_LAYER, 4825 }; 4826 4827 static const struct TextureType 4828 { 4829 const char* name; 4830 const char* description; 4831 bool layered; 4832 CaseType type; 4833 } textureTypes[] = 4834 { 4835 { "3D", "3D texture", true, TEXTURE_3D }, 4836 { "2DArray", "2D array", true, TEXTURE_2D_ARRAY }, 4837 { "Cube", "Cube map", true, TEXTURE_CUBE }, 4838 { "2DMSArray", "2D multisample array", true, TEXTURE_2D_MS_ARRAY }, 4839 { "3DLayer", "3D texture layer ", false, TEXTURE_3D_LAYER }, 4840 { "2DArrayLayer", "2D array layer ", false, TEXTURE_2D_ARRAY_LAYER }, 4841 }; 4842 4843 glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 4844 gl.enableLogging(true); 4845 4846 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4847 4848 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(textureTypes); ++ndx) 4849 { 4850 const tcu::ScopedLogSection section (m_testCtx.getLog(), textureTypes[ndx].name, textureTypes[ndx].description); 4851 const glu::Framebuffer fbo (m_context.getRenderContext()); 4852 const glu::Texture texture (m_context.getRenderContext()); 4853 glw::GLint layered = -1; 4854 4855 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo); 4856 4857 if (textureTypes[ndx].type == TEXTURE_3D || textureTypes[ndx].type == TEXTURE_3D_LAYER) 4858 { 4859 gl.glBindTexture(GL_TEXTURE_3D, *texture); 4860 gl.glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL); 4861 gl.glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4862 gl.glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4863 4864 if (textureTypes[ndx].type == TEXTURE_3D) 4865 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture, 0); 4866 else 4867 gl.glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture, 0, 2); 4868 } 4869 else if (textureTypes[ndx].type == TEXTURE_2D_ARRAY || textureTypes[ndx].type == TEXTURE_2D_ARRAY_LAYER) 4870 { 4871 gl.glBindTexture(GL_TEXTURE_2D_ARRAY, *texture); 4872 gl.glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL); 4873 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4874 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4875 4876 if (textureTypes[ndx].type == TEXTURE_2D_ARRAY) 4877 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture, 0); 4878 else 4879 gl.glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture, 0, 3); 4880 } 4881 else if (textureTypes[ndx].type == TEXTURE_CUBE) 4882 { 4883 gl.glBindTexture(GL_TEXTURE_CUBE_MAP, *texture); 4884 for (int face = 0; face < 6; ++face) 4885 gl.glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA8, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL); 4886 gl.glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4887 gl.glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4888 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture, 0); 4889 } 4890 else if (textureTypes[ndx].type == TEXTURE_2D_MS_ARRAY) 4891 { 4892 // check extension 4893 if (!m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array")) 4894 { 4895 m_testCtx.getLog() << tcu::TestLog::Message << "GL_OES_texture_storage_multisample_2d_array not supported, skipping." << tcu::TestLog::EndMessage; 4896 continue; 4897 } 4898 4899 gl.glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, *texture); 4900 gl.glTexStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 1, GL_RGBA8, 32, 32, 32, GL_FALSE); 4901 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture, 0); 4902 } 4903 4904 GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup attachment"); 4905 4906 gl.glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_LAYERED, &layered); 4907 GLU_EXPECT_NO_ERROR(gl.glGetError(), "getFramebufferParameteriv"); 4908 4909 m_testCtx.getLog() << tcu::TestLog::Message << "GL_FRAMEBUFFER_ATTACHMENT_LAYERED = " << glu::getBooleanStr(layered) << tcu::TestLog::EndMessage; 4910 4911 if (layered != GL_TRUE && layered != GL_FALSE) 4912 { 4913 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected boolean, got " << layered << tcu::TestLog::EndMessage; 4914 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid boolean"); 4915 } 4916 else if ((layered == GL_TRUE) != textureTypes[ndx].layered) 4917 { 4918 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected " << ((textureTypes[ndx].layered) ? ("GL_TRUE") : ("GL_FALSE")) << ", got " << glu::getBooleanStr(layered) << tcu::TestLog::EndMessage; 4919 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid layer count"); 4920 } 4921 } 4922 4923 return STOP; 4924 } 4925 4926 class FramebufferIncompleteLayereTargetsCase : public GeometryShaderFeartureTestCase 4927 { 4928 public: 4929 FramebufferIncompleteLayereTargetsCase (Context& context, const char* name, const char* description); 4930 IterateResult iterate (void); 4931 }; 4932 4933 FramebufferIncompleteLayereTargetsCase::FramebufferIncompleteLayereTargetsCase (Context& context, const char* name, const char* description) 4934 : GeometryShaderFeartureTestCase(context, name, description) 4935 { 4936 } 4937 4938 FramebufferIncompleteLayereTargetsCase::IterateResult FramebufferIncompleteLayereTargetsCase::iterate (void) 4939 { 4940 glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 4941 gl.enableLogging(true); 4942 4943 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 4944 4945 { 4946 const tcu::ScopedLogSection section (m_testCtx.getLog(), "LayerAndNonLayer", "Layered and non-layered"); 4947 const glu::Framebuffer fbo (m_context.getRenderContext()); 4948 const glu::Texture texture0 (m_context.getRenderContext()); 4949 const glu::Texture texture1 (m_context.getRenderContext()); 4950 4951 glw::GLint fboStatus; 4952 4953 gl.glBindTexture(GL_TEXTURE_2D_ARRAY, *texture0); 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.glBindTexture(GL_TEXTURE_2D_ARRAY, *texture1); 4959 gl.glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL); 4960 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4961 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4962 4963 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo); 4964 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture0, 0); 4965 gl.glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, *texture1, 0, 0); 4966 4967 GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup fbo"); 4968 4969 fboStatus = gl.glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); 4970 m_testCtx.getLog() << tcu::TestLog::Message << "Framebuffer status: " << glu::getFramebufferStatusStr(fboStatus) << tcu::TestLog::EndMessage; 4971 4972 if (fboStatus != GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS) 4973 { 4974 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS, got " << glu::getFramebufferStatusStr(fboStatus) << tcu::TestLog::EndMessage; 4975 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid layer count"); 4976 } 4977 } 4978 4979 { 4980 const tcu::ScopedLogSection section (m_testCtx.getLog(), "DifferentTarget", "Different target"); 4981 const glu::Framebuffer fbo (m_context.getRenderContext()); 4982 const glu::Texture texture0 (m_context.getRenderContext()); 4983 const glu::Texture texture1 (m_context.getRenderContext()); 4984 4985 glw::GLint fboStatus; 4986 4987 gl.glBindTexture(GL_TEXTURE_2D_ARRAY, *texture0); 4988 gl.glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL); 4989 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4990 gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4991 4992 gl.glBindTexture(GL_TEXTURE_3D, *texture1); 4993 gl.glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL); 4994 gl.glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4995 gl.glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4996 4997 gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo); 4998 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, *texture0, 0); 4999 gl.glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, *texture1, 0); 5000 5001 GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup fbo"); 5002 5003 fboStatus = gl.glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); 5004 m_testCtx.getLog() << tcu::TestLog::Message << "Framebuffer status: " << glu::getFramebufferStatusStr(fboStatus) << tcu::TestLog::EndMessage; 5005 5006 if (fboStatus != GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS) 5007 { 5008 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS, got " << glu::getFramebufferStatusStr(fboStatus) << tcu::TestLog::EndMessage; 5009 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "invalid layer count"); 5010 } 5011 } 5012 5013 return STOP; 5014 } 5015 5016 class ReferencedByGeometryShaderCase : public GeometryShaderFeartureTestCase 5017 { 5018 public: 5019 ReferencedByGeometryShaderCase (Context& context, const char* name, const char* description); 5020 IterateResult iterate (void); 5021 }; 5022 5023 ReferencedByGeometryShaderCase::ReferencedByGeometryShaderCase (Context& context, const char* name, const char* description) 5024 : GeometryShaderFeartureTestCase(context, name, description) 5025 { 5026 } 5027 5028 ReferencedByGeometryShaderCase::IterateResult ReferencedByGeometryShaderCase::iterate (void) 5029 { 5030 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5031 5032 { 5033 static const char* const vertexSource = "#version 310 es\n" 5034 "uniform highp vec4 u_position;\n" 5035 "void main (void)\n" 5036 "{\n" 5037 " gl_Position = u_position;\n" 5038 "}\n"; 5039 static const char* const fragmentSource = "#version 310 es\n" 5040 "layout(location = 0) out mediump vec4 fragColor;\n" 5041 "void main (void)\n" 5042 "{\n" 5043 " fragColor = vec4(1.0, 1.0, 1.0, 1.0);\n" 5044 "}\n"; 5045 static const char* const geometrySource = "#version 310 es\n" 5046 "#extension GL_EXT_geometry_shader : require\n" 5047 "layout(points) in;\n" 5048 "layout(points, max_vertices=1) out;\n" 5049 "uniform highp vec4 u_offset;\n" 5050 "void main (void)\n" 5051 "{\n" 5052 " gl_Position = gl_in[0].gl_Position + u_offset;\n" 5053 " EmitVertex();\n" 5054 "}\n"; 5055 5056 const glu::ShaderProgram program(m_context.getRenderContext(), glu::ProgramSources() 5057 << glu::VertexSource(vertexSource) 5058 << glu::FragmentSource(fragmentSource) 5059 << glu::GeometrySource(geometrySource)); 5060 m_testCtx.getLog() << program; 5061 5062 { 5063 const tcu::ScopedLogSection section (m_testCtx.getLog(), "UnreferencedUniform", "Unreferenced uniform u_position"); 5064 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 5065 const deUint32 props[1] = { GL_REFERENCED_BY_GEOMETRY_SHADER }; 5066 deUint32 resourcePos; 5067 glw::GLsizei length = 0; 5068 glw::GLint referenced = 0; 5069 5070 gl.enableLogging(true); 5071 5072 resourcePos = gl.glGetProgramResourceIndex(program.getProgram(), GL_UNIFORM, "u_position"); 5073 m_testCtx.getLog() << tcu::TestLog::Message << "u_position resource index: " << resourcePos << tcu::TestLog::EndMessage; 5074 5075 gl.glGetProgramResourceiv(program.getProgram(), GL_UNIFORM, resourcePos, 1, props, 1, &length, &referenced); 5076 m_testCtx.getLog() << tcu::TestLog::Message << "Query GL_REFERENCED_BY_GEOMETRY_SHADER, got " << length << " value(s), value[0] = " << glu::getBooleanStr(referenced) << tcu::TestLog::EndMessage; 5077 5078 GLU_EXPECT_NO_ERROR(gl.glGetError(), "query resource"); 5079 5080 if (length == 0 || referenced != GL_FALSE) 5081 { 5082 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected GL_FALSE." << tcu::TestLog::EndMessage; 5083 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected value"); 5084 } 5085 } 5086 5087 { 5088 const tcu::ScopedLogSection section (m_testCtx.getLog(), "ReferencedUniform", "Referenced uniform u_offset"); 5089 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog()); 5090 const deUint32 props[1] = { GL_REFERENCED_BY_GEOMETRY_SHADER }; 5091 deUint32 resourcePos; 5092 glw::GLsizei length = 0; 5093 glw::GLint referenced = 0; 5094 5095 gl.enableLogging(true); 5096 5097 resourcePos = gl.glGetProgramResourceIndex(program.getProgram(), GL_UNIFORM, "u_offset"); 5098 m_testCtx.getLog() << tcu::TestLog::Message << "u_offset resource index: " << resourcePos << tcu::TestLog::EndMessage; 5099 5100 gl.glGetProgramResourceiv(program.getProgram(), GL_UNIFORM, resourcePos, 1, props, 1, &length, &referenced); 5101 m_testCtx.getLog() << tcu::TestLog::Message << "Query GL_REFERENCED_BY_GEOMETRY_SHADER, got " << length << " value(s), value[0] = " << glu::getBooleanStr(referenced) << tcu::TestLog::EndMessage; 5102 5103 GLU_EXPECT_NO_ERROR(gl.glGetError(), "query resource"); 5104 5105 if (length == 0 || referenced != GL_TRUE) 5106 { 5107 m_testCtx.getLog() << tcu::TestLog::Message << "Error, expected GL_TRUE." << tcu::TestLog::EndMessage; 5108 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected value"); 5109 } 5110 } 5111 } 5112 5113 return STOP; 5114 } 5115 5116 class VertexFeedbackCase : public TestCase 5117 { 5118 public: 5119 enum DrawMethod 5120 { 5121 METHOD_DRAW_ARRAYS = 0, 5122 METHOD_DRAW_ARRAYS_INSTANCED, 5123 METHOD_DRAW_ARRAYS_INDIRECT, 5124 METHOD_DRAW_ELEMENTS, 5125 METHOD_DRAW_ELEMENTS_INSTANCED, 5126 METHOD_DRAW_ELEMENTS_INDIRECT, 5127 5128 METHOD_LAST 5129 }; 5130 enum PrimitiveType 5131 { 5132 PRIMITIVE_LINE_LOOP = 0, 5133 PRIMITIVE_LINE_STRIP, 5134 PRIMITIVE_TRIANGLE_STRIP, 5135 PRIMITIVE_TRIANGLE_FAN, 5136 PRIMITIVE_POINTS, 5137 5138 PRIMITIVE_LAST 5139 }; 5140 5141 VertexFeedbackCase (Context& context, const char* name, const char* description, DrawMethod method, PrimitiveType output); 5142 ~VertexFeedbackCase (void); 5143 private: 5144 void init (void); 5145 void deinit (void); 5146 IterateResult iterate (void); 5147 5148 glu::ShaderProgram* genProgram (void); 5149 deUint32 getOutputPrimitive (void); 5150 deUint32 getBasePrimitive (void); 5151 5152 const DrawMethod m_method; 5153 const PrimitiveType m_output; 5154 5155 deUint32 m_elementBuf; 5156 deUint32 m_arrayBuf; 5157 deUint32 m_offsetBuf; 5158 deUint32 m_feedbackBuf; 5159 deUint32 m_indirectBuffer; 5160 glu::ShaderProgram* m_program; 5161 glu::VertexArray* m_vao; 5162 }; 5163 5164 VertexFeedbackCase::VertexFeedbackCase (Context& context, const char* name, const char* description, DrawMethod method, PrimitiveType output) 5165 : TestCase (context, name, description) 5166 , m_method (method) 5167 , m_output (output) 5168 , m_elementBuf (0) 5169 , m_arrayBuf (0) 5170 , m_offsetBuf (0) 5171 , m_feedbackBuf (0) 5172 , m_indirectBuffer (0) 5173 , m_program (DE_NULL) 5174 , m_vao (DE_NULL) 5175 { 5176 DE_ASSERT(method < METHOD_LAST); 5177 DE_ASSERT(output < PRIMITIVE_LAST); 5178 } 5179 5180 VertexFeedbackCase::~VertexFeedbackCase (void) 5181 { 5182 deinit(); 5183 } 5184 5185 void VertexFeedbackCase::init (void) 5186 { 5187 // requirements 5188 5189 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 5190 throw tcu::NotSupportedError("test requires GL_EXT_geometry_shader extension"); 5191 5192 // log what test tries to do 5193 5194 m_testCtx.getLog() 5195 << tcu::TestLog::Message 5196 << "Testing GL_EXT_geometry_shader transform feedback relaxations.\n" 5197 << "Capturing vertex shader varying, no geometry shader. Invoke with:" 5198 << tcu::TestLog::EndMessage; 5199 5200 switch (m_method) 5201 { 5202 case METHOD_DRAW_ARRAYS: m_testCtx.getLog() << tcu::TestLog::Message << "Draw method: drawArrays" << tcu::TestLog::EndMessage; break; 5203 case METHOD_DRAW_ARRAYS_INSTANCED: m_testCtx.getLog() << tcu::TestLog::Message << "Draw method: drawArraysInstanced" << tcu::TestLog::EndMessage; break; 5204 case METHOD_DRAW_ARRAYS_INDIRECT: m_testCtx.getLog() << tcu::TestLog::Message << "Draw method: drawArraysIndirect" << tcu::TestLog::EndMessage; break; 5205 case METHOD_DRAW_ELEMENTS: m_testCtx.getLog() << tcu::TestLog::Message << "Draw method: drawElements" << tcu::TestLog::EndMessage; break; 5206 case METHOD_DRAW_ELEMENTS_INSTANCED: m_testCtx.getLog() << tcu::TestLog::Message << "Draw method: drawElementsInstanced" << tcu::TestLog::EndMessage; break; 5207 case METHOD_DRAW_ELEMENTS_INDIRECT: m_testCtx.getLog() << tcu::TestLog::Message << "Draw method: drawElementsIndirect" << tcu::TestLog::EndMessage; break; 5208 default: 5209 DE_ASSERT(false); 5210 } 5211 switch (m_output) 5212 { 5213 case PRIMITIVE_LINE_LOOP: m_testCtx.getLog() << tcu::TestLog::Message << "Draw primitive: line loop" << tcu::TestLog::EndMessage; break; 5214 case PRIMITIVE_LINE_STRIP: m_testCtx.getLog() << tcu::TestLog::Message << "Draw primitive: line strip" << tcu::TestLog::EndMessage; break; 5215 case PRIMITIVE_TRIANGLE_STRIP: m_testCtx.getLog() << tcu::TestLog::Message << "Draw primitive: triangle strip" << tcu::TestLog::EndMessage; break; 5216 case PRIMITIVE_TRIANGLE_FAN: m_testCtx.getLog() << tcu::TestLog::Message << "Draw primitive: triangle fan" << tcu::TestLog::EndMessage; break; 5217 case PRIMITIVE_POINTS: m_testCtx.getLog() << tcu::TestLog::Message << "Draw primitive: points" << tcu::TestLog::EndMessage; break; 5218 default: 5219 DE_ASSERT(false); 5220 } 5221 5222 // resources 5223 5224 { 5225 static const deUint16 elementData[] = 5226 { 5227 0, 1, 2, 3, 5228 }; 5229 static const tcu::Vec4 arrayData[] = 5230 { 5231 tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), 5232 tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), 5233 tcu::Vec4(2.0f, 0.0f, 0.0f, 0.0f), 5234 tcu::Vec4(3.0f, 0.0f, 0.0f, 0.0f), 5235 }; 5236 static const tcu::Vec4 offsetData[] = 5237 { 5238 tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), 5239 tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), 5240 tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), 5241 tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), 5242 }; 5243 5244 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5245 const int feedbackSize = 8 * sizeof(float[4]); 5246 5247 m_vao = new glu::VertexArray(m_context.getRenderContext()); 5248 gl.bindVertexArray(**m_vao); 5249 GLU_EXPECT_NO_ERROR(gl.getError(), "set up vao"); 5250 5251 gl.genBuffers(1, &m_elementBuf); 5252 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBuf); 5253 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), &elementData[0], GL_STATIC_DRAW); 5254 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf"); 5255 5256 gl.genBuffers(1, &m_arrayBuf); 5257 gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuf); 5258 gl.bufferData(GL_ARRAY_BUFFER, sizeof(arrayData), &arrayData[0], GL_STATIC_DRAW); 5259 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf"); 5260 5261 gl.genBuffers(1, &m_offsetBuf); 5262 gl.bindBuffer(GL_ARRAY_BUFFER, m_offsetBuf); 5263 gl.bufferData(GL_ARRAY_BUFFER, sizeof(offsetData), &offsetData[0], GL_STATIC_DRAW); 5264 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf"); 5265 5266 gl.genBuffers(1, &m_feedbackBuf); 5267 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_feedbackBuf); 5268 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, feedbackSize, DE_NULL, GL_DYNAMIC_COPY); 5269 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf"); 5270 5271 m_program = genProgram(); 5272 5273 if (!m_program->isOk()) 5274 { 5275 m_testCtx.getLog() << *m_program; 5276 throw tcu::TestError("could not build program"); 5277 } 5278 } 5279 } 5280 5281 void VertexFeedbackCase::deinit (void) 5282 { 5283 if (m_elementBuf) 5284 { 5285 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_elementBuf); 5286 m_elementBuf = 0; 5287 } 5288 5289 if (m_arrayBuf) 5290 { 5291 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_arrayBuf); 5292 m_arrayBuf = 0; 5293 } 5294 5295 if (m_offsetBuf) 5296 { 5297 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_offsetBuf); 5298 m_offsetBuf = 0; 5299 } 5300 5301 if (m_feedbackBuf) 5302 { 5303 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_feedbackBuf); 5304 m_feedbackBuf = 0; 5305 } 5306 5307 if (m_indirectBuffer) 5308 { 5309 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_indirectBuffer); 5310 m_indirectBuffer = 0; 5311 } 5312 5313 delete m_program; 5314 m_program = DE_NULL; 5315 5316 delete m_vao; 5317 m_vao = DE_NULL; 5318 } 5319 5320 VertexFeedbackCase::IterateResult VertexFeedbackCase::iterate (void) 5321 { 5322 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5323 const deUint32 outputPrimitive = getOutputPrimitive(); 5324 const deUint32 basePrimitive = getBasePrimitive(); 5325 5326 const int posLocation = gl.getAttribLocation(m_program->getProgram(), "a_position"); 5327 const int offsetLocation = gl.getAttribLocation(m_program->getProgram(), "a_offset"); 5328 5329 if (posLocation == -1) 5330 throw tcu::TestError("a_position location was -1"); 5331 if (offsetLocation == -1) 5332 throw tcu::TestError("a_offset location was -1"); 5333 5334 gl.useProgram(m_program->getProgram()); 5335 5336 gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuf); 5337 gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 5338 gl.enableVertexAttribArray(posLocation); 5339 5340 gl.bindBuffer(GL_ARRAY_BUFFER, m_offsetBuf); 5341 gl.vertexAttribPointer(offsetLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 5342 gl.enableVertexAttribArray(offsetLocation); 5343 5344 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_feedbackBuf); 5345 GLU_EXPECT_NO_ERROR(gl.getError(), "bind buffer base"); 5346 5347 m_testCtx.getLog() << tcu::TestLog::Message << "Calling BeginTransformFeedback(" << glu::getPrimitiveTypeStr(basePrimitive) << ")" << tcu::TestLog::EndMessage; 5348 gl.beginTransformFeedback(basePrimitive); 5349 GLU_EXPECT_NO_ERROR(gl.getError(), "beginTransformFeedback"); 5350 5351 switch (m_method) 5352 { 5353 case METHOD_DRAW_ARRAYS: 5354 { 5355 m_testCtx.getLog() << tcu::TestLog::Message << "Calling DrawArrays(" << glu::getPrimitiveTypeStr(outputPrimitive) << ", ...)" << tcu::TestLog::EndMessage; 5356 gl.drawArrays(outputPrimitive, 0, 4); 5357 break; 5358 } 5359 5360 case METHOD_DRAW_ARRAYS_INSTANCED: 5361 { 5362 m_testCtx.getLog() << tcu::TestLog::Message << "Calling DrawArraysInstanced(" << glu::getPrimitiveTypeStr(outputPrimitive) << ", ...)" << tcu::TestLog::EndMessage; 5363 gl.vertexAttribDivisor(offsetLocation, 2); 5364 gl.drawArraysInstanced(outputPrimitive, 0, 3, 2); 5365 break; 5366 } 5367 5368 case METHOD_DRAW_ELEMENTS: 5369 { 5370 m_testCtx.getLog() << tcu::TestLog::Message << "Calling DrawElements(" << glu::getPrimitiveTypeStr(outputPrimitive) << ", ...)" << tcu::TestLog::EndMessage; 5371 gl.drawElements(outputPrimitive, 4, GL_UNSIGNED_SHORT, DE_NULL); 5372 break; 5373 } 5374 5375 case METHOD_DRAW_ELEMENTS_INSTANCED: 5376 { 5377 m_testCtx.getLog() << tcu::TestLog::Message << "Calling DrawElementsInstanced(" << glu::getPrimitiveTypeStr(outputPrimitive) << ", ...)" << tcu::TestLog::EndMessage; 5378 gl.drawElementsInstanced(outputPrimitive, 3, GL_UNSIGNED_SHORT, DE_NULL, 2); 5379 break; 5380 } 5381 5382 case METHOD_DRAW_ARRAYS_INDIRECT: 5383 { 5384 struct DrawArraysIndirectCommand 5385 { 5386 deUint32 count; 5387 deUint32 instanceCount; 5388 deUint32 first; 5389 deUint32 reservedMustBeZero; 5390 } params; 5391 5392 DE_STATIC_ASSERT(sizeof(DrawArraysIndirectCommand) == sizeof(deUint32[4])); 5393 5394 params.count = 4; 5395 params.instanceCount = 1; 5396 params.first = 0; 5397 params.reservedMustBeZero = 0; 5398 5399 gl.genBuffers(1, &m_indirectBuffer); 5400 gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_indirectBuffer); 5401 gl.bufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(params), ¶ms, GL_STATIC_DRAW); 5402 5403 m_testCtx.getLog() << tcu::TestLog::Message << "Calling DrawElementsIndirect(" << glu::getPrimitiveTypeStr(outputPrimitive) << ", ...)" << tcu::TestLog::EndMessage; 5404 gl.drawArraysIndirect(outputPrimitive, DE_NULL); 5405 break; 5406 } 5407 5408 case METHOD_DRAW_ELEMENTS_INDIRECT: 5409 { 5410 struct DrawElementsIndirectCommand 5411 { 5412 deUint32 count; 5413 deUint32 instanceCount; 5414 deUint32 firstIndex; 5415 deInt32 baseVertex; 5416 deUint32 reservedMustBeZero; 5417 } params; 5418 5419 DE_STATIC_ASSERT(sizeof(DrawElementsIndirectCommand) == sizeof(deUint32[5])); 5420 5421 params.count = 4; 5422 params.instanceCount = 1; 5423 params.firstIndex = 0; 5424 params.baseVertex = 0; 5425 params.reservedMustBeZero = 0; 5426 5427 gl.genBuffers(1, &m_indirectBuffer); 5428 gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_indirectBuffer); 5429 gl.bufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(params), ¶ms, GL_STATIC_DRAW); 5430 5431 m_testCtx.getLog() << tcu::TestLog::Message << "Calling DrawElementsIndirect(" << glu::getPrimitiveTypeStr(outputPrimitive) << ", ...)" << tcu::TestLog::EndMessage; 5432 gl.drawElementsIndirect(outputPrimitive, GL_UNSIGNED_SHORT, DE_NULL); 5433 break; 5434 } 5435 5436 default: 5437 DE_ASSERT(false); 5438 } 5439 GLU_EXPECT_NO_ERROR(gl.getError(), "draw"); 5440 5441 gl.endTransformFeedback(); 5442 GLU_EXPECT_NO_ERROR(gl.getError(), "endTransformFeedback"); 5443 5444 m_testCtx.getLog() << tcu::TestLog::Message << "No errors." << tcu::TestLog::EndMessage; 5445 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5446 5447 return STOP; 5448 } 5449 5450 glu::ShaderProgram* VertexFeedbackCase::genProgram (void) 5451 { 5452 static const char* const vertexSource = "#version 310 es\n" 5453 "in highp vec4 a_position;\n" 5454 "in highp vec4 a_offset;\n" 5455 "out highp vec4 tf_value;\n" 5456 "void main (void)\n" 5457 "{\n" 5458 " gl_Position = a_position;\n" 5459 " tf_value = a_position + a_offset;\n" 5460 "}\n"; 5461 static const char* const fragmentSource = "#version 310 es\n" 5462 "layout(location = 0) out mediump vec4 fragColor;\n" 5463 "void main (void)\n" 5464 "{\n" 5465 " fragColor = vec4(1.0);\n" 5466 "}\n"; 5467 5468 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 5469 << glu::VertexSource(vertexSource) 5470 << glu::FragmentSource(fragmentSource) 5471 << glu::TransformFeedbackVarying("tf_value") 5472 << glu::TransformFeedbackMode(GL_INTERLEAVED_ATTRIBS)); 5473 } 5474 5475 deUint32 VertexFeedbackCase::getOutputPrimitive (void) 5476 { 5477 switch(m_output) 5478 { 5479 case PRIMITIVE_LINE_LOOP: return GL_LINE_LOOP; 5480 case PRIMITIVE_LINE_STRIP: return GL_LINE_STRIP; 5481 case PRIMITIVE_TRIANGLE_STRIP: return GL_TRIANGLE_STRIP; 5482 case PRIMITIVE_TRIANGLE_FAN: return GL_TRIANGLE_FAN; 5483 case PRIMITIVE_POINTS: return GL_POINTS; 5484 default: 5485 DE_ASSERT(false); 5486 return 0; 5487 } 5488 } 5489 5490 deUint32 VertexFeedbackCase::getBasePrimitive (void) 5491 { 5492 switch(m_output) 5493 { 5494 case PRIMITIVE_LINE_LOOP: return GL_LINES; 5495 case PRIMITIVE_LINE_STRIP: return GL_LINES; 5496 case PRIMITIVE_TRIANGLE_STRIP: return GL_TRIANGLES; 5497 case PRIMITIVE_TRIANGLE_FAN: return GL_TRIANGLES; 5498 case PRIMITIVE_POINTS: return GL_POINTS; 5499 default: 5500 DE_ASSERT(false); 5501 return 0; 5502 } 5503 } 5504 5505 class VertexFeedbackOverflowCase : public TestCase 5506 { 5507 public: 5508 enum Method 5509 { 5510 METHOD_DRAW_ARRAYS = 0, 5511 METHOD_DRAW_ELEMENTS, 5512 }; 5513 5514 VertexFeedbackOverflowCase (Context& context, const char* name, const char* description, Method method); 5515 ~VertexFeedbackOverflowCase (void); 5516 5517 private: 5518 void init (void); 5519 void deinit (void); 5520 IterateResult iterate (void); 5521 glu::ShaderProgram* genProgram (void); 5522 5523 const Method m_method; 5524 5525 deUint32 m_elementBuf; 5526 deUint32 m_arrayBuf; 5527 deUint32 m_feedbackBuf; 5528 glu::ShaderProgram* m_program; 5529 glu::VertexArray* m_vao; 5530 }; 5531 5532 VertexFeedbackOverflowCase::VertexFeedbackOverflowCase (Context& context, const char* name, const char* description, Method method) 5533 : TestCase (context, name, description) 5534 , m_method (method) 5535 , m_elementBuf (0) 5536 , m_arrayBuf (0) 5537 , m_feedbackBuf (0) 5538 , m_program (DE_NULL) 5539 , m_vao (DE_NULL) 5540 { 5541 } 5542 5543 VertexFeedbackOverflowCase::~VertexFeedbackOverflowCase (void) 5544 { 5545 deinit(); 5546 } 5547 5548 void VertexFeedbackOverflowCase::init (void) 5549 { 5550 // requirements 5551 5552 if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) 5553 throw tcu::NotSupportedError("test requires GL_EXT_geometry_shader extension"); 5554 5555 // log what test tries to do 5556 5557 m_testCtx.getLog() 5558 << tcu::TestLog::Message 5559 << "Testing GL_EXT_geometry_shader transform feedback overflow behavior.\n" 5560 << "Capturing vertex shader varying, rendering 2 triangles. Allocating feedback buffer for 5 vertices." 5561 << tcu::TestLog::EndMessage; 5562 5563 // resources 5564 5565 { 5566 static const deUint16 elementData[] = 5567 { 5568 0, 1, 2, 5569 0, 1, 2, 5570 }; 5571 static const tcu::Vec4 arrayData[] = 5572 { 5573 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 5574 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 5575 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 5576 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), 5577 }; 5578 5579 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5580 5581 m_vao = new glu::VertexArray(m_context.getRenderContext()); 5582 gl.bindVertexArray(**m_vao); 5583 GLU_EXPECT_NO_ERROR(gl.getError(), "set up vao"); 5584 5585 if (m_method == METHOD_DRAW_ELEMENTS) 5586 { 5587 gl.genBuffers(1, &m_elementBuf); 5588 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBuf); 5589 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), &elementData[0], GL_STATIC_DRAW); 5590 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf"); 5591 } 5592 5593 gl.genBuffers(1, &m_arrayBuf); 5594 gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuf); 5595 gl.bufferData(GL_ARRAY_BUFFER, sizeof(arrayData), &arrayData[0], GL_STATIC_DRAW); 5596 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf"); 5597 5598 { 5599 const int feedbackCount = 5 * 4; // 5x vec4 5600 const std::vector<float> initialBufferContents (feedbackCount, -1.0f); 5601 5602 m_testCtx.getLog() << tcu::TestLog::Message << "Filling feeback buffer with dummy value (-1.0)." << tcu::TestLog::EndMessage; 5603 5604 gl.genBuffers(1, &m_feedbackBuf); 5605 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_feedbackBuf); 5606 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, (int)(sizeof(float) * initialBufferContents.size()), &initialBufferContents[0], GL_DYNAMIC_COPY); 5607 GLU_EXPECT_NO_ERROR(gl.getError(), "gen buf"); 5608 } 5609 5610 m_program = genProgram(); 5611 5612 if (!m_program->isOk()) 5613 { 5614 m_testCtx.getLog() << *m_program; 5615 throw tcu::TestError("could not build program"); 5616 } 5617 } 5618 } 5619 5620 void VertexFeedbackOverflowCase::deinit (void) 5621 { 5622 if (m_elementBuf) 5623 { 5624 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_elementBuf); 5625 m_elementBuf = 0; 5626 } 5627 5628 if (m_arrayBuf) 5629 { 5630 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_arrayBuf); 5631 m_arrayBuf = 0; 5632 } 5633 5634 if (m_feedbackBuf) 5635 { 5636 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_feedbackBuf); 5637 m_feedbackBuf = 0; 5638 } 5639 5640 delete m_program; 5641 m_program = DE_NULL; 5642 5643 delete m_vao; 5644 m_vao = DE_NULL; 5645 } 5646 5647 VertexFeedbackOverflowCase::IterateResult VertexFeedbackOverflowCase::iterate (void) 5648 { 5649 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 5650 const int posLocation = gl.getAttribLocation(m_program->getProgram(), "a_position"); 5651 5652 if (posLocation == -1) 5653 throw tcu::TestError("a_position location was -1"); 5654 5655 gl.useProgram(m_program->getProgram()); 5656 5657 gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuf); 5658 gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 5659 gl.enableVertexAttribArray(posLocation); 5660 5661 if (m_method == METHOD_DRAW_ELEMENTS) 5662 { 5663 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBuf); 5664 GLU_EXPECT_NO_ERROR(gl.getError(), "bind buffers"); 5665 } 5666 5667 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_feedbackBuf); 5668 GLU_EXPECT_NO_ERROR(gl.getError(), "bind buffer base"); 5669 5670 m_testCtx.getLog() << tcu::TestLog::Message << "Capturing 2 triangles." << tcu::TestLog::EndMessage; 5671 5672 gl.beginTransformFeedback(GL_TRIANGLES); 5673 5674 if (m_method == METHOD_DRAW_ELEMENTS) 5675 gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL); 5676 else if (m_method == METHOD_DRAW_ARRAYS) 5677 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4); 5678 else 5679 DE_ASSERT(false); 5680 5681 gl.endTransformFeedback(); 5682 GLU_EXPECT_NO_ERROR(gl.getError(), "capture"); 5683 5684 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying final triangle was not partially written to the feedback buffer." << tcu::TestLog::EndMessage; 5685 5686 { 5687 const void* ptr = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(float[4]) * 5, GL_MAP_READ_BIT); 5688 std::vector<float> feedback; 5689 bool error = false; 5690 5691 GLU_EXPECT_NO_ERROR(gl.getError(), "mapBufferRange"); 5692 if (!ptr) 5693 throw tcu::TestError("mapBufferRange returned null"); 5694 5695 feedback.resize(5*4); 5696 deMemcpy(&feedback[0], ptr, sizeof(float[4]) * 5); 5697 5698 if (gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER) != GL_TRUE) 5699 throw tcu::TestError("unmapBuffer returned false"); 5700 5701 // Verify vertices 0 - 2 5702 for (int vertex = 0; vertex < 3; ++vertex) 5703 { 5704 for (int component = 0; component < 4; ++component) 5705 { 5706 if (feedback[vertex*4 + component] != 1.0f) 5707 { 5708 m_testCtx.getLog() 5709 << tcu::TestLog::Message 5710 << "Feedback buffer vertex " << vertex << ", component " << component << ": unexpected value, expected 1.0, got " << feedback[vertex*4 + component] 5711 << tcu::TestLog::EndMessage; 5712 error = true; 5713 } 5714 } 5715 } 5716 5717 // Verify vertices 3 - 4 5718 for (int vertex = 3; vertex < 5; ++vertex) 5719 { 5720 for (int component = 0; component < 4; ++component) 5721 { 5722 if (feedback[vertex*4 + component] != -1.0f) 5723 { 5724 m_testCtx.getLog() 5725 << tcu::TestLog::Message 5726 << "Feedback buffer vertex " << vertex << ", component " << component << ": unexpected value, expected -1.0, got " << feedback[vertex*4 + component] 5727 << tcu::TestLog::EndMessage; 5728 error = true; 5729 } 5730 } 5731 } 5732 5733 if (error) 5734 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Feedback result validation failed"); 5735 else 5736 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 5737 } 5738 5739 return STOP; 5740 } 5741 5742 glu::ShaderProgram* VertexFeedbackOverflowCase::genProgram (void) 5743 { 5744 static const char* const vertexSource = "#version 310 es\n" 5745 "in highp vec4 a_position;\n" 5746 "void main (void)\n" 5747 "{\n" 5748 " gl_Position = a_position;\n" 5749 "}\n"; 5750 static const char* const fragmentSource = "#version 310 es\n" 5751 "layout(location = 0) out mediump vec4 fragColor;\n" 5752 "void main (void)\n" 5753 "{\n" 5754 " fragColor = vec4(1.0);\n" 5755 "}\n"; 5756 5757 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() 5758 << glu::VertexSource(vertexSource) 5759 << glu::FragmentSource(fragmentSource) 5760 << glu::TransformFeedbackVarying("gl_Position") 5761 << glu::TransformFeedbackMode(GL_INTERLEAVED_ATTRIBS)); 5762 } 5763 5764 } // anonymous 5765 5766 GeometryShaderTests::GeometryShaderTests (Context& context) 5767 : TestCaseGroup(context, "geometry_shading", "Geometry shader tests") 5768 { 5769 } 5770 5771 GeometryShaderTests::~GeometryShaderTests (void) 5772 { 5773 } 5774 5775 void GeometryShaderTests::init (void) 5776 { 5777 struct PrimitiveTestSpec 5778 { 5779 deUint32 primitiveType; 5780 const char* name; 5781 deUint32 outputType; 5782 }; 5783 5784 struct EmitTestSpec 5785 { 5786 deUint32 outputType; 5787 int emitCountA; //!< primitive A emit count 5788 int endCountA; //!< primitive A end count 5789 int emitCountB; //!< 5790 int endCountB; //!< 5791 const char* name; 5792 }; 5793 5794 static const struct LayeredTarget 5795 { 5796 LayeredRenderCase::LayeredRenderTargetType target; 5797 const char* name; 5798 const char* desc; 5799 } layerTargets[] = 5800 { 5801 { LayeredRenderCase::TARGET_CUBE, "cubemap", "cubemap" }, 5802 { LayeredRenderCase::TARGET_3D, "3d", "3D texture" }, 5803 { LayeredRenderCase::TARGET_2D_ARRAY, "2d_array", "2D array texture" }, 5804 { LayeredRenderCase::TARGET_2D_MS_ARRAY, "2d_multisample_array", "2D multisample array texture" }, 5805 }; 5806 5807 tcu::TestCaseGroup* const queryGroup = new tcu::TestCaseGroup(m_testCtx, "query", "Query tests."); 5808 tcu::TestCaseGroup* const basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Basic tests."); 5809 tcu::TestCaseGroup* const inputPrimitiveGroup = new tcu::TestCaseGroup(m_testCtx, "input", "Different input primitives."); 5810 tcu::TestCaseGroup* const conversionPrimitiveGroup = new tcu::TestCaseGroup(m_testCtx, "conversion", "Different input and output primitives."); 5811 tcu::TestCaseGroup* const emitGroup = new tcu::TestCaseGroup(m_testCtx, "emit", "Different emit counts."); 5812 tcu::TestCaseGroup* const varyingGroup = new tcu::TestCaseGroup(m_testCtx, "varying", "Test varyings."); 5813 tcu::TestCaseGroup* const layeredGroup = new tcu::TestCaseGroup(m_testCtx, "layered", "Layered rendering."); 5814 tcu::TestCaseGroup* const instancedGroup = new tcu::TestCaseGroup(m_testCtx, "instanced", "Instanced rendering."); 5815 tcu::TestCaseGroup* const negativeGroup = new tcu::TestCaseGroup(m_testCtx, "negative", "Negative tests."); 5816 tcu::TestCaseGroup* const feedbackGroup = new tcu::TestCaseGroup(m_testCtx, "vertex_transform_feedback", "Transform feedback."); 5817 5818 this->addChild(queryGroup); 5819 this->addChild(basicGroup); 5820 this->addChild(inputPrimitiveGroup); 5821 this->addChild(conversionPrimitiveGroup); 5822 this->addChild(emitGroup); 5823 this->addChild(varyingGroup); 5824 this->addChild(layeredGroup); 5825 this->addChild(instancedGroup); 5826 this->addChild(negativeGroup); 5827 this->addChild(feedbackGroup); 5828 5829 // query test 5830 { 5831 // limits with a corresponding glsl constant 5832 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_input_components", "", GL_MAX_GEOMETRY_INPUT_COMPONENTS, "MaxGeometryInputComponents", 64)); 5833 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_output_components", "", GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, "MaxGeometryOutputComponents", 128)); 5834 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_image_uniforms", "", GL_MAX_GEOMETRY_IMAGE_UNIFORMS, "MaxGeometryImageUniforms", 0)); 5835 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_texture_image_units", "", GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, "MaxGeometryTextureImageUnits", 16)); 5836 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_output_vertices", "", GL_MAX_GEOMETRY_OUTPUT_VERTICES, "MaxGeometryOutputVertices", 256)); 5837 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_total_output_components", "", GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, "MaxGeometryTotalOutputComponents", 1024)); 5838 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_uniform_components", "", GL_MAX_GEOMETRY_UNIFORM_COMPONENTS, "MaxGeometryUniformComponents", 1024)); 5839 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_atomic_counters", "", GL_MAX_GEOMETRY_ATOMIC_COUNTERS, "MaxGeometryAtomicCounters", 0)); 5840 queryGroup->addChild(new GeometryProgramLimitCase(m_context, "max_geometry_atomic_counter_buffers", "", GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS, "MaxGeometryAtomicCounterBuffers", 0)); 5841 5842 // program queries 5843 queryGroup->addChild(new GeometryShaderVerticesQueryCase (m_context, "geometry_linked_vertices_out", "GL_GEOMETRY_LINKED_VERTICES_OUT")); 5844 queryGroup->addChild(new GeometryShaderInputQueryCase (m_context, "geometry_linked_input_type", "GL_GEOMETRY_LINKED_INPUT_TYPE")); 5845 queryGroup->addChild(new GeometryShaderOutputQueryCase (m_context, "geometry_linked_output_type", "GL_GEOMETRY_LINKED_OUTPUT_TYPE")); 5846 queryGroup->addChild(new GeometryShaderInvocationsQueryCase (m_context, "geometry_shader_invocations", "GL_GEOMETRY_SHADER_INVOCATIONS")); 5847 5848 // limits 5849 queryGroup->addChild(new ImplementationLimitCase(m_context, "max_geometry_shader_invocations", "", GL_MAX_GEOMETRY_SHADER_INVOCATIONS, 32)); 5850 queryGroup->addChild(new ImplementationLimitCase(m_context, "max_geometry_uniform_blocks", "", GL_MAX_GEOMETRY_UNIFORM_BLOCKS, 12)); 5851 queryGroup->addChild(new ImplementationLimitCase(m_context, "max_geometry_shader_storage_blocks", "", GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, 0)); 5852 5853 // layer_provoking_vertex_ext 5854 queryGroup->addChild(new LayerProvokingVertexQueryCase(m_context, "layer_provoking_vertex", "GL_LAYER_PROVOKING_VERTEX")); 5855 5856 // primitives_generated 5857 queryGroup->addChild(new PrimitivesGeneratedQueryCase(m_context, "primitives_generated_no_geometry", "PRIMITIVES_GENERATED query with no geometry shader", PrimitivesGeneratedQueryCase::TEST_NO_GEOMETRY)); 5858 queryGroup->addChild(new PrimitivesGeneratedQueryCase(m_context, "primitives_generated_no_amplification", "PRIMITIVES_GENERATED query with non amplifying geometry shader", PrimitivesGeneratedQueryCase::TEST_NO_AMPLIFICATION)); 5859 queryGroup->addChild(new PrimitivesGeneratedQueryCase(m_context, "primitives_generated_amplification", "PRIMITIVES_GENERATED query with amplifying geometry shader", PrimitivesGeneratedQueryCase::TEST_AMPLIFICATION)); 5860 queryGroup->addChild(new PrimitivesGeneratedQueryCase(m_context, "primitives_generated_partial_primitives", "PRIMITIVES_GENERATED query with geometry shader emitting partial primitives", PrimitivesGeneratedQueryCase::TEST_PARTIAL_PRIMITIVES)); 5861 queryGroup->addChild(new PrimitivesGeneratedQueryCase(m_context, "primitives_generated_instanced", "PRIMITIVES_GENERATED query with instanced geometry shader", PrimitivesGeneratedQueryCase::TEST_INSTANCED)); 5862 5863 // fbo 5864 queryGroup->addChild(new ImplementationLimitCase (m_context, "max_framebuffer_layers", "", GL_MAX_FRAMEBUFFER_LAYERS, 256)); 5865 queryGroup->addChild(new FramebufferDefaultLayersCase (m_context, "framebuffer_default_layers", "")); 5866 queryGroup->addChild(new FramebufferAttachmentLayeredCase (m_context, "framebuffer_attachment_layered", "")); 5867 queryGroup->addChild(new FramebufferIncompleteLayereTargetsCase (m_context, "framebuffer_incomplete_layer_targets", "")); 5868 5869 // resource query 5870 queryGroup->addChild(new ReferencedByGeometryShaderCase (m_context, "referenced_by_geometry_shader", "")); 5871 } 5872 5873 // basic tests 5874 { 5875 basicGroup->addChild(new OutputCountCase (m_context, "output_10", "Output 10 vertices", OutputCountPatternSpec(10))); 5876 basicGroup->addChild(new OutputCountCase (m_context, "output_128", "Output 128 vertices", OutputCountPatternSpec(128))); 5877 basicGroup->addChild(new OutputCountCase (m_context, "output_256", "Output 256 vertices", OutputCountPatternSpec(256))); 5878 basicGroup->addChild(new OutputCountCase (m_context, "output_max", "Output max vertices", OutputCountPatternSpec(-1))); 5879 basicGroup->addChild(new OutputCountCase (m_context, "output_10_and_100", "Output 10 and 100 vertices in two invocations", OutputCountPatternSpec(10, 100))); 5880 basicGroup->addChild(new OutputCountCase (m_context, "output_100_and_10", "Output 100 and 10 vertices in two invocations", OutputCountPatternSpec(100, 10))); 5881 basicGroup->addChild(new OutputCountCase (m_context, "output_0_and_128", "Output 0 and 128 vertices in two invocations", OutputCountPatternSpec(0, 128))); 5882 basicGroup->addChild(new OutputCountCase (m_context, "output_128_and_0", "Output 128 and 0 vertices in two invocations", OutputCountPatternSpec(128, 0))); 5883 5884 basicGroup->addChild(new VaryingOutputCountCase (m_context, "output_vary_by_attribute", "Output varying number of vertices", VaryingOutputCountShader::READ_ATTRIBUTE, VaryingOutputCountCase::MODE_WITHOUT_INSTANCING)); 5885 basicGroup->addChild(new VaryingOutputCountCase (m_context, "output_vary_by_uniform", "Output varying number of vertices", VaryingOutputCountShader::READ_UNIFORM, VaryingOutputCountCase::MODE_WITHOUT_INSTANCING)); 5886 basicGroup->addChild(new VaryingOutputCountCase (m_context, "output_vary_by_texture", "Output varying number of vertices", VaryingOutputCountShader::READ_TEXTURE, VaryingOutputCountCase::MODE_WITHOUT_INSTANCING)); 5887 5888 basicGroup->addChild(new BuiltinVariableRenderTest (m_context, "point_size", "test gl_PointSize", BuiltinVariableShader::TEST_POINT_SIZE)); 5889 basicGroup->addChild(new BuiltinVariableRenderTest (m_context, "primitive_id_in", "test gl_PrimitiveIDIn", BuiltinVariableShader::TEST_PRIMITIVE_ID_IN)); 5890 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)); 5891 basicGroup->addChild(new BuiltinVariableRenderTest (m_context, "primitive_id", "test gl_PrimitiveID", BuiltinVariableShader::TEST_PRIMITIVE_ID)); 5892 } 5893 5894 // input primitives 5895 { 5896 static const PrimitiveTestSpec inputPrimitives[] = 5897 { 5898 { GL_POINTS, "points", GL_POINTS }, 5899 { GL_LINES, "lines", GL_LINE_STRIP }, 5900 { GL_LINE_LOOP, "line_loop", GL_LINE_STRIP }, 5901 { GL_LINE_STRIP, "line_strip", GL_LINE_STRIP }, 5902 { GL_TRIANGLES, "triangles", GL_TRIANGLE_STRIP }, 5903 { GL_TRIANGLE_STRIP, "triangle_strip", GL_TRIANGLE_STRIP }, 5904 { GL_TRIANGLE_FAN, "triangle_fan", GL_TRIANGLE_STRIP }, 5905 { GL_LINES_ADJACENCY, "lines_adjacency", GL_LINE_STRIP }, 5906 { GL_LINE_STRIP_ADJACENCY, "line_strip_adjacency", GL_LINE_STRIP }, 5907 { GL_TRIANGLES_ADJACENCY, "triangles_adjacency", GL_TRIANGLE_STRIP } 5908 }; 5909 5910 tcu::TestCaseGroup* const basicPrimitiveGroup = new tcu::TestCaseGroup(m_testCtx, "basic_primitive", "Different input and output primitives."); 5911 tcu::TestCaseGroup* const triStripAdjacencyGroup = new tcu::TestCaseGroup(m_testCtx, "triangle_strip_adjacency", "Different triangle_strip_adjacency vertex counts."); 5912 5913 // more basic types 5914 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(inputPrimitives); ++ndx) 5915 basicPrimitiveGroup->addChild(new GeometryExpanderRenderTest(m_context, inputPrimitives[ndx].name, inputPrimitives[ndx].name, inputPrimitives[ndx].primitiveType, inputPrimitives[ndx].outputType)); 5916 5917 // triangle strip adjacency with different vtx counts 5918 for (int vtxCount = 0; vtxCount <= 12; ++vtxCount) 5919 { 5920 const std::string name = "vertex_count_" + de::toString(vtxCount); 5921 const std::string desc = "Vertex count is " + de::toString(vtxCount); 5922 5923 triStripAdjacencyGroup->addChild(new TriangleStripAdjacencyVertexCountTest(m_context, name.c_str(), desc.c_str(), vtxCount)); 5924 } 5925 5926 inputPrimitiveGroup->addChild(basicPrimitiveGroup); 5927 inputPrimitiveGroup->addChild(triStripAdjacencyGroup); 5928 } 5929 5930 // different type conversions 5931 { 5932 static const PrimitiveTestSpec conversionPrimitives[] = 5933 { 5934 { GL_TRIANGLES, "triangles_to_points", GL_POINTS }, 5935 { GL_LINES, "lines_to_points", GL_POINTS }, 5936 { GL_POINTS, "points_to_lines", GL_LINE_STRIP }, 5937 { GL_TRIANGLES, "triangles_to_lines", GL_LINE_STRIP }, 5938 { GL_POINTS, "points_to_triangles", GL_TRIANGLE_STRIP }, 5939 { GL_LINES, "lines_to_triangles", GL_TRIANGLE_STRIP } 5940 }; 5941 5942 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(conversionPrimitives); ++ndx) 5943 conversionPrimitiveGroup->addChild(new GeometryExpanderRenderTest(m_context, conversionPrimitives[ndx].name, conversionPrimitives[ndx].name, conversionPrimitives[ndx].primitiveType, conversionPrimitives[ndx].outputType)); 5944 } 5945 5946 // emit different amounts 5947 { 5948 static const EmitTestSpec emitTests[] = 5949 { 5950 { GL_POINTS, 0, 0, 0, 0, "points" }, 5951 { GL_POINTS, 0, 1, 0, 0, "points" }, 5952 { GL_POINTS, 1, 1, 0, 0, "points" }, 5953 { GL_POINTS, 0, 2, 0, 0, "points" }, 5954 { GL_POINTS, 1, 2, 0, 0, "points" }, 5955 { GL_LINE_STRIP, 0, 0, 0, 0, "line_strip" }, 5956 { GL_LINE_STRIP, 0, 1, 0, 0, "line_strip" }, 5957 { GL_LINE_STRIP, 1, 1, 0, 0, "line_strip" }, 5958 { GL_LINE_STRIP, 2, 1, 0, 0, "line_strip" }, 5959 { GL_LINE_STRIP, 0, 2, 0, 0, "line_strip" }, 5960 { GL_LINE_STRIP, 1, 2, 0, 0, "line_strip" }, 5961 { GL_LINE_STRIP, 2, 2, 0, 0, "line_strip" }, 5962 { GL_LINE_STRIP, 2, 2, 2, 0, "line_strip" }, 5963 { GL_TRIANGLE_STRIP, 0, 0, 0, 0, "triangle_strip" }, 5964 { GL_TRIANGLE_STRIP, 0, 1, 0, 0, "triangle_strip" }, 5965 { GL_TRIANGLE_STRIP, 1, 1, 0, 0, "triangle_strip" }, 5966 { GL_TRIANGLE_STRIP, 2, 1, 0, 0, "triangle_strip" }, 5967 { GL_TRIANGLE_STRIP, 3, 1, 0, 0, "triangle_strip" }, 5968 { GL_TRIANGLE_STRIP, 0, 2, 0, 0, "triangle_strip" }, 5969 { GL_TRIANGLE_STRIP, 1, 2, 0, 0, "triangle_strip" }, 5970 { GL_TRIANGLE_STRIP, 2, 2, 0, 0, "triangle_strip" }, 5971 { GL_TRIANGLE_STRIP, 3, 2, 0, 0, "triangle_strip" }, 5972 { GL_TRIANGLE_STRIP, 3, 2, 3, 0, "triangle_strip" }, 5973 }; 5974 5975 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(emitTests); ++ndx) 5976 { 5977 std::string name = std::string(emitTests[ndx].name) + "_emit_" + de::toString(emitTests[ndx].emitCountA) + "_end_" + de::toString(emitTests[ndx].endCountA); 5978 std::string desc = std::string(emitTests[ndx].name) + " output, emit " + de::toString(emitTests[ndx].emitCountA) + " vertices, call EndPrimitive " + de::toString(emitTests[ndx].endCountA) + " times"; 5979 5980 if (emitTests[ndx].emitCountB) 5981 { 5982 name += "_emit_" + de::toString(emitTests[ndx].emitCountB) + "_end_" + de::toString(emitTests[ndx].endCountB); 5983 desc += ", emit " + de::toString(emitTests[ndx].emitCountB) + " vertices, call EndPrimitive " + de::toString(emitTests[ndx].endCountB) + " times"; 5984 } 5985 5986 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)); 5987 } 5988 } 5989 5990 // varying 5991 { 5992 struct VaryingTestSpec 5993 { 5994 int vertexOutputs; 5995 int geometryOutputs; 5996 const char* name; 5997 const char* desc; 5998 }; 5999 6000 static const VaryingTestSpec varyingTests[] = 6001 { 6002 { -1, 1, "vertex_no_op_geometry_out_1", "vertex_no_op_geometry_out_1" }, 6003 { 0, 1, "vertex_out_0_geometry_out_1", "vertex_out_0_geometry_out_1" }, 6004 { 0, 2, "vertex_out_0_geometry_out_2", "vertex_out_0_geometry_out_2" }, 6005 { 1, 0, "vertex_out_1_geometry_out_0", "vertex_out_1_geometry_out_0" }, 6006 { 1, 2, "vertex_out_1_geometry_out_2", "vertex_out_1_geometry_out_2" }, 6007 }; 6008 6009 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(varyingTests); ++ndx) 6010 varyingGroup->addChild(new VaryingTest(m_context, varyingTests[ndx].name, varyingTests[ndx].desc, varyingTests[ndx].vertexOutputs, varyingTests[ndx].geometryOutputs)); 6011 } 6012 6013 // layered 6014 { 6015 static const struct TestType 6016 { 6017 LayeredRenderCase::TestType test; 6018 const char* testPrefix; 6019 const char* descPrefix; 6020 } tests[] = 6021 { 6022 { LayeredRenderCase::TEST_DEFAULT_LAYER, "render_with_default_layer_", "Render to all layers of " }, 6023 { LayeredRenderCase::TEST_SINGLE_LAYER, "render_to_one_", "Render to one layer of " }, 6024 { LayeredRenderCase::TEST_ALL_LAYERS, "render_to_all_", "Render to all layers of " }, 6025 { LayeredRenderCase::TEST_DIFFERENT_LAYERS, "render_different_to_", "Render different data to different layers" }, 6026 { LayeredRenderCase::TEST_LAYER_ID, "fragment_layer_", "Read gl_Layer in fragment shader" }, 6027 { LayeredRenderCase::TEST_LAYER_PROVOKING_VERTEX, "layer_provoking_vertex_", "Verify LAYER_PROVOKING_VERTEX" }, 6028 }; 6029 6030 for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx) 6031 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(layerTargets); ++targetNdx) 6032 { 6033 const std::string name = std::string(tests[testNdx].testPrefix) + layerTargets[targetNdx].name; 6034 const std::string desc = std::string(tests[testNdx].descPrefix) + layerTargets[targetNdx].desc; 6035 6036 layeredGroup->addChild(new LayeredRenderCase(m_context, name.c_str(), desc.c_str(), layerTargets[targetNdx].target, tests[testNdx].test)); 6037 } 6038 } 6039 6040 // instanced 6041 { 6042 static const struct InvocationCase 6043 { 6044 const char* name; 6045 int numInvocations; 6046 } invocationCases[] = 6047 { 6048 { "1", 1 }, 6049 { "2", 2 }, 6050 { "8", 8 }, 6051 { "32", 32 }, 6052 { "max", -1 }, 6053 }; 6054 static const int numDrawInstances[] = { 2, 4, 8 }; 6055 static const int numDrawInvocations[] = { 2, 8 }; 6056 6057 // same amount of content to all invocations 6058 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(invocationCases); ++ndx) 6059 instancedGroup->addChild(new GeometryInvocationCase(m_context, 6060 (std::string("geometry_") + invocationCases[ndx].name + "_invocations").c_str(), 6061 (std::string("Geometry shader with ") + invocationCases[ndx].name + " invocation(s)").c_str(), 6062 invocationCases[ndx].numInvocations, 6063 GeometryInvocationCase::CASE_FIXED_OUTPUT_COUNTS)); 6064 6065 // different amount of content to each invocation 6066 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(invocationCases); ++ndx) 6067 if (invocationCases[ndx].numInvocations != 1) 6068 instancedGroup->addChild(new GeometryInvocationCase(m_context, 6069 (std::string("geometry_output_different_") + invocationCases[ndx].name + "_invocations").c_str(), 6070 "Geometry shader invocation(s) with different emit counts", 6071 invocationCases[ndx].numInvocations, 6072 GeometryInvocationCase::CASE_DIFFERENT_OUTPUT_COUNTS)); 6073 6074 // invocation per layer 6075 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(layerTargets); ++targetNdx) 6076 { 6077 const std::string name = std::string("invocation_per_layer_") + layerTargets[targetNdx].name; 6078 const std::string desc = std::string("Render to multiple layers with multiple invocations, one invocation per layer, target ") + layerTargets[targetNdx].desc; 6079 6080 instancedGroup->addChild(new LayeredRenderCase(m_context, name.c_str(), desc.c_str(), layerTargets[targetNdx].target, LayeredRenderCase::TEST_INVOCATION_PER_LAYER)); 6081 } 6082 6083 // multiple layers per invocation 6084 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(layerTargets); ++targetNdx) 6085 { 6086 const std::string name = std::string("multiple_layers_per_invocation_") + layerTargets[targetNdx].name; 6087 const std::string desc = std::string("Render to multiple layers with multiple invocations, multiple layers per invocation, target ") + layerTargets[targetNdx].desc; 6088 6089 instancedGroup->addChild(new LayeredRenderCase(m_context, name.c_str(), desc.c_str(), layerTargets[targetNdx].target, LayeredRenderCase::TEST_MULTIPLE_LAYERS_PER_INVOCATION)); 6090 } 6091 6092 // different invocation output counts depending on {uniform, attrib, texture} 6093 instancedGroup->addChild(new VaryingOutputCountCase(m_context, "invocation_output_vary_by_attribute", "Output varying number of vertices", VaryingOutputCountShader::READ_ATTRIBUTE, VaryingOutputCountCase::MODE_WITH_INSTANCING)); 6094 instancedGroup->addChild(new VaryingOutputCountCase(m_context, "invocation_output_vary_by_uniform", "Output varying number of vertices", VaryingOutputCountShader::READ_UNIFORM, VaryingOutputCountCase::MODE_WITH_INSTANCING)); 6095 instancedGroup->addChild(new VaryingOutputCountCase(m_context, "invocation_output_vary_by_texture", "Output varying number of vertices", VaryingOutputCountShader::READ_TEXTURE, VaryingOutputCountCase::MODE_WITH_INSTANCING)); 6096 6097 // with drawInstanced 6098 for (int instanceNdx = 0; instanceNdx < DE_LENGTH_OF_ARRAY(numDrawInstances); ++instanceNdx) 6099 for (int invocationNdx = 0; invocationNdx < DE_LENGTH_OF_ARRAY(numDrawInvocations); ++invocationNdx) 6100 { 6101 const std::string name = std::string("draw_") + de::toString(numDrawInstances[instanceNdx]) + "_instances_geometry_" + de::toString(numDrawInvocations[invocationNdx]) + "_invocations"; 6102 const std::string desc = std::string("Draw ") + de::toString(numDrawInstances[instanceNdx]) + " instances, with " + de::toString(numDrawInvocations[invocationNdx]) + " geometry shader invocations."; 6103 6104 instancedGroup->addChild(new DrawInstancedGeometryInstancedCase(m_context, name.c_str(), desc.c_str(), numDrawInstances[instanceNdx], numDrawInvocations[invocationNdx])); 6105 } 6106 } 6107 6108 // negative (wrong types) 6109 { 6110 struct PrimitiveToInputTypeConversion 6111 { 6112 GLenum inputType; 6113 GLenum primitiveType; 6114 }; 6115 6116 static const PrimitiveToInputTypeConversion legalConversions[] = 6117 { 6118 { GL_POINTS, GL_POINTS }, 6119 { GL_LINES, GL_LINES }, 6120 { GL_LINES, GL_LINE_LOOP }, 6121 { GL_LINES, GL_LINE_STRIP }, 6122 { GL_LINES_ADJACENCY, GL_LINES_ADJACENCY }, 6123 { GL_LINES_ADJACENCY, GL_LINE_STRIP_ADJACENCY }, 6124 { GL_TRIANGLES, GL_TRIANGLES }, 6125 { GL_TRIANGLES, GL_TRIANGLE_STRIP }, 6126 { GL_TRIANGLES, GL_TRIANGLE_FAN }, 6127 { GL_TRIANGLES_ADJACENCY, GL_TRIANGLES_ADJACENCY }, 6128 { GL_TRIANGLES_ADJACENCY, GL_TRIANGLE_STRIP_ADJACENCY }, 6129 }; 6130 6131 static const GLenum inputTypes[] = 6132 { 6133 GL_POINTS, 6134 GL_LINES, 6135 GL_LINES_ADJACENCY, 6136 GL_TRIANGLES, 6137 GL_TRIANGLES_ADJACENCY 6138 }; 6139 6140 static const GLenum primitiveTypes[] = 6141 { 6142 GL_POINTS, 6143 GL_LINES, 6144 GL_LINE_LOOP, 6145 GL_LINE_STRIP, 6146 GL_LINES_ADJACENCY, 6147 GL_LINE_STRIP_ADJACENCY, 6148 GL_TRIANGLES, 6149 GL_TRIANGLE_STRIP, 6150 GL_TRIANGLE_FAN, 6151 GL_TRIANGLES_ADJACENCY, 6152 GL_TRIANGLE_STRIP_ADJACENCY 6153 }; 6154 6155 for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); ++inputTypeNdx) 6156 for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveTypeNdx) 6157 { 6158 const GLenum inputType = inputTypes[inputTypeNdx]; 6159 const GLenum primitiveType = primitiveTypes[primitiveTypeNdx]; 6160 const std::string name = std::string("type_") + inputTypeToGLString(sglr::rr_util::mapGLGeometryShaderInputType(inputType)) + "_primitive_" + primitiveTypeToString(primitiveType); 6161 const std::string desc = std::string("Shader input type ") + inputTypeToGLString(sglr::rr_util::mapGLGeometryShaderInputType(inputType)) + ", draw primitive type " + primitiveTypeToString(primitiveType); 6162 6163 bool isLegal = false; 6164 6165 for (int legalNdx = 0; legalNdx < DE_LENGTH_OF_ARRAY(legalConversions); ++legalNdx) 6166 if (legalConversions[legalNdx].inputType == inputType && legalConversions[legalNdx].primitiveType == primitiveType) 6167 isLegal = true; 6168 6169 // only illegal 6170 if (!isLegal) 6171 negativeGroup->addChild(new NegativeDrawCase(m_context, name.c_str(), desc.c_str(), inputType, primitiveType)); 6172 } 6173 } 6174 6175 // vertex transform feedback 6176 { 6177 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_line_loop", "Capture line loop lines", VertexFeedbackCase::METHOD_DRAW_ARRAYS, VertexFeedbackCase::PRIMITIVE_LINE_LOOP)); 6178 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_line_strip", "Capture line strip lines", VertexFeedbackCase::METHOD_DRAW_ARRAYS, VertexFeedbackCase::PRIMITIVE_LINE_STRIP)); 6179 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_triangle_strip", "Capture triangle strip triangles", VertexFeedbackCase::METHOD_DRAW_ARRAYS, VertexFeedbackCase::PRIMITIVE_TRIANGLE_STRIP)); 6180 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_triangle_fan", "Capture triangle fan triangles", VertexFeedbackCase::METHOD_DRAW_ARRAYS, VertexFeedbackCase::PRIMITIVE_TRIANGLE_FAN)); 6181 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_draw_arrays", "Capture primitives generated with drawArrays", VertexFeedbackCase::METHOD_DRAW_ARRAYS, VertexFeedbackCase::PRIMITIVE_POINTS)); 6182 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_draw_arrays_instanced", "Capture primitives generated with drawArraysInstanced", VertexFeedbackCase::METHOD_DRAW_ARRAYS_INSTANCED, VertexFeedbackCase::PRIMITIVE_POINTS)); 6183 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_draw_arrays_indirect", "Capture primitives generated with drawArraysIndirect", VertexFeedbackCase::METHOD_DRAW_ARRAYS_INDIRECT, VertexFeedbackCase::PRIMITIVE_POINTS)); 6184 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_draw_elements", "Capture primitives generated with drawElements", VertexFeedbackCase::METHOD_DRAW_ELEMENTS, VertexFeedbackCase::PRIMITIVE_POINTS)); 6185 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_draw_elements_instanced", "Capture primitives generated with drawElementsInstanced", VertexFeedbackCase::METHOD_DRAW_ELEMENTS_INSTANCED, VertexFeedbackCase::PRIMITIVE_POINTS)); 6186 feedbackGroup->addChild(new VertexFeedbackCase(m_context, "capture_vertex_draw_elements_indirect", "Capture primitives generated with drawElementsIndirect", VertexFeedbackCase::METHOD_DRAW_ELEMENTS_INDIRECT, VertexFeedbackCase::PRIMITIVE_POINTS)); 6187 6188 feedbackGroup->addChild(new VertexFeedbackOverflowCase(m_context, "capture_vertex_draw_arrays_overflow_single_buffer", "Capture triangles to too small a buffer", VertexFeedbackOverflowCase::METHOD_DRAW_ARRAYS)); 6189 feedbackGroup->addChild(new VertexFeedbackOverflowCase(m_context, "capture_vertex_draw_elements_overflow_single_buffer", "Capture triangles to too small a buffer", VertexFeedbackOverflowCase::METHOD_DRAW_ELEMENTS)); 6190 } 6191 } 6192 6193 } // Functional 6194 } // gles31 6195 } // deqp 6196