4

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?

2 Answers 2

7

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;
Sign up to request clarification or add additional context in comments.

6 Comments

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?
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.
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?
Check vkGetBufferMemoryRequirements2 instead of vkGetBufferMemoryRequirements2KHR. The former is the core version, which should be available with Vulkan 1.1 and up.
I didn't know that, it work well now thanks a lot for the precise answer
|
0

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
);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.