Merge "Fix error double accounting in fuzzyCompare()" am: 0cf17c4bf8
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / tessellation / vktTessellationGeometryPointSizeTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2014 The Android Open Source Project
6  * Copyright (c) 2016 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22 * \brief Tessellation Geometry Interaction - Point Size
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktTessellationGeometryPassthroughTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTessellationUtil.hpp"
28
29 #include "tcuTestLog.hpp"
30
31 #include "vkDefs.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkBuilderUtil.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkImageUtil.hpp"
36
37 #include "deUniquePtr.hpp"
38
39 #include <string>
40 #include <vector>
41
42 namespace vkt
43 {
44 namespace tessellation
45 {
46
47 using namespace vk;
48
49 namespace
50 {
51
52 enum Constants
53 {
54         RENDER_SIZE = 32,
55 };
56
57 enum FlagBits
58 {
59         FLAG_VERTEX_SET                                         = 1u << 0,              // !< set gl_PointSize in vertex shader
60         FLAG_TESSELLATION_EVALUATION_SET        = 1u << 1,              // !< set gl_PointSize in tessellation evaluation shader
61         FLAG_TESSELLATION_ADD                           = 1u << 2,              // !< read and add to gl_PointSize in tessellation shader pair
62         FLAG_GEOMETRY_SET                                       = 1u << 3,              // !< set gl_PointSize in geometry shader
63         FLAG_GEOMETRY_ADD                                       = 1u << 4,              // !< read and add to gl_PointSize in geometry shader
64 };
65 typedef deUint32 Flags;
66
67 void checkPointSizeRequirements (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const int maxPointSize)
68 {
69         const VkPhysicalDeviceProperties properties = getPhysicalDeviceProperties(vki, physDevice);
70         if (maxPointSize > static_cast<int>(properties.limits.pointSizeRange[1]))
71                 throw tcu::NotSupportedError("Test requires point size " + de::toString(maxPointSize));
72         // Point size granularity must be 1.0 at most, so no need to check it for this test.
73 }
74
75 int getExpectedPointSize (const Flags flags)
76 {
77         int addition = 0;
78
79         // geometry
80         if (flags & FLAG_GEOMETRY_SET)
81                 return 6;
82         else if (flags & FLAG_GEOMETRY_ADD)
83                 addition += 2;
84
85         // tessellation
86         if (flags & FLAG_TESSELLATION_EVALUATION_SET)
87                 return 4 + addition;
88         else if (flags & FLAG_TESSELLATION_ADD)
89                 addition += 2;
90
91         // vertex
92         if (flags & FLAG_VERTEX_SET)
93                 return 2 + addition;
94
95         // undefined
96         DE_ASSERT(false);
97         return -1;
98 }
99
100 inline bool isTessellationStage (const Flags flags)
101 {
102         return (flags & (FLAG_TESSELLATION_EVALUATION_SET | FLAG_TESSELLATION_ADD)) != 0;
103 }
104
105 inline bool isGeometryStage (const Flags flags)
106 {
107         return (flags & (FLAG_GEOMETRY_SET | FLAG_GEOMETRY_ADD)) != 0;
108 }
109
110 bool verifyImage (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image, const int expectedSize)
111 {
112         log << tcu::TestLog::Message << "Verifying rendered point size. Expecting " << expectedSize << " pixels." << tcu::TestLog::EndMessage;
113
114         bool                    resultAreaFound = false;
115         tcu::IVec4              resultArea;
116         const tcu::Vec4 black(0.0, 0.0, 0.0, 1.0);
117
118         // Find rasterization output area
119
120         for (int y = 0; y < image.getHeight(); ++y)
121         for (int x = 0; x < image.getWidth();  ++x)
122                 if (image.getPixel(x, y) != black)
123                 {
124                         if (!resultAreaFound)
125                         {
126                                 // first fragment
127                                 resultArea = tcu::IVec4(x, y, x + 1, y + 1);
128                                 resultAreaFound = true;
129                         }
130                         else
131                         {
132                                 // union area
133                                 resultArea.x() = de::min(resultArea.x(), x);
134                                 resultArea.y() = de::min(resultArea.y(), y);
135                                 resultArea.z() = de::max(resultArea.z(), x+1);
136                                 resultArea.w() = de::max(resultArea.w(), y+1);
137                         }
138                 }
139
140         if (!resultAreaFound)
141         {
142                 log << tcu::TestLog::Message << "Verification failed, could not find any point fragments." << tcu::TestLog::EndMessage;
143                 return false;
144         }
145
146         const tcu::IVec2 pointSize = resultArea.swizzle(2,3) - resultArea.swizzle(0, 1);
147
148         if (pointSize.x() != pointSize.y())
149         {
150                 log << tcu::TestLog::Message << "ERROR! Rasterized point is not a square. Point size was " << pointSize << tcu::TestLog::EndMessage;
151                 return false;
152         }
153
154         if (pointSize.x() != expectedSize)
155         {
156                 log << tcu::TestLog::Message << "ERROR! Point size invalid, expected " << expectedSize << ", got " << pointSize.x() << tcu::TestLog::EndMessage;
157                 return false;
158         }
159
160         return true;
161 }
162
163 void initPrograms (vk::SourceCollections& programCollection, const Flags flags)
164 {
165         // Vertex shader
166         {
167                 std::ostringstream src;
168                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
169                         << "\n"
170                         << "void main (void)\n"
171                         << "{\n"
172                         << "    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n";
173
174                 if (flags & FLAG_VERTEX_SET)
175                         src << "    gl_PointSize = 2.0;\n";
176
177                 src << "}\n";
178
179                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
180         }
181
182         // Fragment shader
183         {
184                 std::ostringstream src;
185                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
186                         << "layout(location = 0) out mediump vec4 fragColor;\n"
187                         << "\n"
188                         << "void main (void)\n"
189                         << "{\n"
190                         << "    fragColor = vec4(1.0);\n"
191                         << "}\n";
192
193                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
194         }
195
196         if (isTessellationStage(flags))
197         {
198                 // Tessellation control shader
199                 {
200                         std::ostringstream src;
201                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
202                                 << "#extension GL_EXT_tessellation_shader : require\n"
203                                 << "#extension GL_EXT_tessellation_point_size : require\n"
204                                 << "layout(vertices = 1) out;\n"
205                                 << "\n"
206                                 << "void main (void)\n"
207                                 << "{\n"
208                                 << "    gl_TessLevelOuter[0] = 3.0;\n"
209                                 << "    gl_TessLevelOuter[1] = 3.0;\n"
210                                 << "    gl_TessLevelOuter[2] = 3.0;\n"
211                                 << "    gl_TessLevelInner[0] = 3.0;\n"
212                                 << "\n"
213                                 << "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n";
214
215                         if (flags & FLAG_TESSELLATION_ADD)
216                                 src << "    // pass as is to eval\n"
217                                         << "    gl_out[gl_InvocationID].gl_PointSize = gl_in[gl_InvocationID].gl_PointSize;\n";
218
219                         src << "}\n";
220
221                         programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
222                 }
223
224                 // Tessellation evaluation shader
225                 {
226                         std::ostringstream src;
227                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
228                                 << "#extension GL_EXT_tessellation_shader : require\n"
229                                 << "#extension GL_EXT_tessellation_point_size : require\n"
230                                 << "layout(triangles, point_mode) in;\n"
231                                 << "\n"
232                                 << "void main (void)\n"
233                                 << "{\n"
234                                 << "    // hide all but one vertex\n"
235                                 << "    if (gl_TessCoord.x < 0.99)\n"
236                                 << "        gl_Position = vec4(-2.0, 0.0, 0.0, 1.0);\n"
237                                 << "    else\n"
238                                 << "        gl_Position = gl_in[0].gl_Position;\n";
239
240                         if (flags & FLAG_TESSELLATION_ADD)
241                                 src << "\n"
242                                         << "    // add to point size\n"
243                                         << "    gl_PointSize = gl_in[0].gl_PointSize + 2.0;\n";
244                         else if (flags & FLAG_TESSELLATION_EVALUATION_SET)
245                                 src << "\n"
246                                         << "    // set point size\n"
247                                         << "    gl_PointSize = 4.0;\n";
248
249                         src << "}\n";
250
251                         programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
252                 }
253         }
254
255         if (isGeometryStage(flags))
256         {
257                 // Geometry shader
258                 std::ostringstream src;
259                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
260                         << "#extension GL_EXT_geometry_shader : require\n"
261                         << "#extension GL_EXT_geometry_point_size : require\n"
262                         << "layout(points) in;\n"
263                         << "layout(points, max_vertices = 1) out;\n"
264                         << "\n"
265                         << "void main (void)\n"
266                         << "{\n"
267                         << "    gl_Position  = gl_in[0].gl_Position;\n";
268
269                 if (flags & FLAG_GEOMETRY_SET)
270                         src << "    gl_PointSize = 6.0;\n";
271                 else if (flags & FLAG_GEOMETRY_ADD)
272                         src << "    gl_PointSize = gl_in[0].gl_PointSize + 2.0;\n";
273
274                 src << "\n"
275                         << "    EmitVertex();\n"
276                         << "}\n";
277
278                 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
279         }
280 }
281
282 tcu::TestStatus test (Context& context, const Flags flags)
283 {
284         const int expectedPointSize = getExpectedPointSize(flags);
285         {
286                 const InstanceInterface& vki        = context.getInstanceInterface();
287                 const VkPhysicalDevice   physDevice = context.getPhysicalDevice();
288
289                 requireFeatures           (vki, physDevice, FEATURE_TESSELLATION_SHADER | FEATURE_GEOMETRY_SHADER | FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE);
290                 checkPointSizeRequirements(vki, physDevice, expectedPointSize);
291         }
292         {
293                 tcu::TestLog& log = context.getTestContext().getLog();
294
295                 if (flags & FLAG_VERTEX_SET)
296                         log << tcu::TestLog::Message << "Setting point size in vertex shader to 2.0." << tcu::TestLog::EndMessage;
297                 if (flags & FLAG_TESSELLATION_EVALUATION_SET)
298                         log << tcu::TestLog::Message << "Setting point size in tessellation evaluation shader to 4.0." << tcu::TestLog::EndMessage;
299                 if (flags & FLAG_TESSELLATION_ADD)
300                         log << tcu::TestLog::Message << "Reading point size in tessellation control shader and adding 2.0 to it in evaluation." << tcu::TestLog::EndMessage;
301                 if (flags & FLAG_GEOMETRY_SET)
302                         log << tcu::TestLog::Message << "Setting point size in geometry shader to 6.0." << tcu::TestLog::EndMessage;
303                 if (flags & FLAG_GEOMETRY_ADD)
304                         log << tcu::TestLog::Message << "Reading point size in geometry shader and adding 2.0." << tcu::TestLog::EndMessage;
305         }
306
307         const DeviceInterface&  vk                                      = context.getDeviceInterface();
308         const VkDevice                  device                          = context.getDevice();
309         const VkQueue                   queue                           = context.getUniversalQueue();
310         const deUint32                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
311         Allocator&                              allocator                       = context.getDefaultAllocator();
312
313         // Color attachment
314
315         const tcu::IVec2                          renderSize                             = tcu::IVec2(RENDER_SIZE, RENDER_SIZE);
316         const VkFormat                            colorFormat                            = VK_FORMAT_R8G8B8A8_UNORM;
317         const VkImageSubresourceRange colorImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
318         const Image                                       colorAttachmentImage           (vk, device, allocator,
319                                                                                                                          makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 1u),
320                                                                                                                          MemoryRequirement::Any);
321
322         // Color output buffer
323
324         const VkDeviceSize      colorBufferSizeBytes = renderSize.x()*renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
325         const Buffer            colorBuffer          (vk, device, allocator, makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible);
326
327         // Pipeline
328
329         const Unique<VkImageView>               colorAttachmentView(makeImageView                                               (vk, device, *colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorImageSubresourceRange));
330         const Unique<VkRenderPass>              renderPass                 (makeRenderPass                                              (vk, device, colorFormat));
331         const Unique<VkFramebuffer>             framebuffer                (makeFramebuffer                                             (vk, device, *renderPass, *colorAttachmentView, renderSize.x(), renderSize.y(), 1u));
332         const Unique<VkPipelineLayout>  pipelineLayout     (makePipelineLayoutWithoutDescriptors(vk, device));
333         const Unique<VkCommandPool>             cmdPool                    (makeCommandPool                                             (vk, device, queueFamilyIndex));
334         const Unique<VkCommandBuffer>   cmdBuffer                  (allocateCommandBuffer                               (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
335
336         GraphicsPipelineBuilder                 pipelineBuilder;
337
338         pipelineBuilder
339                 .setPrimitiveTopology             (VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
340                 .setRenderSize                            (renderSize)
341                 .setPatchControlPoints            (1)
342                 .setShader                                        (vk, device, VK_SHADER_STAGE_VERTEX_BIT,                                      context.getBinaryCollection().get("vert"), DE_NULL)
343                 .setShader                                        (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,                            context.getBinaryCollection().get("frag"), DE_NULL);
344
345         if (isTessellationStage(flags))
346                 pipelineBuilder
347                         .setShader                                (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,        context.getBinaryCollection().get("tesc"), DE_NULL)
348                         .setShader                                (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, context.getBinaryCollection().get("tese"), DE_NULL);
349
350         if (isGeometryStage(flags))
351                 pipelineBuilder
352                         .setShader                                (vk, device, VK_SHADER_STAGE_GEOMETRY_BIT,                            context.getBinaryCollection().get("geom"), DE_NULL);
353
354         const Unique<VkPipeline> pipeline(pipelineBuilder.build(vk, device, *pipelineLayout, *renderPass));
355
356         // Draw commands
357
358         beginCommandBuffer(vk, *cmdBuffer);
359
360         {
361                 const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier(
362                         (VkAccessFlags)0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
363                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
364                         *colorAttachmentImage, colorImageSubresourceRange);
365
366                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
367                         0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier);
368         }
369
370         // Begin render pass
371         {
372                 const VkRect2D renderArea = {
373                         makeOffset2D(0, 0),
374                         makeExtent2D(renderSize.x(), renderSize.y()),
375                 };
376                 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
377
378                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor);
379         }
380
381         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
382
383         vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
384         endRenderPass(vk, *cmdBuffer);
385
386         // Copy render result to a host-visible buffer
387         {
388                 const VkImageMemoryBarrier colorAttachmentPreCopyBarrier = makeImageMemoryBarrier(
389                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
390                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
391                         *colorAttachmentImage, colorImageSubresourceRange);
392
393                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
394                         0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentPreCopyBarrier);
395         }
396         {
397                 const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeExtent3D(renderSize.x(), renderSize.y(), 1), makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
398                 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorAttachmentImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &copyRegion);
399         }
400         {
401                 const VkBufferMemoryBarrier postCopyBarrier = makeBufferMemoryBarrier(
402                         VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, colorBufferSizeBytes);
403
404                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
405                         0u, DE_NULL, 1u, &postCopyBarrier, 0u, DE_NULL);
406         }
407
408         endCommandBuffer(vk, *cmdBuffer);
409         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
410
411         // Verify results
412         {
413                 const Allocation& alloc = colorBuffer.getAllocation();
414                 invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), colorBufferSizeBytes);
415                 tcu::ConstPixelBufferAccess image(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, alloc.getHostPtr());
416
417                 tcu::TestLog& log = context.getTestContext().getLog();
418                 log << tcu::LogImage("color0", "", image);
419
420                 if (verifyImage(log, image, expectedPointSize))
421                         return tcu::TestStatus::pass("OK");
422                 else
423                         return tcu::TestStatus::fail("Didn't render expected point");
424         }
425 }
426
427 std::string getTestCaseName (const Flags flags)
428 {
429         std::ostringstream buf;
430
431         // join per-bit descriptions into a single string with '_' separator
432         if (flags & FLAG_VERTEX_SET)                                    buf                                                                                                                                             << "vertex_set";
433         if (flags & FLAG_TESSELLATION_EVALUATION_SET)   buf << ((flags & (FLAG_TESSELLATION_EVALUATION_SET-1))  ? ("_") : ("")) << "evaluation_set";
434         if (flags & FLAG_TESSELLATION_ADD)                              buf << ((flags & (FLAG_TESSELLATION_ADD-1))                             ? ("_") : ("")) << "control_pass_eval_add";
435         if (flags & FLAG_GEOMETRY_SET)                                  buf << ((flags & (FLAG_GEOMETRY_SET-1))                                 ? ("_") : ("")) << "geometry_set";
436         if (flags & FLAG_GEOMETRY_ADD)                                  buf << ((flags & (FLAG_GEOMETRY_ADD-1))                                 ? ("_") : ("")) << "geometry_add";
437
438         return buf.str();
439 }
440
441 std::string getTestCaseDescription (const Flags flags)
442 {
443         std::ostringstream buf;
444
445         // join per-bit descriptions into a single string with ", " separator
446         if (flags & FLAG_VERTEX_SET)                                    buf                                                                                                                                                     << "set point size in vertex shader";
447         if (flags & FLAG_TESSELLATION_EVALUATION_SET)   buf << ((flags & (FLAG_TESSELLATION_EVALUATION_SET-1))  ? (", ") : (""))        << "set point size in tessellation evaluation shader";
448         if (flags & FLAG_TESSELLATION_ADD)                              buf << ((flags & (FLAG_TESSELLATION_ADD-1))                             ? (", ") : (""))        << "add to point size in tessellation shader";
449         if (flags & FLAG_GEOMETRY_SET)                                  buf << ((flags & (FLAG_GEOMETRY_SET-1))                                 ? (", ") : (""))        << "set point size in geometry shader";
450         if (flags & FLAG_GEOMETRY_ADD)                                  buf << ((flags & (FLAG_GEOMETRY_ADD-1))                                 ? (", ") : (""))        << "add to point size in geometry shader";
451
452         return buf.str();
453 }
454
455 } // anonymous
456
457 //! Ported from dEQP-GLES31.functional.tessellation_geometry_interaction.point_size.*
458 //! with the exception of the default 1.0 point size cases (not valid in Vulkan).
459 tcu::TestCaseGroup* createGeometryPointSizeTests (tcu::TestContext& testCtx)
460 {
461         de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "point_size", "Test point size"));
462
463         static const Flags caseFlags[] =
464         {
465                 FLAG_VERTEX_SET,
466                                                         FLAG_TESSELLATION_EVALUATION_SET,
467                                                                                                                                         FLAG_GEOMETRY_SET,
468                 FLAG_VERTEX_SET |       FLAG_TESSELLATION_EVALUATION_SET,
469                 FLAG_VERTEX_SET |                                                                                       FLAG_GEOMETRY_SET,
470                 FLAG_VERTEX_SET |       FLAG_TESSELLATION_EVALUATION_SET        |       FLAG_GEOMETRY_SET,
471                 FLAG_VERTEX_SET |       FLAG_TESSELLATION_ADD                           |       FLAG_GEOMETRY_ADD,
472         };
473
474         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(caseFlags); ++ndx)
475         {
476                 const std::string name = getTestCaseName       (caseFlags[ndx]);
477                 const std::string desc = getTestCaseDescription(caseFlags[ndx]);
478
479                 addFunctionCaseWithPrograms(group.get(), name, desc, initPrograms, test, caseFlags[ndx]);
480         }
481
482         return group.release();
483 }
484
485 } // tessellation
486 } // vkt