-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
Vulkan: switching between images for rendering #914
Conversation
non-dispatchable handles (like the vkDescriptorSet) are 64 bit handles. So on 32bit this will create issues. |
TextureId appears to be the size of a pointer, so should work |
This is what I was afraid of. It is not apparent for me how to best solve this. We could shove the VkDescriptorSets in an array and hand out indices (+ an indirection to allow deletion). Or the user could be responsible for management: Put a dynamic array field in the init struct containing the VkDescriptorSets and then ImTextureID is the index into this array. User is responsible for putting the VkDescriptorSets in this array and keeping the ImTextureIDs up to date. Also there is some difficulty of freeing the DescriptorSets (which I didn't touch in this PR). Maybe the DescriptorPool should be internal, so we can use VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT to free individual Sets, otherwise it will be more difficult to recreate the ones still needed.. Any ideas? |
Are many people going to use Vulkan in 32-bits? I could add a |
I think redefining the ImTextureID as unsigned long long (or redefining behind an ifndef if someone wants both Vulkan and 32 bits) would do the trick. As for the first question, I have no idea. |
Question to @martty, @ratchetfreak @SaschaWillems @ParticlePeter and other Vulkan users: Would it perhaps make more sense (and solve this issue) to make I'm asking because I don't really know the typical lifetime of a |
Not sure about this. A descriptor set contains information beyond what the actual image/texture is about. Having So IMO I'd prefer the current way with the |
OK, so there are two topics now here. :) Initially Martty suggested VkDescriptorSet and the problem we have at the moment is that
Now you are suggesting to use I'd be happy if you Vulkan users can have that discussion, would be super helpful as I'm not using Vulkan myself yet. |
I was really trying to make this change as non-intrusive and user friendly as possible. For users wanting slightly more control can simply make their own I'm not sure why putting the |
Wouldn't the user already have VkDescriptorSet instances they can just point too? |
Currently, I made the Otherwise, the user can use any pointer to |
I went with something similar to @martty 's solution, because one needs to bind an image and sampler to the descriptor set to pass to the cmd within ImGui, and the only ways I thought of to do it, that worked, are to either to do it persistently and pass a descriptor around via the TextureId, or to recreate the descriptor sets on the fly on demand inside of ImGui. I think I understand @SaschaWillems' concern, but it's hard to imagine how to keep ImTexture referring only to a VkImage. My solution was to provide ImGui with a VkImage, and for ImGui to hand me back an ImTexture which is backed by an object that has got the descriptor in it, so that ImGui can manage the sampler and descriptor set persistently on its own. I don't have any expectation that I can unpack the ImTexture and magically use it outside of ImGui. |
@mua Would you mind posting what you did for comparison with other solutions? It would be great if we could get consensus on a solution and merge it. |
@meshula I did not want ImGui to persist any resources, I just put descriptor set handle into ImTextureID just like @martty did, bind it in ImGui_ImplVulkan_RenderDrawData. And add a lazy generator for descriptor set on my texture objects. just a method returns guiDescriptorSet if not allocated previously, using the same descriptor set layout as ImGui. So I can tie lifetime of descriptor set to my texture, buffer, image, sampler etc. |
I merged this PR into my own binding (loosely based on the SDL/Vulkan binding). I automatically create the imgui descriptor set (using the ImGui_ImplGlfwVulkan_AddTexture function from the PR) for every texture that I load into my engine because I use imgui to browse the list of all loaded textures anyway. |
Hi, I found the following comment in imgui_impl_vulkan.cpp which led me to this post, however there doesnt seem to be a solution explained in this post for newbies yet. Is there an interim solution I can use before this is fixed in v1.65? (Will it be fixed in 1.65? =x) |
Finally merged. Here's what I did:
The later commit makes example build files compile with #if UINTPTR_MAX == 0xffffffff
if (sizeof(ImTextureID) < sizeof(ImU64))
{
// We don't support texture switches if ImTextureID hasn't been redefined to be 64-bit. Do a flaky check that other textures haven't been used.
IM_ASSERT(pcmd->TextureId == (ImTextureID)bd->FontDescriptorSet);
desc_set[0] = bd->FontDescriptorSet;
}
#endif The backend will compile on 32-bits platform without a imconfig directives, but support for that will then be disabled at runtime with an assertion to detect other uses (which is unperfect but should catch most). The small niggle with doing this is that to allow for the check to be done, As mentioned countless times, it appears there's no consensus on how to do things right. so this might change. I would still really like people to chime in and provide a lengthy explanation of what could be done. I believe runtime override of texture binding like #2697 is probably the way to go. Thanks @martty and everyone for your patience. |
Thanks everybody for this. Is it possible to get an example of how to use the Vulkan ImTextureID included on the wiki page https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples? |
A similar descriptor set approach was taken, after a bit of erring, in imgui-rs-vulkan-renderer. PS : please overlook Lenna, will submit a PR someday... |
Drawing a bunch of images this way can kneecap performance, since each draw will be wrapped in a descset switch. dear-imgui can have a image descriptor array instead and pass texture IDs in push constants.
Backend would reserve some |
Good point! @dpwiz Put all textures in an array, then just get the specific texture by index without rebinding, which can improve performance. But the implementation could be a little complex. Suppose we need to change textures frequently( sometimes, we just don't know all textures will be used or maybe it will take too many memory to load all textures), then we'll need a way to update the texture array, which might cause the texture index changed for a specific texture. A possible solution here (Just add an indirect layer):
|
You can treat the texture array as a pool for some texture id slots. Nothing to reinvent here. Allocate a bunch of "slots", fill in with all the initially known ImageViews (fonts, etc.), add remaining to a free list. Adding a texture would mean picking one slot from the free list and writing a new ImageView to its array index. Evicting a texture is simply returning its index to the free list. Let the texture owner manage its resources. Also, using image views means you can update the data without updating the descriptor. If you really need to shuttle new image data without blocking to rebuild the descriptor array, just copy your data to the image you've already registered. |
Someone maybe know when will this be documented in here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples ? It would be really helpfull. |
Just like using some tech like descriptor indexing to get a unbound descriptor set, and it's easy to update this set async safe, i think it is a good idea for imgui texture binding. |
Although likely to be a bit bulky, it would be nice if someone could add an example for loading textures in Vulkan in this Wiki page: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples |
Hey there, I'm reading through this and the vulkan backend code, this question probably has a super obvious answer but, here goes: I see calls to vkAllocateDescriptorSets, and I get they are allocated from pools. Do I need to worry about descriptor sets reaching some maximum? |
As @ocornut, @rolandhill, and @Chomiczjakub asked, I have added an example to the above page for Vulkan after struggling with this for a while. I am far from a Vulkan/ImGui expert, so if someone would be willing to look it over for any egregious errors/malpractice I would appreciate it. If anyone wants to test it out, that would be great too! I made some assumptions for the sake of "brevity":
|
Thanks to @DangitBen for taking the effort. I definitely thought about writing up such an example, but Vulkan is just too bulky. In my opinion it wasn't possible to write something self-contained without falling into the same pitfall that every other tutorial on vulkan out there has fallen into: you can't use their code without being severely limited - even making grave mistakes in terms of real-life code (ie, baking into the example a 1:1 relationship between two objects that doesn't exist). A beginner, when using such code as a base for their own code almost MUST run into serious problems later on when they try to do something that is more real-life, more practical (e.g. try to write an actual game). For example, I could not use my own code to show how to upload a texture to the GPU - because that is useless without using my vulkan engine. And it is not possible to rip out those parts of the engine that are being used and include them in the example-- vulkan is just too darn complex. PS Here is code that I use to upload a texture:
|
Today added @DangitBen Thanks for a lot for this addition to the tutorial. I confirmed it works on my side, but realized using Do you think you or someone) could refactor this? (1) Bundling all data into a structure e.g.
Aptly named this way to emphasis this is an example and likely not a base for more advanced stuff, but I'm also sure some casual users will be happy using this as it so it is nice if it's usable as it. (2) Adding a Aim being that example should be able to exit without any report from debug layer. |
Yeah I did call this out in my comment above, but not in such specific language.
@ocornut done! While I am not certain about what the lifetime of the objects should be, the validation layers seem to be silent and happy now. |
@DangitBen Thank you for updating the wiki! |
Hi, instead of the |
As described previously, I implemented ImTextureID with a VkDescriptorSet.