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