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