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