1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2023 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 Vulkan Dynamic Rendering Depth Stencil Resolve Tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktDynamicRenderingDepthStencilResolveTests.hpp"
25 
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28 
29 #include "vkDefs.hpp"
30 #include "vkDeviceUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkPlatform.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkRef.hpp"
37 #include "vkRefUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkObjUtil.hpp"
41 
42 #include "tcuImageCompare.hpp"
43 #include "tcuFormatUtil.hpp"
44 #include "tcuResultCollector.hpp"
45 #include "tcuTestLog.hpp"
46 #include "tcuTextureUtil.hpp"
47 
48 #include "deUniquePtr.hpp"
49 #include "deSharedPtr.hpp"
50 #include "deMath.h"
51 
52 #include <limits>
53 #include <map>
54 
55 using namespace vk;
56 
57 using tcu::TestLog;
58 using tcu::Vec4;
59 
60 typedef de::SharedPtr<vk::Unique<VkImage>> VkImageSp;
61 typedef de::SharedPtr<vk::Unique<VkImageView>> VkImageViewSp;
62 typedef de::SharedPtr<vk::Unique<VkBuffer>> VkBufferSp;
63 typedef de::SharedPtr<vk::Unique<VkPipeline>> VkPipelineSp;
64 typedef de::SharedPtr<Allocation> AllocationSp;
65 
66 namespace vkt
67 {
68 namespace renderpass
69 {
70 namespace
71 {
72 
73 template <typename T>
safeSharedPtr(T * ptr)74 de::SharedPtr<T> safeSharedPtr(T *ptr)
75 {
76     try
77     {
78         return de::SharedPtr<T>(ptr);
79     }
80     catch (...)
81     {
82         delete ptr;
83         throw;
84     }
85 }
86 
aspectFlagsForFormat(VkFormat vkformat)87 VkImageAspectFlags aspectFlagsForFormat(VkFormat vkformat)
88 {
89     const tcu::TextureFormat format(mapVkFormat(vkformat));
90     VkImageAspectFlags aspectFlags =
91         ((tcu::hasDepthComponent(format.order) ? static_cast<vk::VkImageAspectFlags>(vk::VK_IMAGE_ASPECT_DEPTH_BIT) :
92                                                  0u) |
93          (tcu::hasStencilComponent(format.order) ?
94               static_cast<vk::VkImageAspectFlags>(vk::VK_IMAGE_ASPECT_STENCIL_BIT) :
95               0u));
96     return aspectFlags;
97 }
98 
99 enum VerifyBuffer
100 {
101     VB_DEPTH = 0,
102     VB_STENCIL
103 };
104 
105 struct TestConfig
106 {
107     VkFormat format;
108     uint32_t width;
109     uint32_t height;
110     uint32_t imageLayers;
111     uint32_t viewLayers;
112     uint32_t resolveBaseLayer;
113     VkRect2D renderArea;
114     VkImageAspectFlags aspectFlag;
115     uint32_t sampleCount;
116     VkResolveModeFlagBits depthResolveMode;
117     VkResolveModeFlagBits stencilResolveMode;
118     VerifyBuffer verifyBuffer;
119     VkClearDepthStencilValue clearValue;
120     float depthExpectedValue;
121     uint8_t stencilExpectedValue;
122     bool separateDepthStencilLayouts;
123     const SharedGroupParams groupParams;
124 };
125 
get16bitDepthComponent(uint8_t * pixelPtr)126 float get16bitDepthComponent(uint8_t *pixelPtr)
127 {
128     uint16_t *value = reinterpret_cast<uint16_t *>(pixelPtr);
129     return static_cast<float>(*value) / 65535.0f;
130 }
131 
get24bitDepthComponent(uint8_t * pixelPtr)132 float get24bitDepthComponent(uint8_t *pixelPtr)
133 {
134     const bool littleEndian = (DE_ENDIANNESS == DE_LITTLE_ENDIAN);
135     uint32_t value          = (((uint32_t)pixelPtr[0]) << (!littleEndian * 16u)) | (((uint32_t)pixelPtr[1]) << 8u) |
136                      (((uint32_t)pixelPtr[2]) << (littleEndian * 16u));
137     return static_cast<float>(value) / 16777215.0f;
138 }
139 
get32bitDepthComponent(uint8_t * pixelPtr)140 float get32bitDepthComponent(uint8_t *pixelPtr)
141 {
142     return *(reinterpret_cast<float *>(pixelPtr));
143 }
144 
145 class DepthStencilResolveTest : public TestInstance
146 {
147 public:
148     DepthStencilResolveTest(Context &context, TestConfig config);
149     virtual ~DepthStencilResolveTest(void);
150 
151     virtual tcu::TestStatus iterate(void);
152 
153 protected:
154     bool isFeaturesSupported(void);
155     VkSampleCountFlagBits sampleCountBitFromSampleCount(uint32_t count) const;
156 
157     VkImageSp createImage(VkFormat vkformat, uint32_t sampleCount, VkImageUsageFlags additionalUsage = 0u);
158     AllocationSp createImageMemory(VkImageSp image);
159     VkImageViewSp createImageView(VkImageSp image, VkFormat vkformat, uint32_t baseArrayLayer);
160     AllocationSp createBufferMemory(void);
161     VkBufferSp createBuffer(void);
162 
163     Move<VkPipelineLayout> createRenderPipelineLayout(void);
164     Move<VkPipeline> createRenderPipeline(VkFormat vkformat, VkPipelineLayout renderPipelineLayout);
165 
166 #ifndef CTS_USES_VULKANSC
167     void beginSecondaryCommandBuffer(VkCommandBuffer cmdBuffer, VerifyBuffer attachmentType,
168                                      VkRenderingFlagsKHR renderingFlags = 0) const;
169 #endif // CTS_USES_VULKANSC
170 
171     void submit(void);
172     bool verifyDepth(void);
173     bool verifyStencil(void);
174 
175 protected:
176     const TestConfig m_config;
177     const bool m_featureSupported;
178 
179     const InstanceInterface &m_vki;
180     const DeviceInterface &m_vkd;
181     VkDevice m_device;
182     VkPhysicalDevice m_physicalDevice;
183 
184     const Unique<VkCommandPool> m_commandPool;
185 
186     VkImageSp m_multisampleImage;
187     AllocationSp m_multisampleImageMemory;
188     VkImageViewSp m_multisampleImageView;
189     VkImageSp m_singlesampleImage;
190     AllocationSp m_singlesampleImageMemory;
191     VkImageViewSp m_singlesampleImageView;
192     VkBufferSp m_buffer;
193     AllocationSp m_bufferMemory;
194 
195     uint32_t m_numRenderPasses;
196     Unique<VkPipelineLayout> m_renderPipelineLayout;
197     Unique<VkPipeline> m_renderPipeline;
198 };
199 
DepthStencilResolveTest(Context & context,TestConfig config)200 DepthStencilResolveTest::DepthStencilResolveTest(Context &context, TestConfig config)
201     : TestInstance(context)
202     , m_config(config)
203     , m_featureSupported(isFeaturesSupported())
204     , m_vki(context.getInstanceInterface())
205     , m_vkd(context.getDeviceInterface())
206     , m_device(context.getDevice())
207     , m_physicalDevice(context.getPhysicalDevice())
208 
209     , m_commandPool(createCommandPool(context.getDeviceInterface(), context.getDevice(),
210                                       VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
211 
212     , m_multisampleImage(createImage(m_config.format, m_config.sampleCount, VK_IMAGE_USAGE_TRANSFER_SRC_BIT))
213     , m_multisampleImageMemory(createImageMemory(m_multisampleImage))
214     , m_multisampleImageView(createImageView(m_multisampleImage, m_config.format, 0u))
215 
216     , m_singlesampleImage(
217           createImage(m_config.format, 1, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT))
218     , m_singlesampleImageMemory(createImageMemory(m_singlesampleImage))
219     , m_singlesampleImageView(createImageView(m_singlesampleImage, m_config.format, m_config.resolveBaseLayer))
220 
221     , m_buffer(createBuffer())
222     , m_bufferMemory(createBufferMemory())
223 
224     , m_numRenderPasses(m_config.verifyBuffer == VB_DEPTH ? 1u : m_config.sampleCount)
225     , m_renderPipelineLayout(createRenderPipelineLayout())
226     , m_renderPipeline(createRenderPipeline(m_config.format, *m_renderPipelineLayout))
227 {
228 }
229 
~DepthStencilResolveTest(void)230 DepthStencilResolveTest::~DepthStencilResolveTest(void)
231 {
232 }
233 
isFeaturesSupported()234 bool DepthStencilResolveTest::isFeaturesSupported()
235 {
236     m_context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
237     m_context.requireDeviceFunctionality("VK_KHR_depth_stencil_resolve");
238     if (m_config.imageLayers > 1)
239         m_context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
240 
241     if (m_config.separateDepthStencilLayouts)
242         m_context.requireDeviceFunctionality("VK_KHR_separate_depth_stencil_layouts");
243 
244     VkPhysicalDeviceDepthStencilResolveProperties dsResolveProperties;
245     deMemset(&dsResolveProperties, 0, sizeof(VkPhysicalDeviceDepthStencilResolveProperties));
246     dsResolveProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES;
247     dsResolveProperties.pNext = DE_NULL;
248 
249     VkPhysicalDeviceProperties2 deviceProperties;
250     deviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
251     deviceProperties.pNext = &dsResolveProperties;
252 
253     // perform query to get supported float control properties
254     const VkPhysicalDevice physicalDevice          = m_context.getPhysicalDevice();
255     const vk::InstanceInterface &instanceInterface = m_context.getInstanceInterface();
256     instanceInterface.getPhysicalDeviceProperties2(physicalDevice, &deviceProperties);
257 
258     // check if both modes are supported
259     VkResolveModeFlagBits depthResolveMode   = m_config.depthResolveMode;
260     VkResolveModeFlagBits stencilResolveMode = m_config.stencilResolveMode;
261 
262     if ((depthResolveMode != VK_RESOLVE_MODE_NONE) &&
263         !(depthResolveMode & dsResolveProperties.supportedDepthResolveModes))
264         TCU_THROW(NotSupportedError, "Depth resolve mode not supported");
265 
266     if ((stencilResolveMode != VK_RESOLVE_MODE_NONE) &&
267         !(stencilResolveMode & dsResolveProperties.supportedStencilResolveModes))
268         TCU_THROW(NotSupportedError, "Stencil resolve mode not supported");
269 
270     // check if the implementation supports setting the depth and stencil resolve
271     // modes to different values when one of those modes is VK_RESOLVE_MODE_NONE
272     if (dsResolveProperties.independentResolveNone)
273     {
274         if ((!dsResolveProperties.independentResolve) && (depthResolveMode != stencilResolveMode) &&
275             (depthResolveMode != VK_RESOLVE_MODE_NONE) && (stencilResolveMode != VK_RESOLVE_MODE_NONE))
276             TCU_THROW(NotSupportedError, "Implementation doesn't support diferent resolve modes");
277     }
278     else if (!dsResolveProperties.independentResolve && (depthResolveMode != stencilResolveMode))
279     {
280         // when independentResolveNone and independentResolve are VK_FALSE then both modes must be the same
281         TCU_THROW(NotSupportedError, "Implementation doesn't support diferent resolve modes");
282     }
283 
284     return true;
285 }
286 
sampleCountBitFromSampleCount(uint32_t count) const287 VkSampleCountFlagBits DepthStencilResolveTest::sampleCountBitFromSampleCount(uint32_t count) const
288 {
289     switch (count)
290     {
291     case 1:
292         return VK_SAMPLE_COUNT_1_BIT;
293     case 2:
294         return VK_SAMPLE_COUNT_2_BIT;
295     case 4:
296         return VK_SAMPLE_COUNT_4_BIT;
297     case 8:
298         return VK_SAMPLE_COUNT_8_BIT;
299     case 16:
300         return VK_SAMPLE_COUNT_16_BIT;
301     case 32:
302         return VK_SAMPLE_COUNT_32_BIT;
303     case 64:
304         return VK_SAMPLE_COUNT_64_BIT;
305 
306     default:
307         DE_FATAL("Invalid sample count");
308         return (VkSampleCountFlagBits)0x0;
309     }
310 }
311 
createImage(VkFormat vkformat,uint32_t sampleCount,VkImageUsageFlags additionalUsage)312 VkImageSp DepthStencilResolveTest::createImage(VkFormat vkformat, uint32_t sampleCount,
313                                                VkImageUsageFlags additionalUsage)
314 {
315     const tcu::TextureFormat format(mapVkFormat(m_config.format));
316     const VkImageTiling imageTiling(VK_IMAGE_TILING_OPTIMAL);
317     VkSampleCountFlagBits sampleCountBit(sampleCountBitFromSampleCount(sampleCount));
318     VkImageUsageFlags usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | additionalUsage;
319 
320     VkImageFormatProperties imageFormatProperties;
321     if (m_vki.getPhysicalDeviceImageFormatProperties(m_physicalDevice, m_config.format, VK_IMAGE_TYPE_2D, imageTiling,
322                                                      usage, 0u,
323                                                      &imageFormatProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
324     {
325         TCU_THROW(NotSupportedError, "Format not supported");
326     }
327     if (imageFormatProperties.sampleCounts < sampleCount)
328     {
329         TCU_THROW(NotSupportedError, "Sample count not supported");
330     }
331     if (imageFormatProperties.maxArrayLayers < m_config.imageLayers)
332     {
333         TCU_THROW(NotSupportedError, "Layers count not supported");
334     }
335 
336     const VkExtent3D imageExtent = {m_config.width, m_config.height, 1u};
337 
338     if (!(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order)))
339         TCU_THROW(NotSupportedError, "Format can't be used as depth/stencil attachment");
340 
341     if (imageFormatProperties.maxExtent.width < imageExtent.width ||
342         imageFormatProperties.maxExtent.height < imageExtent.height ||
343         ((imageFormatProperties.sampleCounts & sampleCountBit) == 0) ||
344         imageFormatProperties.maxArrayLayers < m_config.imageLayers)
345     {
346         TCU_THROW(NotSupportedError, "Image type not supported");
347     }
348 
349     const VkImageCreateInfo pCreateInfo = {
350         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType          sType
351         DE_NULL,                             // const void*              pNext
352         0u,                                  // VkImageCreateFlags       flags
353         VK_IMAGE_TYPE_2D,                    // VkImageType              imageType
354         vkformat,                            // VkFormat                 format
355         imageExtent,                         // VkExtent3D               extent
356         1u,                                  // uint32_t                 mipLevels
357         m_config.imageLayers,                // uint32_t                 arrayLayers
358         sampleCountBit,                      // VkSampleCountFlagBits    samples
359         imageTiling,                         // VkImageTiling            tiling
360         usage,                               // VkImageUsageFlags        usage
361         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode            sharingMode
362         0u,                                  // uint32_t                 queueFamilyIndexCount
363         DE_NULL,                             // const uint32_t*          pQueueFamilyIndices
364         VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout            initialLayout
365     };
366 
367     return safeSharedPtr(new Unique<VkImage>(vk::createImage(m_vkd, m_device, &pCreateInfo)));
368 }
369 
createImageMemory(VkImageSp image)370 AllocationSp DepthStencilResolveTest::createImageMemory(VkImageSp image)
371 {
372     Allocator &allocator = m_context.getDefaultAllocator();
373 
374     de::MovePtr<Allocation> allocation(
375         allocator.allocate(getImageMemoryRequirements(m_vkd, m_device, **image), MemoryRequirement::Any));
376     VK_CHECK(m_vkd.bindImageMemory(m_device, **image, allocation->getMemory(), allocation->getOffset()));
377     return safeSharedPtr(allocation.release());
378 }
379 
createImageView(VkImageSp image,VkFormat vkformat,uint32_t baseArrayLayer)380 VkImageViewSp DepthStencilResolveTest::createImageView(VkImageSp image, VkFormat vkformat, uint32_t baseArrayLayer)
381 {
382     const VkImageSubresourceRange range = {
383         aspectFlagsForFormat(vkformat), // VkImageAspectFlags    aspectMask
384         0u,                             // uint32_t              baseMipLevel
385         1u,                             // uint32_t              levelCount
386         baseArrayLayer,                 // uint32_t              baseArrayLayer
387         m_config.viewLayers             // uint32_t              layerCount
388     };
389 
390     const VkImageViewCreateInfo pCreateInfo = {
391         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType            sType
392         DE_NULL,                                  // const void*                pNext
393         0u,                                       // VkImageViewCreateFlags     flags
394         **image,                                  // VkImage                    image
395         (m_config.viewLayers > 1) ? VK_IMAGE_VIEW_TYPE_2D_ARRAY :
396                                     VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType            viewType
397         vkformat,                                          // VkFormat                   format
398         makeComponentMappingRGBA(),                        // VkComponentMapping         components
399         range,                                             // VkImageSubresourceRange    subresourceRange
400     };
401     return safeSharedPtr(new Unique<VkImageView>(vk::createImageView(m_vkd, m_device, &pCreateInfo)));
402 }
403 
createRenderPipelineLayout(void)404 Move<VkPipelineLayout> DepthStencilResolveTest::createRenderPipelineLayout(void)
405 {
406     VkPushConstantRange pushConstant = {
407         VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags    stageFlags
408         0u,                           // uint32_t              offset
409         4u                            // uint32_t              size
410     };
411 
412     uint32_t pushConstantRangeCount          = 0u;
413     VkPushConstantRange *pPushConstantRanges = DE_NULL;
414     if (m_config.verifyBuffer == VB_STENCIL)
415     {
416         pushConstantRangeCount = 1u;
417         pPushConstantRanges    = &pushConstant;
418     }
419 
420     const VkPipelineLayoutCreateInfo createInfo = {
421         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType                 sType
422         DE_NULL,                                       // const void*                     pNext
423         (vk::VkPipelineLayoutCreateFlags)0,            // VkPipelineLayoutCreateFlags     flags
424         0u,                                            // uint32_t                        setLayoutCount
425         DE_NULL,                                       // const VkDescriptorSetLayout*    pSetLayouts
426         pushConstantRangeCount,                        // uint32_t                        pushConstantRangeCount
427         pPushConstantRanges                            // const VkPushConstantRange*      pPushConstantRanges
428     };
429 
430     return vk::createPipelineLayout(m_vkd, m_device, &createInfo);
431 }
432 
createRenderPipeline(VkFormat format,VkPipelineLayout renderPipelineLayout)433 Move<VkPipeline> DepthStencilResolveTest::createRenderPipeline(VkFormat format, VkPipelineLayout renderPipelineLayout)
434 {
435     const bool testingStencil                    = (m_config.verifyBuffer == VB_STENCIL);
436     const vk::BinaryCollection &binaryCollection = m_context.getBinaryCollection();
437 
438     const Unique<VkShaderModule> vertexShaderModule(
439         createShaderModule(m_vkd, m_device, binaryCollection.get("quad-vert"), 0u));
440     const Unique<VkShaderModule> fragmentShaderModule(
441         createShaderModule(m_vkd, m_device, binaryCollection.get("quad-frag"), 0u));
442     const Move<VkShaderModule> geometryShaderModule(
443         m_config.imageLayers == 1 ? Move<VkShaderModule>() :
444                                     createShaderModule(m_vkd, m_device, binaryCollection.get("quad-geom"), 0u));
445 
446     const VkPipelineVertexInputStateCreateInfo vertexInputState = {
447         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType                             sType
448         DE_NULL,                                                   // const void*                                 pNext
449         (VkPipelineVertexInputStateCreateFlags)0u,                 // VkPipelineVertexInputStateCreateFlags       flags
450         0u,      // uint32_t                                    vertexBindingDescriptionCount
451         DE_NULL, // const VkVertexInputBindingDescription*      pVertexBindingDescriptions
452         0u,      // uint32_t                                    vertexAttributeDescriptionCount
453         DE_NULL  // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
454     };
455     const tcu::UVec2 view(m_config.width, m_config.height);
456     const std::vector<VkViewport> viewports(1, makeViewport(view));
457     const std::vector<VkRect2D> scissors(1, m_config.renderArea);
458 
459     const VkPipelineMultisampleStateCreateInfo multisampleState = {
460         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
461         DE_NULL,
462         (VkPipelineMultisampleStateCreateFlags)0u,
463         sampleCountBitFromSampleCount(m_config.sampleCount),
464         VK_FALSE,
465         0.0f,
466         DE_NULL,
467         VK_FALSE,
468         VK_FALSE,
469     };
470     const VkPipelineDepthStencilStateCreateInfo depthStencilState = {
471         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
472         DE_NULL,
473         (VkPipelineDepthStencilStateCreateFlags)0u,
474 
475         VK_TRUE, // depthTestEnable
476         VK_TRUE,
477         VK_COMPARE_OP_ALWAYS,
478         VK_FALSE,
479         testingStencil, // stencilTestEnable
480         {
481             VK_STENCIL_OP_REPLACE, // failOp
482             VK_STENCIL_OP_REPLACE, // passOp
483             VK_STENCIL_OP_REPLACE, // depthFailOp
484             VK_COMPARE_OP_ALWAYS,  // compareOp
485             0xFFu,                 // compareMask
486             0xFFu,                 // writeMask
487             1                      // reference
488         },
489         {VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE, VK_COMPARE_OP_ALWAYS, 0xFFu, 0xFFu, 1},
490         0.0f,
491         1.0f};
492 
493     std::vector<VkDynamicState> dynamicState;
494     dynamicState.push_back(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
495     const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
496         VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType                      sType
497         DE_NULL,                                              // const void*                          pNext
498         (VkPipelineDynamicStateCreateFlags)0u,                // VkPipelineDynamicStateCreateFlags    flags
499         static_cast<uint32_t>(dynamicState.size()),           // uint32_t                             dynamicStateCount
500         &dynamicState[0]                                      // const VkDynamicState*                pDynamicStates
501     };
502 
503     VkPipelineRenderingCreateInfoKHR dynamicRenderingInfo = {
504         VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, // VkStructureType    sType;
505         DE_NULL,                                          // const void*        pNext;
506         0,                                                // uint32_t           viewMask;
507         0,                                                // uint32_t           colorAttachmentCount;
508         DE_NULL,                                          // const VkFormat*    pColorAttachmentFormats;
509         VK_FORMAT_UNDEFINED,                              // VkFormat           depthAttachmentFormat;
510         VK_FORMAT_UNDEFINED                               // VkFormat           stencilAttachmentFormat;
511     };
512     const tcu::TextureFormat deFormat(mapVkFormat(format));
513     if (tcu::hasDepthComponent(deFormat.order) && m_config.verifyBuffer == VB_DEPTH)
514         dynamicRenderingInfo.depthAttachmentFormat = format;
515     if (tcu::hasStencilComponent(deFormat.order) && m_config.verifyBuffer != VB_DEPTH)
516         dynamicRenderingInfo.stencilAttachmentFormat = format;
517 
518     return makeGraphicsPipeline(
519         m_vkd,                // const DeviceInterface&                        vk
520         m_device,             // const VkDevice                                device
521         renderPipelineLayout, // const VkPipelineLayout                        pipelineLayout
522         *vertexShaderModule,  // const VkShaderModule                          vertexShaderModule
523         DE_NULL,              // const VkShaderModule                          tessellationControlShaderModule
524         DE_NULL,              // const VkShaderModule                          tessellationEvalShaderModule
525         m_config.imageLayers == 1 ?
526             DE_NULL :
527             *geometryShaderModule,           // const VkShaderModule                          geometryShaderModule
528         *fragmentShaderModule,               // const VkShaderModule                          fragmentShaderModule
529         VK_NULL_HANDLE,                      // const VkRenderPass                            renderPass
530         viewports,                           // const std::vector<VkViewport>&                viewports
531         scissors,                            // const std::vector<VkRect2D>&                  scissors
532         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology                     topology
533         0u,                                  // const uint32_t                                subpass
534         0u,                                  // const uint32_t                                patchControlPoints
535         &vertexInputState,                   // const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
536         DE_NULL,            // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
537         &multisampleState,  // const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
538         &depthStencilState, // const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
539         DE_NULL,            // const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo
540         testingStencil ? &dynamicStateCreateInfo :
541                          DE_NULL,               // const VkPipelineDynamicStateCreateInfo*       dynamicStateCreateInfo
542         &dynamicRenderingInfo,                  // const void*                                   pNext
543         static_cast<VkPipelineCreateFlags>(0)); // const VkPipelineCreateFlags                   pipelineCreateFlags
544 }
545 
createBufferMemory(void)546 AllocationSp DepthStencilResolveTest::createBufferMemory(void)
547 {
548     Allocator &allocator = m_context.getDefaultAllocator();
549     de::MovePtr<Allocation> allocation(
550         allocator.allocate(getBufferMemoryRequirements(m_vkd, m_device, **m_buffer), MemoryRequirement::HostVisible));
551     VK_CHECK(m_vkd.bindBufferMemory(m_device, **m_buffer, allocation->getMemory(), allocation->getOffset()));
552     return safeSharedPtr(allocation.release());
553 }
554 
createBuffer(void)555 VkBufferSp DepthStencilResolveTest::createBuffer(void)
556 {
557     const VkBufferUsageFlags bufferUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
558     const tcu::TextureFormat textureFormat(mapVkFormat(m_config.format));
559     const VkDeviceSize pixelSize(textureFormat.getPixelSize());
560     const VkBufferCreateInfo createInfo = {
561         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                                // VkStructureType        sType
562         DE_NULL,                                                             // const void*            pNext
563         0u,                                                                  // VkBufferCreateFlags    flags
564         m_config.width * m_config.height * m_config.imageLayers * pixelSize, // VkDeviceSize           size
565         bufferUsage,                                                         // VkBufferUsageFlags     usage
566         VK_SHARING_MODE_EXCLUSIVE,                                           // VkSharingMode          sharingMode
567         0u,     // uint32_t               queueFamilyIndexCount
568         DE_NULL // const uint32_t*        pQueueFamilyIndices
569     };
570     return safeSharedPtr(new Unique<VkBuffer>(vk::createBuffer(m_vkd, m_device, &createInfo)));
571 }
572 
573 #ifndef CTS_USES_VULKANSC
beginSecondaryCommandBuffer(VkCommandBuffer cmdBuffer,VerifyBuffer attachmentType,VkRenderingFlagsKHR renderingFlags) const574 void DepthStencilResolveTest::beginSecondaryCommandBuffer(VkCommandBuffer cmdBuffer, VerifyBuffer attachmentType,
575                                                           VkRenderingFlagsKHR renderingFlags) const
576 {
577     const DeviceInterface &vkd = m_context.getDeviceInterface();
578     VkFormat depthFormat       = attachmentType == VB_DEPTH ? m_config.format : VK_FORMAT_UNDEFINED;
579     VkFormat stencilFormat     = attachmentType == VB_STENCIL ? m_config.format : VK_FORMAT_UNDEFINED;
580 
581     VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
582         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType                    sType
583         DE_NULL,                                                         // const void*                        pNext
584         renderingFlags,                                                  // VkRenderingFlagsKHR                flags
585         0u,                                                              // uint32_t                            viewMask
586         0u,            // uint32_t                            colorAttachmentCount
587         DE_NULL,       // const VkFormat*                    pColorAttachmentFormats
588         depthFormat,   // VkFormat                            depthAttachmentFormat
589         stencilFormat, // VkFormat                            stencilAttachmentFormat
590         sampleCountBitFromSampleCount(m_config.sampleCount) // VkSampleCountFlagBits            rasterizationSamples
591     };
592 
593     const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
594     VkCommandBufferUsageFlags usageFlags                       = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
595     if (!m_config.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
596         usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
597 
598     const VkCommandBufferBeginInfo commandBufBeginParams{
599         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType                            sType
600         DE_NULL,                                     // const void*                                pNext
601         usageFlags,                                  // VkCommandBufferUsageFlags                flags
602         &bufferInheritanceInfo,                      // const VkCommandBufferInheritanceInfo*    pInheritanceInfo
603     };
604 
605     VK_CHECK(vkd.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
606 }
607 #endif // CTS_USES_VULKANSC
608 
submit(void)609 void DepthStencilResolveTest::submit(void)
610 {
611     const DeviceInterface &vkd(m_context.getDeviceInterface());
612     const VkDevice device(m_context.getDevice());
613     const Unique<VkCommandBuffer> cmdBuffer(
614         allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
615     Move<VkCommandBuffer> secCmdBuffer;
616 
617     const vk::VkImageSubresourceRange imageRange = {
618         aspectFlagsForFormat(m_config.format), // VkImageAspectFlags    aspectMask
619         0u,                                    // uint32_t              baseMipLevel
620         VK_REMAINING_MIP_LEVELS,               // uint32_t              levelCount
621         0u,                                    // uint32_t              baseArrayLayer
622         VK_REMAINING_ARRAY_LAYERS,             // uint32_t              layerCount
623     };
624 
625     const VkImageMemoryBarrier preClearBarrier = {
626         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType            sType
627         DE_NULL,                                // const void*                pNext
628         VK_ACCESS_NONE_KHR,                     // VkAccessFlags              srcAccessMask
629         VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags              dstAccessMask
630         VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout              oldLayout
631         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout              newLayout
632         VK_QUEUE_FAMILY_IGNORED,                // uint32_t                   srcQueueFamilyIndex
633         VK_QUEUE_FAMILY_IGNORED,                // uint32_t                   dstQueueFamilyIndex
634         **m_singlesampleImage,                  // VkImage                    image
635         imageRange,                             // VkImageSubresourceRange    subresourceRange
636     };
637 
638     const VkImageMemoryBarrier preRenderBarrier = {
639         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,           // VkStructureType            sType
640         DE_NULL,                                          // const void*                pNext
641         VK_ACCESS_TRANSFER_WRITE_BIT,                     // VkAccessFlags              srcAccessMask
642         VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,     // VkAccessFlags              dstAccessMask
643         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,             // VkImageLayout              oldLayout
644         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout              newLayout
645         VK_QUEUE_FAMILY_IGNORED,                          // uint32_t                   srcQueueFamilyIndex
646         VK_QUEUE_FAMILY_IGNORED,                          // uint32_t                   dstQueueFamilyIndex
647         **m_singlesampleImage,                            // VkImage                    image
648         imageRange,                                       // VkImageSubresourceRange    subresourceRange
649     };
650 
651     // Clearing resolve image
652     {
653         const Unique<VkCommandBuffer> clearCmdBuffer(
654             allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
655 
656         beginCommandBuffer(vkd, *clearCmdBuffer);
657         vkd.cmdPipelineBarrier(*clearCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
658                                0u, DE_NULL, 0u, DE_NULL, 1u, &preClearBarrier);
659 
660         vkd.cmdClearDepthStencilImage(*clearCmdBuffer, **m_singlesampleImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
661                                       &m_config.clearValue, 1u, &imageRange);
662         endCommandBuffer(vkd, *clearCmdBuffer);
663 
664         vk::submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *clearCmdBuffer);
665     }
666 
667     bool testingDepth = (m_config.verifyBuffer == VB_DEPTH);
668     if (testingDepth)
669     {
670         // Begin rendering
671         VkClearValue clearVal;
672         clearVal.depthStencil = m_config.clearValue;
673 
674         const VkRenderingAttachmentInfo depthAttachment = {
675             VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,      // VkStructureType          sType
676             DE_NULL,                                          // const void*              pNext
677             **m_multisampleImageView,                         // VkImageView              imageView
678             VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout            imageLayout
679             m_config.depthResolveMode,                        // VkResolveModeFlagBits    resolveMode
680             **m_singlesampleImageView,                        // VkImageView              resolveImageView
681             VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout            resolveImageLayout
682             VK_ATTACHMENT_LOAD_OP_CLEAR,                      // VkAttachmentLoadOp       loadOp
683             VK_ATTACHMENT_STORE_OP_STORE,                     // VkAttachmentStoreOp      storeOp
684             clearVal                                          // VkClearValue             clearValue
685         };
686 
687         VkRenderingInfoKHR renderingInfo = {
688             VK_STRUCTURE_TYPE_RENDERING_INFO, // VkStructureType                     sType
689             DE_NULL,                          // const void*                         pNext
690             static_cast<VkRenderingFlags>(0), // VkRenderingFlags                    flags
691             {
692                 // VkRect2D                            renderArea
693                 {0u, 0u},                         // VkOffset2D    offset;
694                 {m_config.width, m_config.height} // VkExtent2D    extent
695             },
696             m_config.viewLayers, // uint32_t                            layerCount
697             0,                   // uint32_t                            viewMask
698             0,                   // uint32_t                            colorAttachmentCount
699             DE_NULL,             // const VkRenderingAttachmentInfo*    pColorAttachments
700             &depthAttachment,    // const VkRenderingAttachmentInfo*    pDepthAttachment
701             DE_NULL              // const VkRenderingAttachmentInfo*    pStencilAttachment
702         };
703 
704         if (m_config.groupParams->useSecondaryCmdBuffer)
705         {
706             secCmdBuffer = allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
707 
708             // Record secondary command buffer
709             if (m_config.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
710             {
711                 beginSecondaryCommandBuffer(*secCmdBuffer, VB_DEPTH,
712                                             VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
713                 vkd.cmdBeginRendering(*secCmdBuffer, &renderingInfo);
714             }
715             else
716                 beginSecondaryCommandBuffer(*secCmdBuffer, VB_DEPTH);
717 
718             vkd.cmdBindPipeline(*secCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
719             vkd.cmdDraw(*secCmdBuffer, 6u, 1u, 0u, 0u);
720 
721             if (m_config.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
722                 vkd.cmdEndRendering(*secCmdBuffer);
723 
724             vk::endCommandBuffer(vkd, *secCmdBuffer);
725 
726             // Record primary command buffer
727             beginCommandBuffer(vkd, *cmdBuffer);
728             vkd.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
729                                    vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
730                                        vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
731                                    0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preRenderBarrier);
732 
733             if (!m_config.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
734             {
735                 renderingInfo.flags = vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
736                 vkd.cmdBeginRendering(*cmdBuffer, &renderingInfo);
737             }
738             vkd.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
739 
740             if (!m_config.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
741                 vkd.cmdEndRendering(*cmdBuffer);
742         }
743         else
744         {
745             // Record primary command buffer
746             beginCommandBuffer(vkd, *cmdBuffer);
747             vkd.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
748                                    vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
749                                        vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
750                                    0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preRenderBarrier);
751             vkd.cmdBeginRendering(*cmdBuffer, &renderingInfo);
752             vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
753             vkd.cmdDraw(*cmdBuffer, 6u, 1u, 0u, 0u);
754             vkd.cmdEndRendering(*cmdBuffer);
755         }
756     }
757     else
758     {
759         beginCommandBuffer(vkd, *cmdBuffer);
760         vkd.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
761                                vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
762                                    vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
763                                0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preRenderBarrier);
764         if (m_config.groupParams->useSecondaryCmdBuffer)
765         {
766             secCmdBuffer = allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
767 
768             for (uint32_t i = 0; i < m_config.sampleCount; i++)
769             {
770                 if (i == 0)
771                 {
772                     // Begin rendering
773                     VkClearValue clearVal;
774                     clearVal.depthStencil = m_config.clearValue;
775 
776                     const VkRenderingAttachmentInfo stencilAttachment = {
777                         VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,      // VkStructureType          sType
778                         DE_NULL,                                          // const void*              pNext
779                         **m_multisampleImageView,                         // VkImageView              imageView
780                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout            imageLayout
781                         m_config.stencilResolveMode,                      // VkResolveModeFlagBits    resolveMode
782                         **m_singlesampleImageView,                        // VkImageView              resolveImageView
783                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout            resolveImageLayout
784                         VK_ATTACHMENT_LOAD_OP_CLEAR,                      // VkAttachmentLoadOp       loadOp
785                         VK_ATTACHMENT_STORE_OP_STORE,                     // VkAttachmentStoreOp      storeOp
786                         clearVal                                          // VkClearValue             clearValue
787                     };
788 
789                     VkRenderingInfoKHR renderingInfo = {
790                         VK_STRUCTURE_TYPE_RENDERING_INFO, // VkStructureType                     sType
791                         DE_NULL,                          // const void*                         pNext
792                         static_cast<VkRenderingFlags>(0), // VkRenderingFlags                    flags
793                         {
794                             // VkRect2D                            renderArea
795                             {0u, 0u},                         // VkOffset2D    offset;
796                             {m_config.width, m_config.height} // VkExtent2D    extent
797                         },
798                         m_config.viewLayers, // uint32_t                            layerCount
799                         0,                   // uint32_t                            viewMask
800                         0,                   // uint32_t                            colorAttachmentCount
801                         DE_NULL,             // const VkRenderingAttachmentInfo*    pColorAttachments
802                         DE_NULL,             // const VkRenderingAttachmentInfo*    pDepthAttachment
803                         &stencilAttachment   // const VkRenderingAttachmentInfo*    pStencilAttachment
804                     };
805 
806                     vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
807                                            VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, 0, 0, 0, 0, 0);
808 
809                     if (m_config.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
810                         beginSecondaryCommandBuffer(*secCmdBuffer, VB_STENCIL,
811                                                     VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
812                     else
813                         beginSecondaryCommandBuffer(*secCmdBuffer, VB_STENCIL);
814 
815                     // Record secondary command buffer
816                     if (m_config.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
817                     {
818                         vkd.cmdBeginRendering(*secCmdBuffer, &renderingInfo);
819                     }
820                     else
821                     {
822                         renderingInfo.flags = vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
823                         vkd.cmdBeginRendering(*cmdBuffer, &renderingInfo);
824                     }
825                 }
826 
827                 // For stencil we can set reference value for just one sample at a time
828                 // so we need to do as many passes as there are samples, first half
829                 // of samples is initialized with 1 and second half with 255
830 
831                 const uint32_t halfOfSamples    = m_config.sampleCount >> 1;
832                 const uint32_t stencilReference = 1 + 254 * (i >= halfOfSamples);
833 
834                 vkd.cmdBindPipeline(*secCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
835                 vkd.cmdPushConstants(*secCmdBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u,
836                                      sizeof(i), &i);
837                 vkd.cmdSetStencilReference(*secCmdBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, stencilReference);
838                 vkd.cmdDraw(*secCmdBuffer, 6u, 1u, 0u, 0u);
839                 if (i == m_config.sampleCount - 1)
840                 {
841                     if (m_config.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
842                         vkd.cmdEndRendering(*secCmdBuffer);
843                     vk::endCommandBuffer(vkd, *secCmdBuffer);
844                     vkd.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
845                     if (!m_config.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
846                         vkd.cmdEndRendering(*cmdBuffer);
847                 }
848             }
849         }
850         else
851         {
852             for (uint32_t i = 0; i < m_config.sampleCount; i++)
853             {
854                 if (i == 0)
855                 {
856                     // Begin rendering
857                     VkClearValue clearVal;
858                     clearVal.depthStencil = m_config.clearValue;
859 
860                     const VkRenderingAttachmentInfo stencilAttachment = {
861                         VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,      // VkStructureType          sType
862                         DE_NULL,                                          // const void*              pNext
863                         **m_multisampleImageView,                         // VkImageView              imageView
864                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout            imageLayout
865                         m_config.stencilResolveMode,                      // VkResolveModeFlagBits    resolveMode
866                         **m_singlesampleImageView,                        // VkImageView              resolveImageView
867                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout            resolveImageLayout
868                         VK_ATTACHMENT_LOAD_OP_CLEAR,                      // VkAttachmentLoadOp       loadOp
869                         VK_ATTACHMENT_STORE_OP_STORE,                     // VkAttachmentStoreOp      storeOp
870                         clearVal                                          // VkClearValue             clearValue
871                     };
872 
873                     VkRenderingInfoKHR renderingInfo = {
874                         VK_STRUCTURE_TYPE_RENDERING_INFO, // VkStructureType                     sType
875                         DE_NULL,                          // const void*                         pNext
876                         static_cast<VkRenderingFlags>(0), // VkRenderingFlags                    flags
877                         {
878                             // VkRect2D                            renderArea
879                             {0u, 0u},                         // VkOffset2D    offset
880                             {m_config.width, m_config.height} // VkExtent2D    extent
881                         },
882                         m_config.viewLayers, // uint32_t                            layerCount
883                         0,                   // uint32_t                            viewMask
884                         0,                   // uint32_t                            colorAttachmentCount
885                         DE_NULL,             // const VkRenderingAttachmentInfo*    pColorAttachments
886                         DE_NULL,             // const VkRenderingAttachmentInfo*    pDepthAttachment
887                         &stencilAttachment   // const VkRenderingAttachmentInfo*    pStencilAttachment
888                     };
889 
890                     vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
891                                            VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, 0, 0, 0, 0, 0);
892                     vkd.cmdBeginRendering(*cmdBuffer, &renderingInfo);
893                 }
894 
895                 // For stencil we can set reference value for just one sample at a time
896                 // so we need to do as many passes as there are samples, first half
897                 // of samples is initialized with 1 and second half with 255
898 
899                 const uint32_t halfOfSamples = m_config.sampleCount >> 1;
900                 uint32_t stencilReference    = 1 + 254 * (i >= halfOfSamples);
901                 vkd.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
902                 vkd.cmdPushConstants(*cmdBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(i),
903                                      &i);
904                 vkd.cmdSetStencilReference(*cmdBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, stencilReference);
905                 vkd.cmdDraw(*cmdBuffer, 6u, 1u, 0u, 0u);
906                 if (i == m_config.sampleCount - 1)
907                     vkd.cmdEndRendering(*cmdBuffer);
908             }
909         }
910     }
911 
912     // Memory barriers between rendering and copying
913     {
914         const VkImageMemoryBarrier barrier = {
915             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
916             DE_NULL,
917 
918             // Note: as per the spec, depth/stencil *resolve* operations are synchronized using the color attachment write access.
919             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
920             VK_ACCESS_TRANSFER_READ_BIT,
921 
922             VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
923             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
924 
925             VK_QUEUE_FAMILY_IGNORED,
926             VK_QUEUE_FAMILY_IGNORED,
927 
928             **m_singlesampleImage,
929             {(m_config.separateDepthStencilLayouts) ?
930                  VkImageAspectFlags(testingDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT) :
931                  aspectFlagsForFormat(m_config.format),
932              0u, 1u, 0u, m_config.viewLayers}};
933 
934         vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
935                                DE_NULL, 0u, DE_NULL, 1u, &barrier);
936     }
937 
938     // Copy image memory to buffers
939     const VkBufferImageCopy region = {
940         0u,
941         0u,
942         0u,
943         {
944             VkImageAspectFlags(testingDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT),
945             0u,
946             0u,
947             m_config.viewLayers,
948         },
949         {0u, 0u, 0u},
950         {m_config.width, m_config.height, 1u}};
951 
952     vkd.cmdCopyImageToBuffer(*cmdBuffer, **m_singlesampleImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_buffer, 1u,
953                              &region);
954 
955     // Memory barriers between copies and host access
956     {
957         const VkBufferMemoryBarrier barrier = {VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
958                                                DE_NULL,
959 
960                                                VK_ACCESS_TRANSFER_WRITE_BIT,
961                                                VK_ACCESS_HOST_READ_BIT,
962 
963                                                VK_QUEUE_FAMILY_IGNORED,
964                                                VK_QUEUE_FAMILY_IGNORED,
965 
966                                                **m_buffer,
967                                                0u,
968                                                VK_WHOLE_SIZE};
969 
970         vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL,
971                                1u, &barrier, 0u, DE_NULL);
972     }
973 
974     vk::endCommandBuffer(vkd, *cmdBuffer);
975 
976     vk::submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *cmdBuffer);
977 }
978 
verifyDepth(void)979 bool DepthStencilResolveTest::verifyDepth(void)
980 {
981     // Invalidate allocation before attempting to read buffer memory.
982     invalidateAlloc(m_context.getDeviceInterface(), m_context.getDevice(), *m_bufferMemory);
983 
984     uint32_t layerSize   = m_config.width * m_config.height;
985     uint32_t valuesCount = layerSize * m_config.viewLayers;
986     uint8_t *pixelPtr    = static_cast<uint8_t *>(m_bufferMemory->getHostPtr());
987 
988     const DeviceInterface &vkd(m_context.getDeviceInterface());
989     invalidateMappedMemoryRange(vkd, m_context.getDevice(), m_bufferMemory->getMemory(), m_bufferMemory->getOffset(),
990                                 VK_WHOLE_SIZE);
991 
992     float expectedValue = m_config.depthExpectedValue;
993     if (m_config.depthResolveMode == VK_RESOLVE_MODE_NONE)
994         expectedValue = m_config.clearValue.depth;
995 
996     // depth data in buffer is tightly packed, ConstPixelBufferAccess
997     // coludn't be used for depth value extraction as it cant interpret
998     // formats containing just depth component
999 
1000     typedef float (*DepthComponentGetterFn)(uint8_t *);
1001     VkFormat format                          = m_config.format;
1002     DepthComponentGetterFn getDepthComponent = &get16bitDepthComponent;
1003     uint32_t pixelStep                       = 2;
1004     float epsilon                            = 0.002f;
1005 
1006     if ((format == VK_FORMAT_X8_D24_UNORM_PACK32) || (format == VK_FORMAT_D24_UNORM_S8_UINT))
1007     {
1008         getDepthComponent = &get24bitDepthComponent;
1009         pixelStep         = 4;
1010     }
1011     else if ((format == VK_FORMAT_D32_SFLOAT) || (format == VK_FORMAT_D32_SFLOAT_S8_UINT))
1012     {
1013         getDepthComponent = &get32bitDepthComponent;
1014         pixelStep         = 4;
1015     }
1016 
1017     for (uint32_t valueIndex = 0; valueIndex < valuesCount; valueIndex++)
1018     {
1019         float depth = (*getDepthComponent)(pixelPtr);
1020         pixelPtr += pixelStep;
1021 
1022         // check if pixel data is outside of render area
1023         int32_t layerIndex   = valueIndex / layerSize;
1024         int32_t inLayerIndex = valueIndex % layerSize;
1025         int32_t x            = inLayerIndex % m_config.width;
1026         int32_t y            = (inLayerIndex - x) / m_config.width;
1027         int32_t x1           = m_config.renderArea.offset.x;
1028         int32_t y1           = m_config.renderArea.offset.y;
1029         int32_t x2           = x1 + m_config.renderArea.extent.width;
1030         int32_t y2           = y1 + m_config.renderArea.extent.height;
1031         if ((x < x1) || (x >= x2) || (y < y1) || (y >= y2))
1032         {
1033             // verify that outside of render area there are clear values
1034             float error = deFloatAbs(depth - m_config.clearValue.depth);
1035             if (error > epsilon)
1036             {
1037                 m_context.getTestContext().getLog()
1038                     << TestLog::Message << "(" << x << ", " << y << ", layer: " << layerIndex
1039                     << ") is outside of render area but depth value is: " << depth << " (expected "
1040                     << m_config.clearValue.depth << ")" << TestLog::EndMessage;
1041                 return false;
1042             }
1043 
1044             // value is correct, go to next one
1045             continue;
1046         }
1047 
1048         float error = deFloatAbs(depth - expectedValue);
1049         if (error > epsilon)
1050         {
1051             m_context.getTestContext().getLog()
1052                 << TestLog::Message << "At (" << x << ", " << y << ", layer: " << layerIndex
1053                 << ") depth value is: " << depth << " expected: " << expectedValue << TestLog::EndMessage;
1054             return false;
1055         }
1056     }
1057     m_context.getTestContext().getLog() << TestLog::Message << "Depth value is " << expectedValue
1058                                         << TestLog::EndMessage;
1059 
1060     return true;
1061 }
1062 
verifyStencil(void)1063 bool DepthStencilResolveTest::verifyStencil(void)
1064 {
1065     // Invalidate allocation before attempting to read buffer memory.
1066     invalidateAlloc(m_context.getDeviceInterface(), m_context.getDevice(), *m_bufferMemory);
1067 
1068     uint32_t layerSize   = m_config.width * m_config.height;
1069     uint32_t valuesCount = layerSize * m_config.viewLayers;
1070     uint8_t *pixelPtr    = static_cast<uint8_t *>(m_bufferMemory->getHostPtr());
1071 
1072     const DeviceInterface &vkd(m_context.getDeviceInterface());
1073     invalidateMappedMemoryRange(vkd, m_context.getDevice(), m_bufferMemory->getMemory(), m_bufferMemory->getOffset(),
1074                                 VK_WHOLE_SIZE);
1075 
1076     // when stencil is tested we are discarding invocations and
1077     // because of that depth and stencil need to be tested separately
1078 
1079     uint8_t expectedValue = m_config.stencilExpectedValue;
1080     if (m_config.stencilResolveMode == VK_RESOLVE_MODE_NONE)
1081         expectedValue = static_cast<uint8_t>(m_config.clearValue.stencil);
1082 
1083     for (uint32_t valueIndex = 0; valueIndex < valuesCount; valueIndex++)
1084     {
1085         uint8_t stencil      = *pixelPtr++;
1086         int32_t layerIndex   = valueIndex / layerSize;
1087         int32_t inLayerIndex = valueIndex % layerSize;
1088         int32_t x            = inLayerIndex % m_config.width;
1089         int32_t y            = (inLayerIndex - x) / m_config.width;
1090         int32_t x1           = m_config.renderArea.offset.x;
1091         int32_t y1           = m_config.renderArea.offset.y;
1092         int32_t x2           = x1 + m_config.renderArea.extent.width;
1093         int32_t y2           = y1 + m_config.renderArea.extent.height;
1094         if ((x < x1) || (x >= x2) || (y < y1) || (y >= y2))
1095         {
1096             if (stencil != m_config.clearValue.stencil)
1097             {
1098                 m_context.getTestContext().getLog()
1099                     << TestLog::Message << "(" << x << ", " << y << ", layer: " << layerIndex
1100                     << ") is outside of render area but stencil value is: " << stencil << " (expected "
1101                     << m_config.clearValue.stencil << ")" << TestLog::EndMessage;
1102                 return false;
1103             }
1104 
1105             // value is correct, go to next one
1106             continue;
1107         }
1108 
1109         if (stencil != expectedValue)
1110         {
1111             m_context.getTestContext().getLog()
1112                 << TestLog::Message << "At (" << x << ", " << y << ", layer: " << layerIndex
1113                 << ") stencil value is: " << static_cast<uint32_t>(stencil)
1114                 << " expected: " << static_cast<uint32_t>(expectedValue) << TestLog::EndMessage;
1115             return false;
1116         }
1117     }
1118     m_context.getTestContext().getLog() << TestLog::Message << "Stencil value is "
1119                                         << static_cast<uint32_t>(expectedValue) << TestLog::EndMessage;
1120 
1121     return true;
1122 }
1123 
iterate(void)1124 tcu::TestStatus DepthStencilResolveTest::iterate(void)
1125 {
1126     submit();
1127 
1128     bool result = false;
1129     if (m_config.verifyBuffer == VB_DEPTH)
1130         result = verifyDepth();
1131     else
1132         result = verifyStencil();
1133 
1134     if (result)
1135         return tcu::TestStatus::pass("Pass");
1136     return tcu::TestStatus::fail("Fail");
1137 }
1138 
1139 struct Programs
1140 {
initvkt::renderpass::__anon1a64054d0111::Programs1141     void init(vk::SourceCollections &dst, TestConfig config) const
1142     {
1143         // geometry shader is only needed in multi-layer framebuffer resolve tests
1144         if (config.imageLayers > 1)
1145         {
1146             const uint32_t layerCount = 3;
1147 
1148             std::ostringstream src;
1149             src << "#version 450\n"
1150                 << "highp float;\n"
1151                 << "\n"
1152                 << "layout(triangles) in;\n"
1153                 << "layout(triangle_strip, max_vertices = " << 3 * 2 * layerCount << ") out;\n"
1154                 << "\n"
1155                 << "in gl_PerVertex {\n"
1156                 << "    vec4 gl_Position;\n"
1157                 << "} gl_in[];\n"
1158                 << "\n"
1159                 << "out gl_PerVertex {\n"
1160                 << "    vec4 gl_Position;\n"
1161                 << "};\n"
1162                 << "\n"
1163                 << "void main (void) {\n"
1164                 << "    for (int layerNdx = 0; layerNdx < " << layerCount << "; ++layerNdx) {\n"
1165                 << "        for(int vertexNdx = 0; vertexNdx < gl_in.length(); vertexNdx++) {\n"
1166                 << "            gl_Position = gl_in[vertexNdx].gl_Position;\n"
1167                 << "            gl_Layer    = layerNdx;\n"
1168                 << "            EmitVertex();\n"
1169                 << "        };\n"
1170                 << "        EndPrimitive();\n"
1171                 << "    };\n"
1172                 << "}\n";
1173 
1174             dst.glslSources.add("quad-geom") << glu::GeometrySource(src.str());
1175         }
1176 
1177         dst.glslSources.add("quad-vert") << glu::VertexSource(
1178             "#version 450\n"
1179             "out gl_PerVertex {\n"
1180             "\tvec4 gl_Position;\n"
1181             "};\n"
1182             "highp float;\n"
1183             "void main (void) {\n"
1184             "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
1185             "\t                   ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
1186             "}\n");
1187 
1188         if (config.verifyBuffer == VB_DEPTH)
1189         {
1190             dst.glslSources.add("quad-frag") << glu::FragmentSource(
1191                 "#version 450\n"
1192                 "precision highp float;\n"
1193                 "precision highp int;\n"
1194                 "void main (void)\n"
1195                 "{\n"
1196                 "  float sampleIndex = float(gl_SampleID);\n"          // sampleIndex is integer in range <0, 63>
1197                 "  float valueIndex = round(mod(sampleIndex, 4.0));\n" // limit possible depth values - count to 4
1198                 "  float value = valueIndex + 2.0;\n"                  // value is one of [2, 3, 4, 5]
1199                 "  value = round(exp2(value));\n"                      // value is one of [4, 8, 16, 32]
1200                 "  bool condition = (int(value) == 8);\n"            // select second sample value (to make it smallest)
1201                 "  value = round(value - float(condition) * 6.0);\n" // value is one of [4, 2, 16, 32]
1202                 "  gl_FragDepth = value / 100.0;\n"                  // sample depth is one of [0.04, 0.02, 0.16, 0.32]
1203                 "}\n");
1204         }
1205         else
1206         {
1207             dst.glslSources.add("quad-frag") << glu::FragmentSource("#version 450\n"
1208                                                                     "precision highp float;\n"
1209                                                                     "precision highp int;\n"
1210                                                                     "layout(push_constant) uniform PushConstant {\n"
1211                                                                     "  highp int sampleID;\n"
1212                                                                     "} pushConstants;\n"
1213                                                                     "void main (void)\n"
1214                                                                     "{\n"
1215                                                                     "  if(gl_SampleID != pushConstants.sampleID)\n"
1216                                                                     "    discard;\n"
1217                                                                     "  gl_FragDepth = 0.5;\n"
1218                                                                     "}\n");
1219         }
1220     }
1221 };
1222 
checkSupport(Context & context)1223 void checkSupport(Context &context)
1224 {
1225     context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
1226 }
1227 
initTests(tcu::TestCaseGroup * group,const SharedGroupParams groupParams)1228 void initTests(tcu::TestCaseGroup *group, const SharedGroupParams groupParams)
1229 {
1230     typedef InstanceFactory1WithSupport<DepthStencilResolveTest, TestConfig, FunctionSupport0, Programs>
1231         DSResolveTestInstance;
1232 
1233     struct FormatData
1234     {
1235         VkFormat format;
1236         const char *name;
1237         bool hasDepth;
1238         bool hasStencil;
1239     };
1240     FormatData formats[] = {
1241         {VK_FORMAT_D16_UNORM, "d16_unorm", true, false},
1242         {VK_FORMAT_X8_D24_UNORM_PACK32, "x8_d24_unorm_pack32", true, false},
1243         {VK_FORMAT_D32_SFLOAT, "d32_sfloat", true, false},
1244         {VK_FORMAT_S8_UINT, "s8_uint", false, true},
1245         {VK_FORMAT_D16_UNORM_S8_UINT, "d16_unorm_s8_uint", true, true},
1246         {VK_FORMAT_D24_UNORM_S8_UINT, "d24_unorm_s8_uint", true, true},
1247         {VK_FORMAT_D32_SFLOAT_S8_UINT, "d32_sfloat_s8_uint", true, true},
1248     };
1249 
1250     struct ResolveModeData
1251     {
1252         VkResolveModeFlagBits flag;
1253         std::string name;
1254     };
1255     ResolveModeData resolveModes[] = {
1256         {VK_RESOLVE_MODE_NONE, "none"},           {VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, "zero"},
1257         {VK_RESOLVE_MODE_AVERAGE_BIT, "average"}, {VK_RESOLVE_MODE_MIN_BIT, "min"},
1258         {VK_RESOLVE_MODE_MAX_BIT, "max"},
1259     };
1260 
1261     struct ImageTestData
1262     {
1263         const char *groupName;
1264         uint32_t width;
1265         uint32_t height;
1266         uint32_t imageLayers;
1267         VkRect2D renderArea;
1268         VkClearDepthStencilValue clearValue;
1269     };
1270 
1271     // NOTE: tests cant be executed for 1D and 3D images:
1272     // 1D images are not tested because acording to specification sampleCounts
1273     // will be set to VK_SAMPLE_COUNT_1_BIT when type is not VK_IMAGE_TYPE_2D
1274     // 3D images are not tested because VkFramebufferCreateInfo specification
1275     // states that: each element of pAttachments that is a 2D or 2D array image
1276     // view taken from a 3D image must not be a depth/stencil format
1277     const uint32_t sampleCounts[]       = {2u, 4u, 8u, 16u, 32u, 64u};
1278     const float depthExpectedValue[][6] = {
1279         // 2 samples    4            8            16            32            64
1280         {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},            // RESOLVE_MODE_NONE
1281         {0.04f, 0.04f, 0.04f, 0.04f, 0.04f, 0.04f},      // RESOLVE_MODE_SAMPLE_ZERO_BIT
1282         {0.03f, 0.135f, 0.135f, 0.135f, 0.135f, 0.135f}, // RESOLVE_MODE_AVERAGE_BIT
1283         {0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f},      // RESOLVE_MODE_MIN_BIT
1284         {0.04f, 0.32f, 0.32f, 0.32f, 0.32f, 0.32f},      // RESOLVE_MODE_MAX_BIT
1285     };
1286     const uint8_t stencilExpectedValue[][6] = {
1287         // 2 samples    4        8        16        32        64
1288         {0u, 0u, 0u, 0u, 0u, 0u},             // RESOLVE_MODE_NONE
1289         {1u, 1u, 1u, 1u, 1u, 1u},             // RESOLVE_MODE_SAMPLE_ZERO_BIT
1290         {0u, 0u, 0u, 0u, 0u, 0u},             // RESOLVE_MODE_AVERAGE_BIT
1291         {1u, 1u, 1u, 1u, 1u, 1u},             // RESOLVE_MODE_MIN_BIT
1292         {255u, 255u, 255u, 255u, 255u, 255u}, // RESOLVE_MODE_MAX_BIT
1293     };
1294 
1295     tcu::TestContext &testCtx(group->getTestContext());
1296 
1297     ImageTestData imageData = {"image_2d_32_32", 32, 32, 1, {{0, 0}, {32, 32}}, {0.000f, 0x00}};
1298 
1299     // iterate over sampleCounts
1300     for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
1301     {
1302         const uint32_t sampleCount(sampleCounts[sampleCountNdx]);
1303         const std::string sampleName("samples_" + de::toString(sampleCount));
1304 
1305         // create test group for sample count
1306         de::MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(testCtx, sampleName.c_str()));
1307 
1308         // iterate over depth/stencil formats
1309         for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1310         {
1311             const FormatData &formatData = formats[formatNdx];
1312             VkFormat format              = formatData.format;
1313             const char *formatName       = formatData.name;
1314             const bool hasDepth          = formatData.hasDepth;
1315             const bool hasStencil        = formatData.hasStencil;
1316             VkImageAspectFlags aspectFlags =
1317                 (hasDepth * VK_IMAGE_ASPECT_DEPTH_BIT) | (hasStencil * VK_IMAGE_ASPECT_STENCIL_BIT);
1318             const int separateLayoutsLoopCount = (hasDepth && hasStencil) ? 2 : 1;
1319 
1320             for (int separateDepthStencilLayouts = 0; separateDepthStencilLayouts < separateLayoutsLoopCount;
1321                  ++separateDepthStencilLayouts)
1322             {
1323                 const bool useSeparateDepthStencilLayouts = bool(separateDepthStencilLayouts);
1324                 const std::string groupName =
1325                     std::string(formatName) + ((useSeparateDepthStencilLayouts) ? "_separate_layouts" : "");
1326 
1327                 // create test group for format
1328                 de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, groupName.c_str()));
1329 
1330                 // iterate over depth resolve modes
1331                 for (size_t depthResolveModeNdx = 0; depthResolveModeNdx < DE_LENGTH_OF_ARRAY(resolveModes);
1332                      depthResolveModeNdx++)
1333                 {
1334                     // iterate over stencil resolve modes
1335                     for (size_t stencilResolveModeNdx = 0; stencilResolveModeNdx < DE_LENGTH_OF_ARRAY(resolveModes);
1336                          stencilResolveModeNdx++)
1337                     {
1338                         // there is no average resolve mode for stencil - go to next iteration
1339                         ResolveModeData &sResolve = resolveModes[stencilResolveModeNdx];
1340                         if (sResolve.flag == VK_RESOLVE_MODE_AVERAGE_BIT)
1341                             continue;
1342 
1343                         // if pDepthStencilResolveAttachment is not NULL and does not have the value VK_ATTACHMENT_UNUSED,
1344                         // depthResolveMode and stencilResolveMode must not both be VK_RESOLVE_MODE_NONE_KHR
1345                         ResolveModeData &dResolve = resolveModes[depthResolveModeNdx];
1346                         if ((dResolve.flag == VK_RESOLVE_MODE_NONE) && (sResolve.flag == VK_RESOLVE_MODE_NONE))
1347                             continue;
1348 
1349                         // If there is no depth, the depth resolve mode should be NONE, or
1350                         // match the stencil resolve mode.
1351                         if (!hasDepth && (dResolve.flag != VK_RESOLVE_MODE_NONE) && (dResolve.flag != sResolve.flag))
1352                             continue;
1353 
1354                         // If there is no stencil, the stencil resolve mode should be NONE, or
1355                         // match the depth resolve mode.
1356                         if (!hasStencil && (sResolve.flag != VK_RESOLVE_MODE_NONE) && (dResolve.flag != sResolve.flag))
1357                             continue;
1358 
1359                         std::string baseName = "depth_" + dResolve.name + "_stencil_" + sResolve.name;
1360 
1361                         if (hasDepth)
1362                         {
1363                             std::string name     = baseName + "_testing_depth";
1364                             const char *testName = name.c_str();
1365                             float expectedValue  = depthExpectedValue[depthResolveModeNdx][sampleCountNdx];
1366 
1367                             const TestConfig testConfig = {format,
1368                                                            imageData.width,
1369                                                            imageData.height,
1370                                                            1u,
1371                                                            1u,
1372                                                            0u,
1373                                                            imageData.renderArea,
1374                                                            aspectFlags,
1375                                                            sampleCount,
1376                                                            dResolve.flag,
1377                                                            sResolve.flag,
1378                                                            VB_DEPTH,
1379                                                            imageData.clearValue,
1380                                                            expectedValue,
1381                                                            0u,
1382                                                            useSeparateDepthStencilLayouts,
1383                                                            groupParams};
1384                             formatGroup->addChild(
1385                                 new DSResolveTestInstance(testCtx, testName, testConfig, checkSupport));
1386                         }
1387 
1388                         if (hasStencil)
1389                         {
1390                             std::string name      = baseName + "_testing_stencil";
1391                             const char *testName  = name.c_str();
1392                             uint8_t expectedValue = stencilExpectedValue[stencilResolveModeNdx][sampleCountNdx];
1393 
1394                             const TestConfig testConfig = {format,
1395                                                            imageData.width,
1396                                                            imageData.height,
1397                                                            1u,
1398                                                            1u,
1399                                                            0u,
1400                                                            imageData.renderArea,
1401                                                            aspectFlags,
1402                                                            sampleCount,
1403                                                            dResolve.flag,
1404                                                            sResolve.flag,
1405                                                            VB_STENCIL,
1406                                                            imageData.clearValue,
1407                                                            0.0f,
1408                                                            expectedValue,
1409                                                            useSeparateDepthStencilLayouts,
1410                                                            groupParams};
1411                             formatGroup->addChild(
1412                                 new DSResolveTestInstance(testCtx, testName, testConfig, checkSupport));
1413                         }
1414                     }
1415                 }
1416                 sampleGroup->addChild(formatGroup.release());
1417             }
1418         }
1419         group->addChild(sampleGroup.release());
1420     }
1421 }
1422 
1423 } // namespace
1424 
createDynamicRenderingDepthStencilResolveTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1425 tcu::TestCaseGroup *createDynamicRenderingDepthStencilResolveTests(tcu::TestContext &testCtx,
1426                                                                    const SharedGroupParams groupParams)
1427 {
1428     // Depth/stencil resolve tests
1429     return createTestGroup(testCtx, "depth_stencil_resolve", initTests, groupParams);
1430 };
1431 
1432 } // namespace renderpass
1433 } // namespace vkt
1434