1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2018 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief VK_KHR_depth_stencil_resolve tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktRenderPassDepthStencilResolveTests.hpp"
25 #include "vktRenderPassTestsUtil.hpp"
26 
27 #include "vktTestCaseUtil.hpp"
28 #include "vktTestGroupUtil.hpp"
29 
30 #include "vkDefs.hpp"
31 #include "vkDeviceUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkPlatform.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkQueryUtil.hpp"
37 #include "vkRef.hpp"
38 #include "vkRefUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42 
43 #include "tcuImageCompare.hpp"
44 #include "tcuFormatUtil.hpp"
45 #include "tcuResultCollector.hpp"
46 #include "tcuTestLog.hpp"
47 #include "tcuTextureUtil.hpp"
48 
49 #include "deUniquePtr.hpp"
50 #include "deSharedPtr.hpp"
51 #include "deMath.h"
52 
53 #include <limits>
54 #include <map>
55 
56 using namespace vk;
57 
58 using tcu::TestLog;
59 using tcu::Vec4;
60 
61 typedef de::SharedPtr<vk::Unique<VkImage>> VkImageSp;
62 typedef de::SharedPtr<vk::Unique<VkImageView>> VkImageViewSp;
63 typedef de::SharedPtr<vk::Unique<VkBuffer>> VkBufferSp;
64 typedef de::SharedPtr<vk::Unique<VkPipeline>> VkPipelineSp;
65 typedef de::SharedPtr<Allocation> AllocationSp;
66 
67 namespace vkt
68 {
69 namespace
70 {
71 
72 using namespace renderpass;
73 
74 template <typename T>
safeSharedPtr(T * ptr)75 de::SharedPtr<T> safeSharedPtr(T *ptr)
76 {
77     try
78     {
79         return de::SharedPtr<T>(ptr);
80     }
81     catch (...)
82     {
83         delete ptr;
84         throw;
85     }
86 }
87 
aspectFlagsForFormat(VkFormat vkformat)88 VkImageAspectFlags aspectFlagsForFormat(VkFormat vkformat)
89 {
90     const tcu::TextureFormat format(mapVkFormat(vkformat));
91     VkImageAspectFlags aspectFlags =
92         ((tcu::hasDepthComponent(format.order) ? static_cast<vk::VkImageAspectFlags>(vk::VK_IMAGE_ASPECT_DEPTH_BIT) :
93                                                  0u) |
94          (tcu::hasStencilComponent(format.order) ?
95               static_cast<vk::VkImageAspectFlags>(vk::VK_IMAGE_ASPECT_STENCIL_BIT) :
96               0u));
97     return aspectFlags;
98 }
99 
100 enum VerifyBuffer
101 {
102     VB_DEPTH = 0,
103     VB_STENCIL
104 };
105 
106 struct TestConfig
107 {
108     VkFormat format;
109     uint32_t width;
110     uint32_t height;
111     uint32_t imageLayers;
112     uint32_t viewLayers;
113     uint32_t resolveBaseLayer;
114     VkRect2D renderArea;
115     VkImageAspectFlags aspectFlag;
116     uint32_t sampleCount;
117     VkResolveModeFlagBits depthResolveMode;
118     VkResolveModeFlagBits stencilResolveMode;
119     VerifyBuffer verifyBuffer;
120     VkClearDepthStencilValue clearValue;
121     float depthExpectedValue;
122     uint8_t stencilExpectedValue;
123     bool separateDepthStencilLayouts;
124     bool unusedResolve;
125     tcu::Maybe<VkFormat> compatibleFormat;
126     bool sampleMask;
127 
resolveFormatvkt::__anonbd6d96410111::TestConfig128     VkFormat resolveFormat() const
129     {
130         return compatibleFormat ? compatibleFormat.get() : format;
131     }
132 
resolveAspectFlagsvkt::__anonbd6d96410111::TestConfig133     VkImageAspectFlags resolveAspectFlags() const
134     {
135         return aspectFlagsForFormat(resolveFormat());
136     }
137 };
138 
139 // Auxiliar class to group depth formats by compatibility in bit size and format. Note there is at most one alternative format for
140 // each given format as of the time this comment is being written, and the alternative (compatible) format for a given format can
141 // only remove aspects but not add them. That is, we cannot use a depth/stencil attachment to resolve a depth-only attachment.
142 //
143 // See:
144 //    * VUID-VkSubpassDescriptionDepthStencilResolve-pDepthStencilResolveAttachment-03181
145 //    * VUID-VkSubpassDescriptionDepthStencilResolve-pDepthStencilResolveAttachment-03182
146 class DepthCompatibilityManager
147 {
148 public:
DepthCompatibilityManager()149     DepthCompatibilityManager() : m_compatibleFormats()
150     {
151         m_compatibleFormats[VK_FORMAT_D32_SFLOAT_S8_UINT] = VK_FORMAT_D32_SFLOAT;
152         m_compatibleFormats[VK_FORMAT_D16_UNORM_S8_UINT]  = VK_FORMAT_D16_UNORM;
153         m_compatibleFormats[VK_FORMAT_D24_UNORM_S8_UINT]  = VK_FORMAT_X8_D24_UNORM_PACK32;
154     }
155 
getAlternativeFormat(VkFormat format) const156     VkFormat getAlternativeFormat(VkFormat format) const
157     {
158         const auto itr = m_compatibleFormats.find(format);
159         if (itr != end(m_compatibleFormats))
160             return itr->second;
161         return VK_FORMAT_UNDEFINED;
162     }
163 
164 private:
165     std::map<VkFormat, VkFormat> m_compatibleFormats;
166 };
167 
get16bitDepthComponent(uint8_t * pixelPtr)168 float get16bitDepthComponent(uint8_t *pixelPtr)
169 {
170     uint16_t *value = reinterpret_cast<uint16_t *>(pixelPtr);
171     return static_cast<float>(*value) / 65535.0f;
172 }
173 
get24bitDepthComponent(uint8_t * pixelPtr)174 float get24bitDepthComponent(uint8_t *pixelPtr)
175 {
176     const bool littleEndian = (DE_ENDIANNESS == DE_LITTLE_ENDIAN);
177     uint32_t value          = (((uint32_t)pixelPtr[0]) << (!littleEndian * 16u)) | (((uint32_t)pixelPtr[1]) << 8u) |
178                      (((uint32_t)pixelPtr[2]) << (littleEndian * 16u));
179     return static_cast<float>(value) / 16777215.0f;
180 }
181 
get32bitDepthComponent(uint8_t * pixelPtr)182 float get32bitDepthComponent(uint8_t *pixelPtr)
183 {
184     return *(reinterpret_cast<float *>(pixelPtr));
185 }
186 
187 class DepthStencilResolveTest : public TestInstance
188 {
189 public:
190     DepthStencilResolveTest(Context &context, TestConfig config);
191     virtual ~DepthStencilResolveTest(void);
192 
193     virtual tcu::TestStatus iterate(void);
194 
195 protected:
196     bool isFeaturesSupported(void);
197     bool isSupportedFormat(Context &context, VkFormat format) const;
198     VkSampleCountFlagBits sampleCountBitFromSampleCount(uint32_t count) const;
199 
200     VkImageSp createImage(VkFormat vkformat, uint32_t sampleCount, VkImageUsageFlags additionalUsage = 0u);
201     AllocationSp createImageMemory(VkImageSp image);
202     VkImageViewSp createImageView(VkImageSp image, VkFormat vkformat, uint32_t baseArrayLayer);
203     AllocationSp createBufferMemory(void);
204     VkBufferSp createBuffer(void);
205 
206     Move<VkRenderPass> createRenderPass(VkFormat vkformat, uint32_t renderPassNo);
207     Move<VkRenderPass> createRenderPassCompatible(void);
208     Move<VkFramebuffer> createFramebuffer(VkRenderPass renderPass, VkImageViewSp multisampleImageView,
209                                           VkImageViewSp singlesampleImageView);
210     Move<VkPipelineLayout> createRenderPipelineLayout(void);
211     Move<VkPipeline> createRenderPipeline(VkRenderPass renderPass, uint32_t renderPassNo,
212                                           VkPipelineLayout renderPipelineLayout);
213 
214     void submit(void);
215     bool verifyDepth(void);
216     bool verifyStencil(void);
217 
218 protected:
219     const TestConfig m_config;
220     const bool m_featureSupported;
221 
222     const InstanceInterface &m_vki;
223     const DeviceInterface &m_vkd;
224     VkDevice m_device;
225     VkPhysicalDevice m_physicalDevice;
226 
227     const Unique<VkCommandPool> m_commandPool;
228 
229     VkImageSp m_multisampleImage;
230     AllocationSp m_multisampleImageMemory;
231     VkImageViewSp m_multisampleImageView;
232     VkImageSp m_singlesampleImage;
233     AllocationSp m_singlesampleImageMemory;
234     VkImageViewSp m_singlesampleImageView;
235     VkBufferSp m_buffer;
236     AllocationSp m_bufferMemory;
237 
238     uint32_t m_numRenderPasses;
239     std::vector<Move<VkRenderPass>> m_renderPass;
240     Unique<VkRenderPass> m_renderPassCompatible;
241     Move<VkFramebuffer> m_framebuffer;
242     Unique<VkPipelineLayout> m_renderPipelineLayout;
243     std::vector<Move<VkPipeline>> m_renderPipeline;
244 };
245 
DepthStencilResolveTest(Context & context,TestConfig config)246 DepthStencilResolveTest::DepthStencilResolveTest(Context &context, TestConfig config)
247     : TestInstance(context)
248     , m_config(config)
249     , m_featureSupported(isFeaturesSupported())
250     , m_vki(context.getInstanceInterface())
251     , m_vkd(context.getDeviceInterface())
252     , m_device(context.getDevice())
253     , m_physicalDevice(context.getPhysicalDevice())
254 
255     , m_commandPool(createCommandPool(context.getDeviceInterface(), context.getDevice(),
256                                       VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
257 
258     , m_multisampleImage(createImage(m_config.format, m_config.sampleCount, VK_IMAGE_USAGE_TRANSFER_SRC_BIT))
259     , m_multisampleImageMemory(createImageMemory(m_multisampleImage))
260     , m_multisampleImageView(createImageView(m_multisampleImage, m_config.format, 0u))
261 
262     , m_singlesampleImage(createImage(
263           m_config.resolveFormat(), 1,
264           (VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
265            (config.unusedResolve ? static_cast<vk::VkImageUsageFlags>(VK_IMAGE_USAGE_TRANSFER_DST_BIT) : 0u))))
266     , m_singlesampleImageMemory(createImageMemory(m_singlesampleImage))
267     , m_singlesampleImageView(createImageView(m_singlesampleImage, m_config.resolveFormat(), m_config.resolveBaseLayer))
268 
269     , m_buffer(createBuffer())
270     , m_bufferMemory(createBufferMemory())
271 
272     , m_numRenderPasses((m_config.verifyBuffer == VB_DEPTH || !m_config.sampleMask) ? 1u : m_config.sampleCount)
273     , m_renderPassCompatible(createRenderPassCompatible())
274     , m_renderPipelineLayout(createRenderPipelineLayout())
275 {
276     for (uint32_t i = 0; i < m_numRenderPasses; i++)
277     {
278         m_renderPass.push_back(createRenderPass(m_config.format, i));
279         m_renderPipeline.push_back(createRenderPipeline(*m_renderPass[i], i, *m_renderPipelineLayout));
280     }
281     m_framebuffer = createFramebuffer(m_config.compatibleFormat ? *m_renderPassCompatible : *m_renderPass[0],
282                                       m_multisampleImageView, m_singlesampleImageView);
283 }
284 
~DepthStencilResolveTest(void)285 DepthStencilResolveTest::~DepthStencilResolveTest(void)
286 {
287 }
288 
isFeaturesSupported()289 bool DepthStencilResolveTest::isFeaturesSupported()
290 {
291     m_context.requireDeviceFunctionality("VK_KHR_depth_stencil_resolve");
292     if (m_config.imageLayers > 1)
293         m_context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
294 
295     if (m_config.separateDepthStencilLayouts)
296         m_context.requireDeviceFunctionality("VK_KHR_separate_depth_stencil_layouts");
297 
298     VkPhysicalDeviceDepthStencilResolveProperties dsResolveProperties;
299     deMemset(&dsResolveProperties, 0, sizeof(VkPhysicalDeviceDepthStencilResolveProperties));
300     dsResolveProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES;
301     dsResolveProperties.pNext = DE_NULL;
302 
303     VkPhysicalDeviceProperties2 deviceProperties;
304     deviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
305     deviceProperties.pNext = &dsResolveProperties;
306 
307     // perform query to get supported float control properties
308     const VkPhysicalDevice physicalDevice          = m_context.getPhysicalDevice();
309     const vk::InstanceInterface &instanceInterface = m_context.getInstanceInterface();
310     instanceInterface.getPhysicalDeviceProperties2(physicalDevice, &deviceProperties);
311 
312     // check if both modes are supported
313     VkResolveModeFlagBits depthResolveMode   = m_config.depthResolveMode;
314     VkResolveModeFlagBits stencilResolveMode = m_config.stencilResolveMode;
315 
316     if ((depthResolveMode != VK_RESOLVE_MODE_NONE) &&
317         !(depthResolveMode & dsResolveProperties.supportedDepthResolveModes))
318         TCU_THROW(NotSupportedError, "Depth resolve mode not supported");
319 
320     if ((stencilResolveMode != VK_RESOLVE_MODE_NONE) &&
321         !(stencilResolveMode & dsResolveProperties.supportedStencilResolveModes))
322         TCU_THROW(NotSupportedError, "Stencil resolve mode not supported");
323 
324     // check if the implementation supports setting the depth and stencil resolve
325     // modes to different values when one of those modes is VK_RESOLVE_MODE_NONE
326     if (dsResolveProperties.independentResolveNone)
327     {
328         if ((!dsResolveProperties.independentResolve) && (depthResolveMode != stencilResolveMode) &&
329             (depthResolveMode != VK_RESOLVE_MODE_NONE) && (stencilResolveMode != VK_RESOLVE_MODE_NONE))
330             TCU_THROW(NotSupportedError, "Implementation doesn't support diferent resolve modes");
331     }
332     else if (!dsResolveProperties.independentResolve && (depthResolveMode != stencilResolveMode))
333     {
334         // when independentResolveNone and independentResolve are VK_FALSE then both modes must be the same
335         TCU_THROW(NotSupportedError, "Implementation doesn't support diferent resolve modes");
336     }
337 
338     // Check alternative format support if needed.
339     if (m_config.compatibleFormat)
340     {
341         if (!isSupportedFormat(m_context, m_config.compatibleFormat.get()))
342             TCU_THROW(NotSupportedError, "Alternative image format for compatibility test not supported");
343     }
344 
345     return true;
346 }
347 
sampleCountBitFromSampleCount(uint32_t count) const348 VkSampleCountFlagBits DepthStencilResolveTest::sampleCountBitFromSampleCount(uint32_t count) const
349 {
350     switch (count)
351     {
352     case 1:
353         return VK_SAMPLE_COUNT_1_BIT;
354     case 2:
355         return VK_SAMPLE_COUNT_2_BIT;
356     case 4:
357         return VK_SAMPLE_COUNT_4_BIT;
358     case 8:
359         return VK_SAMPLE_COUNT_8_BIT;
360     case 16:
361         return VK_SAMPLE_COUNT_16_BIT;
362     case 32:
363         return VK_SAMPLE_COUNT_32_BIT;
364     case 64:
365         return VK_SAMPLE_COUNT_64_BIT;
366 
367     default:
368         DE_FATAL("Invalid sample count");
369         return (VkSampleCountFlagBits)0x0;
370     }
371 }
372 
createImage(VkFormat vkformat,uint32_t sampleCount,VkImageUsageFlags additionalUsage)373 VkImageSp DepthStencilResolveTest::createImage(VkFormat vkformat, uint32_t sampleCount,
374                                                VkImageUsageFlags additionalUsage)
375 {
376     const tcu::TextureFormat format(mapVkFormat(m_config.format));
377     const VkImageTiling imageTiling(VK_IMAGE_TILING_OPTIMAL);
378     VkSampleCountFlagBits sampleCountBit(sampleCountBitFromSampleCount(sampleCount));
379     VkImageUsageFlags usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | additionalUsage;
380 
381     VkImageFormatProperties imageFormatProperties;
382     if (m_vki.getPhysicalDeviceImageFormatProperties(m_physicalDevice, m_config.format, VK_IMAGE_TYPE_2D, imageTiling,
383                                                      usage, 0u,
384                                                      &imageFormatProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
385     {
386         TCU_THROW(NotSupportedError, "Format not supported");
387     }
388     if (imageFormatProperties.sampleCounts < sampleCount)
389     {
390         TCU_THROW(NotSupportedError, "Sample count not supported");
391     }
392     if (imageFormatProperties.maxArrayLayers < m_config.imageLayers)
393     {
394         TCU_THROW(NotSupportedError, "Layers count not supported");
395     }
396 
397     const VkExtent3D imageExtent = {m_config.width, m_config.height, 1u};
398 
399     if (!(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order)))
400         TCU_THROW(NotSupportedError, "Format can't be used as depth/stencil attachment");
401 
402     if (imageFormatProperties.maxExtent.width < imageExtent.width ||
403         imageFormatProperties.maxExtent.height < imageExtent.height ||
404         ((imageFormatProperties.sampleCounts & sampleCountBit) == 0) ||
405         imageFormatProperties.maxArrayLayers < m_config.imageLayers)
406     {
407         TCU_THROW(NotSupportedError, "Image type not supported");
408     }
409 
410     const VkImageCreateInfo pCreateInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
411                                            DE_NULL,
412                                            0u,
413                                            VK_IMAGE_TYPE_2D,
414                                            vkformat,
415                                            imageExtent,
416                                            1u,
417                                            m_config.imageLayers,
418                                            sampleCountBit,
419                                            imageTiling,
420                                            usage,
421                                            VK_SHARING_MODE_EXCLUSIVE,
422                                            0u,
423                                            DE_NULL,
424                                            VK_IMAGE_LAYOUT_UNDEFINED};
425 
426     return safeSharedPtr(new Unique<VkImage>(vk::createImage(m_vkd, m_device, &pCreateInfo)));
427 }
428 
createImageMemory(VkImageSp image)429 AllocationSp DepthStencilResolveTest::createImageMemory(VkImageSp image)
430 {
431     Allocator &allocator = m_context.getDefaultAllocator();
432 
433     de::MovePtr<Allocation> allocation(
434         allocator.allocate(getImageMemoryRequirements(m_vkd, m_device, **image), MemoryRequirement::Any));
435     VK_CHECK(m_vkd.bindImageMemory(m_device, **image, allocation->getMemory(), allocation->getOffset()));
436     return safeSharedPtr(allocation.release());
437 }
438 
createImageView(VkImageSp image,VkFormat vkformat,uint32_t baseArrayLayer)439 VkImageViewSp DepthStencilResolveTest::createImageView(VkImageSp image, VkFormat vkformat, uint32_t baseArrayLayer)
440 {
441     const VkImageSubresourceRange range = {aspectFlagsForFormat(vkformat), 0u, 1u, baseArrayLayer, m_config.viewLayers};
442 
443     const VkImageViewCreateInfo pCreateInfo = {
444         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
445         DE_NULL,
446         0u,
447         **image,
448         (m_config.viewLayers > 1) ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D,
449         vkformat,
450         makeComponentMappingRGBA(),
451         range,
452     };
453     return safeSharedPtr(new Unique<VkImageView>(vk::createImageView(m_vkd, m_device, &pCreateInfo)));
454 }
455 
createRenderPass(VkFormat vkformat,uint32_t renderPassNo)456 Move<VkRenderPass> DepthStencilResolveTest::createRenderPass(VkFormat vkformat, uint32_t renderPassNo)
457 {
458     const VkSampleCountFlagBits samples(sampleCountBitFromSampleCount(m_config.sampleCount));
459 
460     VkImageLayout layout             = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
461     VkImageLayout stencilLayout      = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
462     VkImageLayout finalLayout        = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
463     VkImageLayout stencilFinalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
464 
465     if (m_config.separateDepthStencilLayouts)
466     {
467         if (m_config.verifyBuffer == VB_DEPTH)
468         {
469             layout        = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
470             stencilLayout = VK_IMAGE_LAYOUT_GENERAL;
471         }
472         else
473         {
474             layout        = VK_IMAGE_LAYOUT_GENERAL;
475             stencilLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
476         }
477     }
478 
479     if (renderPassNo != m_numRenderPasses - 1)
480     {
481         finalLayout        = layout;
482         stencilFinalLayout = stencilLayout;
483     }
484 
485     const VkAttachmentDescriptionStencilLayout multisampleAttachmentStencilLayout = {
486         VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT,         // VkStructureType sType;
487         DE_NULL,                                                         // const void* pNext;
488         (renderPassNo == 0) ? VK_IMAGE_LAYOUT_UNDEFINED : stencilLayout, // VkImageLayout initialLayout;
489         stencilFinalLayout,
490     };
491     const AttachmentDescription2 multisampleAttachment // VkAttachmentDescription2
492         (
493             // VkStructureType sType;
494             m_config.separateDepthStencilLayouts ? &multisampleAttachmentStencilLayout : DE_NULL, // const void* pNext;
495             0u,              // VkAttachmentDescriptionFlags flags;
496             m_config.format, // VkFormat format;
497             samples,         // VkSampleCountFlagBits samples;
498             (renderPassNo == 0) ? VK_ATTACHMENT_LOAD_OP_CLEAR :
499                                   VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
500             (m_numRenderPasses > 1) ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE,
501             (renderPassNo == 0) ? VK_ATTACHMENT_LOAD_OP_CLEAR :
502                                   VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp stencilLoadOp;
503             (m_numRenderPasses > 1) ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE,
504             (renderPassNo == 0) ? VK_IMAGE_LAYOUT_UNDEFINED : layout, // VkImageLayout initialLayout;
505             finalLayout                                               // VkImageLayout finalLayout;
506         );
507     const VkAttachmentReferenceStencilLayout multisampleAttachmentRefStencilLayout = {
508         VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT, // VkStructureType sType;
509         DE_NULL,                                               // const void* pNext;
510         stencilLayout                                          // VkImageLayout stencilLayout;
511     };
512     const AttachmentReference2 multisampleAttachmentRef // VkAttachmentReference2
513         (
514             // VkStructureType sType;
515             m_config.separateDepthStencilLayouts ? &multisampleAttachmentRefStencilLayout :
516                                                    DE_NULL, // const void* pNext;
517             0u,                                             // uint32_t attachment;
518             layout,                                         // VkImageLayout layout;
519             m_config.aspectFlag                             // VkImageAspectFlags aspectMask;
520         );
521 
522     vk::VkImageLayout singleSampleInitialLayout =
523         (m_config.unusedResolve ? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED);
524     vk::VkImageLayout singleSampleStencilInitialLayout =
525         (m_config.unusedResolve ? VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED);
526     if (renderPassNo != 0)
527     {
528         singleSampleInitialLayout        = layout;
529         singleSampleStencilInitialLayout = stencilLayout;
530     }
531 
532     const VkAttachmentDescriptionStencilLayout singlesampleAttachmentStencilLayout = {
533         VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT, // VkStructureType sType;
534         DE_NULL,                                                 // const void* pNext;
535         singleSampleStencilInitialLayout,                        // VkImageLayout initialLayout;
536         stencilFinalLayout,
537     };
538     const AttachmentDescription2 singlesampleAttachment // VkAttachmentDescription2
539         (
540             // VkStructureType sType;
541             m_config.separateDepthStencilLayouts ? &singlesampleAttachmentStencilLayout : DE_NULL, // const void* pNext;
542             0u,                           // VkAttachmentDescriptionFlags flags;
543             vkformat,                     // VkFormat format;
544             VK_SAMPLE_COUNT_1_BIT,        // VkSampleCountFlagBits samples;
545             VK_ATTACHMENT_LOAD_OP_CLEAR,  // VkAttachmentLoadOp loadOp;
546             VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
547             VK_ATTACHMENT_LOAD_OP_CLEAR,  // VkAttachmentLoadOp stencilLoadOp;
548             VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp;
549             singleSampleInitialLayout,    // VkImageLayout initialLayout;
550             finalLayout                   // VkImageLayout finalLayout;
551         );
552 
553     const VkAttachmentReferenceStencilLayout singlesampleAttachmentRefStencilLayout = {
554         VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT, // VkStructureType sType;
555         DE_NULL,                                               // const void* pNext;
556         stencilLayout                                          // VkImageLayout stencilLayout;
557     };
558     const AttachmentReference2 singlesampleAttachmentRef // VkAttachmentReference2
559         (
560             // VkStructureType sType;
561             m_config.separateDepthStencilLayouts ? &singlesampleAttachmentRefStencilLayout :
562                                                    DE_NULL, // const void* pNext;
563             ((m_config.unusedResolve || renderPassNo != m_numRenderPasses - 1) ? VK_ATTACHMENT_UNUSED :
564                                                                                  1u), // uint32_t attachment;
565             layout,                                                                   // VkImageLayout layout;
566             aspectFlagsForFormat(vkformat)                                            // VkImageAspectFlags aspectMask;
567         );
568 
569     std::vector<AttachmentDescription2> attachments;
570     attachments.push_back(multisampleAttachment);
571     attachments.push_back(singlesampleAttachment);
572 
573     VkSubpassDescriptionDepthStencilResolve dsResolveDescription = {
574         VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE,
575         DE_NULL,                     // const void* pNext;
576         m_config.depthResolveMode,   // VkResolveModeFlagBits depthResolveMode;
577         m_config.stencilResolveMode, // VkResolveModeFlagBits stencilResolveMode;
578         &singlesampleAttachmentRef   // VkAttachmentReference2 pDepthStencilResolveAttachment;
579     };
580 
581     const SubpassDescription2 subpass // VkSubpassDescription2
582         (
583             // VkStructureType sType;
584             renderPassNo == m_numRenderPasses - 1 ? &dsResolveDescription : DE_NULL, // const void* pNext;
585             (VkSubpassDescriptionFlags)0,                                            // VkSubpassDescriptionFlags flags;
586             VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
587             0u,                              // uint32_t viewMask;
588             0u,                              // uint32_t inputAttachmentCount;
589             DE_NULL,                         // const VkAttachmentReference2* pInputAttachments;
590             0u,                              // uint32_t colorAttachmentCount;
591             DE_NULL,                         // const VkAttachmentReference2* pColorAttachments;
592             DE_NULL,                         // const VkAttachmentReference2* pResolveAttachments;
593             &multisampleAttachmentRef,       // const VkAttachmentReference2* pDepthStencilAttachment;
594             0u,                              // uint32_t preserveAttachmentCount;
595             DE_NULL                          // const uint32_t* pPreserveAttachments;
596         );
597 
598     const RenderPassCreateInfo2 renderPassCreator // VkRenderPassCreateInfo2
599         (
600             // VkStructureType sType;
601             DE_NULL,                      // const void* pNext;
602             (VkRenderPassCreateFlags)0u,  // VkRenderPassCreateFlags flags;
603             (uint32_t)attachments.size(), // uint32_t attachmentCount;
604             &attachments[0],              // const VkAttachmentDescription2* pAttachments;
605             1u,                           // uint32_t subpassCount;
606             &subpass,                     // const VkSubpassDescription2* pSubpasses;
607             0u,                           // uint32_t dependencyCount;
608             DE_NULL,                      // const VkSubpassDependency2* pDependencies;
609             0u,                           // uint32_t correlatedViewMaskCount;
610             DE_NULL                       // const uint32_t* pCorrelatedViewMasks;
611         );
612 
613     return renderPassCreator.createRenderPass(m_vkd, m_device);
614 }
615 
616 // Checks format support.
617 // Note: we need the context because this is called from the constructor only after m_config has been set.
isSupportedFormat(Context & context,VkFormat format) const618 bool DepthStencilResolveTest::isSupportedFormat(Context &context, VkFormat format) const
619 {
620     const VkImageUsageFlags usage =
621         VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
622         (m_config.unusedResolve ? VK_IMAGE_USAGE_TRANSFER_DST_BIT : static_cast<vk::VkImageUsageFlagBits>(0u));
623     VkImageFormatProperties props;
624 
625     const auto &vki           = context.getInstanceInterface();
626     const auto physicalDevice = context.getPhysicalDevice();
627     const auto formatCheck    = vki.getPhysicalDeviceImageFormatProperties(physicalDevice, format, VK_IMAGE_TYPE_2D,
628                                                                            VK_IMAGE_TILING_OPTIMAL, usage, 0u, &props);
629 
630     return (formatCheck == VK_SUCCESS);
631 }
632 
createRenderPassCompatible(void)633 Move<VkRenderPass> DepthStencilResolveTest::createRenderPassCompatible(void)
634 {
635     // Early exit if we are not testing compatibility.
636     if (!m_config.compatibleFormat)
637         return {};
638 
639     return createRenderPass(m_config.compatibleFormat.get(), 0);
640 }
641 
createFramebuffer(VkRenderPass renderPass,VkImageViewSp multisampleImageView,VkImageViewSp singlesampleImageView)642 Move<VkFramebuffer> DepthStencilResolveTest::createFramebuffer(VkRenderPass renderPass,
643                                                                VkImageViewSp multisampleImageView,
644                                                                VkImageViewSp singlesampleImageView)
645 {
646     std::vector<VkImageView> attachments;
647     attachments.push_back(**multisampleImageView);
648     attachments.push_back(**singlesampleImageView);
649 
650     const VkFramebufferCreateInfo createInfo = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
651                                                 DE_NULL,
652                                                 0u,
653 
654                                                 renderPass,
655                                                 (uint32_t)attachments.size(),
656                                                 &attachments[0],
657 
658                                                 m_config.width,
659                                                 m_config.height,
660                                                 m_config.viewLayers};
661 
662     return vk::createFramebuffer(m_vkd, m_device, &createInfo);
663 }
664 
createRenderPipelineLayout(void)665 Move<VkPipelineLayout> DepthStencilResolveTest::createRenderPipelineLayout(void)
666 {
667     VkPushConstantRange pushConstant = {VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 4u};
668 
669     uint32_t pushConstantRangeCount          = 0u;
670     VkPushConstantRange *pPushConstantRanges = DE_NULL;
671     if (m_config.verifyBuffer == VB_STENCIL)
672     {
673         pushConstantRangeCount = 1u;
674         pPushConstantRanges    = &pushConstant;
675     }
676 
677     const VkPipelineLayoutCreateInfo createInfo = {VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
678                                                    DE_NULL,
679                                                    (vk::VkPipelineLayoutCreateFlags)0,
680 
681                                                    0u,
682                                                    DE_NULL,
683 
684                                                    pushConstantRangeCount,
685                                                    pPushConstantRanges};
686 
687     return vk::createPipelineLayout(m_vkd, m_device, &createInfo);
688 }
689 
createRenderPipeline(VkRenderPass renderPass,uint32_t renderPassNo,VkPipelineLayout renderPipelineLayout)690 Move<VkPipeline> DepthStencilResolveTest::createRenderPipeline(VkRenderPass renderPass, uint32_t renderPassNo,
691                                                                VkPipelineLayout renderPipelineLayout)
692 {
693     const bool testingStencil                    = (m_config.verifyBuffer == VB_STENCIL);
694     const vk::BinaryCollection &binaryCollection = m_context.getBinaryCollection();
695 
696     const Unique<VkShaderModule> vertexShaderModule(
697         createShaderModule(m_vkd, m_device, binaryCollection.get("quad-vert"), 0u));
698     const Unique<VkShaderModule> fragmentShaderModule(
699         createShaderModule(m_vkd, m_device, binaryCollection.get("quad-frag"), 0u));
700     const Move<VkShaderModule> geometryShaderModule(
701         m_config.imageLayers == 1 ? Move<VkShaderModule>() :
702                                     createShaderModule(m_vkd, m_device, binaryCollection.get("quad-geom"), 0u));
703 
704     const VkPipelineVertexInputStateCreateInfo vertexInputState = {
705         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
706         DE_NULL,
707         (VkPipelineVertexInputStateCreateFlags)0u,
708 
709         0u,
710         DE_NULL,
711 
712         0u,
713         DE_NULL};
714     const tcu::UVec2 view(m_config.width, m_config.height);
715     const std::vector<VkViewport> viewports(1, makeViewport(view));
716     const std::vector<VkRect2D> scissors(1, m_config.renderArea);
717     const VkSampleMask samplemask[2] = {renderPassNo < 32 ? (1u << renderPassNo) : 0,
718                                         renderPassNo < 32 ? 0 : (1u << (renderPassNo - 32))};
719 
720     const VkPipelineMultisampleStateCreateInfo multisampleState = {
721         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, DE_NULL,  (VkPipelineMultisampleStateCreateFlags)0u,
722 
723         sampleCountBitFromSampleCount(m_config.sampleCount),      VK_FALSE, 0.0f,
724         (m_config.sampleMask) ? &samplemask[0] : DE_NULL,         VK_FALSE, VK_FALSE,
725     };
726     const VkPipelineDepthStencilStateCreateInfo depthStencilState = {
727         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
728         DE_NULL,
729         (VkPipelineDepthStencilStateCreateFlags)0u,
730 
731         VK_TRUE, // depthTestEnable
732         VK_TRUE,
733         VK_COMPARE_OP_ALWAYS,
734         VK_FALSE,
735         testingStencil, // stencilTestEnable
736         {
737             VK_STENCIL_OP_REPLACE, // failOp
738             VK_STENCIL_OP_REPLACE, // passOp
739             VK_STENCIL_OP_REPLACE, // depthFailOp
740             VK_COMPARE_OP_ALWAYS,  // compareOp
741             0xFFu,                 // compareMask
742             0xFFu,                 // writeMask
743             1                      // reference
744         },
745         {VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE, VK_COMPARE_OP_ALWAYS, 0xFFu, 0xFFu, 1},
746         0.0f,
747         1.0f};
748 
749     std::vector<VkDynamicState> dynamicState;
750     dynamicState.push_back(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
751     const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
752         VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType                      sType;
753         DE_NULL,                                              // const void*                          pNext;
754         (VkPipelineDynamicStateCreateFlags)0u,                // VkPipelineDynamicStateCreateFlags    flags;
755         static_cast<uint32_t>(dynamicState.size()),           // uint32_t                             dynamicStateCount;
756         &dynamicState[0]                                      // const VkDynamicState*                pDynamicStates;
757     };
758 
759     return makeGraphicsPipeline(
760         m_vkd,                // const DeviceInterface&                        vk
761         m_device,             // const VkDevice                                device
762         renderPipelineLayout, // const VkPipelineLayout                        pipelineLayout
763         *vertexShaderModule,  // const VkShaderModule                          vertexShaderModule
764         DE_NULL,              // const VkShaderModule                          tessellationControlShaderModule
765         DE_NULL,              // const VkShaderModule                          tessellationEvalShaderModule
766         m_config.imageLayers == 1 ?
767             DE_NULL :
768             *geometryShaderModule,           // const VkShaderModule                          geometryShaderModule
769         *fragmentShaderModule,               // const VkShaderModule                          fragmentShaderModule
770         renderPass,                          // const VkRenderPass                            renderPass
771         viewports,                           // const std::vector<VkViewport>&                viewports
772         scissors,                            // const std::vector<VkRect2D>&                  scissors
773         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology                     topology
774         0u,                                  // const uint32_t                                subpass
775         0u,                                  // const uint32_t                                patchControlPoints
776         &vertexInputState,                   // const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
777         DE_NULL,            // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
778         &multisampleState,  // const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
779         &depthStencilState, // const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
780         DE_NULL,            // const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo
781         testingStencil ? &dynamicStateCreateInfo :
782                          DE_NULL); // const VkPipelineDynamicStateCreateInfo*       dynamicStateCreateInfo
783 }
784 
createBufferMemory(void)785 AllocationSp DepthStencilResolveTest::createBufferMemory(void)
786 {
787     Allocator &allocator = m_context.getDefaultAllocator();
788     de::MovePtr<Allocation> allocation(
789         allocator.allocate(getBufferMemoryRequirements(m_vkd, m_device, **m_buffer), MemoryRequirement::HostVisible));
790     VK_CHECK(m_vkd.bindBufferMemory(m_device, **m_buffer, allocation->getMemory(), allocation->getOffset()));
791     return safeSharedPtr(allocation.release());
792 }
793 
createBuffer(void)794 VkBufferSp DepthStencilResolveTest::createBuffer(void)
795 {
796     const VkBufferUsageFlags bufferUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
797     const tcu::TextureFormat textureFormat(mapVkFormat(m_config.format));
798     const VkDeviceSize pixelSize(textureFormat.getPixelSize());
799     const VkBufferCreateInfo createInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
800                                            DE_NULL,
801                                            0u,
802 
803                                            m_config.width * m_config.height * m_config.imageLayers * pixelSize,
804                                            bufferUsage,
805 
806                                            VK_SHARING_MODE_EXCLUSIVE,
807                                            0u,
808                                            DE_NULL};
809     return safeSharedPtr(new Unique<VkBuffer>(vk::createBuffer(m_vkd, m_device, &createInfo)));
810 }
811 
submit(void)812 void DepthStencilResolveTest::submit(void)
813 {
814     const DeviceInterface &vkd(m_context.getDeviceInterface());
815     const VkDevice device(m_context.getDevice());
816 
817     // When the depth/stencil resolve attachment is unused, it needs to be cleared outside
818     // the render pass so it has the expected values.
819     if (m_config.unusedResolve)
820     {
821         const Unique<VkCommandBuffer> commandBuffer(
822             allocateCommandBuffer(m_vkd, m_device, *m_commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
823         const vk::VkImageSubresourceRange imageRange = {
824             m_config.resolveAspectFlags(), 0u, VK_REMAINING_MIP_LEVELS, 0u, VK_REMAINING_ARRAY_LAYERS,
825         };
826         const vk::VkImageMemoryBarrier preBarrier = {
827             vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
828             nullptr,
829 
830             // src and dst access masks.
831             0,
832             vk::VK_ACCESS_TRANSFER_WRITE_BIT,
833 
834             // old and new layouts.
835             vk::VK_IMAGE_LAYOUT_UNDEFINED,
836             vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
837 
838             VK_QUEUE_FAMILY_IGNORED,
839             VK_QUEUE_FAMILY_IGNORED,
840 
841             **m_singlesampleImage,
842             imageRange,
843         };
844         const vk::VkImageMemoryBarrier postBarrier = {
845             vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
846             nullptr,
847 
848             // src and dst access masks.
849             vk::VK_ACCESS_TRANSFER_WRITE_BIT,
850             0,
851 
852             // old and new layouts.
853             vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
854             vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
855 
856             VK_QUEUE_FAMILY_IGNORED,
857             VK_QUEUE_FAMILY_IGNORED,
858 
859             **m_singlesampleImage,
860             imageRange,
861         };
862 
863         vk::beginCommandBuffer(m_vkd, commandBuffer.get());
864         m_vkd.cmdPipelineBarrier(commandBuffer.get(), vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
865                                  vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preBarrier);
866         m_vkd.cmdClearDepthStencilImage(commandBuffer.get(), **m_singlesampleImage,
867                                         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_config.clearValue, 1u,
868                                         &imageRange);
869         m_vkd.cmdPipelineBarrier(commandBuffer.get(), vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
870                                  vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u,
871                                  &postBarrier);
872         vk::endCommandBuffer(m_vkd, commandBuffer.get());
873 
874         vk::submitCommandsAndWait(m_vkd, m_device, m_context.getUniversalQueue(), commandBuffer.get());
875     }
876 
877     const Unique<VkCommandBuffer> commandBuffer(
878         allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
879     const RenderpassSubpass2::SubpassBeginInfo subpassBeginInfo(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
880     const RenderpassSubpass2::SubpassEndInfo subpassEndInfo(DE_NULL);
881 
882     beginCommandBuffer(vkd, *commandBuffer);
883     bool testingDepth = (m_config.verifyBuffer == VB_DEPTH);
884     if (testingDepth)
885     {
886         {
887             VkClearValue clearValues[2];
888             clearValues[0].depthStencil = m_config.clearValue;
889             clearValues[1].depthStencil = m_config.clearValue;
890 
891             const VkRenderPassBeginInfo beginInfo = {
892                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
893                 DE_NULL,
894 
895                 (m_config.compatibleFormat ? *m_renderPassCompatible : *m_renderPass[0]),
896                 *m_framebuffer,
897 
898                 {{0u, 0u}, {m_config.width, m_config.height}},
899 
900                 2u,
901                 clearValues};
902             RenderpassSubpass2::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
903         }
904 
905         // Render
906         vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline[0]);
907         vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
908         RenderpassSubpass2::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
909     }
910     else
911     {
912         // Stencil
913         for (uint32_t i = 0; i < m_config.sampleCount; i++)
914         {
915             if (i == 0 || m_config.sampleMask)
916             {
917                 VkClearValue clearValues[2];
918                 clearValues[0].depthStencil = m_config.clearValue;
919                 clearValues[1].depthStencil = m_config.clearValue;
920 
921                 const VkRenderPassBeginInfo beginInfo = {
922                     VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
923                     DE_NULL,
924 
925                     (m_config.compatibleFormat ? *m_renderPassCompatible : *m_renderPass[i]),
926                     *m_framebuffer,
927 
928                     {{0u, 0u}, {m_config.width, m_config.height}},
929 
930                     2u,
931                     clearValues};
932                 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
933                                        VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, 0, 0, 0, 0, 0);
934                 RenderpassSubpass2::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
935             }
936             // For stencil we can set reference value for just one sample at a time
937             // so we need to do as many passes as there are samples, first half
938             // of samples is initialized with 1 and second half with 255
939             const uint32_t halfOfSamples = m_config.sampleCount >> 1;
940 
941             uint32_t stencilReference = 1 + 254 * (i >= halfOfSamples);
942             vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
943                                 *m_renderPipeline[m_config.sampleMask ? i : 0]);
944             vkd.cmdPushConstants(*commandBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(i),
945                                  &i);
946             vkd.cmdSetStencilReference(*commandBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, stencilReference);
947             vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
948             if (i == m_config.sampleCount - 1 || m_config.sampleMask)
949                 RenderpassSubpass2::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
950         }
951     }
952 
953     // Memory barriers between rendering and copying
954     {
955         const VkImageMemoryBarrier barrier = {
956             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
957             DE_NULL,
958 
959             // Note: as per the spec, depth/stencil *resolve* operations are synchronized using the color attachment write access.
960             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
961             VK_ACCESS_TRANSFER_READ_BIT,
962 
963             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
964             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
965 
966             VK_QUEUE_FAMILY_IGNORED,
967             VK_QUEUE_FAMILY_IGNORED,
968 
969             **m_singlesampleImage,
970             {(m_config.separateDepthStencilLayouts) ?
971                  VkImageAspectFlags(testingDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT) :
972                  m_config.resolveAspectFlags(),
973              0u, 1u, 0u, m_config.viewLayers}};
974 
975         vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
976                                0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
977     }
978 
979     // Copy image memory to buffers
980     const VkBufferImageCopy region = {
981         0u,
982         0u,
983         0u,
984         {
985             VkImageAspectFlags(testingDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT),
986             0u,
987             0u,
988             m_config.viewLayers,
989         },
990         {0u, 0u, 0u},
991         {m_config.width, m_config.height, 1u}};
992 
993     vkd.cmdCopyImageToBuffer(*commandBuffer, **m_singlesampleImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_buffer,
994                              1u, &region);
995 
996     // Memory barriers between copies and host access
997     {
998         const VkBufferMemoryBarrier barrier = {VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
999                                                DE_NULL,
1000 
1001                                                VK_ACCESS_TRANSFER_WRITE_BIT,
1002                                                VK_ACCESS_HOST_READ_BIT,
1003 
1004                                                VK_QUEUE_FAMILY_IGNORED,
1005                                                VK_QUEUE_FAMILY_IGNORED,
1006 
1007                                                **m_buffer,
1008                                                0u,
1009                                                VK_WHOLE_SIZE};
1010 
1011         vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u,
1012                                DE_NULL, 1u, &barrier, 0u, DE_NULL);
1013     }
1014 
1015     endCommandBuffer(vkd, *commandBuffer);
1016 
1017     submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *commandBuffer);
1018 }
1019 
verifyDepth(void)1020 bool DepthStencilResolveTest::verifyDepth(void)
1021 {
1022     // Invalidate allocation before attempting to read buffer memory.
1023     invalidateAlloc(m_context.getDeviceInterface(), m_context.getDevice(), *m_bufferMemory);
1024 
1025     uint32_t layerSize   = m_config.width * m_config.height;
1026     uint32_t valuesCount = layerSize * m_config.viewLayers;
1027     uint8_t *pixelPtr    = static_cast<uint8_t *>(m_bufferMemory->getHostPtr());
1028 
1029     const DeviceInterface &vkd(m_context.getDeviceInterface());
1030     invalidateMappedMemoryRange(vkd, m_context.getDevice(), m_bufferMemory->getMemory(), m_bufferMemory->getOffset(),
1031                                 VK_WHOLE_SIZE);
1032 
1033     float expectedValue = m_config.depthExpectedValue;
1034     if (m_config.depthResolveMode == VK_RESOLVE_MODE_NONE || m_config.unusedResolve)
1035         expectedValue = m_config.clearValue.depth;
1036 
1037     // depth data in buffer is tightly packed, ConstPixelBufferAccess
1038     // coludn't be used for depth value extraction as it cant interpret
1039     // formats containing just depth component
1040 
1041     typedef float (*DepthComponentGetterFn)(uint8_t *);
1042     VkFormat format                          = m_config.format;
1043     DepthComponentGetterFn getDepthComponent = &get16bitDepthComponent;
1044     uint32_t pixelStep                       = 2;
1045     float epsilon                            = 0.002f;
1046 
1047     if ((format == VK_FORMAT_X8_D24_UNORM_PACK32) || (format == VK_FORMAT_D24_UNORM_S8_UINT))
1048     {
1049         getDepthComponent = &get24bitDepthComponent;
1050         pixelStep         = 4;
1051     }
1052     else if ((format == VK_FORMAT_D32_SFLOAT) || (format == VK_FORMAT_D32_SFLOAT_S8_UINT))
1053     {
1054         getDepthComponent = &get32bitDepthComponent;
1055         pixelStep         = 4;
1056     }
1057 
1058     for (uint32_t valueIndex = 0; valueIndex < valuesCount; valueIndex++)
1059     {
1060         float depth = (*getDepthComponent)(pixelPtr);
1061         pixelPtr += pixelStep;
1062 
1063         // check if pixel data is outside of render area
1064         int32_t layerIndex   = valueIndex / layerSize;
1065         int32_t inLayerIndex = valueIndex % layerSize;
1066         int32_t x            = inLayerIndex % m_config.width;
1067         int32_t y            = (inLayerIndex - x) / m_config.width;
1068         int32_t x1           = m_config.renderArea.offset.x;
1069         int32_t y1           = m_config.renderArea.offset.y;
1070         int32_t x2           = x1 + m_config.renderArea.extent.width;
1071         int32_t y2           = y1 + m_config.renderArea.extent.height;
1072         if ((x < x1) || (x >= x2) || (y < y1) || (y >= y2))
1073         {
1074             // verify that outside of render area there are clear values
1075             float error = deFloatAbs(depth - m_config.clearValue.depth);
1076             if (error > epsilon)
1077             {
1078                 m_context.getTestContext().getLog()
1079                     << TestLog::Message << "(" << x << ", " << y << ", layer: " << layerIndex
1080                     << ") is outside of render area but depth value is: " << depth << " (expected "
1081                     << m_config.clearValue.depth << ")" << TestLog::EndMessage;
1082                 return false;
1083             }
1084 
1085             // value is correct, go to next one
1086             continue;
1087         }
1088 
1089         float error = deFloatAbs(depth - expectedValue);
1090         if (error > epsilon)
1091         {
1092             m_context.getTestContext().getLog()
1093                 << TestLog::Message << "At (" << x << ", " << y << ", layer: " << layerIndex
1094                 << ") depth value is: " << depth << " expected: " << expectedValue << TestLog::EndMessage;
1095             return false;
1096         }
1097     }
1098     m_context.getTestContext().getLog() << TestLog::Message << "Depth value is " << expectedValue
1099                                         << TestLog::EndMessage;
1100 
1101     return true;
1102 }
1103 
verifyStencil(void)1104 bool DepthStencilResolveTest::verifyStencil(void)
1105 {
1106     // Invalidate allocation before attempting to read buffer memory.
1107     invalidateAlloc(m_context.getDeviceInterface(), m_context.getDevice(), *m_bufferMemory);
1108 
1109     uint32_t layerSize   = m_config.width * m_config.height;
1110     uint32_t valuesCount = layerSize * m_config.viewLayers;
1111     uint8_t *pixelPtr    = static_cast<uint8_t *>(m_bufferMemory->getHostPtr());
1112 
1113     const DeviceInterface &vkd(m_context.getDeviceInterface());
1114     invalidateMappedMemoryRange(vkd, m_context.getDevice(), m_bufferMemory->getMemory(), m_bufferMemory->getOffset(),
1115                                 VK_WHOLE_SIZE);
1116 
1117     // when stencil is tested we are discarding invocations and
1118     // because of that depth and stencil need to be tested separately
1119 
1120     uint8_t expectedValue = m_config.stencilExpectedValue;
1121     if (m_config.stencilResolveMode == VK_RESOLVE_MODE_NONE || m_config.unusedResolve)
1122         expectedValue = static_cast<uint8_t>(m_config.clearValue.stencil);
1123 
1124     for (uint32_t valueIndex = 0; valueIndex < valuesCount; valueIndex++)
1125     {
1126         uint8_t stencil      = *pixelPtr++;
1127         int32_t layerIndex   = valueIndex / layerSize;
1128         int32_t inLayerIndex = valueIndex % layerSize;
1129         int32_t x            = inLayerIndex % m_config.width;
1130         int32_t y            = (inLayerIndex - x) / m_config.width;
1131         int32_t x1           = m_config.renderArea.offset.x;
1132         int32_t y1           = m_config.renderArea.offset.y;
1133         int32_t x2           = x1 + m_config.renderArea.extent.width;
1134         int32_t y2           = y1 + m_config.renderArea.extent.height;
1135         if ((x < x1) || (x >= x2) || (y < y1) || (y >= y2))
1136         {
1137             if (stencil != m_config.clearValue.stencil)
1138             {
1139                 m_context.getTestContext().getLog()
1140                     << TestLog::Message << "(" << x << ", " << y << ", layer: " << layerIndex
1141                     << ") is outside of render area but stencil value is: " << stencil << " (expected "
1142                     << m_config.clearValue.stencil << ")" << TestLog::EndMessage;
1143                 return false;
1144             }
1145 
1146             // value is correct, go to next one
1147             continue;
1148         }
1149 
1150         if (stencil != expectedValue)
1151         {
1152             m_context.getTestContext().getLog()
1153                 << TestLog::Message << "At (" << x << ", " << y << ", layer: " << layerIndex
1154                 << ") stencil value is: " << static_cast<uint32_t>(stencil)
1155                 << " expected: " << static_cast<uint32_t>(expectedValue) << TestLog::EndMessage;
1156             return false;
1157         }
1158     }
1159     m_context.getTestContext().getLog() << TestLog::Message << "Stencil value is "
1160                                         << static_cast<uint32_t>(expectedValue) << TestLog::EndMessage;
1161 
1162     return true;
1163 }
1164 
iterate(void)1165 tcu::TestStatus DepthStencilResolveTest::iterate(void)
1166 {
1167     submit();
1168 
1169     bool result = false;
1170     if (m_config.verifyBuffer == VB_DEPTH)
1171         result = verifyDepth();
1172     else
1173         result = verifyStencil();
1174 
1175     if (result)
1176         return tcu::TestStatus::pass("Pass");
1177     return tcu::TestStatus::fail("Fail");
1178 }
1179 
1180 struct Programs
1181 {
initvkt::__anonbd6d96410111::Programs1182     void init(vk::SourceCollections &dst, TestConfig config) const
1183     {
1184         // geometry shader is only needed in multi-layer framebuffer resolve tests
1185         if (config.imageLayers > 1)
1186         {
1187             const uint32_t layerCount = 3;
1188 
1189             std::ostringstream src;
1190             src << "#version 450\n"
1191                 << "highp float;\n"
1192                 << "\n"
1193                 << "layout(triangles) in;\n"
1194                 << "layout(triangle_strip, max_vertices = " << 3 * 2 * layerCount << ") out;\n"
1195                 << "\n"
1196                 << "in gl_PerVertex {\n"
1197                 << "    vec4 gl_Position;\n"
1198                 << "} gl_in[];\n"
1199                 << "\n"
1200                 << "out gl_PerVertex {\n"
1201                 << "    vec4 gl_Position;\n"
1202                 << "};\n"
1203                 << "\n"
1204                 << "void main (void) {\n"
1205                 << "    for (int layerNdx = 0; layerNdx < " << layerCount << "; ++layerNdx) {\n"
1206                 << "        for(int vertexNdx = 0; vertexNdx < gl_in.length(); vertexNdx++) {\n"
1207                 << "            gl_Position = gl_in[vertexNdx].gl_Position;\n"
1208                 << "            gl_Layer    = layerNdx;\n"
1209                 << "            EmitVertex();\n"
1210                 << "        };\n"
1211                 << "        EndPrimitive();\n"
1212                 << "    };\n"
1213                 << "}\n";
1214 
1215             dst.glslSources.add("quad-geom") << glu::GeometrySource(src.str());
1216         }
1217 
1218         dst.glslSources.add("quad-vert") << glu::VertexSource(
1219             "#version 450\n"
1220             "out gl_PerVertex {\n"
1221             "\tvec4 gl_Position;\n"
1222             "};\n"
1223             "highp float;\n"
1224             "void main (void) {\n"
1225             "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
1226             "\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
1227             "}\n");
1228 
1229         if (config.verifyBuffer == VB_DEPTH)
1230         {
1231             dst.glslSources.add("quad-frag") << glu::FragmentSource(
1232                 "#version 450\n"
1233                 "precision highp float;\n"
1234                 "precision highp int;\n"
1235                 "void main (void)\n"
1236                 "{\n"
1237                 "  float sampleIndex = float(gl_SampleID);\n"          // sampleIndex is integer in range <0, 63>
1238                 "  float valueIndex = round(mod(sampleIndex, 4.0));\n" // limit possible depth values - count to 4
1239                 "  float value = valueIndex + 2.0;\n"                  // value is one of [2, 3, 4, 5]
1240                 "  value = round(exp2(value));\n"                      // value is one of [4, 8, 16, 32]
1241                 "  bool condition = (int(value) == 8);\n"            // select second sample value (to make it smallest)
1242                 "  value = round(value - float(condition) * 6.0);\n" // value is one of [4, 2, 16, 32]
1243                 "  gl_FragDepth = value / 100.0;\n"                  // sample depth is one of [0.04, 0.02, 0.16, 0.32]
1244                 "}\n");
1245         }
1246         else
1247         {
1248             if (config.sampleMask)
1249             {
1250                 dst.glslSources.add("quad-frag") << glu::FragmentSource("#version 450\n"
1251                                                                         "precision highp float;\n"
1252                                                                         "precision highp int;\n"
1253                                                                         "void main (void)\n"
1254                                                                         "{\n"
1255                                                                         "  gl_FragDepth = 0.5;\n"
1256                                                                         "}\n");
1257             }
1258             else
1259             {
1260                 dst.glslSources.add("quad-frag") << glu::FragmentSource("#version 450\n"
1261                                                                         "precision highp float;\n"
1262                                                                         "precision highp int;\n"
1263                                                                         "layout(push_constant) uniform PushConstant {\n"
1264                                                                         "  highp int sampleID;\n"
1265                                                                         "} pushConstants;\n"
1266                                                                         "void main (void)\n"
1267                                                                         "{\n"
1268                                                                         "  if(gl_SampleID != pushConstants.sampleID)\n"
1269                                                                         "    discard;\n"
1270                                                                         "  gl_FragDepth = 0.5;\n"
1271                                                                         "}\n");
1272             }
1273         }
1274     }
1275 };
1276 
checkSupport(Context & context)1277 void checkSupport(Context &context)
1278 {
1279     context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
1280 }
1281 
1282 class PropertiesTestCase : public vkt::TestCase
1283 {
1284 public:
PropertiesTestCase(tcu::TestContext & testCtx,const std::string & name)1285     PropertiesTestCase(tcu::TestContext &testCtx, const std::string &name) : vkt::TestCase(testCtx, name)
1286     {
1287     }
~PropertiesTestCase(void)1288     virtual ~PropertiesTestCase(void)
1289     {
1290     }
1291 
1292     virtual TestInstance *createInstance(Context &context) const;
1293     virtual void checkSupport(Context &context) const;
1294 };
1295 
1296 class PropertiesTestInstance : public vkt::TestInstance
1297 {
1298 public:
PropertiesTestInstance(Context & context)1299     PropertiesTestInstance(Context &context) : vkt::TestInstance(context)
1300     {
1301     }
~PropertiesTestInstance(void)1302     virtual ~PropertiesTestInstance(void)
1303     {
1304     }
1305 
1306     virtual tcu::TestStatus iterate(void);
1307 };
1308 
createInstance(Context & context) const1309 TestInstance *PropertiesTestCase::createInstance(Context &context) const
1310 {
1311     return new PropertiesTestInstance(context);
1312 }
1313 
checkSupport(Context & context) const1314 void PropertiesTestCase::checkSupport(Context &context) const
1315 {
1316     context.requireDeviceFunctionality("VK_KHR_depth_stencil_resolve");
1317 }
1318 
iterate(void)1319 tcu::TestStatus PropertiesTestInstance::iterate(void)
1320 {
1321     vk::VkPhysicalDeviceDepthStencilResolveProperties dsrProperties;
1322     dsrProperties.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES;
1323     dsrProperties.pNext = nullptr;
1324 
1325     vk::VkPhysicalDeviceProperties2 properties2;
1326     properties2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1327     properties2.pNext = &dsrProperties;
1328 
1329     m_context.getInstanceInterface().getPhysicalDeviceProperties2(m_context.getPhysicalDevice(), &properties2);
1330 
1331 #ifndef CTS_USES_VULKANSC
1332     if ((dsrProperties.supportedDepthResolveModes & vk::VK_RESOLVE_MODE_SAMPLE_ZERO_BIT) == 0)
1333         TCU_FAIL("supportedDepthResolveModes does not include VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR");
1334 
1335     if ((dsrProperties.supportedStencilResolveModes & vk::VK_RESOLVE_MODE_SAMPLE_ZERO_BIT) == 0)
1336         TCU_FAIL("supportedStencilResolveModes does not include VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR");
1337 #endif // CTS_USES_VULKANCTS
1338 
1339     if ((dsrProperties.supportedStencilResolveModes & vk::VK_RESOLVE_MODE_AVERAGE_BIT) != 0)
1340         TCU_FAIL("supportedStencilResolveModes includes forbidden VK_RESOLVE_MODE_AVERAGE_BIT_KHR");
1341 
1342     if (dsrProperties.independentResolve == VK_TRUE && dsrProperties.independentResolveNone != VK_TRUE)
1343         TCU_FAIL("independentResolve supported but independentResolveNone not supported");
1344 
1345     return tcu::TestStatus::pass("Pass");
1346 }
1347 
initTests(tcu::TestCaseGroup * group)1348 void initTests(tcu::TestCaseGroup *group)
1349 {
1350     typedef InstanceFactory1WithSupport<DepthStencilResolveTest, TestConfig, FunctionSupport0, Programs>
1351         DSResolveTestInstance;
1352 
1353     struct FormatData
1354     {
1355         VkFormat format;
1356         const char *name;
1357         bool hasDepth;
1358         bool hasStencil;
1359     };
1360     FormatData formats[] = {
1361         {VK_FORMAT_D16_UNORM, "d16_unorm", true, false},
1362         {VK_FORMAT_X8_D24_UNORM_PACK32, "x8_d24_unorm_pack32", true, false},
1363         {VK_FORMAT_D32_SFLOAT, "d32_sfloat", true, false},
1364         {VK_FORMAT_S8_UINT, "s8_uint", false, true},
1365         {VK_FORMAT_D16_UNORM_S8_UINT, "d16_unorm_s8_uint", true, true},
1366         {VK_FORMAT_D24_UNORM_S8_UINT, "d24_unorm_s8_uint", true, true},
1367         {VK_FORMAT_D32_SFLOAT_S8_UINT, "d32_sfloat_s8_uint", true, true},
1368     };
1369 
1370     struct ResolveModeData
1371     {
1372         VkResolveModeFlagBits flag;
1373         std::string name;
1374     };
1375     ResolveModeData resolveModes[] = {
1376         {VK_RESOLVE_MODE_NONE, "none"},           {VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, "zero"},
1377         {VK_RESOLVE_MODE_AVERAGE_BIT, "average"}, {VK_RESOLVE_MODE_MIN_BIT, "min"},
1378         {VK_RESOLVE_MODE_MAX_BIT, "max"},
1379     };
1380 
1381     struct ImageTestData
1382     {
1383         const char *groupName;
1384         uint32_t width;
1385         uint32_t height;
1386         uint32_t imageLayers;
1387         VkRect2D renderArea;
1388         VkClearDepthStencilValue clearValue;
1389     };
1390 
1391     // NOTE: tests cant be executed for 1D and 3D images:
1392     // 1D images are not tested because acording to specification sampleCounts
1393     // will be set to VK_SAMPLE_COUNT_1_BIT when type is not VK_IMAGE_TYPE_2D
1394     // 3D images are not tested because VkFramebufferCreateInfo specification
1395     // states that: each element of pAttachments that is a 2D or 2D array image
1396     // view taken from a 3D image must not be a depth/stencil format
1397     ImageTestData imagesTestData[] = {
1398         {"image_2d_32_32", 32, 32, 1, {{0, 0}, {32, 32}}, {0.000f, 0x00}},
1399         {"image_2d_8_32", 8, 32, 1, {{1, 1}, {6, 30}}, {0.123f, 0x01}},
1400         {"image_2d_49_13", 49, 13, 1, {{10, 5}, {20, 8}}, {1.000f, 0x05}},
1401         {"image_2d_5_1", 5, 1, 1, {{0, 0}, {5, 1}}, {0.500f, 0x00}},
1402         {"image_2d_17_1", 17, 1, 1, {{1, 0}, {15, 1}}, {0.789f, 0xfa}},
1403     };
1404     const uint32_t sampleCounts[]       = {2u, 4u, 8u, 16u, 32u, 64u};
1405     const float depthExpectedValue[][6] = {
1406         // 2 samples    4            8            16            32            64
1407         {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},            // RESOLVE_MODE_NONE - expect clear value
1408         {0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 0.04f},      // RESOLVE_MODE_SAMPLE_ZERO_BIT
1409         {0.03f, 0.135f, 0.135f, 0.135f, 0.135f, 0.135f}, // RESOLVE_MODE_AVERAGE_BIT
1410         {0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f},      // RESOLVE_MODE_MIN_BIT
1411         {0.04f, 0.32f, 0.32f, 0.32f, 0.32f, 0.32f},      // RESOLVE_MODE_MAX_BIT
1412     };
1413     const uint8_t stencilExpectedValue[][6] = {
1414         // 2 samples    4        8        16        32        64
1415         {0u, 0u, 0u, 0u, 0u, 0u},             // RESOLVE_MODE_NONE - expect clear value
1416         {1u, 1u, 1u, 1u, 1u, 1u},             // RESOLVE_MODE_SAMPLE_ZERO_BIT
1417         {0u, 0u, 0u, 0u, 0u, 0u},             // RESOLVE_MODE_AVERAGE_BIT - not supported
1418         {1u, 1u, 1u, 1u, 1u, 1u},             // RESOLVE_MODE_MIN_BIT
1419         {255u, 255u, 255u, 255u, 255u, 255u}, // RESOLVE_MODE_MAX_BIT
1420     };
1421 
1422     const DepthCompatibilityManager compatManager;
1423 
1424     tcu::TestContext &testCtx(group->getTestContext());
1425 
1426     // Misc tests.
1427     {
1428         // Miscellaneous depth/stencil resolve tests
1429         de::MovePtr<tcu::TestCaseGroup> miscGroup(new tcu::TestCaseGroup(testCtx, "misc"));
1430         // Check reported depth/stencil resolve properties
1431         miscGroup->addChild(new PropertiesTestCase(testCtx, "properties"));
1432         group->addChild(miscGroup.release());
1433     }
1434 
1435     // iterate over image data
1436     for (uint32_t imageDataNdx = 0; imageDataNdx < DE_LENGTH_OF_ARRAY(imagesTestData); imageDataNdx++)
1437     {
1438         ImageTestData imageData = imagesTestData[imageDataNdx];
1439 
1440         // create test group for image data
1441         de::MovePtr<tcu::TestCaseGroup> imageGroup(new tcu::TestCaseGroup(testCtx, imageData.groupName));
1442 
1443         // iterate over sampleCounts
1444         for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
1445         {
1446             const uint32_t sampleCount(sampleCounts[sampleCountNdx]);
1447             const std::string sampleName("samples_" + de::toString(sampleCount));
1448 
1449             // create test group for sample count
1450             de::MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(testCtx, sampleName.c_str()));
1451 
1452             // iterate over depth/stencil formats
1453             for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1454             {
1455                 const FormatData &formatData = formats[formatNdx];
1456                 VkFormat format              = formatData.format;
1457                 const char *formatName       = formatData.name;
1458                 const bool hasDepth          = formatData.hasDepth;
1459                 const bool hasStencil        = formatData.hasStencil;
1460                 VkImageAspectFlags aspectFlags =
1461                     (hasDepth * VK_IMAGE_ASPECT_DEPTH_BIT) | (hasStencil * VK_IMAGE_ASPECT_STENCIL_BIT);
1462                 const int separateLayoutsLoopCount = (hasDepth && hasStencil) ? 2 : 1;
1463 
1464                 for (int separateDepthStencilLayouts = 0; separateDepthStencilLayouts < separateLayoutsLoopCount;
1465                      ++separateDepthStencilLayouts)
1466                 {
1467                     const bool useSeparateDepthStencilLayouts = bool(separateDepthStencilLayouts);
1468                     const std::string groupName =
1469                         std::string(formatName) + ((useSeparateDepthStencilLayouts) ? "_separate_layouts" : "");
1470 
1471                     // create test group for format
1472                     de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, groupName.c_str()));
1473 
1474                     // iterate over depth resolve modes
1475                     for (size_t depthResolveModeNdx = 0; depthResolveModeNdx < DE_LENGTH_OF_ARRAY(resolveModes);
1476                          depthResolveModeNdx++)
1477                     {
1478                         // iterate over stencil resolve modes
1479                         for (size_t stencilResolveModeNdx = 0; stencilResolveModeNdx < DE_LENGTH_OF_ARRAY(resolveModes);
1480                              stencilResolveModeNdx++)
1481                         {
1482                             for (int unusedIdx = 0; unusedIdx < 2; ++unusedIdx)
1483                             {
1484                                 // there is no average resolve mode for stencil - go to next iteration
1485                                 ResolveModeData &sResolve = resolveModes[stencilResolveModeNdx];
1486                                 if (sResolve.flag == VK_RESOLVE_MODE_AVERAGE_BIT)
1487                                     continue;
1488 
1489                                 // if pDepthStencilResolveAttachment is not NULL and does not have the value VK_ATTACHMENT_UNUSED,
1490                                 // depthResolveMode and stencilResolveMode must not both be VK_RESOLVE_MODE_NONE_KHR
1491                                 ResolveModeData &dResolve = resolveModes[depthResolveModeNdx];
1492                                 if ((dResolve.flag == VK_RESOLVE_MODE_NONE) && (sResolve.flag == VK_RESOLVE_MODE_NONE))
1493                                     continue;
1494 
1495                                 // If there is no depth, the depth resolve mode should be NONE, or
1496                                 // match the stencil resolve mode.
1497                                 if (!hasDepth && (dResolve.flag != VK_RESOLVE_MODE_NONE) &&
1498                                     (dResolve.flag != sResolve.flag))
1499                                     continue;
1500 
1501                                 // If there is no stencil, the stencil resolve mode should be NONE, or
1502                                 // match the depth resolve mode.
1503                                 if (!hasStencil && (sResolve.flag != VK_RESOLVE_MODE_NONE) &&
1504                                     (dResolve.flag != sResolve.flag))
1505                                     continue;
1506 
1507                                 const bool unusedResolve = (unusedIdx > 0);
1508 
1509                                 std::string baseName = "depth_" + dResolve.name + "_stencil_" + sResolve.name;
1510                                 if (unusedResolve)
1511                                     baseName += "_unused_resolve";
1512 
1513                                 if (hasDepth)
1514                                 {
1515                                     std::string name     = baseName + "_testing_depth";
1516                                     const char *testName = name.c_str();
1517                                     float expectedValue  = depthExpectedValue[depthResolveModeNdx][sampleCountNdx];
1518 
1519                                     const TestConfig testConfig = {format,
1520                                                                    imageData.width,
1521                                                                    imageData.height,
1522                                                                    1u,
1523                                                                    1u,
1524                                                                    0u,
1525                                                                    imageData.renderArea,
1526                                                                    aspectFlags,
1527                                                                    sampleCount,
1528                                                                    dResolve.flag,
1529                                                                    sResolve.flag,
1530                                                                    VB_DEPTH,
1531                                                                    imageData.clearValue,
1532                                                                    expectedValue,
1533                                                                    0u,
1534                                                                    useSeparateDepthStencilLayouts,
1535                                                                    unusedResolve,
1536                                                                    tcu::Nothing,
1537                                                                    false};
1538                                     formatGroup->addChild(
1539                                         new DSResolveTestInstance(testCtx, testName, testConfig, checkSupport));
1540 
1541                                     if (sampleCountNdx == 0 && imageDataNdx == 0 &&
1542                                         dResolve.flag != VK_RESOLVE_MODE_NONE)
1543                                     {
1544                                         const auto compatibleFormat = compatManager.getAlternativeFormat(format);
1545 
1546                                         if (compatibleFormat != VK_FORMAT_UNDEFINED)
1547                                         {
1548                                             std::string compatibilityTestName        = "compatibility_" + name;
1549                                             TestConfig compatibilityTestConfig       = testConfig;
1550                                             compatibilityTestConfig.compatibleFormat = tcu::just(compatibleFormat);
1551 
1552                                             formatGroup->addChild(
1553                                                 new DSResolveTestInstance(testCtx, compatibilityTestName.c_str(),
1554                                                                           compatibilityTestConfig, checkSupport));
1555                                         }
1556                                     }
1557                                 }
1558                                 if (hasStencil)
1559                                 {
1560                                     std::string name      = baseName + "_testing_stencil";
1561                                     const char *testName  = name.c_str();
1562                                     uint8_t expectedValue = stencilExpectedValue[stencilResolveModeNdx][sampleCountNdx];
1563 
1564                                     const TestConfig testConfig = {format,
1565                                                                    imageData.width,
1566                                                                    imageData.height,
1567                                                                    1u,
1568                                                                    1u,
1569                                                                    0u,
1570                                                                    imageData.renderArea,
1571                                                                    aspectFlags,
1572                                                                    sampleCount,
1573                                                                    dResolve.flag,
1574                                                                    sResolve.flag,
1575                                                                    VB_STENCIL,
1576                                                                    imageData.clearValue,
1577                                                                    0.0f,
1578                                                                    expectedValue,
1579                                                                    useSeparateDepthStencilLayouts,
1580                                                                    unusedResolve,
1581                                                                    tcu::Nothing,
1582                                                                    false};
1583                                     formatGroup->addChild(
1584                                         new DSResolveTestInstance(testCtx, testName, testConfig, checkSupport));
1585 
1586                                     if (dResolve.flag == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT)
1587                                     {
1588                                         std::string samplemaskTestName  = name + "_samplemask";
1589                                         TestConfig samplemaskTestConfig = testConfig;
1590                                         samplemaskTestConfig.sampleMask = true;
1591                                         formatGroup->addChild(new DSResolveTestInstance(
1592                                             testCtx, samplemaskTestName.c_str(), samplemaskTestConfig, checkSupport));
1593                                     }
1594 
1595                                     // All formats with stencil and depth aspects have incompatible formats and sizes in the depth
1596                                     // aspect, so their only alternative is the VK_FORMAT_S8_UINT format. Finally, that stencil-only
1597                                     // format has no compatible formats that can be used.
1598                                     if (sampleCountNdx == 0 && imageDataNdx == 0 && hasDepth &&
1599                                         sResolve.flag != VK_RESOLVE_MODE_NONE)
1600                                     {
1601                                         std::string compatibilityTestName        = "compatibility_" + name;
1602                                         TestConfig compatibilityTestConfig       = testConfig;
1603                                         compatibilityTestConfig.compatibleFormat = tcu::just(VK_FORMAT_S8_UINT);
1604 
1605                                         formatGroup->addChild(
1606                                             new DSResolveTestInstance(testCtx, compatibilityTestName.c_str(),
1607                                                                       compatibilityTestConfig, checkSupport));
1608                                     }
1609                                 }
1610                             }
1611                         }
1612                     }
1613                     sampleGroup->addChild(formatGroup.release());
1614                 }
1615             }
1616 
1617             imageGroup->addChild(sampleGroup.release());
1618         }
1619 
1620         group->addChild(imageGroup.release());
1621     }
1622 
1623     {
1624         // layered texture tests are done for all stencil modes and depth modes - not all combinations
1625         // Test checks if all layer are resolved in multi-layered framebuffer and if we can have a framebuffer
1626         // which starts at a layer other than zero. Both parts are tested together by rendering to layers
1627         // 4-6 and resolving to layers 1-3.
1628         ImageTestData layeredTextureTestData = {"image_2d_16_64_6", 16, 64, 6, {{10, 10}, {6, 54}}, {1.0f, 0x0}};
1629 
1630         de::MovePtr<tcu::TestCaseGroup> imageGroup(new tcu::TestCaseGroup(testCtx, layeredTextureTestData.groupName));
1631 
1632         for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
1633         {
1634             const uint32_t sampleCount(sampleCounts[sampleCountNdx]);
1635             const std::string sampleName("samples_" + de::toString(sampleCount));
1636 
1637             // create test group for sample count
1638             de::MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(testCtx, sampleName.c_str()));
1639 
1640             // iterate over depth/stencil formats
1641             for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1642             {
1643                 const FormatData &formatData = formats[formatNdx];
1644                 VkFormat format              = formatData.format;
1645                 const char *formatName       = formatData.name;
1646                 const bool hasDepth          = formatData.hasDepth;
1647                 const bool hasStencil        = formatData.hasStencil;
1648                 VkImageAspectFlags aspectFlags =
1649                     (hasDepth * VK_IMAGE_ASPECT_DEPTH_BIT) | (hasStencil * VK_IMAGE_ASPECT_STENCIL_BIT);
1650                 const int separateLayoutsLoopCount = (hasDepth && hasStencil) ? 2 : 1;
1651 
1652                 for (int separateDepthStencilLayouts = 0; separateDepthStencilLayouts < separateLayoutsLoopCount;
1653                      ++separateDepthStencilLayouts)
1654                 {
1655                     const bool useSeparateDepthStencilLayouts = bool(separateDepthStencilLayouts);
1656                     const std::string groupName =
1657                         std::string(formatName) + ((useSeparateDepthStencilLayouts) ? "_separate_layouts" : "");
1658 
1659                     // create test group for format
1660                     de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, groupName.c_str()));
1661 
1662                     for (size_t resolveModeNdx = 0; resolveModeNdx < DE_LENGTH_OF_ARRAY(resolveModes); resolveModeNdx++)
1663                     {
1664                         for (int unusedIdx = 0; unusedIdx < 2; ++unusedIdx)
1665                         {
1666                             ResolveModeData &mode = resolveModes[resolveModeNdx];
1667 
1668                             const bool unusedResolve       = (unusedIdx > 0);
1669                             const std::string unusedSuffix = (unusedResolve ? "_unused_resolve" : "");
1670 
1671                             if (!hasStencil && mode.flag == VK_RESOLVE_MODE_NONE)
1672                                 continue;
1673 
1674                             if (!hasDepth && mode.flag == VK_RESOLVE_MODE_NONE)
1675                                 continue;
1676 
1677                             if (hasDepth)
1678                             {
1679                                 std::string name            = "depth_" + mode.name + unusedSuffix;
1680                                 const char *testName        = name.c_str();
1681                                 float expectedValue         = depthExpectedValue[resolveModeNdx][sampleCountNdx];
1682                                 const TestConfig testConfig = {format,
1683                                                                layeredTextureTestData.width,
1684                                                                layeredTextureTestData.height,
1685                                                                layeredTextureTestData.imageLayers,
1686                                                                3u,
1687                                                                0u,
1688                                                                layeredTextureTestData.renderArea,
1689                                                                aspectFlags,
1690                                                                sampleCount,
1691                                                                mode.flag,
1692                                                                VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
1693                                                                VB_DEPTH,
1694                                                                layeredTextureTestData.clearValue,
1695                                                                expectedValue,
1696                                                                0u,
1697                                                                useSeparateDepthStencilLayouts,
1698                                                                unusedResolve,
1699                                                                tcu::Nothing,
1700                                                                false};
1701                                 formatGroup->addChild(
1702                                     new DSResolveTestInstance(testCtx, testName, testConfig, checkSupport));
1703                             }
1704 
1705                             // there is no average resolve mode for stencil - go to next iteration
1706                             if (mode.flag == VK_RESOLVE_MODE_AVERAGE_BIT)
1707                                 continue;
1708 
1709                             if (hasStencil)
1710                             {
1711                                 std::string name            = "stencil_" + mode.name + unusedSuffix;
1712                                 const char *testName        = name.c_str();
1713                                 uint8_t expectedValue       = stencilExpectedValue[resolveModeNdx][sampleCountNdx];
1714                                 const TestConfig testConfig = {format,
1715                                                                layeredTextureTestData.width,
1716                                                                layeredTextureTestData.height,
1717                                                                layeredTextureTestData.imageLayers,
1718                                                                3u,
1719                                                                0u,
1720                                                                layeredTextureTestData.renderArea,
1721                                                                aspectFlags,
1722                                                                sampleCount,
1723                                                                VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
1724                                                                mode.flag,
1725                                                                VB_STENCIL,
1726                                                                layeredTextureTestData.clearValue,
1727                                                                0.0f,
1728                                                                expectedValue,
1729                                                                useSeparateDepthStencilLayouts,
1730                                                                unusedResolve,
1731                                                                tcu::Nothing,
1732                                                                false};
1733                                 formatGroup->addChild(
1734                                     new DSResolveTestInstance(testCtx, testName, testConfig, checkSupport));
1735                             }
1736                         }
1737                     }
1738                     sampleGroup->addChild(formatGroup.release());
1739                 }
1740             }
1741             imageGroup->addChild(sampleGroup.release());
1742         }
1743 
1744         group->addChild(imageGroup.release());
1745     }
1746 }
1747 
1748 } // namespace
1749 
createRenderPass2DepthStencilResolveTests(tcu::TestContext & testCtx)1750 tcu::TestCaseGroup *createRenderPass2DepthStencilResolveTests(tcu::TestContext &testCtx)
1751 {
1752     return createTestGroup(testCtx, "depth_stencil_resolve", initTests);
1753 }
1754 
1755 } // namespace vkt
1756