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 Buffers Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktApiBufferTests.hpp"
26
27 #include "deStringUtil.hpp"
28 #include "gluVarType.hpp"
29 #include "tcuTestLog.hpp"
30 #include "vkPrograms.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vktTestCase.hpp"
34
35 namespace vkt
36 {
37
38 using namespace vk;
39
40 namespace api
41 {
42
43 namespace
44 {
45
46 static const deUint32 MAX_BUFFER_SIZE_DIVISOR = 16;
47
48 struct BufferCaseParameters
49 {
50 VkBufferUsageFlags usage;
51 VkBufferCreateFlags flags;
52 VkSharingMode sharingMode;
53 };
54
55 class BufferTestInstance : public TestInstance
56 {
57 public:
BufferTestInstance(Context & ctx,BufferCaseParameters testCase)58 BufferTestInstance (Context& ctx,
59 BufferCaseParameters testCase)
60 : TestInstance (ctx)
61 , m_testCase (testCase)
62 {}
63 virtual tcu::TestStatus iterate (void);
64 tcu::TestStatus bufferCreateAndAllocTest (VkDeviceSize size);
65
66 private:
67 BufferCaseParameters m_testCase;
68 };
69
70 class BuffersTestCase : public TestCase
71 {
72 public:
BuffersTestCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,BufferCaseParameters testCase)73 BuffersTestCase (tcu::TestContext& testCtx,
74 const std::string& name,
75 const std::string& description,
76 BufferCaseParameters testCase)
77 : TestCase(testCtx, name, description)
78 , m_testCase(testCase)
79 {}
80
~BuffersTestCase(void)81 virtual ~BuffersTestCase (void) {}
createInstance(Context & ctx) const82 virtual TestInstance* createInstance (Context& ctx) const
83 {
84 tcu::TestLog& log = m_testCtx.getLog();
85 log << tcu::TestLog::Message << getBufferUsageFlagsStr(m_testCase.usage) << tcu::TestLog::EndMessage;
86 return new BufferTestInstance(ctx, m_testCase);
87 }
88
89 private:
90 BufferCaseParameters m_testCase;
91 };
92
bufferCreateAndAllocTest(VkDeviceSize size)93 tcu::TestStatus BufferTestInstance::bufferCreateAndAllocTest (VkDeviceSize size)
94 {
95 const VkPhysicalDevice vkPhysicalDevice = m_context.getPhysicalDevice();
96 const InstanceInterface& vkInstance = m_context.getInstanceInterface();
97 const VkDevice vkDevice = m_context.getDevice();
98 const DeviceInterface& vk = m_context.getDeviceInterface();
99 Move<VkBuffer> testBuffer;
100 VkMemoryRequirements memReqs;
101 Move<VkDeviceMemory> memory;
102 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
103 const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(vkInstance, vkPhysicalDevice);
104
105 // Create buffer
106 {
107 VkBufferCreateInfo bufferParams =
108 {
109 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
110 DE_NULL,
111 m_testCase.flags,
112 size,
113 m_testCase.usage,
114 m_testCase.sharingMode,
115 1u, // deUint32 queueFamilyCount;
116 &queueFamilyIndex,
117 };
118
119 try
120 {
121 testBuffer = createBuffer(vk, vkDevice, &bufferParams);
122 }
123 catch (const vk::Error& error)
124 {
125 return tcu::TestStatus::fail("Buffer creation failed! (requested memory size: " + de::toString(size) + ", Error code: " + de::toString(error.getMessage()) + ")");
126 }
127
128 vk.getBufferMemoryRequirements(vkDevice, *testBuffer, &memReqs);
129
130 const deUint32 heapTypeIndex = (deUint32)deCtz32(memReqs.memoryTypeBits);
131 const VkMemoryType memoryType = memoryProperties.memoryTypes[heapTypeIndex];
132 const VkMemoryHeap memoryHeap = memoryProperties.memoryHeaps[memoryType.heapIndex];
133 const VkDeviceSize maxBufferSize = memoryHeap.size / MAX_BUFFER_SIZE_DIVISOR;
134 // If the requested size is too large, clamp it based on the selected heap size
135 if (size > maxBufferSize)
136 {
137 size = maxBufferSize;
138 bufferParams.size = size;
139 try
140 {
141 // allocate a new buffer with the adjusted size, the old one will be destroyed by the smart pointer
142 testBuffer = createBuffer(vk, vkDevice, &bufferParams);
143 }
144 catch (const vk::Error& error)
145 {
146 return tcu::TestStatus::fail("Buffer creation failed! (requested memory size: " + de::toString(size) + ", Error code: " + de::toString(error.getMessage()) + ")");
147 }
148 vk.getBufferMemoryRequirements(vkDevice, *testBuffer, &memReqs);
149 }
150
151 if (size > memReqs.size)
152 {
153 std::ostringstream errorMsg;
154 errorMsg << "Requied memory size (" << memReqs.size << " bytes) smaller than the buffer's size (" << size << " bytes)!";
155 return tcu::TestStatus::fail(errorMsg.str());
156 }
157 }
158
159 // Allocate and bind memory
160 {
161 const VkMemoryAllocateInfo memAlloc =
162 {
163 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
164 NULL,
165 memReqs.size,
166 (deUint32)deCtz32(memReqs.memoryTypeBits) // deUint32 memoryTypeIndex
167 };
168
169 try
170 {
171 memory = allocateMemory(vk, vkDevice, &memAlloc, (const VkAllocationCallbacks*)DE_NULL);
172 }
173 catch (const vk::Error& error)
174 {
175 return tcu::TestStatus::fail("Alloc memory failed! (requested memory size: " + de::toString(size) + ", Error code: " + de::toString(error.getMessage()) + ")");
176 }
177
178 if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) ||
179 (m_testCase.flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) ||
180 (m_testCase.flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT))
181 {
182 VkQueue queue = 0;
183
184 vk.getDeviceQueue(vkDevice, queueFamilyIndex, 0, &queue);
185
186 const VkSparseMemoryBind sparseMemoryBind =
187 {
188 0, // VkDeviceSize resourceOffset;
189 memReqs.size, // VkDeviceSize size;
190 *memory, // VkDeviceMemory memory;
191 0, // VkDeviceSize memoryOffset;
192 0 // VkSparseMemoryBindFlags flags;
193 };
194
195 const VkSparseBufferMemoryBindInfo sparseBufferMemoryBindInfo =
196 {
197 *testBuffer, // VkBuffer buffer;
198 1u, // deUint32 bindCount;
199 &sparseMemoryBind // const VkSparseMemoryBind* pBinds;
200 };
201
202 const VkBindSparseInfo bindSparseInfo =
203 {
204 VK_STRUCTURE_TYPE_BIND_SPARSE_INFO, // VkStructureType sType;
205 DE_NULL, // const void* pNext;
206 0, // deUint32 waitSemaphoreCount;
207 DE_NULL, // const VkSemaphore* pWaitSemaphores;
208 1u, // deUint32 bufferBindCount;
209 &sparseBufferMemoryBindInfo, // const VkSparseBufferMemoryBindInfo* pBufferBinds;
210 0, // deUint32 imageOpaqueBindCount;
211 DE_NULL, // const VkSparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds;
212 0, // deUint32 imageBindCount;
213 DE_NULL, // const VkSparseImageMemoryBindInfo* pImageBinds;
214 0, // deUint32 signalSemaphoreCount;
215 DE_NULL, // const VkSemaphore* pSignalSemaphores;
216 };
217
218 const VkFenceCreateInfo fenceParams =
219 {
220 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
221 DE_NULL, // const void* pNext;
222 0u // VkFenceCreateFlags flags;
223 };
224
225 const vk::Unique<vk::VkFence> fence(vk::createFence(vk, vkDevice, &fenceParams));
226
227 VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
228 if (vk.queueBindSparse(queue, 1, &bindSparseInfo, *fence) != VK_SUCCESS)
229 return tcu::TestStatus::fail("Bind sparse buffer memory failed! (requested memory size: " + de::toString(size) + ")");
230
231 VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), VK_TRUE, ~(0ull) /* infinity */));
232 } else
233 if (vk.bindBufferMemory(vkDevice, *testBuffer, *memory, 0) != VK_SUCCESS)
234 return tcu::TestStatus::fail("Bind buffer memory failed! (requested memory size: " + de::toString(size) + ")");
235 }
236
237 return tcu::TestStatus::pass("Buffer test");
238 }
239
iterate(void)240 tcu::TestStatus BufferTestInstance::iterate (void)
241 {
242 const VkPhysicalDeviceFeatures& physicalDeviceFeatures = m_context.getDeviceFeatures();
243
244 if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT ) && !physicalDeviceFeatures.sparseBinding)
245 TCU_THROW(NotSupportedError, "Sparse bindings feature is not supported");
246
247 if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT ) && !physicalDeviceFeatures.sparseResidencyBuffer)
248 TCU_THROW(NotSupportedError, "Sparse buffer residency feature is not supported");
249
250 if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT ) && !physicalDeviceFeatures.sparseResidencyAliased)
251 TCU_THROW(NotSupportedError, "Sparse aliased residency feature is not supported");
252
253 const VkDeviceSize testSizes[] =
254 {
255 1,
256 1181,
257 15991,
258 16384
259 };
260 tcu::TestStatus testStatus = tcu::TestStatus::pass("Buffer test");
261
262 for (int i = 0; i < DE_LENGTH_OF_ARRAY(testSizes); i++)
263 {
264 if ((testStatus = bufferCreateAndAllocTest(testSizes[i])).getCode() != QP_TEST_RESULT_PASS)
265 return testStatus;
266 }
267
268 if (m_testCase.usage & (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT))
269 {
270 const VkPhysicalDevice vkPhysicalDevice = m_context.getPhysicalDevice();
271 const InstanceInterface& vkInstance = m_context.getInstanceInterface();
272 VkPhysicalDeviceProperties props;
273
274 vkInstance.getPhysicalDeviceProperties(vkPhysicalDevice, &props);
275 testStatus = bufferCreateAndAllocTest((VkDeviceSize) props.limits.maxTexelBufferElements);
276 }
277
278 return testStatus;
279 }
280
281 } // anonymous
282
createBufferTests(tcu::TestContext & testCtx)283 tcu::TestCaseGroup* createBufferTests (tcu::TestContext& testCtx)
284 {
285 const VkBufferUsageFlags bufferUsageModes[] =
286 {
287 VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
288 VK_BUFFER_USAGE_TRANSFER_DST_BIT,
289 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
290 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
291 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
292 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
293 VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
294 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
295 VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
296 };
297
298 const VkBufferCreateFlags bufferCreateFlags[] =
299 {
300 VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
301 VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
302 VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
303 };
304
305 de::MovePtr<tcu::TestCaseGroup> buffersTests (new tcu::TestCaseGroup(testCtx, "buffer", "Buffer Tests"));
306
307 deUint32 numberOfBufferUsageFlags = DE_LENGTH_OF_ARRAY(bufferUsageModes);
308 deUint32 numberOfBufferCreateFlags = DE_LENGTH_OF_ARRAY(bufferCreateFlags);
309 deUint32 maximumValueOfBufferUsageFlags = (1 << (numberOfBufferUsageFlags - 1)) - 1;
310 deUint32 maximumValueOfBufferCreateFlags = (1 << (numberOfBufferCreateFlags)) - 1;
311
312 for (deUint32 combinedBufferCreateFlags = 0; combinedBufferCreateFlags <= maximumValueOfBufferCreateFlags; combinedBufferCreateFlags++)
313 {
314 for (deUint32 combinedBufferUsageFlags = 1; combinedBufferUsageFlags <= maximumValueOfBufferUsageFlags; combinedBufferUsageFlags++)
315 {
316 if (combinedBufferCreateFlags == VK_BUFFER_CREATE_SPARSE_ALIASED_BIT)
317 {
318 // spec says: If flags contains VK_BUFFER_CREATE_SPARSE_ALIASED_BIT, it must also contain at least one of
319 // VK_BUFFER_CREATE_SPARSE_BINDING_BIT or VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT
320 continue;
321 }
322 BufferCaseParameters testParams =
323 {
324 combinedBufferUsageFlags,
325 combinedBufferCreateFlags,
326 VK_SHARING_MODE_EXCLUSIVE
327 };
328 std::ostringstream testName;
329 std::ostringstream testDescription;
330 testName << "createBuffer_" << combinedBufferUsageFlags << "_" << combinedBufferCreateFlags;
331 testDescription << "vkCreateBuffer test " << combinedBufferUsageFlags << " " << combinedBufferCreateFlags;
332 buffersTests->addChild(new BuffersTestCase(testCtx, testName.str(), testDescription.str(), testParams));
333 }
334 }
335
336 return buffersTests.release();
337 }
338
339 } // api
340 } // vk
341