Skip to content

Commit

Permalink
Clean docs and (unused) API (#388)
Browse files Browse the repository at this point in the history
* Improvements to docs and codegen

* codegen

* fixes
  • Loading branch information
almarklein authored Oct 23, 2023
1 parent 871319f commit 369f372
Show file tree
Hide file tree
Showing 13 changed files with 80 additions and 87 deletions.
27 changes: 15 additions & 12 deletions codegen/apipatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,15 +286,13 @@ def get_class_def(self, classname):
bases = sorted(cls.bases or [], key=lambda n: n.count("GPUObjectBase"))
bases = [b for b in bases if b not in ignore]
# Cover some special cases
if not bases and classname.lower().endswith("error"):
if "memory" in classname:
bases = "(MemoryError)"
else:
bases = "(Exception)"
elif not bases:
bases = ""
else:
bases = f"({', '.join(bases)})"
if classname.lower().endswith("error"):
if "memory" in classname.lower():
bases.append("MemoryError")
elif not bases:
bases.append("Exception")

bases = "" if not bases else f"({', '.join(bases)})"
return f"class {classname}{bases}:"

def get_method_def(self, classname, methodname):
Expand Down Expand Up @@ -437,10 +435,15 @@ def class_is_known(self, classname):

def get_class_def(self, classname):
line, _ = self.classes[classname]
if "):" in line:
return line.replace("(", f"(base.{classname}, ")
else:

if "):" not in line:
return line.replace(":", f"(base.{classname}):")
else:
i = line.find("(")
bases = line[i:].strip("():").replace(",", " ").split()
bases = [b for b in bases if b.startswith("GPU")]
bases.insert(0, f"base.{classname}")
return line[:i] + "(" + ", ".join(bases) + "):"

def get_method_def(self, classname, methodname):
_, methods = self.classes[classname]
Expand Down
3 changes: 3 additions & 0 deletions codegen/idlparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ def resolve_type(self, typename):
"ImageData": "memoryview",
"VideoFrame": "memoryview",
"GPUPipelineConstantValue": "float",
"GPUExternalTexture": "object",
}
name = pythonmap.get(name, name)

Expand Down Expand Up @@ -403,6 +404,8 @@ def _post_process(self):
"GPUSupportedLimits",
"GPUSupportedFeatures",
"WGSLLanguageFeatures",
"GPUUncapturedErrorEvent",
"GPUExternalTexture",
]:
self._interfaces.pop(name, None)

Expand Down
4 changes: 2 additions & 2 deletions docs/guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Selecting the backend

To use ``wgpu``, you must select a backend. Eventually
there may be multiple backends, but at the moment
there is only one backend, which is based on the Rust libary
there is only one, which is based on the Rust libary
`wgpu-native <https://github.com/gfx-rs/wgpu>`__. You select
the backend by importing it:

