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