-
-
Notifications
You must be signed in to change notification settings - Fork 10.5k
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
Enable 4k/retina support (example_emscripten_wgpu) #7151
Conversation
Hello, |
Ok no problem. I will look into it. |
The demo is live Note that you must use Chrome as Firefox currently does not support webgpu (nothing to do with my changes). You need to use a 4k monitor to see the difference... |
After struggling for a while I was able to consolidate in a single html file
I have tested the following:
|
SDL3 + Emscripten is untested, i must have left a makefile to facilitate testing once it becomes avaialble but its probably not going to be soon. |
@ocornut I may have found a way to get rid of the |
Err its fine to put whatever we need in the HTML, and seems overkill to alter Emscripten. My request was that we avoid multiple HTML files unless there is a good reason for them to be different, and if they are different that we facilitate synching of them by reducing their diff. It’s also nice that our template HTML stays somehow aligned with common standards eg Emscripten owns default template. |
It's actually not a big problem to update emscripten. I already submitted the PR. I just realized that what SDL was doing was pretty clever and as a result they didn't need this extra It will also make the ImGui HTML template closer to the one in emscripten (since that one does not use the Now I would prefer to wait until the emscripten PR is merged/released to proceed with this one because it will be cleaner. Do you want me to close it and reopen one later? Or simply keep it open until then? |
We can keep open until a release happens. |
@ypujante I'm yet to fix my PR up to make this cleaner but when acquiring all the needed items I removed the js code that inits the instance adapter and device in the html and it still is happy. I have yet to remove it on the branch yet but tested it locally if you want to give it a go and test you can see the changes I have done here: Is there any issue you can foresee (maybe a browser I'll have to check) that calling all the init webgpu code from the cpp will cause ? |
@Zelif Thank you for participating in the discussion and providing your feedback. IMO, I think that you are correct that it would be desirable to have a single html file that is free of webgpu code entirely. To be honest I did try this approach but my "naive" implementation did not work. What I tried was to take the webgpu code from html and put it in int main(int, char**)
{
EM_ASM({
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
Module.preinitializedWebGPUDevice = device;
});
// .... But unfortunately that did not work due to This is why I reverted to putting it back in the html with conditional compilation. It sounds like you have found a way to make it work but it is just hard for me to see how exactly in the diff you pointed to (as a side note, I am not sure I understand why you have conditional compilation on So to answer your question, if it works in the cpp code, I don't think I can foresee an issue and I believe it to be cleaner overall. The less html/javascript code, the better. I suppose this PR can be merged first the way it is and then you can simply move the code to cpp? I am not sure what @ocornut would prefer. Finally, I can see that your PR is about multiviewport support. I am not sure if that can be of any help, but I am currently working on a brand new glfw emscripten port from the ground up. It is implemented in cpp and it supports natively multiple glfw windows (meaning you can call glfwCreateWindow multiple times, each "window" being associated to a different canvas). It is not released yet but wanted to put in on your radar if that can help. |
@ypujante The conditionals are in there as I am in the process of changing the example for webgpu to support both web and desktop there were not many changes but one of them resulted in getting the
Mainloop (1)#if defined(__EMSCRIPTEN__)
emscripten_set_main_loop_arg(MainLoopStep, window, 0, false);
#else
while (!glfwWindowShouldClose(window)) {
MainLoopStep(window);
wgpuSwapChainPresent(wgpu_swap_chain);
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
}
}
#endif Surface Creation (2)#if defined(__EMSCRIPTEN__)
wgpu::SurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
html_surface_desc.selector = "#canvas";
wgpu::SurfaceDescriptor surfaceDesc = {};
surfaceDesc.nextInChain = &html_surface_desc;
wgpu_surface = wgpu_instance.CreateSurface(&surfaceDesc);
#else
wgpu_surface = wgpu::glfw::CreateSurfaceForWindow(wgpu_instance, window);
#endif Async loading inside main.cpp (3)General idea is that we need to grab the instance, adapter and device async via callbacks: static void RequestDeviceCallback(WGPURequestDeviceStatus status, WGPUDevice cDevice, const char* message, void* userdata)
{
wgpu::Device device = wgpu::Device::Acquire(cDevice);
wgpuDeviceSetUncapturedErrorCallback(cDevice, print_wgpu_error, nullptr);
reinterpret_cast<void (*)(wgpu::Device)>(userdata)(device);
}
static void RequestAdapterCallback(WGPURequestAdapterStatus status, WGPUAdapter cAdapter, const char* message, void* userdata)
{
if (status != WGPURequestAdapterStatus_Success) {
exit(0);
}
wgpu::Adapter adapter = wgpu::Adapter::Acquire(cAdapter);
adapter.RequestDevice(nullptr, RequestDeviceCallback, userdata);
}
static void InitWGPU(void (*callback)(wgpu::Device))
{
wgpu_instance = wgpu::Instance::Acquire(wgpuCreateInstance(nullptr));
wgpu_instance.RequestAdapter(nullptr, RequestAdapterCallback, reinterpret_cast<void*>(callback));
}
InitWGPU([](wgpu::Device device) {
// Got device, adapter, instance
// continue with loading like normal
} I want to clean this up a bit to reduce the changes and harder to look at callback (am unsure how but that is something to look at later :D ). Hopefully it helps out, this does use the Edit: And yeah if you merge it in the way it is, that is fine I will revert when the multiviewport work is ready to be pushed out. Was interjecting for the most part as something I can remember to do and find easier. |
@Zelif Thank you for your explanation. I guess I am not familiar with webgpu in general, but I guess I don't understand what is webgpu for desktop. Isn't webgpu for the web by definition? I am just very curious. |
@ypujante Just unfortunately named :D This was me running both in web and desktop: |
I just released the wip project. Still a lot to do, but it's working (and with ImGui/example_emscripten_gpu no less) |
Hi @ocornut, Happy New year. I have reverted the PR that I had ongoing with emscripten because it introduced some side effects that I had not anticipated and there is no "quick" fix. As a result, this PR, in its current state, is in my opinion the right way to go for ImGui to add 4k support for the emscripten/glfw backend. I can see that there are currently no conflicts to merge this branch, but please let me know if you want me to merge the latest base branch to this PR before you move forward. Thank you |
Given that it has been a while and now there are conflicts for merging, I am closing this PR for now. I will have a better solution soon once my new project which has now reached 1.0 is integrated in emscripten. I will open a new PR at a later time. |
Hi @ocornut
Following the merge you did this morning for emscripten/glfw, I am pushing a new pull request to enable 4k/retina support in the
example_emscripten_wgpu
example.Background:
I am the author of the changes that got merged in emscripten/glfw recently to enable support for 4k/retina displays, thus making the rendering much higher quality. Here are the release notes (that I wrote) from emscripten 3.1.51:
As you can see from this pull request, the changes are very minimal. Also, because emscripten/glfw prior to version 3.1.51 was ignoring the glfw window hint
GLFW_SCALE_TO_MONITOR
, then having this hint present will not affect any user not using the latest version of 3.1.51In terms of result I took some screenshot so you can see a before/after comparison:
Low resolution:
High resolution:
As you can see it is particularly noticeable on everything that is drawn, like the checkboxes, the triangle to close/open the window or any shape in the custom rendering example.
In terms of changes:
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE)
canvas
with adiv
that is the one managing the width/height (glfw automatically forces the canvas to be 2x the size (frame buffer =>glfwGetFramebufferSize
) and uses css to render it at screen size (glfwGetWindowSize
) and use this div forImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback
.I am going to push a live example of this changes once this PR is created.