Skip to content

Commit

Permalink
Readme changes; slight example cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
PyryM committed Jan 19, 2024
1 parent c5e8424 commit 5150d07
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 22 deletions.
57 changes: 43 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# xgpu

`xgpu` is a Python 3.7+ binding of [webgpu-native](https://github.com/gfx-rs/wgpu-native) which is auto-generated at build-time and tracks the upstream releases as closely as possible. It is currently in beta, and until it is more mature most users should probably use [wgpu-py](https://github.com/pygfx/wgpu-py).
`xgpu` is an agressively typed, red-squiggle-free Python binding
of [wgpu-native](https://github.com/gfx-rs/wgpu-native), autogenerated from
the C headers to always track the latest upstream release.

Not 'production ready'.

### Install

Expand All @@ -9,16 +13,30 @@ Wheels are built for Mac (x86 only), Windows, and Linux for Python 3.7+:
pip install xgpu
```

### Conventions
### Motivation

The motivation for this project compared to the other, currently-existing,
semi-mature wgpu_native binding [wgpu-py](https://github.com/pygfx/wgpu-py)
is very simple: I would like to enable typechecking and not get red squiggles
everywhere. Also, I would like the Python bindings to update as soon as possible
after upstream wgpu_native has a new release. `xgpu` addresses the first by
being fully type-hinted and red-squiggle-free, and the second by being
automatically generated from the raw upstream C headers.

`xgpu` is a mostly 1-to-1 binding of `webgpu.h` and `wgpu.h` from `wgpu_native`.
### Conventions/Philosophy

`xgpu` is a mostly 1-to-1 binding of `webgpu.h` (+`wgpu.h` from `wgpu_native`).

#### General name conventions

`xgpu` largely tries to maintain the names from `webgpu.h` rather than localizing
them into Python's conventions.

* Names keep their formatting from `webgpu.h` but lose `WGPU` prefixes: `WGPUTextureSampleType` -> `TextureSampleType`
* Field names, functions, etc. maintain same camel-case: `WGPUAdapterProperties.vendorName` -> `AdapterProperties.vendorName`
* Enum variants lose prefix: `WGPUTextureUsage_CopySrc` -> `TextureUsage.CopySrc`
- Names invalid in Python are prefixed with "_": `WGPUBufferUsage_None` -> `BufferUsage._None`
* Fields: `WGPUAdapterProperties.vendorName` -> `AdapterProperties.vendorName`
* Member functions: `wgpuDeviceHasFeature` -> `Device.hasFeature`
* Enum values: `WGPUTextureUsage_CopySrc` -> `TextureUsage.CopySrc`
- Names invalid in Python are prefixed with "_": `WGPUBufferUsage_None` -> `BufferUsage._None`, `WGPUTextureDimension_2D` -> `TextureDimension._2D`

#### Struct constructors

Expand All @@ -35,7 +53,7 @@ extents.height = 100
extents.depthOrArrayLayers = 1
```

#### "Member" function calls
#### Member functions

As a C API, `webgpu.h` follows typical C convention for member functions, which is to define
them like:
Expand All @@ -47,11 +65,11 @@ uint32_t wgpuTextureGetHeight(WGPUTexture texture)
In `xgpu` these become genuine member functions, e.g.,
```python
class TextureView:
class Texture:
def getHeight(self) -> int
```

#### Array passing conventions
#### Array arguments / fields

Some `webgpu.h` functions and structs take arrays using the convention of passing first
the array item count, and then the array pointer, e.g.,
Expand All @@ -77,7 +95,7 @@ def pipelineLayoutDescriptor(*, bindGroupLayouts: List["BindGroupLayout"])

#### Enums and Flags

Enums are translated into `IntEnum`s and inherit all their conveniences:
Enums are translated into `IntEnum`s:

```python
mode = xgpu.AddressMode.MirrorRepeat
Expand Down Expand Up @@ -117,8 +135,7 @@ Callbacks must be explicitly wrapped in the appropriate callback type:

```python
def my_adapter_cb(status: xgpu.RequestAdapterStatus, gotten: xgpu.Adapter, msg: str):
print("Got adapter with msg:", msg, ", status:", status.name)
adapter[0] = gotten
print(f"Got adapter with msg:'{msg}', status: {status.name}")

cb = xgpu.RequestAdapterCallback(my_adapter_cb)
```
Expand Down Expand Up @@ -167,6 +184,18 @@ my_array = np.ones(100, dtype=np.float32)
wrapped = xgpu.DataPtr.wrap(my_array)
```

### Codegen
### Codegen/Local Build

The code generation was written in Typescript and runs in `bun`. Python users shouldn’t have to touch this.
You will need [bun](https://bun.sh/) to run the codegen. Deno *might*
work but just go ahead and install bun. You will also need to have
ruff and cffi installed in python (`pip install ruff cffi`).

Then:
```
python codegen/fetch_wgpu_bins.py
bun codegen/generate.ts
cd xgpu
python _build_ext.py
cd ..
pip install .
```
9 changes: 3 additions & 6 deletions examples/triangle_offscreen.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,7 @@ def _main(device: xg.Device):
layout = device.createPipelineLayout(bindGroupLayouts=[])

color_tex = device.createTexture(
usage=xg.TextureUsageFlags(
[xg.TextureUsage.RenderAttachment, xg.TextureUsage.CopySrc]
),
usage=xg.TextureUsage.RenderAttachment | xg.TextureUsage.CopySrc,
size=xg.extent3D(width=WIDTH, height=HEIGHT, depthOrArrayLayers=1),
format=xg.TextureFormat.RGBA8Unorm,
viewFormats=[xg.TextureFormat.RGBA8Unorm],
Expand All @@ -90,7 +88,7 @@ def _main(device: xg.Device):
vertex = xg.vertexState(module=shader, entryPoint="vs_main", constants=[], buffers=[])
color_target = xg.colorTargetState(
format=xg.TextureFormat.RGBA8Unorm,
writeMask=xg.ColorWriteMaskFlags([xg.ColorWriteMask.All]),
writeMask=xg.ColorWriteMask.All,
)
multisample = xg.multisampleState()
fragment = xg.fragmentState(
Expand All @@ -109,8 +107,7 @@ def _main(device: xg.Device):
format=xg.TextureFormat.RGBA8Unorm,
dimension=xg.TextureViewDimension._2D,
mipLevelCount=1,
arrayLayerCount=1,
aspect=xg.TextureAspect.All,
arrayLayerCount=1
)

color_attachment = xg.renderPassColorAttachment(
Expand Down
2 changes: 0 additions & 2 deletions examples/triangle_windowed.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ def main():
primitive = xg.primitiveState(
topology=xg.PrimitiveTopology.TriangleList,
stripIndexFormat=xg.IndexFormat.Undefined,
frontFace=xg.FrontFace.CCW,
cullMode=xg.CullMode._None,
)
vertex = xg.vertexState(module=shader, entryPoint="vs_main", constants=[], buffers=[])
color_target = xg.colorTargetState(
Expand Down

0 comments on commit 5150d07

Please sign in to comment.