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