• 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 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, &region);
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