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"
43 #include "tcuTestLog.hpp"
59 TEST_TYPE_DEFAULT_LAYER, // !< draw to default layer
60 TEST_TYPE_SINGLE_LAYER, // !< draw to single layer
61 TEST_TYPE_ALL_LAYERS, // !< draw all layers
62 TEST_TYPE_DIFFERENT_CONTENT, // !< draw different content to different layers
63 TEST_TYPE_LAYER_ID, // !< draw to all layers, verify gl_Layer fragment input
64 TEST_TYPE_INVOCATION_PER_LAYER, // !< draw to all layers, one invocation per layer
65 TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION, // !< draw to all layers, multiple invocations write to multiple layers
70 VkImageViewType viewType;
81 static const float s_colors[][4] =
83 { 1.0f, 1.0f, 1.0f, 1.0f }, // white
84 { 1.0f, 0.0f, 0.0f, 1.0f }, // red
85 { 0.0f, 1.0f, 0.0f, 1.0f }, // green
86 { 0.0f, 0.0f, 1.0f, 1.0f }, // blue
87 { 1.0f, 1.0f, 0.0f, 1.0f }, // yellow
88 { 1.0f, 0.0f, 1.0f, 1.0f }, // magenta
91 deUint32 getTargetLayer (const ImageParams& imageParams)
93 if (imageParams.viewType == VK_IMAGE_VIEW_TYPE_3D)
94 return imageParams.size.depth / 2;
96 return imageParams.numLayers / 2;
99 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
101 std::string s(getImageViewTypeName(imageViewType));
102 return de::toLower(s.substr(19));
105 VkImageType getImageType (const VkImageViewType viewType)
109 case VK_IMAGE_VIEW_TYPE_1D:
110 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
111 return VK_IMAGE_TYPE_1D;
113 case VK_IMAGE_VIEW_TYPE_2D:
114 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
115 case VK_IMAGE_VIEW_TYPE_CUBE:
116 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
117 return VK_IMAGE_TYPE_2D;
119 case VK_IMAGE_VIEW_TYPE_3D:
120 return VK_IMAGE_TYPE_3D;
124 return VK_IMAGE_TYPE_LAST;
128 inline bool isCubeImageViewType (const VkImageViewType viewType)
130 return viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
133 VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const VkImageUsageFlags usage)
135 const VkImageCreateInfo imageParams =
137 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
138 DE_NULL, // const void* pNext;
139 flags, // VkImageCreateFlags flags;
140 type, // VkImageType imageType;
141 format, // VkFormat format;
142 size, // VkExtent3D extent;
143 1u, // deUint32 mipLevels;
144 numLayers, // deUint32 arrayLayers;
145 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
146 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
147 usage, // VkImageUsageFlags usage;
148 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
149 0u, // deUint32 queueFamilyIndexCount;
150 DE_NULL, // const deUint32* pQueueFamilyIndices;
151 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
156 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
157 const VkDevice device,
158 const VkFormat colorFormat)
160 const VkAttachmentDescription colorAttachmentDescription =
162 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
163 colorFormat, // VkFormat format;
164 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
165 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
166 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
167 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
168 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
169 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
170 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
173 const VkAttachmentReference colorAttachmentRef =
175 0u, // deUint32 attachment;
176 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
179 const VkSubpassDescription subpassDescription =
181 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
182 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
183 0u, // deUint32 inputAttachmentCount;
184 DE_NULL, // const VkAttachmentReference* pInputAttachments;
185 1u, // deUint32 colorAttachmentCount;
186 &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments;
187 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
188 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
189 0u, // deUint32 preserveAttachmentCount;
190 DE_NULL // const deUint32* pPreserveAttachments;
193 const VkRenderPassCreateInfo renderPassInfo =
195 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
196 DE_NULL, // const void* pNext;
197 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
198 1u, // deUint32 attachmentCount;
199 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments;
200 1u, // deUint32 subpassCount;
201 &subpassDescription, // const VkSubpassDescription* pSubpasses;
202 0u, // deUint32 dependencyCount;
203 DE_NULL // const VkSubpassDependency* pDependencies;
206 return createRenderPass(vk, device, &renderPassInfo);
209 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
210 const VkDevice device,
211 const VkPipelineLayout pipelineLayout,
212 const VkRenderPass renderPass,
213 const VkShaderModule vertexModule,
214 const VkShaderModule geometryModule,
215 const VkShaderModule fragmentModule,
216 const VkExtent2D renderSize)
218 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
220 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
221 DE_NULL, // const void* pNext;
222 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
223 0u, // uint32_t vertexBindingDescriptionCount;
224 DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
225 0u, // uint32_t vertexAttributeDescriptionCount;
226 DE_NULL, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
229 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
231 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
232 DE_NULL, // const void* pNext;
233 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
234 VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // VkPrimitiveTopology topology;
235 VK_FALSE, // VkBool32 primitiveRestartEnable;
238 const VkViewport viewport = makeViewport(
240 static_cast<float>(renderSize.width), static_cast<float>(renderSize.height),
242 const VkRect2D scissor =
245 makeExtent2D(renderSize.width, renderSize.height),
248 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
250 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
251 DE_NULL, // const void* pNext;
252 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
253 1u, // uint32_t viewportCount;
254 &viewport, // const VkViewport* pViewports;
255 1u, // uint32_t scissorCount;
256 &scissor, // const VkRect2D* pScissors;
259 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
261 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
262 DE_NULL, // const void* pNext;
263 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
264 VK_FALSE, // VkBool32 depthClampEnable;
265 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
266 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
267 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
268 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
269 VK_FALSE, // VkBool32 depthBiasEnable;
270 0.0f, // float depthBiasConstantFactor;
271 0.0f, // float depthBiasClamp;
272 0.0f, // float depthBiasSlopeFactor;
273 1.0f, // float lineWidth;
276 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
278 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
279 DE_NULL, // const void* pNext;
280 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
281 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
282 VK_FALSE, // VkBool32 sampleShadingEnable;
283 0.0f, // float minSampleShading;
284 DE_NULL, // const VkSampleMask* pSampleMask;
285 VK_FALSE, // VkBool32 alphaToCoverageEnable;
286 VK_FALSE // VkBool32 alphaToOneEnable;
289 const VkStencilOpState stencilOpState = makeStencilOpState(
290 VK_STENCIL_OP_KEEP, // stencil fail
291 VK_STENCIL_OP_KEEP, // depth & stencil pass
292 VK_STENCIL_OP_KEEP, // depth only fail
293 VK_COMPARE_OP_ALWAYS, // compare op
298 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
300 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
301 DE_NULL, // const void* pNext;
302 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
303 VK_FALSE, // VkBool32 depthTestEnable;
304 VK_FALSE, // VkBool32 depthWriteEnable;
305 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
306 VK_FALSE, // VkBool32 depthBoundsTestEnable;
307 VK_FALSE, // VkBool32 stencilTestEnable;
308 stencilOpState, // VkStencilOpState front;
309 stencilOpState, // VkStencilOpState back;
310 0.0f, // float minDepthBounds;
311 1.0f, // float maxDepthBounds;
314 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
315 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
317 VK_FALSE, // VkBool32 blendEnable;
318 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
319 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
320 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
321 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
322 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
323 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
324 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
327 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
329 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
330 DE_NULL, // const void* pNext;
331 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
332 VK_FALSE, // VkBool32 logicOpEnable;
333 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
334 1u, // deUint32 attachmentCount;
335 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
336 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
339 const VkPipelineShaderStageCreateInfo pShaderStages[] =
342 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
343 DE_NULL, // const void* pNext;
344 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
345 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
346 vertexModule, // VkShaderModule module;
347 "main", // const char* pName;
348 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
351 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
352 DE_NULL, // const void* pNext;
353 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
354 VK_SHADER_STAGE_GEOMETRY_BIT, // VkShaderStageFlagBits stage;
355 geometryModule, // VkShaderModule module;
356 "main", // const char* pName;
357 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
360 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
361 DE_NULL, // const void* pNext;
362 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
363 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
364 fragmentModule, // VkShaderModule module;
365 "main", // const char* pName;
366 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
370 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
372 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
373 DE_NULL, // const void* pNext;
374 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
375 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount;
376 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
377 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
378 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
379 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
380 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
381 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
382 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
383 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
384 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
385 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
386 pipelineLayout, // VkPipelineLayout layout;
387 renderPass, // VkRenderPass renderPass;
388 0u, // deUint32 subpass;
389 DE_NULL, // VkPipeline basePipelineHandle;
390 0, // deInt32 basePipelineIndex;
393 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
396 //! Convenience wrapper to access 1D, 2D, and 3D image layers/slices in a uniform way.
397 class LayeredImageAccess
400 static LayeredImageAccess create (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
402 if (type == VK_IMAGE_TYPE_1D)
403 return LayeredImageAccess(format, size.width, numLayers, pData);
405 return LayeredImageAccess(type, format, size, numLayers, pData);
408 inline tcu::ConstPixelBufferAccess getLayer (const int layer) const
410 return tcu::getSubregion(m_wholeImage, 0, (m_1dModifier * layer), ((~m_1dModifier & 1) * layer), m_width, m_height, 1);
413 inline int getNumLayersOrSlices (void) const
419 // Specialized for 1D images.
420 LayeredImageAccess (const VkFormat format, const deUint32 width, const deUint32 numLayers, const void* pData)
421 : m_width (static_cast<int>(width))
424 , m_layers (numLayers)
425 , m_wholeImage (tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_layers, 1, pData))
429 LayeredImageAccess (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
430 : m_width (static_cast<int>(size.width))
431 , m_height (static_cast<int>(size.height))
433 , m_layers (static_cast<int>(type == VK_IMAGE_TYPE_3D ? size.depth : numLayers))
434 , m_wholeImage (tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_height, m_layers, pData))
440 const int m_1dModifier;
442 const tcu::ConstPixelBufferAccess m_wholeImage;
445 inline bool compareColors (const Vec4& colorA, const Vec4& colorB, const Vec4& threshold)
447 return tcu::allEqual(
448 tcu::lessThan(tcu::abs(colorA - colorB), threshold),
449 tcu::BVec4(true, true, true, true));
452 bool verifyImageSingleColoredRow (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image, const float rowWidthRatio, const tcu::Vec4& barColor)
454 DE_ASSERT(rowWidthRatio > 0.0f);
456 const Vec4 black (0.0f, 0.0f, 0.0f, 1.0f);
457 const Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
458 const Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
459 const Vec4 threshold (0.02f);
460 const int barLength = static_cast<int>(rowWidthRatio * static_cast<float>(image.getWidth()));
461 const int barLengthThreshold = 1;
462 tcu::TextureLevel errorMask (image.getFormat(), image.getWidth(), image.getHeight());
463 tcu::PixelBufferAccess errorMaskAccess = errorMask.getAccess();
465 tcu::clear(errorMask.getAccess(), green);
467 log << tcu::TestLog::Message
468 << "Expecting all pixels with distance less or equal to (about) " << barLength
469 << " pixels from left border to be of color " << barColor.swizzle(0, 1, 2) << "."
470 << tcu::TestLog::EndMessage;
472 bool allPixelsOk = true;
474 for (int y = 0; y < image.getHeight(); ++y)
475 for (int x = 0; x < image.getWidth(); ++x)
477 const Vec4 color = image.getPixel(x, y);
478 const bool isBlack = compareColors(color, black, threshold);
479 const bool isColor = compareColors(color, barColor, threshold);
483 if (x <= barLength - barLengthThreshold)
485 else if (x >= barLength + barLengthThreshold)
488 isOk = isColor || isBlack;
493 errorMaskAccess.setPixel(red, x, y);
498 log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
499 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
500 << tcu::TestLog::Image("Layer", "Layer", image)
501 << tcu::TestLog::EndImageSet;
506 log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
507 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
508 << tcu::TestLog::Image("Layer", "Layer", image)
509 << tcu::TestLog::Image("ErrorMask", "Errors", errorMask)
510 << tcu::TestLog::EndImageSet;
514 log << tcu::TestLog::Image("LayerContent", "Layer content", image);
519 bool verifyEmptyImage (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image)
521 log << tcu::TestLog::Message << "Expecting empty image" << tcu::TestLog::EndMessage;
523 const Vec4 black (0.0f, 0.0f, 0.0f, 1.0f);
524 const Vec4 threshold (0.02f);
526 for (int y = 0; y < image.getHeight(); ++y)
527 for (int x = 0; x < image.getWidth(); ++x)
529 const Vec4 color = image.getPixel(x, y);
531 if (!compareColors(color, black, threshold))
533 log << tcu::TestLog::Message
534 << "Found (at least) one bad pixel at " << x << "," << y << ". Pixel color is not background color."
535 << tcu::TestLog::EndMessage
536 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
537 << tcu::TestLog::Image("Layer", "Layer", image)
538 << tcu::TestLog::EndImageSet;
543 log << tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage;
548 bool verifyLayerContent (tcu::TestLog& log, const TestType testType, const tcu::ConstPixelBufferAccess image, const int layerNdx, const int numLayers)
550 const Vec4 white (1.0f, 1.0f, 1.0f, 1.0f);
551 const int targetLayer = numLayers / 2;
552 const float variableBarRatio = static_cast<float>(layerNdx) / static_cast<float>(numLayers);
556 case TEST_TYPE_DEFAULT_LAYER:
558 return verifyImageSingleColoredRow(log, image, 0.5f, white);
560 return verifyEmptyImage(log, image);
562 case TEST_TYPE_SINGLE_LAYER:
563 if (layerNdx == targetLayer)
564 return verifyImageSingleColoredRow(log, image, 0.5f, white);
566 return verifyEmptyImage(log, image);
568 case TEST_TYPE_ALL_LAYERS:
569 case TEST_TYPE_INVOCATION_PER_LAYER:
570 return verifyImageSingleColoredRow(log, image, 0.5f, s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
572 case TEST_TYPE_DIFFERENT_CONTENT:
573 case TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION:
575 return verifyEmptyImage(log, image);
577 return verifyImageSingleColoredRow(log, image, variableBarRatio, white);
579 case TEST_TYPE_LAYER_ID:
581 // This code must be in sync with the fragment shader.
582 const tcu::Vec4 layerColor( (layerNdx % 2) == 1 ? 1.0f : 0.5f,
583 ((layerNdx/2) % 2) == 1 ? 1.0f : 0.5f,
584 layerNdx == 0 ? 1.0f : 0.0f,
586 return verifyImageSingleColoredRow(log, image, 0.5f, layerColor);
595 std::string getLayerDescription (const VkImageViewType viewType, const int layer)
597 std::ostringstream str;
598 const int numCubeFaces = 6;
600 if (isCubeImageViewType(viewType))
601 str << "cube " << (layer / numCubeFaces) << ", face " << (layer % numCubeFaces);
602 else if (viewType == VK_IMAGE_VIEW_TYPE_3D)
603 str << "slice z = " << layer;
605 str << "layer " << layer;
610 bool verifyResults (tcu::TestLog& log, const TestParams& params, const VkFormat colorFormat, const void* resultData)
612 const LayeredImageAccess image = LayeredImageAccess::create(getImageType(params.image.viewType), colorFormat, params.image.size, params.image.numLayers, resultData);
614 int numGoodLayers = 0;
616 for (int layerNdx = 0; layerNdx < image.getNumLayersOrSlices(); ++layerNdx)
618 const tcu::ConstPixelBufferAccess layerImage = image.getLayer(layerNdx);
620 log << tcu::TestLog::Message << "Verifying " << getLayerDescription(params.image.viewType, layerNdx) << tcu::TestLog::EndMessage;
622 if (verifyLayerContent(log, params.testType, layerImage, layerNdx, image.getNumLayersOrSlices()))
626 return numGoodLayers == image.getNumLayersOrSlices();
629 std::string toGlsl (const Vec4& v)
631 std::ostringstream str;
633 for (int i = 0; i < 4; ++i)
634 str << (i != 0 ? ", " : "") << de::floatToString(v[i], 1);
639 void initPrograms (SourceCollections& programCollection, const TestParams params)
641 const bool geomOutputColor = (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_INVOCATION_PER_LAYER);
645 std::ostringstream src;
646 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
648 << "void main(void)\n"
652 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
657 const int numLayers = static_cast<int>(params.image.viewType == VK_IMAGE_VIEW_TYPE_3D ? params.image.size.depth : params.image.numLayers);
659 const int maxVertices = (params.testType == TEST_TYPE_DIFFERENT_CONTENT) ? (numLayers + 1) * numLayers :
660 (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_LAYER_ID) ? numLayers * 4 :
661 (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION) ? 6 : 4;
663 std::ostringstream src;
664 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
667 if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
668 src << "layout(points, invocations = " << numLayers << ") in;\n";
670 src << "layout(points) in;\n";
672 src << "layout(triangle_strip, max_vertices = " << maxVertices << ") out;\n"
674 << (geomOutputColor ? "layout(location = 0) out vec4 vert_color;\n\n" : "")
675 << "out gl_PerVertex {\n"
676 << " vec4 gl_Position;\n"
679 << "void main(void)\n"
682 std::ostringstream colorTable;
684 const int numColors = DE_LENGTH_OF_ARRAY(s_colors);
686 colorTable << " const vec4 colors[" << numColors << "] = vec4[" << numColors << "](";
688 const std::string padding(colorTable.str().length(), ' ');
690 for (int i = 0; i < numColors; ++i)
691 colorTable << (i != 0 ? ",\n" + padding : "") << toGlsl(s_colors[i]);
693 colorTable << ");\n";
696 if (params.testType == TEST_TYPE_DEFAULT_LAYER)
698 src << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
699 << " EmitVertex();\n"
701 << " gl_Position = vec4(-1.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 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
708 << " EmitVertex();\n";
710 else if (params.testType == TEST_TYPE_SINGLE_LAYER)
712 const deUint32 targetLayer = getTargetLayer(params.image);
714 src << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
715 << " gl_Layer = " << targetLayer << ";\n"
716 << " EmitVertex();\n"
718 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
719 << " gl_Layer = " << targetLayer << ";\n"
720 << " EmitVertex();\n"
722 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
723 << " gl_Layer = " << targetLayer << ";\n"
724 << " EmitVertex();\n"
726 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
727 << " gl_Layer = " << targetLayer << ";\n"
728 << " EmitVertex();\n";
730 else if (params.testType == TEST_TYPE_ALL_LAYERS)
732 src << colorTable.str()
734 << " for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
735 << " const int colorNdx = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
737 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
738 << " gl_Layer = layerNdx;\n"
739 << " vert_color = colors[colorNdx];\n"
740 << " EmitVertex();\n"
742 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
743 << " gl_Layer = layerNdx;\n"
744 << " vert_color = colors[colorNdx];\n"
745 << " EmitVertex();\n"
747 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
748 << " gl_Layer = layerNdx;\n"
749 << " vert_color = colors[colorNdx];\n"
750 << " EmitVertex();\n"
752 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
753 << " gl_Layer = layerNdx;\n"
754 << " vert_color = colors[colorNdx];\n"
755 << " EmitVertex();\n"
756 << " EndPrimitive();\n"
759 else if (params.testType == TEST_TYPE_LAYER_ID)
761 src << " for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
762 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
763 << " gl_Layer = layerNdx;\n"
764 << " EmitVertex();\n"
766 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
767 << " gl_Layer = layerNdx;\n"
768 << " EmitVertex();\n"
770 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
771 << " gl_Layer = layerNdx;\n"
772 << " EmitVertex();\n"
774 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
775 << " gl_Layer = layerNdx;\n"
776 << " EmitVertex();\n"
777 << " EndPrimitive();\n"
780 else if (params.testType == TEST_TYPE_DIFFERENT_CONTENT)
782 src << " for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
783 << " for (int colNdx = 0; colNdx <= layerNdx; ++colNdx) {\n"
784 << " const float posX = float(colNdx) / float(" << numLayers << ") * 2.0 - 1.0;\n"
786 << " gl_Position = vec4(posX, 1.0, 0.0, 1.0);\n"
787 << " gl_Layer = layerNdx;\n"
788 << " EmitVertex();\n"
790 << " gl_Position = vec4(posX, -1.0, 0.0, 1.0);\n"
791 << " gl_Layer = layerNdx;\n"
792 << " EmitVertex();\n"
794 << " EndPrimitive();\n"
797 else if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER)
799 src << colorTable.str()
800 << " const int colorNdx = gl_InvocationID % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
802 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
803 << " gl_Layer = gl_InvocationID;\n"
804 << " vert_color = colors[colorNdx];\n"
805 << " EmitVertex();\n"
807 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
808 << " gl_Layer = gl_InvocationID;\n"
809 << " vert_color = colors[colorNdx];\n"
810 << " EmitVertex();\n"
812 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
813 << " gl_Layer = gl_InvocationID;\n"
814 << " vert_color = colors[colorNdx];\n"
815 << " EmitVertex();\n"
817 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
818 << " gl_Layer = gl_InvocationID;\n"
819 << " vert_color = colors[colorNdx];\n"
820 << " EmitVertex();\n"
821 << " EndPrimitive();\n";
823 else if (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
825 src << " const int layerA = gl_InvocationID;\n"
826 << " const int layerB = (gl_InvocationID + 1) % " << numLayers << ";\n"
827 << " const float aEnd = float(layerA) / float(" << numLayers << ") * 2.0 - 1.0;\n"
828 << " const float bEnd = float(layerB) / float(" << numLayers << ") * 2.0 - 1.0;\n"
830 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
831 << " gl_Layer = layerA;\n"
832 << " EmitVertex();\n"
834 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
835 << " gl_Layer = layerA;\n"
836 << " EmitVertex();\n"
838 << " gl_Position = vec4(aEnd, -1.0, 0.0, 1.0);\n"
839 << " gl_Layer = layerA;\n"
840 << " EmitVertex();\n"
841 << " EndPrimitive();\n"
843 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
844 << " gl_Layer = layerB;\n"
845 << " EmitVertex();\n"
847 << " gl_Position = vec4(bEnd, 1.0, 0.0, 1.0);\n"
848 << " gl_Layer = layerB;\n"
849 << " EmitVertex();\n"
851 << " gl_Position = vec4(bEnd, -1.0, 0.0, 1.0);\n"
852 << " gl_Layer = layerB;\n"
853 << " EmitVertex();\n"
854 << " EndPrimitive();\n";
859 src << "}\n"; // end main
861 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
866 std::ostringstream src;
867 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
869 << "layout(location = 0) out vec4 o_color;\n"
870 << (geomOutputColor ? "layout(location = 0) in vec4 vert_color;\n" : "")
872 << "void main(void)\n"
875 if (params.testType == TEST_TYPE_LAYER_ID)
877 // This code must be in sync with verifyLayerContent()
878 src << " o_color = vec4( (gl_Layer % 2) == 1 ? 1.0 : 0.5,\n"
879 << " ((gl_Layer/2) % 2) == 1 ? 1.0 : 0.5,\n"
880 << " gl_Layer == 0 ? 1.0 : 0.0,\n"
883 else if (geomOutputColor)
884 src << " o_color = vert_color;\n";
886 src << " o_color = vec4(1.0);\n";
890 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
894 tcu::TestStatus test (Context& context, const TestParams params)
896 if (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType &&
897 (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_maintenance1")))
898 TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
900 const DeviceInterface& vk = context.getDeviceInterface();
901 const InstanceInterface& vki = context.getInstanceInterface();
902 const VkDevice device = context.getDevice();
903 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
904 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
905 const VkQueue queue = context.getUniversalQueue();
906 Allocator& allocator = context.getDefaultAllocator();
908 checkGeometryShaderSupport(vki, physDevice);
910 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
911 const deUint32 numLayers = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
912 const Vec4 clearColor = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
913 const VkDeviceSize colorBufferSize = params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * tcu::getPixelSize(mapVkFormat(colorFormat));
914 const VkImageCreateFlags imageCreateFlags = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
915 (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
916 const VkImageViewType viewType = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
918 const Unique<VkImage> colorImage (makeImage (vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
919 params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
920 const UniquePtr<Allocation> colorImageAlloc (bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any));
921 const Unique<VkImageView> colorAttachment (makeImageView (vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
923 const Unique<VkBuffer> colorBuffer (makeBuffer (vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
924 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
926 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
927 const Unique<VkShaderModule> geometryModule (createShaderModule (vk, device, context.getBinaryCollection().get("geom"), 0u));
928 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
930 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, colorFormat));
931 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, *colorAttachment, params.image.size.width, params.image.size.height, numLayers));
932 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device));
933 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
934 makeExtent2D(params.image.size.width, params.image.size.height)));
935 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
936 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
938 zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
940 beginCommandBuffer(vk, *cmdBuffer);
942 const VkClearValue clearValue = makeClearValueColor(clearColor);
943 const VkRect2D renderArea =
946 makeExtent2D(params.image.size.width, params.image.size.height),
948 const VkRenderPassBeginInfo renderPassBeginInfo =
950 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
951 DE_NULL, // const void* pNext;
952 *renderPass, // VkRenderPass renderPass;
953 *framebuffer, // VkFramebuffer framebuffer;
954 renderArea, // VkRect2D renderArea;
955 1u, // uint32_t clearValueCount;
956 &clearValue, // const VkClearValue* pClearValues;
958 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
960 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
961 vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
962 vk.cmdEndRenderPass(*cmdBuffer);
964 // Prepare color image for copy
966 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers);
967 const VkImageMemoryBarrier barriers[] =
970 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
971 DE_NULL, // const void* pNext;
972 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask;
973 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask;
974 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
975 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
976 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
977 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
978 *colorImage, // VkImage image;
979 colorSubresourceRange, // VkImageSubresourceRange subresourceRange;
983 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
984 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
986 // Color image -> host buffer
988 const VkBufferImageCopy region =
990 0ull, // VkDeviceSize bufferOffset;
991 0u, // uint32_t bufferRowLength;
992 0u, // uint32_t bufferImageHeight;
993 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, params.image.numLayers), // VkImageSubresourceLayers imageSubresource;
994 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
995 params.image.size, // VkExtent3D imageExtent;
998 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
1000 // Buffer write barrier
1002 const VkBufferMemoryBarrier barriers[] =
1005 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1006 DE_NULL, // const void* pNext;
1007 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1008 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1009 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1010 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1011 *colorBuffer, // VkBuffer buffer;
1012 0ull, // VkDeviceSize offset;
1013 VK_WHOLE_SIZE, // VkDeviceSize size;
1017 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1018 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u);
1021 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1022 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1024 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSize);
1026 if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1027 return tcu::TestStatus::fail("Rendered images are incorrect");
1029 return tcu::TestStatus::pass("OK");
1034 tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx)
1036 MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "layered", "Layered rendering tests."));
1042 const char* description;
1045 { TEST_TYPE_DEFAULT_LAYER, "render_to_default_layer", "Render to the default layer" },
1046 { TEST_TYPE_SINGLE_LAYER, "render_to_one", "Render to one layer" },
1047 { TEST_TYPE_ALL_LAYERS, "render_to_all", "Render to all layers" },
1048 { TEST_TYPE_DIFFERENT_CONTENT, "render_different_content", "Render different data to different layers" },
1049 { TEST_TYPE_LAYER_ID, "fragment_layer", "Read gl_Layer in fragment shader" },
1050 { TEST_TYPE_INVOCATION_PER_LAYER, "invocation_per_layer", "Render to multiple layers with multiple invocations, one invocation per layer" },
1051 { TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION, "multiple_layers_per_invocation", "Render to multiple layers with multiple invocations, multiple layers per invocation", },
1054 const ImageParams imageParams[] =
1056 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, { 64, 1, 1 }, 4 },
1057 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, { 64, 64, 1 }, 4 },
1058 { VK_IMAGE_VIEW_TYPE_CUBE, { 64, 64, 1 }, 6 },
1059 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, { 64, 64, 1 }, 2*6 },
1060 { VK_IMAGE_VIEW_TYPE_3D, { 64, 64, 8 }, 1 }
1063 for (int imageParamNdx = 0; imageParamNdx < DE_LENGTH_OF_ARRAY(imageParams); ++imageParamNdx)
1065 MovePtr<tcu::TestCaseGroup> viewTypeGroup(new tcu::TestCaseGroup(testCtx, getShortImageViewTypeName(imageParams[imageParamNdx].viewType).c_str(), ""));
1067 for (int testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx)
1069 const TestParams params =
1071 testTypes[testTypeNdx].test,
1072 imageParams[imageParamNdx],
1074 addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, initPrograms, test, params);
1077 group->addChild(viewTypeGroup.release());
1080 return group.release();