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