Expand Down Expand Up @@ -203,7 +203,7 @@ object. These objects provide a quite versatile view on ndarray data:
.. code-block:: py
# One could, for instance read the content of a buffer
m = buffer.read_data()
m = device.queue.read_buffer(buffer)
# Cast it to float32
m = m.cast("f")
# Index it
Expand Down
6 changes: 3 additions & 3 deletions docs/start.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Python 3.7 or higher is required. Pypy is supported. Only depends on ``cffi`` (i
pip install wgpu
Since most users will want to render something to screen, we recommend installing GLGW as well:
Since most users will want to render something to screen, we recommend installing GLFW as well:

.. code-block:: bash
Expand Down Expand Up @@ -54,8 +54,8 @@ is selected automatically, but can be overridden by setting the
Windows
+++++++

On Windows 10+, things should just work. On older Windows versions you
may need to install the Vulkan drivers.
On Windows 10+, things should just work. If your machine has a dedicated GPU,
you may want to update to the latest (Nvidia or AMD) drivers.

MacOS
+++++
Expand Down
6 changes: 5 additions & 1 deletion docs/utils.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Utils
=====

The wgpu library provides a few utilities. Note that the functions below need to be explictly imported.
The wgpu library provides a few utilities. Note that most functions below need to be explictly imported.


Get default device
Expand All @@ -13,6 +13,10 @@ Get default device
Compute with buffers
--------------------

.. code-block:: py
from wgpu.utils.compute import compute_with_buffers
.. autofunction:: wgpu.utils.compute_with_buffers


Expand Down
29 changes: 13 additions & 16 deletions docs/wgpu.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@ Graphics Processing Unit.
The WebGPU API is still being developed and occasionally there are backwards
incompatible changes. Since we mostly follow the WebGPU API, there may be
backwards incompatible changes to wgpu-py too. This will be so until
the WebGPU API settles as a standard.
the WebGPU API settles as a standard. In the mean time, keep an eye on the
`CHANGELOG.md <https://github.com/pygfx/wgpu-py/blob/main/CHANGELOG.md>`_.


How to read this API
--------------------

The classes in this API all have a name staring with "GPU", this helps
discern them from flags and enums. These classes are never instantiated
directly; new objects are returned by certain methods.
directly; new objects are returned by special methods (mostly from the device).

Most methods in this API have no positional arguments; each argument
must be referenced by name. Some argument values must be a :doc:`dict <wgpu_structs>`, these
Expand All @@ -44,7 +45,7 @@ here accept the fields in that struct as keyword arguments.


Each backend may also implement minor differences (usually additions)
from the base API. For the ``rs`` backend check ``print(wgpu.backends.rs.apidiff.__doc__)``.
from the base API. The ``rs`` backend only adds ``GPUAdapter.request_device_tracing()``.


Overview
Expand Down Expand Up @@ -89,8 +90,6 @@ for it, that can be attached to a shader.
To let a shader sample from a texture, you also need a :class:`GPUSampler` that
defines the filtering and sampling behavior beyond the edges.

WebGPU also defines the :class:`GPUExternalTexture`, but this is not (yet?) used in wgpu-py.

Bind groups
+++++++++++

Expand Down Expand Up @@ -144,16 +143,16 @@ implememted in wgpu-py.
Error handling
++++++++++++++

Errors are caught and logged using the ``wgpu`` logger.
Errors in wgpu-native are raised as Python errors where possible. Uncaught errors
and warnings are logged using the ``wgpu`` logger.

Todo: document the role of these classes:
:class:`GPUUncapturedErrorEvent`
:class:`GPUError`
:class:`GPUValidationError`
:class:`GPUOutOfMemoryError`
:class:`GPUInternalError`
:class:`GPUPipelineError`
:class:`GPUDeviceLostInfo`
There are specific exceptions that can be raised:
* :class:`GPUError` is the generic (base) error class.
* :class:`GPUValidationError` is for wgpu validation errors. Shader errors also fall into this category.
* :class:`GPUOutOfMemoryError` is a wgpu `MemoryError`.
* :class:`GPUInternalError` when wgpu reaches a internal error state.
* :class:`GPUPipelineError` for errors related to the pipeline.
* :class:`GPUDeviceLostInfo` when the device is lost.

TODO
++++
Expand Down Expand Up @@ -202,7 +201,6 @@ List of GPU classes
~GPUDevice
~GPUDeviceLostInfo
~GPUError
~GPUExternalTexture
~GPUInternalError
~GPUObjectBase
~GPUOutOfMemoryError
Expand All @@ -220,5 +218,4 @@ List of GPU classes
~GPUShaderModule
~GPUTexture
~GPUTextureView
~GPUUncapturedErrorEvent
~GPUValidationError
1 change: 1 addition & 0 deletions docs/wgpu_enums.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ Enums
.. automodule:: wgpu.enums
:members:
:undoc-members:
:exclude-members: Enum
1 change: 1 addition & 0 deletions docs/wgpu_flags.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ Flags
.. automodule:: wgpu.flags
:members:
:undoc-members:
:exclude-members: Flags
1 change: 1 addition & 0 deletions docs/wgpu_structs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ Structs
.. automodule:: wgpu.structs
:members:
:undoc-members:
:exclude-members: Struct
39 changes: 16 additions & 23 deletions wgpu/backends/rs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2688,20 +2688,17 @@ def _destroy(self):
libf.wgpuRenderBundleRelease(internal)


class GPUDeviceLostInfo(base.GPUDeviceLostInfo):
pass


class GPUError(base.GPUError, Exception):
class GPUQuerySet(base.GPUQuerySet, GPUObjectBase):
pass


class GPUOutOfMemoryError(base.GPUOutOfMemoryError, GPUError):
pass
def destroy(self):
if self._internal is not None and lib is not None:
self._internal, internal = None, self._internal
# H: void f(WGPUQuerySet querySet)
libf.wgpuQuerySetRelease(internal)


class GPUValidationError(base.GPUValidationError, GPUError):
pass
# %% Subclasses that don't need anything else


class GPUCompilationMessage(base.GPUCompilationMessage):
Expand All @@ -2712,32 +2709,28 @@ class GPUCompilationInfo(base.GPUCompilationInfo):
pass


class GPUQuerySet(base.GPUQuerySet, GPUObjectBase):
class GPUDeviceLostInfo(base.GPUDeviceLostInfo):
pass

def destroy(self):
if self._internal is not None and lib is not None:
self._internal, internal = None, self._internal
# H: void f(WGPUQuerySet querySet)
libf.wgpuQuerySetRelease(internal)

class GPUError(base.GPUError):
pass


class GPUExternalTexture(base.GPUExternalTexture, GPUObjectBase):
class GPUOutOfMemoryError(base.GPUOutOfMemoryError, GPUError):
pass


class GPUUncapturedErrorEvent(base.GPUUncapturedErrorEvent):
class GPUValidationError(base.GPUValidationError, GPUError):
pass


class GPUPipelineError(base.GPUPipelineError, Exception):
def __init__(self, message="", options=None):
super().__init__(message, options)
class GPUPipelineError(base.GPUPipelineError):
pass


class GPUInternalError(base.GPUInternalError, GPUError):
def __init__(self, message):
super().__init__(message)
pass


# %%
Expand Down
38 changes: 14 additions & 24 deletions wgpu/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
"GPUBuffer",
"GPUTexture",
"GPUTextureView",
"GPUExternalTexture",
"GPUSampler",
"GPUBindGroupLayout",
"GPUBindGroup",
Expand Down Expand Up @@ -55,7 +54,6 @@
"GPUValidationError",
"GPUOutOfMemoryError",
"GPUInternalError",
"GPUUncapturedErrorEvent",
]

