1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2014 The Android Open Source Project
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Geometry shader layered rendering tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktGeometryLayeredRenderingTests.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktGeometryTestsUtil.hpp"
29
30 #include "vkPrograms.hpp"
31 #include "vkStrUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkBuilderUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkObjUtil.hpp"
41
42 #include "deStringUtil.hpp"
43 #include "deUniquePtr.hpp"
44
45 #include "tcuTextureUtil.hpp"
46 #include "tcuVectorUtil.hpp"
47 #include "tcuTestLog.hpp"
48
49 namespace vkt
50 {
51 namespace geometry
52 {
53 namespace
54 {
55 using namespace vk;
56 using de::MovePtr;
57 using de::UniquePtr;
58 using tcu::Vec4;
59 using tcu::IVec3;
60
61 enum TestType
62 {
63 TEST_TYPE_DEFAULT_LAYER, // !< draw to default layer
64 TEST_TYPE_SINGLE_LAYER, // !< draw to single layer
65 TEST_TYPE_ALL_LAYERS, // !< draw all layers
66 TEST_TYPE_DIFFERENT_CONTENT, // !< draw different content to different layers
67 TEST_TYPE_LAYER_ID, // !< draw to all layers, verify gl_Layer fragment input
68 TEST_TYPE_INVOCATION_PER_LAYER, // !< draw to all layers, one invocation per layer
69 TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION, // !< draw to all layers, multiple invocations write to multiple layers
70 TEST_TYPE_LAYERED_READBACK, // !< draw to two layers multiple times
71 };
72
73 struct ImageParams
74 {
75 VkImageViewType viewType;
76 VkExtent3D size;
77 deUint32 numLayers;
78 };
79
80 struct TestParams
81 {
82 TestType testType;
83 ImageParams image;
84 };
85
86 static const float s_colors[][4] =
87 {
88 { 1.0f, 1.0f, 1.0f, 1.0f }, // white
89 { 1.0f, 0.0f, 0.0f, 1.0f }, // red
90 { 0.0f, 1.0f, 0.0f, 1.0f }, // green
91 { 0.0f, 0.0f, 1.0f, 1.0f }, // blue
92 { 1.0f, 1.0f, 0.0f, 1.0f }, // yellow
93 { 1.0f, 0.0f, 1.0f, 1.0f }, // magenta
94 };
95
scaleColor(const tcu::Vec4 & color,float factor)96 tcu::Vec4 scaleColor(const tcu::Vec4& color, float factor)
97 {
98 return tcu::Vec4(color[0] * factor,
99 color[1] * factor,
100 color[2] * factor,
101 color[3]);
102 }
103
getTargetLayer(const ImageParams & imageParams)104 deUint32 getTargetLayer (const ImageParams& imageParams)
105 {
106 if (imageParams.viewType == VK_IMAGE_VIEW_TYPE_3D)
107 return imageParams.size.depth / 2;
108 else
109 return imageParams.numLayers / 2;
110 }
111
getShortImageViewTypeName(const VkImageViewType imageViewType)112 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
113 {
114 std::string s(getImageViewTypeName(imageViewType));
115 return de::toLower(s.substr(19));
116 }
117
getImageType(const VkImageViewType viewType)118 VkImageType getImageType (const VkImageViewType viewType)
119 {
120 switch (viewType)
121 {
122 case VK_IMAGE_VIEW_TYPE_1D:
123 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
124 return VK_IMAGE_TYPE_1D;
125
126 case VK_IMAGE_VIEW_TYPE_2D:
127 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
128 case VK_IMAGE_VIEW_TYPE_CUBE:
129 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
130 return VK_IMAGE_TYPE_2D;
131
132 case VK_IMAGE_VIEW_TYPE_3D:
133 return VK_IMAGE_TYPE_3D;
134
135 default:
136 DE_ASSERT(0);
137 return VK_IMAGE_TYPE_LAST;
138 }
139 }
140
getStencilBufferFormat(VkFormat depthStencilImageFormat)141 VkFormat getStencilBufferFormat(VkFormat depthStencilImageFormat)
142 {
143 const tcu::TextureFormat tcuFormat = mapVkFormat(depthStencilImageFormat);
144 const VkFormat result = (tcuFormat.order == tcu::TextureFormat::S || tcuFormat.order == tcu::TextureFormat::DS) ? VK_FORMAT_S8_UINT : VK_FORMAT_UNDEFINED;
145
146 DE_ASSERT(result != VK_FORMAT_UNDEFINED);
147
148 return result;
149 }
150
isCubeImageViewType(const VkImageViewType viewType)151 inline bool isCubeImageViewType (const VkImageViewType viewType)
152 {
153 return viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
154 }
155
checkImageFormatProperties(const InstanceInterface & vki,const VkPhysicalDevice & physDevice,const VkImageType & imageType,const VkImageTiling & imageTiling,const VkImageUsageFlags imageUsageFlags,const VkImageCreateFlags imageCreateFlags,const VkFormat format,const VkExtent3D & requiredSize,const deUint32 requiredLayers)156 void checkImageFormatProperties (const InstanceInterface& vki,
157 const VkPhysicalDevice& physDevice,
158 const VkImageType& imageType,
159 const VkImageTiling& imageTiling,
160 const VkImageUsageFlags imageUsageFlags,
161 const VkImageCreateFlags imageCreateFlags,
162 const VkFormat format,
163 const VkExtent3D& requiredSize,
164 const deUint32 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, imageCreateFlags, &imageFormatProperties);
172
173 if (result != VK_SUCCESS ||
174 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 deUint32 numLayers,const VkImageUsageFlags usage)183 VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const VkImageUsageFlags usage)
184 {
185 const VkImageCreateInfo imageParams =
186 {
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, // deUint32 mipLevels;
194 numLayers, // deUint32 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, // deUint32 queueFamilyIndexCount;
200 DE_NULL, // const deUint32* 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,
207 const VkDevice device,
208 const VkFormat colorFormat,
209 const VkFormat dsFormat,
210 const bool useDepthStencil)
211 {
212 return vk::makeRenderPass(vk, device, colorFormat, useDepthStencil ? dsFormat : VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD);
213 }
214
215
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)216 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
217 const VkDevice device,
218 const VkPipelineLayout pipelineLayout,
219 const VkRenderPass renderPass,
220 const VkShaderModule vertexModule,
221 const VkShaderModule geometryModule,
222 const VkShaderModule fragmentModule,
223 const VkExtent2D renderSize,
224 const bool useDepthStencil = false)
225 {
226 const std::vector<VkViewport> viewports (1, makeViewport(renderSize));
227 const std::vector<VkRect2D> scissors (1, makeRect2D(renderSize));
228
229 const VkStencilOpState stencilOpState = makeStencilOpState(
230 VK_STENCIL_OP_KEEP, // stencil fail
231 VK_STENCIL_OP_INCREMENT_AND_CLAMP, // depth & stencil pass
232 VK_STENCIL_OP_KEEP, // depth only fail
233 VK_COMPARE_OP_ALWAYS, // compare op
234 ~0u, // compare mask
235 ~0u, // write mask
236 0u); // reference
237
238 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
239 {
240 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
241 DE_NULL, // const void* pNext;
242 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
243 useDepthStencil ? VK_TRUE : VK_FALSE, // VkBool32 depthTestEnable;
244 useDepthStencil ? VK_TRUE : VK_FALSE, // VkBool32 depthWriteEnable;
245 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
246 VK_FALSE, // VkBool32 depthBoundsTestEnable;
247 useDepthStencil ? VK_TRUE : VK_FALSE, // VkBool32 stencilTestEnable;
248 stencilOpState, // VkStencilOpState front;
249 stencilOpState, // VkStencilOpState back;
250 0.0f, // float minDepthBounds;
251 1.0f // float maxDepthBounds;
252 };
253
254 return vk::makeGraphicsPipeline(vk, // const DeviceInterface& vk
255 device, // const VkDevice device
256 pipelineLayout, // const VkPipelineLayout pipelineLayout
257 vertexModule, // const VkShaderModule vertexShaderModule
258 DE_NULL, // const VkShaderModule tessellationControlModule
259 DE_NULL, // const VkShaderModule tessellationEvalModule
260 geometryModule, // const VkShaderModule geometryShaderModule
261 fragmentModule, // const VkShaderModule fragmentShaderModule
262 renderPass, // const VkRenderPass renderPass
263 viewports, // const std::vector<VkViewport>& viewports
264 scissors, // const std::vector<VkRect2D>& scissors
265 VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // const VkPrimitiveTopology topology
266 0u, // const deUint32 subpass
267 0u, // const deUint32 patchControlPoints
268 DE_NULL, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
269 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
270 DE_NULL, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
271 &pipelineDepthStencilStateInfo); // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
272 }
273
makeFramebuffer(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass,const VkImageView * pAttachments,const deUint32 attachmentsCount,const deUint32 width,const deUint32 height,const deUint32 layers)274 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface& vk,
275 const VkDevice device,
276 const VkRenderPass renderPass,
277 const VkImageView* pAttachments,
278 const deUint32 attachmentsCount,
279 const deUint32 width,
280 const deUint32 height,
281 const deUint32 layers)
282 {
283 const VkFramebufferCreateInfo framebufferInfo = {
284 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
285 DE_NULL, // const void* pNext;
286 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags;
287 renderPass, // VkRenderPass renderPass;
288 attachmentsCount, // uint32_t attachmentCount;
289 pAttachments, // const VkImageView* pAttachments;
290 width, // uint32_t width;
291 height, // uint32_t height;
292 layers, // uint32_t layers;
293 };
294
295 return createFramebuffer(vk, device, &framebufferInfo);
296 }
297
298 //! Convenience wrapper to access 1D, 2D, and 3D image layers/slices in a uniform way.
299 class LayeredImageAccess
300 {
301 public:
create(const VkImageType type,const VkFormat format,const VkExtent3D size,const deUint32 numLayers,const void * pData)302 static LayeredImageAccess create (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
303 {
304 if (type == VK_IMAGE_TYPE_1D)
305 return LayeredImageAccess(format, size.width, numLayers, pData);
306 else
307 return LayeredImageAccess(type, format, size, numLayers, pData);
308 }
309
getLayer(const int layer) const310 inline tcu::ConstPixelBufferAccess getLayer (const int layer) const
311 {
312 return tcu::getSubregion(m_wholeImage, 0, (m_1dModifier * layer), ((~m_1dModifier & 1) * layer), m_width, m_height, 1);
313 }
314
getNumLayersOrSlices(void) const315 inline int getNumLayersOrSlices (void) const
316 {
317 return m_layers;
318 }
319
320 private:
321 // Specialized for 1D images.
LayeredImageAccess(const VkFormat format,const deUint32 width,const deUint32 numLayers,const void * pData)322 LayeredImageAccess (const VkFormat format, const deUint32 width, const deUint32 numLayers, const void* pData)
323 : m_width (static_cast<int>(width))
324 , m_height (1)
325 , m_1dModifier (1)
326 , m_layers (numLayers)
327 , m_wholeImage (tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_layers, 1, pData))
328 {
329 }
330
LayeredImageAccess(const VkImageType type,const VkFormat format,const VkExtent3D size,const deUint32 numLayers,const void * pData)331 LayeredImageAccess (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
332 : m_width (static_cast<int>(size.width))
333 , m_height (static_cast<int>(size.height))
334 , m_1dModifier (0)
335 , m_layers (static_cast<int>(type == VK_IMAGE_TYPE_3D ? size.depth : numLayers))
336 , m_wholeImage (tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_height, m_layers, pData))
337 {
338 }
339
340 const int m_width;
341 const int m_height;
342 const int m_1dModifier;
343 const int m_layers;
344 const tcu::ConstPixelBufferAccess m_wholeImage;
345 };
346
compareColors(const Vec4 & colorA,const Vec4 & colorB,const Vec4 & threshold)347 inline bool compareColors (const Vec4& colorA, const Vec4& colorB, const Vec4& threshold)
348 {
349 return tcu::allEqual(
350 tcu::lessThan(tcu::abs(colorA - colorB), threshold),
351 tcu::BVec4(true, true, true, true));
352 }
353
verifyImageSingleColoredRow(tcu::TestLog & log,const tcu::ConstPixelBufferAccess image,const float rowWidthRatio,const tcu::Vec4 & barColor)354 bool verifyImageSingleColoredRow (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image, const float rowWidthRatio, const tcu::Vec4& barColor)
355 {
356 DE_ASSERT(rowWidthRatio > 0.0f);
357
358 const Vec4 black (0.0f, 0.0f, 0.0f, 1.0f);
359 const Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
360 const Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
361 const Vec4 threshold (0.02f);
362 const int barLength = static_cast<int>(rowWidthRatio * static_cast<float>(image.getWidth()));
363 const int barLengthThreshold = 1;
364 tcu::TextureLevel errorMask (image.getFormat(), image.getWidth(), image.getHeight());
365 tcu::PixelBufferAccess errorMaskAccess = errorMask.getAccess();
366
367 tcu::clear(errorMask.getAccess(), green);
368
369 log << tcu::TestLog::Message
370 << "Expecting all pixels with distance less or equal to (about) " << barLength
371 << " pixels from left border to be of color " << barColor.swizzle(0, 1, 2) << "."
372 << tcu::TestLog::EndMessage;
373
374 bool allPixelsOk = true;
375
376 for (int y = 0; y < image.getHeight(); ++y)
377 for (int x = 0; x < image.getWidth(); ++x)
378 {
379 const Vec4 color = image.getPixel(x, y);
380 const bool isBlack = compareColors(color, black, threshold);
381 const bool isColor = compareColors(color, barColor, threshold);
382
383 bool isOk;
384
385 if (x <= barLength - barLengthThreshold)
386 isOk = isColor;
387 else if (x >= barLength + barLengthThreshold)
388 isOk = isBlack;
389 else
390 isOk = isColor || isBlack;
391
392 allPixelsOk &= isOk;
393
394 if (!isOk)
395 errorMaskAccess.setPixel(red, x, y);
396 }
397
398 if (allPixelsOk)
399 {
400 log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
401 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
402 << tcu::TestLog::Image("Layer", "Layer", image)
403 << tcu::TestLog::EndImageSet;
404 return true;
405 }
406 else
407 {
408 log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
409 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
410 << tcu::TestLog::Image("Layer", "Layer", image)
411 << tcu::TestLog::Image("ErrorMask", "Errors", errorMask)
412 << tcu::TestLog::EndImageSet;
413 return false;
414 }
415
416 log << tcu::TestLog::Image("LayerContent", "Layer content", image);
417
418 return allPixelsOk;
419 }
420
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)421 static bool verifyImageMultipleBars (tcu::TestLog& log,
422 const tcu::ConstPixelBufferAccess image,
423 const float* barWidthRatios,
424 const tcu::Vec4* barValues,
425 const int barsCount,
426 const int numUsedChannels,
427 const std::string& imageTypeName)
428 {
429 const Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
430 const Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
431 const Vec4 threshold (0.02f);
432 const tcu::TextureFormat errorMaskFormat (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8));
433 tcu::TextureLevel errorMask (errorMaskFormat, image.getWidth(), image.getHeight());
434 tcu::PixelBufferAccess errorMaskAccess = errorMask.getAccess();
435 bool allPixelsOk = true;
436
437 DE_ASSERT(barsCount > 0);
438
439 tcu::clear(errorMask.getAccess(), green);
440
441 // Format information message
442 {
443 int leftBorder = 0;
444 int rightBorder = 0;
445 std::ostringstream str;
446
447 for (int barNdx = 0; barNdx < barsCount; ++barNdx)
448 {
449 leftBorder = rightBorder;
450 rightBorder = static_cast<int>(barWidthRatios[barNdx] * static_cast<float>(image.getWidth()));
451
452 DE_ASSERT(leftBorder < rightBorder);
453
454 str << std::endl << " [" << leftBorder << "," <<rightBorder << "): ";
455
456 switch (numUsedChannels)
457 {
458 case 1: str << barValues[barNdx][0]; break;
459 case 4: str << barValues[barNdx]; break;
460 default: DE_ASSERT(false); break;
461 }
462 }
463
464 log << tcu::TestLog::Message
465 << "Expecting " + imageTypeName + " values depending x-axis position to be of following values: "
466 << str.str()
467 << tcu::TestLog::EndMessage;
468 }
469
470 for (int x = 0; x < image.getWidth(); ++x)
471 {
472 tcu::Vec4 expectedValue = barValues[0];
473
474 for (int barNdx = 0; barNdx < barsCount; ++barNdx)
475 {
476 const int rightBorder = static_cast<int>(barWidthRatios[barNdx] * static_cast<float>(image.getWidth()));
477
478 if (x < rightBorder)
479 {
480 expectedValue = barValues[barNdx];
481
482 break;
483 }
484 }
485
486 for (int y = 0; y < image.getHeight(); ++y)
487 {
488 const tcu::Vec4 realValue = image.getPixel(x, y);
489 bool isOk = false;
490
491 switch (numUsedChannels)
492 {
493 case 1: isOk = fabs(realValue[0] - expectedValue[0]) < threshold[0]; break;
494 case 4: isOk = compareColors(realValue, expectedValue, threshold); break;
495 default: DE_ASSERT(false); break;
496 }
497
498 if (!isOk)
499 errorMaskAccess.setPixel(red, x, y);
500
501 allPixelsOk = allPixelsOk && isOk;
502 }
503 }
504
505 if (allPixelsOk)
506 {
507 log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
508 << tcu::TestLog::ImageSet(imageTypeName + "LayerContent", imageTypeName + " Layer Content")
509 << tcu::TestLog::Image("Layer", "Layer", image)
510 << tcu::TestLog::EndImageSet;
511 }
512 else
513 {
514 log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
515 << tcu::TestLog::ImageSet(imageTypeName + "LayerContent", imageTypeName + " Layer Content")
516 << tcu::TestLog::Image("Layer", "Layer", image)
517 << tcu::TestLog::Image("ErrorMask", "Errors", errorMask)
518 << tcu::TestLog::EndImageSet;
519 }
520
521 return allPixelsOk;
522 }
523
convertDepthToColorBufferAccess(const tcu::ConstPixelBufferAccess & inputImage,tcu::PixelBufferAccess & outputImage)524 static void convertDepthToColorBufferAccess (const tcu::ConstPixelBufferAccess& inputImage, tcu::PixelBufferAccess& outputImage)
525 {
526 for (int y = 0; y < inputImage.getHeight(); y++)
527 for (int x = 0; x < inputImage.getWidth(); x++)
528 {
529 const float depth = inputImage.getPixDepth(x, y);
530 const tcu::Vec4 color = tcu::Vec4(depth, depth, depth, 1.0f);
531
532 outputImage.setPixel(color, x, y);
533 }
534 }
535
convertStencilToColorBufferAccess(const tcu::ConstPixelBufferAccess & inputImage,tcu::PixelBufferAccess & outputImage,int maxValue)536 static void convertStencilToColorBufferAccess (const tcu::ConstPixelBufferAccess& inputImage, tcu::PixelBufferAccess& outputImage, int maxValue)
537 {
538 for (int y = 0; y < inputImage.getHeight(); y++)
539 for (int x = 0; x < inputImage.getWidth(); x++)
540 {
541 const int stencilInt = inputImage.getPixStencil(x, y);
542 const float stencil = (stencilInt < maxValue) ? float(stencilInt) / float(maxValue) : 1.0f;
543 const tcu::Vec4 color = tcu::Vec4(stencil, stencil, stencil, 1.0f);
544
545 outputImage.setPixel(color, x, y);
546 }
547 }
548
verifyEmptyImage(tcu::TestLog & log,const tcu::ConstPixelBufferAccess image)549 bool verifyEmptyImage (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image)
550 {
551 log << tcu::TestLog::Message << "Expecting empty image" << tcu::TestLog::EndMessage;
552
553 const Vec4 black (0.0f, 0.0f, 0.0f, 1.0f);
554 const Vec4 threshold (0.02f);
555
556 for (int y = 0; y < image.getHeight(); ++y)
557 for (int x = 0; x < image.getWidth(); ++x)
558 {
559 const Vec4 color = image.getPixel(x, y);
560
561 if (!compareColors(color, black, threshold))
562 {
563 log << tcu::TestLog::Message
564 << "Found (at least) one bad pixel at " << x << "," << y << ". Pixel color is not background color."
565 << tcu::TestLog::EndMessage
566 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
567 << tcu::TestLog::Image("Layer", "Layer", image)
568 << tcu::TestLog::EndImageSet;
569 return false;
570 }
571 }
572
573 log << tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage;
574
575 return true;
576 }
577
verifyLayerContent(tcu::TestLog & log,const TestType testType,const tcu::ConstPixelBufferAccess image,const int layerNdx,const int numLayers,const bool depthCheck,const bool stencilCheck)578 bool verifyLayerContent (tcu::TestLog& log, const TestType testType, const tcu::ConstPixelBufferAccess image, const int layerNdx, const int numLayers, const bool depthCheck, const bool stencilCheck)
579 {
580 const Vec4 white (1.0f, 1.0f, 1.0f, 1.0f);
581 const int targetLayer = numLayers / 2;
582 const float variableBarRatio = static_cast<float>(layerNdx) / static_cast<float>(numLayers);
583
584 switch (testType)
585 {
586 case TEST_TYPE_DEFAULT_LAYER:
587 if (layerNdx == 0)
588 return verifyImageSingleColoredRow(log, image, 0.5f, white);
589 else
590 return verifyEmptyImage(log, image);
591
592 case TEST_TYPE_SINGLE_LAYER:
593 if (layerNdx == targetLayer)
594 return verifyImageSingleColoredRow(log, image, 0.5f, white);
595 else
596 return verifyEmptyImage(log, image);
597
598 case TEST_TYPE_ALL_LAYERS:
599 case TEST_TYPE_INVOCATION_PER_LAYER:
600 return verifyImageSingleColoredRow(log, image, 0.5f, s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
601
602 case TEST_TYPE_DIFFERENT_CONTENT:
603 case TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION:
604 if (layerNdx == 0)
605 return verifyEmptyImage(log, image);
606 else
607 return verifyImageSingleColoredRow(log, image, variableBarRatio, white);
608
609 case TEST_TYPE_LAYER_ID:
610 {
611 // This code must be in sync with the fragment shader.
612 const tcu::Vec4 layerColor( (layerNdx % 2) == 1 ? 1.0f : 0.5f,
613 ((layerNdx/2) % 2) == 1 ? 1.0f : 0.5f,
614 layerNdx == 0 ? 1.0f : 0.0f,
615 1.0f);
616 return verifyImageSingleColoredRow(log, image, 0.5f, layerColor);
617 }
618
619 case TEST_TYPE_LAYERED_READBACK:
620 {
621 const float barWidthRatios[] = { 0.25f, 0.5f, 1.0f };
622 const int barsCount = DE_LENGTH_OF_ARRAY(barWidthRatios);
623 bool result = false;
624
625 if (depthCheck)
626 {
627 const std::string checkType = "Depth";
628 const float pass0depth = static_cast<float>(layerNdx + 1) / static_cast<float>(2 * numLayers);
629 const float pass1depth = static_cast<float>(layerNdx + 0) / static_cast<float>(2 * numLayers);
630 const tcu::Vec4 barDepths[barsCount] = { tcu::Vec4(pass1depth), tcu::Vec4(pass0depth), tcu::Vec4(1.0f) };
631 tcu::TextureLevel depthAsColorBuffer (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), image.getWidth(), image.getHeight());
632 tcu::PixelBufferAccess depthAsColor (depthAsColorBuffer);
633 const int numUsedChannels (tcu::getNumUsedChannels(depthAsColor.getFormat().order));
634
635 convertDepthToColorBufferAccess(image, depthAsColor);
636
637 result = verifyImageMultipleBars(log, depthAsColor, barWidthRatios, barDepths, barsCount, numUsedChannels, checkType);
638 }
639 else if (stencilCheck)
640 {
641 const std::string checkType = "Stencil";
642 const int maxStencilValue = 4;
643 const float pass0stencil = static_cast<float>(1.0f / maxStencilValue);
644 const float pass1stencil = static_cast<float>(2.0f / maxStencilValue);
645 const tcu::Vec4 barStencils[barsCount] = { tcu::Vec4(pass1stencil), tcu::Vec4(pass0stencil), tcu::Vec4(0.0f) };
646 tcu::TextureLevel stencilAsColorBuffer (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), image.getWidth(), image.getHeight());
647 tcu::PixelBufferAccess stencilAsColor (stencilAsColorBuffer);
648 const int numUsedChannels (tcu::getNumUsedChannels(stencilAsColor.getFormat().order));
649
650 convertStencilToColorBufferAccess(image, stencilAsColor, maxStencilValue);
651
652 result = verifyImageMultipleBars(log, stencilAsColor, barWidthRatios, barStencils, barsCount, numUsedChannels, checkType);
653 }
654 else
655 {
656 const std::string checkType = "Color";
657 const tcu::Vec4 baseColor (s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
658 const tcu::Vec4 barColors[barsCount] = { scaleColor(baseColor, 1.00f), scaleColor(baseColor, 0.50f), scaleColor(baseColor, 0.25f) };
659 const int numUsedChannels (tcu::getNumUsedChannels(image.getFormat().order));
660
661 result = verifyImageMultipleBars(log, image, barWidthRatios, barColors, barsCount, numUsedChannels, checkType);
662 }
663
664 return result;
665 }
666
667 default:
668 DE_ASSERT(0);
669 return false;
670 };
671 }
672
getLayerDescription(const VkImageViewType viewType,const int layer)673 std::string getLayerDescription (const VkImageViewType viewType, const int layer)
674 {
675 std::ostringstream str;
676 const int numCubeFaces = 6;
677
678 if (isCubeImageViewType(viewType))
679 str << "cube " << (layer / numCubeFaces) << ", face " << (layer % numCubeFaces);
680 else if (viewType == VK_IMAGE_VIEW_TYPE_3D)
681 str << "slice z = " << layer;
682 else
683 str << "layer " << layer;
684
685 return str.str();
686 }
687
verifyResults(tcu::TestLog & log,const TestParams & params,const VkFormat imageFormat,const void * resultData,const bool depthCheck=false,const bool stencilCheck=false)688 bool verifyResults (tcu::TestLog& log, const TestParams& params, const VkFormat imageFormat, const void* resultData, const bool depthCheck = false, const bool stencilCheck = false)
689 {
690 const LayeredImageAccess image = LayeredImageAccess::create(getImageType(params.image.viewType), imageFormat, params.image.size, params.image.numLayers, resultData);
691
692 int numGoodLayers = 0;
693
694 for (int layerNdx = 0; layerNdx < image.getNumLayersOrSlices(); ++layerNdx)
695 {
696 const tcu::ConstPixelBufferAccess layerImage = image.getLayer(layerNdx);
697
698 log << tcu::TestLog::Message << "Verifying " << getLayerDescription(params.image.viewType, layerNdx) << tcu::TestLog::EndMessage;
699
700 if (verifyLayerContent(log, params.testType, layerImage, layerNdx, image.getNumLayersOrSlices(), depthCheck, stencilCheck))
701 ++numGoodLayers;
702 }
703
704 return numGoodLayers == image.getNumLayersOrSlices();
705 }
706
toGlsl(const Vec4 & v)707 std::string toGlsl (const Vec4& v)
708 {
709 std::ostringstream str;
710 str << "vec4(";
711 for (int i = 0; i < 4; ++i)
712 str << (i != 0 ? ", " : "") << de::floatToString(v[i], 1);
713 str << ")";
714 return str.str();
715 }
716
initPrograms(SourceCollections & programCollection,const TestParams params)717 void initPrograms (SourceCollections& programCollection, const TestParams params)
718 {
719 const bool geomOutputColor = (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_LAYERED_READBACK);
720
721 // Vertex shader
722 {
723 std::ostringstream src;
724 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
725 << "\n"
726 << "void main(void)\n"
727 << "{\n"
728 << "}\n";
729
730 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
731 }
732
733 // Geometry shader
734 {
735 const int numLayers = static_cast<int>(params.image.viewType == VK_IMAGE_VIEW_TYPE_3D ? params.image.size.depth : params.image.numLayers);
736
737 const int maxVertices = (params.testType == TEST_TYPE_DIFFERENT_CONTENT) ? (numLayers + 1) * numLayers :
738 (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_LAYER_ID || params.testType == TEST_TYPE_LAYERED_READBACK) ? numLayers * 4 :
739 (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION) ? 6 : 4;
740
741 std::ostringstream src;
742 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
743 << "\n";
744
745 if (params.testType == TEST_TYPE_LAYERED_READBACK)
746 src << "layout(binding = 0) readonly uniform Input {\n"
747 << " int pass;\n"
748 << "} uInput;\n\n";
749
750 if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
751 src << "layout(points, invocations = " << numLayers << ") in;\n";
752 else
753 src << "layout(points) in;\n";
754
755 src << "layout(triangle_strip, max_vertices = " << maxVertices << ") out;\n"
756 << "\n"
757 << (geomOutputColor ? "layout(location = 0) out vec4 vert_color;\n\n" : "")
758 << "out gl_PerVertex {\n"
759 << " vec4 gl_Position;\n"
760 << "};\n"
761 << "\n"
762 << "void main(void)\n"
763 << "{\n";
764
765 std::ostringstream colorTable;
766 {
767 const int numColors = DE_LENGTH_OF_ARRAY(s_colors);
768
769 colorTable << " const vec4 colors[" << numColors << "] = vec4[" << numColors << "](";
770
771 const std::string padding(colorTable.str().length(), ' ');
772
773 for (int i = 0; i < numColors; ++i)
774 colorTable << (i != 0 ? ",\n" + padding : "") << toGlsl(s_colors[i]);
775
776 colorTable << ");\n";
777 }
778
779 if (params.testType == TEST_TYPE_DEFAULT_LAYER)
780 {
781 src << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
782 << " EmitVertex();\n"
783 << "\n"
784 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
785 << " EmitVertex();\n"
786 << "\n"
787 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
788 << " EmitVertex();\n"
789 << "\n"
790 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
791 << " EmitVertex();\n";
792 }
793 else if (params.testType == TEST_TYPE_SINGLE_LAYER)
794 {
795 const deUint32 targetLayer = getTargetLayer(params.image);
796
797 src << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
798 << " gl_Layer = " << targetLayer << ";\n"
799 << " EmitVertex();\n"
800 << "\n"
801 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
802 << " gl_Layer = " << targetLayer << ";\n"
803 << " EmitVertex();\n"
804 << "\n"
805 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
806 << " gl_Layer = " << targetLayer << ";\n"
807 << " EmitVertex();\n"
808 << "\n"
809 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
810 << " gl_Layer = " << targetLayer << ";\n"
811 << " EmitVertex();\n";
812 }
813 else if (params.testType == TEST_TYPE_ALL_LAYERS)
814 {
815 src << colorTable.str()
816 << "\n"
817 << " for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
818 << " const int colorNdx = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
819 << "\n"
820 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
821 << " gl_Layer = layerNdx;\n"
822 << " vert_color = colors[colorNdx];\n"
823 << " EmitVertex();\n"
824 << "\n"
825 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
826 << " gl_Layer = layerNdx;\n"
827 << " vert_color = colors[colorNdx];\n"
828 << " EmitVertex();\n"
829 << "\n"
830 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
831 << " gl_Layer = layerNdx;\n"
832 << " vert_color = colors[colorNdx];\n"
833 << " EmitVertex();\n"
834 << "\n"
835 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
836 << " gl_Layer = layerNdx;\n"
837 << " vert_color = colors[colorNdx];\n"
838 << " EmitVertex();\n"
839 << " EndPrimitive();\n"
840 << " };\n";
841 }
842 else if (params.testType == TEST_TYPE_LAYER_ID)
843 {
844 src << " for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
845 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
846 << " gl_Layer = layerNdx;\n"
847 << " EmitVertex();\n"
848 << "\n"
849 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
850 << " gl_Layer = layerNdx;\n"
851 << " EmitVertex();\n"
852 << "\n"
853 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
854 << " gl_Layer = layerNdx;\n"
855 << " EmitVertex();\n"
856 << "\n"
857 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
858 << " gl_Layer = layerNdx;\n"
859 << " EmitVertex();\n"
860 << " EndPrimitive();\n"
861 << " };\n";
862 }
863 else if (params.testType == TEST_TYPE_DIFFERENT_CONTENT)
864 {
865 src << " for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
866 << " for (int colNdx = 0; colNdx <= layerNdx; ++colNdx) {\n"
867 << " const float posX = float(colNdx) / float(" << numLayers << ") * 2.0 - 1.0;\n"
868 << "\n"
869 << " gl_Position = vec4(posX, 1.0, 0.0, 1.0);\n"
870 << " gl_Layer = layerNdx;\n"
871 << " EmitVertex();\n"
872 << "\n"
873 << " gl_Position = vec4(posX, -1.0, 0.0, 1.0);\n"
874 << " gl_Layer = layerNdx;\n"
875 << " EmitVertex();\n"
876 << " }\n"
877 << " EndPrimitive();\n"
878 << " }\n";
879 }
880 else if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER)
881 {
882 src << colorTable.str()
883 << " const int colorNdx = gl_InvocationID % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
884 << "\n"
885 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
886 << " gl_Layer = gl_InvocationID;\n"
887 << " vert_color = colors[colorNdx];\n"
888 << " EmitVertex();\n"
889 << "\n"
890 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
891 << " gl_Layer = gl_InvocationID;\n"
892 << " vert_color = colors[colorNdx];\n"
893 << " EmitVertex();\n"
894 << "\n"
895 << " gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
896 << " gl_Layer = gl_InvocationID;\n"
897 << " vert_color = colors[colorNdx];\n"
898 << " EmitVertex();\n"
899 << "\n"
900 << " gl_Position = vec4( 0.0, 1.0, 0.0, 1.0);\n"
901 << " gl_Layer = gl_InvocationID;\n"
902 << " vert_color = colors[colorNdx];\n"
903 << " EmitVertex();\n"
904 << " EndPrimitive();\n";
905 }
906 else if (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
907 {
908 src << " const int layerA = gl_InvocationID;\n"
909 << " const int layerB = (gl_InvocationID + 1) % " << numLayers << ";\n"
910 << " const float aEnd = float(layerA) / float(" << numLayers << ") * 2.0 - 1.0;\n"
911 << " const float bEnd = float(layerB) / float(" << numLayers << ") * 2.0 - 1.0;\n"
912 << "\n"
913 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
914 << " gl_Layer = layerA;\n"
915 << " EmitVertex();\n"
916 << "\n"
917 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
918 << " gl_Layer = layerA;\n"
919 << " EmitVertex();\n"
920 << "\n"
921 << " gl_Position = vec4(aEnd, -1.0, 0.0, 1.0);\n"
922 << " gl_Layer = layerA;\n"
923 << " EmitVertex();\n"
924 << " EndPrimitive();\n"
925 << "\n"
926 << " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
927 << " gl_Layer = layerB;\n"
928 << " EmitVertex();\n"
929 << "\n"
930 << " gl_Position = vec4(bEnd, 1.0, 0.0, 1.0);\n"
931 << " gl_Layer = layerB;\n"
932 << " EmitVertex();\n"
933 << "\n"
934 << " gl_Position = vec4(bEnd, -1.0, 0.0, 1.0);\n"
935 << " gl_Layer = layerB;\n"
936 << " EmitVertex();\n"
937 << " EndPrimitive();\n";
938 }
939 else if (params.testType == TEST_TYPE_LAYERED_READBACK)
940 {
941 src << colorTable.str()
942 << " for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
943 << " const int colorNdx = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
944 << " const vec3 passColor0 = (uInput.pass == 0 ? 0.5 : 1.0) * vec3(colors[colorNdx]);\n"
945 << " const vec4 passColor = vec4(passColor0, 1.0);\n"
946 << " const float posX = (uInput.pass == 0 ? 0.0 : -0.5);\n"
947 << " const float posZ = float(layerNdx + 1 - uInput.pass) / float(" << 2*numLayers << ");\n"
948 << "\n"
949 << " gl_Position = vec4(-1.0, -1.0, posZ, 1.0);\n"
950 << " gl_Layer = layerNdx;\n"
951 << " vert_color = passColor;\n"
952 << " EmitVertex();\n"
953 << "\n"
954 << " gl_Position = vec4(-1.0, 1.0, posZ, 1.0);\n"
955 << " gl_Layer = layerNdx;\n"
956 << " vert_color = passColor;\n"
957 << " EmitVertex();\n"
958 << "\n"
959 << " gl_Position = vec4(posX, -1.0, posZ, 1.0);\n"
960 << " gl_Layer = layerNdx;\n"
961 << " vert_color = passColor;\n"
962 << " EmitVertex();\n"
963 << "\n"
964 << " gl_Position = vec4(posX, 1.0, posZ, 1.0);\n"
965 << " gl_Layer = layerNdx;\n"
966 << " vert_color = passColor;\n"
967 << " EmitVertex();\n"
968 << "\n"
969 << " EndPrimitive();\n"
970 << " }\n";
971 }
972 else
973 DE_ASSERT(0);
974
975 src << "}\n"; // end main
976
977 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
978 }
979
980 // Fragment shader
981 {
982 std::ostringstream src;
983 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
984 << "\n"
985 << "layout(location = 0) out vec4 o_color;\n"
986 << (geomOutputColor ? "layout(location = 0) in vec4 vert_color;\n" : "")
987 << "\n"
988 << "void main(void)\n"
989 << "{\n";
990
991 if (params.testType == TEST_TYPE_LAYER_ID)
992 {
993 // This code must be in sync with verifyLayerContent()
994 src << " o_color = vec4( (gl_Layer % 2) == 1 ? 1.0 : 0.5,\n"
995 << " ((gl_Layer/2) % 2) == 1 ? 1.0 : 0.5,\n"
996 << " gl_Layer == 0 ? 1.0 : 0.0,\n"
997 << " 1.0);\n";
998 }
999 else if (geomOutputColor)
1000 src << " o_color = vert_color;\n";
1001 else
1002 src << " o_color = vec4(1.0);\n";
1003
1004 src << "}\n";
1005
1006 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1007 }
1008 }
1009
test(Context & context,const TestParams params)1010 tcu::TestStatus test (Context& context, const TestParams params)
1011 {
1012 if (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType &&
1013 (!isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_maintenance1")))
1014 TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
1015
1016 const DeviceInterface& vk = context.getDeviceInterface();
1017 const InstanceInterface& vki = context.getInstanceInterface();
1018 const VkDevice device = context.getDevice();
1019 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1020 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1021 const VkQueue queue = context.getUniversalQueue();
1022 Allocator& allocator = context.getDefaultAllocator();
1023
1024 checkGeometryShaderSupport(vki, physDevice);
1025
1026 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1027 const deUint32 numLayers = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1028 const Vec4 clearColor = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1029 const VkDeviceSize colorBufferSize = params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * tcu::getPixelSize(mapVkFormat(colorFormat));
1030 const VkImageCreateFlags imageCreateFlags = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1031 (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
1032 const VkImageViewType viewType = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1033
1034 const Unique<VkImage> colorImage (makeImage (vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
1035 params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1036 const UniquePtr<Allocation> colorImageAlloc (bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any));
1037 const Unique<VkImageView> colorAttachment (makeImageView (vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1038
1039 const Unique<VkBuffer> colorBuffer (makeBuffer (vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
1040 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1041
1042 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
1043 const Unique<VkShaderModule> geometryModule (createShaderModule (vk, device, context.getBinaryCollection().get("geom"), 0u));
1044 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
1045
1046 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, colorFormat));
1047 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, &*colorAttachment, 1u, params.image.size.width, params.image.size.height, numLayers));
1048 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device));
1049 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
1050 makeExtent2D(params.image.size.width, params.image.size.height)));
1051 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1052 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1053
1054 zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1055
1056 beginCommandBuffer(vk, *cmdBuffer);
1057
1058 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, params.image.size.width, params.image.size.height), clearColor);
1059
1060 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1061 vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1062 endRenderPass(vk, *cmdBuffer);
1063
1064 // Prepare color image for copy
1065 {
1066 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers);
1067 const VkImageMemoryBarrier barriers[] =
1068 {
1069 {
1070 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1071 DE_NULL, // const void* pNext;
1072 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask;
1073 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask;
1074 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1075 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1076 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1077 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1078 *colorImage, // VkImage image;
1079 colorSubresourceRange, // VkImageSubresourceRange subresourceRange;
1080 },
1081 };
1082
1083 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1084 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1085 }
1086 // Color image -> host buffer
1087 {
1088 const VkBufferImageCopy region =
1089 {
1090 0ull, // VkDeviceSize bufferOffset;
1091 0u, // uint32_t bufferRowLength;
1092 0u, // uint32_t bufferImageHeight;
1093 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, params.image.numLayers), // VkImageSubresourceLayers imageSubresource;
1094 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1095 params.image.size, // VkExtent3D imageExtent;
1096 };
1097
1098 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
1099 }
1100 // Buffer write barrier
1101 {
1102 const VkBufferMemoryBarrier barriers[] =
1103 {
1104 {
1105 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1106 DE_NULL, // const void* pNext;
1107 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1108 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1109 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1110 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1111 *colorBuffer, // VkBuffer buffer;
1112 0ull, // VkDeviceSize offset;
1113 VK_WHOLE_SIZE, // VkDeviceSize size;
1114 },
1115 };
1116
1117 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1118 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u);
1119 }
1120
1121 endCommandBuffer(vk, *cmdBuffer);
1122 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1123
1124 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSize);
1125
1126 if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1127 return tcu::TestStatus::fail("Rendered images are incorrect");
1128 else
1129 return tcu::TestStatus::pass("OK");
1130 }
1131
testLayeredReadBack(Context & context,const TestParams params)1132 tcu::TestStatus testLayeredReadBack (Context& context, const TestParams params)
1133 {
1134 if (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType &&
1135 (!isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_maintenance1")))
1136 TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
1137
1138 const DeviceInterface& vk = context.getDeviceInterface();
1139 const InstanceInterface& vki = context.getInstanceInterface();
1140 const VkDevice device = context.getDevice();
1141 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1142 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1143 const VkQueue queue = context.getUniversalQueue();
1144 Allocator& allocator = context.getDefaultAllocator();
1145
1146 checkGeometryShaderSupport(vki, physDevice);
1147
1148 const size_t passCount = 2;
1149 const deUint32 numLayers = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1150 const VkImageCreateFlags imageCreateFlags = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1151 (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
1152 const VkImageViewType viewType = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1153 const VkImageType imageType = getImageType(params.image.viewType);
1154 const VkExtent2D imageExtent2D = makeExtent2D(params.image.size.width, params.image.size.height);
1155
1156 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1157 const deUint32 colorImagePixelSize = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
1158 const VkDeviceSize colorBufferSize = params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * colorImagePixelSize;
1159 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1160
1161 const bool dsUsed = (VK_IMAGE_VIEW_TYPE_3D != params.image.viewType);
1162 const VkFormat dsFormat = VK_FORMAT_D24_UNORM_S8_UINT;
1163 const deUint32 dsImagePixelSize = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(dsFormat)));
1164 const VkImageUsageFlags dsImageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1165 const VkImageAspectFlags dsAspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
1166 const VkDeviceSize depthBufferSize = params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * dsImagePixelSize;
1167
1168 const VkFormat stencilBufferFormat = getStencilBufferFormat(dsFormat);
1169 const deUint32 stencilPixelSize = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(stencilBufferFormat)));
1170 const VkDeviceSize stencilBufferSize = params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * stencilPixelSize;
1171
1172 checkImageFormatProperties(vki, physDevice, imageType, VK_IMAGE_TILING_OPTIMAL, dsImageUsage, imageCreateFlags, dsFormat, params.image.size, params.image.numLayers);
1173
1174 const Unique<VkImage> colorImage (makeImage (vk, device, makeImageCreateInfo(imageCreateFlags, imageType, colorFormat, params.image.size, params.image.numLayers, colorImageUsage)));
1175 const UniquePtr<Allocation> colorImageAlloc (bindImage (vk, device, allocator, *colorImage, MemoryRequirement::Any));
1176 const Unique<VkImageView> colorAttachment (makeImageView (vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1177 const Unique<VkBuffer> colorBuffer (makeBuffer (vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
1178 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1179
1180 const Unique<VkImage> dsImage (makeImage (vk, device, makeImageCreateInfo(imageCreateFlags, imageType, dsFormat, params.image.size, params.image.numLayers, dsImageUsage)));
1181 const UniquePtr<Allocation> dsImageAlloc (bindImage (vk, device, allocator, *dsImage, MemoryRequirement::Any));
1182 const Unique<VkImageView> dsAttachment (makeImageView (vk, device, *dsImage, viewType, dsFormat, makeImageSubresourceRange(dsAspectFlags, 0u, 1u, 0u, numLayers)));
1183 const Unique<VkBuffer> depthBuffer (makeBuffer (vk, device, makeBufferCreateInfo(depthBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
1184 const UniquePtr<Allocation> depthBufferAlloc (bindBuffer (vk, device, allocator, *depthBuffer, MemoryRequirement::HostVisible));
1185 const Unique<VkBuffer> stencilBuffer (makeBuffer (vk, device, makeBufferCreateInfo(stencilBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
1186 const UniquePtr<Allocation> stencilBufferAlloc (bindBuffer (vk, device, allocator, *stencilBuffer, MemoryRequirement::HostVisible));
1187
1188 const VkImageView attachments[] = {*colorAttachment, *dsAttachment};
1189 const deUint32 attachmentsCount = dsUsed ? DE_LENGTH_OF_ARRAY(attachments) : 1u;
1190
1191 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
1192 const Unique<VkShaderModule> geometryModule (createShaderModule (vk, device, context.getBinaryCollection().get("geom"), 0u));
1193 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
1194
1195 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, colorFormat, dsFormat, dsUsed));
1196 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, attachments, attachmentsCount, params.image.size.width, params.image.size.height, numLayers));
1197
1198 const Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder()
1199 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, passCount)
1200 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, passCount);
1201 const Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder()
1202 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_GEOMETRY_BIT)
1203 .build(vk, device);
1204 const Move<VkDescriptorSet> descriptorSet[] =
1205 {
1206 makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout),
1207 makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout),
1208 };
1209
1210 const size_t uniformBufSize = sizeof(deUint32);
1211 const VkBufferCreateInfo uniformBufCI = makeBufferCreateInfo(uniformBufSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1212 const Move<VkBuffer> uniformBuf[] = { createBuffer(vk, device, &uniformBufCI), createBuffer(vk, device, &uniformBufCI) };
1213 const MovePtr<Allocation> uniformBufAlloc[] =
1214 {
1215 allocator.allocate(getBufferMemoryRequirements(vk, device, *uniformBuf[0]), MemoryRequirement::HostVisible),
1216 allocator.allocate(getBufferMemoryRequirements(vk, device, *uniformBuf[1]), MemoryRequirement::HostVisible),
1217 };
1218 const VkDescriptorBufferInfo uniformBufDesc[] =
1219 {
1220 makeDescriptorBufferInfo(*uniformBuf[0], 0ull, uniformBufSize),
1221 makeDescriptorBufferInfo(*uniformBuf[1], 0ull, uniformBufSize),
1222 };
1223
1224 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device, *descriptorSetLayout));
1225 const Unique<VkPipeline> pipeline (makeGraphicsPipeline (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule, imageExtent2D, dsUsed));
1226 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1227 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1228 const VkImageSubresourceRange colorSubresRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers);
1229 const VkImageSubresourceRange dsSubresRange = makeImageSubresourceRange(dsAspectFlags, 0u, 1u, 0u, params.image.numLayers);
1230 const VkImageMemoryBarrier colorPassBarrier = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1231 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresRange);
1232 const VkImageMemoryBarrier dsPassBarrier = makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1233 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *dsImage, dsSubresRange);
1234 std::string result;
1235
1236 beginCommandBuffer(vk, *cmdBuffer);
1237 {
1238 const VkImageMemoryBarrier colorBarrier = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1239 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *colorImage, colorSubresRange);
1240 const VkImageMemoryBarrier dsBarrier = makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1241 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *dsImage, dsSubresRange);
1242
1243 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorBarrier);
1244
1245 if (dsUsed)
1246 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsBarrier);
1247
1248 for (deUint32 layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1249 {
1250 const deUint32 imageDepth = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? layerNdx : 0u;
1251 const deUint32 layer = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? 0u : layerNdx;
1252 const VkOffset3D imageOffset = makeOffset3D(0u, 0u, imageDepth);
1253 const VkExtent3D imageExtent = makeExtent3D(params.image.size.width, params.image.size.height, 1u);
1254
1255 // Clear color image with initial value
1256 {
1257 const tcu::Vec4 clearColor = scaleColor(s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)], 0.25f);
1258 const deUint32 bufferSliceSize = params.image.size.width * params.image.size.height * colorImagePixelSize;
1259 const VkDeviceSize bufferOffset = layerNdx * bufferSliceSize;
1260 const VkImageSubresourceLayers imageSubresource = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, layer, 1u);
1261 const VkBufferImageCopy bufferImageCopyRegion = makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
1262
1263 fillBuffer(vk, device, *colorBufferAlloc, bufferOffset, bufferSliceSize, colorFormat, clearColor);
1264 vk.cmdCopyBufferToImage(*cmdBuffer, *colorBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1265 }
1266
1267 // Clear depth image with initial value
1268 if (dsUsed)
1269 {
1270 const float depthValue = 1.0f;
1271 const deUint32 bufferSliceSize = params.image.size.width * params.image.size.height * dsImagePixelSize;
1272 const VkDeviceSize bufferOffset = layerNdx * bufferSliceSize;
1273 const VkImageSubresourceLayers imageSubresource = makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, layer, 1u);
1274 const VkBufferImageCopy bufferImageCopyRegion = makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
1275
1276 fillBuffer(vk, device, *depthBufferAlloc, bufferOffset, bufferSliceSize, dsFormat, depthValue);
1277 vk.cmdCopyBufferToImage(*cmdBuffer, *depthBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1278 }
1279
1280 // Clear stencil image with initial value
1281 if (dsUsed)
1282 {
1283 const deUint8 stencilValue = 0;
1284 const deUint32 bufferSliceSize = params.image.size.width * params.image.size.height * stencilPixelSize;
1285 const VkDeviceSize bufferOffset = layerNdx * bufferSliceSize;
1286 const VkImageSubresourceLayers imageSubresource = makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, layer, 1u);
1287 const VkBufferImageCopy bufferImageCopyRegion = makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
1288 deUint8* bufferStart = static_cast<deUint8*>((*stencilBufferAlloc).getHostPtr());
1289 deUint8* bufferLayerStart = &bufferStart[bufferOffset];
1290
1291 deMemset(bufferLayerStart, stencilValue, bufferSliceSize);
1292 flushMappedMemoryRange(vk, device, stencilBufferAlloc->getMemory(), stencilBufferAlloc->getOffset() + bufferOffset, bufferSliceSize);
1293 vk.cmdCopyBufferToImage(*cmdBuffer, *stencilBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1294 }
1295 }
1296 }
1297 // Change images layouts
1298 {
1299 const VkImageMemoryBarrier colorBarrier = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1300 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresRange);
1301 const VkImageMemoryBarrier dsBarrier = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1302 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *dsImage, dsSubresRange);
1303
1304 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorBarrier);
1305
1306 if (dsUsed)
1307 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsBarrier);
1308 }
1309
1310 for (deUint32 pass = 0; pass < passCount; ++pass)
1311 {
1312 DE_ASSERT(sizeof(pass) == uniformBufSize);
1313
1314 VK_CHECK(vk.bindBufferMemory(device, *uniformBuf[pass], uniformBufAlloc[pass]->getMemory(), uniformBufAlloc[pass]->getOffset()));
1315 deMemcpy(uniformBufAlloc[pass]->getHostPtr(), &pass, uniformBufSize);
1316 flushMappedMemoryRange(vk, device, uniformBufAlloc[pass]->getMemory(), uniformBufAlloc[pass]->getOffset(), uniformBufSize);
1317
1318 DescriptorSetUpdateBuilder()
1319 .writeSingle(*descriptorSet[pass], DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufDesc[pass])
1320 .update(vk, device);
1321
1322 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet[pass], 0u, DE_NULL);
1323 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(imageExtent2D));
1324 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1325 vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1326 endRenderPass(vk, *cmdBuffer);
1327
1328 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorPassBarrier);
1329
1330 if (dsUsed)
1331 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsPassBarrier);
1332 }
1333 endCommandBuffer(vk, *cmdBuffer);
1334 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1335
1336 zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1337 zeroBuffer(vk, device, *depthBufferAlloc, depthBufferSize);
1338 zeroBuffer(vk, device, *stencilBufferAlloc, stencilBufferSize);
1339
1340 beginCommandBuffer(vk, *cmdBuffer);
1341 {
1342 // Copy color image
1343 {
1344 const VkImageMemoryBarrier preCopyBarrier = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1345 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorImage, colorSubresRange);
1346 const VkBufferImageCopy region = makeBufferImageCopy(params.image.size, makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, params.image.numLayers));
1347 const VkBufferMemoryBarrier postCopyBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
1348
1349 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1350 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
1351 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
1352 }
1353
1354 // Depth/Stencil image copy
1355 if (dsUsed)
1356 {
1357 const VkImageMemoryBarrier preCopyBarrier = makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1358 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dsImage, dsSubresRange);
1359 const VkBufferImageCopy depthCopyRegion = makeBufferImageCopy(params.image.size, makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, params.image.numLayers));
1360 const VkBufferImageCopy stencilCopyRegion = makeBufferImageCopy(params.image.size, makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, params.image.numLayers));
1361 const VkBufferMemoryBarrier postCopyBarriers[] =
1362 {
1363 makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *depthBuffer, 0ull, VK_WHOLE_SIZE),
1364 makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *stencilBuffer, 0ull, VK_WHOLE_SIZE),
1365 };
1366
1367 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1368 vk.cmdCopyImageToBuffer(*cmdBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *depthBuffer, 1u, &depthCopyRegion);
1369 vk.cmdCopyImageToBuffer(*cmdBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *stencilBuffer, 1u, &stencilCopyRegion);
1370 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(postCopyBarriers), postCopyBarriers, DE_NULL, 0u);
1371 }
1372 }
1373 endCommandBuffer(vk, *cmdBuffer);
1374 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1375
1376 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSize);
1377 invalidateMappedMemoryRange(vk, device, depthBufferAlloc->getMemory(), depthBufferAlloc->getOffset(), depthBufferSize);
1378 invalidateMappedMemoryRange(vk, device, stencilBufferAlloc->getMemory(), stencilBufferAlloc->getOffset(), stencilBufferSize);
1379
1380 if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1381 result += " Color";
1382
1383 if (dsUsed)
1384 {
1385 if (!verifyResults(context.getTestContext().getLog(), params, dsFormat, depthBufferAlloc->getHostPtr(), true, false))
1386 result += " Depth";
1387
1388 if (!verifyResults(context.getTestContext().getLog(), params, stencilBufferFormat, stencilBufferAlloc->getHostPtr(), false, true))
1389 result += " Stencil";
1390 }
1391
1392 if (result.empty())
1393 return tcu::TestStatus::pass("OK");
1394 else
1395 return tcu::TestStatus::fail("Following parts of image are incorrect:" + result);
1396 }
1397
1398 } // anonymous
1399
createLayeredRenderingTests(tcu::TestContext & testCtx)1400 tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx)
1401 {
1402 MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "layered", "Layered rendering tests."));
1403
1404 const struct
1405 {
1406 TestType test;
1407 const char* name;
1408 const char* description;
1409 } testTypes[] =
1410 {
1411 { TEST_TYPE_DEFAULT_LAYER, "render_to_default_layer", "Render to the default layer" },
1412 { TEST_TYPE_SINGLE_LAYER, "render_to_one", "Render to one layer" },
1413 { TEST_TYPE_ALL_LAYERS, "render_to_all", "Render to all layers" },
1414 { TEST_TYPE_DIFFERENT_CONTENT, "render_different_content", "Render different data to different layers" },
1415 { TEST_TYPE_LAYER_ID, "fragment_layer", "Read gl_Layer in fragment shader" },
1416 { TEST_TYPE_INVOCATION_PER_LAYER, "invocation_per_layer", "Render to multiple layers with multiple invocations, one invocation per layer" },
1417 { TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION, "multiple_layers_per_invocation", "Render to multiple layers with multiple invocations, multiple layers per invocation", },
1418 { TEST_TYPE_LAYERED_READBACK, "readback", "Render to multiple layers with two passes to check LOAD_OP_LOAD capability" },
1419 };
1420
1421 const ImageParams imageParams[] =
1422 {
1423 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, { 64, 1, 1 }, 4 },
1424 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, { 64, 64, 1 }, 4 },
1425 { VK_IMAGE_VIEW_TYPE_CUBE, { 64, 64, 1 }, 6 },
1426 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, { 64, 64, 1 }, 2*6 },
1427 { VK_IMAGE_VIEW_TYPE_3D, { 64, 64, 8 }, 1 }
1428 };
1429
1430 for (int imageParamNdx = 0; imageParamNdx < DE_LENGTH_OF_ARRAY(imageParams); ++imageParamNdx)
1431 {
1432 MovePtr<tcu::TestCaseGroup> viewTypeGroup(new tcu::TestCaseGroup(testCtx, getShortImageViewTypeName(imageParams[imageParamNdx].viewType).c_str(), ""));
1433
1434 for (int testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx)
1435 {
1436 const TestParams params =
1437 {
1438 testTypes[testTypeNdx].test,
1439 imageParams[imageParamNdx],
1440 };
1441
1442 if (testTypes[testTypeNdx].test == TEST_TYPE_LAYERED_READBACK)
1443 addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, initPrograms, testLayeredReadBack, params);
1444 else
1445 addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, initPrograms, test, params);
1446 }
1447
1448 group->addChild(viewTypeGroup.release());
1449 }
1450
1451 return group.release();
1452 }
1453
1454 } // geometry
1455 } // vkt
1456