1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci *  Vulkan Conformance Tests
3e5c31af7Sopenharmony_ci * ------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2015 The Khronos Group Inc.
6e5c31af7Sopenharmony_ci * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7e5c31af7Sopenharmony_ci *
8e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
9e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
10e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
11e5c31af7Sopenharmony_ci *
12e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
13e5c31af7Sopenharmony_ci *
14e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
15e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
16e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
18e5c31af7Sopenharmony_ci * limitations under the License.
19e5c31af7Sopenharmony_ci *
20e5c31af7Sopenharmony_ci *//*!
21e5c31af7Sopenharmony_ci * \file
22e5c31af7Sopenharmony_ci * \brief Vulkan Buffers Tests
23e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
24e5c31af7Sopenharmony_ci
25e5c31af7Sopenharmony_ci#include "vktApiBufferTests.hpp"
26e5c31af7Sopenharmony_ci#include "gluVarType.hpp"
27e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
28e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
29e5c31af7Sopenharmony_ci#include "vkPlatform.hpp"
30e5c31af7Sopenharmony_ci#include "vkPrograms.hpp"
31e5c31af7Sopenharmony_ci#include "vkQueryUtil.hpp"
32e5c31af7Sopenharmony_ci#include "vkRefUtil.hpp"
33e5c31af7Sopenharmony_ci#include "vktTestCase.hpp"
34e5c31af7Sopenharmony_ci#include "vktTestCaseUtil.hpp"
35e5c31af7Sopenharmony_ci#include "tcuPlatform.hpp"
36e5c31af7Sopenharmony_ci
37e5c31af7Sopenharmony_ci#include <algorithm>
38e5c31af7Sopenharmony_ci#include <limits>
39e5c31af7Sopenharmony_ci
40e5c31af7Sopenharmony_cinamespace vkt
41e5c31af7Sopenharmony_ci{
42e5c31af7Sopenharmony_cinamespace api
43e5c31af7Sopenharmony_ci{
44e5c31af7Sopenharmony_cinamespace
45e5c31af7Sopenharmony_ci{
46e5c31af7Sopenharmony_ciusing namespace vk;
47e5c31af7Sopenharmony_ci
48e5c31af7Sopenharmony_cienum AllocationKind
49e5c31af7Sopenharmony_ci{
50e5c31af7Sopenharmony_ci	ALLOCATION_KIND_SUBALLOCATED = 0,
51e5c31af7Sopenharmony_ci	ALLOCATION_KIND_DEDICATED,
52e5c31af7Sopenharmony_ci
53e5c31af7Sopenharmony_ci	ALLOCATION_KIND_LAST,
54e5c31af7Sopenharmony_ci};
55e5c31af7Sopenharmony_ci
56e5c31af7Sopenharmony_citcu::PlatformMemoryLimits getPlatformMemoryLimits (Context& context)
57e5c31af7Sopenharmony_ci{
58e5c31af7Sopenharmony_ci	tcu::PlatformMemoryLimits memoryLimits;
59e5c31af7Sopenharmony_ci
60e5c31af7Sopenharmony_ci	context.getTestContext().getPlatform().getMemoryLimits(memoryLimits);
61e5c31af7Sopenharmony_ci
62e5c31af7Sopenharmony_ci	return memoryLimits;
63e5c31af7Sopenharmony_ci}
64e5c31af7Sopenharmony_ci
65e5c31af7Sopenharmony_ciVkDeviceSize getMaxBufferSize(const VkDeviceSize& bufferSize,
66e5c31af7Sopenharmony_ci							  const VkDeviceSize& alignment,
67e5c31af7Sopenharmony_ci							  const tcu::PlatformMemoryLimits& limits)
68e5c31af7Sopenharmony_ci{
69e5c31af7Sopenharmony_ci	VkDeviceSize size = bufferSize;
70e5c31af7Sopenharmony_ci
71e5c31af7Sopenharmony_ci	if (limits.totalDeviceLocalMemory == 0)
72e5c31af7Sopenharmony_ci	{
73e5c31af7Sopenharmony_ci		// 'UMA' systems where device memory counts against system memory
74e5c31af7Sopenharmony_ci		size = std::min(bufferSize, limits.totalSystemMemory - alignment);
75e5c31af7Sopenharmony_ci	}
76e5c31af7Sopenharmony_ci	else
77e5c31af7Sopenharmony_ci	{
78e5c31af7Sopenharmony_ci		// 'LMA' systems where device memory is local to the GPU
79e5c31af7Sopenharmony_ci		size = std::min(bufferSize, limits.totalDeviceLocalMemory - alignment);
80e5c31af7Sopenharmony_ci	}
81e5c31af7Sopenharmony_ci
82e5c31af7Sopenharmony_ci	return size;
83e5c31af7Sopenharmony_ci}
84e5c31af7Sopenharmony_ci
85e5c31af7Sopenharmony_cistruct BufferCaseParameters
86e5c31af7Sopenharmony_ci{
87e5c31af7Sopenharmony_ci	VkBufferUsageFlags	usage;
88e5c31af7Sopenharmony_ci	VkBufferCreateFlags	flags;
89e5c31af7Sopenharmony_ci	VkSharingMode		sharingMode;
90e5c31af7Sopenharmony_ci};
91e5c31af7Sopenharmony_ci
92e5c31af7Sopenharmony_ciclass BufferTestInstance : public TestInstance
93e5c31af7Sopenharmony_ci{
94e5c31af7Sopenharmony_cipublic:
95e5c31af7Sopenharmony_ci										BufferTestInstance				(Context&					ctx,
96e5c31af7Sopenharmony_ci																		 BufferCaseParameters		testCase)
97e5c31af7Sopenharmony_ci										: TestInstance					(ctx)
98e5c31af7Sopenharmony_ci										, m_testCase					(testCase)
99e5c31af7Sopenharmony_ci	{
100e5c31af7Sopenharmony_ci	}
101e5c31af7Sopenharmony_ci	virtual tcu::TestStatus				iterate							(void);
102e5c31af7Sopenharmony_ci	virtual tcu::TestStatus				bufferCreateAndAllocTest		(VkDeviceSize				size);
103e5c31af7Sopenharmony_ci
104e5c31af7Sopenharmony_ciprotected:
105e5c31af7Sopenharmony_ci	BufferCaseParameters				m_testCase;
106e5c31af7Sopenharmony_ci};
107e5c31af7Sopenharmony_ci
108e5c31af7Sopenharmony_ciclass DedicatedAllocationBufferTestInstance : public BufferTestInstance
109e5c31af7Sopenharmony_ci{
110e5c31af7Sopenharmony_cipublic:
111e5c31af7Sopenharmony_ci										DedicatedAllocationBufferTestInstance
112e5c31af7Sopenharmony_ci																		(Context&					ctx,
113e5c31af7Sopenharmony_ci																		 BufferCaseParameters		testCase)
114e5c31af7Sopenharmony_ci										: BufferTestInstance			(ctx, testCase)
115e5c31af7Sopenharmony_ci	{
116e5c31af7Sopenharmony_ci	}
117e5c31af7Sopenharmony_ci	virtual tcu::TestStatus				bufferCreateAndAllocTest		(VkDeviceSize				size);
118e5c31af7Sopenharmony_ci};
119e5c31af7Sopenharmony_ci
120e5c31af7Sopenharmony_ciclass BuffersTestCase : public TestCase
121e5c31af7Sopenharmony_ci{
122e5c31af7Sopenharmony_cipublic:
123e5c31af7Sopenharmony_ci										BuffersTestCase					(tcu::TestContext&			testCtx,
124e5c31af7Sopenharmony_ci																		 const std::string&			name,
125e5c31af7Sopenharmony_ci																		 BufferCaseParameters		testCase)
126e5c31af7Sopenharmony_ci										: TestCase						(testCtx, name)
127e5c31af7Sopenharmony_ci										, m_testCase					(testCase)
128e5c31af7Sopenharmony_ci	{
129e5c31af7Sopenharmony_ci	}
130e5c31af7Sopenharmony_ci
131e5c31af7Sopenharmony_ci	virtual								~BuffersTestCase				(void)
132e5c31af7Sopenharmony_ci	{
133e5c31af7Sopenharmony_ci	}
134e5c31af7Sopenharmony_ci
135e5c31af7Sopenharmony_ci	virtual TestInstance*				createInstance					(Context&					ctx) const
136e5c31af7Sopenharmony_ci	{
137e5c31af7Sopenharmony_ci		tcu::TestLog&					log								= m_testCtx.getLog();
138e5c31af7Sopenharmony_ci		log << tcu::TestLog::Message << getBufferUsageFlagsStr(m_testCase.usage) << tcu::TestLog::EndMessage;
139e5c31af7Sopenharmony_ci		return new BufferTestInstance(ctx, m_testCase);
140e5c31af7Sopenharmony_ci	}
141e5c31af7Sopenharmony_ci
142e5c31af7Sopenharmony_ci	virtual void						checkSupport					(Context&					ctx) const
143e5c31af7Sopenharmony_ci	{
144e5c31af7Sopenharmony_ci		const VkPhysicalDeviceFeatures&		physicalDeviceFeatures = getPhysicalDeviceFeatures(ctx.getInstanceInterface(), ctx.getPhysicalDevice());
145e5c31af7Sopenharmony_ci
146e5c31af7Sopenharmony_ci		if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) && !physicalDeviceFeatures.sparseBinding)
147e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Sparse bindings feature is not supported");
148e5c31af7Sopenharmony_ci
149e5c31af7Sopenharmony_ci		if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) && !physicalDeviceFeatures.sparseResidencyBuffer)
150e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Sparse buffer residency feature is not supported");
151e5c31af7Sopenharmony_ci
152e5c31af7Sopenharmony_ci		if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) && !physicalDeviceFeatures.sparseResidencyAliased)
153e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Sparse aliased residency feature is not supported");
154e5c31af7Sopenharmony_ci	}
155e5c31af7Sopenharmony_ci
156e5c31af7Sopenharmony_ciprivate:
157e5c31af7Sopenharmony_ci	BufferCaseParameters				m_testCase;
158e5c31af7Sopenharmony_ci};
159e5c31af7Sopenharmony_ci
160e5c31af7Sopenharmony_ciclass DedicatedAllocationBuffersTestCase : public TestCase
161e5c31af7Sopenharmony_ci{
162e5c31af7Sopenharmony_ci	public:
163e5c31af7Sopenharmony_ci										DedicatedAllocationBuffersTestCase
164e5c31af7Sopenharmony_ci																		(tcu::TestContext&			testCtx,
165e5c31af7Sopenharmony_ci																		 const std::string&			name,
166e5c31af7Sopenharmony_ci																		 BufferCaseParameters		testCase)
167e5c31af7Sopenharmony_ci										: TestCase						(testCtx, name)
168e5c31af7Sopenharmony_ci										, m_testCase					(testCase)
169e5c31af7Sopenharmony_ci	{
170e5c31af7Sopenharmony_ci	}
171e5c31af7Sopenharmony_ci
172e5c31af7Sopenharmony_ci	virtual								~DedicatedAllocationBuffersTestCase
173e5c31af7Sopenharmony_ci																		(void)
174e5c31af7Sopenharmony_ci	{
175e5c31af7Sopenharmony_ci	}
176e5c31af7Sopenharmony_ci
177e5c31af7Sopenharmony_ci	virtual TestInstance*				createInstance					(Context&					ctx) const
178e5c31af7Sopenharmony_ci	{
179e5c31af7Sopenharmony_ci		tcu::TestLog&					log								= m_testCtx.getLog();
180e5c31af7Sopenharmony_ci		log << tcu::TestLog::Message << getBufferUsageFlagsStr(m_testCase.usage) << tcu::TestLog::EndMessage;
181e5c31af7Sopenharmony_ci		return new DedicatedAllocationBufferTestInstance(ctx, m_testCase);
182e5c31af7Sopenharmony_ci	}
183e5c31af7Sopenharmony_ci
184e5c31af7Sopenharmony_ci	virtual void						checkSupport					(Context&					ctx) const
185e5c31af7Sopenharmony_ci	{
186e5c31af7Sopenharmony_ci		if (!ctx.isDeviceFunctionalitySupported("VK_KHR_dedicated_allocation"))
187e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Not supported");
188e5c31af7Sopenharmony_ci	}
189e5c31af7Sopenharmony_ciprivate:
190e5c31af7Sopenharmony_ci	BufferCaseParameters				m_testCase;
191e5c31af7Sopenharmony_ci};
192e5c31af7Sopenharmony_ci
193e5c31af7Sopenharmony_citcu::TestStatus BufferTestInstance::bufferCreateAndAllocTest			(VkDeviceSize				size)
194e5c31af7Sopenharmony_ci{
195e5c31af7Sopenharmony_ci	const VkPhysicalDevice				vkPhysicalDevice				= m_context.getPhysicalDevice();
196e5c31af7Sopenharmony_ci	const InstanceInterface&			vkInstance						= m_context.getInstanceInterface();
197e5c31af7Sopenharmony_ci	const VkDevice						vkDevice						= m_context.getDevice();
198e5c31af7Sopenharmony_ci	const DeviceInterface&				vk								= m_context.getDeviceInterface();
199e5c31af7Sopenharmony_ci	const deUint32						queueFamilyIndex				= m_context.getSparseQueueFamilyIndex();
200e5c31af7Sopenharmony_ci	const VkPhysicalDeviceMemoryProperties
201e5c31af7Sopenharmony_ci										memoryProperties				= getPhysicalDeviceMemoryProperties(vkInstance, vkPhysicalDevice);
202e5c31af7Sopenharmony_ci	const VkPhysicalDeviceLimits		limits							= getPhysicalDeviceProperties(vkInstance, vkPhysicalDevice).limits;
203e5c31af7Sopenharmony_ci	Move<VkBuffer>						buffer;
204e5c31af7Sopenharmony_ci	Move<VkDeviceMemory>				memory;
205e5c31af7Sopenharmony_ci	VkMemoryRequirements				memReqs;
206e5c31af7Sopenharmony_ci
207e5c31af7Sopenharmony_ci	if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0)
208e5c31af7Sopenharmony_ci	{
209e5c31af7Sopenharmony_ci		size = std::min(size, limits.sparseAddressSpaceSize);
210e5c31af7Sopenharmony_ci	}
211e5c31af7Sopenharmony_ci
212e5c31af7Sopenharmony_ci	// Create the test buffer and a memory allocation for it
213e5c31af7Sopenharmony_ci	{
214e5c31af7Sopenharmony_ci		// Create a minimal buffer first to get the supported memory types
215e5c31af7Sopenharmony_ci		VkBufferCreateInfo				bufferParams					=
216e5c31af7Sopenharmony_ci		{
217e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType			sType;
218e5c31af7Sopenharmony_ci			DE_NULL,													// const void*				pNext;
219e5c31af7Sopenharmony_ci			m_testCase.flags,											// VkBufferCreateFlags		flags;
220e5c31af7Sopenharmony_ci			1u,															// VkDeviceSize				size;
221e5c31af7Sopenharmony_ci			m_testCase.usage,											// VkBufferUsageFlags		usage;
222e5c31af7Sopenharmony_ci			m_testCase.sharingMode,										// VkSharingMode			sharingMode;
223e5c31af7Sopenharmony_ci			1u,															// uint32_t					queueFamilyIndexCount;
224e5c31af7Sopenharmony_ci			&queueFamilyIndex,											// const uint32_t*			pQueueFamilyIndices;
225e5c31af7Sopenharmony_ci		};
226e5c31af7Sopenharmony_ci
227e5c31af7Sopenharmony_ci		buffer = createBuffer(vk, vkDevice, &bufferParams);
228e5c31af7Sopenharmony_ci		vk.getBufferMemoryRequirements(vkDevice, *buffer, &memReqs);
229e5c31af7Sopenharmony_ci
230e5c31af7Sopenharmony_ci		const deUint32					heapTypeIndex					= (deUint32)deCtz32(memReqs.memoryTypeBits);
231e5c31af7Sopenharmony_ci		const VkMemoryType				memoryType						= memoryProperties.memoryTypes[heapTypeIndex];
232e5c31af7Sopenharmony_ci		const VkMemoryHeap				memoryHeap						= memoryProperties.memoryHeaps[memoryType.heapIndex];
233e5c31af7Sopenharmony_ci		const deUint32					shrinkBits						= 4u;	// number of bits to shift when reducing the size with each iteration
234e5c31af7Sopenharmony_ci
235e5c31af7Sopenharmony_ci		// Buffer size - Choose half of the reported heap size for the maximum buffer size, we
236e5c31af7Sopenharmony_ci		// should attempt to test as large a portion as possible.
237e5c31af7Sopenharmony_ci		//
238e5c31af7Sopenharmony_ci		// However on a system where device memory is shared with the system, the maximum size
239e5c31af7Sopenharmony_ci		// should be tested against the platform memory limits as significant portion of the heap
240e5c31af7Sopenharmony_ci		// may already be in use by the operating system and other running processes.
241e5c31af7Sopenharmony_ci		const VkDeviceSize  availableBufferSize	= getMaxBufferSize(memoryHeap.size,
242e5c31af7Sopenharmony_ci																   memReqs.alignment,
243e5c31af7Sopenharmony_ci																   getPlatformMemoryLimits(m_context));
244e5c31af7Sopenharmony_ci
245e5c31af7Sopenharmony_ci		// For our test buffer size, halve the maximum available size and align
246e5c31af7Sopenharmony_ci		const VkDeviceSize maxBufferSize = deAlign64(availableBufferSize >> 1, memReqs.alignment);
247e5c31af7Sopenharmony_ci
248e5c31af7Sopenharmony_ci		size = std::min(size, maxBufferSize);
249e5c31af7Sopenharmony_ci
250e5c31af7Sopenharmony_ci		while (*memory == DE_NULL)
251e5c31af7Sopenharmony_ci		{
252e5c31af7Sopenharmony_ci			// Create the buffer
253e5c31af7Sopenharmony_ci			{
254e5c31af7Sopenharmony_ci				VkResult				result							= VK_ERROR_OUT_OF_HOST_MEMORY;
255e5c31af7Sopenharmony_ci				VkBuffer				rawBuffer						= DE_NULL;
256e5c31af7Sopenharmony_ci
257e5c31af7Sopenharmony_ci				bufferParams.size = size;
258e5c31af7Sopenharmony_ci				buffer = Move<VkBuffer>();		// free the previous buffer, if any
259e5c31af7Sopenharmony_ci				result = vk.createBuffer(vkDevice, &bufferParams, (vk::VkAllocationCallbacks*)DE_NULL, &rawBuffer);
260e5c31af7Sopenharmony_ci
261e5c31af7Sopenharmony_ci				if (result != VK_SUCCESS)
262e5c31af7Sopenharmony_ci				{
263e5c31af7Sopenharmony_ci					size = deAlign64(size >> shrinkBits, memReqs.alignment);
264e5c31af7Sopenharmony_ci
265e5c31af7Sopenharmony_ci					if (size == 0 || bufferParams.size == memReqs.alignment)
266e5c31af7Sopenharmony_ci					{
267e5c31af7Sopenharmony_ci						return tcu::TestStatus::fail("Buffer creation failed! (" + de::toString(getResultName(result)) + ")");
268e5c31af7Sopenharmony_ci					}
269e5c31af7Sopenharmony_ci
270e5c31af7Sopenharmony_ci					continue;	// didn't work, try with a smaller buffer
271e5c31af7Sopenharmony_ci				}
272e5c31af7Sopenharmony_ci
273e5c31af7Sopenharmony_ci				buffer = Move<VkBuffer>(check<VkBuffer>(rawBuffer), Deleter<VkBuffer>(vk, vkDevice, DE_NULL));
274e5c31af7Sopenharmony_ci			}
275e5c31af7Sopenharmony_ci
276e5c31af7Sopenharmony_ci			vk.getBufferMemoryRequirements(vkDevice, *buffer, &memReqs);	// get the proper size requirement
277e5c31af7Sopenharmony_ci
278e5c31af7Sopenharmony_ci#ifdef CTS_USES_VULKANSC
279e5c31af7Sopenharmony_ci			if (m_context.getTestContext().getCommandLine().isSubProcess())
280e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
281e5c31af7Sopenharmony_ci			{
282e5c31af7Sopenharmony_ci				if (size > memReqs.size)
283e5c31af7Sopenharmony_ci				{
284e5c31af7Sopenharmony_ci					std::ostringstream		errorMsg;
285e5c31af7Sopenharmony_ci					errorMsg << "Required memory size (" << memReqs.size << " bytes) smaller than the buffer's size (" << size << " bytes)!";
286e5c31af7Sopenharmony_ci					return tcu::TestStatus::fail(errorMsg.str());
287e5c31af7Sopenharmony_ci				}
288e5c31af7Sopenharmony_ci			}
289e5c31af7Sopenharmony_ci
290e5c31af7Sopenharmony_ci			// Allocate the memory
291e5c31af7Sopenharmony_ci			{
292e5c31af7Sopenharmony_ci				VkResult				result							= VK_ERROR_OUT_OF_HOST_MEMORY;
293e5c31af7Sopenharmony_ci				VkDeviceMemory			rawMemory						= DE_NULL;
294e5c31af7Sopenharmony_ci
295e5c31af7Sopenharmony_ci				const VkMemoryAllocateInfo
296e5c31af7Sopenharmony_ci										memAlloc						=
297e5c31af7Sopenharmony_ci				{
298e5c31af7Sopenharmony_ci					VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,				// VkStructureType			sType;
299e5c31af7Sopenharmony_ci					NULL,												// const void*				pNext;
300e5c31af7Sopenharmony_ci					memReqs.size,										// VkDeviceSize				allocationSize;
301e5c31af7Sopenharmony_ci					heapTypeIndex,										// uint32_t					memoryTypeIndex;
302e5c31af7Sopenharmony_ci				};
303e5c31af7Sopenharmony_ci
304e5c31af7Sopenharmony_ci				result = vk.allocateMemory(vkDevice, &memAlloc, (VkAllocationCallbacks*)DE_NULL, &rawMemory);
305e5c31af7Sopenharmony_ci
306e5c31af7Sopenharmony_ci				if (result != VK_SUCCESS)
307e5c31af7Sopenharmony_ci				{
308e5c31af7Sopenharmony_ci					size = deAlign64(size >> shrinkBits, memReqs.alignment);
309e5c31af7Sopenharmony_ci
310e5c31af7Sopenharmony_ci					if (size == 0 || memReqs.size == memReqs.alignment)
311e5c31af7Sopenharmony_ci					{
312e5c31af7Sopenharmony_ci						return tcu::TestStatus::fail("Unable to allocate " + de::toString(memReqs.size) + " bytes of memory");
313e5c31af7Sopenharmony_ci					}
314e5c31af7Sopenharmony_ci
315e5c31af7Sopenharmony_ci					continue;	// didn't work, try with a smaller allocation (and a smaller buffer)
316e5c31af7Sopenharmony_ci				}
317e5c31af7Sopenharmony_ci
318e5c31af7Sopenharmony_ci				memory = Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL));
319e5c31af7Sopenharmony_ci			}
320e5c31af7Sopenharmony_ci		} // while
321e5c31af7Sopenharmony_ci	}
322e5c31af7Sopenharmony_ci
323e5c31af7Sopenharmony_ci	// Bind the memory
324e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
325e5c31af7Sopenharmony_ci	if ((m_testCase.flags & (VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT)) != 0)
326e5c31af7Sopenharmony_ci	{
327e5c31af7Sopenharmony_ci		const VkQueue					queue							= m_context.getSparseQueue();
328e5c31af7Sopenharmony_ci
329e5c31af7Sopenharmony_ci		const VkSparseMemoryBind		sparseMemoryBind				=
330e5c31af7Sopenharmony_ci		{
331e5c31af7Sopenharmony_ci			0,															// VkDeviceSize				resourceOffset;
332e5c31af7Sopenharmony_ci			memReqs.size,												// VkDeviceSize				size;
333e5c31af7Sopenharmony_ci			*memory,													// VkDeviceMemory			memory;
334e5c31af7Sopenharmony_ci			0,															// VkDeviceSize				memoryOffset;
335e5c31af7Sopenharmony_ci			0															// VkSparseMemoryBindFlags	flags;
336e5c31af7Sopenharmony_ci		};
337e5c31af7Sopenharmony_ci
338e5c31af7Sopenharmony_ci		const VkSparseBufferMemoryBindInfo
339e5c31af7Sopenharmony_ci										sparseBufferMemoryBindInfo		=
340e5c31af7Sopenharmony_ci		{
341e5c31af7Sopenharmony_ci			*buffer,													// VkBuffer					buffer;
342e5c31af7Sopenharmony_ci			1u,															// deUint32					bindCount;
343e5c31af7Sopenharmony_ci			&sparseMemoryBind											// const VkSparseMemoryBind* pBinds;
344e5c31af7Sopenharmony_ci		};
345e5c31af7Sopenharmony_ci
346e5c31af7Sopenharmony_ci		const VkBindSparseInfo			bindSparseInfo					=
347e5c31af7Sopenharmony_ci		{
348e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_BIND_SPARSE_INFO,							// VkStructureType			sType;
349e5c31af7Sopenharmony_ci			DE_NULL,													// const void*				pNext;
350e5c31af7Sopenharmony_ci			0,															// deUint32					waitSemaphoreCount;
351e5c31af7Sopenharmony_ci			DE_NULL,													// const VkSemaphore*		pWaitSemaphores;
352e5c31af7Sopenharmony_ci			1u,															// deUint32					bufferBindCount;
353e5c31af7Sopenharmony_ci			&sparseBufferMemoryBindInfo,								// const VkSparseBufferMemoryBindInfo* pBufferBinds;
354e5c31af7Sopenharmony_ci			0,															// deUint32					imageOpaqueBindCount;
355e5c31af7Sopenharmony_ci			DE_NULL,													// const VkSparseImageOpaqueMemoryBindInfo*	pImageOpaqueBinds;
356e5c31af7Sopenharmony_ci			0,															// deUint32					imageBindCount;
357e5c31af7Sopenharmony_ci			DE_NULL,													// const VkSparseImageMemoryBindInfo* pImageBinds;
358e5c31af7Sopenharmony_ci			0,															// deUint32					signalSemaphoreCount;
359e5c31af7Sopenharmony_ci			DE_NULL,													// const VkSemaphore*		pSignalSemaphores;
360e5c31af7Sopenharmony_ci		};
361e5c31af7Sopenharmony_ci
362e5c31af7Sopenharmony_ci		const vk::Unique<vk::VkFence>	fence							(vk::createFence(vk, vkDevice));
363e5c31af7Sopenharmony_ci
364e5c31af7Sopenharmony_ci		if (vk.queueBindSparse(queue, 1, &bindSparseInfo, *fence) != VK_SUCCESS)
365e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail("Bind sparse buffer memory failed! (requested memory size: " + de::toString(size) + ")");
366e5c31af7Sopenharmony_ci
367e5c31af7Sopenharmony_ci		VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), VK_TRUE, ~(0ull) /* infinity */));
368e5c31af7Sopenharmony_ci	}
369e5c31af7Sopenharmony_ci	else if (vk.bindBufferMemory(vkDevice, *buffer, *memory, 0) != VK_SUCCESS)
370e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Bind buffer memory failed! (requested memory size: " + de::toString(size) + ")");
371e5c31af7Sopenharmony_ci#else
372e5c31af7Sopenharmony_ci	if (vk.bindBufferMemory(vkDevice, *buffer, *memory, 0) != VK_SUCCESS)
373e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Bind buffer memory failed! (requested memory size: " + de::toString(size) + ")");
374e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
375e5c31af7Sopenharmony_ci
376e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("Pass");
377e5c31af7Sopenharmony_ci}
378e5c31af7Sopenharmony_ci
379e5c31af7Sopenharmony_citcu::TestStatus							BufferTestInstance::iterate		(void)
380e5c31af7Sopenharmony_ci{
381e5c31af7Sopenharmony_ci	const VkDeviceSize					testSizes[]						=
382e5c31af7Sopenharmony_ci	{
383e5c31af7Sopenharmony_ci		1,
384e5c31af7Sopenharmony_ci		1181,
385e5c31af7Sopenharmony_ci		15991,
386e5c31af7Sopenharmony_ci		16384,
387e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
388e5c31af7Sopenharmony_ci		~0ull,		// try to exercise a very large buffer too (will be clamped to a sensible size later)
389e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
390e5c31af7Sopenharmony_ci	};
391e5c31af7Sopenharmony_ci
392e5c31af7Sopenharmony_ci	for (int i = 0; i < DE_LENGTH_OF_ARRAY(testSizes); ++i)
393e5c31af7Sopenharmony_ci	{
394e5c31af7Sopenharmony_ci		const tcu::TestStatus			testStatus						= bufferCreateAndAllocTest(testSizes[i]);
395e5c31af7Sopenharmony_ci
396e5c31af7Sopenharmony_ci		if (testStatus.getCode() != QP_TEST_RESULT_PASS)
397e5c31af7Sopenharmony_ci			return testStatus;
398e5c31af7Sopenharmony_ci	}
399e5c31af7Sopenharmony_ci
400e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("Pass");
401e5c31af7Sopenharmony_ci}
402e5c31af7Sopenharmony_ci
403e5c31af7Sopenharmony_citcu::TestStatus							DedicatedAllocationBufferTestInstance::bufferCreateAndAllocTest
404e5c31af7Sopenharmony_ci																		(VkDeviceSize				size)
405e5c31af7Sopenharmony_ci{
406e5c31af7Sopenharmony_ci	const VkPhysicalDevice				vkPhysicalDevice				= m_context.getPhysicalDevice();
407e5c31af7Sopenharmony_ci	const InstanceInterface&			vkInstance						= m_context.getInstanceInterface();
408e5c31af7Sopenharmony_ci	const VkDevice						vkDevice						= m_context.getDevice();
409e5c31af7Sopenharmony_ci	const DeviceInterface&				vk								= m_context.getDeviceInterface();
410e5c31af7Sopenharmony_ci	const deUint32						queueFamilyIndex				= m_context.getUniversalQueueFamilyIndex();
411e5c31af7Sopenharmony_ci	const VkPhysicalDeviceMemoryProperties
412e5c31af7Sopenharmony_ci										memoryProperties				= getPhysicalDeviceMemoryProperties(vkInstance, vkPhysicalDevice);
413e5c31af7Sopenharmony_ci	const VkPhysicalDeviceLimits		limits							= getPhysicalDeviceProperties(vkInstance, vkPhysicalDevice).limits;
414e5c31af7Sopenharmony_ci
415e5c31af7Sopenharmony_ci	VkMemoryDedicatedRequirements	dedicatedRequirements			=
416e5c31af7Sopenharmony_ci	{
417e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,				// VkStructureType			sType;
418e5c31af7Sopenharmony_ci		DE_NULL,														// const void*				pNext;
419e5c31af7Sopenharmony_ci		false,															// VkBool32					prefersDedicatedAllocation
420e5c31af7Sopenharmony_ci		false															// VkBool32					requiresDedicatedAllocation
421e5c31af7Sopenharmony_ci	};
422e5c31af7Sopenharmony_ci	VkMemoryRequirements2			memReqs							=
423e5c31af7Sopenharmony_ci	{
424e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,						// VkStructureType			sType
425e5c31af7Sopenharmony_ci		&dedicatedRequirements,											// void*					pNext
426e5c31af7Sopenharmony_ci		{0, 0, 0}														// VkMemoryRequirements		memoryRequirements
427e5c31af7Sopenharmony_ci	};
428e5c31af7Sopenharmony_ci
429e5c31af7Sopenharmony_ci	if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0)
430e5c31af7Sopenharmony_ci		size = std::min(size, limits.sparseAddressSpaceSize);
431e5c31af7Sopenharmony_ci
432e5c31af7Sopenharmony_ci	// Create a minimal buffer first to get the supported memory types
433e5c31af7Sopenharmony_ci	VkBufferCreateInfo					bufferParams					=
434e5c31af7Sopenharmony_ci	{
435e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,							// VkStructureType			sType
436e5c31af7Sopenharmony_ci		DE_NULL,														// const void*				pNext
437e5c31af7Sopenharmony_ci		m_testCase.flags,												// VkBufferCreateFlags		flags
438e5c31af7Sopenharmony_ci		1u,																// VkDeviceSize				size
439e5c31af7Sopenharmony_ci		m_testCase.usage,												// VkBufferUsageFlags		usage
440e5c31af7Sopenharmony_ci		m_testCase.sharingMode,											// VkSharingMode			sharingMode
441e5c31af7Sopenharmony_ci		1u,																// uint32_t					queueFamilyIndexCount
442e5c31af7Sopenharmony_ci		&queueFamilyIndex,												// const uint32_t*			pQueueFamilyIndices
443e5c31af7Sopenharmony_ci	};
444e5c31af7Sopenharmony_ci
445e5c31af7Sopenharmony_ci	Move<VkBuffer>						buffer							= createBuffer(vk, vkDevice, &bufferParams);
446e5c31af7Sopenharmony_ci
447e5c31af7Sopenharmony_ci	VkBufferMemoryRequirementsInfo2	info							=
448e5c31af7Sopenharmony_ci	{
449e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,			// VkStructureType			sType
450e5c31af7Sopenharmony_ci		DE_NULL,														// const void*				pNext
451e5c31af7Sopenharmony_ci		*buffer															// VkBuffer					buffer
452e5c31af7Sopenharmony_ci	};
453e5c31af7Sopenharmony_ci
454e5c31af7Sopenharmony_ci	vk.getBufferMemoryRequirements2(vkDevice, &info, &memReqs);
455e5c31af7Sopenharmony_ci
456e5c31af7Sopenharmony_ci	if (dedicatedRequirements.requiresDedicatedAllocation == VK_TRUE)
457e5c31af7Sopenharmony_ci	{
458e5c31af7Sopenharmony_ci		std::ostringstream				errorMsg;
459e5c31af7Sopenharmony_ci		errorMsg << "Nonexternal objects cannot require dedicated allocation.";
460e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail(errorMsg.str());
461e5c31af7Sopenharmony_ci	}
462e5c31af7Sopenharmony_ci
463e5c31af7Sopenharmony_ci	if(memReqs.memoryRequirements.memoryTypeBits == 0)
464e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("memoryTypeBits is 0");
465e5c31af7Sopenharmony_ci
466e5c31af7Sopenharmony_ci	const deUint32						heapTypeIndex					= static_cast<deUint32>(deCtz32(memReqs.memoryRequirements.memoryTypeBits));
467e5c31af7Sopenharmony_ci	const VkMemoryType					memoryType						= memoryProperties.memoryTypes[heapTypeIndex];
468e5c31af7Sopenharmony_ci	const VkMemoryHeap					memoryHeap						= memoryProperties.memoryHeaps[memoryType.heapIndex];
469e5c31af7Sopenharmony_ci	const deUint32						shrinkBits						= 4u;	// number of bits to shift when reducing the size with each iteration
470e5c31af7Sopenharmony_ci
471e5c31af7Sopenharmony_ci	// Buffer size - Choose half of the reported heap size for the maximum buffer size, we
472e5c31af7Sopenharmony_ci	// should attempt to test as large a portion as possible.
473e5c31af7Sopenharmony_ci	//
474e5c31af7Sopenharmony_ci	// However on a system where device memory is shared with the system, the maximum size
475e5c31af7Sopenharmony_ci	// should be tested against the platform memory limits as a significant portion of the heap
476e5c31af7Sopenharmony_ci	// may already be in use by the operating system and other running processes.
477e5c31af7Sopenharmony_ci	const VkDeviceSize maxBufferSize = getMaxBufferSize(memoryHeap.size,
478e5c31af7Sopenharmony_ci													   memReqs.memoryRequirements.alignment,
479e5c31af7Sopenharmony_ci													   getPlatformMemoryLimits(m_context));
480e5c31af7Sopenharmony_ci
481e5c31af7Sopenharmony_ci	Move<VkDeviceMemory>				memory;
482e5c31af7Sopenharmony_ci	size = deAlign64(std::min(size, maxBufferSize >> 1), memReqs.memoryRequirements.alignment);
483e5c31af7Sopenharmony_ci	while (*memory == DE_NULL)
484e5c31af7Sopenharmony_ci	{
485e5c31af7Sopenharmony_ci		// Create the buffer
486e5c31af7Sopenharmony_ci		{
487e5c31af7Sopenharmony_ci			VkResult					result							= VK_ERROR_OUT_OF_HOST_MEMORY;
488e5c31af7Sopenharmony_ci			VkBuffer					rawBuffer						= DE_NULL;
489e5c31af7Sopenharmony_ci
490e5c31af7Sopenharmony_ci			bufferParams.size = size;
491e5c31af7Sopenharmony_ci			buffer = Move<VkBuffer>(); // free the previous buffer, if any
492e5c31af7Sopenharmony_ci			result = vk.createBuffer(vkDevice, &bufferParams, (VkAllocationCallbacks*)DE_NULL, &rawBuffer);
493e5c31af7Sopenharmony_ci
494e5c31af7Sopenharmony_ci			if (result != VK_SUCCESS)
495e5c31af7Sopenharmony_ci			{
496e5c31af7Sopenharmony_ci				size = deAlign64(size >> shrinkBits, memReqs.memoryRequirements.alignment);
497e5c31af7Sopenharmony_ci
498e5c31af7Sopenharmony_ci				if (size == 0 || bufferParams.size == memReqs.memoryRequirements.alignment)
499e5c31af7Sopenharmony_ci					return tcu::TestStatus::fail("Buffer creation failed! (" + de::toString(getResultName(result)) + ")");
500e5c31af7Sopenharmony_ci
501e5c31af7Sopenharmony_ci				continue; // didn't work, try with a smaller buffer
502e5c31af7Sopenharmony_ci			}
503e5c31af7Sopenharmony_ci
504e5c31af7Sopenharmony_ci			buffer = Move<VkBuffer>(check<VkBuffer>(rawBuffer), Deleter<VkBuffer>(vk, vkDevice, DE_NULL));
505e5c31af7Sopenharmony_ci		}
506e5c31af7Sopenharmony_ci
507e5c31af7Sopenharmony_ci		info.buffer = *buffer;
508e5c31af7Sopenharmony_ci		vk.getBufferMemoryRequirements2(vkDevice, &info, &memReqs);		// get the proper size requirement
509e5c31af7Sopenharmony_ci
510e5c31af7Sopenharmony_ci		if (size > memReqs.memoryRequirements.size)
511e5c31af7Sopenharmony_ci		{
512e5c31af7Sopenharmony_ci			std::ostringstream			errorMsg;
513e5c31af7Sopenharmony_ci			errorMsg << "Requied memory size (" << memReqs.memoryRequirements.size << " bytes) smaller than the buffer's size (" << size << " bytes)!";
514e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail(errorMsg.str());
515e5c31af7Sopenharmony_ci		}
516e5c31af7Sopenharmony_ci
517e5c31af7Sopenharmony_ci		// Allocate the memory
518e5c31af7Sopenharmony_ci		{
519e5c31af7Sopenharmony_ci			VkResult					result							= VK_ERROR_OUT_OF_HOST_MEMORY;
520e5c31af7Sopenharmony_ci			VkDeviceMemory				rawMemory						= DE_NULL;
521e5c31af7Sopenharmony_ci
522e5c31af7Sopenharmony_ci			vk::VkMemoryDedicatedAllocateInfo
523e5c31af7Sopenharmony_ci										dedicatedInfo					=
524e5c31af7Sopenharmony_ci			{
525e5c31af7Sopenharmony_ci				VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,		// VkStructureType			sType
526e5c31af7Sopenharmony_ci				DE_NULL,												// const void*				pNext
527e5c31af7Sopenharmony_ci				DE_NULL,												// VkImage					image
528e5c31af7Sopenharmony_ci				*buffer													// VkBuffer					buffer
529e5c31af7Sopenharmony_ci			};
530e5c31af7Sopenharmony_ci
531e5c31af7Sopenharmony_ci			VkMemoryAllocateInfo		memoryAllocateInfo				=
532e5c31af7Sopenharmony_ci			{
533e5c31af7Sopenharmony_ci				VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,					// VkStructureType			sType
534e5c31af7Sopenharmony_ci				&dedicatedInfo,											// const void*				pNext
535e5c31af7Sopenharmony_ci				memReqs.memoryRequirements.size,						// VkDeviceSize				allocationSize
536e5c31af7Sopenharmony_ci				heapTypeIndex,											// deUint32					memoryTypeIndex
537e5c31af7Sopenharmony_ci			};
538e5c31af7Sopenharmony_ci
539e5c31af7Sopenharmony_ci			result = vk.allocateMemory(vkDevice, &memoryAllocateInfo, (VkAllocationCallbacks*)DE_NULL, &rawMemory);
540e5c31af7Sopenharmony_ci
541e5c31af7Sopenharmony_ci			if (result != VK_SUCCESS)
542e5c31af7Sopenharmony_ci			{
543e5c31af7Sopenharmony_ci				size = deAlign64(size >> shrinkBits, memReqs.memoryRequirements.alignment);
544e5c31af7Sopenharmony_ci
545e5c31af7Sopenharmony_ci				if (size == 0 || memReqs.memoryRequirements.size == memReqs.memoryRequirements.alignment)
546e5c31af7Sopenharmony_ci					return tcu::TestStatus::fail("Unable to allocate " + de::toString(memReqs.memoryRequirements.size) + " bytes of memory");
547e5c31af7Sopenharmony_ci
548e5c31af7Sopenharmony_ci				continue; // didn't work, try with a smaller allocation (and a smaller buffer)
549e5c31af7Sopenharmony_ci			}
550e5c31af7Sopenharmony_ci
551e5c31af7Sopenharmony_ci			memory = Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL));
552e5c31af7Sopenharmony_ci		}
553e5c31af7Sopenharmony_ci	} // while
554e5c31af7Sopenharmony_ci
555e5c31af7Sopenharmony_ci	if (vk.bindBufferMemory(vkDevice, *buffer, *memory, 0) != VK_SUCCESS)
556e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Bind buffer memory failed! (requested memory size: " + de::toString(size) + ")");
557e5c31af7Sopenharmony_ci
558e5c31af7Sopenharmony_ci	return tcu::TestStatus::pass("Pass");
559e5c31af7Sopenharmony_ci}
560e5c31af7Sopenharmony_ci
561e5c31af7Sopenharmony_cistd::string getBufferUsageFlagsName (const VkBufferUsageFlags flags)
562e5c31af7Sopenharmony_ci{
563e5c31af7Sopenharmony_ci	switch (flags)
564e5c31af7Sopenharmony_ci	{
565e5c31af7Sopenharmony_ci		case VK_BUFFER_USAGE_TRANSFER_SRC_BIT:			return "transfer_src";
566e5c31af7Sopenharmony_ci		case VK_BUFFER_USAGE_TRANSFER_DST_BIT:			return "transfer_dst";
567e5c31af7Sopenharmony_ci		case VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT:	return "uniform_texel";
568e5c31af7Sopenharmony_ci		case VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT:	return "storage_texel";
569e5c31af7Sopenharmony_ci		case VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT:		return "uniform";
570e5c31af7Sopenharmony_ci		case VK_BUFFER_USAGE_STORAGE_BUFFER_BIT:		return "storage";
571e5c31af7Sopenharmony_ci		case VK_BUFFER_USAGE_INDEX_BUFFER_BIT:			return "index";
572e5c31af7Sopenharmony_ci		case VK_BUFFER_USAGE_VERTEX_BUFFER_BIT:			return "vertex";
573e5c31af7Sopenharmony_ci		case VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT:		return "indirect";
574e5c31af7Sopenharmony_ci		default:
575e5c31af7Sopenharmony_ci			DE_FATAL("Unknown buffer usage flag");
576e5c31af7Sopenharmony_ci			return "";
577e5c31af7Sopenharmony_ci	}
578e5c31af7Sopenharmony_ci}
579e5c31af7Sopenharmony_ci
580e5c31af7Sopenharmony_cistd::string getBufferCreateFlagsName (const VkBufferCreateFlags flags)
581e5c31af7Sopenharmony_ci{
582e5c31af7Sopenharmony_ci	std::ostringstream name;
583e5c31af7Sopenharmony_ci
584e5c31af7Sopenharmony_ci	if (flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT)
585e5c31af7Sopenharmony_ci		name << "_binding";
586e5c31af7Sopenharmony_ci	if (flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT)
587e5c31af7Sopenharmony_ci		name << "_residency";
588e5c31af7Sopenharmony_ci	if (flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT)
589e5c31af7Sopenharmony_ci		name << "_aliased";
590e5c31af7Sopenharmony_ci	if (flags == 0u)
591e5c31af7Sopenharmony_ci		name << "_zero";
592e5c31af7Sopenharmony_ci
593e5c31af7Sopenharmony_ci	DE_ASSERT(!name.str().empty());
594e5c31af7Sopenharmony_ci
595e5c31af7Sopenharmony_ci	return name.str().substr(1);
596e5c31af7Sopenharmony_ci}
597e5c31af7Sopenharmony_ci
598e5c31af7Sopenharmony_ci// Create all VkBufferUsageFlags combinations recursively
599e5c31af7Sopenharmony_civoid createBufferUsageCases (tcu::TestCaseGroup& testGroup, const deUint32 firstNdx, const deUint32 bufferUsageFlags, const AllocationKind allocationKind)
600e5c31af7Sopenharmony_ci{
601e5c31af7Sopenharmony_ci	const VkBufferUsageFlags			bufferUsageModes[]	=
602e5c31af7Sopenharmony_ci	{
603e5c31af7Sopenharmony_ci		VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
604e5c31af7Sopenharmony_ci		VK_BUFFER_USAGE_TRANSFER_DST_BIT,
605e5c31af7Sopenharmony_ci		VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
606e5c31af7Sopenharmony_ci		VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
607e5c31af7Sopenharmony_ci		VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
608e5c31af7Sopenharmony_ci		VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
609e5c31af7Sopenharmony_ci		VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
610e5c31af7Sopenharmony_ci		VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
611e5c31af7Sopenharmony_ci		VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
612e5c31af7Sopenharmony_ci	};
613e5c31af7Sopenharmony_ci
614e5c31af7Sopenharmony_ci	tcu::TestContext&					testCtx				= testGroup.getTestContext();
615e5c31af7Sopenharmony_ci
616e5c31af7Sopenharmony_ci	// Add test groups
617e5c31af7Sopenharmony_ci	for (deUint32 currentNdx = firstNdx; currentNdx < DE_LENGTH_OF_ARRAY(bufferUsageModes); currentNdx++)
618e5c31af7Sopenharmony_ci	{
619e5c31af7Sopenharmony_ci		const deUint32					newBufferUsageFlags	= bufferUsageFlags | bufferUsageModes[currentNdx];
620e5c31af7Sopenharmony_ci		const std::string				newGroupName		= getBufferUsageFlagsName(bufferUsageModes[currentNdx]);
621e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup>	newTestGroup		(new tcu::TestCaseGroup(testCtx, newGroupName.c_str()));
622e5c31af7Sopenharmony_ci
623e5c31af7Sopenharmony_ci		createBufferUsageCases(*newTestGroup, currentNdx + 1u, newBufferUsageFlags, allocationKind);
624e5c31af7Sopenharmony_ci		testGroup.addChild(newTestGroup.release());
625e5c31af7Sopenharmony_ci	}
626e5c31af7Sopenharmony_ci
627e5c31af7Sopenharmony_ci	// Add test cases
628e5c31af7Sopenharmony_ci	if (bufferUsageFlags != 0u)
629e5c31af7Sopenharmony_ci	{
630e5c31af7Sopenharmony_ci		// \note SPARSE_RESIDENCY and SPARSE_ALIASED have to be used together with the SPARSE_BINDING flag.
631e5c31af7Sopenharmony_ci		const VkBufferCreateFlags		bufferCreateFlags[]		=
632e5c31af7Sopenharmony_ci		{
633e5c31af7Sopenharmony_ci			0,
634e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
635e5c31af7Sopenharmony_ci			VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
636e5c31af7Sopenharmony_ci			VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
637e5c31af7Sopenharmony_ci			VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,
638e5c31af7Sopenharmony_ci			VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,
639e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
640e5c31af7Sopenharmony_ci		};
641e5c31af7Sopenharmony_ci
642e5c31af7Sopenharmony_ci		// Dedicated allocation does not support sparse feature
643e5c31af7Sopenharmony_ci		const int						numBufferCreateFlags	= (allocationKind == ALLOCATION_KIND_SUBALLOCATED) ? DE_LENGTH_OF_ARRAY(bufferCreateFlags) : 1;
644e5c31af7Sopenharmony_ci
645e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup>	newTestGroup			(new tcu::TestCaseGroup(testCtx, "create"));
646e5c31af7Sopenharmony_ci
647e5c31af7Sopenharmony_ci		for (int bufferCreateFlagsNdx = 0; bufferCreateFlagsNdx < numBufferCreateFlags; bufferCreateFlagsNdx++)
648e5c31af7Sopenharmony_ci		{
649e5c31af7Sopenharmony_ci			const BufferCaseParameters	testParams	=
650e5c31af7Sopenharmony_ci			{
651e5c31af7Sopenharmony_ci				bufferUsageFlags,
652e5c31af7Sopenharmony_ci				bufferCreateFlags[bufferCreateFlagsNdx],
653e5c31af7Sopenharmony_ci				VK_SHARING_MODE_EXCLUSIVE
654e5c31af7Sopenharmony_ci			};
655e5c31af7Sopenharmony_ci
656e5c31af7Sopenharmony_ci			const std::string			allocStr	= (allocationKind == ALLOCATION_KIND_SUBALLOCATED) ? "suballocation of " : "dedicated alloc. of ";
657e5c31af7Sopenharmony_ci			const std::string			caseName	= getBufferCreateFlagsName(bufferCreateFlags[bufferCreateFlagsNdx]);
658e5c31af7Sopenharmony_ci
659e5c31af7Sopenharmony_ci			switch (allocationKind)
660e5c31af7Sopenharmony_ci			{
661e5c31af7Sopenharmony_ci				case ALLOCATION_KIND_SUBALLOCATED:
662e5c31af7Sopenharmony_ci					newTestGroup->addChild(new BuffersTestCase(testCtx, caseName.c_str(), testParams));
663e5c31af7Sopenharmony_ci					break;
664e5c31af7Sopenharmony_ci				case ALLOCATION_KIND_DEDICATED:
665e5c31af7Sopenharmony_ci					newTestGroup->addChild(new DedicatedAllocationBuffersTestCase(testCtx, caseName.c_str(), testParams));
666e5c31af7Sopenharmony_ci					break;
667e5c31af7Sopenharmony_ci				default:
668e5c31af7Sopenharmony_ci					DE_FATAL("Unknown test type");
669e5c31af7Sopenharmony_ci			}
670e5c31af7Sopenharmony_ci		}
671e5c31af7Sopenharmony_ci		testGroup.addChild(newTestGroup.release());
672e5c31af7Sopenharmony_ci	}
673e5c31af7Sopenharmony_ci}
674e5c31af7Sopenharmony_ci
675e5c31af7Sopenharmony_citcu::TestStatus testDepthStencilBufferFeatures(Context& context, VkFormat format)
676e5c31af7Sopenharmony_ci{
677e5c31af7Sopenharmony_ci	const InstanceInterface&	vki				= context.getInstanceInterface();
678e5c31af7Sopenharmony_ci	VkPhysicalDevice			physicalDevice	= context.getPhysicalDevice();
679e5c31af7Sopenharmony_ci	VkFormatProperties			formatProperties;
680e5c31af7Sopenharmony_ci
681e5c31af7Sopenharmony_ci	vki.getPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties);
682e5c31af7Sopenharmony_ci
683e5c31af7Sopenharmony_ci	if (formatProperties.bufferFeatures == 0x0)
684e5c31af7Sopenharmony_ci		return tcu::TestStatus::pass("Pass");
685e5c31af7Sopenharmony_ci	else
686e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Fail");
687e5c31af7Sopenharmony_ci}
688e5c31af7Sopenharmony_ci
689e5c31af7Sopenharmony_cistruct LargeBufferParameters
690e5c31af7Sopenharmony_ci{
691e5c31af7Sopenharmony_ci	deUint64				bufferSize;
692e5c31af7Sopenharmony_ci	bool					useMaxBufferSize;
693e5c31af7Sopenharmony_ci	VkBufferCreateFlags		flags;
694e5c31af7Sopenharmony_ci};
695e5c31af7Sopenharmony_ci
696e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
697e5c31af7Sopenharmony_citcu::TestStatus testLargeBuffer(Context& context, LargeBufferParameters params)
698e5c31af7Sopenharmony_ci{
699e5c31af7Sopenharmony_ci	const DeviceInterface&			vk					= context.getDeviceInterface();
700e5c31af7Sopenharmony_ci	const VkDevice					vkDevice			= context.getDevice();
701e5c31af7Sopenharmony_ci	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
702e5c31af7Sopenharmony_ci	const VkPhysicalDeviceLimits	limits				= getPhysicalDeviceProperties(context.getInstanceInterface(),
703e5c31af7Sopenharmony_ci				                                                                      context.getPhysicalDevice()).limits;
704e5c31af7Sopenharmony_ci	VkBuffer						rawBuffer			= DE_NULL;
705e5c31af7Sopenharmony_ci
706e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
707e5c31af7Sopenharmony_ci	if (params.useMaxBufferSize)
708e5c31af7Sopenharmony_ci		params.bufferSize = context.getMaintenance4Properties().maxBufferSize;
709e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
710e5c31af7Sopenharmony_ci
711e5c31af7Sopenharmony_ci	if ((params.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0)
712e5c31af7Sopenharmony_ci		params.bufferSize = std::min(params.bufferSize, limits.sparseAddressSpaceSize);
713e5c31af7Sopenharmony_ci
714e5c31af7Sopenharmony_ci	VkBufferCreateInfo bufferParams =
715e5c31af7Sopenharmony_ci	{
716e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType			sType;
717e5c31af7Sopenharmony_ci		DE_NULL,								// const void*				pNext;
718e5c31af7Sopenharmony_ci		params.flags,							// VkBufferCreateFlags		flags;
719e5c31af7Sopenharmony_ci		params.bufferSize,						// VkDeviceSize				size;
720e5c31af7Sopenharmony_ci		VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,		// VkBufferUsageFlags		usage;
721e5c31af7Sopenharmony_ci		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
722e5c31af7Sopenharmony_ci		1u,										// uint32_t					queueFamilyIndexCount;
723e5c31af7Sopenharmony_ci		&queueFamilyIndex,						// const uint32_t*			pQueueFamilyIndices;
724e5c31af7Sopenharmony_ci	};
725e5c31af7Sopenharmony_ci
726e5c31af7Sopenharmony_ci	VkResult result = vk.createBuffer(vkDevice, &bufferParams, (vk::VkAllocationCallbacks*)DE_NULL, &rawBuffer);
727e5c31af7Sopenharmony_ci
728e5c31af7Sopenharmony_ci	// if buffer creation succeeds verify that the correct amount of memory was bound to it
729e5c31af7Sopenharmony_ci	if (result == VK_SUCCESS)
730e5c31af7Sopenharmony_ci	{
731e5c31af7Sopenharmony_ci		VkMemoryRequirements memoryRequirements;
732e5c31af7Sopenharmony_ci		vk.getBufferMemoryRequirements(vkDevice, rawBuffer, &memoryRequirements);
733e5c31af7Sopenharmony_ci		vk.destroyBuffer(vkDevice, rawBuffer, DE_NULL);
734e5c31af7Sopenharmony_ci
735e5c31af7Sopenharmony_ci		if (memoryRequirements.size >= params.bufferSize)
736e5c31af7Sopenharmony_ci			return tcu::TestStatus::pass("Pass");
737e5c31af7Sopenharmony_ci		return tcu::TestStatus::fail("Fail");
738e5c31af7Sopenharmony_ci	}
739e5c31af7Sopenharmony_ci
740e5c31af7Sopenharmony_ci	// check if one of the allowed errors was returned
741e5c31af7Sopenharmony_ci	if ((result == VK_ERROR_OUT_OF_DEVICE_MEMORY) ||
742e5c31af7Sopenharmony_ci		(result == VK_ERROR_OUT_OF_HOST_MEMORY))
743e5c31af7Sopenharmony_ci		return tcu::TestStatus::pass("Pass");
744e5c31af7Sopenharmony_ci
745e5c31af7Sopenharmony_ci	return tcu::TestStatus::fail("Fail");
746e5c31af7Sopenharmony_ci}
747e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
748e5c31af7Sopenharmony_ci
749e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
750e5c31af7Sopenharmony_civoid checkMaintenance4Support(Context& context, LargeBufferParameters params)
751e5c31af7Sopenharmony_ci{
752e5c31af7Sopenharmony_ci	if (params.useMaxBufferSize)
753e5c31af7Sopenharmony_ci		context.requireDeviceFunctionality("VK_KHR_maintenance4");
754e5c31af7Sopenharmony_ci	else if (context.isDeviceFunctionalitySupported("VK_KHR_maintenance4") &&
755e5c31af7Sopenharmony_ci		params.bufferSize > context.getMaintenance4Properties().maxBufferSize)
756e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "vkCreateBuffer with a size larger than maxBufferSize is not valid usage");
757e5c31af7Sopenharmony_ci
758e5c31af7Sopenharmony_ci	const VkPhysicalDeviceFeatures& physicalDeviceFeatures = getPhysicalDeviceFeatures(context.getInstanceInterface(), context.getPhysicalDevice());
759e5c31af7Sopenharmony_ci	if ((params.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) && !physicalDeviceFeatures.sparseBinding)
760e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Sparse bindings feature is not supported");
761e5c31af7Sopenharmony_ci}
762e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
763e5c31af7Sopenharmony_ci
764e5c31af7Sopenharmony_ci} // anonymous
765e5c31af7Sopenharmony_ci
766e5c31af7Sopenharmony_ci tcu::TestCaseGroup* createBufferTests (tcu::TestContext& testCtx)
767e5c31af7Sopenharmony_ci{
768e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> buffersTests (new tcu::TestCaseGroup(testCtx, "buffer"));
769e5c31af7Sopenharmony_ci
770e5c31af7Sopenharmony_ci	{
771e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup>	regularAllocation	(new tcu::TestCaseGroup(testCtx, "suballocation"));
772e5c31af7Sopenharmony_ci		createBufferUsageCases(*regularAllocation, 0u, 0u, ALLOCATION_KIND_SUBALLOCATED);
773e5c31af7Sopenharmony_ci		buffersTests->addChild(regularAllocation.release());
774e5c31af7Sopenharmony_ci	}
775e5c31af7Sopenharmony_ci
776e5c31af7Sopenharmony_ci	{
777e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup>	dedicatedAllocation	(new tcu::TestCaseGroup(testCtx, "dedicated_alloc"));
778e5c31af7Sopenharmony_ci		createBufferUsageCases(*dedicatedAllocation, 0u, 0u, ALLOCATION_KIND_DEDICATED);
779e5c31af7Sopenharmony_ci		buffersTests->addChild(dedicatedAllocation.release());
780e5c31af7Sopenharmony_ci	}
781e5c31af7Sopenharmony_ci
782e5c31af7Sopenharmony_ci	{
783e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "basic"));
784e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
785e5c31af7Sopenharmony_ci		// Creating buffer using maxBufferSize limit.
786e5c31af7Sopenharmony_ci		addFunctionCase(basicTests.get(), "max_size",
787e5c31af7Sopenharmony_ci						checkMaintenance4Support, testLargeBuffer, LargeBufferParameters
788e5c31af7Sopenharmony_ci						{
789e5c31af7Sopenharmony_ci							0u,
790e5c31af7Sopenharmony_ci							true,
791e5c31af7Sopenharmony_ci							0u
792e5c31af7Sopenharmony_ci						});
793e5c31af7Sopenharmony_ci		// Creating sparse buffer using maxBufferSize limit.
794e5c31af7Sopenharmony_ci		addFunctionCase(basicTests.get(), "max_size_sparse",
795e5c31af7Sopenharmony_ci						checkMaintenance4Support, testLargeBuffer, LargeBufferParameters
796e5c31af7Sopenharmony_ci						{
797e5c31af7Sopenharmony_ci							0u,
798e5c31af7Sopenharmony_ci							true,
799e5c31af7Sopenharmony_ci							VK_BUFFER_CREATE_SPARSE_BINDING_BIT
800e5c31af7Sopenharmony_ci						});
801e5c31af7Sopenharmony_ci		// Creating a ULLONG_MAX buffer and verify that it either succeeds or returns one of the allowed errors.
802e5c31af7Sopenharmony_ci		addFunctionCase(basicTests.get(), "size_max_uint64",
803e5c31af7Sopenharmony_ci						checkMaintenance4Support, testLargeBuffer, LargeBufferParameters
804e5c31af7Sopenharmony_ci						{
805e5c31af7Sopenharmony_ci							std::numeric_limits<deUint64>::max(),
806e5c31af7Sopenharmony_ci							false,
807e5c31af7Sopenharmony_ci							0u
808e5c31af7Sopenharmony_ci						});
809e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
810e5c31af7Sopenharmony_ci		buffersTests->addChild(basicTests.release());
811e5c31af7Sopenharmony_ci	}
812e5c31af7Sopenharmony_ci
813e5c31af7Sopenharmony_ci	{
814e5c31af7Sopenharmony_ci		static const VkFormat dsFormats[] =
815e5c31af7Sopenharmony_ci		{
816e5c31af7Sopenharmony_ci			VK_FORMAT_S8_UINT,
817e5c31af7Sopenharmony_ci			VK_FORMAT_D16_UNORM,
818e5c31af7Sopenharmony_ci			VK_FORMAT_D16_UNORM_S8_UINT,
819e5c31af7Sopenharmony_ci			VK_FORMAT_D24_UNORM_S8_UINT,
820e5c31af7Sopenharmony_ci			VK_FORMAT_D32_SFLOAT,
821e5c31af7Sopenharmony_ci			VK_FORMAT_D32_SFLOAT_S8_UINT,
822e5c31af7Sopenharmony_ci			VK_FORMAT_X8_D24_UNORM_PACK32
823e5c31af7Sopenharmony_ci		};
824e5c31af7Sopenharmony_ci
825e5c31af7Sopenharmony_ci		// Checks that drivers are not exposing undesired format features for depth/stencil formats.
826e5c31af7Sopenharmony_ci		de::MovePtr<tcu::TestCaseGroup>	invalidBufferFeatures(new tcu::TestCaseGroup(testCtx, "invalid_buffer_features"));
827e5c31af7Sopenharmony_ci
828e5c31af7Sopenharmony_ci		for (const auto& testFormat : dsFormats)
829e5c31af7Sopenharmony_ci		{
830e5c31af7Sopenharmony_ci			std::string formatName = de::toLower(getFormatName(testFormat));
831e5c31af7Sopenharmony_ci
832e5c31af7Sopenharmony_ci			addFunctionCase(invalidBufferFeatures.get(), formatName, testDepthStencilBufferFeatures, testFormat);
833e5c31af7Sopenharmony_ci		}
834e5c31af7Sopenharmony_ci
835e5c31af7Sopenharmony_ci		buffersTests->addChild(invalidBufferFeatures.release());
836e5c31af7Sopenharmony_ci	}
837e5c31af7Sopenharmony_ci
838e5c31af7Sopenharmony_ci	return buffersTests.release();
839e5c31af7Sopenharmony_ci}
840e5c31af7Sopenharmony_ci
841e5c31af7Sopenharmony_ci} // api
842e5c31af7Sopenharmony_ci} // vk
843