Greetings!
I've been developing with wgpu-rs to do both 2D and 3D graphics and been having a blast :) I'll admit that my learning curve has been fairly steep; a lot of blankly staring at code. But I think I'm starting to get the hang of it. So far your examples have been my only real guide, and I'm very grateful for them. They've been super helpful.
I have quite a few questions about how best to go about things. If this is not the right place to ask these questions, please direct me to a better spot.
As I'm working through the examples and ramping up the number and complexity of objects I'm drawing on the screen, I'm wondering:
I also have some higher level questions:
If, based on my questions, I'm missing the point of basic concepts (quite possible), please feel free to correct me. I'd rather look dumb today than be dumb tomorrow.
As I've mentioned before, I think you guys are doing a fantastic job! I appreciate everything you've done so far. Please keep up the good work :)
If I have 1,000 objects on the screen, and they only differ by some minor information, is it better to have 1,000 pipelines whose buffers don't change between renders, or have 1 pipeline and update the pipeline's buffer per object render?
If the objects are all drawn the same way (i.e., they use the same shader pipeline), then you'll only need one pipeline. You can also avoid having to change vertex buffers by putting all vertex data for a pipeline in the same buffer or a small number of buffers.
Is there a significant performance penalty in updating buffers every render? Am I worrying about premature optimization?
Data that need updating every frame are usually passed as shader resources. If you only need a small number of values to be updated, you can pass these to the shader directly. Updating large buffers is slow (relatively speaking) and typically something you want to avoid doing every frame.
Is there a way to treat a texture as a buffer? It seems you have to bake the texture into the pipeline never to be changed. Is that correct? If 1,000 objects on the screen were identical except for the texture (aka a thumbnail sheet), does that imply 1,000 pipelines?
The data that is baked into the pipeline describes the kind(s) of texture that may be bound to the pipeline, but nothing about the actual data of a particular texture. So if all 1,000 of your objects use the same shaders, and have the same texture format, you only need one pipeline.
If I want to use a different shader between renders, I need to create a new pipeline, correct? I believe pipelines are intended to be immutable but allow updating buffer info. Let me know if I'm wrong.
Yes, different shader sets require different pipelines. When setting up a pipeline, you are essentially telling the GPU what kind of data to expect, and what to do with that data, but the actual data you pass it can vary.
If data is the same across pipelines (such as a transformation matrix), is it possible to put that information into a single buffer and have the pipelines reference that central buffer? With Rust, I'm not sure how I would go about that due to the memory sharing restrictions, or whether its a good idea. But I was wondering and thought I'd ask.
Yes, you can share a central resource between pipelines.
I believe the buffer in Rust code is simply a pointer to memory on the GPU (or memory physically near the GPU). Is my understanding correct? If so, does the buffer know to release the memory if it goes out of scope? Do I need to do anything specifically? I may be totally misunderstanding the role of buffers here, so forgive me if this is a stupid question.
wgpu automatically handles buffer memory, so you don't need to worry about allocating or freeing memory to go with buffers. Your understanding is generally correct as far as the API is concerned -- there are some performance things to keep in mind, and hopefully the docs will be clearer on that soon.
Has WebGPU become official? Am I working with a real representation of the API, or just Apple's Metal-ish recommendation?
The spec hasn't been finalized, but you can keep an eye on the process at the github repo and look at the current revision of the spec here.
Are there any resources I should be aware of to learn WebGPU better?
This is still a work in progress, and there are some basic docs coming up in the next release (if you clone the current master branch, you can build them with cargo doc). Apart from that, there aren't too many resources about WebGPU available simply because it's not standard yet.
Thank you for the answer, @cormac-obrien !
It feels to me that the basic misunderstanding @dmilford has is about the binding model. I'll try to describe it in short:
PipelineLayout object by describing which resources go into which groups/indices. It has to be compatible with (by being a superset of) shader requirements.RenderPipeline object that defines what the shader is, how it gets the data in (vertex attributes, primitive topology, pipeline layout) and how it writes the data out (render target formats, blending, depth-stencil states).BindGroup objects for quick binding (with set_bind_group).For example, if you have 1000 objects that share most of the inputs except for a texture, you'd want something like this:
draw() callPlease let us know if something is unclear.
Thank you both for your detailed and clear responses! That really clears things up. I truly appreciate it.
Most helpful comment
If the objects are all drawn the same way (i.e., they use the same shader pipeline), then you'll only need one pipeline. You can also avoid having to change vertex buffers by putting all vertex data for a pipeline in the same buffer or a small number of buffers.
Data that need updating every frame are usually passed as shader resources. If you only need a small number of values to be updated, you can pass these to the shader directly. Updating large buffers is slow (relatively speaking) and typically something you want to avoid doing every frame.
The data that is baked into the pipeline describes the kind(s) of texture that may be bound to the pipeline, but nothing about the actual data of a particular texture. So if all 1,000 of your objects use the same shaders, and have the same texture format, you only need one pipeline.
Yes, different shader sets require different pipelines. When setting up a pipeline, you are essentially telling the GPU what kind of data to expect, and what to do with that data, but the actual data you pass it can vary.
Yes, you can share a central resource between pipelines.
wgpuautomatically handles buffer memory, so you don't need to worry about allocating or freeing memory to go with buffers. Your understanding is generally correct as far as the API is concerned -- there are some performance things to keep in mind, and hopefully the docs will be clearer on that soon.The spec hasn't been finalized, but you can keep an eye on the process at the github repo and look at the current revision of the spec here.
This is still a work in progress, and there are some basic docs coming up in the next release (if you clone the current
masterbranch, you can build them withcargo doc). Apart from that, there aren't too many resources about WebGPU available simply because it's not standard yet.