1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------ 2e5c31af7Sopenharmony_ci * Vulkan Conformance Tests 3e5c31af7Sopenharmony_ci * ------------------------ 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright (c) 2015 The Khronos Group Inc. 6e5c31af7Sopenharmony_ci * Copyright (c) 2015 Samsung Electronics Co., Ltd. 7e5c31af7Sopenharmony_ci * 8e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 9e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 10e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 11e5c31af7Sopenharmony_ci * 12e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 13e5c31af7Sopenharmony_ci * 14e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 15e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 16e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 18e5c31af7Sopenharmony_ci * limitations under the License. 19e5c31af7Sopenharmony_ci * 20e5c31af7Sopenharmony_ci *//*! 21e5c31af7Sopenharmony_ci * \file 22e5c31af7Sopenharmony_ci * \brief Vulkan Buffers Tests 23e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 24e5c31af7Sopenharmony_ci 25e5c31af7Sopenharmony_ci#include "vktApiBufferTests.hpp" 26e5c31af7Sopenharmony_ci#include "gluVarType.hpp" 27e5c31af7Sopenharmony_ci#include "deStringUtil.hpp" 28e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp" 29e5c31af7Sopenharmony_ci#include "vkPlatform.hpp" 30e5c31af7Sopenharmony_ci#include "vkPrograms.hpp" 31e5c31af7Sopenharmony_ci#include "vkQueryUtil.hpp" 32e5c31af7Sopenharmony_ci#include "vkRefUtil.hpp" 33e5c31af7Sopenharmony_ci#include "vktTestCase.hpp" 34e5c31af7Sopenharmony_ci#include "vktTestCaseUtil.hpp" 35e5c31af7Sopenharmony_ci#include "tcuPlatform.hpp" 36e5c31af7Sopenharmony_ci 37e5c31af7Sopenharmony_ci#include <algorithm> 38e5c31af7Sopenharmony_ci#include <limits> 39e5c31af7Sopenharmony_ci 40e5c31af7Sopenharmony_cinamespace vkt 41e5c31af7Sopenharmony_ci{ 42e5c31af7Sopenharmony_cinamespace api 43e5c31af7Sopenharmony_ci{ 44e5c31af7Sopenharmony_cinamespace 45e5c31af7Sopenharmony_ci{ 46e5c31af7Sopenharmony_ciusing namespace vk; 47e5c31af7Sopenharmony_ci 48e5c31af7Sopenharmony_cienum AllocationKind 49e5c31af7Sopenharmony_ci{ 50e5c31af7Sopenharmony_ci ALLOCATION_KIND_SUBALLOCATED = 0, 51e5c31af7Sopenharmony_ci ALLOCATION_KIND_DEDICATED, 52e5c31af7Sopenharmony_ci 53e5c31af7Sopenharmony_ci ALLOCATION_KIND_LAST, 54e5c31af7Sopenharmony_ci}; 55e5c31af7Sopenharmony_ci 56e5c31af7Sopenharmony_citcu::PlatformMemoryLimits getPlatformMemoryLimits (Context& context) 57e5c31af7Sopenharmony_ci{ 58e5c31af7Sopenharmony_ci tcu::PlatformMemoryLimits memoryLimits; 59e5c31af7Sopenharmony_ci 60e5c31af7Sopenharmony_ci context.getTestContext().getPlatform().getMemoryLimits(memoryLimits); 61e5c31af7Sopenharmony_ci 62e5c31af7Sopenharmony_ci return memoryLimits; 63e5c31af7Sopenharmony_ci} 64e5c31af7Sopenharmony_ci 65e5c31af7Sopenharmony_ciVkDeviceSize getMaxBufferSize(const VkDeviceSize& bufferSize, 66e5c31af7Sopenharmony_ci const VkDeviceSize& alignment, 67e5c31af7Sopenharmony_ci const tcu::PlatformMemoryLimits& limits) 68e5c31af7Sopenharmony_ci{ 69e5c31af7Sopenharmony_ci VkDeviceSize size = bufferSize; 70e5c31af7Sopenharmony_ci 71e5c31af7Sopenharmony_ci if (limits.totalDeviceLocalMemory == 0) 72e5c31af7Sopenharmony_ci { 73e5c31af7Sopenharmony_ci // 'UMA' systems where device memory counts against system memory 74e5c31af7Sopenharmony_ci size = std::min(bufferSize, limits.totalSystemMemory - alignment); 75e5c31af7Sopenharmony_ci } 76e5c31af7Sopenharmony_ci else 77e5c31af7Sopenharmony_ci { 78e5c31af7Sopenharmony_ci // 'LMA' systems where device memory is local to the GPU 79e5c31af7Sopenharmony_ci size = std::min(bufferSize, limits.totalDeviceLocalMemory - alignment); 80e5c31af7Sopenharmony_ci } 81e5c31af7Sopenharmony_ci 82e5c31af7Sopenharmony_ci return size; 83e5c31af7Sopenharmony_ci} 84e5c31af7Sopenharmony_ci 85e5c31af7Sopenharmony_cistruct BufferCaseParameters 86e5c31af7Sopenharmony_ci{ 87e5c31af7Sopenharmony_ci VkBufferUsageFlags usage; 88e5c31af7Sopenharmony_ci VkBufferCreateFlags flags; 89e5c31af7Sopenharmony_ci VkSharingMode sharingMode; 90e5c31af7Sopenharmony_ci}; 91e5c31af7Sopenharmony_ci 92e5c31af7Sopenharmony_ciclass BufferTestInstance : public TestInstance 93e5c31af7Sopenharmony_ci{ 94e5c31af7Sopenharmony_cipublic: 95e5c31af7Sopenharmony_ci BufferTestInstance (Context& ctx, 96e5c31af7Sopenharmony_ci BufferCaseParameters testCase) 97e5c31af7Sopenharmony_ci : TestInstance (ctx) 98e5c31af7Sopenharmony_ci , m_testCase (testCase) 99e5c31af7Sopenharmony_ci { 100e5c31af7Sopenharmony_ci } 101e5c31af7Sopenharmony_ci virtual tcu::TestStatus iterate (void); 102e5c31af7Sopenharmony_ci virtual tcu::TestStatus bufferCreateAndAllocTest (VkDeviceSize size); 103e5c31af7Sopenharmony_ci 104e5c31af7Sopenharmony_ciprotected: 105e5c31af7Sopenharmony_ci BufferCaseParameters m_testCase; 106e5c31af7Sopenharmony_ci}; 107e5c31af7Sopenharmony_ci 108e5c31af7Sopenharmony_ciclass DedicatedAllocationBufferTestInstance : public BufferTestInstance 109e5c31af7Sopenharmony_ci{ 110e5c31af7Sopenharmony_cipublic: 111e5c31af7Sopenharmony_ci DedicatedAllocationBufferTestInstance 112e5c31af7Sopenharmony_ci (Context& ctx, 113e5c31af7Sopenharmony_ci BufferCaseParameters testCase) 114e5c31af7Sopenharmony_ci : BufferTestInstance (ctx, testCase) 115e5c31af7Sopenharmony_ci { 116e5c31af7Sopenharmony_ci } 117e5c31af7Sopenharmony_ci virtual tcu::TestStatus bufferCreateAndAllocTest (VkDeviceSize size); 118e5c31af7Sopenharmony_ci}; 119e5c31af7Sopenharmony_ci 120e5c31af7Sopenharmony_ciclass BuffersTestCase : public TestCase 121e5c31af7Sopenharmony_ci{ 122e5c31af7Sopenharmony_cipublic: 123e5c31af7Sopenharmony_ci BuffersTestCase (tcu::TestContext& testCtx, 124e5c31af7Sopenharmony_ci const std::string& name, 125e5c31af7Sopenharmony_ci BufferCaseParameters testCase) 126e5c31af7Sopenharmony_ci : TestCase (testCtx, name) 127e5c31af7Sopenharmony_ci , m_testCase (testCase) 128e5c31af7Sopenharmony_ci { 129e5c31af7Sopenharmony_ci } 130e5c31af7Sopenharmony_ci 131e5c31af7Sopenharmony_ci virtual ~BuffersTestCase (void) 132e5c31af7Sopenharmony_ci { 133e5c31af7Sopenharmony_ci } 134e5c31af7Sopenharmony_ci 135e5c31af7Sopenharmony_ci virtual TestInstance* createInstance (Context& ctx) const 136e5c31af7Sopenharmony_ci { 137e5c31af7Sopenharmony_ci tcu::TestLog& log = m_testCtx.getLog(); 138e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << getBufferUsageFlagsStr(m_testCase.usage) << tcu::TestLog::EndMessage; 139e5c31af7Sopenharmony_ci return new BufferTestInstance(ctx, m_testCase); 140e5c31af7Sopenharmony_ci } 141e5c31af7Sopenharmony_ci 142e5c31af7Sopenharmony_ci virtual void checkSupport (Context& ctx) const 143e5c31af7Sopenharmony_ci { 144e5c31af7Sopenharmony_ci const VkPhysicalDeviceFeatures& physicalDeviceFeatures = getPhysicalDeviceFeatures(ctx.getInstanceInterface(), ctx.getPhysicalDevice()); 145e5c31af7Sopenharmony_ci 146e5c31af7Sopenharmony_ci if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) && !physicalDeviceFeatures.sparseBinding) 147e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "Sparse bindings feature is not supported"); 148e5c31af7Sopenharmony_ci 149e5c31af7Sopenharmony_ci if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) && !physicalDeviceFeatures.sparseResidencyBuffer) 150e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "Sparse buffer residency feature is not supported"); 151e5c31af7Sopenharmony_ci 152e5c31af7Sopenharmony_ci if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) && !physicalDeviceFeatures.sparseResidencyAliased) 153e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "Sparse aliased residency feature is not supported"); 154e5c31af7Sopenharmony_ci } 155e5c31af7Sopenharmony_ci 156e5c31af7Sopenharmony_ciprivate: 157e5c31af7Sopenharmony_ci BufferCaseParameters m_testCase; 158e5c31af7Sopenharmony_ci}; 159e5c31af7Sopenharmony_ci 160e5c31af7Sopenharmony_ciclass DedicatedAllocationBuffersTestCase : public TestCase 161e5c31af7Sopenharmony_ci{ 162e5c31af7Sopenharmony_ci public: 163e5c31af7Sopenharmony_ci DedicatedAllocationBuffersTestCase 164e5c31af7Sopenharmony_ci (tcu::TestContext& testCtx, 165e5c31af7Sopenharmony_ci const std::string& name, 166e5c31af7Sopenharmony_ci BufferCaseParameters testCase) 167e5c31af7Sopenharmony_ci : TestCase (testCtx, name) 168e5c31af7Sopenharmony_ci , m_testCase (testCase) 169e5c31af7Sopenharmony_ci { 170e5c31af7Sopenharmony_ci } 171e5c31af7Sopenharmony_ci 172e5c31af7Sopenharmony_ci virtual ~DedicatedAllocationBuffersTestCase 173e5c31af7Sopenharmony_ci (void) 174e5c31af7Sopenharmony_ci { 175e5c31af7Sopenharmony_ci } 176e5c31af7Sopenharmony_ci 177e5c31af7Sopenharmony_ci virtual TestInstance* createInstance (Context& ctx) const 178e5c31af7Sopenharmony_ci { 179e5c31af7Sopenharmony_ci tcu::TestLog& log = m_testCtx.getLog(); 180e5c31af7Sopenharmony_ci log << tcu::TestLog::Message << getBufferUsageFlagsStr(m_testCase.usage) << tcu::TestLog::EndMessage; 181e5c31af7Sopenharmony_ci return new DedicatedAllocationBufferTestInstance(ctx, m_testCase); 182e5c31af7Sopenharmony_ci } 183e5c31af7Sopenharmony_ci 184e5c31af7Sopenharmony_ci virtual void checkSupport (Context& ctx) const 185e5c31af7Sopenharmony_ci { 186e5c31af7Sopenharmony_ci if (!ctx.isDeviceFunctionalitySupported("VK_KHR_dedicated_allocation")) 187e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "Not supported"); 188e5c31af7Sopenharmony_ci } 189e5c31af7Sopenharmony_ciprivate: 190e5c31af7Sopenharmony_ci BufferCaseParameters m_testCase; 191e5c31af7Sopenharmony_ci}; 192e5c31af7Sopenharmony_ci 193e5c31af7Sopenharmony_citcu::TestStatus BufferTestInstance::bufferCreateAndAllocTest (VkDeviceSize size) 194e5c31af7Sopenharmony_ci{ 195e5c31af7Sopenharmony_ci const VkPhysicalDevice vkPhysicalDevice = m_context.getPhysicalDevice(); 196e5c31af7Sopenharmony_ci const InstanceInterface& vkInstance = m_context.getInstanceInterface(); 197e5c31af7Sopenharmony_ci const VkDevice vkDevice = m_context.getDevice(); 198e5c31af7Sopenharmony_ci const DeviceInterface& vk = m_context.getDeviceInterface(); 199e5c31af7Sopenharmony_ci const deUint32 queueFamilyIndex = m_context.getSparseQueueFamilyIndex(); 200e5c31af7Sopenharmony_ci const VkPhysicalDeviceMemoryProperties 201e5c31af7Sopenharmony_ci memoryProperties = getPhysicalDeviceMemoryProperties(vkInstance, vkPhysicalDevice); 202e5c31af7Sopenharmony_ci const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vkInstance, vkPhysicalDevice).limits; 203e5c31af7Sopenharmony_ci Move<VkBuffer> buffer; 204e5c31af7Sopenharmony_ci Move<VkDeviceMemory> memory; 205e5c31af7Sopenharmony_ci VkMemoryRequirements memReqs; 206e5c31af7Sopenharmony_ci 207e5c31af7Sopenharmony_ci if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0) 208e5c31af7Sopenharmony_ci { 209e5c31af7Sopenharmony_ci size = std::min(size, limits.sparseAddressSpaceSize); 210e5c31af7Sopenharmony_ci } 211e5c31af7Sopenharmony_ci 212e5c31af7Sopenharmony_ci // Create the test buffer and a memory allocation for it 213e5c31af7Sopenharmony_ci { 214e5c31af7Sopenharmony_ci // Create a minimal buffer first to get the supported memory types 215e5c31af7Sopenharmony_ci VkBufferCreateInfo bufferParams = 216e5c31af7Sopenharmony_ci { 217e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 218e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 219e5c31af7Sopenharmony_ci m_testCase.flags, // VkBufferCreateFlags flags; 220e5c31af7Sopenharmony_ci 1u, // VkDeviceSize size; 221e5c31af7Sopenharmony_ci m_testCase.usage, // VkBufferUsageFlags usage; 222e5c31af7Sopenharmony_ci m_testCase.sharingMode, // VkSharingMode sharingMode; 223e5c31af7Sopenharmony_ci 1u, // uint32_t queueFamilyIndexCount; 224e5c31af7Sopenharmony_ci &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices; 225e5c31af7Sopenharmony_ci }; 226e5c31af7Sopenharmony_ci 227e5c31af7Sopenharmony_ci buffer = createBuffer(vk, vkDevice, &bufferParams); 228e5c31af7Sopenharmony_ci vk.getBufferMemoryRequirements(vkDevice, *buffer, &memReqs); 229e5c31af7Sopenharmony_ci 230e5c31af7Sopenharmony_ci const deUint32 heapTypeIndex = (deUint32)deCtz32(memReqs.memoryTypeBits); 231e5c31af7Sopenharmony_ci const VkMemoryType memoryType = memoryProperties.memoryTypes[heapTypeIndex]; 232e5c31af7Sopenharmony_ci const VkMemoryHeap memoryHeap = memoryProperties.memoryHeaps[memoryType.heapIndex]; 233e5c31af7Sopenharmony_ci const deUint32 shrinkBits = 4u; // number of bits to shift when reducing the size with each iteration 234e5c31af7Sopenharmony_ci 235e5c31af7Sopenharmony_ci // Buffer size - Choose half of the reported heap size for the maximum buffer size, we 236e5c31af7Sopenharmony_ci // should attempt to test as large a portion as possible. 237e5c31af7Sopenharmony_ci // 238e5c31af7Sopenharmony_ci // However on a system where device memory is shared with the system, the maximum size 239e5c31af7Sopenharmony_ci // should be tested against the platform memory limits as significant portion of the heap 240e5c31af7Sopenharmony_ci // may already be in use by the operating system and other running processes. 241e5c31af7Sopenharmony_ci const VkDeviceSize availableBufferSize = getMaxBufferSize(memoryHeap.size, 242e5c31af7Sopenharmony_ci memReqs.alignment, 243e5c31af7Sopenharmony_ci getPlatformMemoryLimits(m_context)); 244e5c31af7Sopenharmony_ci 245e5c31af7Sopenharmony_ci // For our test buffer size, halve the maximum available size and align 246e5c31af7Sopenharmony_ci const VkDeviceSize maxBufferSize = deAlign64(availableBufferSize >> 1, memReqs.alignment); 247e5c31af7Sopenharmony_ci 248e5c31af7Sopenharmony_ci size = std::min(size, maxBufferSize); 249e5c31af7Sopenharmony_ci 250e5c31af7Sopenharmony_ci while (*memory == DE_NULL) 251e5c31af7Sopenharmony_ci { 252e5c31af7Sopenharmony_ci // Create the buffer 253e5c31af7Sopenharmony_ci { 254e5c31af7Sopenharmony_ci VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY; 255e5c31af7Sopenharmony_ci VkBuffer rawBuffer = DE_NULL; 256e5c31af7Sopenharmony_ci 257e5c31af7Sopenharmony_ci bufferParams.size = size; 258e5c31af7Sopenharmony_ci buffer = Move<VkBuffer>(); // free the previous buffer, if any 259e5c31af7Sopenharmony_ci result = vk.createBuffer(vkDevice, &bufferParams, (vk::VkAllocationCallbacks*)DE_NULL, &rawBuffer); 260e5c31af7Sopenharmony_ci 261e5c31af7Sopenharmony_ci if (result != VK_SUCCESS) 262e5c31af7Sopenharmony_ci { 263e5c31af7Sopenharmony_ci size = deAlign64(size >> shrinkBits, memReqs.alignment); 264e5c31af7Sopenharmony_ci 265e5c31af7Sopenharmony_ci if (size == 0 || bufferParams.size == memReqs.alignment) 266e5c31af7Sopenharmony_ci { 267e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("Buffer creation failed! (" + de::toString(getResultName(result)) + ")"); 268e5c31af7Sopenharmony_ci } 269e5c31af7Sopenharmony_ci 270e5c31af7Sopenharmony_ci continue; // didn't work, try with a smaller buffer 271e5c31af7Sopenharmony_ci } 272e5c31af7Sopenharmony_ci 273e5c31af7Sopenharmony_ci buffer = Move<VkBuffer>(check<VkBuffer>(rawBuffer), Deleter<VkBuffer>(vk, vkDevice, DE_NULL)); 274e5c31af7Sopenharmony_ci } 275e5c31af7Sopenharmony_ci 276e5c31af7Sopenharmony_ci vk.getBufferMemoryRequirements(vkDevice, *buffer, &memReqs); // get the proper size requirement 277e5c31af7Sopenharmony_ci 278e5c31af7Sopenharmony_ci#ifdef CTS_USES_VULKANSC 279e5c31af7Sopenharmony_ci if (m_context.getTestContext().getCommandLine().isSubProcess()) 280e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC 281e5c31af7Sopenharmony_ci { 282e5c31af7Sopenharmony_ci if (size > memReqs.size) 283e5c31af7Sopenharmony_ci { 284e5c31af7Sopenharmony_ci std::ostringstream errorMsg; 285e5c31af7Sopenharmony_ci errorMsg << "Required memory size (" << memReqs.size << " bytes) smaller than the buffer's size (" << size << " bytes)!"; 286e5c31af7Sopenharmony_ci return tcu::TestStatus::fail(errorMsg.str()); 287e5c31af7Sopenharmony_ci } 288e5c31af7Sopenharmony_ci } 289e5c31af7Sopenharmony_ci 290e5c31af7Sopenharmony_ci // Allocate the memory 291e5c31af7Sopenharmony_ci { 292e5c31af7Sopenharmony_ci VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY; 293e5c31af7Sopenharmony_ci VkDeviceMemory rawMemory = DE_NULL; 294e5c31af7Sopenharmony_ci 295e5c31af7Sopenharmony_ci const VkMemoryAllocateInfo 296e5c31af7Sopenharmony_ci memAlloc = 297e5c31af7Sopenharmony_ci { 298e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType; 299e5c31af7Sopenharmony_ci NULL, // const void* pNext; 300e5c31af7Sopenharmony_ci memReqs.size, // VkDeviceSize allocationSize; 301e5c31af7Sopenharmony_ci heapTypeIndex, // uint32_t memoryTypeIndex; 302e5c31af7Sopenharmony_ci }; 303e5c31af7Sopenharmony_ci 304e5c31af7Sopenharmony_ci result = vk.allocateMemory(vkDevice, &memAlloc, (VkAllocationCallbacks*)DE_NULL, &rawMemory); 305e5c31af7Sopenharmony_ci 306e5c31af7Sopenharmony_ci if (result != VK_SUCCESS) 307e5c31af7Sopenharmony_ci { 308e5c31af7Sopenharmony_ci size = deAlign64(size >> shrinkBits, memReqs.alignment); 309e5c31af7Sopenharmony_ci 310e5c31af7Sopenharmony_ci if (size == 0 || memReqs.size == memReqs.alignment) 311e5c31af7Sopenharmony_ci { 312e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("Unable to allocate " + de::toString(memReqs.size) + " bytes of memory"); 313e5c31af7Sopenharmony_ci } 314e5c31af7Sopenharmony_ci 315e5c31af7Sopenharmony_ci continue; // didn't work, try with a smaller allocation (and a smaller buffer) 316e5c31af7Sopenharmony_ci } 317e5c31af7Sopenharmony_ci 318e5c31af7Sopenharmony_ci memory = Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL)); 319e5c31af7Sopenharmony_ci } 320e5c31af7Sopenharmony_ci } // while 321e5c31af7Sopenharmony_ci } 322e5c31af7Sopenharmony_ci 323e5c31af7Sopenharmony_ci // Bind the memory 324e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC 325e5c31af7Sopenharmony_ci if ((m_testCase.flags & (VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT)) != 0) 326e5c31af7Sopenharmony_ci { 327e5c31af7Sopenharmony_ci const VkQueue queue = m_context.getSparseQueue(); 328e5c31af7Sopenharmony_ci 329e5c31af7Sopenharmony_ci const VkSparseMemoryBind sparseMemoryBind = 330e5c31af7Sopenharmony_ci { 331e5c31af7Sopenharmony_ci 0, // VkDeviceSize resourceOffset; 332e5c31af7Sopenharmony_ci memReqs.size, // VkDeviceSize size; 333e5c31af7Sopenharmony_ci *memory, // VkDeviceMemory memory; 334e5c31af7Sopenharmony_ci 0, // VkDeviceSize memoryOffset; 335e5c31af7Sopenharmony_ci 0 // VkSparseMemoryBindFlags flags; 336e5c31af7Sopenharmony_ci }; 337e5c31af7Sopenharmony_ci 338e5c31af7Sopenharmony_ci const VkSparseBufferMemoryBindInfo 339e5c31af7Sopenharmony_ci sparseBufferMemoryBindInfo = 340e5c31af7Sopenharmony_ci { 341e5c31af7Sopenharmony_ci *buffer, // VkBuffer buffer; 342e5c31af7Sopenharmony_ci 1u, // deUint32 bindCount; 343e5c31af7Sopenharmony_ci &sparseMemoryBind // const VkSparseMemoryBind* pBinds; 344e5c31af7Sopenharmony_ci }; 345e5c31af7Sopenharmony_ci 346e5c31af7Sopenharmony_ci const VkBindSparseInfo bindSparseInfo = 347e5c31af7Sopenharmony_ci { 348e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_BIND_SPARSE_INFO, // VkStructureType sType; 349e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 350e5c31af7Sopenharmony_ci 0, // deUint32 waitSemaphoreCount; 351e5c31af7Sopenharmony_ci DE_NULL, // const VkSemaphore* pWaitSemaphores; 352e5c31af7Sopenharmony_ci 1u, // deUint32 bufferBindCount; 353e5c31af7Sopenharmony_ci &sparseBufferMemoryBindInfo, // const VkSparseBufferMemoryBindInfo* pBufferBinds; 354e5c31af7Sopenharmony_ci 0, // deUint32 imageOpaqueBindCount; 355e5c31af7Sopenharmony_ci DE_NULL, // const VkSparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds; 356e5c31af7Sopenharmony_ci 0, // deUint32 imageBindCount; 357e5c31af7Sopenharmony_ci DE_NULL, // const VkSparseImageMemoryBindInfo* pImageBinds; 358e5c31af7Sopenharmony_ci 0, // deUint32 signalSemaphoreCount; 359e5c31af7Sopenharmony_ci DE_NULL, // const VkSemaphore* pSignalSemaphores; 360e5c31af7Sopenharmony_ci }; 361e5c31af7Sopenharmony_ci 362e5c31af7Sopenharmony_ci const vk::Unique<vk::VkFence> fence (vk::createFence(vk, vkDevice)); 363e5c31af7Sopenharmony_ci 364e5c31af7Sopenharmony_ci if (vk.queueBindSparse(queue, 1, &bindSparseInfo, *fence) != VK_SUCCESS) 365e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("Bind sparse buffer memory failed! (requested memory size: " + de::toString(size) + ")"); 366e5c31af7Sopenharmony_ci 367e5c31af7Sopenharmony_ci VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), VK_TRUE, ~(0ull) /* infinity */)); 368e5c31af7Sopenharmony_ci } 369e5c31af7Sopenharmony_ci else if (vk.bindBufferMemory(vkDevice, *buffer, *memory, 0) != VK_SUCCESS) 370e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("Bind buffer memory failed! (requested memory size: " + de::toString(size) + ")"); 371e5c31af7Sopenharmony_ci#else 372e5c31af7Sopenharmony_ci if (vk.bindBufferMemory(vkDevice, *buffer, *memory, 0) != VK_SUCCESS) 373e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("Bind buffer memory failed! (requested memory size: " + de::toString(size) + ")"); 374e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC 375e5c31af7Sopenharmony_ci 376e5c31af7Sopenharmony_ci return tcu::TestStatus::pass("Pass"); 377e5c31af7Sopenharmony_ci} 378e5c31af7Sopenharmony_ci 379e5c31af7Sopenharmony_citcu::TestStatus BufferTestInstance::iterate (void) 380e5c31af7Sopenharmony_ci{ 381e5c31af7Sopenharmony_ci const VkDeviceSize testSizes[] = 382e5c31af7Sopenharmony_ci { 383e5c31af7Sopenharmony_ci 1, 384e5c31af7Sopenharmony_ci 1181, 385e5c31af7Sopenharmony_ci 15991, 386e5c31af7Sopenharmony_ci 16384, 387e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC 388e5c31af7Sopenharmony_ci ~0ull, // try to exercise a very large buffer too (will be clamped to a sensible size later) 389e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC 390e5c31af7Sopenharmony_ci }; 391e5c31af7Sopenharmony_ci 392e5c31af7Sopenharmony_ci for (int i = 0; i < DE_LENGTH_OF_ARRAY(testSizes); ++i) 393e5c31af7Sopenharmony_ci { 394e5c31af7Sopenharmony_ci const tcu::TestStatus testStatus = bufferCreateAndAllocTest(testSizes[i]); 395e5c31af7Sopenharmony_ci 396e5c31af7Sopenharmony_ci if (testStatus.getCode() != QP_TEST_RESULT_PASS) 397e5c31af7Sopenharmony_ci return testStatus; 398e5c31af7Sopenharmony_ci } 399e5c31af7Sopenharmony_ci 400e5c31af7Sopenharmony_ci return tcu::TestStatus::pass("Pass"); 401e5c31af7Sopenharmony_ci} 402e5c31af7Sopenharmony_ci 403e5c31af7Sopenharmony_citcu::TestStatus DedicatedAllocationBufferTestInstance::bufferCreateAndAllocTest 404e5c31af7Sopenharmony_ci (VkDeviceSize size) 405e5c31af7Sopenharmony_ci{ 406e5c31af7Sopenharmony_ci const VkPhysicalDevice vkPhysicalDevice = m_context.getPhysicalDevice(); 407e5c31af7Sopenharmony_ci const InstanceInterface& vkInstance = m_context.getInstanceInterface(); 408e5c31af7Sopenharmony_ci const VkDevice vkDevice = m_context.getDevice(); 409e5c31af7Sopenharmony_ci const DeviceInterface& vk = m_context.getDeviceInterface(); 410e5c31af7Sopenharmony_ci const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 411e5c31af7Sopenharmony_ci const VkPhysicalDeviceMemoryProperties 412e5c31af7Sopenharmony_ci memoryProperties = getPhysicalDeviceMemoryProperties(vkInstance, vkPhysicalDevice); 413e5c31af7Sopenharmony_ci const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vkInstance, vkPhysicalDevice).limits; 414e5c31af7Sopenharmony_ci 415e5c31af7Sopenharmony_ci VkMemoryDedicatedRequirements dedicatedRequirements = 416e5c31af7Sopenharmony_ci { 417e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, // VkStructureType sType; 418e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 419e5c31af7Sopenharmony_ci false, // VkBool32 prefersDedicatedAllocation 420e5c31af7Sopenharmony_ci false // VkBool32 requiresDedicatedAllocation 421e5c31af7Sopenharmony_ci }; 422e5c31af7Sopenharmony_ci VkMemoryRequirements2 memReqs = 423e5c31af7Sopenharmony_ci { 424e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, // VkStructureType sType 425e5c31af7Sopenharmony_ci &dedicatedRequirements, // void* pNext 426e5c31af7Sopenharmony_ci {0, 0, 0} // VkMemoryRequirements memoryRequirements 427e5c31af7Sopenharmony_ci }; 428e5c31af7Sopenharmony_ci 429e5c31af7Sopenharmony_ci if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0) 430e5c31af7Sopenharmony_ci size = std::min(size, limits.sparseAddressSpaceSize); 431e5c31af7Sopenharmony_ci 432e5c31af7Sopenharmony_ci // Create a minimal buffer first to get the supported memory types 433e5c31af7Sopenharmony_ci VkBufferCreateInfo bufferParams = 434e5c31af7Sopenharmony_ci { 435e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType 436e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext 437e5c31af7Sopenharmony_ci m_testCase.flags, // VkBufferCreateFlags flags 438e5c31af7Sopenharmony_ci 1u, // VkDeviceSize size 439e5c31af7Sopenharmony_ci m_testCase.usage, // VkBufferUsageFlags usage 440e5c31af7Sopenharmony_ci m_testCase.sharingMode, // VkSharingMode sharingMode 441e5c31af7Sopenharmony_ci 1u, // uint32_t queueFamilyIndexCount 442e5c31af7Sopenharmony_ci &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices 443e5c31af7Sopenharmony_ci }; 444e5c31af7Sopenharmony_ci 445e5c31af7Sopenharmony_ci Move<VkBuffer> buffer = createBuffer(vk, vkDevice, &bufferParams); 446e5c31af7Sopenharmony_ci 447e5c31af7Sopenharmony_ci VkBufferMemoryRequirementsInfo2 info = 448e5c31af7Sopenharmony_ci { 449e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, // VkStructureType sType 450e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext 451e5c31af7Sopenharmony_ci *buffer // VkBuffer buffer 452e5c31af7Sopenharmony_ci }; 453e5c31af7Sopenharmony_ci 454e5c31af7Sopenharmony_ci vk.getBufferMemoryRequirements2(vkDevice, &info, &memReqs); 455e5c31af7Sopenharmony_ci 456e5c31af7Sopenharmony_ci if (dedicatedRequirements.requiresDedicatedAllocation == VK_TRUE) 457e5c31af7Sopenharmony_ci { 458e5c31af7Sopenharmony_ci std::ostringstream errorMsg; 459e5c31af7Sopenharmony_ci errorMsg << "Nonexternal objects cannot require dedicated allocation."; 460e5c31af7Sopenharmony_ci return tcu::TestStatus::fail(errorMsg.str()); 461e5c31af7Sopenharmony_ci } 462e5c31af7Sopenharmony_ci 463e5c31af7Sopenharmony_ci if(memReqs.memoryRequirements.memoryTypeBits == 0) 464e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("memoryTypeBits is 0"); 465e5c31af7Sopenharmony_ci 466e5c31af7Sopenharmony_ci const deUint32 heapTypeIndex = static_cast<deUint32>(deCtz32(memReqs.memoryRequirements.memoryTypeBits)); 467e5c31af7Sopenharmony_ci const VkMemoryType memoryType = memoryProperties.memoryTypes[heapTypeIndex]; 468e5c31af7Sopenharmony_ci const VkMemoryHeap memoryHeap = memoryProperties.memoryHeaps[memoryType.heapIndex]; 469e5c31af7Sopenharmony_ci const deUint32 shrinkBits = 4u; // number of bits to shift when reducing the size with each iteration 470e5c31af7Sopenharmony_ci 471e5c31af7Sopenharmony_ci // Buffer size - Choose half of the reported heap size for the maximum buffer size, we 472e5c31af7Sopenharmony_ci // should attempt to test as large a portion as possible. 473e5c31af7Sopenharmony_ci // 474e5c31af7Sopenharmony_ci // However on a system where device memory is shared with the system, the maximum size 475e5c31af7Sopenharmony_ci // should be tested against the platform memory limits as a significant portion of the heap 476e5c31af7Sopenharmony_ci // may already be in use by the operating system and other running processes. 477e5c31af7Sopenharmony_ci const VkDeviceSize maxBufferSize = getMaxBufferSize(memoryHeap.size, 478e5c31af7Sopenharmony_ci memReqs.memoryRequirements.alignment, 479e5c31af7Sopenharmony_ci getPlatformMemoryLimits(m_context)); 480e5c31af7Sopenharmony_ci 481e5c31af7Sopenharmony_ci Move<VkDeviceMemory> memory; 482e5c31af7Sopenharmony_ci size = deAlign64(std::min(size, maxBufferSize >> 1), memReqs.memoryRequirements.alignment); 483e5c31af7Sopenharmony_ci while (*memory == DE_NULL) 484e5c31af7Sopenharmony_ci { 485e5c31af7Sopenharmony_ci // Create the buffer 486e5c31af7Sopenharmony_ci { 487e5c31af7Sopenharmony_ci VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY; 488e5c31af7Sopenharmony_ci VkBuffer rawBuffer = DE_NULL; 489e5c31af7Sopenharmony_ci 490e5c31af7Sopenharmony_ci bufferParams.size = size; 491e5c31af7Sopenharmony_ci buffer = Move<VkBuffer>(); // free the previous buffer, if any 492e5c31af7Sopenharmony_ci result = vk.createBuffer(vkDevice, &bufferParams, (VkAllocationCallbacks*)DE_NULL, &rawBuffer); 493e5c31af7Sopenharmony_ci 494e5c31af7Sopenharmony_ci if (result != VK_SUCCESS) 495e5c31af7Sopenharmony_ci { 496e5c31af7Sopenharmony_ci size = deAlign64(size >> shrinkBits, memReqs.memoryRequirements.alignment); 497e5c31af7Sopenharmony_ci 498e5c31af7Sopenharmony_ci if (size == 0 || bufferParams.size == memReqs.memoryRequirements.alignment) 499e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("Buffer creation failed! (" + de::toString(getResultName(result)) + ")"); 500e5c31af7Sopenharmony_ci 501e5c31af7Sopenharmony_ci continue; // didn't work, try with a smaller buffer 502e5c31af7Sopenharmony_ci } 503e5c31af7Sopenharmony_ci 504e5c31af7Sopenharmony_ci buffer = Move<VkBuffer>(check<VkBuffer>(rawBuffer), Deleter<VkBuffer>(vk, vkDevice, DE_NULL)); 505e5c31af7Sopenharmony_ci } 506e5c31af7Sopenharmony_ci 507e5c31af7Sopenharmony_ci info.buffer = *buffer; 508e5c31af7Sopenharmony_ci vk.getBufferMemoryRequirements2(vkDevice, &info, &memReqs); // get the proper size requirement 509e5c31af7Sopenharmony_ci 510e5c31af7Sopenharmony_ci if (size > memReqs.memoryRequirements.size) 511e5c31af7Sopenharmony_ci { 512e5c31af7Sopenharmony_ci std::ostringstream errorMsg; 513e5c31af7Sopenharmony_ci errorMsg << "Requied memory size (" << memReqs.memoryRequirements.size << " bytes) smaller than the buffer's size (" << size << " bytes)!"; 514e5c31af7Sopenharmony_ci return tcu::TestStatus::fail(errorMsg.str()); 515e5c31af7Sopenharmony_ci } 516e5c31af7Sopenharmony_ci 517e5c31af7Sopenharmony_ci // Allocate the memory 518e5c31af7Sopenharmony_ci { 519e5c31af7Sopenharmony_ci VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY; 520e5c31af7Sopenharmony_ci VkDeviceMemory rawMemory = DE_NULL; 521e5c31af7Sopenharmony_ci 522e5c31af7Sopenharmony_ci vk::VkMemoryDedicatedAllocateInfo 523e5c31af7Sopenharmony_ci dedicatedInfo = 524e5c31af7Sopenharmony_ci { 525e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, // VkStructureType sType 526e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext 527e5c31af7Sopenharmony_ci DE_NULL, // VkImage image 528e5c31af7Sopenharmony_ci *buffer // VkBuffer buffer 529e5c31af7Sopenharmony_ci }; 530e5c31af7Sopenharmony_ci 531e5c31af7Sopenharmony_ci VkMemoryAllocateInfo memoryAllocateInfo = 532e5c31af7Sopenharmony_ci { 533e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType 534e5c31af7Sopenharmony_ci &dedicatedInfo, // const void* pNext 535e5c31af7Sopenharmony_ci memReqs.memoryRequirements.size, // VkDeviceSize allocationSize 536e5c31af7Sopenharmony_ci heapTypeIndex, // deUint32 memoryTypeIndex 537e5c31af7Sopenharmony_ci }; 538e5c31af7Sopenharmony_ci 539e5c31af7Sopenharmony_ci result = vk.allocateMemory(vkDevice, &memoryAllocateInfo, (VkAllocationCallbacks*)DE_NULL, &rawMemory); 540e5c31af7Sopenharmony_ci 541e5c31af7Sopenharmony_ci if (result != VK_SUCCESS) 542e5c31af7Sopenharmony_ci { 543e5c31af7Sopenharmony_ci size = deAlign64(size >> shrinkBits, memReqs.memoryRequirements.alignment); 544e5c31af7Sopenharmony_ci 545e5c31af7Sopenharmony_ci if (size == 0 || memReqs.memoryRequirements.size == memReqs.memoryRequirements.alignment) 546e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("Unable to allocate " + de::toString(memReqs.memoryRequirements.size) + " bytes of memory"); 547e5c31af7Sopenharmony_ci 548e5c31af7Sopenharmony_ci continue; // didn't work, try with a smaller allocation (and a smaller buffer) 549e5c31af7Sopenharmony_ci } 550e5c31af7Sopenharmony_ci 551e5c31af7Sopenharmony_ci memory = Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL)); 552e5c31af7Sopenharmony_ci } 553e5c31af7Sopenharmony_ci } // while 554e5c31af7Sopenharmony_ci 555e5c31af7Sopenharmony_ci if (vk.bindBufferMemory(vkDevice, *buffer, *memory, 0) != VK_SUCCESS) 556e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("Bind buffer memory failed! (requested memory size: " + de::toString(size) + ")"); 557e5c31af7Sopenharmony_ci 558e5c31af7Sopenharmony_ci return tcu::TestStatus::pass("Pass"); 559e5c31af7Sopenharmony_ci} 560e5c31af7Sopenharmony_ci 561e5c31af7Sopenharmony_cistd::string getBufferUsageFlagsName (const VkBufferUsageFlags flags) 562e5c31af7Sopenharmony_ci{ 563e5c31af7Sopenharmony_ci switch (flags) 564e5c31af7Sopenharmony_ci { 565e5c31af7Sopenharmony_ci case VK_BUFFER_USAGE_TRANSFER_SRC_BIT: return "transfer_src"; 566e5c31af7Sopenharmony_ci case VK_BUFFER_USAGE_TRANSFER_DST_BIT: return "transfer_dst"; 567e5c31af7Sopenharmony_ci case VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT: return "uniform_texel"; 568e5c31af7Sopenharmony_ci case VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT: return "storage_texel"; 569e5c31af7Sopenharmony_ci case VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT: return "uniform"; 570e5c31af7Sopenharmony_ci case VK_BUFFER_USAGE_STORAGE_BUFFER_BIT: return "storage"; 571e5c31af7Sopenharmony_ci case VK_BUFFER_USAGE_INDEX_BUFFER_BIT: return "index"; 572e5c31af7Sopenharmony_ci case VK_BUFFER_USAGE_VERTEX_BUFFER_BIT: return "vertex"; 573e5c31af7Sopenharmony_ci case VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT: return "indirect"; 574e5c31af7Sopenharmony_ci default: 575e5c31af7Sopenharmony_ci DE_FATAL("Unknown buffer usage flag"); 576e5c31af7Sopenharmony_ci return ""; 577e5c31af7Sopenharmony_ci } 578e5c31af7Sopenharmony_ci} 579e5c31af7Sopenharmony_ci 580e5c31af7Sopenharmony_cistd::string getBufferCreateFlagsName (const VkBufferCreateFlags flags) 581e5c31af7Sopenharmony_ci{ 582e5c31af7Sopenharmony_ci std::ostringstream name; 583e5c31af7Sopenharmony_ci 584e5c31af7Sopenharmony_ci if (flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) 585e5c31af7Sopenharmony_ci name << "_binding"; 586e5c31af7Sopenharmony_ci if (flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) 587e5c31af7Sopenharmony_ci name << "_residency"; 588e5c31af7Sopenharmony_ci if (flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) 589e5c31af7Sopenharmony_ci name << "_aliased"; 590e5c31af7Sopenharmony_ci if (flags == 0u) 591e5c31af7Sopenharmony_ci name << "_zero"; 592e5c31af7Sopenharmony_ci 593e5c31af7Sopenharmony_ci DE_ASSERT(!name.str().empty()); 594e5c31af7Sopenharmony_ci 595e5c31af7Sopenharmony_ci return name.str().substr(1); 596e5c31af7Sopenharmony_ci} 597e5c31af7Sopenharmony_ci 598e5c31af7Sopenharmony_ci// Create all VkBufferUsageFlags combinations recursively 599e5c31af7Sopenharmony_civoid createBufferUsageCases (tcu::TestCaseGroup& testGroup, const deUint32 firstNdx, const deUint32 bufferUsageFlags, const AllocationKind allocationKind) 600e5c31af7Sopenharmony_ci{ 601e5c31af7Sopenharmony_ci const VkBufferUsageFlags bufferUsageModes[] = 602e5c31af7Sopenharmony_ci { 603e5c31af7Sopenharmony_ci VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 604e5c31af7Sopenharmony_ci VK_BUFFER_USAGE_TRANSFER_DST_BIT, 605e5c31af7Sopenharmony_ci VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, 606e5c31af7Sopenharmony_ci VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, 607e5c31af7Sopenharmony_ci VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, 608e5c31af7Sopenharmony_ci VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, 609e5c31af7Sopenharmony_ci VK_BUFFER_USAGE_INDEX_BUFFER_BIT, 610e5c31af7Sopenharmony_ci VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 611e5c31af7Sopenharmony_ci VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT 612e5c31af7Sopenharmony_ci }; 613e5c31af7Sopenharmony_ci 614e5c31af7Sopenharmony_ci tcu::TestContext& testCtx = testGroup.getTestContext(); 615e5c31af7Sopenharmony_ci 616e5c31af7Sopenharmony_ci // Add test groups 617e5c31af7Sopenharmony_ci for (deUint32 currentNdx = firstNdx; currentNdx < DE_LENGTH_OF_ARRAY(bufferUsageModes); currentNdx++) 618e5c31af7Sopenharmony_ci { 619e5c31af7Sopenharmony_ci const deUint32 newBufferUsageFlags = bufferUsageFlags | bufferUsageModes[currentNdx]; 620e5c31af7Sopenharmony_ci const std::string newGroupName = getBufferUsageFlagsName(bufferUsageModes[currentNdx]); 621e5c31af7Sopenharmony_ci de::MovePtr<tcu::TestCaseGroup> newTestGroup (new tcu::TestCaseGroup(testCtx, newGroupName.c_str())); 622e5c31af7Sopenharmony_ci 623e5c31af7Sopenharmony_ci createBufferUsageCases(*newTestGroup, currentNdx + 1u, newBufferUsageFlags, allocationKind); 624e5c31af7Sopenharmony_ci testGroup.addChild(newTestGroup.release()); 625e5c31af7Sopenharmony_ci } 626e5c31af7Sopenharmony_ci 627e5c31af7Sopenharmony_ci // Add test cases 628e5c31af7Sopenharmony_ci if (bufferUsageFlags != 0u) 629e5c31af7Sopenharmony_ci { 630e5c31af7Sopenharmony_ci // \note SPARSE_RESIDENCY and SPARSE_ALIASED have to be used together with the SPARSE_BINDING flag. 631e5c31af7Sopenharmony_ci const VkBufferCreateFlags bufferCreateFlags[] = 632e5c31af7Sopenharmony_ci { 633e5c31af7Sopenharmony_ci 0, 634e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC 635e5c31af7Sopenharmony_ci VK_BUFFER_CREATE_SPARSE_BINDING_BIT, 636e5c31af7Sopenharmony_ci VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT, 637e5c31af7Sopenharmony_ci VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT, 638e5c31af7Sopenharmony_ci VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT, 639e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC 640e5c31af7Sopenharmony_ci }; 641e5c31af7Sopenharmony_ci 642e5c31af7Sopenharmony_ci // Dedicated allocation does not support sparse feature 643e5c31af7Sopenharmony_ci const int numBufferCreateFlags = (allocationKind == ALLOCATION_KIND_SUBALLOCATED) ? DE_LENGTH_OF_ARRAY(bufferCreateFlags) : 1; 644e5c31af7Sopenharmony_ci 645e5c31af7Sopenharmony_ci de::MovePtr<tcu::TestCaseGroup> newTestGroup (new tcu::TestCaseGroup(testCtx, "create")); 646e5c31af7Sopenharmony_ci 647e5c31af7Sopenharmony_ci for (int bufferCreateFlagsNdx = 0; bufferCreateFlagsNdx < numBufferCreateFlags; bufferCreateFlagsNdx++) 648e5c31af7Sopenharmony_ci { 649e5c31af7Sopenharmony_ci const BufferCaseParameters testParams = 650e5c31af7Sopenharmony_ci { 651e5c31af7Sopenharmony_ci bufferUsageFlags, 652e5c31af7Sopenharmony_ci bufferCreateFlags[bufferCreateFlagsNdx], 653e5c31af7Sopenharmony_ci VK_SHARING_MODE_EXCLUSIVE 654e5c31af7Sopenharmony_ci }; 655e5c31af7Sopenharmony_ci 656e5c31af7Sopenharmony_ci const std::string allocStr = (allocationKind == ALLOCATION_KIND_SUBALLOCATED) ? "suballocation of " : "dedicated alloc. of "; 657e5c31af7Sopenharmony_ci const std::string caseName = getBufferCreateFlagsName(bufferCreateFlags[bufferCreateFlagsNdx]); 658e5c31af7Sopenharmony_ci 659e5c31af7Sopenharmony_ci switch (allocationKind) 660e5c31af7Sopenharmony_ci { 661e5c31af7Sopenharmony_ci case ALLOCATION_KIND_SUBALLOCATED: 662e5c31af7Sopenharmony_ci newTestGroup->addChild(new BuffersTestCase(testCtx, caseName.c_str(), testParams)); 663e5c31af7Sopenharmony_ci break; 664e5c31af7Sopenharmony_ci case ALLOCATION_KIND_DEDICATED: 665e5c31af7Sopenharmony_ci newTestGroup->addChild(new DedicatedAllocationBuffersTestCase(testCtx, caseName.c_str(), testParams)); 666e5c31af7Sopenharmony_ci break; 667e5c31af7Sopenharmony_ci default: 668e5c31af7Sopenharmony_ci DE_FATAL("Unknown test type"); 669e5c31af7Sopenharmony_ci } 670e5c31af7Sopenharmony_ci } 671e5c31af7Sopenharmony_ci testGroup.addChild(newTestGroup.release()); 672e5c31af7Sopenharmony_ci } 673e5c31af7Sopenharmony_ci} 674e5c31af7Sopenharmony_ci 675e5c31af7Sopenharmony_citcu::TestStatus testDepthStencilBufferFeatures(Context& context, VkFormat format) 676e5c31af7Sopenharmony_ci{ 677e5c31af7Sopenharmony_ci const InstanceInterface& vki = context.getInstanceInterface(); 678e5c31af7Sopenharmony_ci VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); 679e5c31af7Sopenharmony_ci VkFormatProperties formatProperties; 680e5c31af7Sopenharmony_ci 681e5c31af7Sopenharmony_ci vki.getPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties); 682e5c31af7Sopenharmony_ci 683e5c31af7Sopenharmony_ci if (formatProperties.bufferFeatures == 0x0) 684e5c31af7Sopenharmony_ci return tcu::TestStatus::pass("Pass"); 685e5c31af7Sopenharmony_ci else 686e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("Fail"); 687e5c31af7Sopenharmony_ci} 688e5c31af7Sopenharmony_ci 689e5c31af7Sopenharmony_cistruct LargeBufferParameters 690e5c31af7Sopenharmony_ci{ 691e5c31af7Sopenharmony_ci deUint64 bufferSize; 692e5c31af7Sopenharmony_ci bool useMaxBufferSize; 693e5c31af7Sopenharmony_ci VkBufferCreateFlags flags; 694e5c31af7Sopenharmony_ci}; 695e5c31af7Sopenharmony_ci 696e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC 697e5c31af7Sopenharmony_citcu::TestStatus testLargeBuffer(Context& context, LargeBufferParameters params) 698e5c31af7Sopenharmony_ci{ 699e5c31af7Sopenharmony_ci const DeviceInterface& vk = context.getDeviceInterface(); 700e5c31af7Sopenharmony_ci const VkDevice vkDevice = context.getDevice(); 701e5c31af7Sopenharmony_ci const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 702e5c31af7Sopenharmony_ci const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(context.getInstanceInterface(), 703e5c31af7Sopenharmony_ci context.getPhysicalDevice()).limits; 704e5c31af7Sopenharmony_ci VkBuffer rawBuffer = DE_NULL; 705e5c31af7Sopenharmony_ci 706e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC 707e5c31af7Sopenharmony_ci if (params.useMaxBufferSize) 708e5c31af7Sopenharmony_ci params.bufferSize = context.getMaintenance4Properties().maxBufferSize; 709e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC 710e5c31af7Sopenharmony_ci 711e5c31af7Sopenharmony_ci if ((params.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0) 712e5c31af7Sopenharmony_ci params.bufferSize = std::min(params.bufferSize, limits.sparseAddressSpaceSize); 713e5c31af7Sopenharmony_ci 714e5c31af7Sopenharmony_ci VkBufferCreateInfo bufferParams = 715e5c31af7Sopenharmony_ci { 716e5c31af7Sopenharmony_ci VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 717e5c31af7Sopenharmony_ci DE_NULL, // const void* pNext; 718e5c31af7Sopenharmony_ci params.flags, // VkBufferCreateFlags flags; 719e5c31af7Sopenharmony_ci params.bufferSize, // VkDeviceSize size; 720e5c31af7Sopenharmony_ci VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // VkBufferUsageFlags usage; 721e5c31af7Sopenharmony_ci VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 722e5c31af7Sopenharmony_ci 1u, // uint32_t queueFamilyIndexCount; 723e5c31af7Sopenharmony_ci &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices; 724e5c31af7Sopenharmony_ci }; 725e5c31af7Sopenharmony_ci 726e5c31af7Sopenharmony_ci VkResult result = vk.createBuffer(vkDevice, &bufferParams, (vk::VkAllocationCallbacks*)DE_NULL, &rawBuffer); 727e5c31af7Sopenharmony_ci 728e5c31af7Sopenharmony_ci // if buffer creation succeeds verify that the correct amount of memory was bound to it 729e5c31af7Sopenharmony_ci if (result == VK_SUCCESS) 730e5c31af7Sopenharmony_ci { 731e5c31af7Sopenharmony_ci VkMemoryRequirements memoryRequirements; 732e5c31af7Sopenharmony_ci vk.getBufferMemoryRequirements(vkDevice, rawBuffer, &memoryRequirements); 733e5c31af7Sopenharmony_ci vk.destroyBuffer(vkDevice, rawBuffer, DE_NULL); 734e5c31af7Sopenharmony_ci 735e5c31af7Sopenharmony_ci if (memoryRequirements.size >= params.bufferSize) 736e5c31af7Sopenharmony_ci return tcu::TestStatus::pass("Pass"); 737e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("Fail"); 738e5c31af7Sopenharmony_ci } 739e5c31af7Sopenharmony_ci 740e5c31af7Sopenharmony_ci // check if one of the allowed errors was returned 741e5c31af7Sopenharmony_ci if ((result == VK_ERROR_OUT_OF_DEVICE_MEMORY) || 742e5c31af7Sopenharmony_ci (result == VK_ERROR_OUT_OF_HOST_MEMORY)) 743e5c31af7Sopenharmony_ci return tcu::TestStatus::pass("Pass"); 744e5c31af7Sopenharmony_ci 745e5c31af7Sopenharmony_ci return tcu::TestStatus::fail("Fail"); 746e5c31af7Sopenharmony_ci} 747e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC 748e5c31af7Sopenharmony_ci 749e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC 750e5c31af7Sopenharmony_civoid checkMaintenance4Support(Context& context, LargeBufferParameters params) 751e5c31af7Sopenharmony_ci{ 752e5c31af7Sopenharmony_ci if (params.useMaxBufferSize) 753e5c31af7Sopenharmony_ci context.requireDeviceFunctionality("VK_KHR_maintenance4"); 754e5c31af7Sopenharmony_ci else if (context.isDeviceFunctionalitySupported("VK_KHR_maintenance4") && 755e5c31af7Sopenharmony_ci params.bufferSize > context.getMaintenance4Properties().maxBufferSize) 756e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "vkCreateBuffer with a size larger than maxBufferSize is not valid usage"); 757e5c31af7Sopenharmony_ci 758e5c31af7Sopenharmony_ci const VkPhysicalDeviceFeatures& physicalDeviceFeatures = getPhysicalDeviceFeatures(context.getInstanceInterface(), context.getPhysicalDevice()); 759e5c31af7Sopenharmony_ci if ((params.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) && !physicalDeviceFeatures.sparseBinding) 760e5c31af7Sopenharmony_ci TCU_THROW(NotSupportedError, "Sparse bindings feature is not supported"); 761e5c31af7Sopenharmony_ci} 762e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC 763e5c31af7Sopenharmony_ci 764e5c31af7Sopenharmony_ci} // anonymous 765e5c31af7Sopenharmony_ci 766e5c31af7Sopenharmony_ci tcu::TestCaseGroup* createBufferTests (tcu::TestContext& testCtx) 767e5c31af7Sopenharmony_ci{ 768e5c31af7Sopenharmony_ci de::MovePtr<tcu::TestCaseGroup> buffersTests (new tcu::TestCaseGroup(testCtx, "buffer")); 769e5c31af7Sopenharmony_ci 770e5c31af7Sopenharmony_ci { 771e5c31af7Sopenharmony_ci de::MovePtr<tcu::TestCaseGroup> regularAllocation (new tcu::TestCaseGroup(testCtx, "suballocation")); 772e5c31af7Sopenharmony_ci createBufferUsageCases(*regularAllocation, 0u, 0u, ALLOCATION_KIND_SUBALLOCATED); 773e5c31af7Sopenharmony_ci buffersTests->addChild(regularAllocation.release()); 774e5c31af7Sopenharmony_ci } 775e5c31af7Sopenharmony_ci 776e5c31af7Sopenharmony_ci { 777e5c31af7Sopenharmony_ci de::MovePtr<tcu::TestCaseGroup> dedicatedAllocation (new tcu::TestCaseGroup(testCtx, "dedicated_alloc")); 778e5c31af7Sopenharmony_ci createBufferUsageCases(*dedicatedAllocation, 0u, 0u, ALLOCATION_KIND_DEDICATED); 779e5c31af7Sopenharmony_ci buffersTests->addChild(dedicatedAllocation.release()); 780e5c31af7Sopenharmony_ci } 781e5c31af7Sopenharmony_ci 782e5c31af7Sopenharmony_ci { 783e5c31af7Sopenharmony_ci de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "basic")); 784e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC 785e5c31af7Sopenharmony_ci // Creating buffer using maxBufferSize limit. 786e5c31af7Sopenharmony_ci addFunctionCase(basicTests.get(), "max_size", 787e5c31af7Sopenharmony_ci checkMaintenance4Support, testLargeBuffer, LargeBufferParameters 788e5c31af7Sopenharmony_ci { 789e5c31af7Sopenharmony_ci 0u, 790e5c31af7Sopenharmony_ci true, 791e5c31af7Sopenharmony_ci 0u 792e5c31af7Sopenharmony_ci }); 793e5c31af7Sopenharmony_ci // Creating sparse buffer using maxBufferSize limit. 794e5c31af7Sopenharmony_ci addFunctionCase(basicTests.get(), "max_size_sparse", 795e5c31af7Sopenharmony_ci checkMaintenance4Support, testLargeBuffer, LargeBufferParameters 796e5c31af7Sopenharmony_ci { 797e5c31af7Sopenharmony_ci 0u, 798e5c31af7Sopenharmony_ci true, 799e5c31af7Sopenharmony_ci VK_BUFFER_CREATE_SPARSE_BINDING_BIT 800e5c31af7Sopenharmony_ci }); 801e5c31af7Sopenharmony_ci // Creating a ULLONG_MAX buffer and verify that it either succeeds or returns one of the allowed errors. 802e5c31af7Sopenharmony_ci addFunctionCase(basicTests.get(), "size_max_uint64", 803e5c31af7Sopenharmony_ci checkMaintenance4Support, testLargeBuffer, LargeBufferParameters 804e5c31af7Sopenharmony_ci { 805e5c31af7Sopenharmony_ci std::numeric_limits<deUint64>::max(), 806e5c31af7Sopenharmony_ci false, 807e5c31af7Sopenharmony_ci 0u 808e5c31af7Sopenharmony_ci }); 809e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC 810e5c31af7Sopenharmony_ci buffersTests->addChild(basicTests.release()); 811e5c31af7Sopenharmony_ci } 812e5c31af7Sopenharmony_ci 813e5c31af7Sopenharmony_ci { 814e5c31af7Sopenharmony_ci static const VkFormat dsFormats[] = 815e5c31af7Sopenharmony_ci { 816e5c31af7Sopenharmony_ci VK_FORMAT_S8_UINT, 817e5c31af7Sopenharmony_ci VK_FORMAT_D16_UNORM, 818e5c31af7Sopenharmony_ci VK_FORMAT_D16_UNORM_S8_UINT, 819e5c31af7Sopenharmony_ci VK_FORMAT_D24_UNORM_S8_UINT, 820e5c31af7Sopenharmony_ci VK_FORMAT_D32_SFLOAT, 821e5c31af7Sopenharmony_ci VK_FORMAT_D32_SFLOAT_S8_UINT, 822e5c31af7Sopenharmony_ci VK_FORMAT_X8_D24_UNORM_PACK32 823e5c31af7Sopenharmony_ci }; 824e5c31af7Sopenharmony_ci 825e5c31af7Sopenharmony_ci // Checks that drivers are not exposing undesired format features for depth/stencil formats. 826e5c31af7Sopenharmony_ci de::MovePtr<tcu::TestCaseGroup> invalidBufferFeatures(new tcu::TestCaseGroup(testCtx, "invalid_buffer_features")); 827e5c31af7Sopenharmony_ci 828e5c31af7Sopenharmony_ci for (const auto& testFormat : dsFormats) 829e5c31af7Sopenharmony_ci { 830e5c31af7Sopenharmony_ci std::string formatName = de::toLower(getFormatName(testFormat)); 831e5c31af7Sopenharmony_ci 832e5c31af7Sopenharmony_ci addFunctionCase(invalidBufferFeatures.get(), formatName, testDepthStencilBufferFeatures, testFormat); 833e5c31af7Sopenharmony_ci } 834e5c31af7Sopenharmony_ci 835e5c31af7Sopenharmony_ci buffersTests->addChild(invalidBufferFeatures.release()); 836e5c31af7Sopenharmony_ci } 837e5c31af7Sopenharmony_ci 838e5c31af7Sopenharmony_ci return buffersTests.release(); 839e5c31af7Sopenharmony_ci} 840e5c31af7Sopenharmony_ci 841e5c31af7Sopenharmony_ci} // api 842e5c31af7Sopenharmony_ci} // vk 843