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