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 // Note: this is never reached
539 log << tcu::TestLog::Image("LayerContent", "Layer content", image);
540
541 return allPixelsOk;
542 }
543
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)544 static bool verifyImageMultipleBars (tcu::TestLog& log,
545 const tcu::ConstPixelBufferAccess image,
546 const float* barWidthRatios,
547 const tcu::Vec4* barValues,
548 const int barsCount,
549 const int numUsedChannels,
550 const std::string& imageTypeName)
551 {
552 const Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
553 const Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
554 const Vec4 threshold (0.02f);
555 const tcu::TextureFormat errorMaskFormat (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8));
556 tcu::TextureLevel errorMask (errorMaskFormat, image.getWidth(), image.getHeight());
557 tcu::PixelBufferAccess errorMaskAccess = errorMask.getAccess();
558 bool allPixelsOk = true;
559
560 DE_ASSERT(barsCount > 0);
561
562 tcu::clear(errorMask.getAccess(), green);
563
564 // Format information message
565 {
566 int leftBorder = 0;
567 int rightBorder = 0;
568 std::ostringstream str;
569
570 for (int barNdx = 0; barNdx < barsCount; ++barNdx)
571 {
572 leftBorder = rightBorder;
573 rightBorder = static_cast<int>(barWidthRatios[barNdx] * static_cast<float>(image.getWidth()));
574
575 DE_ASSERT(leftBorder < rightBorder);
576
577 str << std::endl << " [" << leftBorder << "," <<rightBorder << "): ";
578
579 switch (numUsedChannels)
580 {
581 case 1: str << barValues[barNdx][0]; break;
582 case 4: str << barValues[barNdx]; break;
583 default: DE_ASSERT(false); break;
584 }
585 }
586
587 log << tcu::TestLog::Message
588 << "Expecting " + imageTypeName + " values depending x-axis position to be of following values: "
589 << str.str()
590 << tcu::TestLog::EndMessage;
591 }
592
593 for (int x = 0; x < image.getWidth(); ++x)
594 {
595 tcu::Vec4 expectedValue = barValues[0];
596
597 for (int barNdx = 0; barNdx < barsCount; ++barNdx)
598 {
599 const int rightBorder = static_cast<int>(barWidthRatios[barNdx] * static_cast<float>(image.getWidth()));
600
601 if (x < rightBorder)
602 {
603 expectedValue = barValues[barNdx];
604
605 break;
606 }
607 }
608
609 for (int y = 0; y < image.getHeight(); ++y)
610 {
611 const tcu::Vec4 realValue = image.getPixel(x, y);
612 bool isOk = false;
613
614 switch (numUsedChannels)
615 {
616 case 1: isOk = fabs(realValue[0] - expectedValue[0]) < threshold[0]; break;
617 case 4: isOk = compareColors(realValue, expectedValue, threshold); break;
618 default: DE_ASSERT(false); break;
619 }
620
621 if (!isOk)
622 errorMaskAccess.setPixel(red, x, y);
623
624 allPixelsOk = allPixelsOk && isOk;
625 }
626 }
627
628 if (allPixelsOk)
629 {
630 log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
631 << tcu::TestLog::ImageSet(imageTypeName + "LayerContent", imageTypeName + " Layer Content")
632 << tcu::TestLog::Image("Layer", "Layer", image)
633 << tcu::TestLog::EndImageSet;
634 }
635 else
636 {
637 log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
638 << tcu::TestLog::ImageSet(imageTypeName + "LayerContent", imageTypeName + " Layer Content")
639 << tcu::TestLog::Image("Layer", "Layer", image)
640 << tcu::TestLog::Image("ErrorMask", "Errors", errorMask)
641 << tcu::TestLog::EndImageSet;
642 }
643
644 return allPixelsOk;
645 }
646
convertDepthToColorBufferAccess(const tcu::ConstPixelBufferAccess & inputImage,tcu::PixelBufferAccess & outputImage)647 static void convertDepthToColorBufferAccess (const tcu::ConstPixelBufferAccess& inputImage, tcu::PixelBufferAccess& outputImage)
648 {
649 for (int y = 0; y < inputImage.getHeight(); y++)
650 for (int x = 0; x < inputImage.getWidth(); x++)
651 {
652 const float depth = inputImage.getPixDepth(x, y);
653 const tcu::Vec4 color = tcu::Vec4(depth, depth, depth, 1.0f);
654
655 outputImage.setPixel(color, x, y);
656 }
657 }
658
convertStencilToColorBufferAccess(const tcu::ConstPixelBufferAccess & inputImage,tcu::PixelBufferAccess & outputImage,int maxValue)659 static void convertStencilToColorBufferAccess (const tcu::ConstPixelBufferAccess& inputImage, tcu::PixelBufferAccess& outputImage, int maxValue)
660 {
661 for (int y = 0; y < inputImage.getHeight(); y++)
662 for (int x = 0; x < inputImage.getWidth(); x++)
663 {
664 const int stencilInt = inputImage.getPixStencil(x, y);
665 const float stencil = (stencilInt < maxValue) ? float(stencilInt) / float(maxValue) : 1.0f;
666 const tcu::Vec4 color = tcu::Vec4(stencil, stencil, stencil, 1.0f);
667
668 outputImage.setPixel(color, x, y);
669 }
670 }
671
verifyEmptyImage(tcu::TestLog & log,const tcu::ConstPixelBufferAccess image)672 bool verifyEmptyImage (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image)
673 {
674 log << tcu::TestLog::Message << "Expecting empty image" << tcu::TestLog::EndMessage;
675
676 const Vec4 black (0.0f, 0.0f, 0.0f, 1.0f);
677 const Vec4 threshold (0.02f);
678
679 for (int y = 0; y < image.getHeight(); ++y)
680 for (int x = 0; x < image.getWidth(); ++x)
681 {
682 const Vec4 color = image.getPixel(x, y);
683
684 if (!compareColors(color, black, threshold))
685 {
686 log << tcu::TestLog::Message
687 << "Found (at least) one bad pixel at " << x << "," << y << ". Pixel color is not background color."
688 << tcu::TestLog::EndMessage
689 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
690 << tcu::TestLog::Image("Layer", "Layer", image)
691 << tcu::TestLog::EndImageSet;
692 return false;
693 }
694 }
695
696 log << tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage;
697
698 return true;
699 }
700
verifyLayerContent(tcu::TestLog & log,const TestType testType,const tcu::ConstPixelBufferAccess image,const int layerNdx,const int numLayers,const bool depthCheck,const bool stencilCheck)701 bool verifyLayerContent (tcu::TestLog& log, const TestType testType, const tcu::ConstPixelBufferAccess image, const int layerNdx, const int numLayers, const bool depthCheck, const bool stencilCheck)
702 {
703 const Vec4 white (1.0f, 1.0f, 1.0f, 1.0f);
704 const int targetLayer = numLayers / 2;
705 const float variableBarRatio = static_cast<float>(layerNdx) / static_cast<float>(numLayers);
706
707 switch (testType)
708 {
709 case TEST_TYPE_DEFAULT_LAYER:
710 if (layerNdx == 0)
711 return verifyImageSingleColoredRow(log, image, 0.5f, white);
712 else
713 return verifyEmptyImage(log, image);
714
715 case TEST_TYPE_SINGLE_LAYER:
716 if (layerNdx == targetLayer)
717 return verifyImageSingleColoredRow(log, image, 0.5f, white);
718 else
719 return verifyEmptyImage(log, image);
720
721 case TEST_TYPE_ALL_LAYERS:
722 case TEST_TYPE_INVOCATION_PER_LAYER:
723 return verifyImageSingleColoredRow(log, image, 0.5f, s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
724
725 case TEST_TYPE_DIFFERENT_CONTENT:
726 case TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION:
727 if (layerNdx == 0)
728 return verifyEmptyImage(log, image);
729 else
730 return verifyImageSingleColoredRow(log, image, variableBarRatio, white);
731
732 case TEST_TYPE_LAYER_ID:
733 {
734 // This code must be in sync with the fragment shader.
735 const tcu::Vec4 layerColor( (layerNdx % 2) == 1 ? 1.0f : 0.5f,
736 ((layerNdx/2) % 2) == 1 ? 1.0f : 0.5f,
737 layerNdx == 0 ? 1.0f : 0.0f,
738 1.0f);
739 return verifyImageSingleColoredRow(log, image, 0.5f, layerColor);
740 }
741
742 case TEST_TYPE_LAYERED_READBACK:
743 {
744 const float barWidthRatios[] = { 0.25f, 0.5f, 1.0f };
745 const int barsCount = DE_LENGTH_OF_ARRAY(barWidthRatios);
746 bool result = false;
747
748 if (depthCheck)
749 {
750 const std::string checkType = "Depth";
751 const float pass0depth = static_cast<float>(layerNdx + 1) / static_cast<float>(2 * numLayers);
752 const float pass1depth = static_cast<float>(layerNdx + 0) / static_cast<float>(2 * numLayers);
753 const tcu::Vec4 barDepths[barsCount] = { tcu::Vec4(pass1depth), tcu::Vec4(pass0depth), tcu::Vec4(1.0f) };
754 tcu::TextureLevel depthAsColorBuffer (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), image.getWidth(), image.getHeight());
755 tcu::PixelBufferAccess depthAsColor (depthAsColorBuffer);
756 const int numUsedChannels (tcu::getNumUsedChannels(depthAsColor.getFormat().order));
757
758 convertDepthToColorBufferAccess(image, depthAsColor);
759
760 result = verifyImageMultipleBars(log, depthAsColor, barWidthRatios, barDepths, barsCount, numUsedChannels, checkType);
761 }
762 else if (stencilCheck)
763 {
764 const std::string checkType = "Stencil";
765 const int maxStencilValue = 4;
766 const float pass0stencil = static_cast<float>(1.0f / maxStencilValue);
767 const float pass1stencil = static_cast<float>(2.0f / maxStencilValue);
768 const tcu::Vec4 barStencils[barsCount] = { tcu::Vec4(pass1stencil), tcu::Vec4(pass0stencil), tcu::Vec4(0.0f) };
769 tcu::TextureLevel stencilAsColorBuffer (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), image.getWidth(), image.getHeight());
770 tcu::PixelBufferAccess stencilAsColor (stencilAsColorBuffer);
771 const int numUsedChannels (tcu::getNumUsedChannels(stencilAsColor.getFormat().order));
772
773 convertStencilToColorBufferAccess(image, stencilAsColor, maxStencilValue);
774
775 result = verifyImageMultipleBars(log, stencilAsColor, barWidthRatios, barStencils, barsCount, numUsedChannels, checkType);
776 }
777 else
778 {
779 const std::string checkType = "Color";
780 const tcu::Vec4 baseColor (s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
781 const tcu::Vec4 barColors[barsCount] = { scaleColor(baseColor, 1.00f), scaleColor(baseColor, 0.50f), scaleColor(baseColor, 0.25f) };
782 const int numUsedChannels (tcu::getNumUsedChannels(image.getFormat().order));
783
784 result = verifyImageMultipleBars(log, image, barWidthRatios, barColors, barsCount, numUsedChannels, checkType);
785 }
786
787 return result;
788 }
789
790 case TEST_TYPE_SECONDARY_CMD_BUFFER:
791 {
792 const tcu::Vec4 clearColor = secondaryCmdBufClearColors[layerNdx % DE_LENGTH_OF_ARRAY(secondaryCmdBufClearColors)];
793 const tcu::Vec4 quadColor = s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)];
794 // The first draw: blend clearColor and quadColor
795 const tcu::Vec4 firstDraw = (clearColor + quadColor) * 0.5f;
796 // The second draw: blend previous result and quadColor
797 const tcu::Vec4 secondDraw = (firstDraw + quadColor) * 0.5f;
798
799 return verifyImageSingleColoredRow(log, image, 0.5f, secondDraw, layerNdx < numLayers / 2, layerNdx >= numLayers / 2);
800 }
801
802 default:
803 DE_ASSERT(0);
804 return false;
805 }
806 }
807
getLayerDescription(const VkImageViewType viewType,const int layer)808 std::string getLayerDescription (const VkImageViewType viewType, const int layer)
809 {
810 std::ostringstream str;
811 const int numCubeFaces = 6;
812
813 if (isCubeImageViewType(viewType))
814 str << "cube " << (layer / numCubeFaces) << ", face " << (layer % numCubeFaces);
815 else if (viewType == VK_IMAGE_VIEW_TYPE_3D)
816 str << "slice z = " << layer;
817 else
818 str << "layer " << layer;
819
820 return str.str();
821 }
822
verifyResults(tcu::TestLog & log,const TestParams & params,const VkFormat imageFormat,const void * resultData,const bool depthCheck=false,const bool stencilCheck=false)823 bool verifyResults (tcu::TestLog& log, const TestParams& params, const VkFormat imageFormat, const void* resultData, const bool depthCheck = false, const bool stencilCheck = false)
824 {
825 const LayeredImageAccess image = LayeredImageAccess::create(getImageType(params.image.viewType), imageFormat, params.image.size, params.image.numLayers, resultData);
826
827 int numGoodLayers = 0;
828
829 for (int layerNdx = 0; layerNdx < image.getNumLayersOrSlices(); ++layerNdx)
830 {
831 const tcu::ConstPixelBufferAccess layerImage = image.getLayer(layerNdx);
832
833 log << tcu::TestLog::Message << "Verifying " << getLayerDescription(params.image.viewType, layerNdx) << tcu::TestLog::EndMessage;
834
835 if (verifyLayerContent(log, params.testType, layerImage, layerNdx, image.getNumLayersOrSlices(), depthCheck, stencilCheck))
836 ++numGoodLayers;
837 }
838
839 return numGoodLayers == image.getNumLayersOrSlices();
840 }
841
toGlsl(const Vec4 & v)842 std::string toGlsl (const Vec4& v)
843 {
844 std::ostringstream str;
845 str << "vec4(";
846 for (int i = 0; i < 4; ++i)
847 str << (i != 0 ? ", " : "") << de::floatToString(v[i], 1);
848 str << ")";
849 return str.str();
850 }
851
initPrograms(SourceCollections & programCollection,const TestParams params)852 void initPrograms (SourceCollections& programCollection, const TestParams params)
853 {
854 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);
855
856 // Vertex shader
857 {
858 std::ostringstream src;
859 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
860 << "\n"
861 << "void main(void)\n"
862 << "{\n"
863 << "}\n";
864
865 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
866 }
867
868 // Geometry shader
869 {
870 const int numLayers = static_cast<int>(params.image.viewType == VK_IMAGE_VIEW_TYPE_3D ? params.image.size.depth : params.image.numLayers);
871
872 const int maxVertices = (params.testType == TEST_TYPE_DIFFERENT_CONTENT) ? (numLayers + 1) * numLayers :
873 (params.testType == TEST_TYPE_ALL_LAYERS
874 || params.testType == TEST_TYPE_LAYER_ID
875 || params.testType == TEST_TYPE_LAYERED_READBACK
876 || params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER) ? numLayers * 4 :
877 (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION) ? 6 : 4;
878
879 std::ostringstream src;
880 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
881 << "\n";
882
883 if (params.testType == TEST_TYPE_LAYERED_READBACK)
884 src << "layout(binding = 0) readonly uniform Input {\n"
885 << " int pass;\n"
886 << "} uInput;\n\n";
887
888 if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
889 src << "layout(points, invocations = " << numLayers << ") in;\n";
890 else
891 src << "layout(points) in;\n";
892
893 src << "layout(triangle_strip, max_vertices = " << maxVertices << ") out;\n"
894 << "\n"
895 << (geomOutputColor ? "layout(location = 0) out vec4 vert_color;\n\n" : "")
896 << "out gl_PerVertex {\n"
897 << " vec4 gl_Position;\n"
898 << " float gl_PointSize;\n"
899 << "};\n"
900 << "\n"
901 << "void main(void)\n"
902 << "{\n";
903
904 std::ostringstream colorTable;
905 {
906 const int numColors = DE_LENGTH_OF_ARRAY(s_colors);
907
908 colorTable << " const vec4 colors[" << numColors << "] = vec4[" << numColors << "](";
909
910 const std::string padding(colorTable.str().length(), ' ');
911
912 for (int i = 0; i < numColors; ++i)
913 colorTable << (i != 0 ? ",\n" + padding : "") << toGlsl(s_colors[i]);
914
915 colorTable << ");\n";
916 }
917
918 if (params.testType == TEST_TYPE_DEFAULT_LAYER)
919 {
920 src << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
921 << " gl_PointSize = 1.0;\n"
922 << " EmitVertex();\n"
923 << "\n"
924 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
925 << " gl_PointSize = 1.0;\n"
926 << " EmitVertex();\n"
927 << "\n"
928 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
929 << " gl_PointSize = 1.0;\n"
930 << " EmitVertex();\n"
931 << "\n"
932 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
933 << " gl_PointSize = 1.0;\n"
934 << " EmitVertex();\n";
935 }
936 else if (params.testType == TEST_TYPE_SINGLE_LAYER)
937 {
938 const deUint32 targetLayer = getTargetLayer(params.image);
939
940 src << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
941 << " gl_Layer = " << targetLayer << ";\n"
942 << " gl_PointSize = 1.0;\n"
943 << " EmitVertex();\n"
944 << "\n"
945 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
946 << " gl_Layer = " << targetLayer << ";\n"
947 << " gl_PointSize = 1.0;\n"
948 << " EmitVertex();\n"
949 << "\n"
950 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
951 << " gl_Layer = " << targetLayer << ";\n"
952 << " gl_PointSize = 1.0;\n"
953 << " EmitVertex();\n"
954 << "\n"
955 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
956 << " gl_Layer = " << targetLayer << ";\n"
957 << " gl_PointSize = 1.0;\n"
958 << " EmitVertex();\n";
959 }
960 else if (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER)
961 {
962 src << colorTable.str()
963 << "\n"
964 << " for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
965 << " const int colorNdx = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
966 << "\n"
967 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
968 << " gl_Layer = layerNdx;\n"
969 << " vert_color = colors[colorNdx];\n"
970 << " gl_PointSize = 1.0;\n"
971 << " EmitVertex();\n"
972 << "\n"
973 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
974 << " gl_Layer = layerNdx;\n"
975 << " vert_color = colors[colorNdx];\n"
976 << " gl_PointSize = 1.0;\n"
977 << " EmitVertex();\n"
978 << "\n"
979 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
980 << " gl_Layer = layerNdx;\n"
981 << " vert_color = colors[colorNdx];\n"
982 << " gl_PointSize = 1.0;\n"
983 << " EmitVertex();\n"
984 << "\n"
985 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
986 << " gl_Layer = layerNdx;\n"
987 << " vert_color = colors[colorNdx];\n"
988 << " gl_PointSize = 1.0;\n"
989 << " EmitVertex();\n"
990 << " EndPrimitive();\n"
991 << " };\n";
992 }
993 else if (params.testType == TEST_TYPE_LAYER_ID)
994 {
995 src << " for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
996 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
997 << " gl_Layer = layerNdx;\n"
998 << " gl_PointSize = 1.0;\n"
999 << " EmitVertex();\n"
1000 << "\n"
1001 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
1002 << " gl_Layer = layerNdx;\n"
1003 << " gl_PointSize = 1.0;\n"
1004 << " EmitVertex();\n"
1005 << "\n"
1006 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
1007 << " gl_Layer = layerNdx;\n"
1008 << " gl_PointSize = 1.0;\n"
1009 << " EmitVertex();\n"
1010 << "\n"
1011 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
1012 << " gl_Layer = layerNdx;\n"
1013 << " gl_PointSize = 1.0;\n"
1014 << " EmitVertex();\n"
1015 << " EndPrimitive();\n"
1016 << " };\n";
1017 }
1018 else if (params.testType == TEST_TYPE_DIFFERENT_CONTENT)
1019 {
1020 src << " for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
1021 << " for (int colNdx = 0; colNdx <= layerNdx; ++colNdx) {\n"
1022 << " const float posX = float(colNdx) / float(" << numLayers << ") * 2.0 - 1.0;\n"
1023 << "\n"
1024 << " gl_Position = vec4(posX, 1.0, 0.0, 1.0);\n"
1025 << " gl_Layer = layerNdx;\n"
1026 << " gl_PointSize = 1.0;\n"
1027 << " EmitVertex();\n"
1028 << "\n"
1029 << " gl_Position = vec4(posX, -1.0, 0.0, 1.0);\n"
1030 << " gl_Layer = layerNdx;\n"
1031 << " gl_PointSize = 1.0;\n"
1032 << " EmitVertex();\n"
1033 << " }\n"
1034 << " EndPrimitive();\n"
1035 << " }\n";
1036 }
1037 else if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER)
1038 {
1039 src << colorTable.str()
1040 << " const int colorNdx = gl_InvocationID % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
1041 << "\n"
1042 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1043 << " gl_Layer = gl_InvocationID;\n"
1044 << " gl_PointSize = 1.0;\n"
1045 << " vert_color = colors[colorNdx];\n"
1046 << " EmitVertex();\n"
1047 << "\n"
1048 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
1049 << " gl_Layer = gl_InvocationID;\n"
1050 << " gl_PointSize = 1.0;\n"
1051 << " vert_color = colors[colorNdx];\n"
1052 << " EmitVertex();\n"
1053 << "\n"
1054 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
1055 << " gl_Layer = gl_InvocationID;\n"
1056 << " gl_PointSize = 1.0;\n"
1057 << " vert_color = colors[colorNdx];\n"
1058 << " EmitVertex();\n"
1059 << "\n"
1060 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
1061 << " gl_Layer = gl_InvocationID;\n"
1062 << " gl_PointSize = 1.0;\n"
1063 << " vert_color = colors[colorNdx];\n"
1064 << " EmitVertex();\n"
1065 << " EndPrimitive();\n";
1066 }
1067 else if (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
1068 {
1069 src << " const int layerA = gl_InvocationID;\n"
1070 << " const int layerB = (gl_InvocationID + 1) % " << numLayers << ";\n"
1071 << " const float aEnd = float(layerA) / float(" << numLayers << ") * 2.0 - 1.0;\n"
1072 << " const float bEnd = float(layerB) / float(" << numLayers << ") * 2.0 - 1.0;\n"
1073 << "\n"
1074 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1075 << " gl_Layer = layerA;\n"
1076 << " gl_PointSize = 1.0;\n"
1077 << " EmitVertex();\n"
1078 << "\n"
1079 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
1080 << " gl_Layer = layerA;\n"
1081 << " gl_PointSize = 1.0;\n"
1082 << " EmitVertex();\n"
1083 << "\n"
1084 << " gl_Position = vec4(aEnd, -1.0, 0.0, 1.0);\n"
1085 << " gl_Layer = layerA;\n"
1086 << " gl_PointSize = 1.0;\n"
1087 << " EmitVertex();\n"
1088 << " EndPrimitive();\n"
1089 << "\n"
1090 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
1091 << " gl_Layer = layerB;\n"
1092 << " gl_PointSize = 1.0;\n"
1093 << " EmitVertex();\n"
1094 << "\n"
1095 << " gl_Position = vec4(bEnd, 1.0, 0.0, 1.0);\n"
1096 << " gl_Layer = layerB;\n"
1097 << " gl_PointSize = 1.0;\n"
1098 << " EmitVertex();\n"
1099 << "\n"
1100 << " gl_Position = vec4(bEnd, -1.0, 0.0, 1.0);\n"
1101 << " gl_Layer = layerB;\n"
1102 << " gl_PointSize = 1.0;\n"
1103 << " EmitVertex();\n"
1104 << " EndPrimitive();\n";
1105 }
1106 else if (params.testType == TEST_TYPE_LAYERED_READBACK)
1107 {
1108 src << colorTable.str()
1109 << " for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
1110 << " const int colorNdx = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
1111 << " const vec3 passColor0 = (uInput.pass == 0 ? 0.5 : 1.0) * vec3(colors[colorNdx]);\n"
1112 << " const vec4 passColor = vec4(passColor0, 1.0);\n"
1113 << " const float posX = (uInput.pass == 0 ? 0.0 : -0.5);\n"
1114 << " const float posZ = float(layerNdx + 1 - uInput.pass) / float(" << 2*numLayers << ");\n"
1115 << "\n"
1116 << " gl_Position = vec4(-1.0, -1.0, posZ, 1.0);\n"
1117 << " gl_Layer = layerNdx;\n"
1118 << " gl_PointSize = 1.0;\n"
1119 << " vert_color = passColor;\n"
1120 << " EmitVertex();\n"
1121 << "\n"
1122 << " gl_Position = vec4(-1.0, 1.0, posZ, 1.0);\n"
1123 << " gl_Layer = layerNdx;\n"
1124 << " gl_PointSize = 1.0;\n"
1125 << " vert_color = passColor;\n"
1126 << " EmitVertex();\n"
1127 << "\n"
1128 << " gl_Position = vec4(posX, -1.0, posZ, 1.0);\n"
1129 << " gl_Layer = layerNdx;\n"
1130 << " gl_PointSize = 1.0;\n"
1131 << " vert_color = passColor;\n"
1132 << " EmitVertex();\n"
1133 << "\n"
1134 << " gl_Position = vec4(posX, 1.0, posZ, 1.0);\n"
1135 << " gl_Layer = layerNdx;\n"
1136 << " gl_PointSize = 1.0;\n"
1137 << " vert_color = passColor;\n"
1138 << " EmitVertex();\n"
1139 << "\n"
1140 << " EndPrimitive();\n"
1141 << " }\n";
1142 }
1143 else
1144 DE_ASSERT(0);
1145
1146 src << "}\n"; // end main
1147
1148 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
1149 }
1150
1151 // Fragment shader
1152 {
1153 std::string imageViewString;
1154
1155 switch (params.image.viewType)
1156 {
1157 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1158 imageViewString = "image1DArray";
1159 break;
1160 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1161 imageViewString = "image2DArray";
1162 break;
1163 case VK_IMAGE_VIEW_TYPE_CUBE:
1164 imageViewString = "imageCube";
1165 break;
1166 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1167 imageViewString = "imageCubeArray";
1168 break;
1169 default:
1170 DE_ASSERT(params.image.viewType == VK_IMAGE_VIEW_TYPE_3D);
1171 imageViewString = "image3D";
1172 break;
1173 }
1174
1175 std::ostringstream src;
1176 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1177 << "\n"
1178 << "layout(location = 0) out vec4 o_color;\n"
1179 << (geomOutputColor ? "layout(location = 0) in vec4 vert_color;\n" : "")
1180 << (params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER ? std::string("layout(set = 0, binding = 0, rgba8) uniform " + imageViewString + " storageImage;\n") : std::string(""))
1181 << "\n"
1182 << "void main(void)\n"
1183 << "{\n";
1184
1185 if (params.testType == TEST_TYPE_LAYER_ID)
1186 {
1187 // This code must be in sync with verifyLayerContent()
1188 src << " o_color = vec4( (gl_Layer % 2) == 1 ? 1.0 : 0.5,\n"
1189 << " ((gl_Layer/2) % 2) == 1 ? 1.0 : 0.5,\n"
1190 << " gl_Layer == 0 ? 1.0 : 0.0,\n"
1191 << " 1.0);\n";
1192 }
1193 else if (params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER)
1194 {
1195 switch (params.image.viewType)
1196 {
1197 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1198 src << " ivec2 coord = ivec2(int(gl_FragCoord.x), gl_Layer);\n";
1199 break;
1200 default:
1201 src << " ivec3 coord = ivec3(int(gl_FragCoord.x), int(gl_FragCoord.y), gl_Layer);\n";
1202 break;
1203 }
1204
1205 src << " vec4 src_color = imageLoad(storageImage, coord);\n"
1206 << " o_color = (vert_color + src_color) / 2.0;\n"
1207 << " imageStore(storageImage, coord, o_color);\n";
1208 }
1209 else if (geomOutputColor)
1210 src << " o_color = vert_color;\n";
1211 else
1212 src << " o_color = vec4(1.0);\n";
1213
1214 src << "}\n";
1215
1216 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1217 }
1218 }
1219
test(Context & context,const TestParams params)1220 tcu::TestStatus test (Context& context, const TestParams params)
1221 {
1222 const DeviceInterface& vk = context.getDeviceInterface();
1223 const InstanceInterface& vki = context.getInstanceInterface();
1224 const VkDevice device = context.getDevice();
1225 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1226 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1227 const VkQueue queue = context.getUniversalQueue();
1228 Allocator& allocator = context.getDefaultAllocator();
1229 VkDeviceSize nonCoherentAtomSize = vk::getPhysicalDeviceProperties(vki, physDevice).limits.nonCoherentAtomSize;
1230 VkDeviceSize alignmentSize = std::max<VkDeviceSize>(nonCoherentAtomSize, 4u);
1231
1232 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1233 const deUint32 numLayers = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1234 const Vec4 clearColor = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1235 const deUint32 colorImagePixelSize = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
1236 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);
1237 const VkImageCreateFlags imageCreateFlags = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1238 (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
1239 const VkImageViewType viewType = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1240
1241 const Unique<VkImage> colorImage (makeImage (vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
1242 params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1243 const UniquePtr<Allocation> colorImageAlloc (bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any));
1244 const Unique<VkImageView> colorAttachment (makeImageView (vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1245
1246 const Unique<VkBuffer> colorBuffer (makeBuffer (vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1247 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1248
1249 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
1250 const Unique<VkShaderModule> geometryModule (createShaderModule (vk, device, context.getBinaryCollection().get("geom"), 0u));
1251 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
1252
1253 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, colorFormat));
1254 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, *colorAttachment, params.image.size.width, params.image.size.height, numLayers));
1255 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device));
1256 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
1257 makeExtent2D(params.image.size.width, params.image.size.height)));
1258 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1259 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1260
1261 zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1262
1263 beginCommandBuffer(vk, *cmdBuffer);
1264
1265 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, params.image.size.width, params.image.size.height), clearColor);
1266
1267 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1268 vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1269 endRenderPass(vk, *cmdBuffer);
1270
1271 // Copy color image to buffer
1272 copyLayeredImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, params.image);
1273
1274 endCommandBuffer(vk, *cmdBuffer);
1275 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1276
1277 invalidateAlloc(vk, device, *colorBufferAlloc);
1278
1279 if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1280 return tcu::TestStatus::fail("Rendered images are incorrect");
1281 else
1282 return tcu::TestStatus::pass("OK");
1283 }
1284
testLayeredReadBack(Context & context,const TestParams params)1285 tcu::TestStatus testLayeredReadBack (Context& context, const TestParams params)
1286 {
1287 const DeviceInterface& vk = context.getDeviceInterface();
1288 const InstanceInterface& vki = context.getInstanceInterface();
1289 const VkDevice device = context.getDevice();
1290 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1291 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1292 const VkQueue queue = context.getUniversalQueue();
1293 Allocator& allocator = context.getDefaultAllocator();
1294 VkDeviceSize nonCoherentAtomSize = vk::getPhysicalDeviceProperties(vki, physDevice).limits.nonCoherentAtomSize;
1295 VkDeviceSize alignmentSize = std::max<VkDeviceSize>(nonCoherentAtomSize, 4u);
1296
1297 const size_t passCount = 2;
1298 const deUint32 numLayers = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1299 const VkImageCreateFlags imageCreateFlags = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1300 (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
1301 const VkImageViewType viewType = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1302 const VkImageType imageType = getImageType(params.image.viewType);
1303 const VkExtent2D imageExtent2D = makeExtent2D(params.image.size.width, params.image.size.height);
1304
1305 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1306 const deUint32 colorImagePixelSize = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
1307 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 );
1308 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1309
1310 const bool dsUsed = true;
1311 const VkFormat dsFormat = VK_FORMAT_D24_UNORM_S8_UINT;
1312 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.
1313 const VkExtent3D dsImageSize = makeExtent3D(params.image.size.width, params.image.size.height, 1u);
1314 const VkImageCreateFlags dsImageCreateFlags = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0);
1315 const deUint32 dsImagePixelSize = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(dsFormat)));
1316 const VkImageUsageFlags dsImageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1317 const VkImageAspectFlags dsAspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
1318 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);
1319
1320 const VkFormat stencilBufferFormat = getStencilBufferFormat(dsFormat);
1321 const deUint32 stencilPixelSize = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(stencilBufferFormat)));
1322 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);
1323
1324 checkImageFormatProperties(vki, physDevice, imageType, VK_IMAGE_TILING_OPTIMAL, dsImageUsage, imageCreateFlags, dsFormat, params.image.size, params.image.numLayers);
1325
1326 const Unique<VkImage> colorImage (makeImage (vk, device, makeImageCreateInfo(imageCreateFlags, imageType, colorFormat, params.image.size, params.image.numLayers, colorImageUsage)));
1327 const UniquePtr<Allocation> colorImageAlloc (bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any));
1328 const Unique<VkImageView> colorAttachment (makeImageView (vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1329 const Unique<VkBuffer> colorBuffer (makeBuffer (vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1330 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1331
1332 const Unique<VkImage> dsImage (makeImage (vk, device, makeImageCreateInfo(dsImageCreateFlags, dsImageType, dsFormat, dsImageSize, numLayers, dsImageUsage)));
1333 const UniquePtr<Allocation> dsImageAlloc (bindImage (vk, device, allocator, *dsImage, MemoryRequirement::Any));
1334 const Unique<VkImageView> dsAttachment (makeImageView (vk, device, *dsImage, viewType, dsFormat, makeImageSubresourceRange(dsAspectFlags, 0u, 1u, 0u, numLayers)));
1335 const Unique<VkBuffer> depthBuffer (makeBuffer (vk, device, depthBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1336 const UniquePtr<Allocation> depthBufferAlloc (bindBuffer (vk, device, allocator, *depthBuffer, MemoryRequirement::HostVisible));
1337 const Unique<VkBuffer> stencilBuffer (makeBuffer (vk, device, stencilBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1338 const UniquePtr<Allocation> stencilBufferAlloc (bindBuffer (vk, device, allocator, *stencilBuffer, MemoryRequirement::HostVisible));
1339
1340 const VkImageView attachments[] = {*colorAttachment, *dsAttachment};
1341 const deUint32 attachmentsCount = dsUsed ? DE_LENGTH_OF_ARRAY(attachments) : 1u;
1342
1343 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
1344 const Unique<VkShaderModule> geometryModule (createShaderModule (vk, device, context.getBinaryCollection().get("geom"), 0u));
1345 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
1346
1347 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, colorFormat, dsFormat, dsUsed));
1348 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, attachmentsCount, attachments, params.image.size.width, params.image.size.height, numLayers));
1349
1350 const Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder()
1351 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, passCount)
1352 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, passCount);
1353 const Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder()
1354 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_GEOMETRY_BIT)
1355 .build(vk, device);
1356 const Move<VkDescriptorSet> descriptorSet[] =
1357 {
1358 makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout),
1359 makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout),
1360 };
1361
1362 const size_t uniformBufSize = sizeof(deUint32);
1363 const VkBufferCreateInfo uniformBufCI = makeBufferCreateInfo(uniformBufSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1364 const Move<VkBuffer> uniformBuf[] = { createBuffer(vk, device, &uniformBufCI), createBuffer(vk, device, &uniformBufCI) };
1365 const MovePtr<Allocation> uniformBufAlloc[] =
1366 {
1367 allocator.allocate(getBufferMemoryRequirements(vk, device, *uniformBuf[0]), MemoryRequirement::HostVisible),
1368 allocator.allocate(getBufferMemoryRequirements(vk, device, *uniformBuf[1]), MemoryRequirement::HostVisible),
1369 };
1370 const VkDescriptorBufferInfo uniformBufDesc[] =
1371 {
1372 makeDescriptorBufferInfo(*uniformBuf[0], 0ull, uniformBufSize),
1373 makeDescriptorBufferInfo(*uniformBuf[1], 0ull, uniformBufSize),
1374 };
1375
1376 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device, *descriptorSetLayout));
1377 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule, imageExtent2D, dsUsed));
1378 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1379 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1380 const VkImageSubresourceRange colorSubresRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers);
1381 const VkImageSubresourceRange dsSubresRange = makeImageSubresourceRange(dsAspectFlags, 0u, 1u, 0u, numLayers);
1382 std::string result;
1383
1384 beginCommandBuffer(vk, *cmdBuffer);
1385 {
1386 // Transition the images to new layouts
1387 const VkImageMemoryBarrier colorBarrier = makeImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1388 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *colorImage, colorSubresRange);
1389 const VkImageMemoryBarrier dsBarrier = makeImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1390 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *dsImage, dsSubresRange);
1391
1392 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorBarrier);
1393
1394 if (dsUsed)
1395 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsBarrier);
1396
1397 for (deUint32 layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1398 {
1399 const VkExtent3D imageExtent = makeExtent3D(params.image.size.width, params.image.size.height, 1u);
1400
1401 // Clear color image with initial value
1402 {
1403 const deUint32 layer = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? 0u : layerNdx;
1404 const deUint32 imageDepth = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? layerNdx : 0u;
1405 const VkOffset3D imageOffset = makeOffset3D(0u, 0u, imageDepth);
1406
1407 const tcu::Vec4 clearColor = scaleColor(s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)], 0.25f);
1408 const deUint32 bufferSliceSize = deAlign32( params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<deInt32>(alignmentSize));
1409 const VkDeviceSize bufferOffset = layerNdx * bufferSliceSize;
1410 const VkImageSubresourceLayers imageSubresource = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, layer, 1u);
1411 const VkBufferImageCopy bufferImageCopyRegion = makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
1412
1413 fillBuffer(vk, device, *colorBufferAlloc, bufferOffset, bufferSliceSize, colorFormat, clearColor);
1414 vk.cmdCopyBufferToImage(*cmdBuffer, *colorBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1415 }
1416
1417 // Clear depth image with initial value
1418 if (dsUsed)
1419 {
1420 const float depthValue = 1.0f;
1421 const deUint32 bufferSliceSize = deAlign32( params.image.size.width * params.image.size.height * dsImagePixelSize, static_cast<deInt32>(alignmentSize));
1422 const VkDeviceSize bufferOffset = layerNdx * bufferSliceSize;
1423 const VkImageSubresourceLayers imageSubresource = makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, layerNdx, 1u);
1424 const VkBufferImageCopy bufferImageCopyRegion = makeBufferImageCopy(bufferOffset, imageSubresource, makeOffset3D(0u, 0u, 0u), imageExtent);
1425
1426 fillBuffer(vk, device, *depthBufferAlloc, bufferOffset, bufferSliceSize, dsFormat, depthValue);
1427 vk.cmdCopyBufferToImage(*cmdBuffer, *depthBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1428 }
1429
1430 // Clear stencil image with initial value
1431 if (dsUsed)
1432 {
1433 const deUint8 stencilValue = 0;
1434 const deUint32 bufferSliceSize = deAlign32( params.image.size.width * params.image.size.height * stencilPixelSize, static_cast<deInt32>(alignmentSize));
1435 const VkDeviceSize bufferOffset = layerNdx * bufferSliceSize;
1436 const VkImageSubresourceLayers imageSubresource = makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, layerNdx, 1u);
1437 const VkBufferImageCopy bufferImageCopyRegion = makeBufferImageCopy(bufferOffset, imageSubresource, makeOffset3D(0u, 0u, 0u), imageExtent);
1438 deUint8* bufferStart = static_cast<deUint8*>((*stencilBufferAlloc).getHostPtr());
1439 deUint8* bufferLayerStart = &bufferStart[bufferOffset];
1440
1441 deMemset(bufferLayerStart, stencilValue, bufferSliceSize);
1442 flushMappedMemoryRange(vk, device, stencilBufferAlloc->getMemory(), stencilBufferAlloc->getOffset() + bufferOffset, bufferSliceSize);
1443 vk.cmdCopyBufferToImage(*cmdBuffer, *stencilBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1444 }
1445 }
1446 }
1447 // Change images layouts
1448 {
1449 // VK_ATTACHMENT_LOAD_OP_LOAD is used for both color and D/S attachments. Thus,
1450 // VK_ACCESS_COLOR_ATTACHMENT_READ_BIT and VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
1451 // bits must be included in the destination access mask of the color and depth barriers
1452 // respectively.
1453 const VkImageMemoryBarrier colorBarrier = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1454 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresRange);
1455 const VkImageMemoryBarrier dsBarrier = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1456 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *dsImage, dsSubresRange);
1457
1458 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorBarrier);
1459
1460 if (dsUsed)
1461 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsBarrier);
1462 }
1463
1464 {
1465 // These barriers are inserted between each pair of renderpasses in the following
1466 // loop. Note that VK_ATTACHMENT_LOAD_OP_LOAD is used for color and D/S attachments
1467 // hence VK_ACCESS_COLOR_ATTACHMENT_READ_BIT and VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
1468 // bits are included in src and dst access mask of the color and depth barriers.
1469 const VkImageMemoryBarrier colorPassBarrier = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1470 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1471 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresRange);
1472 const VkImageMemoryBarrier dsPassBarrier = makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1473 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1474 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *dsImage, dsSubresRange);
1475 for (deUint32 pass = 0; pass < passCount; ++pass)
1476 {
1477 DE_ASSERT(sizeof(pass) == uniformBufSize);
1478
1479 VK_CHECK(vk.bindBufferMemory(device, *uniformBuf[pass], uniformBufAlloc[pass]->getMemory(), uniformBufAlloc[pass]->getOffset()));
1480 deMemcpy(uniformBufAlloc[pass]->getHostPtr(), &pass, uniformBufSize);
1481 flushMappedMemoryRange(vk, device, uniformBufAlloc[pass]->getMemory(), uniformBufAlloc[pass]->getOffset(), VK_WHOLE_SIZE);
1482
1483 DescriptorSetUpdateBuilder()
1484 .writeSingle(*descriptorSet[pass], DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufDesc[pass])
1485 .update(vk, device);
1486
1487 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet[pass], 0u, DE_NULL);
1488 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(imageExtent2D));
1489 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1490 vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1491 endRenderPass(vk, *cmdBuffer);
1492
1493 // Don't add the barrier after the last renderpass
1494 if (pass < passCount - 1)
1495 {
1496 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);
1497
1498 if (dsUsed)
1499 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);
1500 }
1501 }
1502 }
1503 endCommandBuffer(vk, *cmdBuffer);
1504 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1505
1506 zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1507 zeroBuffer(vk, device, *depthBufferAlloc, depthBufferSize);
1508 zeroBuffer(vk, device, *stencilBufferAlloc, stencilBufferSize);
1509
1510 beginCommandBuffer(vk, *cmdBuffer);
1511 {
1512 // Copy color image
1513 {
1514 const VkImageMemoryBarrier preCopyBarrier = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1515 VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorImage, colorSubresRange);
1516 const VkBufferImageCopy region = makeBufferImageCopy(params.image.size, makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, params.image.numLayers));
1517 const VkBufferMemoryBarrier postCopyBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
1518
1519 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1520 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
1521 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
1522 }
1523
1524 // Depth/Stencil image copy
1525 if (dsUsed)
1526 {
1527 const VkImageMemoryBarrier preCopyBarrier = makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1528 VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dsImage, dsSubresRange);
1529 const VkBufferImageCopy depthCopyRegion = makeBufferImageCopy(dsImageSize, makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, numLayers));
1530 const VkBufferImageCopy stencilCopyRegion = makeBufferImageCopy(dsImageSize, makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, numLayers));
1531 const VkBufferMemoryBarrier postCopyBarriers[] =
1532 {
1533 makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *depthBuffer, 0ull, VK_WHOLE_SIZE),
1534 makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *stencilBuffer, 0ull, VK_WHOLE_SIZE),
1535 };
1536
1537 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1538 vk.cmdCopyImageToBuffer(*cmdBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *depthBuffer, 1u, &depthCopyRegion);
1539 vk.cmdCopyImageToBuffer(*cmdBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *stencilBuffer, 1u, &stencilCopyRegion);
1540 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);
1541 }
1542 }
1543 endCommandBuffer(vk, *cmdBuffer);
1544 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1545
1546 invalidateAlloc(vk, device, *colorBufferAlloc);
1547 invalidateAlloc(vk, device, *depthBufferAlloc);
1548 invalidateAlloc(vk, device, *stencilBufferAlloc);
1549
1550 if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1551 result += " Color";
1552
1553 if (dsUsed)
1554 {
1555 if (!verifyResults(context.getTestContext().getLog(), params, dsFormat, depthBufferAlloc->getHostPtr(), true, false))
1556 result += " Depth";
1557
1558 if (!verifyResults(context.getTestContext().getLog(), params, stencilBufferFormat, stencilBufferAlloc->getHostPtr(), false, true))
1559 result += " Stencil";
1560 }
1561
1562 if (result.empty())
1563 return tcu::TestStatus::pass("OK");
1564 else
1565 return tcu::TestStatus::fail("Following parts of image are incorrect:" + result);
1566 }
1567
testSecondaryCmdBuffer(Context & context,const TestParams params)1568 tcu::TestStatus testSecondaryCmdBuffer (Context& context, const TestParams params)
1569 {
1570 const DeviceInterface& vk = context.getDeviceInterface();
1571 const InstanceInterface& vki = context.getInstanceInterface();
1572 const VkDevice device = context.getDevice();
1573 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1574 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1575 const VkQueue queue = context.getUniversalQueue();
1576 Allocator& allocator = context.getDefaultAllocator();
1577 VkDeviceSize nonCoherentAtomSize = vk::getPhysicalDeviceProperties(vki, physDevice).limits.nonCoherentAtomSize;
1578 VkDeviceSize alignmentSize = std::max<VkDeviceSize>(nonCoherentAtomSize, 4u);
1579
1580 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1581 const deUint32 numLayers = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1582 const Vec4 clearColor = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1583 const deUint32 colorImagePixelSize = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
1584 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);
1585
1586 const VkImageCreateFlags imageCreateFlags = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1587 (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
1588 const VkImageViewType viewType = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1589
1590 const Unique<VkImage> colorImage (makeImage(vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
1591 params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1592 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1593 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1594
1595 const Unique<VkImage> offscreenImage (makeImage(vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
1596 params.image.numLayers, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)));
1597 const UniquePtr<Allocation> offscreenImageAlloc (bindImage(vk, device, allocator, *offscreenImage, MemoryRequirement::Any));
1598 const Unique<VkImageView> offscreenImageView (makeImageView(vk, device, *offscreenImage, params.image.viewType, colorFormat,
1599 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers)));
1600
1601 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1602 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1603
1604 const Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder() .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u) .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1605 const Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder() .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT) .build(vk, device);
1606 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
1607
1608 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
1609 const Unique<VkShaderModule> geometryModule (createShaderModule(vk, device, context.getBinaryCollection().get("geom"), 0u));
1610 const Unique<VkShaderModule> fragmentModule (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
1611
1612 const Unique<VkRenderPass> renderPass (makeRenderPassWithSelfDependency(vk, device, colorFormat));
1613 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, *colorImageView, params.image.size.width, params.image.size.height, numLayers));
1614 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout));
1615 const Unique<VkPipeline> pipeline (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
1616 makeExtent2D(params.image.size.width, params.image.size.height)));
1617
1618 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1619 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1620 const Unique<VkCommandBuffer> secondaryCmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY));
1621
1622 zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1623
1624 const VkDescriptorImageInfo imageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *offscreenImageView, VK_IMAGE_LAYOUT_GENERAL);
1625
1626 DescriptorSetUpdateBuilder()
1627 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageDescriptorInfo)
1628 .update(vk, device);
1629
1630 // Clear each layer of storage image
1631 {
1632 vk::Unique<vk::VkCommandBuffer> clearCmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1633 beginCommandBuffer(vk, *clearCmdBuffer);
1634
1635 const vk::VkImageSubresourceRange subresourceRange =
1636 {
1637 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
1638 0u, // deUint32 baseMipLevel
1639 1u, // deUint32 levelCount
1640 0u, // deUint32 baseArrayLayer
1641 params.image.numLayers // deUint32 layerCount
1642 };
1643
1644 const vk::VkImageMemoryBarrier preImageBarrier =
1645 {
1646 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
1647 DE_NULL, // const void* pNext
1648 0u, // VkAccessFlags srcAccessMask
1649 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask
1650 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
1651 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout
1652 queueFamilyIndex, // deUint32 srcQueueFamilyIndex
1653 queueFamilyIndex, // deUint32 dstQueueFamilyIndex
1654 *offscreenImage, // VkImage image
1655 subresourceRange // VkImageSubresourceRange subresourceRange
1656 };
1657
1658 const vk::VkImageMemoryBarrier postImageBarrier =
1659 {
1660 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
1661 DE_NULL, // const void* pNext
1662 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
1663 vk::VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags dstAccessMask
1664 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout
1665 vk::VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
1666 queueFamilyIndex, // deUint32 srcQueueFamilyIndex
1667 queueFamilyIndex, // deUint32 dstQueueFamilyIndex
1668 *offscreenImage, // VkImage image
1669 subresourceRange // VkImageSubresourceRange subresourceRange
1670 };
1671
1672 vk.cmdPipelineBarrier(*clearCmdBuffer,
1673 vk::VK_PIPELINE_STAGE_HOST_BIT,
1674 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
1675 (vk::VkDependencyFlags)0,
1676 0, (const vk::VkMemoryBarrier*)DE_NULL,
1677 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1678 1, &preImageBarrier);
1679
1680 for (deUint32 layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1681 {
1682 const deUint32 imageDepth = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? layerNdx : 0u;
1683 const deUint32 layer = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? 0u : layerNdx;
1684 const VkOffset3D imageOffset = makeOffset3D(0u, 0u, imageDepth);
1685 const VkExtent3D imageExtent = makeExtent3D(params.image.size.width, params.image.size.height, 1u);
1686
1687 {
1688 const tcu::Vec4 storageImageClearColor = secondaryCmdBufClearColors[layerNdx % DE_LENGTH_OF_ARRAY(secondaryCmdBufClearColors)];
1689 const deUint32 bufferSliceSize = deAlign32(params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<deInt32>(alignmentSize));
1690 const VkDeviceSize bufferOffset = layerNdx * bufferSliceSize;
1691 const VkImageSubresourceLayers imageSubresource = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, layer, 1u);
1692 const VkBufferImageCopy bufferImageCopyRegion = makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
1693
1694 fillBuffer(vk, device, *colorBufferAlloc, bufferOffset, bufferSliceSize, colorFormat, storageImageClearColor);
1695 vk.cmdCopyBufferToImage(*clearCmdBuffer, *colorBuffer, *offscreenImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1696 }
1697 }
1698
1699 vk.cmdPipelineBarrier(*clearCmdBuffer,
1700 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
1701 vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1702 (vk::VkDependencyFlags)0,
1703 0, (const vk::VkMemoryBarrier*)DE_NULL,
1704 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1705 1, &postImageBarrier);
1706
1707 endCommandBuffer(vk, *clearCmdBuffer);
1708
1709 submitCommandsAndWait(vk, device, queue, *clearCmdBuffer);
1710 }
1711
1712 // Begin secondary command buffer
1713 {
1714 const VkCommandBufferInheritanceInfo commandBufferInheritanceInfo =
1715 {
1716 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType
1717 DE_NULL, // const void* pNext
1718 *renderPass, // VkRenderPass renderPass
1719 0u, // deUint32 subpass
1720 params.inheritFramebuffer ? *framebuffer : (VkFramebuffer)0, // VkFramebuffer framebuffer
1721 VK_FALSE, // VkBool32 occlusionQueryEnable
1722 0u, // VkQueryControlFlags queryFlags
1723 0u // VkQueryPipelineStatisticFlags pipelineStatistics
1724 };
1725
1726 const VkCommandBufferBeginInfo commandBufferBeginInfo =
1727 {
1728 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType
1729 DE_NULL, // const void* pNext
1730 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
1731 | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, // VkCommandBufferUsageFlags flags
1732 &commandBufferInheritanceInfo // const VkCommandBufferInheritanceInfo* pInheritanceInfo
1733 };
1734
1735 VK_CHECK(vk.beginCommandBuffer(*secondaryCmdBuffer, &commandBufferBeginInfo));
1736 }
1737
1738 vk.cmdBindDescriptorSets(*secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
1739
1740 // Clear framebuffer: upper right corner for half of the layers and bottom right for the others.
1741 {
1742 const VkClearAttachment clearAttachment =
1743 {
1744 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
1745 0u, // deUint32 colorAttachment
1746 makeClearValueColorF32(0.5f, 0.25, 0.0f, 1.0f) // VkClearValue clearValue
1747 };
1748
1749 const VkOffset2D offsetTop = { (deInt32)params.image.size.width / 2, 0 };
1750 const VkOffset2D offsetBottom = { (deInt32)params.image.size.width / 2, (deInt32)params.image.size.height / 2 };
1751 const VkExtent2D extentTop = { params.image.size.width / 2, params.image.size.height / 2 };
1752 const VkExtent2D extentBottom = { params.image.size.width / 2, de::max(params.image.size.height / 2, 1u) };
1753 const VkRect2D rectRightTop = { offsetTop, extentTop };
1754 const VkRect2D rectRightBottom = { offsetBottom, extentBottom };
1755
1756 const VkClearRect rects[] =
1757 {
1758 {
1759 rectRightBottom, // VkRect2D rect
1760 numLayers / 2, // deUint32 baseArrayLayer
1761 numLayers / 2 // deUint32 layerCount
1762 },
1763 {
1764 rectRightTop, // VkRect2D rect
1765 0u, // deUint32 baseArrayLayer
1766 numLayers / 2 // deUint32 layerCount
1767 }
1768 };
1769
1770 vk.cmdClearAttachments(*secondaryCmdBuffer, 1u, &clearAttachment, extentTop.height > 0 ? 2u : 1u, rects);
1771 }
1772
1773 vk.cmdBindPipeline(*secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1774 vk.cmdDraw(*secondaryCmdBuffer, 1u, 1u, 0u, 0u);
1775 // Barrier between draws
1776 {
1777 const VkMemoryBarrier barrier =
1778 {
1779 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType
1780 DE_NULL, // const void* pNext
1781 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask
1782 VK_ACCESS_SHADER_READ_BIT // VkAccessFlags dstAccessMask
1783 };
1784
1785 vk.cmdPipelineBarrier(*secondaryCmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 1u, &barrier, 0u, DE_NULL, 0u, DE_NULL);
1786 }
1787 vk.cmdDraw(*secondaryCmdBuffer, 1u, 1u, 0u, 0u);
1788 endCommandBuffer(vk, *secondaryCmdBuffer);
1789
1790 beginCommandBuffer(vk, *cmdBuffer);
1791 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, params.image.size.width, params.image.size.height), clearColor, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
1792 vk.cmdExecuteCommands(*cmdBuffer, 1u, &(*secondaryCmdBuffer));
1793 endRenderPass(vk, *cmdBuffer);
1794
1795 copyLayeredImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, params.image);
1796
1797 endCommandBuffer(vk, *cmdBuffer);
1798 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1799
1800 invalidateAlloc(vk, device, *colorBufferAlloc);
1801
1802 if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1803 return tcu::TestStatus::fail("Rendered images are incorrect");
1804 else
1805 return tcu::TestStatus::pass("OK");
1806 }
1807
checkSupport(Context & context,const TestParams params)1808 void checkSupport (Context& context, const TestParams params)
1809 {
1810 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
1811
1812 if (params.image.viewType == VK_IMAGE_VIEW_TYPE_3D)
1813 {
1814 context.requireDeviceFunctionality("VK_KHR_maintenance1");
1815
1816 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
1817 !context.getPortabilitySubsetFeatures().imageView2DOn3DImage)
1818 {
1819 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Implementation does not support 2D or 2D array image view to be created on a 3D VkImage");
1820 }
1821 }
1822
1823 if (params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER)
1824 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
1825 }
1826
1827 } // anonymous
1828
createLayeredRenderingTests(tcu::TestContext & testCtx)1829 tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx)
1830 {
1831 MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "layered", "Layered rendering tests."));
1832
1833 const struct
1834 {
1835 TestType test;
1836 const char* name;
1837 const char* description;
1838 } testTypes[] =
1839 {
1840 { TEST_TYPE_DEFAULT_LAYER, "render_to_default_layer", "Render to the default layer" },
1841 { TEST_TYPE_SINGLE_LAYER, "render_to_one", "Render to one layer" },
1842 { TEST_TYPE_ALL_LAYERS, "render_to_all", "Render to all layers" },
1843 { TEST_TYPE_DIFFERENT_CONTENT, "render_different_content", "Render different data to different layers" },
1844 { TEST_TYPE_LAYER_ID, "fragment_layer", "Read gl_Layer in fragment shader" },
1845 { TEST_TYPE_INVOCATION_PER_LAYER, "invocation_per_layer", "Render to multiple layers with multiple invocations, one invocation per layer" },
1846 { TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION, "multiple_layers_per_invocation", "Render to multiple layers with multiple invocations, multiple layers per invocation", },
1847 { TEST_TYPE_LAYERED_READBACK, "readback", "Render to multiple layers with two passes to check LOAD_OP_LOAD capability" },
1848 { TEST_TYPE_SECONDARY_CMD_BUFFER, "secondary_cmd_buffer", "Layered rendering using secondary command buffer" }
1849 };
1850
1851 const struct
1852 {
1853 VkImageViewType viewType;
1854 ImageParams imageParams[2];
1855 } imageParamGroups[] =
1856 {
1857 { 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 } } },
1858 { 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 } } },
1859 { VK_IMAGE_VIEW_TYPE_CUBE, { { VK_IMAGE_VIEW_TYPE_CUBE, { 64, 64, 1 }, 6 }, { VK_IMAGE_VIEW_TYPE_CUBE, { 36, 36, 1 }, 6 } } },
1860 { 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 } } },
1861 { VK_IMAGE_VIEW_TYPE_3D, { { VK_IMAGE_VIEW_TYPE_3D, { 64, 64, 8 }, 1 }, { VK_IMAGE_VIEW_TYPE_3D, { 12, 36, 6 }, 1 } } }
1862 };
1863
1864 for (int imageParamGroupNdx = 0; imageParamGroupNdx < DE_LENGTH_OF_ARRAY(imageParamGroups); ++imageParamGroupNdx)
1865 {
1866 MovePtr<tcu::TestCaseGroup> viewTypeMainGroup(new tcu::TestCaseGroup(testCtx, getShortImageViewTypeName(imageParamGroups[imageParamGroupNdx].viewType).c_str(), ""));
1867
1868 for (int imageParamNdx = 0; imageParamNdx < 2; imageParamNdx++)
1869 {
1870 std::ostringstream viewTypeGroupName;
1871 viewTypeGroupName << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].size.width << "_" << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].size.height << "_";
1872 if (imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].viewType == VK_IMAGE_VIEW_TYPE_3D)
1873 viewTypeGroupName << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].size.depth;
1874 else
1875 viewTypeGroupName << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].numLayers;
1876 MovePtr<tcu::TestCaseGroup> viewTypeGroup(new tcu::TestCaseGroup(testCtx, viewTypeGroupName.str().c_str(), ""));
1877
1878 for (int testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx)
1879 {
1880 TestParams params =
1881 {
1882 testTypes[testTypeNdx].test,
1883 imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx],
1884 false
1885 };
1886
1887 if (testTypes[testTypeNdx].test == TEST_TYPE_LAYERED_READBACK)
1888 addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, checkSupport, initPrograms, testLayeredReadBack, params);
1889 else if (testTypes[testTypeNdx].test == TEST_TYPE_SECONDARY_CMD_BUFFER)
1890 {
1891 addFunctionCaseWithPrograms(viewTypeGroup.get(), "secondary_cmd_buffer", testTypes[testTypeNdx].description, checkSupport, initPrograms, testSecondaryCmdBuffer, params);
1892 params.inheritFramebuffer = true;
1893 addFunctionCaseWithPrograms(viewTypeGroup.get(), "secondary_cmd_buffer_inherit_framebuffer", testTypes[testTypeNdx].description, checkSupport, initPrograms, testSecondaryCmdBuffer, params);
1894 }
1895 else
1896 addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, checkSupport, initPrograms, test, params);
1897 }
1898 viewTypeMainGroup->addChild(viewTypeGroup.release());
1899 }
1900 group->addChild(viewTypeMainGroup.release());
1901 }
1902
1903 return group.release();
1904 }
1905
1906 } // geometry
1907 } // vkt
1908