在我当前的系统中,vulkan信息返回以下设备规格:
memoryHeaps[0]:
size = 8589934592 (0x200000000) (8.00 GiB)
budget = 7826571264 (0x1d2800000) (7.29 GiB)
usage = 0 (0x00000000) (0.00 B)
flags: count = 1
MEMORY_HEAP_DEVICE_LOCAL_BIT
memoryHeaps[1]:
size = 12453414912 (0x2e6480800) (11.60 GiB)
budget = 12453414912 (0x2e6480800) (11.60 GiB)
usage = 0 (0x00000000) (0.00 B)
flags:
None
memoryHeaps[2]:
size = 257949696 (0x0f600000) (246.00 MiB)
budget = 251068416 (0x0ef70000) (239.44 MiB)
usage = 6881280 (0x00690000) (6.56 MiB)
flags: count = 1
MEMORY_HEAP_DEVICE_LOCAL_BIT
总之,堆0好,堆2坏。
我收到一条消息,我正在分配的大量纹理内存不足:
Message: Validation Error: [ VUID-vkAllocateMemory-pAllocateInfo-01713 ] Object 0: handle = 0x5562fe1c6760, name = Logical device: NVIDIA GeForce GTX 1070, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0xe9a2b96f | vkAllocateMemory: attempting to allocate 268435456 bytes from heap 2,but size of that heap is only 257949696 bytes. The Vulkan spec states: pAllocateInfo->allocationSize must be less than or equal to VkPhysicalDeviceMemoryProperties::memoryHeaps[memindex].size where memindex = VkPhysicalDeviceMemoryProperties::memoryTypes[pAllocateInfo->memoryTypeIndex].heapIndex as returned by vkGetPhysicalDeviceMemoryProperties for the VkPhysicalDevice that device was created from (https://vulkan.lunarg.com/doc/view/1.3.211.0/linux/1.3-extensions/vkspec.html#VUID-vkAllocateMemory-pAllocateInfo-01713)
Severity: VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
所以我想告诉VMA使用堆0,它确实有足够的容量来容纳我的giga纹理。
我正试图这样分配:
vk::Device& device = h_interface->GetDevice();
const bool is_3D_image = depth > 0;
// Set image creation information.
vk::ImageCreateInfo image_info = {};
image_info.imageType = is_3D_image ? vk::ImageType::e3D : vk::ImageType::e2D;
image_info.format = format;
image_info.extent = vk::Extent3D(width, height, max(uint32_t(1), depth));
image_info.mipLevels = 1;
image_info.arrayLayers = 1;
image_info.samples = vk::SampleCountFlagBits::e1;
image_info.tiling = tiling;
image_info.usage = usage;
image_info.sharingMode = vk::SharingMode::eExclusive;
image_info.initialLayout = initial_layout;
VmaAllocationCreateInfo allocation_info = {};
allocation_info.usage = VMA_MEMORY_USAGE_AUTO;
uint32_t memoryTypeIndex = 0;
allocation_info.memoryTypeBits = 0u << memoryTypeIndex;
VmaAllocation allocation;
vk::Image image;
VkResult result = vmaCreateImage(
vma_allocator,
(VkImageCreateInfo*)&image_info,
&allocation_info,
(VkImage*)&image,
&allocation,
nullptr);
我试着改变allocation_info.usage
,我试着去改变allocation_info.memoryTypeBits
。在创建VMA结构时,我尝试将除第一个堆之外的所有堆的设备限制设置为0。
我读了三遍:https://gpuopen-librariesandsdks.github.io/VulkanMemoryAllocator/html/choosing_memory_type.html
我没有;我不知道如何告诉VMA请从堆0进行分配。
VMA的VmaAllocationCreateInfo结构有一个名为memoryTypeBits
的成员。这允许您提供一组内存类型,VMA必须从中选择分配。因此,您可以从Vulkan获取内存类型集,并且只指定那些使用堆0的内存类型。
话虽如此,这个问题发生的事实应该让你重新考虑VMA。堆2专门用于将数据从CPU高效地流式传输到GPU。这很容易确定,因为使用它的所有内存类型都是主机可见的。
但是,除非图像使用线性平铺,否则不能直接写入图像的字节。因此,当其他不可见主机的内存类型可用时(除非您的其他标志之一需要它(,VMA不需要使用主机可见内存类型。如果图像不是线性平铺的,并且你没有告诉VMA确保内存在主机上可见,那么它的算法有一个缺陷,应该让你重新考虑继续使用它。