Get rid of invalid buffer create flags combinations
[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 "vktTestCase.hpp"
34
35 namespace vkt
36 {
37
38 using namespace vk;
39
40 namespace api
41 {
42
43 namespace
44 {
45
46 static const deUint32   MAX_BUFFER_SIZE_DIVISOR = 16;
47
48 struct BufferCaseParameters
49 {
50         VkBufferUsageFlags      usage;
51         VkBufferCreateFlags     flags;
52         VkSharingMode           sharingMode;
53 };
54
55 class BufferTestInstance : public TestInstance
56 {
57 public:
58                                                                 BufferTestInstance                      (Context&                               ctx,
59                                                                                                                          BufferCaseParameters   testCase)
60                                                                         : TestInstance  (ctx)
61                                                                         , m_testCase    (testCase)
62                                                                 {}
63         virtual tcu::TestStatus         iterate                                         (void);
64         tcu::TestStatus                         bufferCreateAndAllocTest        (VkDeviceSize           size);
65
66 private:
67         BufferCaseParameters            m_testCase;
68 };
69
70 class BuffersTestCase : public TestCase
71 {
72 public:
73                                                         BuffersTestCase         (tcu::TestContext&              testCtx,
74                                                                                                  const std::string&             name,
75                                                                                                  const std::string&             description,
76                                                                                                  BufferCaseParameters   testCase)
77                                                                 : TestCase(testCtx, name, description)
78                                                                 , m_testCase(testCase)
79                                                         {}
80
81         virtual                                 ~BuffersTestCase        (void) {}
82         virtual TestInstance*   createInstance          (Context&                               ctx) const
83                                                         {
84                                                                 tcu::TestLog& log       = m_testCtx.getLog();
85                                                                 log << tcu::TestLog::Message << getBufferUsageFlagsStr(m_testCase.usage) << tcu::TestLog::EndMessage;
86                                                                 return new BufferTestInstance(ctx, m_testCase);
87                                                         }
88
89 private:
90         BufferCaseParameters            m_testCase;
91 };
92
93  tcu::TestStatus BufferTestInstance::bufferCreateAndAllocTest (VkDeviceSize size)
94 {
95         const VkPhysicalDevice          vkPhysicalDevice        = m_context.getPhysicalDevice();
96         const InstanceInterface&        vkInstance                      = m_context.getInstanceInterface();
97         const VkDevice                          vkDevice                        = m_context.getDevice();
98         const DeviceInterface&          vk                                      = m_context.getDeviceInterface();
99         Move<VkBuffer>                          testBuffer;
100         VkMemoryRequirements            memReqs;
101         Move<VkDeviceMemory>            memory;
102         const deUint32                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
103         const VkPhysicalDeviceMemoryProperties  memoryProperties = getPhysicalDeviceMemoryProperties(vkInstance, vkPhysicalDevice);
104
105         // Create buffer
106         {
107                 VkBufferCreateInfo              bufferParams            =
108                 {
109                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
110                         DE_NULL,
111                         m_testCase.flags,
112                         size,
113                         m_testCase.usage,
114                         m_testCase.sharingMode,
115                         1u,                                                                             //      deUint32                        queueFamilyCount;
116                         &queueFamilyIndex,
117                 };
118
119                 try
120                 {
121                         testBuffer = createBuffer(vk, vkDevice, &bufferParams);
122                 }
123                 catch (const vk::Error& error)
124                 {
125                         return tcu::TestStatus::fail("Buffer creation failed! (requested memory size: " + de::toString(size) + ", Error code: " + de::toString(error.getMessage()) + ")");
126                 }
127
128                 vk.getBufferMemoryRequirements(vkDevice, *testBuffer, &memReqs);
129
130                 const deUint32          heapTypeIndex   = (deUint32)deCtz32(memReqs.memoryTypeBits);
131                 const VkMemoryType      memoryType              = memoryProperties.memoryTypes[heapTypeIndex];
132                 const VkMemoryHeap      memoryHeap              = memoryProperties.memoryHeaps[memoryType.heapIndex];
133                 const VkDeviceSize      maxBufferSize   = memoryHeap.size / MAX_BUFFER_SIZE_DIVISOR;
134                 // If the requested size is too large, clamp it based on the selected heap size
135                 if (size > maxBufferSize)
136                 {
137                         size = maxBufferSize;
138                         bufferParams.size = size;
139                         try
140                         {
141                                 // allocate a new buffer with the adjusted size, the old one will be destroyed by the smart pointer
142                                 testBuffer = createBuffer(vk, vkDevice, &bufferParams);
143                         }
144                         catch (const vk::Error& error)
145                         {
146                                 return tcu::TestStatus::fail("Buffer creation failed! (requested memory size: " + de::toString(size) + ", Error code: " + de::toString(error.getMessage()) + ")");
147                         }
148                         vk.getBufferMemoryRequirements(vkDevice, *testBuffer, &memReqs);
149                 }
150
151                 if (size > memReqs.size)
152                 {
153                         std::ostringstream errorMsg;
154                         errorMsg << "Requied memory size (" << memReqs.size << " bytes) smaller than the buffer's size (" << size << " bytes)!";
155                         return tcu::TestStatus::fail(errorMsg.str());
156                 }
157         }
158
159         // Allocate and bind memory
160         {
161                 const VkMemoryAllocateInfo memAlloc =
162                 {
163                         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
164                         NULL,
165                         memReqs.size,
166                         (deUint32)deCtz32(memReqs.memoryTypeBits)       //      deUint32                memoryTypeIndex
167                 };
168
169                 try
170                 {
171                         memory = allocateMemory(vk, vkDevice, &memAlloc, (const VkAllocationCallbacks*)DE_NULL);
172                 }
173                 catch (const vk::Error& error)
174                 {
175                         return tcu::TestStatus::fail("Alloc memory failed! (requested memory size: " + de::toString(size) + ", Error code: " + de::toString(error.getMessage()) + ")");
176                 }
177
178                 if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) ||
179                         (m_testCase.flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) ||
180                         (m_testCase.flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT))
181                 {
182                         VkQueue queue                                                                                           = 0;
183
184                         vk.getDeviceQueue(vkDevice, queueFamilyIndex, 0, &queue);
185
186                         const VkSparseMemoryBind                        sparseMemoryBind                =
187                         {
188                                 0,                                                                              // VkDeviceSize                                                         resourceOffset;
189                                 memReqs.size,                                                   // VkDeviceSize                                                         size;
190                                 *memory,                                                                // VkDeviceMemory                                                       memory;
191                                 0,                                                                              // VkDeviceSize                                                         memoryOffset;
192                                 0                                                                               // VkSparseMemoryBindFlags                                      flags;
193                         };
194
195                         const VkSparseBufferMemoryBindInfo      sparseBufferMemoryBindInfo      =
196                         {
197                                 *testBuffer,                                                    // VkBuffer                                                                     buffer;
198                                 1u,                                                                             // deUint32                                                                     bindCount;
199                                 &sparseMemoryBind                                               // const VkSparseMemoryBind*                            pBinds;
200                         };
201
202                         const VkBindSparseInfo                          bindSparseInfo                  =
203                         {
204                                 VK_STRUCTURE_TYPE_BIND_SPARSE_INFO,             // VkStructureType                                                      sType;
205                                 DE_NULL,                                                                // const void*                                                          pNext;
206                                 0,                                                                              // deUint32                                                                     waitSemaphoreCount;
207                                 DE_NULL,                                                                // const VkSemaphore*                                           pWaitSemaphores;
208                                 1u,                                                                             // deUint32                                                                     bufferBindCount;
209                                 &sparseBufferMemoryBindInfo,                    // const VkSparseBufferMemoryBindInfo*          pBufferBinds;
210                                 0,                                                                              // deUint32                                                                     imageOpaqueBindCount;
211                                 DE_NULL,                                                                // const VkSparseImageOpaqueMemoryBindInfo*     pImageOpaqueBinds;
212                                 0,                                                                              // deUint32                                                                     imageBindCount;
213                                 DE_NULL,                                                                // const VkSparseImageMemoryBindInfo*           pImageBinds;
214                                 0,                                                                              // deUint32                                                                     signalSemaphoreCount;
215                                 DE_NULL,                                                                // const VkSemaphore*                                           pSignalSemaphores;
216                         };
217
218                         const VkFenceCreateInfo fenceParams =
219                         {
220                                 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,    // VkStructureType              sType;
221                                 DE_NULL,                                                                // const void*                  pNext;
222                                 0u                                                                              // VkFenceCreateFlags   flags;
223                         };
224
225                         const vk::Unique<vk::VkFence> fence(vk::createFence(vk, vkDevice, &fenceParams));
226
227                         if (vk.queueBindSparse(queue, 1, &bindSparseInfo, *fence) != VK_SUCCESS)
228                                 return tcu::TestStatus::fail("Bind sparse buffer memory failed! (requested memory size: " + de::toString(size) + ")");
229
230                         VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), VK_TRUE, ~(0ull) /* infinity */));
231                 }
232                 else
233                 {
234                         if (vk.bindBufferMemory(vkDevice, *testBuffer, *memory, 0) != VK_SUCCESS)
235                                 return tcu::TestStatus::fail("Bind buffer memory failed! (requested memory size: " + de::toString(size) + ")");
236                 }
237         }
238
239         return tcu::TestStatus::pass("Buffer test");
240 }
241
242 tcu::TestStatus BufferTestInstance::iterate (void)
243 {
244         const VkPhysicalDeviceFeatures& physicalDeviceFeatures  = m_context.getDeviceFeatures();
245
246         if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT ) && !physicalDeviceFeatures.sparseBinding)
247                 TCU_THROW(NotSupportedError, "Sparse bindings feature is not supported");
248
249         if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT ) && !physicalDeviceFeatures.sparseResidencyBuffer)
250                 TCU_THROW(NotSupportedError, "Sparse buffer residency feature is not supported");
251
252         if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT ) && !physicalDeviceFeatures.sparseResidencyAliased)
253                 TCU_THROW(NotSupportedError, "Sparse aliased residency feature is not supported");
254
255         const VkDeviceSize testSizes[] =
256         {
257                 1,
258                 1181,
259                 15991,
260                 16384
261         };
262         tcu::TestStatus                                 testStatus                      = tcu::TestStatus::pass("Buffer test");
263
264         for (int i = 0; i < DE_LENGTH_OF_ARRAY(testSizes); i++)
265         {
266                 if ((testStatus = bufferCreateAndAllocTest(testSizes[i])).getCode() != QP_TEST_RESULT_PASS)
267                         return testStatus;
268         }
269
270         if (m_testCase.usage & (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT))
271         {
272                 const VkPhysicalDevice                                  vkPhysicalDevice        = m_context.getPhysicalDevice();
273                 const InstanceInterface&                                vkInstance                      = m_context.getInstanceInterface();
274                 VkPhysicalDeviceProperties      props;
275
276                 vkInstance.getPhysicalDeviceProperties(vkPhysicalDevice, &props);
277                 testStatus = bufferCreateAndAllocTest((VkDeviceSize) props.limits.maxTexelBufferElements);
278         }
279
280         return testStatus;
281 }
282
283 } // anonymous
284
285  tcu::TestCaseGroup* createBufferTests (tcu::TestContext& testCtx)
286 {
287         const VkBufferUsageFlags bufferUsageModes[] =
288         {
289                 VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
290                 VK_BUFFER_USAGE_TRANSFER_DST_BIT,
291                 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
292                 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
293                 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
294                 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
295                 VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
296                 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
297                 VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
298         };
299
300         // \note SPARSE_RESIDENCY and SPARSE_ALIASED have to be used together with the SPARSE_BINDING flag.
301         const VkBufferCreateFlags bufferCreateFlags[] =
302         {
303                 0,
304                 VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
305                 VK_BUFFER_CREATE_SPARSE_BINDING_BIT     |       VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
306                 VK_BUFFER_CREATE_SPARSE_BINDING_BIT     |                                                                                               VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,
307                 VK_BUFFER_CREATE_SPARSE_BINDING_BIT     |       VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT   |       VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,
308         };
309
310         de::MovePtr<tcu::TestCaseGroup> buffersTests    (new tcu::TestCaseGroup(testCtx, "buffer", "Buffer Tests"));
311
312         const deUint32 maximumValueOfBufferUsageFlags   = (1u << (DE_LENGTH_OF_ARRAY(bufferUsageModes) - 1)) - 1u;
313
314         for (deUint32 bufferCreateFlagsNdx = 0u; bufferCreateFlagsNdx < DE_LENGTH_OF_ARRAY(bufferCreateFlags); bufferCreateFlagsNdx++)
315         for (deUint32 combinedBufferUsageFlags = 1u; combinedBufferUsageFlags <= maximumValueOfBufferUsageFlags; combinedBufferUsageFlags++)
316         {
317                 const BufferCaseParameters      testParams =
318                 {
319                         combinedBufferUsageFlags,
320                         bufferCreateFlags[bufferCreateFlagsNdx],
321                         VK_SHARING_MODE_EXCLUSIVE
322                 };
323                 std::ostringstream      testName;
324                 std::ostringstream      testDescription;
325                 testName << "createBuffer_" << combinedBufferUsageFlags << "_" << testParams.flags;
326                 testDescription << "vkCreateBuffer test " << combinedBufferUsageFlags << " " << testParams.flags;
327                 buffersTests->addChild(new BuffersTestCase(testCtx, testName.str(), testDescription.str(), testParams));
328         }
329
330         return buffersTests.release();
331 }
332
333 } // api
334 } // vk