logger = logging.getLogger("wgpu")
Expand Down Expand Up @@ -103,7 +101,7 @@ async def request_adapter_async(
) # no-cover

# IDL: GPUTextureFormat getPreferredCanvasFormat();
@apidiff.change("Disabled because we put it on the canvas context.")
@apidiff.change("Disabled because we put it on the canvas context")
def get_preferred_canvas_format(self):
"""Not implemented in wgpu-py; use `GPUCanvasContext.get_preferred_format()` instead.
The WebGPU spec defines this function, but in wgpu there are different
Expand Down Expand Up @@ -419,12 +417,17 @@ def adapter(self):
return self._adapter

# IDL: readonly attribute Promise<GPUDeviceLostInfo> lost;
@apidiff.hide("Not a Pythonic API")
@property
def lost(self):
"""Provides information about why the device is lost."""
# In JS you can device.lost.then ... to handle lost devices.
# We may want to eventually support something similar async-like?
# at some point
raise NotImplementedError()

# IDL: attribute EventHandler onuncapturederror;
@apidiff.hide("Specific to browsers")
@property
def onuncapturederror(self):
"""Method called when an error is capured?"""
Expand Down Expand Up @@ -908,7 +911,7 @@ def pop_error_scope(self):
raise NotImplementedError()

# IDL: GPUExternalTexture importExternalTexture(GPUExternalTextureDescriptor descriptor);
@apidiff.hide("Specific to browsers.")
@apidiff.hide("Specific to browsers")
def import_external_texture(
self,
*,
Expand Down Expand Up @@ -1843,7 +1846,7 @@ def on_submitted_work_done(self):
raise NotImplementedError()

# IDL: undefined copyExternalImageToTexture( GPUImageCopyExternalImage source, GPUImageCopyTextureTagged destination, GPUExtent3D copySize);
@apidiff.hide("Specific to browsers.")
@apidiff.hide("Specific to browsers")
def copy_external_image_to_texture(self, source, destination, copy_size):
raise NotImplementedError()

Expand All @@ -1854,6 +1857,8 @@ def copy_external_image_to_texture(self, source, destination, copy_size):
class GPUDeviceLostInfo:
"""An object that contains information about the device being lost."""

# Not used at the moment, see device.lost prop

def __init__(self, reason, message):
self._reason = reason
self._message = message
Expand Down Expand Up @@ -1884,7 +1889,7 @@ def message(self):
return self.args[0]


class GPUOutOfMemoryError(GPUError):
class GPUOutOfMemoryError(GPUError, MemoryError):
"""An error raised when the GPU is out of memory."""

# IDL: constructor(DOMString message);
Expand Down Expand Up @@ -2001,24 +2006,9 @@ def count(self):
raise NotImplementedError()


class GPUExternalTexture(GPUObjectBase):
"""Ignore this - specific to browsers."""


class GPUUncapturedErrorEvent:
"""TODO"""

# IDL: [SameObject] readonly attribute GPUError error;
@property
def error(self):
"""The error object."""
raise NotImplementedError()

# IDL: constructor( DOMString type, GPUUncapturedErrorEventInit gpuUncapturedErrorEventInitDict );
def __init__(self, type, gpu_uncaptured_error_event_init_dict):
pass


# %%%%% Post processing

# Note that some toplevel classes are already filtered out by the codegen,
# like GPUExternalTexture and GPUUncapturedErrorEvent, and more.

apidiff.remove_hidden_methods(globals())
Loading

0 comments on commit 369f372

Please sign in to comment.