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