Skip to content

Conversation

@M2-TE
Copy link

@M2-TE M2-TE commented Oct 24, 2025

This resolves #513.

Some background first:
When using C++20 modules, exporting VMA leads to issues with the newly released Clang 21. It e.g. complains about VmaFree being an unkown symbol, as it is a TU-local entity with internal linkage (static), which cannot be exported. The solution here is to also mark the function as inline, which allows the compiler to export this function as part of another function that can be exported.

Looking through the rest of the code, there are a few redundant or contradictory uses of inline and static, which I wanted to hear some thoughts about:

  • Templated functions: These will always be inlined, so adding inline is redundant, but might be nice as an indication of intent. Some of these are also marked as static however, which would only really make sense for template specializations (of which there aren't any, as far as I could tell).
  • static in general: This library is intended to be used in both C and C++ environments, correct? I only have experience with the latter, so correct me if it is wrong for either, but do static functions even make sense here (inside the implementation portion)? The header alongside VMA_IMPLEMENTATION should only be used in a single location in the project, so there won't be any ODR violations. The static keyword for this purpose was supposed to be deprecated in C++11 in favor of using anonymous namespaces instead. Since the implementation side is C++, that might be a better solution, if this functionality is even desired.

@sawickiap
Copy link
Contributor

I've pushed the fix as you suggested, on my fork for now:
https://github.com/sawickiap/VulkanMemoryAllocator

Please let me know if it works for you.

sawickiap pushed a commit to sawickiap/VulkanMemoryAllocator that referenced this pull request Nov 5, 2025
@sawickiap
Copy link
Contributor

Thank you for these suggestions. I think you are right - inline and static may be used inconsistently throughout the library source code. My intent was that:

  • inline is used whenever a function is simple, to hint the compiler to prefer inlining it.
  • static is used for global functions, constants, variables to make them local to the .cpp file so they don't participate in the linking process, which might have some performance cost and could generate errors if clashing with a function with the same name in another .cpp file.

In the latter case, I agree that using an anonymous namespace is a better solution, considering the implementation of VMA is in C++14. I've changed in. Please let me know if it works for you.

@M2-TE
Copy link
Author

M2-TE commented Nov 6, 2025

Your fork works for me; tested with Clang 21 and compiled as part of a C++20 module.

Anonymous namespace implementation LGTM! Marking some static const as constexpr inside it was also a good idea.
You could likely do the same to some of the static const members in your structs/classes, e.g. VmaMappingHysteresis:

class VmaMappingHysteresis
{
    // static const int32_t COUNTER_MIN_EXTRA_MAPPING = 7; // C-style
    static constexpr int32_t COUNTER_MIN_EXTRA_MAPPING = 7; // C++-style
};

Marking them as static constexpr avoids any storage for these inside the structs, just like the current static const. It is a stronger hint to the compiler, that these can (and should) be evaluated at compile time for some extra potential optimizations.

sawickiap pushed a commit to sawickiap/VulkanMemoryAllocator that referenced this pull request Nov 6, 2025
@sawickiap
Copy link
Contributor

Thanks for this suggestion. I changed some member variables from static const to static constexpr.

@M2-TE
Copy link
Author

M2-TE commented Nov 6, 2025

Looks good!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fails to build with clang 21 when used via C++ module

2 participants