• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  *  Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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
22  * \brief Vulkan Buffer View Creation Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktApiBufferViewCreateTests.hpp"
26 #include "deStringUtil.hpp"
27 #include "deSharedPtr.hpp"
28 #include "gluVarType.hpp"
29 #include "tcuTestLog.hpp"
30 #include "vkPrograms.hpp"
31 #include "vkRefUtil.hpp"
32 #include "vktTestCase.hpp"
33 #include "vkQueryUtil.hpp"
34 
35 namespace vkt
36 {
37 
38 using namespace vk;
39 
40 namespace api
41 {
42 
43 namespace
44 {
45 
46 enum AllocationKind
47 {
48 	ALLOCATION_KIND_SUBALLOCATED = 0,
49 	ALLOCATION_KIND_DEDICATED,
50 
51 	ALLOCATION_KIND_LAST,
52 };
53 
54 class IBufferAllocator;
55 
56 struct BufferViewCaseParameters
57 {
58 	VkFormat							format;
59 	VkDeviceSize						offset;
60 	VkDeviceSize						range;
61 	VkBufferUsageFlags					usage;
62 	VkFormatFeatureFlags				features;
63 	AllocationKind						bufferAllocationKind;
64 };
65 
66 class BufferViewTestInstance : public TestInstance
67 {
68 public:
BufferViewTestInstance(Context & ctx,BufferViewCaseParameters createInfo)69 										BufferViewTestInstance			(Context&					ctx,
70 																		 BufferViewCaseParameters	createInfo)
71 										: TestInstance					(ctx)
72 										, m_testCase					(createInfo)
73 	{}
74 	virtual tcu::TestStatus				iterate							(void);
75 
76 protected:
77 	BufferViewCaseParameters			m_testCase;
78 };
79 
80 class IBufferAllocator
81 {
82 public:
83 	virtual tcu::TestStatus				createTestBuffer				(VkDeviceSize				size,
84 																		 VkBufferUsageFlags			usage,
85 																		 Context&					context,
86 																		 Move<VkBuffer>&			testBuffer,
87 																		 Move<VkDeviceMemory>&		memory) const = 0;
88 };
89 
90 class BufferSuballocation : public IBufferAllocator
91 {
92 public:
93 	virtual tcu::TestStatus				createTestBuffer				(VkDeviceSize				size,
94 																		 VkBufferUsageFlags			usage,
95 																		 Context&					context,
96 																		 Move<VkBuffer>&			testBuffer,
97 																		 Move<VkDeviceMemory>&		memory) const;
98 };
99 
100 class BufferDedicatedAllocation	: public IBufferAllocator
101 {
102 public:
103 	virtual tcu::TestStatus				createTestBuffer				(VkDeviceSize				size,
104 																		 VkBufferUsageFlags			usage,
105 																		 Context&					context,
106 																		 Move<VkBuffer>&			testBuffer,
107 																		 Move<VkDeviceMemory>&		memory) const;
108 };
109 
110 class BufferViewTestCase : public TestCase
111 {
112 public:
BufferViewTestCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,BufferViewCaseParameters createInfo)113 										BufferViewTestCase				(tcu::TestContext&			testCtx,
114 																		 const std::string&			name,
115 																		 const std::string&			description,
116 																		 BufferViewCaseParameters	createInfo)
117 										: TestCase						(testCtx, name, description)
118 										, m_testCase					(createInfo)
119 	{}
~BufferViewTestCase(void)120 	virtual								~BufferViewTestCase				(void)
121 	{}
createInstance(Context & ctx) const122 	virtual TestInstance*				createInstance					(Context&					ctx) const
123 	{
124 		return new BufferViewTestInstance(ctx, m_testCase);
125 	}
checkSupport(Context & ctx) const126 	virtual void						checkSupport					(Context&					ctx) const
127 	{
128 		VkFormatProperties					properties;
129 
130 		ctx.getInstanceInterface().getPhysicalDeviceFormatProperties(ctx.getPhysicalDevice(), m_testCase.format, &properties);
131 		if (!(properties.bufferFeatures & m_testCase.features))
132 			TCU_THROW(NotSupportedError, "Format not supported");
133 		if (m_testCase.bufferAllocationKind == ALLOCATION_KIND_DEDICATED)
134 		{
135 			if (!ctx.isDeviceFunctionalitySupported("VK_KHR_dedicated_allocation"))
136 				TCU_THROW(NotSupportedError, "Dedicated allocation not supported");
137 		}
138 	}
139 private:
140 	BufferViewCaseParameters			m_testCase;
141 };
142 
createTestBuffer(VkDeviceSize size,VkBufferUsageFlags usage,Context & context,Move<VkBuffer> & testBuffer,Move<VkDeviceMemory> & memory) const143 tcu::TestStatus BufferSuballocation::createTestBuffer					(VkDeviceSize				size,
144 																		 VkBufferUsageFlags			usage,
145 																		 Context&					context,
146 																		 Move<VkBuffer>&			testBuffer,
147 																		 Move<VkDeviceMemory>&		memory) const
148 {
149 	const VkDevice						vkDevice						= context.getDevice();
150 	const DeviceInterface&				vk								= context.getDeviceInterface();
151 	const deUint32						queueFamilyIndex				= context.getUniversalQueueFamilyIndex();
152 	VkMemoryRequirements				memReqs;
153 	const VkBufferCreateInfo			bufferParams					=
154 	{
155 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,							//	VkStructureType			sType;
156 		DE_NULL,														//	const void*				pNext;
157 		0u,																//	VkBufferCreateFlags		flags;
158 		size,															//	VkDeviceSize			size;
159 		usage,															//	VkBufferUsageFlags		usage;
160 		VK_SHARING_MODE_EXCLUSIVE,										//	VkSharingMode			sharingMode;
161 		1u,																//	deUint32				queueFamilyCount;
162 		&queueFamilyIndex,												//	const deUint32*			pQueueFamilyIndices;
163 	};
164 
165 	try
166 	{
167 		testBuffer = vk::createBuffer(vk, vkDevice, &bufferParams, (const VkAllocationCallbacks*)DE_NULL);
168 	}
169 	catch (const vk::Error& error)
170 	{
171 		return tcu::TestStatus::fail("Buffer creation failed! (Error code: " + de::toString(error.getMessage()) + ")");
172 	}
173 
174 	vk.getBufferMemoryRequirements(vkDevice, *testBuffer, &memReqs);
175 
176 #ifdef CTS_USES_VULKANSC
177 	if (context.getTestContext().getCommandLine().isSubProcess())
178 #endif // CTS_USES_VULKANSC
179 	{
180 		if (size > memReqs.size)
181 		{
182 			std::ostringstream errorMsg;
183 			errorMsg << "Required memory size (" << memReqs.size << " bytes) smaller than the buffer's size (" << size << " bytes)!";
184 			return tcu::TestStatus::fail(errorMsg.str());
185 		}
186 	}
187 
188 	const VkMemoryAllocateInfo			memAlloc						=
189 	{
190 		VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,							//	VkStructureType			sType
191 		NULL,															//	const void*				pNext
192 		memReqs.size,													//	VkDeviceSize			allocationSize
193 		(deUint32)deCtz32(memReqs.memoryTypeBits)						//	deUint32				memoryTypeIndex
194 	};
195 
196 	try
197 	{
198 		memory = allocateMemory(vk, vkDevice, &memAlloc, (const VkAllocationCallbacks*)DE_NULL);
199 	}
200 	catch (const vk::Error& error)
201 	{
202 		return tcu::TestStatus::fail("Alloc memory failed! (Error code: " + de::toString(error.getMessage()) + ")");
203 	}
204 
205 	if (vk.bindBufferMemory(vkDevice, *testBuffer, *memory, 0) != VK_SUCCESS)
206 		return tcu::TestStatus::fail("Bind buffer memory failed!");
207 
208 	return tcu::TestStatus::incomplete();
209 }
210 
createTestBuffer(VkDeviceSize size,VkBufferUsageFlags usage,Context & context,Move<VkBuffer> & testBuffer,Move<VkDeviceMemory> & memory) const211 tcu::TestStatus BufferDedicatedAllocation::createTestBuffer				(VkDeviceSize				size,
212 																		 VkBufferUsageFlags			usage,
213 																		 Context&					context,
214 																		 Move<VkBuffer>&			testBuffer,
215 																		 Move<VkDeviceMemory>&		memory) const
216 {
217 	const InstanceInterface&			vkInstance						= context.getInstanceInterface();
218 	const VkDevice						vkDevice						= context.getDevice();
219 	const VkPhysicalDevice				vkPhysicalDevice				= context.getPhysicalDevice();
220 	const DeviceInterface&				vk								= context.getDeviceInterface();
221 	const deUint32						queueFamilyIndex				= context.getUniversalQueueFamilyIndex();
222 	VkPhysicalDeviceMemoryProperties	memoryProperties;
223 	VkMemoryDedicatedRequirements		dedicatedRequirements			=
224 	{
225 		VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,				// VkStructureType		sType;
226 		DE_NULL,														// const void*			pNext;
227 		false,															// VkBool32				prefersDedicatedAllocation
228 		false															// VkBool32				requiresDedicatedAllocation
229 	};
230 	VkMemoryRequirements2				memReqs							=
231 	{
232 		VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,						// VkStructureType		sType
233 		&dedicatedRequirements,											// void*				pNext
234 		{0, 0, 0}														// VkMemoryRequirements	memoryRequirements
235 	};
236 
237 	const VkBufferCreateInfo			bufferParams					=
238 	{
239 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,							//	VkStructureType			sType;
240 		DE_NULL,														//	const void*				pNext;
241 		0u,																//	VkBufferCreateFlags		flags;
242 		size,															//	VkDeviceSize			size;
243 		usage,															//	VkBufferUsageFlags		usage;
244 		VK_SHARING_MODE_EXCLUSIVE,										//	VkSharingMode			sharingMode;
245 		1u,																//	deUint32				queueFamilyCount;
246 		&queueFamilyIndex,												//	const deUint32*			pQueueFamilyIndices;
247 	};
248 
249 	try
250 	{
251 		testBuffer = vk::createBuffer(vk, vkDevice, &bufferParams, (const VkAllocationCallbacks*)DE_NULL);
252 	}
253 	catch (const vk::Error& error)
254 	{
255 		return tcu::TestStatus::fail("Buffer creation failed! (Error code: " + de::toString(error.getMessage()) + ")");
256 	}
257 
258 	VkBufferMemoryRequirementsInfo2	info								=
259 	{
260 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,			// VkStructureType		sType
261 		DE_NULL,														// const void*			pNext
262 		*testBuffer														// VkBuffer				buffer
263 	};
264 
265 	vk.getBufferMemoryRequirements2(vkDevice, &info, &memReqs);
266 
267 	if (dedicatedRequirements.requiresDedicatedAllocation == VK_TRUE)
268 	{
269 		std::ostringstream				errorMsg;
270 		errorMsg << "Nonexternal objects cannot require dedicated allocation.";
271 		return tcu::TestStatus::fail(errorMsg.str());
272 	}
273 
274 	if (size > memReqs.memoryRequirements.size)
275 	{
276 		std::ostringstream				errorMsg;
277 		errorMsg << "Requied memory size (" << memReqs.memoryRequirements.size << " bytes) smaller than the buffer's size (" << size << " bytes)!";
278 		return tcu::TestStatus::fail(errorMsg.str());
279 	}
280 
281 	deMemset(&memoryProperties, 0, sizeof(memoryProperties));
282 	vkInstance.getPhysicalDeviceMemoryProperties(vkPhysicalDevice, &memoryProperties);
283 
284 	if (memReqs.memoryRequirements.memoryTypeBits == 0)
285 		return tcu::TestStatus::fail("memoryTypeBits is 0");
286 
287 	const deUint32						heapTypeIndex					= static_cast<deUint32>(deCtz32(memReqs.memoryRequirements.memoryTypeBits));
288 
289 	vk.getBufferMemoryRequirements2(vkDevice, &info, &memReqs);			// get the proper size requirement
290 
291 	if (size > memReqs.memoryRequirements.size)
292 	{
293 		std::ostringstream				errorMsg;
294 		errorMsg << "Requied memory size (" << memReqs.memoryRequirements.size << " bytes) smaller than the buffer's size (" << size << " bytes)!";
295 		return tcu::TestStatus::fail(errorMsg.str());
296 	}
297 
298 	{
299 		VkResult						result							= VK_ERROR_OUT_OF_HOST_MEMORY;
300 		VkDeviceMemory					rawMemory						= DE_NULL;
301 
302 		vk::VkMemoryDedicatedAllocateInfo
303 										dedicatedInfo					=
304 		{
305 			VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,			// VkStructureType			sType
306 			DE_NULL,													// const void*				pNext
307 			DE_NULL,													// VkImage					image
308 			*testBuffer													// VkBuffer					buffer
309 		};
310 
311 		VkMemoryAllocateInfo			memoryAllocateInfo				=
312 		{
313 			VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,						// VkStructureType			sType
314 			&dedicatedInfo,												// const void*				pNext
315 			memReqs.memoryRequirements.size,							// VkDeviceSize				allocationSize
316 			heapTypeIndex,												// deUint32					memoryTypeIndex
317 		};
318 
319 		result = vk.allocateMemory(vkDevice, &memoryAllocateInfo, (VkAllocationCallbacks*)DE_NULL, &rawMemory);
320 
321 		if (result != VK_SUCCESS)
322 			return tcu::TestStatus::fail("Unable to allocate " + de::toString(memReqs.memoryRequirements.size) + " bytes of memory");
323 
324 		memory = Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL));
325 	}
326 
327 
328 	if (vk.bindBufferMemory(vkDevice, *testBuffer, *memory, 0) != VK_SUCCESS)
329 		return tcu::TestStatus::fail("Bind buffer memory failed! (requested memory size: " + de::toString(size) + ")");
330 
331 	return tcu::TestStatus::incomplete();
332 }
333 
iterate(void)334 tcu::TestStatus BufferViewTestInstance::iterate							(void)
335 {
336 	const VkDevice						vkDevice						= m_context.getDevice();
337 	const DeviceInterface&				vk								= m_context.getDeviceInterface();
338 	const VkDeviceSize					size							= 3 * 5 * 7 * 64;
339 	Move<VkBuffer>						testBuffer;
340 	Move<VkDeviceMemory>				testBufferMemory;
341 
342 	// Create buffer
343 	if (m_testCase.bufferAllocationKind == ALLOCATION_KIND_DEDICATED)
344 	{
345 		BufferDedicatedAllocation().createTestBuffer(size, m_testCase.usage, m_context, testBuffer, testBufferMemory);
346 	}
347 	else
348 	{
349 		BufferSuballocation().createTestBuffer(size, m_testCase.usage, m_context, testBuffer, testBufferMemory);
350 	}
351 
352 	{
353 		// Create buffer view.
354 		Move<VkBufferView>				bufferView;
355 		const VkBufferViewCreateInfo	bufferViewCreateInfo			=
356 		{
357 			VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,					//	VkStructureType			sType;
358 			NULL,														//	const void*				pNext;
359 			(VkBufferViewCreateFlags)0,
360 			*testBuffer,												//	VkBuffer				buffer;
361 			m_testCase.format,											//	VkFormat				format;
362 			m_testCase.offset,											//	VkDeviceSize			offset;
363 			m_testCase.range,											//	VkDeviceSize			range;
364 		};
365 
366 		try
367 		{
368 			bufferView = createBufferView(vk, vkDevice, &bufferViewCreateInfo, (const VkAllocationCallbacks*)DE_NULL);
369 		}
370 		catch (const vk::Error& error)
371 		{
372 			return tcu::TestStatus::fail("Buffer View creation failed! (Error code: " + de::toString(error.getMessage()) + ")");
373 		}
374 	}
375 
376 	// Testing complete view size.
377 	{
378 		Move<VkBufferView>				completeBufferView;
379 		VkBufferViewCreateInfo			completeBufferViewCreateInfo	=
380 		{
381 			VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,					//	VkStructureType			sType;
382 			NULL,														//	const void*				pNext;
383 			(VkBufferViewCreateFlags)0,
384 			*testBuffer,												//	VkBuffer				buffer;
385 			m_testCase.format,											//	VkFormat				format;
386 			m_testCase.offset,											//	VkDeviceSize			offset;
387 			size,														//	VkDeviceSize			range;
388 		};
389 
390 		try
391 		{
392 			completeBufferView = createBufferView(vk, vkDevice, &completeBufferViewCreateInfo, (const VkAllocationCallbacks*)DE_NULL);
393 		}
394 		catch (const vk::Error& error)
395 		{
396 			return tcu::TestStatus::fail("Buffer View creation failed! (Error code: " + de::toString(error.getMessage()) + ")");
397 		}
398 	}
399 
400 	return tcu::TestStatus::pass("BufferView test");
401 }
402 
403 } // anonymous
404 
createBufferViewCreateTests(tcu::TestContext & testCtx)405  tcu::TestCaseGroup* createBufferViewCreateTests						(tcu::TestContext& testCtx)
406 {
407 	const VkDeviceSize					range							= VK_WHOLE_SIZE;
408 	const vk::VkBufferUsageFlags		usage[]							= { vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT };
409 	const vk::VkFormatFeatureFlags		feature[]						= { vk::VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT, vk::VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT };
410 	const char* const					usageName[]						= { "uniform", "storage"};
411 
412 	de::MovePtr<tcu::TestCaseGroup>		bufferViewTests					(new tcu::TestCaseGroup(testCtx, "create", "BufferView Construction Tests"));
413 
414 	if (!bufferViewTests)
415 		TCU_THROW(InternalError, "Could not create test group \"create\".");
416 
417 	de::MovePtr<tcu::TestCaseGroup>		bufferViewAllocationGroupTests[ALLOCATION_KIND_LAST]
418 																		=
419 	{
420 		de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "suballocation", "BufferView Construction Tests for Suballocated Buffer")),
421 		de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "dedicated_alloc", "BufferView Construction Tests for Dedicatedly Allocated Buffer"))
422 	};
423 
424 	for (deUint32 allocationKind = 0; allocationKind < ALLOCATION_KIND_LAST; ++allocationKind)
425 	for (deUint32 usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usage); ++usageNdx)
426 	{
427 		de::MovePtr<tcu::TestCaseGroup>	usageGroup		(new tcu::TestCaseGroup(testCtx, usageName[usageNdx], ""));
428 
429 		for (deUint32 format = vk::VK_FORMAT_UNDEFINED + 1; format < VK_CORE_FORMAT_LAST; format++)
430 		{
431 			const std::string			formatName						= de::toLower(getFormatName((VkFormat)format)).substr(10);
432 			de::MovePtr<tcu::TestCaseGroup>	formatGroup		(new tcu::TestCaseGroup(testCtx, "suballocation", "BufferView Construction Tests for Suballocated Buffer"));
433 
434 			const std::string			testName						= de::toLower(getFormatName((VkFormat)format)).substr(10);
435 			const std::string			testDescription					= "vkBufferView test " + testName;
436 
437 			{
438 				const BufferViewCaseParameters
439 										testParams						=
440 				{
441 					static_cast<vk::VkFormat>(format),					// VkFormat					format;
442 					0,													// VkDeviceSize				offset;
443 					range,												// VkDeviceSize				range;
444 					usage[usageNdx],									// VkBufferUsageFlags		usage;
445 					feature[usageNdx],									// VkFormatFeatureFlags		flags;
446 					static_cast<AllocationKind>(allocationKind)			// AllocationKind			bufferAllocationKind;
447 				};
448 
449 				usageGroup->addChild(new BufferViewTestCase(testCtx, testName.c_str(), testDescription.c_str(), testParams));
450 			}
451 		}
452 		bufferViewAllocationGroupTests[allocationKind]->addChild(usageGroup.release());
453 	}
454 
455 	for (deUint32 subgroupNdx = 0u; subgroupNdx < DE_LENGTH_OF_ARRAY(bufferViewAllocationGroupTests); ++subgroupNdx)
456 	{
457 		bufferViewTests->addChild(bufferViewAllocationGroupTests[subgroupNdx].release());
458 	}
459 
460 	return bufferViewTests.release();
461 }
462 
463 } // api
464 } // vk
465