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