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, ®ion);
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