xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/api/vktApiBufferViewCreateTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 Buffer View Creation Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktApiBufferViewCreateTests.hpp"
26 #include "deStringUtil.hpp"
27 #include "deSharedPtr.hpp"
28 #include "gluVarType.hpp"
29 #include "tcuTestLog.hpp"
30 #include "vkPrograms.hpp"
31 #include "vkRefUtil.hpp"
32 #include "vktTestCase.hpp"
33 #include "vkQueryUtil.hpp"
34 
35 namespace vkt
36 {
37 
38 using namespace vk;
39 
40 namespace api
41 {
42 
43 namespace
44 {
45 
46 enum AllocationKind
47 {
48     ALLOCATION_KIND_SUBALLOCATED = 0,
49     ALLOCATION_KIND_DEDICATED,
50 
51     ALLOCATION_KIND_LAST,
52 };
53 
54 class IBufferAllocator;
55 
56 struct BufferViewCaseParameters
57 {
58     VkFormat format;
59     VkDeviceSize offset;
60     VkDeviceSize range;
61     VkBufferUsageFlags usage;
62     VkFormatFeatureFlags features;
63     AllocationKind bufferAllocationKind;
64 };
65 
66 class BufferViewTestInstance : public TestInstance
67 {
68 public:
BufferViewTestInstance(Context & ctx,BufferViewCaseParameters createInfo)69     BufferViewTestInstance(Context &ctx, BufferViewCaseParameters createInfo)
70         : TestInstance(ctx)
71         , m_testCase(createInfo)
72     {
73     }
74     virtual tcu::TestStatus iterate(void);
75 
76 protected:
77     BufferViewCaseParameters m_testCase;
78 };
79 
80 class IBufferAllocator
81 {
82 public:
~IBufferAllocator()83     virtual ~IBufferAllocator()
84     {
85     }
86 
87     virtual tcu::TestStatus createTestBuffer(VkDeviceSize size, VkBufferUsageFlags usage, Context &context,
88                                              Move<VkBuffer> &testBuffer, Move<VkDeviceMemory> &memory) const = 0;
89 };
90 
91 class BufferSuballocation : public IBufferAllocator
92 {
93 public:
94     virtual tcu::TestStatus createTestBuffer(VkDeviceSize size, VkBufferUsageFlags usage, Context &context,
95                                              Move<VkBuffer> &testBuffer, Move<VkDeviceMemory> &memory) const;
96 };
97 
98 class BufferDedicatedAllocation : public IBufferAllocator
99 {
100 public:
101     virtual tcu::TestStatus createTestBuffer(VkDeviceSize size, VkBufferUsageFlags usage, Context &context,
102                                              Move<VkBuffer> &testBuffer, Move<VkDeviceMemory> &memory) const;
103 };
104 
105 class BufferViewTestCase : public TestCase
106 {
107 public:
BufferViewTestCase(tcu::TestContext & testCtx,const std::string & name,BufferViewCaseParameters createInfo)108     BufferViewTestCase(tcu::TestContext &testCtx, const std::string &name, BufferViewCaseParameters createInfo)
109         : TestCase(testCtx, name)
110         , m_testCase(createInfo)
111     {
112     }
~BufferViewTestCase(void)113     virtual ~BufferViewTestCase(void)
114     {
115     }
createInstance(Context & ctx) const116     virtual TestInstance *createInstance(Context &ctx) const
117     {
118         return new BufferViewTestInstance(ctx, m_testCase);
119     }
checkSupport(Context & ctx) const120     virtual void checkSupport(Context &ctx) const
121     {
122         VkFormatProperties properties;
123 
124         ctx.getInstanceInterface().getPhysicalDeviceFormatProperties(ctx.getPhysicalDevice(), m_testCase.format,
125                                                                      &properties);
126         if (!(properties.bufferFeatures & m_testCase.features))
127             TCU_THROW(NotSupportedError, "Format not supported");
128         if (m_testCase.bufferAllocationKind == ALLOCATION_KIND_DEDICATED)
129         {
130             if (!ctx.isDeviceFunctionalitySupported("VK_KHR_dedicated_allocation"))
131                 TCU_THROW(NotSupportedError, "Dedicated allocation not supported");
132         }
133     }
134 
135 private:
136     BufferViewCaseParameters m_testCase;
137 };
138 
createTestBuffer(VkDeviceSize size,VkBufferUsageFlags usage,Context & context,Move<VkBuffer> & testBuffer,Move<VkDeviceMemory> & memory) const139 tcu::TestStatus BufferSuballocation::createTestBuffer(VkDeviceSize size, VkBufferUsageFlags usage, Context &context,
140                                                       Move<VkBuffer> &testBuffer, Move<VkDeviceMemory> &memory) const
141 {
142     const VkDevice vkDevice         = context.getDevice();
143     const DeviceInterface &vk       = context.getDeviceInterface();
144     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
145     VkMemoryRequirements memReqs;
146     const VkBufferCreateInfo bufferParams = {
147         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
148         DE_NULL,                              // const void* pNext;
149         0u,                                   // VkBufferCreateFlags flags;
150         size,                                 // VkDeviceSize size;
151         usage,                                // VkBufferUsageFlags usage;
152         VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
153         1u,                                   // uint32_t queueFamilyCount;
154         &queueFamilyIndex,                    // const uint32_t* pQueueFamilyIndices;
155     };
156 
157     try
158     {
159         testBuffer = vk::createBuffer(vk, vkDevice, &bufferParams, (const VkAllocationCallbacks *)DE_NULL);
160     }
161     catch (const vk::Error &error)
162     {
163         return tcu::TestStatus::fail("Buffer creation failed! (Error code: " + de::toString(error.getMessage()) + ")");
164     }
165 
166     vk.getBufferMemoryRequirements(vkDevice, *testBuffer, &memReqs);
167 
168 #ifdef CTS_USES_VULKANSC
169     if (context.getTestContext().getCommandLine().isSubProcess())
170 #endif // CTS_USES_VULKANSC
171     {
172         if (size > memReqs.size)
173         {
174             std::ostringstream errorMsg;
175             errorMsg << "Required memory size (" << memReqs.size << " bytes) smaller than the buffer's size (" << size
176                      << " bytes)!";
177             return tcu::TestStatus::fail(errorMsg.str());
178         }
179     }
180 
181     const VkMemoryAllocateInfo memAlloc = {
182         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,   //    VkStructureType            sType
183         NULL,                                     //    const void*                pNext
184         memReqs.size,                             //    VkDeviceSize            allocationSize
185         (uint32_t)deCtz32(memReqs.memoryTypeBits) //    uint32_t                memoryTypeIndex
186     };
187 
188     try
189     {
190         memory = allocateMemory(vk, vkDevice, &memAlloc, (const VkAllocationCallbacks *)DE_NULL);
191     }
192     catch (const vk::Error &error)
193     {
194         return tcu::TestStatus::fail("Alloc memory failed! (Error code: " + de::toString(error.getMessage()) + ")");
195     }
196 
197     if (vk.bindBufferMemory(vkDevice, *testBuffer, *memory, 0) != VK_SUCCESS)
198         return tcu::TestStatus::fail("Bind buffer memory failed!");
199 
200     return tcu::TestStatus::incomplete();
201 }
202 
createTestBuffer(VkDeviceSize size,VkBufferUsageFlags usage,Context & context,Move<VkBuffer> & testBuffer,Move<VkDeviceMemory> & memory) const203 tcu::TestStatus BufferDedicatedAllocation::createTestBuffer(VkDeviceSize size, VkBufferUsageFlags usage,
204                                                             Context &context, Move<VkBuffer> &testBuffer,
205                                                             Move<VkDeviceMemory> &memory) const
206 {
207     const InstanceInterface &vkInstance     = context.getInstanceInterface();
208     const VkDevice vkDevice                 = context.getDevice();
209     const VkPhysicalDevice vkPhysicalDevice = context.getPhysicalDevice();
210     const DeviceInterface &vk               = context.getDeviceInterface();
211     const uint32_t queueFamilyIndex         = context.getUniversalQueueFamilyIndex();
212     VkPhysicalDeviceMemoryProperties memoryProperties;
213     VkMemoryDedicatedRequirements dedicatedRequirements = {
214         VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, // VkStructureType sType;
215         DE_NULL,                                         // const void* pNext;
216         false,                                           // VkBool32                prefersDedicatedAllocation
217         false                                            // VkBool32                requiresDedicatedAllocation
218     };
219     VkMemoryRequirements2 memReqs = {
220         VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, // VkStructureType        sType
221         &dedicatedRequirements,                  // void*                pNext
222         {0, 0, 0}                                // VkMemoryRequirements    memoryRequirements
223     };
224 
225     const VkBufferCreateInfo bufferParams = {
226         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
227         DE_NULL,                              // const void* pNext;
228         0u,                                   // VkBufferCreateFlags flags;
229         size,                                 // VkDeviceSize size;
230         usage,                                // VkBufferUsageFlags usage;
231         VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
232         1u,                                   // uint32_t queueFamilyCount;
233         &queueFamilyIndex,                    // const uint32_t* pQueueFamilyIndices;
234     };
235 
236     try
237     {
238         testBuffer = vk::createBuffer(vk, vkDevice, &bufferParams, (const VkAllocationCallbacks *)DE_NULL);
239     }
240     catch (const vk::Error &error)
241     {
242         return tcu::TestStatus::fail("Buffer creation failed! (Error code: " + de::toString(error.getMessage()) + ")");
243     }
244 
245     VkBufferMemoryRequirementsInfo2 info = {
246         VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, // VkStructureType        sType
247         DE_NULL,                                             // const void*            pNext
248         *testBuffer                                          // VkBuffer                buffer
249     };
250 
251     vk.getBufferMemoryRequirements2(vkDevice, &info, &memReqs);
252 
253     if (dedicatedRequirements.requiresDedicatedAllocation == VK_TRUE)
254     {
255         std::ostringstream errorMsg;
256         errorMsg << "Nonexternal objects cannot require dedicated allocation.";
257         return tcu::TestStatus::fail(errorMsg.str());
258     }
259 
260     if (size > memReqs.memoryRequirements.size)
261     {
262         std::ostringstream errorMsg;
263         errorMsg << "Requied memory size (" << memReqs.memoryRequirements.size
264                  << " bytes) smaller than the buffer's size (" << size << " bytes)!";
265         return tcu::TestStatus::fail(errorMsg.str());
266     }
267 
268     deMemset(&memoryProperties, 0, sizeof(memoryProperties));
269     vkInstance.getPhysicalDeviceMemoryProperties(vkPhysicalDevice, &memoryProperties);
270 
271     if (memReqs.memoryRequirements.memoryTypeBits == 0)
272         return tcu::TestStatus::fail("memoryTypeBits is 0");
273 
274     const uint32_t heapTypeIndex = static_cast<uint32_t>(deCtz32(memReqs.memoryRequirements.memoryTypeBits));
275 
276     vk.getBufferMemoryRequirements2(vkDevice, &info, &memReqs); // get the proper size requirement
277 
278     if (size > memReqs.memoryRequirements.size)
279     {
280         std::ostringstream errorMsg;
281         errorMsg << "Requied memory size (" << memReqs.memoryRequirements.size
282                  << " bytes) smaller than the buffer's size (" << size << " bytes)!";
283         return tcu::TestStatus::fail(errorMsg.str());
284     }
285 
286     {
287         VkResult result          = VK_ERROR_OUT_OF_HOST_MEMORY;
288         VkDeviceMemory rawMemory = DE_NULL;
289 
290         vk::VkMemoryDedicatedAllocateInfo dedicatedInfo = {
291             VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, // VkStructureType            sType
292             DE_NULL,                                          // const void*                pNext
293             DE_NULL,                                          // VkImage                    image
294             *testBuffer                                       // VkBuffer                    buffer
295         };
296 
297         VkMemoryAllocateInfo memoryAllocateInfo = {
298             VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType            sType
299             &dedicatedInfo,                         // const void*                pNext
300             memReqs.memoryRequirements.size,        // VkDeviceSize                allocationSize
301             heapTypeIndex,                          // uint32_t                    memoryTypeIndex
302         };
303 
304         result = vk.allocateMemory(vkDevice, &memoryAllocateInfo, (VkAllocationCallbacks *)DE_NULL, &rawMemory);
305 
306         if (result != VK_SUCCESS)
307             return tcu::TestStatus::fail("Unable to allocate " + de::toString(memReqs.memoryRequirements.size) +
308                                          " bytes of memory");
309 
310         memory = Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL));
311     }
312 
313     if (vk.bindBufferMemory(vkDevice, *testBuffer, *memory, 0) != VK_SUCCESS)
314         return tcu::TestStatus::fail("Bind buffer memory failed! (requested memory size: " + de::toString(size) + ")");
315 
316     return tcu::TestStatus::incomplete();
317 }
318 
iterate(void)319 tcu::TestStatus BufferViewTestInstance::iterate(void)
320 {
321     const VkDevice vkDevice   = m_context.getDevice();
322     const DeviceInterface &vk = m_context.getDeviceInterface();
323     const VkDeviceSize size   = 3 * 5 * 7 * 64;
324     Move<VkBuffer> testBuffer;
325     Move<VkDeviceMemory> testBufferMemory;
326 
327     // Create buffer
328     if (m_testCase.bufferAllocationKind == ALLOCATION_KIND_DEDICATED)
329     {
330         BufferDedicatedAllocation().createTestBuffer(size, m_testCase.usage, m_context, testBuffer, testBufferMemory);
331     }
332     else
333     {
334         BufferSuballocation().createTestBuffer(size, m_testCase.usage, m_context, testBuffer, testBufferMemory);
335     }
336 
337     {
338         // Create buffer view.
339         Move<VkBufferView> bufferView;
340         const VkBufferViewCreateInfo bufferViewCreateInfo = {
341             VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType sType;
342             NULL,                                      // const void* pNext;
343             (VkBufferViewCreateFlags)0,
344             *testBuffer,       // VkBuffer buffer;
345             m_testCase.format, // VkFormat format;
346             m_testCase.offset, // VkDeviceSize offset;
347             m_testCase.range,  // VkDeviceSize range;
348         };
349 
350         try
351         {
352             bufferView = createBufferView(vk, vkDevice, &bufferViewCreateInfo, (const VkAllocationCallbacks *)DE_NULL);
353         }
354         catch (const vk::Error &error)
355         {
356             return tcu::TestStatus::fail(
357                 "Buffer View creation failed! (Error code: " + de::toString(error.getMessage()) + ")");
358         }
359     }
360 
361     // Testing complete view size.
362     {
363         Move<VkBufferView> completeBufferView;
364         VkBufferViewCreateInfo completeBufferViewCreateInfo = {
365             VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType sType;
366             NULL,                                      // const void* pNext;
367             (VkBufferViewCreateFlags)0,
368             *testBuffer,       // VkBuffer buffer;
369             m_testCase.format, // VkFormat format;
370             m_testCase.offset, // VkDeviceSize offset;
371             size,              // VkDeviceSize range;
372         };
373 
374         try
375         {
376             completeBufferView =
377                 createBufferView(vk, vkDevice, &completeBufferViewCreateInfo, (const VkAllocationCallbacks *)DE_NULL);
378         }
379         catch (const vk::Error &error)
380         {
381             return tcu::TestStatus::fail(
382                 "Buffer View creation failed! (Error code: " + de::toString(error.getMessage()) + ")");
383         }
384     }
385 
386     return tcu::TestStatus::pass("BufferView test");
387 }
388 
389 } // namespace
390 
createBufferViewCreateTests(tcu::TestContext & testCtx)391 tcu::TestCaseGroup *createBufferViewCreateTests(tcu::TestContext &testCtx)
392 {
393     const VkDeviceSize range                 = VK_WHOLE_SIZE;
394     const vk::VkBufferUsageFlags usage[]     = {vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
395                                                 vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT};
396     const vk::VkFormatFeatureFlags feature[] = {vk::VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT,
397                                                 vk::VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT};
398     const char *const usageName[]            = {"uniform", "storage"};
399 
400     de::MovePtr<tcu::TestCaseGroup> bufferViewTests(new tcu::TestCaseGroup(testCtx, "create"));
401 
402     if (!bufferViewTests)
403         TCU_THROW(InternalError, "Could not create test group \"create\".");
404 
405     de::MovePtr<tcu::TestCaseGroup> bufferViewAllocationGroupTests[ALLOCATION_KIND_LAST] = {
406         // BufferView Construction Tests for Suballocated Buffer
407         de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "suballocation")),
408         // BufferView Construction Tests for Dedicatedly Allocated Buffer
409         de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "dedicated_alloc"))};
410 
411     for (uint32_t allocationKind = 0; allocationKind < ALLOCATION_KIND_LAST; ++allocationKind)
412         for (uint32_t usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usage); ++usageNdx)
413         {
414             de::MovePtr<tcu::TestCaseGroup> usageGroup(new tcu::TestCaseGroup(testCtx, usageName[usageNdx]));
415 
416             for (uint32_t format = vk::VK_FORMAT_UNDEFINED + 1; format < VK_CORE_FORMAT_LAST; format++)
417             {
418                 const std::string formatName = de::toLower(getFormatName((VkFormat)format)).substr(10);
419                 de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, "suballocation"));
420 
421                 const std::string testName = de::toLower(getFormatName((VkFormat)format)).substr(10);
422 
423                 {
424                     const BufferViewCaseParameters testParams = {
425                         static_cast<vk::VkFormat>(format),          // VkFormat format;
426                         0,                                          // VkDeviceSize offset;
427                         range,                                      // VkDeviceSize range;
428                         usage[usageNdx],                            // VkBufferUsageFlags usage;
429                         feature[usageNdx],                          // VkFormatFeatureFlags flags;
430                         static_cast<AllocationKind>(allocationKind) // AllocationKind bufferAllocationKind;
431                     };
432 
433                     usageGroup->addChild(new BufferViewTestCase(testCtx, testName.c_str(), testParams));
434                 }
435             }
436             bufferViewAllocationGroupTests[allocationKind]->addChild(usageGroup.release());
437         }
438 
439     for (uint32_t subgroupNdx = 0u; subgroupNdx < DE_LENGTH_OF_ARRAY(bufferViewAllocationGroupTests); ++subgroupNdx)
440     {
441         bufferViewTests->addChild(bufferViewAllocationGroupTests[subgroupNdx].release());
442     }
443 
444     return bufferViewTests.release();
445 }
446 
447 } // namespace api
448 } // namespace vkt
449