• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
6  * Copyright (c) 2017 Google Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file  vktSparseResourcesImageBlockShapes.cpp
22  * \brief Standard block shape tests.
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktSparseResourcesBufferSparseBinding.hpp"
26 #include "vktSparseResourcesTestsUtil.hpp"
27 #include "vktSparseResourcesBase.hpp"
28 #include "vktTestCaseUtil.hpp"
29 
30 #include "vkDefs.hpp"
31 #include "vkRef.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vkPlatform.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 
41 #include "deUniquePtr.hpp"
42 #include "deStringUtil.hpp"
43 
44 #include <string>
45 #include <vector>
46 
47 using namespace vk;
48 
49 namespace vkt
50 {
51 namespace sparse
52 {
53 namespace
54 {
55 
56 class ImageBlockShapesCase : public TestCase
57 {
58 public:
59 	ImageBlockShapesCase			(tcu::TestContext&	testCtx,
60 									 const std::string&	name,
61 									 const ImageType	imageType,
62 									 const tcu::UVec3&	imageSize,
63 									 const VkFormat		format,
64 									 deUint32			numSamples);
65 
initPrograms(SourceCollections & sourceCollections) const66 	void			initPrograms			(SourceCollections&			sourceCollections) const {DE_UNREF(sourceCollections);}
67 	TestInstance*	createInstance			(Context&					context) const;
68 	virtual void	checkSupport			(Context&					context) const;
69 
70 private:
71 	const ImageType		m_imageType;
72 	const tcu::UVec3	m_imageSize;
73 	const VkFormat		m_format;
74 	const deUint32		m_numSamples;
75 };
76 
ImageBlockShapesCase(tcu::TestContext & testCtx,const std::string & name,const ImageType imageType,const tcu::UVec3 & imageSize,const VkFormat format,deUint32 numSamples)77 ImageBlockShapesCase::ImageBlockShapesCase (tcu::TestContext&	testCtx,
78 											const std::string&	name,
79 											const ImageType		imageType,
80 											const tcu::UVec3&	imageSize,
81 											const VkFormat		format,
82 											deUint32			numSamples)
83 	: TestCase		(testCtx, name)
84 	, m_imageType	(imageType)
85 	, m_imageSize	(imageSize)
86 	, m_format		(format)
87 	, m_numSamples	(numSamples)
88 {
89 }
90 
checkSupport(Context & context) const91 void ImageBlockShapesCase::checkSupport (Context& context) const
92 {
93 	const InstanceInterface&	instance		= context.getInstanceInterface();
94 	const VkPhysicalDevice		physicalDevice	= context.getPhysicalDevice();
95 
96 	// Check the image size does not exceed device limits
97 	if (!isImageSizeSupported(instance, physicalDevice, m_imageType, m_imageSize))
98 		TCU_THROW(NotSupportedError, "Image size not supported for device");
99 
100 	// Check if device supports sparse operations for image type
101 	if (!checkSparseSupportForImageType(instance, physicalDevice, m_imageType))
102 		TCU_THROW(NotSupportedError, "Sparse residency for image type is not supported");
103 
104 	if (formatIsR64(m_format))
105 	{
106 		context.requireDeviceFunctionality("VK_EXT_shader_image_atomic_int64");
107 
108 		if (context.getShaderImageAtomicInt64FeaturesEXT().sparseImageInt64Atomics == VK_FALSE)
109 		{
110 			TCU_THROW(NotSupportedError, "sparseImageInt64Atomics is not supported for device");
111 		}
112 	}
113 }
114 
115 class ImageBlockShapesInstance : public SparseResourcesBaseInstance
116 {
117 public:
118 	ImageBlockShapesInstance	(Context&			context,
119 								 const ImageType	imageType,
120 								 const tcu::UVec3&	imageSize,
121 								 const VkFormat		format,
122 								 deUint32			numSamples);
123 
124 	tcu::TestStatus	iterate		(void);
125 
126 private:
127 	const ImageType		m_imageType;
128 	const tcu::UVec3	m_imageSize;
129 	const VkFormat		m_format;
130 	const deUint32		m_numSamples;
131 };
132 
ImageBlockShapesInstance(Context & context,const ImageType imageType,const tcu::UVec3 & imageSize,const VkFormat format,deUint32 numSamples)133 ImageBlockShapesInstance::ImageBlockShapesInstance (Context&			context,
134 													const ImageType		imageType,
135 													const tcu::UVec3&	imageSize,
136 													const VkFormat		format,
137 													deUint32			numSamples)
138 	: SparseResourcesBaseInstance	(context)
139 	, m_imageType					(imageType)
140 	, m_imageSize					(imageSize)
141 	, m_format						(format)
142 	, m_numSamples					(numSamples)
143 {
144 }
145 
iterate(void)146 tcu::TestStatus ImageBlockShapesInstance::iterate (void)
147 {
148 	const InstanceInterface&						instance					= m_context.getInstanceInterface();
149 	const VkPhysicalDevice							physicalDevice				= m_context.getPhysicalDevice();
150 	const VkPhysicalDeviceProperties				physicalDeviceProperties	= getPhysicalDeviceProperties(instance, physicalDevice);
151 	VkImageCreateInfo								imageCreateInfo;
152 	std::vector<VkSparseImageMemoryRequirements>	sparseMemoryRequirements;
153 	const VkPhysicalDeviceSparseProperties			sparseProperties			= physicalDeviceProperties.sparseProperties;
154 	const PlanarFormatDescription					formatDescription			= getPlanarFormatDescription(m_format);
155 
156 	imageCreateInfo.sType					= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
157 	imageCreateInfo.pNext					= DE_NULL;
158 	imageCreateInfo.flags					= VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT | VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
159 	imageCreateInfo.imageType				= mapImageType(m_imageType);
160 	imageCreateInfo.format					= m_format;
161 	imageCreateInfo.extent					= makeExtent3D(getLayerSize(m_imageType, m_imageSize));
162 	imageCreateInfo.mipLevels				= 1u;
163 	imageCreateInfo.arrayLayers				= getNumLayers(m_imageType, m_imageSize);
164 	imageCreateInfo.samples					= static_cast<VkSampleCountFlagBits>(m_numSamples);
165 	imageCreateInfo.tiling					= VK_IMAGE_TILING_OPTIMAL;
166 	imageCreateInfo.initialLayout			= VK_IMAGE_LAYOUT_UNDEFINED;
167 	imageCreateInfo.usage					= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
168 	imageCreateInfo.sharingMode				= VK_SHARING_MODE_EXCLUSIVE;
169 	imageCreateInfo.queueFamilyIndexCount	= 0u;
170 	imageCreateInfo.pQueueFamilyIndices		= DE_NULL;
171 
172 	if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
173 	{
174 		imageCreateInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
175 	}
176 
177 	// Check the format supports given number of samples
178 	VkImageFormatProperties	imageFormatProperties;
179 
180 	if (instance.getPhysicalDeviceImageFormatProperties(physicalDevice,
181 		imageCreateInfo.format,
182 		imageCreateInfo.imageType,
183 		imageCreateInfo.tiling,
184 		imageCreateInfo.usage,
185 		imageCreateInfo.flags,
186 		&imageFormatProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
187 	{
188 		TCU_THROW(NotSupportedError, "Image format does not support sparse operations");
189 	}
190 
191 	if (!(imageFormatProperties.sampleCounts & imageCreateInfo.samples))
192 		TCU_THROW(NotSupportedError, "The image format does not support the number of samples specified");
193 
194 	// Check if device supports sparse operations for image format
195 	if (!checkSparseSupportForImageFormat(instance, physicalDevice, imageCreateInfo))
196 		TCU_THROW(NotSupportedError, "The image format does not support sparse operations");
197 
198 	{
199 		QueueRequirementsVec queueRequirements;
200 		queueRequirements.push_back(QueueRequirements(VK_QUEUE_SPARSE_BINDING_BIT, 1u));
201 
202 		createDeviceSupportingQueues(queueRequirements);
203 	}
204 
205 	{
206 		const DeviceInterface&		deviceInterface	= getDeviceInterface();
207 
208 		// Create sparse image
209 		const Unique<VkImage>		imageSparse( createImage(deviceInterface, getDevice(), &imageCreateInfo) );
210 
211 		// Get sparse image sparse memory requirements
212 		sparseMemoryRequirements	= getImageSparseMemoryRequirements(deviceInterface, getDevice(), *imageSparse);
213 
214 		DE_ASSERT(sparseMemoryRequirements.size() != 0);
215 	}
216 
217 	for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
218 	{
219 		const VkImageAspectFlags		aspect				= (formatDescription.numPlanes > 1) ? getPlaneAspect(planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT;
220 		const deUint32					aspectIndex			= getSparseAspectRequirementsIndex(sparseMemoryRequirements, aspect);
221 
222 		if (aspectIndex == NO_MATCH_FOUND)
223 			TCU_THROW(NotSupportedError, "Not supported image aspect");
224 
225 		VkSparseImageMemoryRequirements	aspectRequirements	= sparseMemoryRequirements[aspectIndex];
226 		VkExtent3D						imageGranularity	= aspectRequirements.formatProperties.imageGranularity;
227 		deUint32						pixelSize			= static_cast<deUint32>(formatDescription.planes[planeNdx].elementSizeBytes) * 8u;
228 		VkExtent3D						expectedGranularity;
229 
230 		if (m_imageType == IMAGE_TYPE_3D)
231 		{
232 			if (!sparseProperties.residencyStandard3DBlockShape)
233 				return tcu::TestStatus::pass("Pass (residencyStandard3DBlockShape disabled)");
234 
235 			switch (pixelSize)
236 			{
237 				case 8:
238 					expectedGranularity.width = 64;
239 					expectedGranularity.height = 32;
240 					expectedGranularity.depth = 32;
241 					break;
242 				case 16:
243 					expectedGranularity.width = 32;
244 					expectedGranularity.height = 32;
245 					expectedGranularity.depth = 32;
246 					break;
247 				case 32:
248 					expectedGranularity.width = 32;
249 					expectedGranularity.height = 32;
250 					expectedGranularity.depth = 16;
251 					break;
252 				case 64:
253 					expectedGranularity.width = 32;
254 					expectedGranularity.height = 16;
255 					expectedGranularity.depth = 16;
256 					break;
257 				default:
258 					DE_ASSERT(pixelSize == 128);
259 					expectedGranularity.width = 16;
260 					expectedGranularity.height = 16;
261 					expectedGranularity.depth = 16;
262 					break;
263 			}
264 		}
265 		else if (m_numSamples == 2)
266 		{
267 			if (!sparseProperties.residencyStandard2DMultisampleBlockShape)
268 				return tcu::TestStatus::pass("Pass (residencyStandard2DMultisampleBlockShape disabled)");
269 
270 			expectedGranularity.depth = 1;
271 
272 			switch (pixelSize)
273 			{
274 				case 8:
275 					expectedGranularity.width = 128;
276 					expectedGranularity.height = 256;
277 					break;
278 				case 16:
279 					expectedGranularity.width = 128;
280 					expectedGranularity.height = 128;
281 					break;
282 				case 32:
283 					expectedGranularity.width = 64;
284 					expectedGranularity.height = 128;
285 					break;
286 				case 64:
287 					expectedGranularity.width = 64;
288 					expectedGranularity.height = 64;
289 					break;
290 				default:
291 					DE_ASSERT(pixelSize == 128);
292 					expectedGranularity.width = 32;
293 					expectedGranularity.height = 64;
294 					break;
295 			}
296 		}
297 		else if (m_numSamples == 4)
298 		{
299 			if (!sparseProperties.residencyStandard2DMultisampleBlockShape)
300 				return tcu::TestStatus::pass("Pass (residencyStandard2DMultisampleBlockShape disabled)");
301 
302 			expectedGranularity.depth = 1;
303 
304 			switch (pixelSize)
305 			{
306 				case 8:
307 					expectedGranularity.width = 128;
308 					expectedGranularity.height = 128;
309 					break;
310 				case 16:
311 					expectedGranularity.width = 128;
312 					expectedGranularity.height = 64;
313 					break;
314 				case 32:
315 					expectedGranularity.width = 64;
316 					expectedGranularity.height = 64;
317 					break;
318 				case 64:
319 					expectedGranularity.width = 64;
320 					expectedGranularity.height = 32;
321 					break;
322 				default:
323 					DE_ASSERT(pixelSize == 128);
324 					expectedGranularity.width = 32;
325 					expectedGranularity.height = 32;
326 					break;
327 			}
328 		}
329 		else if (m_numSamples == 8)
330 		{
331 			if (!sparseProperties.residencyStandard2DMultisampleBlockShape)
332 				return tcu::TestStatus::pass("Pass (residencyStandard2DMultisampleBlockShape disabled)");
333 
334 			expectedGranularity.depth = 1;
335 
336 			switch (pixelSize)
337 			{
338 				case 8:
339 					expectedGranularity.width = 64;
340 					expectedGranularity.height = 128;
341 					break;
342 				case 16:
343 					expectedGranularity.width = 64;
344 					expectedGranularity.height = 64;
345 					break;
346 				case 32:
347 					expectedGranularity.width = 32;
348 					expectedGranularity.height = 64;
349 					break;
350 				case 64:
351 					expectedGranularity.width = 32;
352 					expectedGranularity.height = 32;
353 					break;
354 				default:
355 					DE_ASSERT(pixelSize == 128);
356 					expectedGranularity.width = 16;
357 					expectedGranularity.height = 32;
358 					break;
359 			}
360 		}
361 		else if (m_numSamples == 16)
362 		{
363 			if (!sparseProperties.residencyStandard2DMultisampleBlockShape)
364 				return tcu::TestStatus::pass("Pass (residencyStandard2DMultisampleBlockShape disabled)");
365 
366 			expectedGranularity.depth = 1;
367 
368 			switch (pixelSize)
369 			{
370 				case 8:
371 					expectedGranularity.width = 64;
372 					expectedGranularity.height = 64;
373 					break;
374 				case 16:
375 					expectedGranularity.width = 64;
376 					expectedGranularity.height = 32;
377 					break;
378 				case 32:
379 					expectedGranularity.width = 32;
380 					expectedGranularity.height = 32;
381 					break;
382 				case 64:
383 					expectedGranularity.width = 32;
384 					expectedGranularity.height = 16;
385 					break;
386 				default:
387 					DE_ASSERT(pixelSize == 128);
388 					expectedGranularity.width = 16;
389 					expectedGranularity.height = 16;
390 					break;
391 			}
392 		}
393 		else
394 		{
395 			DE_ASSERT(m_numSamples == 1);
396 
397 			if (!sparseProperties.residencyStandard2DBlockShape)
398 				return tcu::TestStatus::pass("Pass (residencyStandard2DBlockShape disabled)");
399 
400 			expectedGranularity.depth = 1;
401 
402 			switch (pixelSize)
403 			{
404 				case 8:
405 					expectedGranularity.width = 256;
406 					expectedGranularity.height = 256;
407 					break;
408 				case 16:
409 					expectedGranularity.width = 256;
410 					expectedGranularity.height = 128;
411 					break;
412 				case 32:
413 					expectedGranularity.width = 128;
414 					expectedGranularity.height = 128;
415 					break;
416 				case 64:
417 					expectedGranularity.width = 128;
418 					expectedGranularity.height = 64;
419 					break;
420 				default:
421 					DE_ASSERT(pixelSize == 128);
422 					expectedGranularity.width = 64;
423 					expectedGranularity.height = 64;
424 					break;
425 			}
426 		}
427 
428 		if (   imageGranularity.width  != expectedGranularity.width
429 			|| imageGranularity.height != expectedGranularity.height
430 			|| imageGranularity.depth  != expectedGranularity.depth)
431 		{
432 			return tcu::TestStatus::fail("Non-standard block shape used");
433 		}
434 	}
435 	return tcu::TestStatus::pass("Passed");
436 }
437 
createInstance(Context & context) const438 TestInstance* ImageBlockShapesCase::createInstance (Context& context) const
439 {
440 	return new ImageBlockShapesInstance(context, m_imageType, m_imageSize, m_format, m_numSamples);
441 }
442 
443 } // anonymous ns
444 
createImageBlockShapesTests(tcu::TestContext & testCtx)445 tcu::TestCaseGroup* createImageBlockShapesTests (tcu::TestContext& testCtx)
446 {
447 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "image_block_shapes"));
448 
449 	const std::vector<TestImageParameters> imageParameters
450 	{
451 		{ IMAGE_TYPE_2D,			{ tcu::UVec3(512u, 256u, 1u) },		getTestFormats(IMAGE_TYPE_2D) },
452 		{ IMAGE_TYPE_2D_ARRAY,		{ tcu::UVec3(512u, 256u, 6u) },		getTestFormats(IMAGE_TYPE_2D_ARRAY) },
453 		{ IMAGE_TYPE_CUBE,			{ tcu::UVec3(256u, 256u, 1u) },		getTestFormats(IMAGE_TYPE_CUBE) },
454 		{ IMAGE_TYPE_CUBE_ARRAY,	{ tcu::UVec3(256u, 256u, 6u) },		getTestFormats(IMAGE_TYPE_CUBE_ARRAY) },
455 		{ IMAGE_TYPE_3D,			{ tcu::UVec3(512u, 256u, 16u) },	getTestFormats(IMAGE_TYPE_3D) }
456 	};
457 
458 	static const deUint32 sampleCounts[] = { 1u, 2u, 4u, 8u, 16u };
459 
460 	for (size_t imageTypeNdx = 0; imageTypeNdx < imageParameters.size(); ++imageTypeNdx)
461 	{
462 		const ImageType					imageType = imageParameters[imageTypeNdx].imageType;
463 		de::MovePtr<tcu::TestCaseGroup> imageTypeGroup(new tcu::TestCaseGroup(testCtx, getImageTypeName(imageType).c_str()));
464 
465 		for (size_t formatNdx = 0; formatNdx < imageParameters[imageTypeNdx].formats.size(); ++formatNdx)
466 		{
467 			VkFormat						format				= imageParameters[imageTypeNdx].formats[formatNdx].format;
468 			tcu::UVec3						imageSizeAlignment	= getImageSizeAlignment(format);
469 			de::MovePtr<tcu::TestCaseGroup> formatGroup			(new tcu::TestCaseGroup(testCtx, getImageFormatID(format).c_str()));
470 
471 			for (deInt32 sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); ++sampleCountNdx)
472 			{
473 				for (size_t imageSizeNdx = 0; imageSizeNdx < imageParameters[imageTypeNdx].imageSizes.size(); ++imageSizeNdx)
474 				{
475 					const tcu::UVec3	imageSize = imageParameters[imageTypeNdx].imageSizes[imageSizeNdx];
476 
477 					// skip test for images with odd sizes for some YCbCr formats
478 					if ((imageSize.x() % imageSizeAlignment.x()) != 0)
479 						continue;
480 					if ((imageSize.y() % imageSizeAlignment.y()) != 0)
481 						continue;
482 
483 					const deUint32		sampleCount = sampleCounts[sampleCountNdx];
484 					const std::string	name = std::string("samples_") + de::toString(sampleCount);
485 
486 					formatGroup->addChild(new ImageBlockShapesCase(testCtx, name.c_str(), imageType, imageSize, format, sampleCount));
487 				}
488 			}
489 			imageTypeGroup->addChild(formatGroup.release());
490 		}
491 		testGroup->addChild(imageTypeGroup.release());
492 	}
493 
494 	return testGroup.release();
495 }
496 
497 } // sparse
498 } // vkt
499