-
-
Notifications
You must be signed in to change notification settings - Fork 10.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixed VkResult Error on macOS VulkanSDK 1.3.216 #6109
Conversation
A proper implementation needs to check for the availability of the VK_KHR_portability_subset extension, and does not rely on #ifdefs.
Additionally, the application must enable the VK_KHR_portability_enumeration extension to be able to enumerate non-conformant devices.
|
Thanks for the feedback, but I honestly don't know what you mean. If I read the documentation of 1.3.216 right for macOS, it is now enforcing the user, to enable the |
Yes, basically you need to check if the three extensions you are using are supported by the implementation, and only then enable them. It is possible that a future Mac Vulkan implementation will be fully conformant, in which case it will no longer advertise the portability subset, so requesting it will be an error. It is also possible that some other non-Apple implementation provides a non-conformant driver that you want to support here, but restrict behind an Apple-specific #ifdef. The two functions that return a list of available extensions are Things get even more complicated because Omar wants to support previous releases of MoltenVK (mentioned in #6101). While the VK_KHR_portability_subset extension was "always" required to enable, the VK_KHR_portability_enumeration extension is a recent addition. So you may have to resort to some kind of #ifdefing based on the header version anyway. Technically, it would be nice to extend the driver selection process to select a non-conforming implementation only if there are no conforming implementations. See the current selection logic below: imgui/examples/example_sdl_vulkan/main.cpp Lines 117 to 130 in 5c8041b
|
I agree. You could use a
In most cases we try to support old versions of SDK, but Apple ecosystems carrying a culture of aggressive-updating and MoltenVK (along with Vulkan) being known to be frequently updated I am OK if we don't support this if it can simplify examples and/or backends. I can't comment on the other specifics here. Happy to merge when it feels like we have a concensus. |
Unfortunately, availability of header defines for these extensions ripples to other platforms as well. For example, both An alternative would be to provide own definitions for missing things. For example, if
But this is not a solution I would prefer. |
Note that we afaik are talking about the examples/ application, for which it would be more acceptable to raise version requirements.
As opposed to Vulkan backend itself for which ideally we’d accept older versions (as people updating their version of dear imgui and relying on vanilla backends wouldn’t enjoy having to update an SDK to update dear imgui).
|
constexpr auto desired_version = VK_MAKE_VERSION(1, 3, 216); | ||
|
||
#if defined(__APPLE__) && VK_HEADER_VERSION >= desired_version |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't perform the correct test. The preprocessor doesn't know about constexpr variables and substitutes the not-defined name desired_version
with an integer zero in the comparison.
Updated the whole commit. Now there is a proper function, that checks if the extension has to be enabled. Also modernized the code with few C++ aspects(std::cerr, std::vector<>). Maybe check if out and give some feedback. :) Compiles on Windows, as well as on macOS. |
Please don't. This has turned this PR from "need some smal tweaks to merge" into "impossible to merge" :( I just need the minimum amount of changes (closer to 32da8f3 but ok to refactor slightly to use ImVector<> exactly in that spot to simplify adding extension) that also happens to be correct. Thank you for your patience. |
Alright. I understand. So I will change the modernized part to the old one, and change the extension part, to the new one. Is that correct so that it is “merge ready”, if there are no more conflicts? |
Right now there are hundreds of noisy changes in the PR so I would suggest to get back to square one. |
Alright, changed it to the original one, only added the advantages of the extension vector and the function that checks if the enumeration extension has to be enabled. |
This is still using C++ library std::vector instead of ImVector. |
vkEnumerateInstanceVersion(&vulkanVersion); | ||
if (VK_VERSION_MAJOR(vulkanVersion) >= 1 && VK_VERSION_MINOR(vulkanVersion) >= 3 && VK_VERSION_PATCH(vulkanVersion) >= 216) | ||
{ | ||
portabilitySubsetEnabled = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this check disabling portability subset? If the extension is available, it must be enabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see your point. Now that I'm looking over everything again, I see that it would probably be easier to create two functions. One that checks the flag for VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR
and one that checks if the VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME
is enabled. And of course both check if the OS is macOS and the Vulkan version is >= 1.3.216. Is this the best solution? Maybe you know a better one. I am always grateful for better ideas.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stop making unnecessary checks. What does the OS or driver version has to do with anything here? Read what the extension specification actually says, and follow that to the letter.
Alright, I will look over it again, and will try to terminate all the C++ stuff and will change it to the ImVec version. And will look at the function again. It may very well be that something is not be as it should. Sry for the troubles. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've only looked over the code from a legacy SDK standpoint, haven't tried building it or looked at what older SDKs define.
{ | ||
uint32_t vulkanVersion; | ||
vkEnumerateInstanceVersion(&vulkanVersion); | ||
if (VK_VERSION_MAJOR(vulkanVersion) >= 1 && VK_VERSION_MINOR(vulkanVersion) >= 3 && VK_VERSION_PATCH(vulkanVersion) >= 216) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test would fail for future major or minor version bumps such as 1.4.0 or 2.0.0 where the lesser version components reset to lower numbers.
|
||
for (const auto &extension : availableExtensions) | ||
{ | ||
if (strcmp(extension.extensionName, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are all these *_NAME
and *_BIT_KHR
names defined in all older Vulkan SDKs that we support, or do they need to be guarded by the preprocessor, conditionally defined by us, or use our own string literals and constants?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have to look it up, if all *_NAME
and *_BIT_KHR
are in older versions. I only looked at the newest version. Thanks for pointing this out.
So now I reduced everything to one function: bool is_instance_extension_enabled(const char *extension_name)
{
uint32_t extension_count = 0;
VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr);
if (result != VK_SUCCESS)
{
return false;
}
ImVector<VkExtensionProperties> extensions;
extensions.resize(extension_count);
result = vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.Data);
if (result != VK_SUCCESS)
{
return false;
}
for (int i = 0; i < extensions.Size; i++)
{
if (strcmp(extensions[i].extensionName, extension_name) == 0)
{
return true;
}
}
return false;
} It checks if an instance extension is enabled, and returns true, if so, and false, if not. #ifdef __APPLE__
if (is_instance_extension_enabled(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME))
create_info.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
#endif ImVector<const char*> extensions;
uint32_t extensions_count = 0;
const char** glfw_extensions = glfwGetRequiredInstanceExtensions(&extensions_count);
for (uint32_t i = 0; i < extensions_count; i++)
extensions.push_back(glfw_extensions[i]);
#ifdef __APPLE__
if (is_instance_extension_enabled(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME))
extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
#endif I haven't committed it yet, because I don't know if these solutions are any good. |
Easier to commit so we can review. |
Accidentally closed PR. New is open on #6172 Sry for the trouble |
Since VulkanSDK 1.3.216 it is mandatory to use the
VK_KHR_PORTABILITY_subset
extension. Fixed by addingaswell as adding
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME
andVK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME
to the extensions array.Issue: #6101
Note:
Maybe considure changing the extensions array to a vector, for better readability and for easier adding new extensions.