Merge vulkancts/vulkan-cts-1.0.0 into vulkancts/vulkan-cts-1.0.1
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / api / vktApiBufferTests.cpp
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 "vkPlatform.hpp"
34 #include "vktTestCase.hpp"
35
36 namespace vkt
37 {
38 namespace api
39 {
40 namespace
41 {
42 using namespace vk;
43
44 struct BufferCaseParameters
45 {
46         VkBufferUsageFlags      usage;
47         VkBufferCreateFlags     flags;
48         VkSharingMode           sharingMode;
49 };
50
51 class BufferTestInstance : public TestInstance
52 {
53 public:
54                                                                 BufferTestInstance                      (Context&                               ctx,
55                                                                                                                          BufferCaseParameters   testCase)
56                                                                         : TestInstance          (ctx)
57                                                                         , m_testCase            (testCase)
58                                                                         , m_sparseContext       (createSparseContext())
59                                                                 {}
60         virtual tcu::TestStatus         iterate                                         (void);
61         tcu::TestStatus                         bufferCreateAndAllocTest        (VkDeviceSize           size);
62
63 private:
64         BufferCaseParameters            m_testCase;
65
66 private:
67         // Custom context for sparse cases
68         struct SparseContext
69         {
70                 SparseContext (Move<VkDevice>& device, const deUint32 queueFamilyIndex, const InstanceInterface& interface)
71                 : m_device                              (device)
72                 , m_queueFamilyIndex    (queueFamilyIndex)
73                 , m_deviceInterface             (interface, *m_device)
74                 {}
75
76                 Unique<VkDevice>        m_device;
77                 const deUint32          m_queueFamilyIndex;
78                 DeviceDriver            m_deviceInterface;
79         };
80
81         de::UniquePtr<SparseContext>    m_sparseContext;
82
83         // Wrapper functions around m_context calls to support sparse cases.
84         VkPhysicalDevice                                getPhysicalDevice (void) const
85         {
86                 // Same in sparse and regular case
87                 return m_context.getPhysicalDevice();
88         }
89
90         VkDevice                                                getDevice (void) const
91         {
92                 if (m_sparseContext)
93                         return *(m_sparseContext->m_device);
94
95                 return m_context.getDevice();
96         }
97
98         const InstanceInterface&                getInstanceInterface (void) const
99         {
100                 // Same in sparse and regular case
101                 return m_context.getInstanceInterface();
102         }
103
104         const DeviceInterface&                  getDeviceInterface (void) const
105         {
106                 if (m_sparseContext)
107                         return m_sparseContext->m_deviceInterface;
108
109                 return m_context.getDeviceInterface();
110         }
111
112         deUint32                                                getUniversalQueueFamilyIndex (void) const
113         {
114                 if (m_sparseContext)
115                         return m_sparseContext->m_queueFamilyIndex;
116
117                 return m_context.getUniversalQueueFamilyIndex();
118         }
119
120         static deUint32                                 findQueueFamilyIndexWithCaps (const InstanceInterface& vkInstance, VkPhysicalDevice physicalDevice, VkQueueFlags requiredCaps)
121         {
122                 const std::vector<VkQueueFamilyProperties>      queueProps      = getPhysicalDeviceQueueFamilyProperties(vkInstance, physicalDevice);
123
124                 for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
125                 {
126                         if ((queueProps[queueNdx].queueFlags & requiredCaps) == requiredCaps)
127                                 return (deUint32)queueNdx;
128                 }
129
130                 TCU_THROW(NotSupportedError, "No matching queue found");
131         }
132
133         // Create the sparseContext
134         SparseContext*                                  createSparseContext     (void) const
135         {
136                 if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) ||
137                         (m_testCase.flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) ||
138                         (m_testCase.flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT))
139                 {
140                         const InstanceInterface&                vk                              = getInstanceInterface();
141                         const VkPhysicalDevice                  physicalDevice  = getPhysicalDevice();
142                         const VkPhysicalDeviceFeatures  deviceFeatures  = getPhysicalDeviceFeatures(vk, physicalDevice);
143
144                         const deUint32 queueIndex = findQueueFamilyIndexWithCaps(vk, physicalDevice, VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_SPARSE_BINDING_BIT);
145
146                         VkDeviceQueueCreateInfo                 queueInfo;
147                         VkDeviceCreateInfo                              deviceInfo;
148                         const float                                             queuePriority   = 1.0f;
149
150                         deMemset(&queueInfo,    0, sizeof(queueInfo));
151                         deMemset(&deviceInfo,   0, sizeof(deviceInfo));
152
153                         queueInfo.sType                                                 = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
154                         queueInfo.pNext                                                 = DE_NULL;
155                         queueInfo.flags                                                 = (VkDeviceQueueCreateFlags)0u;
156                         queueInfo.queueFamilyIndex                              = queueIndex;
157                         queueInfo.queueCount                                    = 1u;
158                         queueInfo.pQueuePriorities                              = &queuePriority;
159
160                         deviceInfo.sType                                                = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
161                         deviceInfo.pNext                                                = DE_NULL;
162                         deviceInfo.queueCreateInfoCount                 = 1u;
163                         deviceInfo.pQueueCreateInfos                    = &queueInfo;
164                         deviceInfo.enabledExtensionCount                = 0u;
165                         deviceInfo.ppEnabledExtensionNames              = DE_NULL;
166                         deviceInfo.enabledLayerCount                    = 0u;
167                         deviceInfo.ppEnabledLayerNames                  = DE_NULL;
168                         deviceInfo.pEnabledFeatures                             = &deviceFeatures;
169
170                         Move<VkDevice>  device = createDevice(vk, physicalDevice, &deviceInfo);
171
172                         return new SparseContext(device, queueIndex, vk);
173                 }
174
175                 return DE_NULL;
176         }
177 };
178
179 class BuffersTestCase : public TestCase
180 {
181 public:
182                                                         BuffersTestCase         (tcu::TestContext&              testCtx,
183                                                                                                  const std::string&             name,
184                                                                                                  const std::string&             description,
185                                                                                                  BufferCaseParameters   testCase)
186                                                                 : TestCase(testCtx, name, description)
187                                                                 , m_testCase(testCase)
188                                                         {}
189
190         virtual                                 ~BuffersTestCase        (void) {}
191         virtual TestInstance*   createInstance          (Context&                               ctx) const
192                                                         {
193                                                                 tcu::TestLog& log       = m_testCtx.getLog();
194                                                                 log << tcu::TestLog::Message << getBufferUsageFlagsStr(m_testCase.usage) << tcu::TestLog::EndMessage;
195                                                                 return new BufferTestInstance(ctx, m_testCase);
196                                                         }
197
198 private:
199         BufferCaseParameters            m_testCase;
200 };
201
202 inline VkDeviceSize alignDeviceSize (VkDeviceSize val, VkDeviceSize align)
203 {
204         DE_ASSERT(deIsPowerOfTwo64(align));
205         DE_ASSERT(val + align >= val);                          // crash on overflow
206         return (val + align - 1) & ~(align - 1);
207 }
208
209 tcu::TestStatus BufferTestInstance::bufferCreateAndAllocTest (VkDeviceSize size)
210 {
211         const VkPhysicalDevice                                  vkPhysicalDevice        = getPhysicalDevice();
212         const InstanceInterface&                                vkInstance                      = getInstanceInterface();
213         const VkDevice                                                  vkDevice                        = getDevice();
214         const DeviceInterface&                                  vk                                      = getDeviceInterface();
215         const deUint32                                                  queueFamilyIndex        = getUniversalQueueFamilyIndex();
216         const VkPhysicalDeviceMemoryProperties  memoryProperties        = getPhysicalDeviceMemoryProperties(vkInstance, vkPhysicalDevice);
217         const VkPhysicalDeviceLimits                    limits                          = getPhysicalDeviceProperties(vkInstance, vkPhysicalDevice).limits;
218         Move<VkBuffer>                                                  buffer;
219         Move<VkDeviceMemory>                                    memory;
220         VkMemoryRequirements                                    memReqs;
221
222         if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0)
223                 size = std::min(size, limits.sparseAddressSpaceSize);
224
225         // Create the test buffer and a memory allocation for it
226         {
227                 // Create a minimal buffer first to get the supported memory types
228                 VkBufferCreateInfo bufferParams =
229                 {
230                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // VkStructureType        sType;
231                         DE_NULL,                                                                // const void*            pNext;
232                         m_testCase.flags,                                               // VkBufferCreateFlags    flags;
233                         1u,                                                                             // VkDeviceSize           size;
234                         m_testCase.usage,                                               // VkBufferUsageFlags     usage;
235                         m_testCase.sharingMode,                                 // VkSharingMode          sharingMode;
236                         1u,                                                                             // uint32_t               queueFamilyIndexCount;
237                         &queueFamilyIndex,                                              // const uint32_t*        pQueueFamilyIndices;
238                 };
239
240                 buffer = createBuffer(vk, vkDevice, &bufferParams);
241                 vk.getBufferMemoryRequirements(vkDevice, *buffer, &memReqs);
242
243                 const deUint32          heapTypeIndex   = (deUint32)deCtz32(memReqs.memoryTypeBits);
244                 const VkMemoryType      memoryType              = memoryProperties.memoryTypes[heapTypeIndex];
245                 const VkMemoryHeap      memoryHeap              = memoryProperties.memoryHeaps[memoryType.heapIndex];
246                 const VkDeviceSize      maxBufferSize   = alignDeviceSize(memoryHeap.size >> 1, memReqs.alignment);
247                 const deUint32          shrinkBits              = 4;    // number of bits to shift when reducing the size with each iteration
248
249                 size = std::min(size, maxBufferSize);
250
251                 while (*memory == DE_NULL)
252                 {
253                         // Create the buffer
254                         {
255                                 VkResult result         = VK_ERROR_OUT_OF_HOST_MEMORY;
256                                 VkBuffer rawBuffer      = DE_NULL;
257
258                                 bufferParams.size       = size;
259                                 buffer                          = Move<VkBuffer>();             // free the previous buffer, if any
260                                 result                          = vk.createBuffer(vkDevice, &bufferParams, (VkAllocationCallbacks*)DE_NULL, &rawBuffer);
261
262                                 if (result != VK_SUCCESS)
263                                 {
264                                         size = alignDeviceSize(size >> shrinkBits, memReqs.alignment);
265
266                                         if (size == 0 || bufferParams.size == memReqs.alignment)
267                                                 return tcu::TestStatus::fail("Buffer creation failed! (" + de::toString(getResultName(result)) + ")");
268
269                                         continue;       // didn't work, try with a smaller buffer
270                                 }
271
272                                 buffer = Move<VkBuffer>(check<VkBuffer>(rawBuffer), Deleter<VkBuffer>(vk, vkDevice, DE_NULL));
273                         }
274
275                         vk.getBufferMemoryRequirements(vkDevice, *buffer, &memReqs);    // get the proper size requirement
276
277                         if (size > memReqs.size)
278                         {
279                                 std::ostringstream errorMsg;
280                                 errorMsg << "Requied memory size (" << memReqs.size << " bytes) smaller than the buffer's size (" << size << " bytes)!";
281                                 return tcu::TestStatus::fail(errorMsg.str());
282                         }
283
284                         // Allocate the memory
285                         {
286                                 VkResult                result                  = VK_ERROR_OUT_OF_HOST_MEMORY;
287                                 VkDeviceMemory  rawMemory               = DE_NULL;
288
289                                 const VkMemoryAllocateInfo memAlloc =
290                                 {
291                                         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,         // VkStructureType    sType;
292                                         NULL,                                                                           // const void*        pNext;
293                                         memReqs.size,                                                           // VkDeviceSize       allocationSize;
294                                         heapTypeIndex,                                                          // uint32_t           memoryTypeIndex;
295                                 };
296
297                                 result = vk.allocateMemory(vkDevice, &memAlloc, (VkAllocationCallbacks*)DE_NULL, &rawMemory);
298
299                                 if (result != VK_SUCCESS)
300                                 {
301                                         size = alignDeviceSize(size >> shrinkBits, memReqs.alignment);
302
303                                         if (size == 0 || memReqs.size == memReqs.alignment)
304                                                 return tcu::TestStatus::fail("Unable to allocate " + de::toString(memReqs.size) + " bytes of memory");
305
306                                         continue;       // didn't work, try with a smaller allocation (and a smaller buffer)
307                                 }
308
309                                 memory = Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL));
310                         }
311                 } // while
312         }
313
314         // Bind the memory
315         if ((m_testCase.flags & (VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT)) != 0)
316         {
317                 VkQueue                                                         queue                                   = DE_NULL;
318
319                 vk.getDeviceQueue(vkDevice, queueFamilyIndex, 0, &queue);
320
321                 const VkSparseMemoryBind                        sparseMemoryBind                =
322                 {
323                         0,                                                                              // VkDeviceSize                                                         resourceOffset;
324                         memReqs.size,                                                   // VkDeviceSize                                                         size;
325                         *memory,                                                                // VkDeviceMemory                                                       memory;
326                         0,                                                                              // VkDeviceSize                                                         memoryOffset;
327                         0                                                                               // VkSparseMemoryBindFlags                                      flags;
328                 };
329
330                 const VkSparseBufferMemoryBindInfo      sparseBufferMemoryBindInfo      =
331                 {
332                         *buffer,                                                        // VkBuffer                                                                     buffer;
333                         1u,                                                                             // deUint32                                                                     bindCount;
334                         &sparseMemoryBind                                               // const VkSparseMemoryBind*                            pBinds;
335                 };
336
337                 const VkBindSparseInfo                          bindSparseInfo                  =
338                 {
339                         VK_STRUCTURE_TYPE_BIND_SPARSE_INFO,             // VkStructureType                                                      sType;
340                         DE_NULL,                                                                // const void*                                                          pNext;
341                         0,                                                                              // deUint32                                                                     waitSemaphoreCount;
342                         DE_NULL,                                                                // const VkSemaphore*                                           pWaitSemaphores;
343                         1u,                                                                             // deUint32                                                                     bufferBindCount;
344                         &sparseBufferMemoryBindInfo,                    // const VkSparseBufferMemoryBindInfo*          pBufferBinds;
345                         0,                                                                              // deUint32                                                                     imageOpaqueBindCount;
346                         DE_NULL,                                                                // const VkSparseImageOpaqueMemoryBindInfo*     pImageOpaqueBinds;
347                         0,                                                                              // deUint32                                                                     imageBindCount;
348                         DE_NULL,                                                                // const VkSparseImageMemoryBindInfo*           pImageBinds;
349                         0,                                                                              // deUint32                                                                     signalSemaphoreCount;
350                         DE_NULL,                                                                // const VkSemaphore*                                           pSignalSemaphores;
351                 };
352
353                 const VkFenceCreateInfo fenceParams =
354                 {
355                         VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,    // VkStructureType              sType;
356                         DE_NULL,                                                                // const void*                  pNext;
357                         0u                                                                              // VkFenceCreateFlags   flags;
358                 };
359
360                 const vk::Unique<vk::VkFence> fence(vk::createFence(vk, vkDevice, &fenceParams));
361
362                 if (vk.queueBindSparse(queue, 1, &bindSparseInfo, *fence) != VK_SUCCESS)
363                         return tcu::TestStatus::fail("Bind sparse buffer memory failed! (requested memory size: " + de::toString(size) + ")");
364
365                 VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), VK_TRUE, ~(0ull) /* infinity */));
366         }
367         else
368         {
369                 if (vk.bindBufferMemory(vkDevice, *buffer, *memory, 0) != VK_SUCCESS)
370                         return tcu::TestStatus::fail("Bind buffer memory failed! (requested memory size: " + de::toString(size) + ")");
371         }
372
373         return tcu::TestStatus::pass("Pass");
374 }
375
376 tcu::TestStatus BufferTestInstance::iterate (void)
377 {
378         const VkPhysicalDeviceFeatures& physicalDeviceFeatures  = getPhysicalDeviceFeatures(getInstanceInterface(), getPhysicalDevice());
379
380         if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT ) && !physicalDeviceFeatures.sparseBinding)
381                 TCU_THROW(NotSupportedError, "Sparse bindings feature is not supported");
382
383         if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT ) && !physicalDeviceFeatures.sparseResidencyBuffer)
384                 TCU_THROW(NotSupportedError, "Sparse buffer residency feature is not supported");
385
386         if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT ) && !physicalDeviceFeatures.sparseResidencyAliased)
387                 TCU_THROW(NotSupportedError, "Sparse aliased residency feature is not supported");
388
389         const VkDeviceSize testSizes[] =
390         {
391                 1,
392                 1181,
393                 15991,
394                 16384,
395                 ~0ull,          // try to exercise a very large buffer too (will be clamped to a sensible size later)
396         };
397
398         for (int i = 0; i < DE_LENGTH_OF_ARRAY(testSizes); ++i)
399         {
400                 const tcu::TestStatus testStatus = bufferCreateAndAllocTest(testSizes[i]);
401
402                 if (testStatus.getCode() != QP_TEST_RESULT_PASS)
403                         return testStatus;
404         }
405
406         return tcu::TestStatus::pass("Pass");
407 }
408
409 } // anonymous
410
411  tcu::TestCaseGroup* createBufferTests (tcu::TestContext& testCtx)
412 {
413         const VkBufferUsageFlags bufferUsageModes[] =
414         {
415                 VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
416                 VK_BUFFER_USAGE_TRANSFER_DST_BIT,
417                 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
418                 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
419                 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
420                 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
421                 VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
422                 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
423                 VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
424         };
425
426         // \note SPARSE_RESIDENCY and SPARSE_ALIASED have to be used together with the SPARSE_BINDING flag.
427         const VkBufferCreateFlags bufferCreateFlags[] =
428         {
429                 0,
430                 VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
431                 VK_BUFFER_CREATE_SPARSE_BINDING_BIT     |       VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
432                 VK_BUFFER_CREATE_SPARSE_BINDING_BIT     |                                                                                               VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,
433                 VK_BUFFER_CREATE_SPARSE_BINDING_BIT     |       VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT   |       VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,
434         };
435
436         de::MovePtr<tcu::TestCaseGroup> buffersTests    (new tcu::TestCaseGroup(testCtx, "buffer", "Buffer Tests"));
437
438         const deUint32 maximumValueOfBufferUsageFlags   = (1u << (DE_LENGTH_OF_ARRAY(bufferUsageModes) - 1)) - 1u;
439
440         for (deUint32 bufferCreateFlagsNdx = 0u; bufferCreateFlagsNdx < DE_LENGTH_OF_ARRAY(bufferCreateFlags); bufferCreateFlagsNdx++)
441         for (deUint32 combinedBufferUsageFlags = 1u; combinedBufferUsageFlags <= maximumValueOfBufferUsageFlags; combinedBufferUsageFlags++)
442         {
443                 const BufferCaseParameters      testParams =
444                 {
445                         combinedBufferUsageFlags,
446                         bufferCreateFlags[bufferCreateFlagsNdx],
447                         VK_SHARING_MODE_EXCLUSIVE
448                 };
449                 std::ostringstream      testName;
450                 std::ostringstream      testDescription;
451                 testName << "create_buffer_" << combinedBufferUsageFlags << "_" << testParams.flags;
452                 testDescription << "vkCreateBuffer test " << combinedBufferUsageFlags << " " << testParams.flags;
453                 buffersTests->addChild(new BuffersTestCase(testCtx, testName.str(), testDescription.str(), testParams));
454         }
455
456         return buffersTests.release();
457 }
458
459 } // api
460 } // vk