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 56 using namespace glw; 57 58 namespace deqp 59 { 60 namespace gles31 61 { 62 namespace Functional 63 { 64 namespace 65 { 66 67 using namespace gls::StateQueryUtil; 68 69 const int TEST_CANVAS_SIZE = 256; 70 71 static 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"; 81 static 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"; 88 static 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 118 static 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 129 std::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 144 std::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 157 std::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 178 struct OutputCountPatternSpec 179 { 180 OutputCountPatternSpec (int count); 181 OutputCountPatternSpec (int count0, int count1); 182 183 std::vector<int> pattern; 184 }; 185 186 OutputCountPatternSpec::OutputCountPatternSpec (int count) 187 { 188 pattern.push_back(count); 189 } 190 191 OutputCountPatternSpec::OutputCountPatternSpec (int count0, int count1) 192 { 193 pattern.push_back(count0); 194 pattern.push_back(count1); 195 } 196 197 class VertexExpanderShader : public sglr::ShaderProgram 198 { 199 public: 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 206 private: 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 211 VertexExpanderShader::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 225 void 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 235 void 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 242 void 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 267 size_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 282 std::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 296 class VertexEmitterShader : public sglr::ShaderProgram 297 { 298 public: 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 305 private: 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 314 VertexEmitterShader::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 332 void 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 342 void 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 349 void 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 383 std::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 431 class VertexVaryingShader : public sglr::ShaderProgram 432 { 433 public: 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 440 private: 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 447 VertexVaryingShader::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 454 void 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 487 void 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 515 void 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 610 sglr::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 781 class OutputCountShader : public sglr::ShaderProgram 782 { 783 public: 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 790 private: 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 799 OutputCountShader::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 816 void 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 826 void 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 833 void 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 856 std::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 901 size_t OutputCountShader::getPatternEmitCount (const OutputCountPatternSpec& spec) const 902 { 903 return *std::max_element(spec.pattern.begin(), spec.pattern.end()); 904 } 905 906 class BuiltinVariableShader : public sglr::ShaderProgram 907 { 908 public: 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 926 private: 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 934 BuiltinVariableShader::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 951 void 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 961 void 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 987 void 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 1034 const 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 1047 std::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 1126 std::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 1158 std::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 1188 class VaryingOutputCountShader : public sglr::ShaderProgram 1189 { 1190 public: 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 1216 private: 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 1227 VaryingOutputCountShader::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 1251 void 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 1260 void 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 1267 void 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 1342 const 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 1355 std::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 1445 std::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 1477 class InvocationCountShader : public sglr::ShaderProgram 1478 { 1479 public: 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 1490 private: 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 1502 InvocationCountShader::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 1521 void 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 1530 void 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 1537 void 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 1590 std::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 1656 size_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 1668 class InstancedExpansionShader : public sglr::ShaderProgram 1669 { 1670 public: 1671 InstancedExpansionShader (const glu::ContextType& contextType, int numInvocations); 1672 1673 private: 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 1685 InstancedExpansionShader::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 1701 void 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 1710 void 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 1719 void 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 1737 std::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 1752 std::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 1766 std::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 1792 class GeometryShaderRenderTest : public TestCase 1793 { 1794 public: 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 1813 protected: 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 1843 GeometryShaderRenderTest::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 1866 GeometryShaderRenderTest::~GeometryShaderRenderTest (void) 1867 { 1868 deinit(); 1869 } 1870 1871 void 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 1890 void 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 1907 tcu::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 1950 bool 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 2020 void 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 2048 void 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 2151 void GeometryShaderRenderTest::preRender (sglr::Context& ctx, GLuint programID) 2152 { 2153 DE_UNREF(ctx); 2154 DE_UNREF(programID); 2155 } 2156 2157 void GeometryShaderRenderTest::postRender (sglr::Context& ctx, GLuint programID) 2158 { 2159 DE_UNREF(ctx); 2160 DE_UNREF(programID); 2161 } 2162 2163 class GeometryExpanderRenderTest : public GeometryShaderRenderTest 2164 { 2165 public: 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 2171 private: 2172 void init (void); 2173 void deinit (void); 2174 VertexExpanderShader* m_program; 2175 }; 2176 2177 GeometryExpanderRenderTest::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 2183 GeometryExpanderRenderTest::~GeometryExpanderRenderTest (void) 2184 { 2185 } 2186 2187 void 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 2194 void 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 2205 sglr::ShaderProgram& GeometryExpanderRenderTest::getProgram (void) 2206 { 2207 return *m_program; 2208 } 2209 2210 class EmitTest : public GeometryShaderRenderTest 2211 { 2212 public: 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); 2216 private: 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 2229 EmitTest::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 2240 void 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 2247 void 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 2258 sglr::ShaderProgram& EmitTest::getProgram (void) 2259 { 2260 return *m_program; 2261 } 2262 2263 void 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 2274 class VaryingTest : public GeometryShaderRenderTest 2275 { 2276 public: 2277 VaryingTest (Context& context, const char* name, const char* desc, int vertexOut, int geometryOut); 2278 2279 sglr::ShaderProgram& getProgram (void); 2280 private: 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 2290 VaryingTest::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 2298 void VaryingTest::init (void) 2299 { 2300 m_program = new VertexVaryingShader(m_context.getRenderContext().getType(), m_vertexOut, m_geometryOut); 2301 2302 GeometryShaderRenderTest::init(); 2303 } 2304 2305 void 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 2316 sglr::ShaderProgram& VaryingTest::getProgram (void) 2317 { 2318 return *m_program; 2319 } 2320 2321 void 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 2336 class TriangleStripAdjacencyVertexCountTest : public GeometryExpanderRenderTest 2337 { 2338 public: 2339 TriangleStripAdjacencyVertexCountTest (Context& context, const char* name, const char* desc, int numInputVertices); 2340 2341 private: 2342 void genVertexAttribData (void); 2343 2344 int m_numInputVertices; 2345 }; 2346 2347 TriangleStripAdjacencyVertexCountTest::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 2353 void TriangleStripAdjacencyVertexCountTest::genVertexAttribData (void) 2354 { 2355 this->GeometryShaderRenderTest::genVertexAttribData(); 2356 m_numDrawVertices = m_numInputVertices; 2357 } 2358 2359 class NegativeDrawCase : public TestCase 2360 { 2361 public: 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 2370 private: 2371 sglr::Context* m_ctx; 2372 VertexExpanderShader* m_program; 2373 GLenum m_inputType; 2374 GLenum m_inputPrimitives; 2375 }; 2376 2377 NegativeDrawCase::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 2386 NegativeDrawCase::~NegativeDrawCase (void) 2387 { 2388 deinit(); 2389 } 2390 2391 void 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 2400 void NegativeDrawCase::deinit (void) 2401 { 2402 delete m_ctx; 2403 delete m_program; 2404 2405 m_ctx = NULL; 2406 m_program = DE_NULL; 2407 } 2408 2409 NegativeDrawCase::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 2461 class OutputCountCase : public GeometryShaderRenderTest 2462 { 2463 public: 2464 OutputCountCase (Context& context, const char* name, const char* desc, const OutputCountPatternSpec&); 2465 private: 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 2477 OutputCountCase::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 2485 void 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 2541 void 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 2552 sglr::ShaderProgram& OutputCountCase::getProgram (void) 2553 { 2554 return *m_program; 2555 } 2556 2557 void 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 2571 class BuiltinVariableRenderTest : public GeometryShaderRenderTest 2572 { 2573 public: 2574 BuiltinVariableRenderTest (Context& context, const char* name, const char* desc, BuiltinVariableShader::VariableTest test, int flags = 0); 2575 2576 private: 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 2587 BuiltinVariableRenderTest::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 2594 void 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 2617 void 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 2629 sglr::ShaderProgram& BuiltinVariableRenderTest::getProgram (void) 2630 { 2631 return *m_program; 2632 } 2633 2634 void 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 2658 class LayeredRenderCase : public TestCase 2659 { 2660 public: 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 2691 private: 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 2733 LayeredRenderCase::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 2752 LayeredRenderCase::~LayeredRenderCase (void) 2753 { 2754 deinit(); 2755 } 2756 2757 void 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 2799 void 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 2820 LayeredRenderCase::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 2917 void 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 2994 void 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 3010 void 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 3030 void 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 3059 std::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 3078 std::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 3297 std::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 3360 void 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 3384 void 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 3437 bool 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 3510 bool 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 3574 bool 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 3606 bool 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 3636 int 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 3651 glw::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 3666 tcu::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 3681 tcu::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 3696 class VaryingOutputCountCase : public GeometryShaderRenderTest 3697 { 3698 public: 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); 3707 private: 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 3723 VaryingOutputCountCase::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 3733 void 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 3798 void 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 3809 void 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 3846 sglr::ShaderProgram& VaryingOutputCountCase::getProgram (void) 3847 { 3848 return *m_program; 3849 } 3850 3851 void 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 3861 void 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 3889 void 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 3917 class GeometryProgramQueryCase : public TestCase 3918 { 3919 public: 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 3932 private: 3933 void expectProgramValue (deUint32 program, int value); 3934 void expectQueryError (deUint32 program); 3935 3936 const glw::GLenum m_target; 3937 3938 protected: 3939 std::vector<ProgramCase> m_cases; 3940 }; 3941 3942 GeometryProgramQueryCase::GeometryProgramQueryCase (Context& context, const char* name, const char* description, glw::