Merge "Merge "Fix color change verification in dithering tests" into nougat-cts-dev...
[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 #include "gluVarType.hpp"
27 #include "deStringUtil.hpp"
28 #include "tcuTestLog.hpp"
29 #include "vkPlatform.hpp"
30 #include "vkPrograms.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vktTestCase.hpp"
34
35 #include <algorithm>
36
37 namespace vkt
38 {
39 namespace api
40 {
41 namespace
42 {
43 using namespace vk;
44
45 enum AllocationKind
46 {
47         ALLOCATION_KIND_SUBALLOCATED = 0,
48         ALLOCATION_KIND_DEDICATED,
49
50         ALLOCATION_KIND_LAST,
51 };
52
53 struct BufferCaseParameters
54 {
55         VkBufferUsageFlags      usage;
56         VkBufferCreateFlags     flags;
57         VkSharingMode           sharingMode;
58 };
59
60 class BufferTestInstance : public TestInstance
61 {
62 public:
63                                                                                 BufferTestInstance                              (Context&                                       ctx,
64                                                                                                                                                  BufferCaseParameters           testCase)
65                                                                                 : TestInstance                                  (ctx)
66                                                                                 , m_testCase                                    (testCase)
67                                                                                 , m_sparseContext                               (createSparseContext())
68         {
69         }
70         virtual tcu::TestStatus                         iterate                                                 (void);
71         virtual tcu::TestStatus                         bufferCreateAndAllocTest                (VkDeviceSize                           size);
72
73 protected:
74         BufferCaseParameters                            m_testCase;
75
76         // Wrapper functions around m_context calls to support sparse cases.
77         VkPhysicalDevice                                        getPhysicalDevice                               (void) const
78         {
79                 // Same in sparse and regular case
80                 return m_context.getPhysicalDevice();
81         }
82
83         VkDevice                                                        getDevice                                               (void) const
84         {
85                 if (m_sparseContext)
86                 {
87                         return *(m_sparseContext->m_device);
88                 }
89                 return m_context.getDevice();
90         }
91
92         const InstanceInterface&                        getInstanceInterface                    (void) const
93         {
94                 // Same in sparse and regular case
95                 return m_context.getInstanceInterface();
96         }
97
98         const DeviceInterface&                          getDeviceInterface                              (void) const
99         {
100                 if (m_sparseContext)
101                 {
102                         return m_sparseContext->m_deviceInterface;
103                 }
104                 return m_context.getDeviceInterface();
105         }
106
107         deUint32                                                        getUniversalQueueFamilyIndex    (void) const
108         {
109                 if (m_sparseContext)
110                 {
111                         return m_sparseContext->m_queueFamilyIndex;
112                 }
113                 return m_context.getUniversalQueueFamilyIndex();
114         }
115
116 private:
117         // Custom context for sparse cases
118         struct SparseContext
119         {
120                                                                                 SparseContext                                   (Move<VkDevice>&                        device,
121                                                                                                                                                  const deUint32                         queueFamilyIndex,
122                                                                                                                                                  const InstanceInterface&       interface)
123                                                                                 : m_device                                              (device)
124                                                                                 , m_queueFamilyIndex                    (queueFamilyIndex)
125                                                                                 , m_deviceInterface                             (interface, *m_device)
126                 {
127                 }
128
129                 Unique<VkDevice>                                m_device;
130                 const deUint32                                  m_queueFamilyIndex;
131                 DeviceDriver                                    m_deviceInterface;
132         };
133
134         de::UniquePtr<SparseContext>            m_sparseContext;
135
136         static deUint32                                         findQueueFamilyIndexWithCaps    (const InstanceInterface&       vkInstance,
137                                                                                                                                                  VkPhysicalDevice                       physicalDevice,
138                                                                                                                                                  VkQueueFlags                           requiredCaps)
139         {
140                 const std::vector<vk::VkQueueFamilyProperties>
141                                                                                 queueProps                                              = getPhysicalDeviceQueueFamilyProperties(vkInstance, physicalDevice);
142
143                 for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
144                 {
145                         if ((queueProps[queueNdx].queueFlags & requiredCaps) == requiredCaps)
146                         {
147                                 return (deUint32)queueNdx;
148                         }
149                 }
150
151                 TCU_THROW(NotSupportedError, "No matching queue found");
152         }
153
154         // Create the sparseContext
155         SparseContext*                                          createSparseContext                             (void) const
156         {
157                 if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT)
158                 ||      (m_testCase.flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT)
159                 ||      (m_testCase.flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT))
160                 {
161                         const InstanceInterface&        vk                                                              = getInstanceInterface();
162                         const VkPhysicalDevice          physicalDevice                                  = getPhysicalDevice();
163                         const vk::VkPhysicalDeviceFeatures
164                                                                                 deviceFeatures                                  = getPhysicalDeviceFeatures(vk, physicalDevice);
165                         const deUint32                          queueIndex                                              = findQueueFamilyIndexWithCaps(vk, physicalDevice, VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_SPARSE_BINDING_BIT);
166                         const float                                     queuePriority                                   = 1.0f;
167                         VkDeviceQueueCreateInfo         queueInfo                                               =
168                         {
169                                 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
170                                 DE_NULL,
171                                 static_cast<VkDeviceQueueCreateFlags>(0u),
172                                 queueIndex,
173                                 1u,
174                                 &queuePriority
175                         };
176                         VkDeviceCreateInfo                      deviceInfo                                              =
177                         {
178                                 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
179                                 DE_NULL,
180                                 static_cast<VkDeviceQueueCreateFlags>(0u),
181                                 1u,
182                                 &queueInfo,
183                                 0u,
184                                 DE_NULL,
185                                 0u,
186                                 DE_NULL,
187                                 &deviceFeatures
188                         };
189
190                         Move<VkDevice>                          device                                                  = createDevice(vk, physicalDevice, &deviceInfo);
191
192                         return new SparseContext(device, queueIndex, vk);
193                 }
194
195                 return DE_NULL;
196         }
197 };
198
199 class DedicatedAllocationBufferTestInstance : public BufferTestInstance
200 {
201 public:
202                                                                                 DedicatedAllocationBufferTestInstance
203                                                                                                                                                 (Context&                                       ctx,
204                                                                                                                                                  BufferCaseParameters           testCase)
205                                                                                 : BufferTestInstance                    (ctx, testCase)
206         {
207         }
208         virtual tcu::TestStatus                         bufferCreateAndAllocTest                (VkDeviceSize                           size);
209 };
210
211 class BuffersTestCase : public TestCase
212 {
213 public:
214                                                                                 BuffersTestCase                                 (tcu::TestContext&                      testCtx,
215                                                                                                                                                  const std::string&                     name,
216                                                                                                                                                  const std::string&                     description,
217                                                                                                                                                  BufferCaseParameters           testCase)
218                                                                                 : TestCase                                              (testCtx, name, description)
219                                                                                 , m_testCase                                    (testCase)
220         {
221         }
222
223         virtual                                                         ~BuffersTestCase                                (void)
224         {
225         }
226
227         virtual TestInstance*                           createInstance                                  (Context&                                       ctx) const
228         {
229                 tcu::TestLog&                                   log                                                             = m_testCtx.getLog();
230                 log << tcu::TestLog::Message << getBufferUsageFlagsStr(m_testCase.usage) << tcu::TestLog::EndMessage;
231                 return new BufferTestInstance(ctx, m_testCase);
232         }
233
234 private:
235         BufferCaseParameters                            m_testCase;
236 };
237
238 class DedicatedAllocationBuffersTestCase : public TestCase
239 {
240         public:
241                                                                                 DedicatedAllocationBuffersTestCase
242                                                                                                                                                 (tcu::TestContext&                      testCtx,
243                                                                                                                                                  const std::string&                     name,
244                                                                                                                                                  const std::string&                     description,
245                                                                                                                                                  BufferCaseParameters           testCase)
246                                                                                 : TestCase                                              (testCtx, name, description)
247                                                                                 , m_testCase                                    (testCase)
248         {
249         }
250
251         virtual                                                         ~DedicatedAllocationBuffersTestCase
252                                                                                                                                                 (void)
253         {
254         }
255
256         virtual TestInstance*                           createInstance                                  (Context&                                       ctx) const
257         {
258                 tcu::TestLog&                                   log                                                             = m_testCtx.getLog();
259                 log << tcu::TestLog::Message << getBufferUsageFlagsStr(m_testCase.usage) << tcu::TestLog::EndMessage;
260                 const std::vector<std::string>& extensions                                              = ctx.getDeviceExtensions();
261                 const deBool                                    isSupported                                             = std::find(extensions.begin(), extensions.end(), "VK_KHR_dedicated_allocation") != extensions.end();
262                 if (!isSupported)
263                 {
264                         TCU_THROW(NotSupportedError, "Not supported");
265                 }
266                 return new DedicatedAllocationBufferTestInstance(ctx, m_testCase);
267         }
268
269 private:
270         BufferCaseParameters                            m_testCase;
271 };
272
273 tcu::TestStatus BufferTestInstance::bufferCreateAndAllocTest                    (VkDeviceSize                           size)
274 {
275         const VkPhysicalDevice                          vkPhysicalDevice                                = getPhysicalDevice();
276         const InstanceInterface&                        vkInstance                                              = getInstanceInterface();
277         const VkDevice                                          vkDevice                                                = getDevice();
278         const DeviceInterface&                          vk                                                              = getDeviceInterface();
279         const deUint32                                          queueFamilyIndex                                = getUniversalQueueFamilyIndex();
280         const VkPhysicalDeviceMemoryProperties
281                                                                                 memoryProperties                                = getPhysicalDeviceMemoryProperties(vkInstance, vkPhysicalDevice);
282         const VkPhysicalDeviceLimits            limits                                                  = getPhysicalDeviceProperties(vkInstance, vkPhysicalDevice).limits;
283         Move<VkBuffer>                                          buffer;
284         Move<VkDeviceMemory>                            memory;
285         VkMemoryRequirements                            memReqs;
286
287         if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0)
288         {
289                 size = std::min(size, limits.sparseAddressSpaceSize);
290         }
291
292         // Create the test buffer and a memory allocation for it
293         {
294                 // Create a minimal buffer first to get the supported memory types
295                 VkBufferCreateInfo                              bufferParams                                    =
296                 {
297                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                                           // VkStructureType                      sType;
298                         DE_NULL,                                                                                                        // const void*                          pNext;
299                         m_testCase.flags,                                                                                       // VkBufferCreateFlags          flags;
300                         1u,                                                                                                                     // VkDeviceSize                         size;
301                         m_testCase.usage,                                                                                       // VkBufferUsageFlags           usage;
302                         m_testCase.sharingMode,                                                                         // VkSharingMode                        sharingMode;
303                         1u,                                                                                                                     // uint32_t                                     queueFamilyIndexCount;
304                         &queueFamilyIndex,                                                                                      // const uint32_t*                      pQueueFamilyIndices;
305                 };
306
307                 buffer = createBuffer(vk, vkDevice, &bufferParams);
308                 vk.getBufferMemoryRequirements(vkDevice, *buffer, &memReqs);
309
310                 const deUint32                                  heapTypeIndex                                   = (deUint32)deCtz32(memReqs.memoryTypeBits);
311                 const VkMemoryType                              memoryType                                              = memoryProperties.memoryTypes[heapTypeIndex];
312                 const VkMemoryHeap                              memoryHeap                                              = memoryProperties.memoryHeaps[memoryType.heapIndex];
313                 const VkDeviceSize                              maxBufferSize                                   = deAlign64(memoryHeap.size >> 1u, memReqs.alignment);
314                 const deUint32                                  shrinkBits                                              = 4u;   // number of bits to shift when reducing the size with each iteration
315
316                 size = std::min(size, maxBufferSize);
317
318                 while (*memory == DE_NULL)
319                 {
320                         // Create the buffer
321                         {
322                                 VkResult                                result                                                  = VK_ERROR_OUT_OF_HOST_MEMORY;
323                                 VkBuffer                                rawBuffer                                               = DE_NULL;
324
325                                 bufferParams.size = size;
326                                 buffer = Move<VkBuffer>();              // free the previous buffer, if any
327                                 result = vk.createBuffer(vkDevice, &bufferParams, (vk::VkAllocationCallbacks*)DE_NULL, &rawBuffer);
328
329                                 if (result != VK_SUCCESS)
330                                 {
331                                         size = deAlign64(size >> shrinkBits, memReqs.alignment);
332
333                                         if (size == 0 || bufferParams.size == memReqs.alignment)
334                                         {
335                                                 return tcu::TestStatus::fail("Buffer creation failed! (" + de::toString(getResultName(result)) + ")");
336                                         }
337
338                                         continue;       // didn't work, try with a smaller buffer
339                                 }
340
341                                 buffer = Move<VkBuffer>(check<VkBuffer>(rawBuffer), Deleter<VkBuffer>(vk, vkDevice, DE_NULL));
342                         }
343
344                         vk.getBufferMemoryRequirements(vkDevice, *buffer, &memReqs);    // get the proper size requirement
345
346                         if (size > memReqs.size)
347                         {
348                                 std::ostringstream              errorMsg;
349                                 errorMsg << "Requied memory size (" << memReqs.size << " bytes) smaller than the buffer's size (" << size << " bytes)!";
350                                 return tcu::TestStatus::fail(errorMsg.str());
351                         }
352
353                         // Allocate the memory
354                         {
355                                 VkResult                                result                                                  = VK_ERROR_OUT_OF_HOST_MEMORY;
356                                 VkDeviceMemory                  rawMemory                                               = DE_NULL;
357
358                                 const VkMemoryAllocateInfo
359                                                                                 memAlloc                                                =
360                                 {
361                                         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,                         // VkStructureType                      sType;
362                                         NULL,                                                                                           // const void*                          pNext;
363                                         memReqs.size,                                                                           // VkDeviceSize                         allocationSize;
364                                         heapTypeIndex,                                                                          // uint32_t                                     memoryTypeIndex;
365                                 };
366
367                                 result = vk.allocateMemory(vkDevice, &memAlloc, (VkAllocationCallbacks*)DE_NULL, &rawMemory);
368
369                                 if (result != VK_SUCCESS)
370                                 {
371                                         size = deAlign64(size >> shrinkBits, memReqs.alignment);
372
373                                         if (size == 0 || memReqs.size == memReqs.alignment)
374                                         {
375                                                 return tcu::TestStatus::fail("Unable to allocate " + de::toString(memReqs.size) + " bytes of memory");
376                                         }
377
378                                         continue;       // didn't work, try with a smaller allocation (and a smaller buffer)
379                                 }
380
381                                 memory = Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL));
382                         }
383                 } // while
384         }
385
386         // Bind the memory
387         if ((m_testCase.flags & (VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT)) != 0)
388         {
389                 const VkQueue                                   queue                                                   = getDeviceQueue(vk, vkDevice, queueFamilyIndex, 0);
390
391                 const VkSparseMemoryBind                sparseMemoryBind                                =
392                 {
393                         0,                                                                                                                      // VkDeviceSize                         resourceOffset;
394                         memReqs.size,                                                                                           // VkDeviceSize                         size;
395                         *memory,                                                                                                        // VkDeviceMemory                       memory;
396                         0,                                                                                                                      // VkDeviceSize                         memoryOffset;
397                         0                                                                                                                       // VkSparseMemoryBindFlags      flags;
398                 };
399
400                 const VkSparseBufferMemoryBindInfo
401                                                                                 sparseBufferMemoryBindInfo              =
402                 {
403                         *buffer,                                                                                                        // VkBuffer                                     buffer;
404                         1u,                                                                                                                     // deUint32                                     bindCount;
405                         &sparseMemoryBind                                                                                       // const VkSparseMemoryBind* pBinds;
406                 };
407
408                 const VkBindSparseInfo                  bindSparseInfo                                  =
409                 {
410                         VK_STRUCTURE_TYPE_BIND_SPARSE_INFO,                                                     // VkStructureType                      sType;
411                         DE_NULL,                                                                                                        // const void*                          pNext;
412                         0,                                                                                                                      // deUint32                                     waitSemaphoreCount;
413                         DE_NULL,                                                                                                        // const VkSemaphore*           pWaitSemaphores;
414                         1u,                                                                                                                     // deUint32                                     bufferBindCount;
415                         &sparseBufferMemoryBindInfo,                                                            // const VkSparseBufferMemoryBindInfo* pBufferBinds;
416                         0,                                                                                                                      // deUint32                                     imageOpaqueBindCount;
417                         DE_NULL,                                                                                                        // const VkSparseImageOpaqueMemoryBindInfo*     pImageOpaqueBinds;
418                         0,                                                                                                                      // deUint32                                     imageBindCount;
419                         DE_NULL,                                                                                                        // const VkSparseImageMemoryBindInfo* pImageBinds;
420                         0,                                                                                                                      // deUint32                                     signalSemaphoreCount;
421                         DE_NULL,                                                                                                        // const VkSemaphore*           pSignalSemaphores;
422                 };
423
424                 const vk::Unique<vk::VkFence>   fence                                                   (vk::createFence(vk, vkDevice));
425
426                 if (vk.queueBindSparse(queue, 1, &bindSparseInfo, *fence) != VK_SUCCESS)
427                         return tcu::TestStatus::fail("Bind sparse buffer memory failed! (requested memory size: " + de::toString(size) + ")");
428
429                 VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), VK_TRUE, ~(0ull) /* infinity */));
430         }
431         else if (vk.bindBufferMemory(vkDevice, *buffer, *memory, 0) != VK_SUCCESS)
432                 return tcu::TestStatus::fail("Bind buffer memory failed! (requested memory size: " + de::toString(size) + ")");
433
434         return tcu::TestStatus::pass("Pass");
435 }
436
437 tcu::TestStatus                                                 BufferTestInstance::iterate             (void)
438 {
439         const VkPhysicalDeviceFeatures&         physicalDeviceFeatures                  = getPhysicalDeviceFeatures(getInstanceInterface(), getPhysicalDevice());
440
441         if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT ) && !physicalDeviceFeatures.sparseBinding)
442                 TCU_THROW(NotSupportedError, "Sparse bindings feature is not supported");
443
444         if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT ) && !physicalDeviceFeatures.sparseResidencyBuffer)
445                 TCU_THROW(NotSupportedError, "Sparse buffer residency feature is not supported");
446
447         if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT ) && !physicalDeviceFeatures.sparseResidencyAliased)
448                 TCU_THROW(NotSupportedError, "Sparse aliased residency feature is not supported");
449
450         const VkDeviceSize                                      testSizes[]                                             =
451         {
452                 1,
453                 1181,
454                 15991,
455                 16384,
456                 ~0ull,          // try to exercise a very large buffer too (will be clamped to a sensible size later)
457         };
458
459         for (int i = 0; i < DE_LENGTH_OF_ARRAY(testSizes); ++i)
460         {
461                 const tcu::TestStatus                   testStatus                                              = bufferCreateAndAllocTest(testSizes[i]);
462
463                 if (testStatus.getCode() != QP_TEST_RESULT_PASS)
464                         return testStatus;
465         }
466
467         return tcu::TestStatus::pass("Pass");
468 }
469
470 tcu::TestStatus                                                 DedicatedAllocationBufferTestInstance::bufferCreateAndAllocTest
471                                                                                                                                                 (VkDeviceSize                           size)
472 {
473         const VkPhysicalDevice                          vkPhysicalDevice                                = getPhysicalDevice();
474         const InstanceInterface&                        vkInstance                                              = getInstanceInterface();
475         const VkDevice                                          vkDevice                                                = getDevice();
476         const DeviceInterface&                          vk                                                              = getDeviceInterface();
477         const deUint32                                          queueFamilyIndex                                = getUniversalQueueFamilyIndex();
478         const VkPhysicalDeviceMemoryProperties
479                                                                                 memoryProperties                                = getPhysicalDeviceMemoryProperties(vkInstance, vkPhysicalDevice);
480         const VkPhysicalDeviceLimits            limits                                                  = getPhysicalDeviceProperties(vkInstance, vkPhysicalDevice).limits;
481
482         VkMemoryDedicatedRequirementsKHR        dedicatedRequirements                   =
483         {
484                 VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,                    // VkStructureType                      sType;
485                 DE_NULL,                                                                                                                // const void*                          pNext;
486                 false,                                                                                                                  // VkBool32                                     prefersDedicatedAllocation
487                 false                                                                                                                   // VkBool32                                     requiresDedicatedAllocation
488         };
489         VkMemoryRequirements2KHR                        memReqs                                                 =
490         {
491                 VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,                                    // VkStructureType                      sType
492                 &dedicatedRequirements,                                                                                 // void*                                        pNext
493                 {0, 0, 0}                                                                                                               // VkMemoryRequirements         memoryRequirements
494         };
495
496         if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0)
497                 size = std::min(size, limits.sparseAddressSpaceSize);
498
499         // Create a minimal buffer first to get the supported memory types
500         VkBufferCreateInfo                                      bufferParams                                    =
501         {
502                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                                                   // VkStructureType                      sType
503                 DE_NULL,                                                                                                                // const void*                          pNext
504                 m_testCase.flags,                                                                                               // VkBufferCreateFlags          flags
505                 1u,                                                                                                                             // VkDeviceSize                         size
506                 m_testCase.usage,                                                                                               // VkBufferUsageFlags           usage
507                 m_testCase.sharingMode,                                                                                 // VkSharingMode                        sharingMode
508                 1u,                                                                                                                             // uint32_t                                     queueFamilyIndexCount
509                 &queueFamilyIndex,                                                                                              // const uint32_t*                      pQueueFamilyIndices
510         };
511
512         Move<VkBuffer>                                          buffer                                                  = createBuffer(vk, vkDevice, &bufferParams);
513
514         VkBufferMemoryRequirementsInfo2KHR      info                                                    =
515         {
516                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR,                // VkStructureType                      sType
517                 DE_NULL,                                                                                                                // const void*                          pNext
518                 *buffer                                                                                                                 // VkBuffer                                     buffer
519         };
520
521         vk.getBufferMemoryRequirements2KHR(vkDevice, &info, &memReqs);
522
523         if (dedicatedRequirements.requiresDedicatedAllocation == VK_TRUE)
524         {
525                 std::ostringstream                              errorMsg;
526                 errorMsg << "Nonexternal objects cannot require dedicated allocation.";
527                 return tcu::TestStatus::fail(errorMsg.str());
528         }
529
530         const deUint32                                          heapTypeIndex                                   = static_cast<deUint32>(deCtz32(memReqs.memoryRequirements.memoryTypeBits));
531         const VkMemoryType                                      memoryType                                              = memoryProperties.memoryTypes[heapTypeIndex];
532         const VkMemoryHeap                                      memoryHeap                                              = memoryProperties.memoryHeaps[memoryType.heapIndex];
533         const VkDeviceSize                                      maxBufferSize                                   = deAlign64(memoryHeap.size >> 1u, memReqs.memoryRequirements.alignment);
534         const deUint32                                          shrinkBits                                              = 4u;   // number of bits to shift when reducing the size with each iteration
535
536         Move<VkDeviceMemory>                            memory;
537         size = std::min(size, maxBufferSize);
538         while (*memory == DE_NULL)
539         {
540                 // Create the buffer
541                 {
542                         VkResult                                        result                                                  = VK_ERROR_OUT_OF_HOST_MEMORY;
543                         VkBuffer                                        rawBuffer                                               = DE_NULL;
544
545                         bufferParams.size = size;
546                         buffer = Move<VkBuffer>(); // free the previous buffer, if any
547                         result = vk.createBuffer(vkDevice, &bufferParams, (VkAllocationCallbacks*)DE_NULL, &rawBuffer);
548
549                         if (result != VK_SUCCESS)
550                         {
551                                 size = deAlign64(size >> shrinkBits, memReqs.memoryRequirements.alignment);
552
553                                 if (size == 0 || bufferParams.size == memReqs.memoryRequirements.alignment)
554                                         return tcu::TestStatus::fail("Buffer creation failed! (" + de::toString(getResultName(result)) + ")");
555
556                                 continue; // didn't work, try with a smaller buffer
557                         }
558
559                         buffer = Move<VkBuffer>(check<VkBuffer>(rawBuffer), Deleter<VkBuffer>(vk, vkDevice, DE_NULL));
560                 }
561
562                 info.buffer = *buffer;
563                 vk.getBufferMemoryRequirements2KHR(vkDevice, &info, &memReqs); // get the proper size requirement
564
565                 if (size > memReqs.memoryRequirements.size)
566                 {
567                         std::ostringstream                      errorMsg;
568                         errorMsg << "Requied memory size (" << memReqs.memoryRequirements.size << " bytes) smaller than the buffer's size (" << size << " bytes)!";
569                         return tcu::TestStatus::fail(errorMsg.str());
570                 }
571
572                 // Allocate the memory
573                 {
574                         VkResult                                        result                                                  = VK_ERROR_OUT_OF_HOST_MEMORY;
575                         VkDeviceMemory                          rawMemory                                               = DE_NULL;
576
577                         vk::VkMemoryDedicatedAllocateInfoKHR
578                                                                                 dedicatedInfo                                   =
579                         {
580                                 VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,   // VkStructureType                      sType
581                                 DE_NULL,                                                                                                // const void*                          pNext
582                                 DE_NULL,                                                                                                // VkImage                                      image
583                                 *buffer                                                                                                 // VkBuffer                                     buffer
584                         };
585
586                         VkMemoryAllocateInfo            memoryAllocateInfo                              =
587                         {
588                                 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,                                 // VkStructureType                      sType
589                                 &dedicatedInfo,                                                                                 // const void*                          pNext
590                                 memReqs.memoryRequirements.size,                                                // VkDeviceSize                         allocationSize
591                                 heapTypeIndex,                                                                                  // deUint32                                     memoryTypeIndex
592                         };
593
594                         result = vk.allocateMemory(vkDevice, &memoryAllocateInfo, (VkAllocationCallbacks*)DE_NULL, &rawMemory);
595
596                         if (result != VK_SUCCESS)
597                         {
598                                 size = deAlign64(size >> shrinkBits, memReqs.memoryRequirements.alignment);
599
600                                 if (size == 0 || memReqs.memoryRequirements.size == memReqs.memoryRequirements.alignment)
601                                         return tcu::TestStatus::fail("Unable to allocate " + de::toString(memReqs.memoryRequirements.size) + " bytes of memory");
602
603                                 continue; // didn't work, try with a smaller allocation (and a smaller buffer)
604                         }
605
606                         memory = Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL));
607                 }
608         } // while
609
610         if (vk.bindBufferMemory(vkDevice, *buffer, *memory, 0) != VK_SUCCESS)
611                 return tcu::TestStatus::fail("Bind buffer memory failed! (requested memory size: " + de::toString(size) + ")");
612
613         return tcu::TestStatus::pass("Pass");
614 }
615
616 std::string getBufferUsageFlagsName (const VkBufferUsageFlags flags)
617 {
618         switch (flags)
619         {
620                 case VK_BUFFER_USAGE_TRANSFER_SRC_BIT:                  return "transfer_src";
621                 case VK_BUFFER_USAGE_TRANSFER_DST_BIT:                  return "transfer_dst";
622                 case VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT:  return "uniform_texel";
623                 case VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT:  return "storage_texel";
624                 case VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT:                return "uniform";
625                 case VK_BUFFER_USAGE_STORAGE_BUFFER_BIT:                return "storage";
626                 case VK_BUFFER_USAGE_INDEX_BUFFER_BIT:                  return "index";
627                 case VK_BUFFER_USAGE_VERTEX_BUFFER_BIT:                 return "vertex";
628                 case VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT:               return "indirect";
629                 default:
630                         DE_FATAL("Unknown buffer usage flag");
631                         return "";
632         }
633 }
634
635 std::string getBufferCreateFlagsName (const VkBufferCreateFlags flags)
636 {
637         std::ostringstream name;
638
639         if (flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT)
640                 name << "_binding";
641         if (flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT)
642                 name << "_residency";
643         if (flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT)
644                 name << "_aliased";
645         if (flags == 0u)
646                 name << "_zero";
647
648         DE_ASSERT(!name.str().empty());
649
650         return name.str().substr(1);
651 }
652
653 // Create all VkBufferUsageFlags combinations recursively
654 void createBufferUsageCases (tcu::TestCaseGroup& testGroup, const deUint32 firstNdx, const deUint32 bufferUsageFlags, const AllocationKind allocationKind)
655 {
656         const VkBufferUsageFlags                        bufferUsageModes[]      =
657         {
658                 VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
659                 VK_BUFFER_USAGE_TRANSFER_DST_BIT,
660                 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
661                 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
662                 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
663                 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
664                 VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
665                 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
666                 VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
667         };
668
669         tcu::TestContext&                                       testCtx                         = testGroup.getTestContext();
670
671         // Add test groups
672         for (deUint32 currentNdx = firstNdx; currentNdx < DE_LENGTH_OF_ARRAY(bufferUsageModes); currentNdx++)
673         {
674                 const deUint32                                  newBufferUsageFlags     = bufferUsageFlags | bufferUsageModes[currentNdx];
675                 const std::string                               newGroupName            = getBufferUsageFlagsName(bufferUsageModes[currentNdx]);
676                 de::MovePtr<tcu::TestCaseGroup> newTestGroup            (new tcu::TestCaseGroup(testCtx, newGroupName.c_str(), ""));
677
678                 createBufferUsageCases(*newTestGroup, currentNdx + 1u, newBufferUsageFlags, allocationKind);
679                 testGroup.addChild(newTestGroup.release());
680         }
681
682         // Add test cases
683         if (bufferUsageFlags != 0u)
684         {
685                 // \note SPARSE_RESIDENCY and SPARSE_ALIASED have to be used together with the SPARSE_BINDING flag.
686                 const VkBufferCreateFlags               bufferCreateFlags[]             =
687                 {
688                         0,
689                         VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
690                         VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
691                         VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,
692                         VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,
693                 };
694
695                 // Dedicated allocation does not support sparse feature
696                 const int                                               numBufferCreateFlags    = (allocationKind == ALLOCATION_KIND_SUBALLOCATED) ? DE_LENGTH_OF_ARRAY(bufferCreateFlags) : 1;
697
698                 de::MovePtr<tcu::TestCaseGroup> newTestGroup                    (new tcu::TestCaseGroup(testCtx, "create", ""));
699
700                 for (int bufferCreateFlagsNdx = 0; bufferCreateFlagsNdx < numBufferCreateFlags; bufferCreateFlagsNdx++)
701                 {
702                         const BufferCaseParameters      testParams      =
703                         {
704                                 bufferUsageFlags,
705                                 bufferCreateFlags[bufferCreateFlagsNdx],
706                                 VK_SHARING_MODE_EXCLUSIVE
707                         };
708
709                         const std::string                       allocStr        = (allocationKind == ALLOCATION_KIND_SUBALLOCATED) ? "suballocation of " : "dedicated alloc. of ";
710                         const std::string                       caseName        = getBufferCreateFlagsName(bufferCreateFlags[bufferCreateFlagsNdx]);
711                         const std::string                       caseDesc        = "vkCreateBuffer test: " + allocStr + de::toString(bufferUsageFlags) + " " + de::toString(testParams.flags);
712
713                         switch (allocationKind)
714                         {
715                                 case ALLOCATION_KIND_SUBALLOCATED:
716                                         newTestGroup->addChild(new BuffersTestCase(testCtx, caseName.c_str(), caseDesc.c_str(), testParams));
717                                         break;
718                                 case ALLOCATION_KIND_DEDICATED:
719                                         newTestGroup->addChild(new DedicatedAllocationBuffersTestCase(testCtx, caseName.c_str(), caseDesc.c_str(), testParams));
720                                         break;
721                                 default:
722                                         DE_FATAL("Unknown test type");
723                         }
724                 }
725                 testGroup.addChild(newTestGroup.release());
726         }
727 }
728
729 } // anonymous
730
731  tcu::TestCaseGroup* createBufferTests (tcu::TestContext& testCtx)
732 {
733         de::MovePtr<tcu::TestCaseGroup> buffersTests (new tcu::TestCaseGroup(testCtx, "buffer", "Buffer Tests"));
734
735         {
736                 de::MovePtr<tcu::TestCaseGroup> regularAllocation       (new tcu::TestCaseGroup(testCtx, "suballocation", "Regular suballocation of memory."));
737                 createBufferUsageCases(*regularAllocation, 0u, 0u, ALLOCATION_KIND_SUBALLOCATED);
738                 buffersTests->addChild(regularAllocation.release());
739         }
740
741         {
742                 de::MovePtr<tcu::TestCaseGroup> dedicatedAllocation     (new tcu::TestCaseGroup(testCtx, "dedicated_alloc", "Dedicated allocation of memory."));
743                 createBufferUsageCases(*dedicatedAllocation, 0u, 0u, ALLOCATION_KIND_DEDICATED);
744                 buffersTests->addChild(dedicatedAllocation.release());
745         }
746
747         return buffersTests.release();
748 }
749
750 } // api
751 } // vk