Open NHodgesVFX opened 2 years ago
Thanks for the kind words π
It would be cool with other backends and I have considered it, I even planned for it. However, I'm not sure how much benefit it will do right now compared to the amount of work (but please prove me wrong). Also, I'm not sure about WGPU as opposed to directly using WebGPU, Metal, Vulkan etc. but I will definitely consider it if it becomes relevant. However, first, I need to be convinced that another backend is worth the trouble π
So to explain my opinion, please keep in mind the purpose of three-d
which is to make it simple to draw stuff. This is great for visualisation, tools, simple games etc. but if you want to make a AAA game, you probably want to use something else. Also keep in mind that it should be possible to write your own shaders and combine high-level features with low-level graphics calls which complicates adding another backend.
GLOW uses OpenGL which is deprecated on Apple platforms
This is definitely a good argument for making a Metal backend, but OpenGL is still working, so not super urgent.
OpenGL, although still extremely relevant, is a previous gen technology.
OpenGL is, as you said, still relevant and still the most cross platform graphics API and on some platforms the standard graphics API. For me, that it's old, is not an argument that would make me do a lot of work.
GLOW uses OpenGL 3.3 (According to the readme of three-d) for its max spec which misses features which are used a lot today like compute shaders.
I specified 3.3 since that corresponds to webgl2 and I can therefore write the same code (almost). I'm curious to know what you want to use compute shaders for? Also, please keep in mind the purpose of three-d
.
GLOW will likely not support WebGPU, which will greatly expand the power of 3d on the web.
GLOW will definitely not support WebGPU. Again I'm curious as to what features you are missing? And again, think of the purpose of three-d
.
WGPU in theory may be faster then GLOW when using the Vulkan, DX12, Metal, and WebGPU back-ends
It's true that you can get a performance gain if using a modern graphics API, but I would always look at the code and hardware first. How much you gain will depend on the platform, some might give a significant speed-up (I'm guessing apple products). However, modern graphics APIs tend to be more complex and that complexity will either be reflected in three-d
, making it less simple to use, or some of the performance gain will be lost to keep it simple. And again, the purpose is not to cater for AAA game companies, so the small performance gain is not important compared to keeping the crate simple to use (that's not saying performance is not important, just that the graphics API is not the main source of performance problems).
I think there are some good points in support of wgpu.
one obvious issue is that its still not final and breaking changes every few months.
opengl is
create_buffer
being gen_buffer
on desktop which doesn't set the buffer state on creation, while webgl's create_buffer
does, while modern opengl 4.5 desktop has its own create_buffers
function which behaves similar to webgl's counterpart. https://stackoverflow.com/questions/31841494/difference-in-glgenbuffers-and-glcreatebuffers which might lead to about platform / hardware specific workarounds = more maintenance burden.I definitely think opengl backend should be the priority for now as wgpu is still unstable. but having wgpu backend is cool because
EDIT: I just found three-d looking for an 3D rendering crate. there's LOTS of 2d rendering libs in rust, but only rend3 or three-d for 3D rendering atm. my use case is just egui + few gltf scenes + a lot of billboards + lua scripting for plugins. for simple cases like draw rectangle and more complex but common cases like pbr gltf scenes, i would like to use a rendering crate (and allow lua plugins to use it too). but for specialized cases like billboards, and whether they need to be displayed or not, and generation of meshes, i would like to compute shaders or other features like draw_count_buffers / multi indirect drawing to improve performance. idk if three-d aims to support such use cases, but thought i should provide an example for the sake of this issue.
Thanks for the input @coderedart π
First of all, I hope that I got the right message across with the first reply; I definitely think it is a good idea with other backends. My sole concern is that it is a lot of work (all shaders has to be reimplemented for example) and that it will limit other development efforts, but it is difficult to know exactly how bad it is. Could be interesting to make a quick proof of concept though.
I didn't (and I still havenβt) looked much into WGPU, I just follow it at a distance, so nice with some insights. Could be really nice to have one API instead of implementing a lot of different backends, so it is quite attractive, but it sounds like it needs to be a bit more stable.
Compute shaders are definitely nice to have, but unfortunately they are not available everywhere yet, so Iβm unsure how I can support them without dropping support on some platforms or having specific behaviour for different platforms which wouldn't be nice from a user perspective. Also, I think you can draw millions of billboards with three-d
(if you haven't found it, billboards are Sprites
with None
as direction), if not more, before you get into performance problems, especially if you use deferred rendering. But maybe I misunderstood your use case. Generating meshes is a great use case but it is quite rare that it is not possible to create them offline on the cpu and upload them to the gpu (ie. the classic way) or alternatively on-demand in parallel on the cpu and then upload it (which is also quite fast). So, compute shaders are nice to have, not a blocking feature, as I see it π
At least for me the appeal of compute shaders and my use case for them is to be able to simulate large numbers of particles in real-time. I didn't realize glow actually supports compute shaders, if you were going to implement them I would just make it so they all have the same interface, that way the user doesn't need to figure out what function to call on what platform. If the user is on a platform / OpenGL version that doesn't support compute shaders then just panic like std does.
You could also have a toggle of some kind somewhere like Portable and Desktop then its up to the user to figure out which is better for their use case given a list of features each one supports.
Also as far as wgpu stability goes the bevy engine uses it and I haven't seen them having any major issues with it. Also wgpu does support GLSL shaders so you might not need to completely rewrite them.
btw, I'm not asking three-d to support compute shaders. three-d can stay simple (as it is right now), and only expose the current high/mid API abstracting over wgpu / openGL. but i would like to take that low level context rendering api to use compute shaders or other features based on my target hardware.
One reason I'm afraid of openGL is the driver issues and unsafety.
one really really convincing argument for three-d itself, regardless of my niche use case, is that wgpu is getting angle backend which allows it to run even on gles 2 or dx11 platforms (source: wgpu README).
if i use three-d (with wgpu) and find that some of my users using windows 11 have issues with vulkan drivers, i could just change a single line in my app and release a dx12 version until the drivers are fixed as a workaround or even gles with less performance workarounds. I can even just change the backend i use at program startup based on user configuration (MYAPP_DRIVER_BACKEND) and ask them to test if some bug is happening with other backends too. its way too convenient :)
I cannot use sprites for now. I'm making a overlay application, which just shows stuff "over" the game (Guild Wars 2) with a transparent window with mouse passthrough. so, i must keep my resource usage as low as possible to not compete with the game itself. very very niche case :D and i also don't want to lose in performance benchmarks with other competing similar non-rust Overlays.
I think both of you have valid points π
This is of course not just a discussion about compute shaders, but I think it is a good example of a feature that could be added at some point in the future to three-d
and hopefully it's possible to disable the feature compile time on the platforms where it is not supported (I already do that with a few features). However, as noted, newer OpenGL versions also supports compute shaders, so you could take advantage of the possibility to combine low-level graphics calls with high-level three-d
features and basically do the compute shader part "manually" using OpenGL and three-d
for the rest. That means compute shaders are already supported, though not really in a nice way and maybe not on all platforms which was possible if using another backend.
That leads os to the points about OpenGL unsafety and so on, which are very valid indeed. One of the points of using a library like three-d
is of course to avoid all of the problems that OpenGL (or other graphics APIs) can cause. However, if you combine three-d
features with direct OpenGL calls, then you still have to fight with OpenGL errors in the low-level part of the code. I'm not sure how much better I think other graphics API's are, but if using WGPU
then it sounds like it's would be a better experience.
Driver bugs is also a valid point, I'm don't have a windows computer, so I don't know how bad it is. And yeah apple support is also a valid point as I also said earlier. However, these things tend to move very slowly (I predict that WebGPU is not supported on all major browsers before at least 5 years, and probably 10 π ).
WGPU
sounds really fantastic from a developer point of view, but as someone that has been hoping for some universal graphics API for ages, I reserve the right to be a bit sceptical π I'm mostly concerned that there are some differences between the API's that cannot be properly aligned, but as three-d
should be simple and therefore use standard drawing features of the graphics API, that might not be a problem. Anyway, I think it's definitely worth the try. If anyone wants to make a WGPU
backend, please just write on this issue π Otherwise, I will look at it at some point.
And @coderedart, your use case sounds super nice, please share screenshots or something, if you'd like. And it might be super niche, but I think it is a quite typical that you want to use three-d
for the "standard" drawing stuff and then make a custom low-level implementation for the very specific thing that makes your application unique. Maybe you can also consider using mid-level features in the core
module, they should not introduce any overhead π
@asny I will also add to discussion. WebGPU is new, it removed a lot of mistakes from previous graphics api interfaces. It provide easier interface and scalability than OpeGL, my boss which is senior OpenGL engineer is saying he never want to go back to OpenGL :D :D, But in future WebGPU will provide access to Vulkan/Metal/DirectX core via browser, so for us who develop Web3D content for industry it will be gamechanger and we can create bigger and better looking applications :)
And basically, when WebGPU will be supported across browsers, you can remove all your opengl code, there will be no backend, there will be only webgpu , which will cover opengl,vulkan,metal for your :)
@erikpa1 This is a discussion is about using WGPU, the Rust crate, not WebGPU the graphics API π
@asny wgpu is rust crate which implements webgpu standard :) so I think thats the same,...
if i wanted to add wgpu backend to three-d, where would i start? start porting the shaders and mid-level api?
I just realized that three-d
uses custom windowing code for web, is there a reason not to use winit?
if i wanted to add wgpu backend to three-d, where would i start? start porting the shaders and mid-level api?
That's a good question. This may be obvious but it should just be to change the context in the context
module from glow
to wgpu
(switch between the two with a feature flag?) and use wgpu
everywhere that currently use glow
low-level functionality (again switch with the same feature flag) which primarily is in the core
module. It seems like wgpu
supports glsl shaders (with the glsl
feature flag enabled), so no need to port the shaders yet.
This was the very naive description of the task, in practice it is probably not that easy to switch since glow
and wgpu
functionality is not equal. However, to figure out the problems exactly, one just have to try it out, I think. So aiming at getting the triangle
example running would be a good start. In the process, when you encounter problems that has no obvious solution, let me know, and we can maybe figure it out together π I'll try to be quick to respond π€ How does that sound?
I just realized that three-d uses custom windowing code for web, is there a reason not to use winit?
Well, I'm pretty sure winit
didn't support web when I started using it (at least I found out recently that it had), so that is the reason. So I guess that is a task as well, to replace the canvas code with winit π
understood, i will start by first porting to winit, which is useful regardless of the wgpu stuff.
not urgent, but one thing that will need consideration for high level APIs is that wgpu can be multi-threaded, so for example, you could setup a rendergraph first and execute it later in a background thread like pipelined rendering.
Sounds great π
Good point. For the record, I think we should avoid multi threading right now to not complicate things further, but I guess that is also what you are saying. However, I guess the solution is also relevant with respect to the immediate mode of OpenGL and command queue of wgpu
. I guess we need to accumulate the commands in a command queue for wgpu
and then apply it when we render? Or maybe at the end of the frame? Right now, uniforms, buffers, textures etc are updated right away when something change.
porting to winit was pretty easy.
but I give up on adding wgpu to three-d. It is very much possible to do so, but first, rewriting it from scratch seems to be much simpler and easier than patching the existing code. and second, i also don't have enough rendering knowledge to pull it off.
Program
object with a PipeLine
object. naga event provides a proper way to add defines . Though, i am honestly afraid of touching this as my shader skills are garbage (I have no idea about how bindings groups / locations are assigned to uniforms and attributes if they are not provided in layout explicitly. ). Ofcourse, if someone else feels different, then they are welcome to try. that's why i mentioned naga and shader reflection so that the next person knows where to start.
but I give up on adding wgpu to three-d. It is very much possible to do so, but first, rewriting it from scratch seems to be much simpler and easier than patching the existing code. and second, i also don't have enough rendering knowledge to pull it off.
I totally understand, I tried to warn you that this was no small endeavour π I'm not sure I agree about rewriting from scratch now that I know how much effort that takes, but you are right that three-d
was specifically designed with OpenGL/WebGL in mind. That said, the core rendering concepts (Buffer, Texture, program aka RenderPipeline) are the same no matter the graphics API and since three-d
aim for doing the standard rendering easy (and not the 10% special cases) three-d
would use very limited subset of wgpu
and make no attempt to support anything fancy (but still make it possible to do yourself, giving access to the low-level context). Therefore, it should be doable to add support for wgpu
without having to do a lot of major changes to the API. However, it might be needed to do some workarounds especially since OpenGL/WebGL and wgpu
behaves fundamentally differently with respect to sending commands to the GPU. But again, I think it is doable but requires a lot of effort.
About the shaders, if it is not easy to do automatic conversion using Naga (I would just do it offline and have both copies of the shader in the source) they could be written again. Shouldn't be a big problem to do, it again just requires effort, and of course multiple shaders needs to be kept in sync.
Finally, i don't think patching this crate instead of rewriting is worth the effort. this will definitely take a few days of work to complete. during that time, we can probably have a new crate from scratch with much cleaner API and less effort.
I'll dare you to do it π
Based on the above conversation I wonder if their would be a reason to keep Glow and not just have wgpu as the only backend. Wgpu supports opengl es, webgl2 and angle which should cover older computers and web(until webgpu is prevalent).
Yeah that might be a good approach but i would prefer that both live alongside each other in the beginning if it's at all possible. Again the overall structure of three-d
should stay the same since the concepts are the same so should be doable to switch between the two contexts. The main advantage to only use wgpu
as I see it is that we don't have to duplicate shaders, which is also a significant advantage π and of course I might also be wrong in my analysis π I want to give it a go at some point but I also really like to do something fun as the next task so I'm not sure when that will be.
Based on the above conversation I wonder if their would be a reason to keep Glow and not just have wgpu as the only backend. Wgpu supports opengl es, webgl2 and angle which should cover older computers and web(until webgpu is prevalent).
One reason is because wgpu currently has issues with hybrid graphics on Linux. Particularly if the dpgu is Nvidia based, and it seems related to wayland (xorg is unmaintained tech now). If wgpu were to be used it would have to closely follow upstream. You can see some of what I've experienced here
It would be cool to have a WGPU backed for a couple of reasons
There is another framework https://github.com/BVE-Reborn/rend3 that is similar to this one that uses WGPU as its back-end but it is a lot more verbose compared to this library.
Thanks for offering a really cool and simple to get started 3D Library in rust :)