miyoku
miyoku

Reputation: 187

Using Vulkan memory allocator with Volk

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?

Upvotes: 4

Views: 2293

Answers (2)

enigmaticPhysicist
enigmaticPhysicist

Reputation: 1729

One must pass volk's vkGetInstanceProcAddr and vkGetDeviceProcAddr to vmaCreateAllocator(), so that it can find all of the Vulkan API calls it needs to function.

VmaAllocator allocator;
vmaCreateAllocator(
    &(VmaAllocatorCreateInfo){
        .physicalDevice = physical_device,
        .device = g_device,
        .instance = instance,
        .pVulkanFunctions = &(VmaVulkanFunctions){
            .vkGetInstanceProcAddr = vkGetInstanceProcAddr,
            .vkGetDeviceProcAddr = vkGetDeviceProcAddr
            }
    },
    &allocator
);

Upvotes: 0

Sascha Willems
Sascha Willems

Reputation: 5808

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;

Upvotes: 6

Related Questions