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