• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &region);
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