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