0

I'm currently trying to use Vulkan memory allocator with the meta loader Volk here is the link of the two: https://github.com/zeux/volk

https://gpuopen.com/vulkan-memory-allocator/

But I have trouble with creating the VmaAllocator, here is my code:

void VulkApp::Init(PipelineFlags t_Conf, entt::registry& t_reg)
{
    volkInitialize();
    WindowProps props = {};
    props.Height = 600;
    props.Width = 800;
    props.Title = "Engine";
    currentWindow = EngWindow::Create(props);

    //Create all physical, logical, instance for vulkan
    Prepare();
    VolkDeviceTable test;
    volkLoadDeviceTable(&test, m_LogicalDevice->GetVkDevice());
    VmaAllocatorCreateInfo allocatorCreateInfo = {};
    allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_2;
    allocatorCreateInfo.physicalDevice = m_PhysicalDevice->GetVkPhysicalDevice();
    allocatorCreateInfo.device = m_LogicalDevice->GetVkDevice();
    allocatorCreateInfo.instance = m_Instance->GetRawVkInstance();
    allocatorCreateInfo.pVulkanFunctions = reinterpret_cast<const VmaVulkanFunctions*> (&test);

    VmaAllocator allocator;
    vmaCreateAllocator(&allocatorCreateInfo, &allocator);
    BuildRenderPipelines(t_Conf, t_reg);
}

void VulkApp::Prepare()
{
    m_Instance = std::make_unique<VulkInst>();
    volkLoadInstance(m_Instance->GetRawVkInstance());
    currentWindow->CreateSurface(m_Instance->GetRawVkInstance(), &m_Surface);
    m_PhysicalDevice = std::make_unique<PhysicalDevice>(*m_Instance);
    m_LogicalDevice = std::make_unique<LogicalDevice>(*m_Instance, *m_PhysicalDevice, m_Surface);
    volkLoadDevice(m_LogicalDevice->GetVkDevice());
    m_SwapChain = std::make_unique<SwapChain>(ChooseSwapExtent(), *m_LogicalDevice, *m_PhysicalDevice, m_Surface);
    GraphicsHelpers::CreateCommandPool(m_CommandPool, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); //TODO: added Transient bit
    CreateFrameSyncResources();

    /*
    Create Camera
    */
    BuildSwapChainResources();
}

I don't have any error when i build, but when i execute, the VmaCreateAllocator return an error:

Exception raised at 0x00007FFAB0CD836B (VkLayer_khronos_validation.dll) in My_Game.exe : 0xC0000005 : access violation reading location 0x0000000000000120.

Not very useful, but it stops on the line 14082 of the file vk_mem_alloc.h:

(*m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties)(m_PhysicalDevice, &m_MemProps);

The program check all the vulkan validation function so my vulkan function table must be good. But still the allocation fail. I'm sorry i don't put a 'minimal' code, but with vulkan, even the minimum is really long. So, as a first test, maybe some of you have an insight of the error?

miyoku
  • 107
  • 1
  • 13

1 Answers1

2

If you use a loader like Volk, you need to provide all memory related Vulkan function pointers used by VMA yourself.

This is done via the pVulkanFunctions member of the VmaAllocatorCreateInfo structure.

So when creating your VmaAllactor you set the function pointer in that to those fetched via Volk like this:

VmaVulkanFunctions vma_vulkan_func{};
vma_vulkan_func.vkAllocateMemory                    = vkAllocateMemory;
vma_vulkan_func.vkBindBufferMemory                  = vkBindBufferMemory;
vma_vulkan_func.vkBindImageMemory                   = vkBindImageMemory;
vma_vulkan_func.vkCreateBuffer                      = vkCreateBuffer;
vma_vulkan_func.vkCreateImage                       = vkCreateImage;
vma_vulkan_func.vkDestroyBuffer                     = vkDestroyBuffer;
vma_vulkan_func.vkDestroyImage                      = vkDestroyImage;
vma_vulkan_func.vkFlushMappedMemoryRanges           = vkFlushMappedMemoryRanges;
vma_vulkan_func.vkFreeMemory                        = vkFreeMemory;
vma_vulkan_func.vkGetBufferMemoryRequirements       = vkGetBufferMemoryRequirements;
vma_vulkan_func.vkGetImageMemoryRequirements        = vkGetImageMemoryRequirements;
vma_vulkan_func.vkGetPhysicalDeviceMemoryProperties = vkGetPhysicalDeviceMemoryProperties;
vma_vulkan_func.vkGetPhysicalDeviceProperties       = vkGetPhysicalDeviceProperties;
vma_vulkan_func.vkInvalidateMappedMemoryRanges      = vkInvalidateMappedMemoryRanges;
vma_vulkan_func.vkMapMemory                         = vkMapMemory;
vma_vulkan_func.vkUnmapMemory                       = vkUnmapMemory;
vma_vulkan_func.vkCmdCopyBuffer                     = vkCmdCopyBuffer;

And then pass those to the create info:

VmaAllocatorCreateInfo allocator_info{};
...
allocator_info.pVulkanFunctions = &vma_vulkan_func;
Sascha Willems
  • 5,280
  • 1
  • 14
  • 21
  • I set up my vulkan function with the VolkDeviceTable: ````VolkDeviceTable test; volkLoadDeviceTable(&test, m_LogicalDevice->GetVkDevice()); allocatorCreateInfo.pVulkanFunctions = (VmaVulkanFunctions*)&test;```` I think it was the easier way to it no? – miyoku Aug 27 '22 at 17:01
  • You can't simply cast a `VolkDeviceTable` to `VmaVulkanFunctions`. Those are different types. Vma doesn't know about the Volk type, so there is now way for it to interpret that structure. While the cast may seem to work, the access violation you see is a result of this. – Sascha Willems Aug 27 '22 at 19:41
  • Ok i see, i'm trying to do so, nevertheless there is a weird problem with functions like these: ``vkGetBufferMemoryRequirements2KHR`` I'm using vulkan version 1.2. I've checked my instance, VMA import which all use 1.2. But after the ``volkLoadDevice``, these function end up nullptr. Instead, if i try to load them in a volkDeviceTable, these functions have a correct pointer. What is the difference? – miyoku Aug 27 '22 at 20:04
  • 1
    Check `vkGetBufferMemoryRequirements2` instead of `vkGetBufferMemoryRequirements2KHR`. The former is the core version, which should be available with Vulkan 1.1 and up. – Sascha Willems Aug 28 '22 at 05:50
  • I didn't know that, it work well now thanks a lot for the precise answer – miyoku Aug 28 '22 at 09:04