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