mewgpu 3.7.2

Maybe Easier Wgpu (mew), a thin abstraction over wgpu's chaos
Maybe Easier _Wgpu_ (mew), a thin (?) abstraction to hopefully help organize
your 3 buffers, 20 bind groups, 13 vertex formats, and 7 pipelines.  
~~No other combination is allowed.~~

[_wgpu_](https://lib.rs/wgpu) is a ~~1~~ 0.98:1 API for the WebGPU standard.
While that makes it very portable, versatile, and well-documented, since I'm not
a hardcore graphics chud, I don't find it very intuitive to use.

My main problem with it is how many bloody times you need to define the same
thing, and quadruple-check that all the layouts line up with each other: first
the `BindGroupLayoutDescriptor`, which turns into a `BindGroupLayout`, which is
then used in a `PipelineLayoutDescriptor` by putting it into a
`BindGroupLayoutEntry`...  
Wait, crap, I think I forgot a struct somewhere along the line.


## The point of this

This library aims to, at least a little bit, make it easier to define all the
related information in one place (in wrapper structs).
It primarily uses like 20 `macro_rules!` to write boilerplate that generates
buffer, bind group, and pipeline layouts. It also stores them in a convenient
"render context" struct.

My original goal _wasn't_ to simplify the _wgpu_ API, rather just to follow a
programming pattern I used, but with the amount of boilerplate this let me cut
down on, it did kind of end up as a "simplification wrapper". However, it still
should be possible to lobotomize my code and mix-and-match your own custom
handlers, so you can do the same funky lower-level stuff as you could if you use
_wgpu_ directly.

(It eventually mutated and grew a couple helper structs, see below.)


## Not the point of this

As I mentioned, this isn't supposed to dumb down the _wgpu_ API, but rather make
it easier to define everything. Some bits & bobs are default-disabled like
multisampling pipelines or depth buffers are always in `Less` mode, but I may
make an update some day to support changing these. In the meantime, well, it's
open source, go ham.

This library is for people who have already used _wgpu_ at least once and like
the control it gives, so if you're brand-new to graphics programming, this
likely isn't the super-simple graphics toolkit you're looking for.

~~I should also point out, this doesn't handle making windows. You can use
[_winit_](https://lib.rs/winit) for that, its API is actually quite usable
directly, especially compared to _wgpu_. The example highlights integrating
this and _winit_ in practice, because, well, what else would an example do if
not drawing to the screen?~~
**Update:** Not that long after, I made a smol helper struct that bundled a
_winit_ window with a _wgpu_ surface and managed construction, which I found
really helpful to cut down on boilerplate.  
Not long after that, I tried dealing with WebGL and realized I had to interleave
context creation with window creation... _WHAT_ the **FU-**  
Anyway, I made another helper struct to deal with that anti-pattern too. It
took a bit of mental gymnastics to figure out what needed to happen, but I hope
my API is idiot-proof enough to keep myself from breaking everything, at least.  
_(Laughs in refactoring an already half-completed project)_


## ~~public static~~ Final note

Because I'm not a graphics programming chud (my only "graphical" programming
experience prior to _wgpu_ is Processing, ShaderToy, a 3D wireframe demo in the
terminal, raycasting in a 2D grid world, and 5 minutes of Bevy), _I don't know
the normal way to do proper graphics._ All my knowledge of _wgpu_ came from the
docs, experimentation, and [this tutorial](https://sotrh.github.io/learn-wgpu/),
which is really handy though ever-so-slightly (very) outdated.

You'll also need to excuse my weird code, using both really verbose traits in
combination with oversized macros where traits would be too painful (trust me, I
tried). I use lots of type wrappers and generics to (maybe) make it easier to
integrate your own types if you need any functionality that I missed.


## Usage

TL;DR all those pesky layout descriptors you need to keep track of are
generated & stored in a central "context" object, and then fetched when needed.
The context also holds the adapter & device, handles creating buffers &
pipelines for you, etc., caching everything in a type map.

To get started, you need to define all the shader structs/types, buffers,
samplers, textures, bind groups, and pipelines - put simply, anything that
needs a `...Descriptor` struct to create (excluding render passes, though that
might come in a future update if I think I came up with a good abstraction).  
The key point is that all related descriptors for an object are stored in, or
can be generated by, its _mew_ wrapper type.

```rust
mew! {
    // Vertex type, with an optional step of Vertex or Instance.
    vertex_struct ExampleVertexStruct step Vertex [
        0 ints => Uint16x2,
        1 norms => Snorm8x4,
        2 floats => Float32x3,
    ];

    // Vertex buffer, sized by its "type" parameter <ExampleVertexStruct>.
    buffer VertexBuffer <ExampleVertexStruct> as VERTEX | COPY_DST;

    // Regular shader struct. Note how you need to manually number fields.
    shader_struct ExampleShaderStruct [
        0 int => I32,
        1 mat => Mat4x4f,
        2 float => F32,
    ];

    // Shader struct buffer, same deal as VertexBuffer.
    buffer ShaderBuffer <ExampleShaderStruct> as STORAGE | COPY_DST;

    // Sampler with a mode, optionally setting other properties beyond the default.
    sampler Sampler as Filtering {
        mag_filter: Nearest,
    };

    // Texture with various properties
    texture Texture {
        usage: TEXTURE_BINDING | COPY_DST,
        dimension: D2,
        sample_type: FLOAT,
    };

    // Putting it all together in a bindgroup. Buffers are taken ownership of by
    // bind group objects when they are created, but they are reference-counted by
    // wgpu internally, so go nuts cloning them.
    bind_group ExampleBindGroup [
        0 sampler @ FRAGMENT => Sampler,
        1 texture @ FRAGMENT => Texture,
        2 buffer @ FRAGMENT | VERTEX => ShaderBuffer,
    ];

    // Putting everything you've put together, together.
    pipeline ExamplePipeline {
        bind_groups: [
            0 => ExampleBindGroup,
        ],
        vertex_types: [
            0 => ExampleVertexStruct,
        ],
        fragment_targets: [
            0 => ALPHA_BLENDING ALL as ANY,
        ],
        immediate_size: 4,
        depth: Depth32Float,
        cull: Back,
    };
}
```

Next we initialize a [`RenderContext`], either with the builder model or with
a straight `new()`, and we're basically ready to go.  
To create a buffer, call [`RenderContext::new_buffer`], with the desired length
of the buffer. The only reason we need to define the "type parameter" in the
buffer definition is because normally, buffer creations are measured by bytes.
Specifying a type will work like a `Vec`, big enough to fit some number of full
types.  
To create a bind group, call [`RenderContext::new_bind_group`], passing in a
_tuple_ of the inner bind groups. The bind group will take ownership but you can
access each buffer/texture later.  
Same goes for creating a pipeline, except [`RenderContext::new_pipeline`] takes
a few more arguments about the target surface and shader.

And that's the biggest pain point of _wgpu_ done for you, no more wrangling with
trying to keep 30 type definitions in line with each other. The rest of the
job is left to you, writing to the buffers and using the bind groups is
basically the same as vanilla _wgpu_ (do keep an eye out on derefs though,
they're a bit special - see the examples).


## Caveats

- Uniform buffers are weird. Put all data in a matrix and hope for the best.
  I managed to correctly pad regular storage buffers though.
- You can't change some default values, like mipmap size. Probably coming in a
  future version.

## Problem?

~~It's open source, fix it yourself fatass.~~

Shoot me an email at
[64\_Tesseract@protonmail.com](mailto:64_Tesseract@protonmail.com),
I'll maybe respond. I can't stand github & I'm definitely not uploading my code
to microslop, so my issue tracker is email.

## Features

### `wgpu-30`

**Default**  
Uses _wgpu_ ^30.0, the latest at time of writing. Exported as just `wgpu`.  
Not compatible with `wgpu-29`.

### `wgpu-29`

Uses _wgpu_ ^29.0 rather than 30.0. You probably don't need to enable this
unless you're stuck with another library that only uses 29.0. Exported as just
`wgpu`.  
Not compatible with `wgpu-30`.

### `android`

Proxies feature `android-native-activity` in _winit_. Does nothing in the crate
itself.

### `winit`

**Default**  
Enables _winit_ as a public dependency and provides some handy utilities under
[`winitutils`].

### `sync`

`RenderContext` uses `Arc`s instead of `RefCell`s, potentially slowing it down
but allowing it to be shared across threads. Only needed in very specific
situations, your rendering should probably all be done in one thread.