• 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  vktSparseResourcesImageAlignedMipSize.cpp
22  * \brief Aligned mip size 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 ImageAlignedMipSizeCase : public TestCase
57 {
58 public:
59 	ImageAlignedMipSizeCase			(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 
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 };
75 
ImageAlignedMipSizeCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const ImageType imageType,const tcu::UVec3 & imageSize,const VkFormat format)76 ImageAlignedMipSizeCase::ImageAlignedMipSizeCase	(tcu::TestContext&	testCtx,
77 													 const std::string&	name,
78 													 const std::string&	description,
79 													 const ImageType	imageType,
80 													 const tcu::UVec3&	imageSize,
81 													 const VkFormat		format)
82 	: TestCase		(testCtx, name, description)
83 	, m_imageType	(imageType)
84 	, m_imageSize	(imageSize)
85 	, m_format		(format)
86 {
87 }
88 
checkSupport(Context & context) const89 void ImageAlignedMipSizeCase::checkSupport (Context& context) const
90 {
91 	const InstanceInterface&	instance		= context.getInstanceInterface();
92 	const VkPhysicalDevice		physicalDevice	= context.getPhysicalDevice();
93 
94 	// Check the image size does not exceed device limits
95 	if (!isImageSizeSupported(instance, physicalDevice, m_imageType, m_imageSize))
96 		TCU_THROW(NotSupportedError, "Image size not supported for device");
97 
98 	// Check if device supports sparse operations for image type
99 	if (!checkSparseSupportForImageType(instance, physicalDevice, m_imageType))
100 		TCU_THROW(NotSupportedError, "Sparse residency for image type is not supported");
101 
102 	if (formatIsR64(m_format))
103 	{
104 		context.requireDeviceFunctionality("VK_EXT_shader_image_atomic_int64");
105 
106 		if (context.getShaderImageAtomicInt64FeaturesEXT().sparseImageInt64Atomics == VK_FALSE)
107 		{
108 			TCU_THROW(NotSupportedError, "sparseImageInt64Atomics is not supported for device");
109 		}
110 	}
111 }
112 
113 class ImageAlignedMipSizeInstance : public SparseResourcesBaseInstance
114 {
115 public:
116 	ImageAlignedMipSizeInstance	(Context&			context,
117 								 const ImageType	imageType,
118 								 const tcu::UVec3&	imageSize,
119 								 const VkFormat		format);
120 
121 	tcu::TestStatus	iterate		(void);
122 
123 private:
124 	const ImageType		m_imageType;
125 	const tcu::UVec3	m_imageSize;
126 	const VkFormat		m_format;
127 };
128 
ImageAlignedMipSizeInstance(Context & context,const ImageType imageType,const tcu::UVec3 & imageSize,const VkFormat format)129 ImageAlignedMipSizeInstance::ImageAlignedMipSizeInstance	(Context&			context,
130 															 const ImageType	imageType,
131 															 const tcu::UVec3&	imageSize,
132 															 const VkFormat		format)
133 	: SparseResourcesBaseInstance	(context)
134 	, m_imageType					(imageType)
135 	, m_imageSize					(imageSize)
136 	, m_format						(format)
137 {
138 }
139 
iterate(void)140 tcu::TestStatus ImageAlignedMipSizeInstance::iterate (void)
141 {
142 	const InstanceInterface&				instance					= m_context.getInstanceInterface();
143 	const VkPhysicalDevice					physicalDevice				= m_context.getPhysicalDevice();
144 	const VkPhysicalDeviceProperties		physicalDeviceProperties	= getPhysicalDeviceProperties(instance, physicalDevice);
145 	VkImageCreateInfo						imageCreateInfo;
146 	VkSparseImageMemoryRequirements			aspectRequirements;
147 	VkExtent3D								imageGranularity;
148 	const VkPhysicalDeviceSparseProperties	sparseProperties			= physicalDeviceProperties.sparseProperties;
149 	const PlanarFormatDescription			formatDescription			= getPlanarFormatDescription(m_format);
150 
151 
152 	imageCreateInfo.sType					= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
153 	imageCreateInfo.pNext					= DE_NULL;
154 	imageCreateInfo.flags					= VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT | VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
155 	imageCreateInfo.imageType				= mapImageType(m_imageType);
156 	imageCreateInfo.format					= m_format;
157 	imageCreateInfo.extent					= makeExtent3D(getLayerSize(m_imageType, m_imageSize));
158 	imageCreateInfo.arrayLayers				= getNumLayers(m_imageType, m_imageSize);
159 	imageCreateInfo.samples					= VK_SAMPLE_COUNT_1_BIT;
160 	imageCreateInfo.tiling					= VK_IMAGE_TILING_OPTIMAL;
161 	imageCreateInfo.initialLayout			= VK_IMAGE_LAYOUT_UNDEFINED;
162 	imageCreateInfo.usage					= VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
163 											  VK_IMAGE_USAGE_STORAGE_BIT;
164 	imageCreateInfo.sharingMode				= VK_SHARING_MODE_EXCLUSIVE;
165 	imageCreateInfo.queueFamilyIndexCount	= 0u;
166 	imageCreateInfo.pQueueFamilyIndices		= DE_NULL;
167 
168 	if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
169 	{
170 		imageCreateInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
171 	}
172 
173 	// Check if device supports sparse operations for image format
174 	if (!checkSparseSupportForImageFormat(instance, physicalDevice, imageCreateInfo))
175 		TCU_THROW(NotSupportedError, "The image format does not support sparse operations");
176 
177 	{
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 		imageCreateInfo.mipLevels = getMipmapCount(m_format, formatDescription, imageFormatProperties, imageCreateInfo.extent);
192 	}
193 
194 	{
195 		QueueRequirementsVec queueRequirements;
196 		queueRequirements.push_back(QueueRequirements(VK_QUEUE_SPARSE_BINDING_BIT, 1u));
197 
198 		createDeviceSupportingQueues(queueRequirements);
199 	}
200 
201 	{
202 		const DeviceInterface&								deviceInterface				= getDeviceInterface();
203 
204 		// Create sparse image
205 		const Unique<VkImage>								imageSparse					(createImage(deviceInterface, getDevice(), &imageCreateInfo));
206 
207 		// Get sparse image sparse memory requirements
208 		const std::vector<VkSparseImageMemoryRequirements>	sparseMemoryRequirements	= getImageSparseMemoryRequirements(deviceInterface, getDevice(), *imageSparse);
209 
210 		DE_ASSERT(sparseMemoryRequirements.size() != 0);
211 
212 		const deUint32										colorAspectIndex			= getSparseAspectRequirementsIndex(sparseMemoryRequirements, VK_IMAGE_ASPECT_COLOR_BIT);
213 
214 		if (colorAspectIndex == NO_MATCH_FOUND)
215 			TCU_THROW(NotSupportedError, "Not supported image aspect - the test supports currently only VK_IMAGE_ASPECT_COLOR_BIT");
216 
217 		aspectRequirements	= sparseMemoryRequirements[colorAspectIndex];
218 		imageGranularity	= aspectRequirements.formatProperties.imageGranularity;
219 	}
220 
221 	if (sparseProperties.residencyAlignedMipSize)
222 	{
223 		deUint32	lod	= 0;
224 		VkExtent3D	extent;
225 
226 		do
227 		{
228 			extent = mipLevelExtents(imageCreateInfo.extent, lod);
229 			if (   extent.width  % imageGranularity.width  != 0
230 				|| extent.height % imageGranularity.height != 0
231 				|| extent.depth  % imageGranularity.depth  != 0)
232 			{
233 				break;
234 			}
235 
236 			lod++;
237 		}
238 		while (extent.width != 1 || extent.height != 1 || extent.depth != 1);
239 
240 		if (lod != aspectRequirements.imageMipTailFirstLod)
241 			return tcu::TestStatus::fail("Unexpected first LOD for mip tail.");
242 		else
243 			return tcu::TestStatus::pass("pass");
244 	}
245 	else if (aspectRequirements.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT)
246 	{
247 		return tcu::TestStatus::fail("Aligned mip size flag doesn't match in device and image properties.");
248 	}
249 	else
250 	{
251 		return tcu::TestStatus::pass("Aligned mip size not enabled.");
252 	}
253 }
254 
createInstance(Context & context) const255 TestInstance* ImageAlignedMipSizeCase::createInstance (Context& context) const
256 {
257 	return new ImageAlignedMipSizeInstance(context, m_imageType, m_imageSize, m_format);
258 }
259 
260 } // anonymous ns
261 
createImageAlignedMipSizeTests(tcu::TestContext & testCtx)262 tcu::TestCaseGroup* createImageAlignedMipSizeTests (tcu::TestContext& testCtx)
263 {
264 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "aligned_mip_size", "Aligned mip size"));
265 
266 	const std::vector<TestImageParameters> imageParameters
267 	{
268 		{ IMAGE_TYPE_2D,		 { tcu::UVec3(512u, 256u, 1u) },	getTestFormats(IMAGE_TYPE_2D) },
269 		{ IMAGE_TYPE_2D_ARRAY,	 { tcu::UVec3(512u, 256u, 6u) },	getTestFormats(IMAGE_TYPE_2D_ARRAY) },
270 		{ IMAGE_TYPE_CUBE,		 { tcu::UVec3(256u, 256u, 1u) },	getTestFormats(IMAGE_TYPE_CUBE) },
271 		{ IMAGE_TYPE_CUBE_ARRAY, { tcu::UVec3(256u, 256u, 6u) },	getTestFormats(IMAGE_TYPE_CUBE_ARRAY) },
272 		{ IMAGE_TYPE_3D,		 { tcu::UVec3(512u, 256u, 16u) },	getTestFormats(IMAGE_TYPE_3D) }
273 	};
274 
275 	for (size_t imageTypeNdx = 0; imageTypeNdx < imageParameters.size(); ++imageTypeNdx)
276 	{
277 		const ImageType					imageType = imageParameters[imageTypeNdx].imageType;
278 		de::MovePtr<tcu::TestCaseGroup> imageTypeGroup(new tcu::TestCaseGroup(testCtx, getImageTypeName(imageType).c_str(), ""));
279 
280 		for (size_t formatNdx = 0; formatNdx < imageParameters[imageTypeNdx].formats.size(); ++formatNdx)
281 		{
282 			VkFormat			format				= imageParameters[imageTypeNdx].formats[formatNdx].format;
283 			tcu::UVec3			imageSizeAlignment	= getImageSizeAlignment(format);
284 			const std::string	name				= getImageFormatID(format);
285 			const tcu::UVec3	imageSize			= imageParameters[imageTypeNdx].imageSizes[0];
286 
287 			// skip test for images with odd sizes for some YCbCr formats
288 			if ((imageSize.x() % imageSizeAlignment.x()) != 0)
289 				continue;
290 			if ((imageSize.y() % imageSizeAlignment.y()) != 0)
291 				continue;
292 
293 			imageTypeGroup->addChild(new ImageAlignedMipSizeCase(testCtx, name.c_str(), "", imageType, imageSize, format));
294 		}
295 		testGroup->addChild(imageTypeGroup.release());
296 	}
297 
298 	return testGroup.release();
299 }
300 
301 } // sparse
302 } // vkt
303