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