1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2019 Google Inc.
6 * Copyright (c) 2019 The Khronos Group Inc.
7 * Copyright (c) 2014 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Geometry shader layered rendering tests
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktGeometryLayeredRenderingTests.hpp"
27 #include "vktTestCase.hpp"
28 #include "vktTestCaseUtil.hpp"
29 #include "vktGeometryTestsUtil.hpp"
30
31 #include "vkPrograms.hpp"
32 #include "vkStrUtil.hpp"
33 #include "vkQueryUtil.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkRefUtil.hpp"
36 #include "vkBarrierUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkBuilderUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42
43 #include "deStringUtil.hpp"
44 #include "deUniquePtr.hpp"
45
46 #include "tcuTextureUtil.hpp"
47 #include "tcuVectorUtil.hpp"
48 #include "tcuTestLog.hpp"
49
50 namespace vkt
51 {
52 namespace geometry
53 {
54 namespace
55 {
56 using namespace vk;
57 using de::MovePtr;
58 using de::UniquePtr;
59 using tcu::Vec4;
60 using tcu::IVec3;
61
62 enum TestType
63 {
64 TEST_TYPE_DEFAULT_LAYER, // !< draw to default layer
65 TEST_TYPE_SINGLE_LAYER, // !< draw to single layer
66 TEST_TYPE_ALL_LAYERS, // !< draw all layers
67 TEST_TYPE_DIFFERENT_CONTENT, // !< draw different content to different layers
68 TEST_TYPE_LAYER_ID, // !< draw to all layers, verify gl_Layer fragment input
69 TEST_TYPE_INVOCATION_PER_LAYER, // !< draw to all layers, one invocation per layer
70 TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION, // !< draw to all layers, multiple invocations write to multiple layers
71 TEST_TYPE_LAYERED_READBACK, // !< draw to two layers multiple times
72 TEST_TYPE_SECONDARY_CMD_BUFFER // !< layered rendering using secondary command buffer
73 };
74
75 struct ImageParams
76 {
77 VkImageViewType viewType;
78 VkExtent3D size;
79 deUint32 numLayers;
80 };
81
82 struct TestParams
83 {
84 TestType testType;
85 ImageParams image;
86 bool inheritFramebuffer;
87 };
88
89 const float s_colors[][4] =
90 {
91 { 1.0f, 1.0f, 1.0f, 1.0f }, // white
92 { 1.0f, 0.0f, 0.0f, 1.0f }, // red
93 { 0.0f, 1.0f, 0.0f, 1.0f }, // green
94 { 0.0f, 0.0f, 1.0f, 1.0f }, // blue
95 { 1.0f, 1.0f, 0.0f, 1.0f }, // yellow
96 { 1.0f, 0.0f, 1.0f, 1.0f }, // magenta
97 };
98
99 const tcu::Vec4 secondaryCmdBufClearColors[] =
100 {
101 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
102 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
103 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
104 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
105 tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f),
106 tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f)
107 };
108
scaleColor(const tcu::Vec4 & color,float factor)109 tcu::Vec4 scaleColor(const tcu::Vec4& color, float factor)
110 {
111 return tcu::Vec4(color[0] * factor,
112 color[1] * factor,
113 color[2] * factor,
114 color[3]);
115 }
116
getTargetLayer(const ImageParams & imageParams)117 deUint32 getTargetLayer (const ImageParams& imageParams)
118 {
119 if (imageParams.viewType == VK_IMAGE_VIEW_TYPE_3D)
120 return imageParams.size.depth / 2;
121 else
122 return imageParams.numLayers / 2;
123 }
124
getShortImageViewTypeName(const VkImageViewType imageViewType)125 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
126 {
127 std::string s(getImageViewTypeName(imageViewType));
128 return de::toLower(s.substr(19));
129 }
130
getImageType(const VkImageViewType viewType)131 VkImageType getImageType (const VkImageViewType viewType)
132 {
133 switch (viewType)
134 {
135 case VK_IMAGE_VIEW_TYPE_1D:
136 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
137 return VK_IMAGE_TYPE_1D;
138
139 case VK_IMAGE_VIEW_TYPE_2D:
140 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
141 case VK_IMAGE_VIEW_TYPE_CUBE:
142 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
143 return VK_IMAGE_TYPE_2D;
144
145 case VK_IMAGE_VIEW_TYPE_3D:
146 return VK_IMAGE_TYPE_3D;
147
148 default:
149 DE_ASSERT(0);
150 return VK_IMAGE_TYPE_LAST;
151 }
152 }
153
getStencilBufferFormat(VkFormat depthStencilImageFormat)154 VkFormat getStencilBufferFormat(VkFormat depthStencilImageFormat)
155 {
156 const tcu::TextureFormat tcuFormat = mapVkFormat(depthStencilImageFormat);
157 const VkFormat result = (tcuFormat.order == tcu::TextureFormat::S || tcuFormat.order == tcu::TextureFormat::DS) ? VK_FORMAT_S8_UINT : VK_FORMAT_UNDEFINED;
158
159 DE_ASSERT(result != VK_FORMAT_UNDEFINED);
160
161 return result;
162 }
163
isCubeImageViewType(const VkImageViewType viewType)164 inline bool isCubeImageViewType (const VkImageViewType viewType)
165 {
166 return viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
167 }
168
checkImageFormatProperties(const InstanceInterface & vki,const VkPhysicalDevice & physDevice,const VkImageType & imageType,const VkImageTiling & imageTiling,const VkImageUsageFlags imageUsageFlags,const VkImageCreateFlags imageCreateFlags,const VkFormat format,const VkExtent3D & requiredSize,const deUint32 requiredLayers)169 void checkImageFormatProperties (const InstanceInterface& vki,
170 const VkPhysicalDevice& physDevice,
171 const VkImageType& imageType,
172 const VkImageTiling& imageTiling,
173 const VkImageUsageFlags imageUsageFlags,
174 const VkImageCreateFlags imageCreateFlags,
175 const VkFormat format,
176 const VkExtent3D& requiredSize,
177 const deUint32 requiredLayers)
178 {
179 VkImageFormatProperties imageFormatProperties;
180 VkResult result;
181
182 deMemset(&imageFormatProperties, 0, sizeof(imageFormatProperties));
183
184 result = vki.getPhysicalDeviceImageFormatProperties(physDevice, format, imageType, imageTiling, imageUsageFlags, imageCreateFlags, &imageFormatProperties);
185
186 if (result != VK_SUCCESS ||
187 imageFormatProperties.maxArrayLayers < requiredLayers ||
188 imageFormatProperties.maxExtent.height < requiredSize.height ||
189 imageFormatProperties.maxExtent.width < requiredSize.width ||
190 imageFormatProperties.maxExtent.depth < requiredSize.depth)
191 {
192 TCU_THROW(NotSupportedError, "Depth/stencil format is not supported");
193 }
194 }
195
makeImageCreateInfo(const VkImageCreateFlags flags,const VkImageType type,const VkFormat format,const VkExtent3D size,const deUint32 numLayers,const VkImageUsageFlags usage)196 VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const VkImageUsageFlags usage)
197 {
198 const VkImageCreateInfo imageParams =
199 {
200 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
201 DE_NULL, // const void* pNext;
202 flags, // VkImageCreateFlags flags;
203 type, // VkImageType imageType;
204 format, // VkFormat format;
205 size, // VkExtent3D extent;
206 1u, // deUint32 mipLevels;
207 numLayers, // deUint32 arrayLayers;
208 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
209 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
210 usage, // VkImageUsageFlags usage;
211 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
212 0u, // deUint32 queueFamilyIndexCount;
213 DE_NULL, // const deUint32* pQueueFamilyIndices;
214 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
215 };
216 return imageParams;
217 }
218
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkFormat dsFormat,const bool useDepthStencil)219 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
220 const VkDevice device,
221 const VkFormat colorFormat,
222 const VkFormat dsFormat,
223 const bool useDepthStencil)
224 {
225 return vk::makeRenderPass(vk, device, colorFormat, useDepthStencil ? dsFormat : VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD);
226 }
227
makeRenderPassWithSelfDependency(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat)228 Move<VkRenderPass> makeRenderPassWithSelfDependency (const DeviceInterface& vk,
229 const VkDevice device,
230 const VkFormat colorFormat)
231 {
232 const VkAttachmentDescription attachmentDescription =
233 {
234 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
235 colorFormat, // VkFormat format
236 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
237 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
238 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
239 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
240 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
241 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
242 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
243 };
244
245 const VkAttachmentReference colorAttachmentRef =
246 {
247 0u, // deUint32 attachment
248 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout
249 };
250
251 const VkSubpassDescription subpassDescription =
252 {
253 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
254 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
255 0u, // deUint32 inputAttachmentCount
256 DE_NULL, // const VkAttachmentReference* pInputAttachments
257 1u, // deUint32 colorAttachmentCount
258 &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments
259 DE_NULL, // const VkAttachmentReference* pResolveAttachments
260 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment
261 0u, // deUint32 preserveAttachmentCount
262 DE_NULL // const deUint32* pPreserveAttachments
263 };
264
265 const VkSubpassDependency subpassDependency =
266 {
267 0u, // deUint32 srcSubpass
268 0u, // deUint32 dstSubpass
269 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags srcStageMask
270 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask
271 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask
272 VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask
273 0u, // VkDependencyFlags dependencyFlags
274 };
275
276 const VkRenderPassCreateInfo renderPassInfo =
277 {
278 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType
279 DE_NULL, // const void* pNext
280 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
281 1u, // deUint32 attachmentCount
282 &attachmentDescription, // const VkAttachmentDescription* pAttachments
283 1u, // deUint32 subpassCount
284 &subpassDescription, // const VkSubpassDescription* pSubpasses
285 1u, // deUint32 dependencyCount
286 &subpassDependency // const VkSubpassDependency* pDependencies
287 };
288
289 return createRenderPass(vk, device, &renderPassInfo);
290 }
291
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule geometryModule,const VkShaderModule fragmentModule,const VkExtent2D renderSize,const bool useDepthStencil=false)292 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
293 const VkDevice device,
294 const VkPipelineLayout pipelineLayout,
295 const VkRenderPass renderPass,
296 const VkShaderModule vertexModule,
297 const VkShaderModule geometryModule,
298 const VkShaderModule fragmentModule,
299 const VkExtent2D renderSize,
300 const bool useDepthStencil = false)
301 {
302 const std::vector<VkViewport> viewports (1, makeViewport(renderSize));
303 const std::vector<VkRect2D> scissors (1, makeRect2D(renderSize));
304
305 const VkStencilOpState stencilOpState = makeStencilOpState(
306 VK_STENCIL_OP_KEEP, // stencil fail
307 VK_STENCIL_OP_INCREMENT_AND_CLAMP, // depth & stencil pass
308 VK_STENCIL_OP_KEEP, // depth only fail
309 VK_COMPARE_OP_ALWAYS, // compare op
310 ~0u, // compare mask
311 ~0u, // write mask
312 0u); // reference
313
314 const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
315 {
316 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
317 DE_NULL, // const void* pNext
318 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags
319 useDepthStencil ? VK_TRUE : VK_FALSE, // VkBool32 depthTestEnable
320 useDepthStencil ? VK_TRUE : VK_FALSE, // VkBool32 depthWriteEnable
321 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp
322 VK_FALSE, // VkBool32 depthBoundsTestEnable
323 useDepthStencil ? VK_TRUE : VK_FALSE, // VkBool32 stencilTestEnable
324 stencilOpState, // VkStencilOpState front
325 stencilOpState, // VkStencilOpState back
326 0.0f, // float minDepthBounds
327 1.0f // float maxDepthBounds
328 };
329
330 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
331 {
332 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
333 DE_NULL, // const void* pNext
334 0u, // VkPipelineVertexInputStateCreateFlags flags
335 0u, // deUint32 vertexBindingDescriptionCount
336 DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
337 0u, // deUint32 vertexAttributeDescriptionCount
338 DE_NULL // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
339 };
340
341 return vk::makeGraphicsPipeline(vk, // const DeviceInterface& vk
342 device, // const VkDevice device
343 pipelineLayout, // const VkPipelineLayout pipelineLayout
344 vertexModule, // const VkShaderModule vertexShaderModule
345 DE_NULL, // const VkShaderModule tessellationControlModule
346 DE_NULL, // const VkShaderModule tessellationEvalModule
347 geometryModule, // const VkShaderModule geometryShaderModule
348 fragmentModule, // const VkShaderModule fragmentShaderModule
349 renderPass, // const VkRenderPass renderPass
350 viewports, // const std::vector<VkViewport>& viewports
351 scissors, // const std::vector<VkRect2D>& scissors
352 VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // const VkPrimitiveTopology topology
353 0u, // const deUint32 subpass
354 0u, // const deUint32 patchControlPoints
355 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
356 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
357 DE_NULL, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
358 &pipelineDepthStencilStateInfo); // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
359 }
360
copyLayeredImageToBuffer(const DeviceInterface & vk,VkCommandBuffer cmdBuffer,VkImage image,VkBuffer buffer,const ImageParams & imageParams)361 void copyLayeredImageToBuffer(const DeviceInterface& vk, VkCommandBuffer cmdBuffer, VkImage image, VkBuffer buffer, const ImageParams& imageParams)
362 {
363 // Image read barrier
364 {
365 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, imageParams.numLayers);
366 const VkImageMemoryBarrier barrier =
367 {
368 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
369 DE_NULL, // const void* pNext
370 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask
371 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask
372 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout
373 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout
374 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex
375 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex
376 image, // VkImage image
377 colorSubresourceRange // VkImageSubresourceRange subresourceRange
378 };
379
380 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
381 }
382 // Color image -> host buffer
383 {
384 const VkBufferImageCopy region =
385 {
386 0ull, // VkDeviceSize bufferOffset
387 0u, // deUint32 bufferRowLength
388 0u, // deUint32 bufferImageHeight
389 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageParams.numLayers), // VkImageSubresourceLayers imageSubresource
390 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset
391 imageParams.size // VkExtent3D imageExtent
392 };
393
394 vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, ®ion);
395 }
396 // Buffer write barrier
397 {
398 const VkBufferMemoryBarrier barrier =
399 {
400 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType
401 DE_NULL, // const void* pNext
402 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
403 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask
404 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex
405 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex
406 buffer, // VkBuffer buffer
407 0ull, // VkDeviceSize offset
408 VK_WHOLE_SIZE // VkDeviceSize size
409 };
410
411 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &barrier, DE_NULL, 0u);
412 }
413 }
414
415 //! Convenience wrapper to access 1D, 2D, and 3D image layers/slices in a uniform way.
416 class LayeredImageAccess
417 {
418 public:
create(const VkImageType type,const VkFormat format,const VkExtent3D size,const deUint32 numLayers,const void * pData)419 static LayeredImageAccess create (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
420 {
421 if (type == VK_IMAGE_TYPE_1D)
422 return LayeredImageAccess(format, size.width, numLayers, pData);
423 else
424 return LayeredImageAccess(type, format, size, numLayers, pData);
425 }
426
getLayer(const int layer) const427 inline tcu::ConstPixelBufferAccess getLayer (const int layer) const
428 {
429 return tcu::getSubregion(m_wholeImage, 0, (m_1dModifier * layer), ((~m_1dModifier & 1) * layer), m_width, m_height, 1);
430 }
431
getNumLayersOrSlices(void) const432 inline int getNumLayersOrSlices (void) const
433 {
434 return m_layers;
435 }
436
437 private:
438 // Specialized for 1D images.
LayeredImageAccess(const VkFormat format,const deUint32 width,const deUint32 numLayers,const void * pData)439 LayeredImageAccess (const VkFormat format, const deUint32 width, const deUint32 numLayers, const void* pData)
440 : m_width (static_cast<int>(width))
441 , m_height (1)
442 , m_1dModifier (1)
443 , m_layers (numLayers)
444 , m_wholeImage (tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_layers, 1, pData))
445 {
446 }
447
LayeredImageAccess(const VkImageType type,const VkFormat format,const VkExtent3D size,const deUint32 numLayers,const void * pData)448 LayeredImageAccess (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
449 : m_width (static_cast<int>(size.width))
450 , m_height (static_cast<int>(size.height))
451 , m_1dModifier (0)
452 , m_layers (static_cast<int>(type == VK_IMAGE_TYPE_3D ? size.depth : numLayers))
453 , m_wholeImage (tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_height, m_layers, pData))
454 {
455 }
456
457 const int m_width;
458 const int m_height;
459 const int m_1dModifier;
460 const int m_layers;
461 const tcu::ConstPixelBufferAccess m_wholeImage;
462 };
463
compareColors(const Vec4 & colorA,const Vec4 & colorB,const Vec4 & threshold)464 inline bool compareColors (const Vec4& colorA, const Vec4& colorB, const Vec4& threshold)
465 {
466 return tcu::allEqual(
467 tcu::lessThan(tcu::abs(colorA - colorB), threshold),
468 tcu::BVec4(true, true, true, true));
469 }
470
verifyImageSingleColoredRow(tcu::TestLog & log,const tcu::ConstPixelBufferAccess image,const float rowWidthRatio,const tcu::Vec4 & barColor,bool topRightCleared=false,bool bottomRightCleared=false)471 bool verifyImageSingleColoredRow (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image, const float rowWidthRatio, const tcu::Vec4& barColor, bool topRightCleared = false, bool bottomRightCleared = false)
472 {
473 DE_ASSERT(rowWidthRatio > 0.0f);
474
475 const Vec4 black (0.0f, 0.0f, 0.0f, 1.0f);
476 const Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
477 const Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
478 const Vec4 brown (0.5f, 0.25f, 0.0f, 1.0f);
479 const Vec4 threshold (0.02f);
480 const int barLength = static_cast<int>(rowWidthRatio * static_cast<float>(image.getWidth()));
481 const int barLengthThreshold = 1;
482 tcu::TextureLevel errorMask (image.getFormat(), image.getWidth(), image.getHeight());
483 tcu::PixelBufferAccess errorMaskAccess = errorMask.getAccess();
484
485 tcu::clear(errorMask.getAccess(), green);
486
487 log << tcu::TestLog::Message
488 << "Expecting all pixels with distance less or equal to (about) " << barLength
489 << " pixels from left border to be of color " << barColor.swizzle(0, 1, 2) << "."
490 << tcu::TestLog::EndMessage;
491
492 bool allPixelsOk = true;
493
494 for (int y = 0; y < image.getHeight(); ++y)
495 for (int x = 0; x < image.getWidth(); ++x)
496 {
497 const Vec4 color = image.getPixel(x, y);
498 const bool isBlack = compareColors(color, black, threshold);
499 const bool isBrown = compareColors(color, brown, threshold);
500 const bool isColor = compareColors(color, barColor, threshold);
501 const bool isOutsideColor = ((topRightCleared && y < image.getHeight() / 2) || (bottomRightCleared && y >= image.getHeight() / 2)) ? isBrown : isBlack;
502
503 bool isOk;
504
505 if (x <= barLength - barLengthThreshold)
506 isOk = isColor;
507 else if (x >= barLength + barLengthThreshold)
508 {
509 isOk = isOutsideColor;
510 }
511 else
512 isOk = isColor || isOutsideColor;
513
514 allPixelsOk &= isOk;
515
516 if (!isOk)
517 errorMaskAccess.setPixel(red, x, y);
518 }
519
520 if (allPixelsOk)
521 {
522 log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
523 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
524 << tcu::TestLog::Image("Layer", "Layer", image)
525 << tcu::TestLog::EndImageSet;
526 return true;
527 }
528 else
529 {
530 log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
531 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
532 << tcu::TestLog::Image("Layer", "Layer", image)
533 << tcu::TestLog::Image("ErrorMask", "Errors", errorMask)
534 << tcu::TestLog::EndImageSet;
535 return false;
536 }
537
538 log << tcu::TestLog::Image("LayerContent", "Layer content", image);
539
540 return allPixelsOk;
541 }
542
verifyImageMultipleBars(tcu::TestLog & log,const tcu::ConstPixelBufferAccess image,const float * barWidthRatios,const tcu::Vec4 * barValues,const int barsCount,const int numUsedChannels,const std::string & imageTypeName)543 static bool verifyImageMultipleBars (tcu::TestLog& log,
544 const tcu::ConstPixelBufferAccess image,
545 const float* barWidthRatios,
546 const tcu::Vec4* barValues,
547 const int barsCount,
548 const int numUsedChannels,
549 const std::string& imageTypeName)
550 {
551 const Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
552 const Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
553 const Vec4 threshold (0.02f);
554 const tcu::TextureFormat errorMaskFormat (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8));
555 tcu::TextureLevel errorMask (errorMaskFormat, image.getWidth(), image.getHeight());
556 tcu::PixelBufferAccess errorMaskAccess = errorMask.getAccess();
557 bool allPixelsOk = true;
558
559 DE_ASSERT(barsCount > 0);
560
561 tcu::clear(errorMask.getAccess(), green);
562
563 // Format information message
564 {
565 int leftBorder = 0;
566 int rightBorder = 0;
567 std::ostringstream str;
568
569 for (int barNdx = 0; barNdx < barsCount; ++barNdx)
570 {
571 leftBorder = rightBorder;
572 rightBorder = static_cast<int>(barWidthRatios[barNdx] * static_cast<float>(image.getWidth()));
573
574 DE_ASSERT(leftBorder < rightBorder);
575
576 str << std::endl << " [" << leftBorder << "," <<rightBorder << "): ";
577
578 switch (numUsedChannels)
579 {
580 case 1: str << barValues[barNdx][0]; break;
581 case 4: str << barValues[barNdx]; break;
582 default: DE_ASSERT(false); break;
583 }
584 }
585
586 log << tcu::TestLog::Message
587 << "Expecting " + imageTypeName + " values depending x-axis position to be of following values: "
588 << str.str()
589 << tcu::TestLog::EndMessage;
590 }
591
592 for (int x = 0; x < image.getWidth(); ++x)
593 {
594 tcu::Vec4 expectedValue = barValues[0];
595
596 for (int barNdx = 0; barNdx < barsCount; ++barNdx)
597 {
598 const int rightBorder = static_cast<int>(barWidthRatios[barNdx] * static_cast<float>(image.getWidth()));
599
600 if (x < rightBorder)
601 {
602 expectedValue = barValues[barNdx];
603
604 break;
605 }
606 }
607
608 for (int y = 0; y < image.getHeight(); ++y)
609 {
610 const tcu::Vec4 realValue = image.getPixel(x, y);
611 bool isOk = false;
612
613 switch (numUsedChannels)
614 {
615 case 1: isOk = fabs(realValue[0] - expectedValue[0]) < threshold[0]; break;
616 case 4: isOk = compareColors(realValue, expectedValue, threshold); break;
617 default: DE_ASSERT(false); break;
618 }
619
620 if (!isOk)
621 errorMaskAccess.setPixel(red, x, y);
622
623 allPixelsOk = allPixelsOk && isOk;
624 }
625 }
626
627 if (allPixelsOk)
628 {
629 log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
630 << tcu::TestLog::ImageSet(imageTypeName + "LayerContent", imageTypeName + " Layer Content")
631 << tcu::TestLog::Image("Layer", "Layer", image)
632 << tcu::TestLog::EndImageSet;
633 }
634 else
635 {
636 log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
637 << tcu::TestLog::ImageSet(imageTypeName + "LayerContent", imageTypeName + " Layer Content")
638 << tcu::TestLog::Image("Layer", "Layer", image)
639 << tcu::TestLog::Image("ErrorMask", "Errors", errorMask)
640 << tcu::TestLog::EndImageSet;
641 }
642
643 return allPixelsOk;
644 }
645
convertDepthToColorBufferAccess(const tcu::ConstPixelBufferAccess & inputImage,tcu::PixelBufferAccess & outputImage)646 static void convertDepthToColorBufferAccess (const tcu::ConstPixelBufferAccess& inputImage, tcu::PixelBufferAccess& outputImage)
647 {
648 for (int y = 0; y < inputImage.getHeight(); y++)
649 for (int x = 0; x < inputImage.getWidth(); x++)
650 {
651 const float depth = inputImage.getPixDepth(x, y);
652 const tcu::Vec4 color = tcu::Vec4(depth, depth, depth, 1.0f);
653
654 outputImage.setPixel(color, x, y);
655 }
656 }
657
convertStencilToColorBufferAccess(const tcu::ConstPixelBufferAccess & inputImage,tcu::PixelBufferAccess & outputImage,int maxValue)658 static void convertStencilToColorBufferAccess (const tcu::ConstPixelBufferAccess& inputImage, tcu::PixelBufferAccess& outputImage, int maxValue)
659 {
660 for (int y = 0; y < inputImage.getHeight(); y++)
661 for (int x = 0; x < inputImage.getWidth(); x++)
662 {
663 const int stencilInt = inputImage.getPixStencil(x, y);
664 const float stencil = (stencilInt < maxValue) ? float(stencilInt) / float(maxValue) : 1.0f;
665 const tcu::Vec4 color = tcu::Vec4(stencil, stencil, stencil, 1.0f);
666
667 outputImage.setPixel(color, x, y);
668 }
669 }
670
verifyEmptyImage(tcu::TestLog & log,const tcu::ConstPixelBufferAccess image)671 bool verifyEmptyImage (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image)
672 {
673 log << tcu::TestLog::Message << "Expecting empty image" << tcu::TestLog::EndMessage;
674
675 const Vec4 black (0.0f, 0.0f, 0.0f, 1.0f);
676 const Vec4 threshold (0.02f);
677
678 for (int y = 0; y < image.getHeight(); ++y)
679 for (int x = 0; x < image.getWidth(); ++x)
680 {
681 const Vec4 color = image.getPixel(x, y);
682
683 if (!compareColors(color, black, threshold))
684 {
685 log << tcu::TestLog::Message
686 << "Found (at least) one bad pixel at " << x << "," << y << ". Pixel color is not background color."
687 << tcu::TestLog::EndMessage
688 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
689 << tcu::TestLog::Image("Layer", "Layer", image)
690 << tcu::TestLog::EndImageSet;
691 return false;
692 }
693 }
694
695 log << tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage;
696
697 return true;
698 }
699
verifyLayerContent(tcu::TestLog & log,const TestType testType,const tcu::ConstPixelBufferAccess image,const int layerNdx,const int numLayers,const bool depthCheck,const bool stencilCheck)700 bool verifyLayerContent (tcu::TestLog& log, const TestType testType, const tcu::ConstPixelBufferAccess image, const int layerNdx, const int numLayers, const bool depthCheck, const bool stencilCheck)
701 {
702 const Vec4 white (1.0f, 1.0f, 1.0f, 1.0f);
703 const int targetLayer = numLayers / 2;
704 const float variableBarRatio = static_cast<float>(layerNdx) / static_cast<float>(numLayers);
705
706 switch (testType)
707 {
708 case TEST_TYPE_DEFAULT_LAYER:
709 if (layerNdx == 0)
710 return verifyImageSingleColoredRow(log, image, 0.5f, white);
711 else
712 return verifyEmptyImage(log, image);
713
714 case TEST_TYPE_SINGLE_LAYER:
715 if (layerNdx == targetLayer)
716 return verifyImageSingleColoredRow(log, image, 0.5f, white);
717 else
718 return verifyEmptyImage(log, image);
719
720 case TEST_TYPE_ALL_LAYERS:
721 case TEST_TYPE_INVOCATION_PER_LAYER:
722 return verifyImageSingleColoredRow(log, image, 0.5f, s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
723
724 case TEST_TYPE_DIFFERENT_CONTENT:
725 case TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION:
726 if (layerNdx == 0)
727 return verifyEmptyImage(log, image);
728 else
729 return verifyImageSingleColoredRow(log, image, variableBarRatio, white);
730
731 case TEST_TYPE_LAYER_ID:
732 {
733 // This code must be in sync with the fragment shader.
734 const tcu::Vec4 layerColor( (layerNdx % 2) == 1 ? 1.0f : 0.5f,
735 ((layerNdx/2) % 2) == 1 ? 1.0f : 0.5f,
736 layerNdx == 0 ? 1.0f : 0.0f,
737 1.0f);
738 return verifyImageSingleColoredRow(log, image, 0.5f, layerColor);
739 }
740
741 case TEST_TYPE_LAYERED_READBACK:
742 {
743 const float barWidthRatios[] = { 0.25f, 0.5f, 1.0f };
744 const int barsCount = DE_LENGTH_OF_ARRAY(barWidthRatios);
745 bool result = false;
746
747 if (depthCheck)
748 {
749 const std::string checkType = "Depth";
750 const float pass0depth = static_cast<float>(layerNdx + 1) / static_cast<float>(2 * numLayers);
751 const float pass1depth = static_cast<float>(layerNdx + 0) / static_cast<float>(2 * numLayers);
752 const tcu::Vec4 barDepths[barsCount] = { tcu::Vec4(pass1depth), tcu::Vec4(pass0depth), tcu::Vec4(1.0f) };
753 tcu::TextureLevel depthAsColorBuffer (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), image.getWidth(), image.getHeight());
754 tcu::PixelBufferAccess depthAsColor (depthAsColorBuffer);
755 const int numUsedChannels (tcu::getNumUsedChannels(depthAsColor.getFormat().order));
756
757 convertDepthToColorBufferAccess(image, depthAsColor);
758
759 result = verifyImageMultipleBars(log, depthAsColor, barWidthRatios, barDepths, barsCount, numUsedChannels, checkType);
760 }
761 else if (stencilCheck)
762 {
763 const std::string checkType = "Stencil";
764 const int maxStencilValue = 4;
765 const float pass0stencil = static_cast<float>(1.0f / maxStencilValue);
766 const float pass1stencil = static_cast<float>(2.0f / maxStencilValue);
767 const tcu::Vec4 barStencils[barsCount] = { tcu::Vec4(pass1stencil), tcu::Vec4(pass0stencil), tcu::Vec4(0.0f) };
768 tcu::TextureLevel stencilAsColorBuffer (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), image.getWidth(), image.getHeight());
769 tcu::PixelBufferAccess stencilAsColor (stencilAsColorBuffer);
770 const int numUsedChannels (tcu::getNumUsedChannels(stencilAsColor.getFormat().order));
771
772 convertStencilToColorBufferAccess(image, stencilAsColor, maxStencilValue);
773
774 result = verifyImageMultipleBars(log, stencilAsColor, barWidthRatios, barStencils, barsCount, numUsedChannels, checkType);
775 }
776 else
777 {
778 const std::string checkType = "Color";
779 const tcu::Vec4 baseColor (s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
780 const tcu::Vec4 barColors[barsCount] = { scaleColor(baseColor, 1.00f), scaleColor(baseColor, 0.50f), scaleColor(baseColor, 0.25f) };
781 const int numUsedChannels (tcu::getNumUsedChannels(image.getFormat().order));
782
783 result = verifyImageMultipleBars(log, image, barWidthRatios, barColors, barsCount, numUsedChannels, checkType);
784 }
785
786 return result;
787 }
788
789 case TEST_TYPE_SECONDARY_CMD_BUFFER:
790 {
791 const tcu::Vec4 clearColor = secondaryCmdBufClearColors[layerNdx % DE_LENGTH_OF_ARRAY(secondaryCmdBufClearColors)];
792 const tcu::Vec4 quadColor = s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)];
793 // The first draw: blend clearColor and quadColor
794 const tcu::Vec4 firstDraw = (clearColor + quadColor) * 0.5f;
795 // The second draw: blend previous result and quadColor
796 const tcu::Vec4 secondDraw = (firstDraw + quadColor) * 0.5f;
797
798 return verifyImageSingleColoredRow(log, image, 0.5f, secondDraw, layerNdx < numLayers / 2, layerNdx >= numLayers / 2);
799 }
800
801 default:
802 DE_ASSERT(0);
803 return false;
804 };
805 }
806
getLayerDescription(const VkImageViewType viewType,const int layer)807 std::string getLayerDescription (const VkImageViewType viewType, const int layer)
808 {
809 std::ostringstream str;
810 const int numCubeFaces = 6;
811
812 if (isCubeImageViewType(viewType))
813 str << "cube " << (layer / numCubeFaces) << ", face " << (layer % numCubeFaces);
814 else if (viewType == VK_IMAGE_VIEW_TYPE_3D)
815 str << "slice z = " << layer;
816 else
817 str << "layer " << layer;
818
819 return str.str();
820 }
821
verifyResults(tcu::TestLog & log,const TestParams & params,const VkFormat imageFormat,const void * resultData,const bool depthCheck=false,const bool stencilCheck=false)822 bool verifyResults (tcu::TestLog& log, const TestParams& params, const VkFormat imageFormat, const void* resultData, const bool depthCheck = false, const bool stencilCheck = false)
823 {
824 const LayeredImageAccess image = LayeredImageAccess::create(getImageType(params.image.viewType), imageFormat, params.image.size, params.image.numLayers, resultData);
825
826 int numGoodLayers = 0;
827
828 for (int layerNdx = 0; layerNdx < image.getNumLayersOrSlices(); ++layerNdx)
829 {
830 const tcu::ConstPixelBufferAccess layerImage = image.getLayer(layerNdx);
831
832 log << tcu::TestLog::Message << "Verifying " << getLayerDescription(params.image.viewType, layerNdx) << tcu::TestLog::EndMessage;
833
834 if (verifyLayerContent(log, params.testType, layerImage, layerNdx, image.getNumLayersOrSlices(), depthCheck, stencilCheck))
835 ++numGoodLayers;
836 }
837
838 return numGoodLayers == image.getNumLayersOrSlices();
839 }
840
toGlsl(const Vec4 & v)841 std::string toGlsl (const Vec4& v)
842 {
843 std::ostringstream str;
844 str << "vec4(";
845 for (int i = 0; i < 4; ++i)
846 str << (i != 0 ? ", " : "") << de::floatToString(v[i], 1);
847 str << ")";
848 return str.str();
849 }
850
initPrograms(SourceCollections & programCollection,const TestParams params)851 void initPrograms (SourceCollections& programCollection, const TestParams params)
852 {
853 const bool geomOutputColor = (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_LAYERED_READBACK || params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER);
854
855 // Vertex shader
856 {
857 std::ostringstream src;
858 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
859 << "\n"
860 << "void main(void)\n"
861 << "{\n"
862 << "}\n";
863
864 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
865 }
866
867 // Geometry shader
868 {
869 const int numLayers = static_cast<int>(params.image.viewType == VK_IMAGE_VIEW_TYPE_3D ? params.image.size.depth : params.image.numLayers);
870
871 const int maxVertices = (params.testType == TEST_TYPE_DIFFERENT_CONTENT) ? (numLayers + 1) * numLayers :
872 (params.testType == TEST_TYPE_ALL_LAYERS
873 || params.testType == TEST_TYPE_LAYER_ID
874 || params.testType == TEST_TYPE_LAYERED_READBACK
875 || params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER) ? numLayers * 4 :
876 (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION) ? 6 : 4;
877
878 std::ostringstream src;
879 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
880 << "\n";
881
882 if (params.testType == TEST_TYPE_LAYERED_READBACK)
883 src << "layout(binding = 0) readonly uniform Input {\n"
884 << " int pass;\n"
885 << "} uInput;\n\n";
886
887 if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
888 src << "layout(points, invocations = " << numLayers << ") in;\n";
889 else
890 src << "layout(points) in;\n";
891
892 src << "layout(triangle_strip, max_vertices = " << maxVertices << ") out;\n"
893 << "\n"
894 << (geomOutputColor ? "layout(location = 0) out vec4 vert_color;\n\n" : "")
895 << "out gl_PerVertex {\n"
896 << " vec4 gl_Position;\n"
897 << " float gl_PointSize;\n"
898 << "};\n"
899 << "\n"
900 << "void main(void)\n"
901 << "{\n";
902
903 std::ostringstream colorTable;
904 {
905 const int numColors = DE_LENGTH_OF_ARRAY(s_colors);
906
907 colorTable << " const vec4 colors[" << numColors << "] = vec4[" << numColors << "](";
908
909 const std::string padding(colorTable.str().length(), ' ');
910
911 for (int i = 0; i < numColors; ++i)
912 colorTable << (i != 0 ? ",\n" + padding : "") << toGlsl(s_colors[i]);
913
914 colorTable << ");\n";
915 }
916
917 if (params.testType == TEST_TYPE_DEFAULT_LAYER)
918 {
919 src << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
920 << " gl_PointSize = 1.0;\n"
921 << " EmitVertex();\n"
922 << "\n"
923 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
924 << " gl_PointSize = 1.0;\n"
925 << " EmitVertex();\n"
926 << "\n"
927 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
928 << " gl_PointSize = 1.0;\n"
929 << " EmitVertex();\n"
930 << "\n"
931 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
932 << " gl_PointSize = 1.0;\n"
933 << " EmitVertex();\n";
934 }
935 else if (params.testType == TEST_TYPE_SINGLE_LAYER)
936 {
937 const deUint32 targetLayer = getTargetLayer(params.image);
938
939 src << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
940 << " gl_Layer = " << targetLayer << ";\n"
941 << " gl_PointSize = 1.0;\n"
942 << " EmitVertex();\n"
943 << "\n"
944 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
945 << " gl_Layer = " << targetLayer << ";\n"
946 << " gl_PointSize = 1.0;\n"
947 << " EmitVertex();\n"
948 << "\n"
949 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
950 << " gl_Layer = " << targetLayer << ";\n"
951 << " gl_PointSize = 1.0;\n"
952 << " EmitVertex();\n"
953 << "\n"
954 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
955 << " gl_Layer = " << targetLayer << ";\n"
956 << " gl_PointSize = 1.0;\n"
957 << " EmitVertex();\n";
958 }
959 else if (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER)
960 {
961 src << colorTable.str()
962 << "\n"
963 << " for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
964 << " const int colorNdx = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
965 << "\n"
966 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
967 << " gl_Layer = layerNdx;\n"
968 << " vert_color = colors[colorNdx];\n"
969 << " gl_PointSize = 1.0;\n"
970 << " EmitVertex();\n"
971 << "\n"
972 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
973 << " gl_Layer = layerNdx;\n"
974 << " vert_color = colors[colorNdx];\n"
975 << " gl_PointSize = 1.0;\n"
976 << " EmitVertex();\n"
977 << "\n"
978 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
979 << " gl_Layer = layerNdx;\n"
980 << " vert_color = colors[colorNdx];\n"
981 << " gl_PointSize = 1.0;\n"
982 << " EmitVertex();\n"
983 << "\n"
984 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
985 << " gl_Layer = layerNdx;\n"
986 << " vert_color = colors[colorNdx];\n"
987 << " gl_PointSize = 1.0;\n"
988 << " EmitVertex();\n"
989 << " EndPrimitive();\n"
990 << " };\n";
991 }
992 else if (params.testType == TEST_TYPE_LAYER_ID)
993 {
994 src << " for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
995 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
996 << " gl_Layer = layerNdx;\n"
997 << " gl_PointSize = 1.0;\n"
998 << " EmitVertex();\n"
999 << "\n"
1000 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
1001 << " gl_Layer = layerNdx;\n"
1002 << " gl_PointSize = 1.0;\n"
1003 << " EmitVertex();\n"
1004 << "\n"
1005 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
1006 << " gl_Layer = layerNdx;\n"
1007 << " gl_PointSize = 1.0;\n"
1008 << " EmitVertex();\n"
1009 << "\n"
1010 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
1011 << " gl_Layer = layerNdx;\n"
1012 << " gl_PointSize = 1.0;\n"
1013 << " EmitVertex();\n"
1014 << " EndPrimitive();\n"
1015 << " };\n";
1016 }
1017 else if (params.testType == TEST_TYPE_DIFFERENT_CONTENT)
1018 {
1019 src << " for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
1020 << " for (int colNdx = 0; colNdx <= layerNdx; ++colNdx) {\n"
1021 << " const float posX = float(colNdx) / float(" << numLayers << ") * 2.0 - 1.0;\n"
1022 << "\n"
1023 << " gl_Position = vec4(posX, 1.0, 0.0, 1.0);\n"
1024 << " gl_Layer = layerNdx;\n"
1025 << " gl_PointSize = 1.0;\n"
1026 << " EmitVertex();\n"
1027 << "\n"
1028 << " gl_Position = vec4(posX, -1.0, 0.0, 1.0);\n"
1029 << " gl_Layer = layerNdx;\n"
1030 << " gl_PointSize = 1.0;\n"
1031 << " EmitVertex();\n"
1032 << " }\n"
1033 << " EndPrimitive();\n"
1034 << " }\n";
1035 }
1036 else if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER)
1037 {
1038 src << colorTable.str()
1039 << " const int colorNdx = gl_InvocationID % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
1040 << "\n"
1041 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1042 << " gl_Layer = gl_InvocationID;\n"
1043 << " gl_PointSize = 1.0;\n"
1044 << " vert_color = colors[colorNdx];\n"
1045 << " EmitVertex();\n"
1046 << "\n"
1047 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
1048 << " gl_Layer = gl_InvocationID;\n"
1049 << " gl_PointSize = 1.0;\n"
1050 << " vert_color = colors[colorNdx];\n"
1051 << " EmitVertex();\n"
1052 << "\n"
1053 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
1054 << " gl_Layer = gl_InvocationID;\n"
1055 << " gl_PointSize = 1.0;\n"
1056 << " vert_color = colors[colorNdx];\n"
1057 << " EmitVertex();\n"
1058 << "\n"
1059 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
1060 << " gl_Layer = gl_InvocationID;\n"
1061 << " gl_PointSize = 1.0;\n"
1062 << " vert_color = colors[colorNdx];\n"
1063 << " EmitVertex();\n"
1064 << " EndPrimitive();\n";
1065 }
1066 else if (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
1067 {
1068 src << " const int layerA = gl_InvocationID;\n"
1069 << " const int layerB = (gl_InvocationID + 1) % " << numLayers << ";\n"
1070 << " const float aEnd = float(layerA) / float(" << numLayers << ") * 2.0 - 1.0;\n"
1071 << " const float bEnd = float(layerB) / float(" << numLayers << ") * 2.0 - 1.0;\n"
1072 << "\n"
1073 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1074 << " gl_Layer = layerA;\n"
1075 << " gl_PointSize = 1.0;\n"
1076 << " EmitVertex();\n"
1077 << "\n"
1078 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
1079 << " gl_Layer = layerA;\n"
1080 << " gl_PointSize = 1.0;\n"
1081 << " EmitVertex();\n"
1082 << "\n"
1083 << " gl_Position = vec4(aEnd, -1.0, 0.0, 1.0);\n"
1084 << " gl_Layer = layerA;\n"
1085 << " gl_PointSize = 1.0;\n"
1086 << " EmitVertex();\n"
1087 << " EndPrimitive();\n"
1088 << "\n"
1089 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
1090 << " gl_Layer = layerB;\n"
1091 << " gl_PointSize = 1.0;\n"
1092 << " EmitVertex();\n"
1093 << "\n"
1094 << " gl_Position = vec4(bEnd, 1.0, 0.0, 1.0);\n"
1095 << " gl_Layer = layerB;\n"
1096 << " gl_PointSize = 1.0;\n"
1097 << " EmitVertex();\n"
1098 << "\n"
1099 << " gl_Position = vec4(bEnd, -1.0, 0.0, 1.0);\n"
1100 << " gl_Layer = layerB;\n"
1101 << " gl_PointSize = 1.0;\n"
1102 << " EmitVertex();\n"
1103 << " EndPrimitive();\n";
1104 }
1105 else if (params.testType == TEST_TYPE_LAYERED_READBACK)
1106 {
1107 src << colorTable.str()
1108 << " for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
1109 << " const int colorNdx = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
1110 << " const vec3 passColor0 = (uInput.pass == 0 ? 0.5 : 1.0) * vec3(colors[colorNdx]);\n"
1111 << " const vec4 passColor = vec4(passColor0, 1.0);\n"
1112 << " const float posX = (uInput.pass == 0 ? 0.0 : -0.5);\n"
1113 << " const float posZ = float(layerNdx + 1 - uInput.pass) / float(" << 2*numLayers << ");\n"
1114 << "\n"
1115 << " gl_Position = vec4(-1.0, -1.0, posZ, 1.0);\n"
1116 << " gl_Layer = layerNdx;\n"
1117 << " gl_PointSize = 1.0;\n"
1118 << " vert_color = passColor;\n"
1119 << " EmitVertex();\n"
1120 << "\n"
1121 << " gl_Position = vec4(-1.0, 1.0, posZ, 1.0);\n"
1122 << " gl_Layer = layerNdx;\n"
1123 << " gl_PointSize = 1.0;\n"
1124 << " vert_color = passColor;\n"
1125 << " EmitVertex();\n"
1126 << "\n"
1127 << " gl_Position = vec4(posX, -1.0, posZ, 1.0);\n"
1128 << " gl_Layer = layerNdx;\n"
1129 << " gl_PointSize = 1.0;\n"
1130 << " vert_color = passColor;\n"
1131 << " EmitVertex();\n"
1132 << "\n"
1133 << " gl_Position = vec4(posX, 1.0, posZ, 1.0);\n"
1134 << " gl_Layer = layerNdx;\n"
1135 << " gl_PointSize = 1.0;\n"
1136 << " vert_color = passColor;\n"
1137 << " EmitVertex();\n"
1138 << "\n"
1139 << " EndPrimitive();\n"
1140 << " }\n";
1141 }
1142 else
1143 DE_ASSERT(0);
1144
1145 src << "}\n"; // end main
1146
1147 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
1148 }
1149
1150 // Fragment shader
1151 {
1152 std::string imageViewString;
1153
1154 switch (params.image.viewType)
1155 {
1156 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1157 imageViewString = "image1DArray";
1158 break;
1159 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1160 imageViewString = "image2DArray";
1161 break;
1162 case VK_IMAGE_VIEW_TYPE_CUBE:
1163 imageViewString = "imageCube";
1164 break;
1165 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1166 imageViewString = "imageCubeArray";
1167 break;
1168 default:
1169 DE_ASSERT(params.image.viewType == VK_IMAGE_VIEW_TYPE_3D);
1170 imageViewString = "image3D";
1171 break;
1172 };
1173
1174 std::ostringstream src;
1175 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1176 << "\n"
1177 << "layout(location = 0) out vec4 o_color;\n"
1178 << (geomOutputColor ? "layout(location = 0) in vec4 vert_color;\n" : "")
1179 << (params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER ? std::string("layout(set = 0, binding = 0, rgba8) uniform " + imageViewString + " storageImage;\n") : std::string(""))
1180 << "\n"
1181 << "void main(void)\n"
1182 << "{\n";
1183
1184 if (params.testType == TEST_TYPE_LAYER_ID)
1185 {
1186 // This code must be in sync with verifyLayerContent()
1187 src << " o_color = vec4( (gl_Layer % 2) == 1 ? 1.0 : 0.5,\n"
1188 << " ((gl_Layer/2) % 2) == 1 ? 1.0 : 0.5,\n"
1189 << " gl_Layer == 0 ? 1.0 : 0.0,\n"
1190 << " 1.0);\n";
1191 }
1192 else if (params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER)
1193 {
1194 switch (params.image.viewType)
1195 {
1196 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1197 src << " ivec2 coord = ivec2(int(gl_FragCoord.x), gl_Layer);\n";
1198 break;
1199 default:
1200 src << " ivec3 coord = ivec3(int(gl_FragCoord.x), int(gl_FragCoord.y), gl_Layer);\n";
1201 break;
1202 };
1203
1204 src << " vec4 src_color = imageLoad(storageImage, coord);\n"
1205 << " o_color = (vert_color + src_color) / 2.0;\n"
1206 << " imageStore(storageImage, coord, o_color);\n";
1207 }
1208 else if (geomOutputColor)
1209 src << " o_color = vert_color;\n";
1210 else
1211 src << " o_color = vec4(1.0);\n";
1212
1213 src << "}\n";
1214
1215 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1216 }
1217 }
1218
test(Context & context,const TestParams params)1219 tcu::TestStatus test (Context& context, const TestParams params)
1220 {
1221 const DeviceInterface& vk = context.getDeviceInterface();
1222 const InstanceInterface& vki = context.getInstanceInterface();
1223 const VkDevice device = context.getDevice();
1224 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1225 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1226 const VkQueue queue = context.getUniversalQueue();
1227 Allocator& allocator = context.getDefaultAllocator();
1228 VkDeviceSize nonCoherentAtomSize = vk::getPhysicalDeviceProperties(vki, physDevice).limits.nonCoherentAtomSize;
1229 VkDeviceSize alignmentSize = std::max<VkDeviceSize>(nonCoherentAtomSize, 4u);
1230
1231 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1232 const deUint32 numLayers = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1233 const Vec4 clearColor = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1234 const deUint32 colorImagePixelSize = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
1235 const VkDeviceSize colorBufferSize = static_cast<VkDeviceSize>(deAlignSize(params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<std::size_t>(alignmentSize)) * params.image.size.depth * params.image.numLayers);
1236 const VkImageCreateFlags imageCreateFlags = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1237 (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
1238 const VkImageViewType viewType = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1239
1240 const Unique<VkImage> colorImage (makeImage (vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
1241 params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1242 const UniquePtr<Allocation> colorImageAlloc (bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any));
1243 const Unique<VkImageView> colorAttachment (makeImageView (vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1244
1245 const Unique<VkBuffer> colorBuffer (makeBuffer (vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1246 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1247
1248 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
1249 const Unique<VkShaderModule> geometryModule (createShaderModule (vk, device, context.getBinaryCollection().get("geom"), 0u));
1250 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
1251
1252 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, colorFormat));
1253 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, *colorAttachment, params.image.size.width, params.image.size.height, numLayers));
1254 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device));
1255 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
1256 makeExtent2D(params.image.size.width, params.image.size.height)));
1257 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1258 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1259
1260 zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1261
1262 beginCommandBuffer(vk, *cmdBuffer);
1263
1264 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, params.image.size.width, params.image.size.height), clearColor);
1265
1266 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1267 vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1268 endRenderPass(vk, *cmdBuffer);
1269
1270 // Copy color image to buffer
1271 copyLayeredImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, params.image);
1272
1273 endCommandBuffer(vk, *cmdBuffer);
1274 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1275
1276 invalidateAlloc(vk, device, *colorBufferAlloc);
1277
1278 if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1279 return tcu::TestStatus::fail("Rendered images are incorrect");
1280 else
1281 return tcu::TestStatus::pass("OK");
1282 }
1283
testLayeredReadBack(Context & context,const TestParams params)1284 tcu::TestStatus testLayeredReadBack (Context& context, const TestParams params)
1285 {
1286 const DeviceInterface& vk = context.getDeviceInterface();
1287 const InstanceInterface& vki = context.getInstanceInterface();
1288 const VkDevice device = context.getDevice();
1289 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1290 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1291 const VkQueue queue = context.getUniversalQueue();
1292 Allocator& allocator = context.getDefaultAllocator();
1293 VkDeviceSize nonCoherentAtomSize = vk::getPhysicalDeviceProperties(vki, physDevice).limits.nonCoherentAtomSize;
1294 VkDeviceSize alignmentSize = std::max<VkDeviceSize>(nonCoherentAtomSize, 4u);
1295
1296 const size_t passCount = 2;
1297 const deUint32 numLayers = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1298 const VkImageCreateFlags imageCreateFlags = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1299 (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
1300 const VkImageViewType viewType = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1301 const VkImageType imageType = getImageType(params.image.viewType);
1302 const VkExtent2D imageExtent2D = makeExtent2D(params.image.size.width, params.image.size.height);
1303
1304 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1305 const deUint32 colorImagePixelSize = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
1306 const VkDeviceSize colorBufferSize = static_cast<VkDeviceSize>( deAlignSize(params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<std::size_t>(alignmentSize)) * params.image.size.depth * params.image.numLayers );
1307 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1308
1309 const bool dsUsed = true;
1310 const VkFormat dsFormat = VK_FORMAT_D24_UNORM_S8_UINT;
1311 const VkImageType dsImageType = (imageType == VK_IMAGE_TYPE_3D ? VK_IMAGE_TYPE_2D : imageType); // depth/stencil 2D_ARRAY attachments cannot be taken from 3D image, use 2D_ARRAY image instead.
1312 const VkExtent3D dsImageSize = makeExtent3D(params.image.size.width, params.image.size.height, 1u);
1313 const VkImageCreateFlags dsImageCreateFlags = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0);
1314 const deUint32 dsImagePixelSize = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(dsFormat)));
1315 const VkImageUsageFlags dsImageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1316 const VkImageAspectFlags dsAspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
1317 const VkDeviceSize depthBufferSize = static_cast<VkDeviceSize>(deAlignSize(params.image.size.width * params.image.size.height * dsImagePixelSize, static_cast<std::size_t>(alignmentSize)) * params.image.size.depth * params.image.numLayers);
1318
1319 const VkFormat stencilBufferFormat = getStencilBufferFormat(dsFormat);
1320 const deUint32 stencilPixelSize = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(stencilBufferFormat)));
1321 const VkDeviceSize stencilBufferSize = static_cast<VkDeviceSize>(deAlignSize( params.image.size.width * params.image.size.height * stencilPixelSize, static_cast<std::size_t>(alignmentSize)) * params.image.size.depth * params.image.numLayers);
1322
1323 checkImageFormatProperties(vki, physDevice, imageType, VK_IMAGE_TILING_OPTIMAL, dsImageUsage, imageCreateFlags, dsFormat, params.image.size, params.image.numLayers);
1324
1325 const Unique<VkImage> colorImage (makeImage (vk, device, makeImageCreateInfo(imageCreateFlags, imageType, colorFormat, params.image.size, params.image.numLayers, colorImageUsage)));
1326 const UniquePtr<Allocation> colorImageAlloc (bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any));
1327 const Unique<VkImageView> colorAttachment (makeImageView (vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1328 const Unique<VkBuffer> colorBuffer (makeBuffer (vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1329 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1330
1331 const Unique<VkImage> dsImage (makeImage (vk, device, makeImageCreateInfo(dsImageCreateFlags, dsImageType, dsFormat, dsImageSize, numLayers, dsImageUsage)));
1332 const UniquePtr<Allocation> dsImageAlloc (bindImage (vk, device, allocator, *dsImage, MemoryRequirement::Any));
1333 const Unique<VkImageView> dsAttachment (makeImageView (vk, device, *dsImage, viewType, dsFormat, makeImageSubresourceRange(dsAspectFlags, 0u, 1u, 0u, numLayers)));
1334 const Unique<VkBuffer> depthBuffer (makeBuffer (vk, device, depthBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1335 const UniquePtr<Allocation> depthBufferAlloc (bindBuffer (vk, device, allocator, *depthBuffer, MemoryRequirement::HostVisible));
1336 const Unique<VkBuffer> stencilBuffer (makeBuffer (vk, device, stencilBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1337 const UniquePtr<Allocation> stencilBufferAlloc (bindBuffer (vk, device, allocator, *stencilBuffer, MemoryRequirement::HostVisible));
1338
1339 const VkImageView attachments[] = {*colorAttachment, *dsAttachment};
1340 const deUint32 attachmentsCount = dsUsed ? DE_LENGTH_OF_ARRAY(attachments) : 1u;
1341
1342 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
1343 const Unique<VkShaderModule> geometryModule (createShaderModule (vk, device, context.getBinaryCollection().get("geom"), 0u));
1344 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
1345
1346 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, colorFormat, dsFormat, dsUsed));
1347 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, attachmentsCount, attachments, params.image.size.width, params.image.size.height, numLayers));
1348
1349 const Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder()
1350 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, passCount)
1351 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, passCount);
1352 const Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder()
1353 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_GEOMETRY_BIT)
1354 .build(vk, device);
1355 const Move<VkDescriptorSet> descriptorSet[] =
1356 {
1357 makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout),
1358 makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout),
1359 };
1360
1361 const size_t uniformBufSize = sizeof(deUint32);
1362 const VkBufferCreateInfo uniformBufCI = makeBufferCreateInfo(uniformBufSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1363 const Move<VkBuffer> uniformBuf[] = { createBuffer(vk, device, &uniformBufCI), createBuffer(vk, device, &uniformBufCI) };
1364 const MovePtr<Allocation> uniformBufAlloc[] =
1365 {
1366 allocator.allocate(getBufferMemoryRequirements(vk, device, *uniformBuf[0]), MemoryRequirement::HostVisible),
1367 allocator.allocate(getBufferMemoryRequirements(vk, device, *uniformBuf[1]), MemoryRequirement::HostVisible),
1368 };
1369 const VkDescriptorBufferInfo uniformBufDesc[] =
1370 {
1371 makeDescriptorBufferInfo(*uniformBuf[0], 0ull, uniformBufSize),
1372 makeDescriptorBufferInfo(*uniformBuf[1], 0ull, uniformBufSize),
1373 };
1374
1375 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device, *descriptorSetLayout));
1376 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule, imageExtent2D, dsUsed));
1377 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1378 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1379 const VkImageSubresourceRange colorSubresRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers);
1380 const VkImageSubresourceRange dsSubresRange = makeImageSubresourceRange(dsAspectFlags, 0u, 1u, 0u, numLayers);
1381 std::string result;
1382
1383 beginCommandBuffer(vk, *cmdBuffer);
1384 {
1385 // Transition the images to new layouts
1386 const VkImageMemoryBarrier colorBarrier = makeImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1387 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *colorImage, colorSubresRange);
1388 const VkImageMemoryBarrier dsBarrier = makeImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1389 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *dsImage, dsSubresRange);
1390
1391 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorBarrier);
1392
1393 if (dsUsed)
1394 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsBarrier);
1395
1396 for (deUint32 layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1397 {
1398 const VkExtent3D imageExtent = makeExtent3D(params.image.size.width, params.image.size.height, 1u);
1399
1400 // Clear color image with initial value
1401 {
1402 const deUint32 layer = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? 0u : layerNdx;
1403 const deUint32 imageDepth = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? layerNdx : 0u;
1404 const VkOffset3D imageOffset = makeOffset3D(0u, 0u, imageDepth);
1405
1406 const tcu::Vec4 clearColor = scaleColor(s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)], 0.25f);
1407 const deUint32 bufferSliceSize = deAlign32( params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<deInt32>(alignmentSize));
1408 const VkDeviceSize bufferOffset = layerNdx * bufferSliceSize;
1409 const VkImageSubresourceLayers imageSubresource = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, layer, 1u);
1410 const VkBufferImageCopy bufferImageCopyRegion = makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
1411
1412 fillBuffer(vk, device, *colorBufferAlloc, bufferOffset, bufferSliceSize, colorFormat, clearColor);
1413 vk.cmdCopyBufferToImage(*cmdBuffer, *colorBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1414 }
1415
1416 // Clear depth image with initial value
1417 if (dsUsed)
1418 {
1419 const float depthValue = 1.0f;
1420 const deUint32 bufferSliceSize = deAlign32( params.image.size.width * params.image.size.height * dsImagePixelSize, static_cast<deInt32>(alignmentSize));
1421 const VkDeviceSize bufferOffset = layerNdx * bufferSliceSize;
1422 const VkImageSubresourceLayers imageSubresource = makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, layerNdx, 1u);
1423 const VkBufferImageCopy bufferImageCopyRegion = makeBufferImageCopy(bufferOffset, imageSubresource, makeOffset3D(0u, 0u, 0u), imageExtent);
1424
1425 fillBuffer(vk, device, *depthBufferAlloc, bufferOffset, bufferSliceSize, dsFormat, depthValue);
1426 vk.cmdCopyBufferToImage(*cmdBuffer, *depthBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1427 }
1428
1429 // Clear stencil image with initial value
1430 if (dsUsed)
1431 {
1432 const deUint8 stencilValue = 0;
1433 const deUint32 bufferSliceSize = deAlign32( params.image.size.width * params.image.size.height * stencilPixelSize, static_cast<deInt32>(alignmentSize));
1434 const VkDeviceSize bufferOffset = layerNdx * bufferSliceSize;
1435 const VkImageSubresourceLayers imageSubresource = makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, layerNdx, 1u);
1436 const VkBufferImageCopy bufferImageCopyRegion = makeBufferImageCopy(bufferOffset, imageSubresource, makeOffset3D(0u, 0u, 0u), imageExtent);
1437 deUint8* bufferStart = static_cast<deUint8*>((*stencilBufferAlloc).getHostPtr());
1438 deUint8* bufferLayerStart = &bufferStart[bufferOffset];
1439
1440 deMemset(bufferLayerStart, stencilValue, bufferSliceSize);
1441 flushMappedMemoryRange(vk, device, stencilBufferAlloc->getMemory(), stencilBufferAlloc->getOffset() + bufferOffset, bufferSliceSize);
1442 vk.cmdCopyBufferToImage(*cmdBuffer, *stencilBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1443 }
1444 }
1445 }
1446 // Change images layouts
1447 {
1448 // VK_ATTACHMENT_LOAD_OP_LOAD is used for both color and D/S attachments. Thus,
1449 // VK_ACCESS_COLOR_ATTACHMENT_READ_BIT and VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
1450 // bits must be included in the destination access mask of the color and depth barriers
1451 // respectively.
1452 const VkImageMemoryBarrier colorBarrier = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1453 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresRange);
1454 const VkImageMemoryBarrier dsBarrier = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1455 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *dsImage, dsSubresRange);
1456
1457 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorBarrier);
1458
1459 if (dsUsed)
1460 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsBarrier);
1461 }
1462
1463 {
1464 // These barriers are inserted between each pair of renderpasses in the following
1465 // loop. Note that VK_ATTACHMENT_LOAD_OP_LOAD is used for color and D/S attachments
1466 // hence VK_ACCESS_COLOR_ATTACHMENT_READ_BIT and VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
1467 // bits are included in src and dst access mask of the color and depth barriers.
1468 const VkImageMemoryBarrier colorPassBarrier = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1469 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1470 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresRange);
1471 const VkImageMemoryBarrier dsPassBarrier = makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1472 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1473 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *dsImage, dsSubresRange);
1474 for (deUint32 pass = 0; pass < passCount; ++pass)
1475 {
1476 DE_ASSERT(sizeof(pass) == uniformBufSize);
1477
1478 VK_CHECK(vk.bindBufferMemory(device, *uniformBuf[pass], uniformBufAlloc[pass]->getMemory(), uniformBufAlloc[pass]->getOffset()));
1479 deMemcpy(uniformBufAlloc[pass]->getHostPtr(), &pass, uniformBufSize);
1480 flushMappedMemoryRange(vk, device, uniformBufAlloc[pass]->getMemory(), uniformBufAlloc[pass]->getOffset(), VK_WHOLE_SIZE);
1481
1482 DescriptorSetUpdateBuilder()
1483 .writeSingle(*descriptorSet[pass], DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufDesc[pass])
1484 .update(vk, device);
1485
1486 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet[pass], 0u, DE_NULL);
1487 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(imageExtent2D));
1488 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1489 vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1490 endRenderPass(vk, *cmdBuffer);
1491
1492 // Don't add the barrier after the last renderpass
1493 if (pass < passCount - 1)
1494 {
1495 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorPassBarrier);
1496
1497 if (dsUsed)
1498 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsPassBarrier);
1499 }
1500 }
1501 }
1502 endCommandBuffer(vk, *cmdBuffer);
1503 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1504
1505 zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1506 zeroBuffer(vk, device, *depthBufferAlloc, depthBufferSize);
1507 zeroBuffer(vk, device, *stencilBufferAlloc, stencilBufferSize);
1508
1509 beginCommandBuffer(vk, *cmdBuffer);
1510 {
1511 // Copy color image
1512 {
1513 const VkImageMemoryBarrier preCopyBarrier = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1514 VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorImage, colorSubresRange);
1515 const VkBufferImageCopy region = makeBufferImageCopy(params.image.size, makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, params.image.numLayers));
1516 const VkBufferMemoryBarrier postCopyBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
1517
1518 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1519 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
1520 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
1521 }
1522
1523 // Depth/Stencil image copy
1524 if (dsUsed)
1525 {
1526 const VkImageMemoryBarrier preCopyBarrier = makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1527 VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dsImage, dsSubresRange);
1528 const VkBufferImageCopy depthCopyRegion = makeBufferImageCopy(dsImageSize, makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, numLayers));
1529 const VkBufferImageCopy stencilCopyRegion = makeBufferImageCopy(dsImageSize, makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, numLayers));
1530 const VkBufferMemoryBarrier postCopyBarriers[] =
1531 {
1532 makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *depthBuffer, 0ull, VK_WHOLE_SIZE),
1533 makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *stencilBuffer, 0ull, VK_WHOLE_SIZE),
1534 };
1535
1536 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1537 vk.cmdCopyImageToBuffer(*cmdBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *depthBuffer, 1u, &depthCopyRegion);
1538 vk.cmdCopyImageToBuffer(*cmdBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *stencilBuffer, 1u, &stencilCopyRegion);
1539 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(postCopyBarriers), postCopyBarriers, DE_NULL, 0u);
1540 }
1541 }
1542 endCommandBuffer(vk, *cmdBuffer);
1543 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1544
1545 invalidateAlloc(vk, device, *colorBufferAlloc);
1546 invalidateAlloc(vk, device, *depthBufferAlloc);
1547 invalidateAlloc(vk, device, *stencilBufferAlloc);
1548
1549 if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1550 result += " Color";
1551
1552 if (dsUsed)
1553 {
1554 if (!verifyResults(context.getTestContext().getLog(), params, dsFormat, depthBufferAlloc->getHostPtr(), true, false))
1555 result += " Depth";
1556
1557 if (!verifyResults(context.getTestContext().getLog(), params, stencilBufferFormat, stencilBufferAlloc->getHostPtr(), false, true))
1558 result += " Stencil";
1559 }
1560
1561 if (result.empty())
1562 return tcu::TestStatus::pass("OK");
1563 else
1564 return tcu::TestStatus::fail("Following parts of image are incorrect:" + result);
1565 }
1566
testSecondaryCmdBuffer(Context & context,const TestParams params)1567 tcu::TestStatus testSecondaryCmdBuffer (Context& context, const TestParams params)
1568 {
1569 const DeviceInterface& vk = context.getDeviceInterface();
1570 const InstanceInterface& vki = context.getInstanceInterface();
1571 const VkDevice device = context.getDevice();
1572 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1573 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1574 const VkQueue queue = context.getUniversalQueue();
1575 Allocator& allocator = context.getDefaultAllocator();
1576 VkDeviceSize nonCoherentAtomSize = vk::getPhysicalDeviceProperties(vki, physDevice).limits.nonCoherentAtomSize;
1577 VkDeviceSize alignmentSize = std::max<VkDeviceSize>(nonCoherentAtomSize, 4u);
1578
1579 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1580 const deUint32 numLayers = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1581 const Vec4 clearColor = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1582 const deUint32 colorImagePixelSize = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
1583 const VkDeviceSize colorBufferSize = static_cast<VkDeviceSize>(deAlignSize(params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<std::size_t>(alignmentSize)) * params.image.size.depth * params.image.numLayers);
1584
1585 const VkImageCreateFlags imageCreateFlags = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1586 (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
1587 const VkImageViewType viewType = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1588
1589 const Unique<VkImage> colorImage (makeImage(vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
1590 params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1591 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1592 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1593
1594 const Unique<VkImage> offscreenImage (makeImage(vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
1595 params.image.numLayers, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)));
1596 const UniquePtr<Allocation> offscreenImageAlloc (bindImage(vk, device, allocator, *offscreenImage, MemoryRequirement::Any));
1597 const Unique<VkImageView> offscreenImageView (makeImageView(vk, device, *offscreenImage, params.image.viewType, colorFormat,
1598 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers)));
1599
1600 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1601 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1602
1603 const Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder() .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u) .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1604 const Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder() .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT) .build(vk, device);
1605 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
1606
1607 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
1608 const Unique<VkShaderModule> geometryModule (createShaderModule(vk, device, context.getBinaryCollection().get("geom"), 0u));
1609 const Unique<VkShaderModule> fragmentModule (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
1610
1611 const Unique<VkRenderPass> renderPass (makeRenderPassWithSelfDependency(vk, device, colorFormat));
1612 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, *colorImageView, params.image.size.width, params.image.size.height, numLayers));
1613 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout));
1614 const Unique<VkPipeline> pipeline (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
1615 makeExtent2D(params.image.size.width, params.image.size.height)));
1616
1617 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1618 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1619 const Unique<VkCommandBuffer> secondaryCmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY));
1620
1621 zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1622
1623 const VkDescriptorImageInfo imageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *offscreenImageView, VK_IMAGE_LAYOUT_GENERAL);
1624
1625 DescriptorSetUpdateBuilder()
1626 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageDescriptorInfo)
1627 .update(vk, device);
1628
1629 // Clear each layer of storage image
1630 {
1631 vk::Unique<vk::VkCommandBuffer> clearCmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1632 beginCommandBuffer(vk, *clearCmdBuffer);
1633
1634 const vk::VkImageSubresourceRange subresourceRange =
1635 {
1636 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
1637 0u, // deUint32 baseMipLevel
1638 1u, // deUint32 levelCount
1639 0u, // deUint32 baseArrayLayer
1640 params.image.numLayers // deUint32 layerCount
1641 };
1642
1643 const vk::VkImageMemoryBarrier preImageBarrier =
1644 {
1645 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
1646 DE_NULL, // const void* pNext
1647 0u, // VkAccessFlags srcAccessMask
1648 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask
1649 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
1650 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout
1651 queueFamilyIndex, // deUint32 srcQueueFamilyIndex
1652 queueFamilyIndex, // deUint32 dstQueueFamilyIndex
1653 *offscreenImage, // VkImage image
1654 subresourceRange // VkImageSubresourceRange subresourceRange
1655 };
1656
1657 const vk::VkImageMemoryBarrier postImageBarrier =
1658 {
1659 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
1660 DE_NULL, // const void* pNext
1661 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
1662 vk::VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags dstAccessMask
1663 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout
1664 vk::VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
1665 queueFamilyIndex, // deUint32 srcQueueFamilyIndex
1666 queueFamilyIndex, // deUint32 dstQueueFamilyIndex
1667 *offscreenImage, // VkImage image
1668 subresourceRange // VkImageSubresourceRange subresourceRange
1669 };
1670
1671 vk.cmdPipelineBarrier(*clearCmdBuffer,
1672 vk::VK_PIPELINE_STAGE_HOST_BIT,
1673 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
1674 (vk::VkDependencyFlags)0,
1675 0, (const vk::VkMemoryBarrier*)DE_NULL,
1676 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1677 1, &preImageBarrier);
1678
1679 for (deUint32 layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1680 {
1681 const deUint32 imageDepth = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? layerNdx : 0u;
1682 const deUint32 layer = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? 0u : layerNdx;
1683 const VkOffset3D imageOffset = makeOffset3D(0u, 0u, imageDepth);
1684 const VkExtent3D imageExtent = makeExtent3D(params.image.size.width, params.image.size.height, 1u);
1685
1686 {
1687 const tcu::Vec4 storageImageClearColor = secondaryCmdBufClearColors[layerNdx % DE_LENGTH_OF_ARRAY(secondaryCmdBufClearColors)];
1688 const deUint32 bufferSliceSize = deAlign32(params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<deInt32>(alignmentSize));
1689 const VkDeviceSize bufferOffset = layerNdx * bufferSliceSize;
1690 const VkImageSubresourceLayers imageSubresource = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, layer, 1u);
1691 const VkBufferImageCopy bufferImageCopyRegion = makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
1692
1693 fillBuffer(vk, device, *colorBufferAlloc, bufferOffset, bufferSliceSize, colorFormat, storageImageClearColor);
1694 vk.cmdCopyBufferToImage(*clearCmdBuffer, *colorBuffer, *offscreenImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1695 }
1696 }
1697
1698 vk.cmdPipelineBarrier(*clearCmdBuffer,
1699 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
1700 vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1701 (vk::VkDependencyFlags)0,
1702 0, (const vk::VkMemoryBarrier*)DE_NULL,
1703 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1704 1, &postImageBarrier);
1705
1706 endCommandBuffer(vk, *clearCmdBuffer);
1707
1708 submitCommandsAndWait(vk, device, queue, *clearCmdBuffer);
1709 }
1710
1711 // Begin secondary command buffer
1712 {
1713 const VkCommandBufferInheritanceInfo commandBufferInheritanceInfo =
1714 {
1715 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType
1716 DE_NULL, // const void* pNext
1717 *renderPass, // VkRenderPass renderPass
1718 0u, // deUint32 subpass
1719 params.inheritFramebuffer ? *framebuffer : (VkFramebuffer)0, // VkFramebuffer framebuffer
1720 VK_FALSE, // VkBool32 occlusionQueryEnable
1721 0u, // VkQueryControlFlags queryFlags
1722 0u // VkQueryPipelineStatisticFlags pipelineStatistics
1723 };
1724
1725 const VkCommandBufferBeginInfo commandBufferBeginInfo =
1726 {
1727 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType
1728 DE_NULL, // const void* pNext
1729 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
1730 | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, // VkCommandBufferUsageFlags flags
1731 &commandBufferInheritanceInfo // const VkCommandBufferInheritanceInfo* pInheritanceInfo
1732 };
1733
1734 VK_CHECK(vk.beginCommandBuffer(*secondaryCmdBuffer, &commandBufferBeginInfo));
1735 }
1736
1737 vk.cmdBindDescriptorSets(*secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
1738
1739 // Clear framebuffer: upper right corner for half of the layers and bottom right for the others.
1740 {
1741 const VkClearAttachment clearAttachment =
1742 {
1743 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
1744 0u, // deUint32 colorAttachment
1745 makeClearValueColorF32(0.5f, 0.25, 0.0f, 1.0f) // VkClearValue clearValue
1746 };
1747
1748 const VkOffset2D offsetTop = { (deInt32)params.image.size.width / 2, 0 };
1749 const VkOffset2D offsetBottom = { (deInt32)params.image.size.width / 2, (deInt32)params.image.size.height / 2 };
1750 const VkExtent2D extentTop = { params.image.size.width / 2, params.image.size.height / 2 };
1751 const VkExtent2D extentBottom = { params.image.size.width / 2, de::max(params.image.size.height / 2, 1u) };
1752 const VkRect2D rectRightTop = { offsetTop, extentTop };
1753 const VkRect2D rectRightBottom = { offsetBottom, extentBottom };
1754
1755 const VkClearRect rects[] =
1756 {
1757 {
1758 rectRightBottom, // VkRect2D rect
1759 numLayers / 2, // deUint32 baseArrayLayer
1760 numLayers / 2 // deUint32 layerCount
1761 },
1762 {
1763 rectRightTop, // VkRect2D rect
1764 0u, // deUint32 baseArrayLayer
1765 numLayers / 2 // deUint32 layerCount
1766 }
1767 };
1768
1769 vk.cmdClearAttachments(*secondaryCmdBuffer, 1u, &clearAttachment, extentTop.height > 0 ? 2u : 1u, rects);
1770 }
1771
1772 vk.cmdBindPipeline(*secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1773 vk.cmdDraw(*secondaryCmdBuffer, 1u, 1u, 0u, 0u);
1774 // Barrier between draws
1775 {
1776 const VkMemoryBarrier barrier =
1777 {
1778 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType
1779 DE_NULL, // const void* pNext
1780 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask
1781 VK_ACCESS_SHADER_READ_BIT // VkAccessFlags dstAccessMask
1782 };
1783
1784 vk.cmdPipelineBarrier(*secondaryCmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 1u, &barrier, 0u, DE_NULL, 0u, DE_NULL);
1785 }
1786 vk.cmdDraw(*secondaryCmdBuffer, 1u, 1u, 0u, 0u);
1787 endCommandBuffer(vk, *secondaryCmdBuffer);
1788
1789 beginCommandBuffer(vk, *cmdBuffer);
1790 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, params.image.size.width, params.image.size.height), clearColor, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
1791 vk.cmdExecuteCommands(*cmdBuffer, 1u, &(*secondaryCmdBuffer));
1792 endRenderPass(vk, *cmdBuffer);
1793
1794 copyLayeredImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, params.image);
1795
1796 endCommandBuffer(vk, *cmdBuffer);
1797 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1798
1799 invalidateAlloc(vk, device, *colorBufferAlloc);
1800
1801 if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1802 return tcu::TestStatus::fail("Rendered images are incorrect");
1803 else
1804 return tcu::TestStatus::pass("OK");
1805 }
1806
checkSupport(Context & context,const TestParams params)1807 void checkSupport (Context& context, const TestParams params)
1808 {
1809 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
1810
1811 if (params.image.viewType == VK_IMAGE_VIEW_TYPE_3D)
1812 context.requireDeviceFunctionality("VK_KHR_maintenance1");
1813
1814 if (params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER)
1815 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
1816 }
1817
1818 } // anonymous
1819
createLayeredRenderingTests(tcu::TestContext & testCtx)1820 tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx)
1821 {
1822 MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "layered", "Layered rendering tests."));
1823
1824 const struct
1825 {
1826 TestType test;
1827 const char* name;
1828 const char* description;
1829 } testTypes[] =
1830 {
1831 { TEST_TYPE_DEFAULT_LAYER, "render_to_default_layer", "Render to the default layer" },
1832 { TEST_TYPE_SINGLE_LAYER, "render_to_one", "Render to one layer" },
1833 { TEST_TYPE_ALL_LAYERS, "render_to_all", "Render to all layers" },
1834 { TEST_TYPE_DIFFERENT_CONTENT, "render_different_content", "Render different data to different layers" },
1835 { TEST_TYPE_LAYER_ID, "fragment_layer", "Read gl_Layer in fragment shader" },
1836 { TEST_TYPE_INVOCATION_PER_LAYER, "invocation_per_layer", "Render to multiple layers with multiple invocations, one invocation per layer" },
1837 { TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION, "multiple_layers_per_invocation", "Render to multiple layers with multiple invocations, multiple layers per invocation", },
1838 { TEST_TYPE_LAYERED_READBACK, "readback", "Render to multiple layers with two passes to check LOAD_OP_LOAD capability" },
1839 { TEST_TYPE_SECONDARY_CMD_BUFFER, "secondary_cmd_buffer", "Layered rendering using secondary command buffer" }
1840 };
1841
1842 const struct
1843 {
1844 VkImageViewType viewType;
1845 ImageParams imageParams[2];
1846 } imageParamGroups[] =
1847 {
1848 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, { { VK_IMAGE_VIEW_TYPE_1D_ARRAY, { 64, 1, 1 }, 4 }, { VK_IMAGE_VIEW_TYPE_1D_ARRAY, { 12, 1, 1 }, 6 } } },
1849 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, { { VK_IMAGE_VIEW_TYPE_2D_ARRAY, { 64, 64, 1 }, 4 }, { VK_IMAGE_VIEW_TYPE_2D_ARRAY, { 12, 36, 1 }, 6 } } },
1850 { VK_IMAGE_VIEW_TYPE_CUBE, { { VK_IMAGE_VIEW_TYPE_CUBE, { 64, 64, 1 }, 6 }, { VK_IMAGE_VIEW_TYPE_CUBE, { 36, 36, 1 }, 6 } } },
1851 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, { { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, { 64, 64, 1 }, 2*6 }, { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, { 36, 36, 1 }, 2*6 } } },
1852 { VK_IMAGE_VIEW_TYPE_3D, { { VK_IMAGE_VIEW_TYPE_3D, { 64, 64, 8 }, 1 }, { VK_IMAGE_VIEW_TYPE_3D, { 12, 36, 6 }, 1 } } }
1853 };
1854
1855 for (int imageParamGroupNdx = 0; imageParamGroupNdx < DE_LENGTH_OF_ARRAY(imageParamGroups); ++imageParamGroupNdx)
1856 {
1857 MovePtr<tcu::TestCaseGroup> viewTypeMainGroup(new tcu::TestCaseGroup(testCtx, getShortImageViewTypeName(imageParamGroups[imageParamGroupNdx].viewType).c_str(), ""));
1858
1859 for (int imageParamNdx = 0; imageParamNdx < 2; imageParamNdx++)
1860 {
1861 std::ostringstream viewTypeGroupName;
1862 viewTypeGroupName << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].size.width << "_" << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].size.height << "_";
1863 if (imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].viewType == VK_IMAGE_VIEW_TYPE_3D)
1864 viewTypeGroupName << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].size.depth;
1865 else
1866 viewTypeGroupName << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].numLayers;
1867 MovePtr<tcu::TestCaseGroup> viewTypeGroup(new tcu::TestCaseGroup(testCtx, viewTypeGroupName.str().c_str(), ""));
1868
1869 for (int testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx)
1870 {
1871 TestParams params =
1872 {
1873 testTypes[testTypeNdx].test,
1874 imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx],
1875 false
1876 };
1877
1878 if (testTypes[testTypeNdx].test == TEST_TYPE_LAYERED_READBACK)
1879 addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, checkSupport, initPrograms, testLayeredReadBack, params);
1880 else if (testTypes[testTypeNdx].test == TEST_TYPE_SECONDARY_CMD_BUFFER)
1881 {
1882 addFunctionCaseWithPrograms(viewTypeGroup.get(), "secondary_cmd_buffer", testTypes[testTypeNdx].description, checkSupport, initPrograms, testSecondaryCmdBuffer, params);
1883 params.inheritFramebuffer = true;
1884 addFunctionCaseWithPrograms(viewTypeGroup.get(), "secondary_cmd_buffer_inherit_framebuffer", testTypes[testTypeNdx].description, checkSupport, initPrograms, testSecondaryCmdBuffer, params);
1885 }
1886 else
1887 addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, checkSupport, initPrograms, test, params);
1888 }
1889 viewTypeMainGroup->addChild(viewTypeGroup.release());
1890 }
1891 group->addChild(viewTypeMainGroup.release());
1892 }
1893
1894 return group.release();
1895 }
1896
1897 } // geometry
1898 } // vkt
1899