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