1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2014 The Android Open Source Project
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Geometry shader layered rendering tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktGeometryLayeredRenderingTests.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktGeometryTestsUtil.hpp"
30 #include "vkPrograms.hpp"
31 #include "vkStrUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkImageUtil.hpp"
38 #include "deStringUtil.hpp"
39 #include "deUniquePtr.hpp"
41 #include "tcuTextureUtil.hpp"
42 #include "tcuVectorUtil.hpp"
58 TEST_TYPE_DEFAULT_LAYER, // !< draw to default layer
59 TEST_TYPE_SINGLE_LAYER, // !< draw to single layer
60 TEST_TYPE_ALL_LAYERS, // !< draw all layers
61 TEST_TYPE_DIFFERENT_CONTENT, // !< draw different content to different layers
62 TEST_TYPE_LAYER_ID, // !< draw to all layers, verify gl_Layer fragment input
63 TEST_TYPE_INVOCATION_PER_LAYER, // !< draw to all layers, one invocation per layer
64 TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION, // !< draw to all layers, multiple invocations write to multiple layers
69 VkImageViewType viewType;
80 static const float s_colors[][4] =
82 { 1.0f, 1.0f, 1.0f, 1.0f }, // white
83 { 1.0f, 0.0f, 0.0f, 1.0f }, // red
84 { 0.0f, 1.0f, 0.0f, 1.0f }, // green
85 { 0.0f, 0.0f, 1.0f, 1.0f }, // blue
86 { 1.0f, 1.0f, 0.0f, 1.0f }, // yellow
87 { 1.0f, 0.0f, 1.0f, 1.0f }, // magenta
90 deUint32 getTargetLayer (const ImageParams& imageParams)
92 if (imageParams.viewType == VK_IMAGE_VIEW_TYPE_3D)
93 return imageParams.size.depth / 2;
95 return imageParams.numLayers / 2;
98 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
100 std::string s(getImageViewTypeName(imageViewType));
101 return de::toLower(s.substr(19));
104 VkImageType getImageType (const VkImageViewType viewType)
108 case VK_IMAGE_VIEW_TYPE_1D:
109 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
110 return VK_IMAGE_TYPE_1D;
112 case VK_IMAGE_VIEW_TYPE_2D:
113 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
114 case VK_IMAGE_VIEW_TYPE_CUBE:
115 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
116 return VK_IMAGE_TYPE_2D;
118 case VK_IMAGE_VIEW_TYPE_3D:
119 return VK_IMAGE_TYPE_3D;
123 return VK_IMAGE_TYPE_LAST;
127 inline bool isCubeImageViewType (const VkImageViewType viewType)
129 return viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
132 VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const VkImageUsageFlags usage)
134 const VkImageCreateInfo imageParams =
136 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
137 DE_NULL, // const void* pNext;
138 flags, // VkImageCreateFlags flags;
139 type, // VkImageType imageType;
140 format, // VkFormat format;
141 size, // VkExtent3D extent;
142 1u, // deUint32 mipLevels;
143 numLayers, // deUint32 arrayLayers;
144 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
145 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
146 usage, // VkImageUsageFlags usage;
147 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
148 0u, // deUint32 queueFamilyIndexCount;
149 DE_NULL, // const deUint32* pQueueFamilyIndices;
150 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
155 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
156 const VkDevice device,
157 const VkFormat colorFormat)
159 const VkAttachmentDescription colorAttachmentDescription =
161 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
162 colorFormat, // VkFormat format;
163 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
164 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
165 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
166 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
167 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
168 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
169 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
172 const VkAttachmentReference colorAttachmentRef =
174 0u, // deUint32 attachment;
175 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
178 const VkSubpassDescription subpassDescription =
180 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
181 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
182 0u, // deUint32 inputAttachmentCount;
183 DE_NULL, // const VkAttachmentReference* pInputAttachments;
184 1u, // deUint32 colorAttachmentCount;
185 &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments;
186 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
187 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
188 0u, // deUint32 preserveAttachmentCount;
189 DE_NULL // const deUint32* pPreserveAttachments;
192 const VkRenderPassCreateInfo renderPassInfo =
194 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
195 DE_NULL, // const void* pNext;
196 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
197 1u, // deUint32 attachmentCount;
198 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments;
199 1u, // deUint32 subpassCount;
200 &subpassDescription, // const VkSubpassDescription* pSubpasses;
201 0u, // deUint32 dependencyCount;
202 DE_NULL // const VkSubpassDependency* pDependencies;
205 return createRenderPass(vk, device, &renderPassInfo);
208 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
209 const VkDevice device,
210 const VkPipelineLayout pipelineLayout,
211 const VkRenderPass renderPass,
212 const VkShaderModule vertexModule,
213 const VkShaderModule geometryModule,
214 const VkShaderModule fragmentModule,
215 const VkExtent2D renderSize)
217 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
219 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
220 DE_NULL, // const void* pNext;
221 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
222 0u, // uint32_t vertexBindingDescriptionCount;
223 DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
224 0u, // uint32_t vertexAttributeDescriptionCount;
225 DE_NULL, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
228 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
230 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
231 DE_NULL, // const void* pNext;
232 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
233 VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // VkPrimitiveTopology topology;
234 VK_FALSE, // VkBool32 primitiveRestartEnable;
237 const VkViewport viewport = makeViewport(
239 static_cast<float>(renderSize.width), static_cast<float>(renderSize.height),
241 const VkRect2D scissor =
244 makeExtent2D(renderSize.width, renderSize.height),
247 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
249 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
250 DE_NULL, // const void* pNext;
251 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
252 1u, // uint32_t viewportCount;
253 &viewport, // const VkViewport* pViewports;
254 1u, // uint32_t scissorCount;
255 &scissor, // const VkRect2D* pScissors;
258 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
260 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
261 DE_NULL, // const void* pNext;
262 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
263 VK_FALSE, // VkBool32 depthClampEnable;
264 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
265 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
266 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
267 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
268 VK_FALSE, // VkBool32 depthBiasEnable;
269 0.0f, // float depthBiasConstantFactor;
270 0.0f, // float depthBiasClamp;
271 0.0f, // float depthBiasSlopeFactor;
272 1.0f, // float lineWidth;
275 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
277 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
278 DE_NULL, // const void* pNext;
279 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
280 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
281 VK_FALSE, // VkBool32 sampleShadingEnable;
282 0.0f, // float minSampleShading;
283 DE_NULL, // const VkSampleMask* pSampleMask;
284 VK_FALSE, // VkBool32 alphaToCoverageEnable;
285 VK_FALSE // VkBool32 alphaToOneEnable;
288 const VkStencilOpState stencilOpState = makeStencilOpState(
289 VK_STENCIL_OP_KEEP, // stencil fail
290 VK_STENCIL_OP_KEEP, // depth & stencil pass
291 VK_STENCIL_OP_KEEP, // depth only fail
292 VK_COMPARE_OP_ALWAYS, // compare op
297 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
299 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
300 DE_NULL, // const void* pNext;
301 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
302 VK_FALSE, // VkBool32 depthTestEnable;
303 VK_FALSE, // VkBool32 depthWriteEnable;
304 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
305 VK_FALSE, // VkBool32 depthBoundsTestEnable;
306 VK_FALSE, // VkBool32 stencilTestEnable;
307 stencilOpState, // VkStencilOpState front;
308 stencilOpState, // VkStencilOpState back;
309 0.0f, // float minDepthBounds;
310 1.0f, // float maxDepthBounds;
313 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
314 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
316 VK_FALSE, // VkBool32 blendEnable;
317 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
318 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
319 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
320 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
321 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
322 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
323 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
326 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
328 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
329 DE_NULL, // const void* pNext;
330 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
331 VK_FALSE, // VkBool32 logicOpEnable;
332 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
333 1u, // deUint32 attachmentCount;
334 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
335 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
338 const VkPipelineShaderStageCreateInfo pShaderStages[] =
341 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
342 DE_NULL, // const void* pNext;
343 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
344 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
345 vertexModule, // VkShaderModule module;
346 "main", // const char* pName;
347 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
350 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
351 DE_NULL, // const void* pNext;
352 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
353 VK_SHADER_STAGE_GEOMETRY_BIT, // VkShaderStageFlagBits stage;
354 geometryModule, // VkShaderModule module;
355 "main", // const char* pName;
356 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
359 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
360 DE_NULL, // const void* pNext;
361 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
362 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
363 fragmentModule, // VkShaderModule module;
364 "main", // const char* pName;
365 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
369 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
371 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
372 DE_NULL, // const void* pNext;
373 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
374 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount;
375 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
376 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
377 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
378 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
379 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
380 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
381 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
382 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
383 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
384 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
385 pipelineLayout, // VkPipelineLayout layout;
386 renderPass, // VkRenderPass renderPass;
387 0u, // deUint32 subpass;
388 DE_NULL, // VkPipeline basePipelineHandle;
389 0, // deInt32 basePipelineIndex;
392 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
395 //! Convenience wrapper to access 1D, 2D, and 3D image layers/slices in a uniform way.
396 class LayeredImageAccess
399 static LayeredImageAccess create (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
401 if (type == VK_IMAGE_TYPE_1D)
402 return LayeredImageAccess(format, size.width, numLayers, pData);
404 return LayeredImageAccess(type, format, size, numLayers, pData);
407 inline tcu::ConstPixelBufferAccess getLayer (const int layer) const
409 return tcu::getSubregion(m_wholeImage, 0, (m_1dModifier * layer), ((~m_1dModifier & 1) * layer), m_width, m_height, 1);
412 inline int getNumLayersOrSlices (void) const
418 // Specialized for 1D images.
419 LayeredImageAccess (const VkFormat format, const deUint32 width, const deUint32 numLayers, const void* pData)
420 : m_width (static_cast<int>(width))
423 , m_layers (numLayers)
424 , m_wholeImage (tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_layers, 1, pData))
428 LayeredImageAccess (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
429 : m_width (static_cast<int>(size.width))
430 , m_height (static_cast<int>(size.height))
432 , m_layers (static_cast<int>(type == VK_IMAGE_TYPE_3D ? size.depth : numLayers))
433 , m_wholeImage (tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_height, m_layers, pData))
439 const int m_1dModifier;
441 const tcu::ConstPixelBufferAccess m_wholeImage;
444 inline bool compareColors (const Vec4& colorA, const Vec4& colorB, const Vec4& threshold)
446 return tcu::allEqual(
447 tcu::lessThan(tcu::abs(colorA - colorB), threshold),
448 tcu::BVec4(true, true, true, true));
451 bool verifyImageSingleColoredRow (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image, const float rowWidthRatio, const tcu::Vec4& barColor)
453 DE_ASSERT(rowWidthRatio > 0.0f);
455 const Vec4 black (0.0f, 0.0f, 0.0f, 1.0f);
456 const Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
457 const Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
458 const Vec4 threshold (0.02f);
459 const int barLength = static_cast<int>(rowWidthRatio * static_cast<float>(image.getWidth()));
460 const int barLengthThreshold = 1;
461 tcu::TextureLevel errorMask (image.getFormat(), image.getWidth(), image.getHeight());
462 tcu::PixelBufferAccess errorMaskAccess = errorMask.getAccess();
464 tcu::clear(errorMask.getAccess(), green);
466 log << tcu::TestLog::Message
467 << "Expecting all pixels with distance less or equal to (about) " << barLength
468 << " pixels from left border to be of color " << barColor.swizzle(0, 1, 2) << "."
469 << tcu::TestLog::EndMessage;
471 bool allPixelsOk = true;
473 for (int y = 0; y < image.getHeight(); ++y)
474 for (int x = 0; x < image.getWidth(); ++x)
476 const Vec4 color = image.getPixel(x, y);
477 const bool isBlack = compareColors(color, black, threshold);
478 const bool isColor = compareColors(color, barColor, threshold);
482 if (x <= barLength - barLengthThreshold)
484 else if (x >= barLength + barLengthThreshold)
487 isOk = isColor || isBlack;
492 errorMaskAccess.setPixel(red, x, y);
497 log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
498 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
499 << tcu::TestLog::Image("Layer", "Layer", image)
500 << tcu::TestLog::EndImageSet;
505 log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
506 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
507 << tcu::TestLog::Image("Layer", "Layer", image)
508 << tcu::TestLog::Image("ErrorMask", "Errors", errorMask)
509 << tcu::TestLog::EndImageSet;
513 log << tcu::TestLog::Image("LayerContent", "Layer content", image);
518 bool verifyEmptyImage (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image)
520 log << tcu::TestLog::Message << "Expecting empty image" << tcu::TestLog::EndMessage;
522 const Vec4 black (0.0f, 0.0f, 0.0f, 1.0f);
523 const Vec4 threshold (0.02f);
525 for (int y = 0; y < image.getHeight(); ++y)
526 for (int x = 0; x < image.getWidth(); ++x)
528 const Vec4 color = image.getPixel(x, y);
530 if (!compareColors(color, black, threshold))
532 log << tcu::TestLog::Message
533 << "Found (at least) one bad pixel at " << x << "," << y << ". Pixel color is not background color."
534 << tcu::TestLog::EndMessage
535 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
536 << tcu::TestLog::Image("Layer", "Layer", image)
537 << tcu::TestLog::EndImageSet;
542 log << tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage;
547 bool verifyLayerContent (tcu::TestLog& log, const TestType testType, const tcu::ConstPixelBufferAccess image, const int layerNdx, const int numLayers)
549 const Vec4 white (1.0f, 1.0f, 1.0f, 1.0f);
550 const int targetLayer = numLayers / 2;
551 const float variableBarRatio = static_cast<float>(layerNdx) / static_cast<float>(numLayers);
555 case TEST_TYPE_DEFAULT_LAYER:
557 return verifyImageSingleColoredRow(log, image, 0.5f, white);
559 return verifyEmptyImage(log, image);
561 case TEST_TYPE_SINGLE_LAYER:
562 if (layerNdx == targetLayer)
563 return verifyImageSingleColoredRow(log, image, 0.5f, white);
565 return verifyEmptyImage(log, image);
567 case TEST_TYPE_ALL_LAYERS:
568 case TEST_TYPE_INVOCATION_PER_LAYER:
569 return verifyImageSingleColoredRow(log, image, 0.5f, s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
571 case TEST_TYPE_DIFFERENT_CONTENT:
572 case TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION:
574 return verifyEmptyImage(log, image);
576 return verifyImageSingleColoredRow(log, image, variableBarRatio, white);
578 case TEST_TYPE_LAYER_ID:
580 // This code must be in sync with the fragment shader.
581 const tcu::Vec4 layerColor( (layerNdx % 2) == 1 ? 1.0f : 0.5f,
582 ((layerNdx/2) % 2) == 1 ? 1.0f : 0.5f,
583 layerNdx == 0 ? 1.0f : 0.0f,
585 return verifyImageSingleColoredRow(log, image, 0.5f, layerColor);
594 std::string getLayerDescription (const VkImageViewType viewType, const int layer)
596 std::ostringstream str;
597 const int numCubeFaces = 6;
599 if (isCubeImageViewType(viewType))
600 str << "cube " << (layer / numCubeFaces) << ", face " << (layer % numCubeFaces);
601 else if (viewType == VK_IMAGE_VIEW_TYPE_3D)
602 str << "slice z = " << layer;
604 str << "layer " << layer;
609 bool verifyResults (tcu::TestLog& log, const TestParams& params, const VkFormat colorFormat, const void* resultData)
611 const LayeredImageAccess image = LayeredImageAccess::create(getImageType(params.image.viewType), colorFormat, params.image.size, params.image.numLayers, resultData);
613 int numGoodLayers = 0;
615 for (int layerNdx = 0; layerNdx < image.getNumLayersOrSlices(); ++layerNdx)
617 const tcu::ConstPixelBufferAccess layerImage = image.getLayer(layerNdx);
619 log << tcu::TestLog::Message << "Verifying " << getLayerDescription(params.image.viewType, layerNdx) << tcu::TestLog::EndMessage;
621 if (verifyLayerContent(log, params.testType, layerImage, layerNdx, image.getNumLayersOrSlices()))
625 return numGoodLayers == image.getNumLayersOrSlices();
628 std::string toGlsl (const Vec4& v)
630 std::ostringstream str;
632 for (int i = 0; i < 4; ++i)
633 str << (i != 0 ? ", " : "") << de::floatToString(v[i], 1);
638 void initPrograms (SourceCollections& programCollection, const TestParams params)
640 const bool geomOutputColor = (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_INVOCATION_PER_LAYER);
644 std::ostringstream src;
645 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
647 << "void main(void)\n"
651 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
656 const int maxVertices = (params.testType == TEST_TYPE_DIFFERENT_CONTENT) ? (params.image.numLayers + 1) * params.image.numLayers :
657 (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_LAYER_ID) ? params.image.numLayers * 4 :
658 (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION) ? 6 : 4;
660 std::ostringstream src;
661 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
664 if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
665 src << "layout(points, invocations = " << params.image.numLayers << ") in;\n";
667 src << "layout(points) in;\n";
669 src << "layout(triangle_strip, max_vertices = " << maxVertices << ") out;\n"
671 << (geomOutputColor ? "layout(location = 0) out vec4 vert_color;\n\n" : "")
672 << "out gl_PerVertex {\n"
673 << " vec4 gl_Position;\n"
676 << "void main(void)\n"
679 std::ostringstream colorTable;
681 const int numColors = DE_LENGTH_OF_ARRAY(s_colors);
683 colorTable << " const vec4 colors[" << numColors << "] = vec4[" << numColors << "](";
685 const std::string padding(colorTable.str().length(), ' ');
687 for (int i = 0; i < numColors; ++i)
688 colorTable << (i != 0 ? ",\n" + padding : "") << toGlsl(s_colors[i]);
690 colorTable << ");\n";
693 if (params.testType == TEST_TYPE_DEFAULT_LAYER)
695 src << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
696 << " EmitVertex();\n"
698 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
699 << " EmitVertex();\n"
701 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
702 << " EmitVertex();\n"
704 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
705 << " EmitVertex();\n";
707 else if (params.testType == TEST_TYPE_SINGLE_LAYER)
709 const deUint32 targetLayer = getTargetLayer(params.image);
711 src << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
712 << " gl_Layer = " << targetLayer << ";\n"
713 << " EmitVertex();\n"
715 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
716 << " gl_Layer = " << targetLayer << ";\n"
717 << " EmitVertex();\n"
719 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
720 << " gl_Layer = " << targetLayer << ";\n"
721 << " EmitVertex();\n"
723 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
724 << " gl_Layer = " << targetLayer << ";\n"
725 << " EmitVertex();\n";
727 else if (params.testType == TEST_TYPE_ALL_LAYERS)
729 src << colorTable.str()
731 << " for (int layerNdx = 0; layerNdx < " << params.image.numLayers << "; ++layerNdx) {\n"
732 << " const int colorNdx = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
734 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
735 << " gl_Layer = layerNdx;\n"
736 << " vert_color = colors[colorNdx];\n"
737 << " EmitVertex();\n"
739 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
740 << " gl_Layer = layerNdx;\n"
741 << " vert_color = colors[colorNdx];\n"
742 << " EmitVertex();\n"
744 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
745 << " gl_Layer = layerNdx;\n"
746 << " vert_color = colors[colorNdx];\n"
747 << " EmitVertex();\n"
749 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
750 << " gl_Layer = layerNdx;\n"
751 << " vert_color = colors[colorNdx];\n"
752 << " EmitVertex();\n"
753 << " EndPrimitive();\n"
756 else if (params.testType == TEST_TYPE_LAYER_ID)
758 src << " for (int layerNdx = 0; layerNdx < " << params.image.numLayers << "; ++layerNdx) {\n"
759 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
760 << " gl_Layer = layerNdx;\n"
761 << " EmitVertex();\n"
763 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
764 << " gl_Layer = layerNdx;\n"
765 << " EmitVertex();\n"
767 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
768 << " gl_Layer = layerNdx;\n"
769 << " EmitVertex();\n"
771 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
772 << " gl_Layer = layerNdx;\n"
773 << " EmitVertex();\n"
774 << " EndPrimitive();\n"
777 else if (params.testType == TEST_TYPE_DIFFERENT_CONTENT)
779 src << " for (int layerNdx = 0; layerNdx < " << params.image.numLayers << "; ++layerNdx) {\n"
780 << " for (int colNdx = 0; colNdx <= layerNdx; ++colNdx) {\n"
781 << " const float posX = float(colNdx) / float(" << params.image.numLayers << ") * 2.0 - 1.0;\n"
783 << " gl_Position = vec4(posX, 1.0, 0.0, 1.0);\n"
784 << " gl_Layer = layerNdx;\n"
785 << " EmitVertex();\n"
787 << " gl_Position = vec4(posX, -1.0, 0.0, 1.0);\n"
788 << " gl_Layer = layerNdx;\n"
789 << " EmitVertex();\n"
791 << " EndPrimitive();\n"
794 else if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER)
796 src << colorTable.str()
797 << " const int colorNdx = gl_InvocationID % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
799 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
800 << " gl_Layer = gl_InvocationID;\n"
801 << " vert_color = colors[colorNdx];\n"
802 << " EmitVertex();\n"
804 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
805 << " gl_Layer = gl_InvocationID;\n"
806 << " vert_color = colors[colorNdx];\n"
807 << " EmitVertex();\n"
809 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
810 << " gl_Layer = gl_InvocationID;\n"
811 << " vert_color = colors[colorNdx];\n"
812 << " EmitVertex();\n"
814 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
815 << " gl_Layer = gl_InvocationID;\n"
816 << " vert_color = colors[colorNdx];\n"
817 << " EmitVertex();\n"
818 << " EndPrimitive();\n";
820 else if (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
822 src << " const int layerA = gl_InvocationID;\n"
823 << " const int layerB = (gl_InvocationID + 1) % " << params.image.numLayers << ";\n"
824 << " const float aEnd = float(layerA) / float(" << params.image.numLayers << ") * 2.0 - 1.0;\n"
825 << " const float bEnd = float(layerB) / float(" << params.image.numLayers << ") * 2.0 - 1.0;\n"
827 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
828 << " gl_Layer = layerA;\n"
829 << " EmitVertex();\n"
831 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
832 << " gl_Layer = layerA;\n"
833 << " EmitVertex();\n"
835 << " gl_Position = vec4(aEnd, -1.0, 0.0, 1.0);\n"
836 << " gl_Layer = layerA;\n"
837 << " EmitVertex();\n"
838 << " EndPrimitive();\n"
840 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
841 << " gl_Layer = layerB;\n"
842 << " EmitVertex();\n"
844 << " gl_Position = vec4(bEnd, 1.0, 0.0, 1.0);\n"
845 << " gl_Layer = layerB;\n"
846 << " EmitVertex();\n"
848 << " gl_Position = vec4(bEnd, -1.0, 0.0, 1.0);\n"
849 << " gl_Layer = layerB;\n"
850 << " EmitVertex();\n"
851 << " EndPrimitive();\n";
856 src << "}\n"; // end main
858 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
863 std::ostringstream src;
864 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
866 << "layout(location = 0) out vec4 o_color;\n"
867 << (geomOutputColor ? "layout(location = 0) in vec4 vert_color;\n" : "")
869 << "void main(void)\n"
872 if (params.testType == TEST_TYPE_LAYER_ID)
874 // This code must be in sync with verifyLayerContent()
875 src << " o_color = vec4( (gl_Layer % 2) == 1 ? 1.0 : 0.5,\n"
876 << " ((gl_Layer/2) % 2) == 1 ? 1.0 : 0.5,\n"
877 << " gl_Layer == 0 ? 1.0 : 0.0,\n"
880 else if (geomOutputColor)
881 src << " o_color = vert_color;\n";
883 src << " o_color = vec4(1.0);\n";
887 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
891 tcu::TestStatus test (Context& context, const TestParams params)
893 const DeviceInterface& vk = context.getDeviceInterface();
894 const InstanceInterface& vki = context.getInstanceInterface();
895 const VkDevice device = context.getDevice();
896 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
897 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
898 const VkQueue queue = context.getUniversalQueue();
899 Allocator& allocator = context.getDefaultAllocator();
901 checkGeometryShaderSupport(vki, physDevice);
903 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
904 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers);
905 const Vec4 clearColor = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
906 const VkDeviceSize colorBufferSize = params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * tcu::getPixelSize(mapVkFormat(colorFormat));
907 const VkImageCreateFlags imageCreateFlags = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0);
909 const Unique<VkImage> colorImage (makeImage (vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
910 params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
911 const UniquePtr<Allocation> colorImageAlloc (bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any));
912 const Unique<VkImageView> colorAttachment (makeImageView (vk, device, *colorImage, params.image.viewType, colorFormat, colorSubresourceRange));
913 const Unique<VkBuffer> colorBuffer (makeBuffer (vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
914 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
916 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
917 const Unique<VkShaderModule> geometryModule (createShaderModule (vk, device, context.getBinaryCollection().get("geom"), 0u));
918 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
920 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, colorFormat));
921 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, *colorAttachment, params.image.size.width, params.image.size.height, params.image.numLayers));
922 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device));
923 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
924 makeExtent2D(params.image.size.width, params.image.size.height)));
925 const Unique<VkCommandPool> cmdPool (makeCommandPool (vk, device, queueFamilyIndex));
926 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer (vk, device, *cmdPool));
928 zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
930 beginCommandBuffer(vk, *cmdBuffer);
932 const VkClearValue clearValue = makeClearValueColor(clearColor);
933 const VkRect2D renderArea =
936 makeExtent2D(params.image.size.width, params.image.size.height),
938 const VkRenderPassBeginInfo renderPassBeginInfo =
940 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
941 DE_NULL, // const void* pNext;
942 *renderPass, // VkRenderPass renderPass;
943 *framebuffer, // VkFramebuffer framebuffer;
944 renderArea, // VkRect2D renderArea;
945 1u, // uint32_t clearValueCount;
946 &clearValue, // const VkClearValue* pClearValues;
948 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
950 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
951 vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
952 vk.cmdEndRenderPass(*cmdBuffer);
954 // Prepare color image for copy
956 const VkImageMemoryBarrier barriers[] =
959 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
960 DE_NULL, // const void* pNext;
961 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask;
962 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask;
963 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
964 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
965 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
966 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
967 *colorImage, // VkImage image;
968 colorSubresourceRange, // VkImageSubresourceRange subresourceRange;
972 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
973 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
975 // Color image -> host buffer
977 const VkBufferImageCopy region =
979 0ull, // VkDeviceSize bufferOffset;
980 0u, // uint32_t bufferRowLength;
981 0u, // uint32_t bufferImageHeight;
982 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, params.image.numLayers), // VkImageSubresourceLayers imageSubresource;
983 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
984 params.image.size, // VkExtent3D imageExtent;
987 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
989 // Buffer write barrier
991 const VkBufferMemoryBarrier barriers[] =
994 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
995 DE_NULL, // const void* pNext;
996 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
997 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
998 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
999 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1000 *colorBuffer, // VkBuffer buffer;
1001 0ull, // VkDeviceSize offset;
1002 VK_WHOLE_SIZE, // VkDeviceSize size;
1006 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1007 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u);
1010 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1011 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1013 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSize);
1015 if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1016 return tcu::TestStatus::fail("Rendered images are incorrect");
1018 return tcu::TestStatus::pass("OK");
1023 tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx)
1025 MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "layered", "Layered rendering tests."));
1031 const char* description;
1034 { TEST_TYPE_DEFAULT_LAYER, "render_to_default_layer", "Render to the default layer" },
1035 { TEST_TYPE_SINGLE_LAYER, "render_to_one", "Render to one layer" },
1036 { TEST_TYPE_ALL_LAYERS, "render_to_all", "Render to all layers" },
1037 { TEST_TYPE_DIFFERENT_CONTENT, "render_different_content", "Render different data to different layers" },
1038 { TEST_TYPE_LAYER_ID, "fragment_layer", "Read gl_Layer in fragment shader" },
1039 { TEST_TYPE_INVOCATION_PER_LAYER, "invocation_per_layer", "Render to multiple layers with multiple invocations, one invocation per layer" },
1040 { TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION, "multiple_layers_per_invocation", "Render to multiple layers with multiple invocations, multiple layers per invocation", },
1043 const ImageParams imageParams[] =
1045 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, { 64, 1, 1 }, 4 },
1046 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, { 64, 64, 1 }, 4 },
1047 { VK_IMAGE_VIEW_TYPE_CUBE, { 64, 64, 1 }, 6 },
1048 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, { 64, 64, 1 }, 2*6 },
1049 // No support for rendering to 3d image slices in Vulkan 1.0
1052 for (int imageParamNdx = 0; imageParamNdx < DE_LENGTH_OF_ARRAY(imageParams); ++imageParamNdx)
1054 MovePtr<tcu::TestCaseGroup> viewTypeGroup(new tcu::TestCaseGroup(testCtx, getShortImageViewTypeName(imageParams[imageParamNdx].viewType).c_str(), ""));
1056 for (int testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx)
1058 const TestParams params =
1060 testTypes[testTypeNdx].test,
1061 imageParams[imageParamNdx],
1063 addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, initPrograms, test, params);
1066 group->addChild(viewTypeGroup.release());
1069 return group.release();