diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a760c761..ebb58745 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -176,7 +176,7 @@ jobs: pyversion: '3.13' - name: Test Linux pypy3 os: ubuntu-latest - pyversion: 'pypy3.9' + pyversion: 'pypy3.10' steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.pyversion }} diff --git a/.github/workflows/screenshots.yml b/.github/workflows/screenshots.yml index 1654518a..1840fc99 100644 --- a/.github/workflows/screenshots.yml +++ b/.github/workflows/screenshots.yml @@ -19,8 +19,6 @@ jobs: python-version: '3.12' - name: Install llvmpipe and lavapipe for offscreen canvas run: | - sudo apt-get update -y -qq - sudo add-apt-repository ppa:oibaf/graphics-drivers -y sudo apt-get update -y -qq sudo apt install -y libegl1-mesa-dev libgl1-mesa-dri libxcb-xfixes0-dev mesa-vulkan-drivers - name: Install dev dependencies diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 43afffc9..04b72edf 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -6,7 +6,7 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3.11" + python: "3.12" # If we ever want to run wgpu stuff in the doc build # apt_packages: # - libegl1-mesa-dev diff --git a/CHANGELOG.md b/CHANGELOG.md index 84aba474..6f42e976 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,57 @@ Possible sections in each release: * Security: in case of vulnerabilities. +### [v0.21.0] - 17-03-2025 + +This releases updates to using wgpu-native v24.0.0.2, and updates the API to the latest WebGPU spec (IDL). + +Added: + +* New `canvas_context.get_configuration()` method. +* New `device.adapter_info` property. +* New `usage` arg for `texture.create_view()`. +* New `feaure_level` arg for `request_adapter()`. More a diagnostic tool, not for most end-users. + + +### [v0.20.1] - 14-03-2025 + +Other: +* Add release notes. + + +### [v0.20.0] - 14-03-2025 + +Added: + +* Add Imgui based Stats component by @panxinmiao in https://github.com/pygfx/wgpu-py/pull/670 and https://github.com/pygfx/wgpu-py/pull/674 +* Can pass constants to compute helper by @kushalkolar in https://github.com/pygfx/wgpu-py/pull/676 +* Add simple matmul example by @kushalkolar in https://github.com/pygfx/wgpu-py/pull/677 + +Fixed: + +* Fix imgui scroll event by @panxinmiao in https://github.com/pygfx/wgpu-py/pull/678 + +Changed: + +* Improve error handling by @almarklein in https://github.com/pygfx/wgpu-py/pull/667 +* Bring sleep back to WgpuAwaitable. Slowly back off on the amount of time sleeping. by @fyellin in https://github.com/pygfx/wgpu-py/pull/655 +* Improve performance for 'bitmap' render method by @almarklein in https://github.com/pygfx/wgpu-py/pull/680 + +Other: + +* Stop setting AA_EnableHighDpiScaling since Qt Says it is not needed by @hmaarrfk in https://github.com/pygfx/wgpu-py/pull/657 +* Remove unneeded pytest-anyio package by @hmaarrfk in https://github.com/pygfx/wgpu-py/pull/658 +* Actually run the tests instead of fully skipping them by @hmaarrfk in https://github.com/pygfx/wgpu-py/pull/659 +* Improve state of the art for screenshot testing by @hmaarrfk in https://github.com/pygfx/wgpu-py/pull/555 +* Use default lavapipe for screenshot by @Vipitis in https://github.com/pygfx/wgpu-py/pull/660 +* Fix one typo in _helpers.py by @hmaarrfk in https://github.com/pygfx/wgpu-py/pull/661 +* Fix typo in README.md by @patrini32 in https://github.com/pygfx/wgpu-py/pull/662 +* Improve docs regarding drives on Linux by @almarklein in https://github.com/pygfx/wgpu-py/pull/668 +* Add patches for conda compatibility by @hmaarrfk in https://github.com/pygfx/wgpu-py/pull/666 +* Allow disabling downloading lib when creating wheel by @almarklein in https://github.com/pygfx/wgpu-py/pull/669 +* examples/imgui_cmap_picker.py - update for imgui bundle 1.6.2 by @pthom in https://github.com/pygfx/wgpu-py/pull/671 + + ### [v0.19.3] - 10-12-2024 Fixed: diff --git a/README.md b/README.md index 3e432a8d..668b5a30 100644 --- a/README.md +++ b/README.md @@ -178,3 +178,28 @@ differences. If you want to update the reference screenshot for a given example, you can grab those from the build artifacts as well and commit them to your branch. + +### Testing Locally + +Testing locally is possible, however pixel perfect results will differ from +those on the CIs due to discrepencies in hardware, and driver (we use llvmpipe) +versions. + +On linux, it is possible to force the usage of LLVMPIPE in the test suite +and compare the generated results of screenshots. Beware, the results on your machine +may differ to those on the CI. We always include the CI screenshots in the test suite +to improve the repeatability of the tests. + +If you have access to a linux machine with llvmpipe installed, you may run the +example pixel comparison testing by setting the WGPUPY_WGPU_ADAPTER_NAME +environment variable appropriately. For example + + +``` +WGPUPY_WGPU_ADAPTER_NAME=llvmpipe pytest -v examples/ +``` + +The `WGPUPY_WGPU_ADAPTER_NAME` variable is modeled after the +https://github.com/gfx-rs/wgpu?tab=readme-ov-file#environment-variables +and should only be used for testing the wgpu-py library itself. +It is not part of the supported wgpu-py interface. diff --git a/codegen/apipatcher.py b/codegen/apipatcher.py index 3acd0859..f29a041f 100644 --- a/codegen/apipatcher.py +++ b/codegen/apipatcher.py @@ -644,7 +644,12 @@ def apply(self, code): method_structs.update(self._get_sub_structs(idl, structname)) all_structs.update(method_structs) # Collect structs being checked - checked = structure_checks[classname, methodname] + try: + checked = structure_checks[classname, methodname] + except KeyError: + print( + f"Could not validate check_struct for {classname}.{methodname}; need another codegen run." + ) # Test that a matching check is done unchecked = method_structs.difference(checked) diff --git a/codegen/files.py b/codegen/files.py index 0b7c4b65..ad1a89d1 100644 --- a/codegen/files.py +++ b/codegen/files.py @@ -12,7 +12,13 @@ def read_file(*fname): """Read a file from disk using the relative filename. Line endings are normalized.""" filename = os.path.join(lib_dir, *fname) with open(filename, "rb") as f: - return f.read().decode().replace("\r\n", "\n").replace("\r", "\n") + return ( + f.read() + .decode() + .replace("\r\n", "\n") + .replace("\r", "\n") + .replace("\\\n", "") # Macros escaping a newline + ) class FileCache: diff --git a/codegen/hparser.py b/codegen/hparser.py index d6614b0f..2012f40b 100644 --- a/codegen/hparser.py +++ b/codegen/hparser.py @@ -95,14 +95,15 @@ def _parse_from_h(self): assert name1.startswith("WGPU") name = name1[4:] self.enums[name] = enum = {} - for f in code[i2 + 1 : i3].strip().strip(";").split(","): - f = remove_c_comments(f).strip() + code_block = code[i2 + 1 : i3].strip().strip(";") + block = remove_c_comments(code_block).strip() + for f in block.split(","): if not f: - continue # happens when last item has a comma + continue # no item after last comma key, _, val = f.partition("=") # Handle key key = key.strip() - assert key.startswith("WGPU") and "_" in key + assert key.startswith("WGPU") and "_" in key, f"key={key}" key = key.split("_", 1)[1] # Turn value into an int val = val.strip() @@ -120,18 +121,38 @@ def _parse_from_h(self): else: enum[key] = int(val) - # Turn some enums into flags for line in code.splitlines(): + # collect flags + # schme: typedef WGPUFlags WGPUFlagName; if line.startswith("typedef WGPUFlags "): parts = line.strip().strip(";").split() assert len(parts) == 3 name = parts[-1] - if name.endswith("Flags"): - assert name.startswith("WGPU") - name1 = name[4:-1] # xxFlags -> xxFlag - name2 = name[4:-5] # xxFlags -> xx - name = name1 if name1 in self.enums else name2 - self.flags[name] = self.enums.pop(name) + assert name.startswith("WGPU") + name = name[4:] + assert not name.endswith("Flags"), "XxxxFlags should not longer exist" + assert name not in self.enums, "flags used to look like enums" + self.flags[name] = {} + + # fill flags + # schema: static const WGPUFlagName WGPUFlagName_Value = 0x0000000000000001; + if line.startswith("static const"): + line = remove_c_comments(line).strip() + flag_name = line.removeprefix("static const").lstrip().split()[0] + flag_key, _, val = ( + line.removeprefix(f"static const {flag_name}") + .strip() + .rstrip(";") + .partition("=") + ) + # Check / normalize flag_name + assert flag_name.startswith("WGPU") + flag_name = flag_name[4:] + assert flag_name in self.flags + # Check / normalize flag_key + assert flag_key.startswith(f"WGPU{flag_name}_") + flag_key = flag_key.partition("_")[2].strip() + self.flags[flag_name][flag_key] = self._parse_val_to_int(val) # Collect structs. This is relatively easy, since we only need the C code. # But we don't deal with union structs. @@ -229,3 +250,22 @@ def _parse_from_cffi(self): while alt_name != ffi.getctype(alt_name): alt_name = ffi.getctype(alt_name) self.structs[alt_name] = self.structs[name] + + def _parse_val_to_int(self, val): + """ + little helper to parse complex values for enums. + """ + val = val.strip(" ()") + if "|" in val: + # recursively handle the "OR" values? + res_val = 0 + for sub_val in val.split("|"): + res_val |= self._parse_val_to_int(sub_val) + return res_val + if val.startswith("0x"): + return int(val, 16) + elif "<<" in val: + val1, _, val2 = val.partition("<<") + return int(val1) << int(val2) + else: + return int(val) diff --git a/codegen/idlparser.py b/codegen/idlparser.py index 085be0b8..f4d33040 100644 --- a/codegen/idlparser.py +++ b/codegen/idlparser.py @@ -217,6 +217,7 @@ def resolve_type(self, typename): "AllowSharedBufferSource": "memoryview", "GPUPipelineConstantValue": "float", "GPUExternalTexture": "object", + "undefined": "None", } name = pythonmap.get(name, name) diff --git a/codegen/tests/test_codegen_rspatcher.py b/codegen/tests/test_codegen_rspatcher.py index 29d5e0ee..3e27e462 100644 --- a/codegen/tests/test_codegen_rspatcher.py +++ b/codegen/tests/test_codegen_rspatcher.py @@ -37,7 +37,7 @@ def test_patch_structs(): """ code2 = patch_wgpu_native_backend(dedent(code1)) assert all(line[4:] in code2 for line in code1 if line.strip()) - assert "usage: WGPUBufferUsageFlags/int" in code2 + assert "usage: WGPUBufferUsage/int" in code2 assert "size: int" in code2 assert "# FIXME:" not in code2 assert code2 == patch_wgpu_native_backend(code2) # Don't stack comments @@ -53,7 +53,7 @@ def test_patch_structs(): """ code2 = patch_wgpu_native_backend(dedent(code1)) assert all(line[4:] in code2 for line in code1 if line.strip()) - assert "usage: WGPUBufferUsageFlags/int" in code2 + assert "usage: WGPUBufferUsage/int" in code2 assert "size: int" in code2 assert "# FIXME:" not in code2 @@ -72,7 +72,7 @@ def test_patch_structs(): # Missing values code1 = 'struct = new_struct_p("WGPUBufferDescriptor *",label=c_label,size=size,)' code2 = patch_wgpu_native_backend(dedent(code1)) - assert "usage: WGPUBufferUsageFlags/int" in code2 + assert "usage: WGPUBufferUsage/int" in code2 assert "# FIXME:" not in code2 assert "usage" in code2 # comment added assert code2 == patch_wgpu_native_backend(code2) # Don't stack comments @@ -80,7 +80,7 @@ def test_patch_structs(): # Too many values code1 = 'struct = new_struct_p("WGPUBufferDescriptor *",label=c_label,foo=size,)' code2 = patch_wgpu_native_backend(dedent(code1)) - assert "usage: WGPUBufferUsageFlags/int" in code2 + assert "usage: WGPUBufferUsage/int" in code2 assert "# FIXME: unknown" in code2 assert code2 == patch_wgpu_native_backend(code2) # Don't stack comments diff --git a/codegen/wgpu_native_patcher.py b/codegen/wgpu_native_patcher.py index 0773d279..330c8b0e 100644 --- a/codegen/wgpu_native_patcher.py +++ b/codegen/wgpu_native_patcher.py @@ -15,6 +15,7 @@ import re from collections import defaultdict +from itertools import chain from codegen.utils import print, format_code, Patcher, to_snake_case from codegen.hparser import get_h_parser @@ -290,13 +291,10 @@ def apply(self, code): class StructPatcher(Patcher): def apply(self, code): self._init(code) - hp = get_h_parser() - count = 0 - line_index = -1 - brace_depth = 0 for line, i in self.iter_lines(): + # detect struct definition start (only when not already inside a struct) if "new_struct_p(" in line or "new_struct(" in line: if line.lstrip().startswith("def "): continue # Implementation @@ -304,28 +302,36 @@ def apply(self, code): continue # Implementation if "new_struct_p()" in line or "new_struct()" in line: continue # Comments or docs - line_index = i j = line.index("new_struct") line = line[j:] # start brace searching from right pos - brace_depth = 0 - - if line_index >= 0: - for c in line: - if c == "#": - break - elif c == "(": - brace_depth += 1 - elif c == ")": - brace_depth -= 1 - assert brace_depth >= 0 - if brace_depth == 0: - self._validate_struct(hp, line_index, i) - count += 1 - line_index = -1 - break + # call a function to find the end and validate so we don't skip over nested structure in this loop + self._find_struct_end(line, i) + count += 1 print(f"Validated {count} C structs") + def _find_struct_end(self, first_line, start_line_index): + """ + If a struct start is found, this function will find the end of the struct and then validate it + """ + brace_depth = 0 + hp = get_h_parser() + for line, i in chain( + [(first_line, 0)], self.iter_lines(start_line=start_line_index + 1) + ): + for c in line: + if c == "#": + break + elif c == "(": + brace_depth += 1 + elif c == ")": + brace_depth -= 1 + assert brace_depth >= 0 + if brace_depth == 0: + # here we have found the end of this struct so now we can validate it. + self._validate_struct(hp, start_line_index, i) + return # we assume it always works? + def _validate_struct(self, hp, i1, i2): """Validate a specific struct usage.""" @@ -381,19 +387,32 @@ def _validate_struct(self, hp, i1, i2): self.insert_line(i1, indent + "# H: " + fields) # Check keys + brace_count = 0 keys_found = [] for j in range(2, len(lines) - 1): line = lines[j] - key = line.split("=")[0].strip() - if key.startswith("# not used:"): - key = key.split(":")[1].split("=")[0].strip() - elif key.startswith("#"): - continue - keys_found.append(key) - if key not in struct: - msg = f"unknown C struct field {struct_name}.{key}" - self.insert_line(i1 + j, f"{indent}# FIXME: {msg}") - print(f"ERROR: {msg}") + if brace_count <= 0: + # ready to find a new key candidate + key = line.split("=")[0].strip() + if key.startswith("# not used:"): + key = key.split(":")[1].split("=")[0].strip() + elif key.startswith("#"): + continue + # (still) inside a multi-line structure + for c in line.strip(): + if c == "#": + break # we can ignore this line past the comment in terms of nested structures + elif c == "(": + brace_count += 1 + elif c == ")": + brace_count -= 1 + if brace_count == 0: + # here we finished through the multi line structure + keys_found.append(key) + if key not in struct: + msg = f"unknown C struct field {struct_name}.{key}" + self.insert_line(i1 + j, f"{indent}# FIXME: {msg}") + print(f"ERROR: {msg}") # Insert comments for unused keys more_lines = [] diff --git a/docs/backends.rst b/docs/backends.rst index 01c2f576..c17c764f 100644 --- a/docs/backends.rst +++ b/docs/backends.rst @@ -158,12 +158,14 @@ bytes you wish to change. :param data_offset: The starting offset in the data at which to begin copying. -There are two functions that allow you to perform multiple draw calls at once. -Both require that you enable the feature "multi-draw-indirect". +There are four functions that allow you to perform multiple draw calls at once. +Two take the number of draws to perform as an argument; two have this value in a buffer. Typically, these calls do not reduce work or increase parallelism on the GPU. Rather they reduce driver overhead on the CPU. +The first two require that you enable the feature ``"multi-draw-indirect"``. + .. py:function:: wgpu.backends.wgpu_native.multi_draw_indirect(render_pass_encoder, buffer, *, offset=0, count): Equivalent to:: @@ -171,22 +173,68 @@ they reduce driver overhead on the CPU. render_pass_encoder.draw_indirect(buffer, offset + i * 16) :param render_pass_encoder: The current render pass encoder. - :param buffer: The indirect buffer containing the arguments. + :param buffer: The indirect buffer containing the arguments. Must have length + at least offset + 16 * count. :param offset: The byte offset in the indirect buffer containing the first argument. + Must be a multiple of 4. :param count: The number of draw operations to perform. .. py:function:: wgpu.backends.wgpu_native.multi_draw_indexed_indirect(render_pass_encoder, buffer, *, offset=0, count): Equivalent to:: + for i in range(count): render_pass_encoder.draw_indexed_indirect(buffer, offset + i * 2-) :param render_pass_encoder: The current render pass encoder. - :param buffer: The indirect buffer containing the arguments. + :param buffer: The indirect buffer containing the arguments. Must have length + at least offset + 20 * count. :param offset: The byte offset in the indirect buffer containing the first argument. + Must be a multiple of 4. :param count: The number of draw operations to perform. +The second two require that you enable the feature ``"multi-draw-indirect-count"``. +They are identical to the previous two, except that the ``count`` argument is replaced by +three arguments. The value at ``count_buffer_offset`` in ``count_buffer`` is treated as +an unsigned 32-bit integer. The ``count`` is the minimum of this value and ``max_count``. + +.. py:function:: wgpu.backends.wgpu_native.multi_draw_indirect_count(render_pass_encoder, buffer, *, offset=0, count_buffer, count_offset=0, max_count): + + Equivalent to:: + + count = min(, max_count) + for i in range(count): + render_pass_encoder.draw_indirect(buffer, offset + i * 16) + + :param render_pass_encoder: The current render pass encoder. + :param buffer: The indirect buffer containing the arguments. Must have length + at least offset + 16 * max_count. + :param offset: The byte offset in the indirect buffer containing the first argument. + Must be a multiple of 4. + :param count_buffer: The indirect buffer containing the count. + :param count_buffer_offset: The offset into count_buffer. + Must be a multiple of 4. + :param max_count: The maximum number of draw operations to perform. + +.. py:function:: wgpu.backends.wgpu_native.multi_draw_indexed_indirect_count(render_pass_encoder, buffer, *, offset=0, count_buffer, count_offset=0, max_count): + + Equivalent to:: + + count = min(, max_count) + for i in range(count): + render_pass_encoder.draw_indexed_indirect(buffer, offset + i * 2-) + + :param render_pass_encoder: The current render pass encoder. + :param buffer: The indirect buffer containing the arguments. Must have length + at least offset + 20 * max_count. + :param offset: The byte offset in the indirect buffer containing the first argument. + Must be a multiple of 4. + :param count_buffer: The indirect buffer containing the count. + :param count_buffer_offset: The offset into count_buffer. + Must be a multiple of 4. + :param max_count: The maximum number of draw operations to perform. + Some GPUs allow you collect statistics on their pipelines. Those GPUs that support this have the feature "pipeline-statistics-query", and you must enable this feature when getting the device. diff --git a/docs/start.rst b/docs/start.rst index 156f3759..189cfb2c 100644 --- a/docs/start.rst +++ b/docs/start.rst @@ -6,8 +6,8 @@ Installation Install with pip ---------------- -You can install ``wgpu-py`` via pip. -Python 3.9 or higher is required. Pypy is supported. Only depends on ``cffi`` (installed automatically by pip). +You can install ``wgpu-py`` with your favourite package manager (we use ``pip`` in the example commands below). +Python 3.9 or higher is required. Pypy is supported. .. code-block:: bash @@ -69,6 +69,8 @@ On Linux, it's advisable to install the proprietary drivers of your GPU (if you have a dedicated GPU). You may need to ``apt install mesa-vulkan-drivers``. On Wayland, wgpu-py requires XWayland (available by default on most distributions). +Note that WSL is currently not supported. + Binary wheels for Linux are only available for **manylinux_2_24**. This means that the installation requires ``pip >= 20.3``, and you need a recent Linux distribution, listed `here `_. @@ -84,7 +86,11 @@ Cloud Compute GPU Environments ^^^^^^^^^^^^^^^^ -WGPU can work in GPU cloud compute environments on Linux machines with no physical display output. By default, these environments may lack system libraries that are typically found on a standard linux desktop. On Debian & Ubuntu based systems you should be able to get everything you need by installing the following in addition to your vendor-specific (Nvidia/AMD) GPU drivers: +WGPU can work in GPU cloud compute environments on Linux machines with no +physical display output. By default, these environments may lack system +libraries that are typically found on a standard linux desktop. On Debian & +Ubuntu based systems you should be able to get everything you need by installing +the following in addition to your vendor-specific (Nvidia/AMD) GPU drivers: .. code-block:: bash @@ -119,14 +125,7 @@ On Windows this (probably) just works via DX12. On Linux you can use LavaPipe: .. code-block:: bash - sudo apt update -y -qq - sudo apt install --no-install-recommends -y libegl1-mesa-dev libgl1-mesa-dri libxcb-xfixes0-dev mesa-vulkan-drivers - -The distribution's version of Lavapipe may be a bit outdated. To get a more recent version, you can use this PPA: - -.. code-block:: bash - - sudo add-apt-repository ppa:oibaf/graphics-drivers -y + sudo apt install libegl1-mesa-dev libgl1-mesa-dri libxcb-xfixes0-dev mesa-vulkan-drivers .. note:: diff --git a/examples/compute_matmul.py b/examples/compute_matmul.py new file mode 100644 index 00000000..eb1882db --- /dev/null +++ b/examples/compute_matmul.py @@ -0,0 +1,104 @@ +""" +Simple compute example that performs basic matrix multiplication. + +Uses linear arrays in storage buffers to represent matrices of arbitrary size since +the wgsl standard library only supports matrix multiplication upto 4x4 matrices. +""" + +import numpy as np +from wgpu.utils.compute import compute_with_buffers + +# define matrix shapes +m, k, n = 6, 7, 8 + +A_shape = (m, k) +B_shape = (k, n) + +# create random matrices +A = ( + np.random.rand(A_shape[0] * A_shape[1]) + .astype(np.float32) + .reshape(A_shape, order="C") +) +B = ( + np.random.rand(B_shape[0] * B_shape[1]) + .astype(np.float32) + .reshape(B_shape, order="C") +) + +# define bindings +bindings = { + 0: A, + 1: B, + 3: np.array(A_shape, dtype=np.uint32), + 4: np.array(B_shape, dtype=np.uint32), +} + +shader_src = """ +@group(0) @binding(0) +var A: array; +@group(0) @binding(1) +var B: array; +@group(0) @binding(2) +var C: array; + +@group(0) @binding(3) +var A_shape: array; +@group(0) @binding(4) +var B_shape: array; + + +fn get_1d_index(row_ix: u32, col_ix: u32, n_cols: u32) -> u32 { + // get the 1D index in the array which corresponds + // to the passed row and column index + return row_ix * n_cols + col_ix; +} + +@compute @workgroup_size(1) +fn main(@builtin(global_invocation_id) gid: vec3) { + // naive matrix multiplication + // A ∈ R^(m x k), B ∈ R^(k x n), AB = C ∈ R^(m x n) + // gid.y is "m index", gid.x is "n index" + + // we make these varibles because we cannot pass individual array elements to a function + // i.e. get_1d_index(A_shape[0]) is not possible + let m: u32 = A_shape[0]; + let k: u32 = A_shape[1]; + let n: u32 = B_shape[1]; + + // computes one element of C using A at row gid.y and B at column gid.x + var sum: f32 = 0.0; + + // computes one element of C using A at row gid.y and B at column gid.x + for (var i: u32 = 0; i < k; i++) { + // dot product of A at row = gid.y, col = i and B at row = i, col = gid.x + // A col max index is k - 1, B row max index is k - 1 + sum = sum + A[get_1d_index(gid.y, i, k)] * B[get_1d_index(i, gid.x, n)]; + } + + // set element of C + C[get_1d_index(gid.y, gid.x, n)] = sum; + + return; +} +""" + +# run shader +out = compute_with_buffers( + input_arrays=bindings, + output_arrays={2: (np.prod((m, n)), "f")}, + shader=shader_src, + n=(n, m, 1), # n cols across "x dimension", m rows across "y dimension" +) + +# get output +C = np.frombuffer(out[2], dtype=np.float32).reshape((m, n)) + +# check that results are the same as numpy, we can expect 7 decimal precision +all_close = np.allclose(A @ B, C) +assert all_close +print(f"np.allclose():\n {all_close}\n") +print(f"AB - C:\n{A @ B - C}\n") +diff_norms = np.linalg.norm(A @ B - C, ord="fro") / np.linalg.norm(A @ B, ord="fro") +print(f"||AB - C||_F - ||AB||_F:\n{diff_norms}\n") +print(f"C:\n{C}") diff --git a/examples/compute_timestamps.py b/examples/compute_timestamps.py index 60afddc9..d4887503 100644 --- a/examples/compute_timestamps.py +++ b/examples/compute_timestamps.py @@ -23,7 +23,7 @@ var data3: array; @compute -@workgroup_size({','.join(map(str, local_size))}) +@workgroup_size({",".join(map(str, local_size))}) fn main(@builtin(global_invocation_id) index: vec3) {{ let i: u32 = index.x; data3[i] = data1[i] + data2[i]; @@ -152,7 +152,7 @@ Index 1: end timestamp """ timestamps = device.queue.read_buffer(query_buf).cast("Q").tolist() -print(f"Adding two {n} sized arrays took {(timestamps[1]-timestamps[0])/1000} us") +print(f"Adding two {n} sized arrays took {(timestamps[1] - timestamps[0]) / 1000} us") # Read result out = device.queue.read_buffer(buffer3).cast("i") diff --git a/examples/cube.py b/examples/cube.py index 46a65683..153bfe94 100644 --- a/examples/cube.py +++ b/examples/cube.py @@ -15,6 +15,8 @@ import wgpu import numpy as np +from wgpu.gui.auto import WgpuCanvas, run + # %% Entrypoints (sync and async) @@ -453,21 +455,21 @@ async def draw_frame_async(): uniform_data = np.zeros((), dtype=uniform_dtype) -if __name__ == "__main__": - from wgpu.gui.auto import WgpuCanvas, run +print("Available adapters on this system:") +for a in wgpu.gpu.enumerate_adapters_sync(): + print(a.summary) - print("Available adapters on this system:") - for a in wgpu.gpu.enumerate_adapters_sync(): - print(a.summary) +canvas = WgpuCanvas(size=(640, 480), title="wgpu cube example") - canvas = WgpuCanvas(size=(640, 480), title="wgpu cube example") +draw_frame = setup_drawing_sync(canvas) - draw_frame = setup_drawing_sync(canvas) - def animate(): - draw_frame() - canvas.request_draw() +def animate(): + draw_frame() + canvas.request_draw() - canvas.request_draw(animate) +canvas.request_draw(animate) + +if __name__ == "__main__": run() diff --git a/examples/gui_asyncio.py b/examples/gui_asyncio.py index 803ae927..6ea02843 100644 --- a/examples/gui_asyncio.py +++ b/examples/gui_asyncio.py @@ -38,7 +38,7 @@ async def main_loop(): frame_count += 1 etime = time.perf_counter() - last_frame_time if etime > 1: - print(f"{frame_count/etime:0.1f} FPS") + print(f"{frame_count / etime:0.1f} FPS") last_frame_time, frame_count = time.perf_counter(), 0 # dispose resources diff --git a/examples/gui_auto.py b/examples/gui_auto.py index 9571f71d..bc9e6109 100644 --- a/examples/gui_auto.py +++ b/examples/gui_auto.py @@ -6,9 +6,10 @@ from wgpu.gui.auto import WgpuCanvas, run -from triangle import setup_drawing_sync -# from cube import setup_drawing_sync - +try: + from .triangle import setup_drawing_sync +except ImportError: + from triangle import setup_drawing_sync canvas = WgpuCanvas(title=f"Triangle example on {WgpuCanvas.__name__}") draw_frame = setup_drawing_sync(canvas) diff --git a/examples/gui_direct.py b/examples/gui_direct.py index a1005234..bc9b8134 100644 --- a/examples/gui_direct.py +++ b/examples/gui_direct.py @@ -64,7 +64,7 @@ def main(): frame_count += 1 etime = time.perf_counter() - last_frame_time if etime > 1: - print(f"{frame_count/etime:0.1f} FPS") + print(f"{frame_count / etime:0.1f} FPS") last_frame_time, frame_count = time.perf_counter(), 0 # dispose resources diff --git a/examples/gui_trio.py b/examples/gui_trio.py index f5ed70b3..34572e55 100644 --- a/examples/gui_trio.py +++ b/examples/gui_trio.py @@ -45,7 +45,7 @@ async def main_loop(): frame_count += 1 etime = time.perf_counter() - last_frame_time if etime > 1: - print(f"{frame_count/etime:0.1f} FPS") + print(f"{frame_count / etime:0.1f} FPS") last_frame_time, frame_count = time.perf_counter(), 0 # dispose resources diff --git a/examples/imgui_cmap_picker.py b/examples/imgui_cmap_picker.py index dd13f3a8..806d0915 100644 --- a/examples/imgui_cmap_picker.py +++ b/examples/imgui_cmap_picker.py @@ -102,7 +102,7 @@ def update_gui(): for cmap_name, tex_id in cmap_data.items(): # text part of each item clicked, enabled = imgui.menu_item( - cmap_name, None, p_selected=current_cmap == cmap_name + cmap_name, "", p_selected=current_cmap == cmap_name ) imgui.same_line() # the image part of each item, give it the texture id diff --git a/examples/imgui_renderer_sea.py b/examples/imgui_renderer_sea.py index 8bb70c32..ebe51093 100644 --- a/examples/imgui_renderer_sea.py +++ b/examples/imgui_renderer_sea.py @@ -9,10 +9,10 @@ import time import numpy as np from imgui_bundle import imgui -from wgpu.utils.imgui import ImguiRenderer +from wgpu.utils.imgui import ImguiRenderer, Stats # Create a canvas to render to -canvas = WgpuCanvas(title="imgui_sea", size=(800, 450), max_fps=60) +canvas = WgpuCanvas(title="imgui_sea", size=(800, 450), max_fps=-1, vsync=False) # Create a wgpu device adapter = wgpu.gpu.request_adapter_sync(power_preference="high-performance") @@ -377,9 +377,12 @@ def render(): # set the GUI update function that gets called to return the draw data imgui_renderer.set_gui(lambda: gui(app_state)) +stats = Stats(device, canvas, align="right") + def loop(): - render() + with stats: + render() imgui_renderer.render() canvas.request_draw() diff --git a/examples/screenshots/gui_auto.png b/examples/screenshots/gui_auto.png new file mode 100644 index 00000000..643c3977 Binary files /dev/null and b/examples/screenshots/gui_auto.png differ diff --git a/examples/tests/test_examples.py b/examples/tests/test_examples.py index a9b9b1d1..955df62e 100644 --- a/examples/tests/test_examples.py +++ b/examples/tests/test_examples.py @@ -94,7 +94,10 @@ def unload_module(): # the first part of the test everywhere else; ensuring that examples # can at least import, run and render something if not is_lavapipe: - pytest.skip("screenshot comparisons are only done when using lavapipe") + pytest.skip( + "screenshot comparisons are only done when using lavapipe. " + "Rerun your tests with WGPUPY_WGPU_ADAPTER_NAME=llvmpipe" + ) # regenerate screenshot if requested screenshots_dir.mkdir(exist_ok=True) @@ -108,36 +111,62 @@ def unload_module(): ), "found # test_example = true but no reference screenshot available" stored_img = imageio.imread(screenshot_path) # assert similarity - is_similar = np.allclose(img, stored_img, atol=1) - update_diffs(module, is_similar, img, stored_img) - assert is_similar, ( - f"rendered image for example {module} changed, see " - f"the {diffs_dir.relative_to(ROOT).as_posix()} folder" - " for visual diffs (you can download this folder from" - " CI build artifacts as well)" - ) + atol = 1 + try: + np.testing.assert_allclose(img, stored_img, atol=atol) + is_similar = True + except Exception as e: + is_similar = False + raise AssertionError( + f"rendered image for example {module_name} changed, see " + f"the {diffs_dir.relative_to(ROOT).as_posix()} folder" + " for visual diffs (you can download this folder from" + " CI build artifacts as well)" + ) from e + finally: + update_diffs(module_name, is_similar, img, stored_img, atol=atol) -def update_diffs(module, is_similar, img, stored_img): +def update_diffs(module, is_similar, img, stored_img, *, atol): diffs_dir.mkdir(exist_ok=True) + + if is_similar: + for path in [ + # Keep filename in sync with the ones generated below + diffs_dir / f"{module}-rgb.png", + diffs_dir / f"{module}-alpha.png", + diffs_dir / f"{module}-rgb-above_atol.png", + diffs_dir / f"{module}-alpha-above_atol.png", + diffs_dir / f"{module}.png", + ]: + if path.exists(): + path.unlink() + return + # cast to float32 to avoid overflow # compute absolute per-pixel difference diffs_rgba = np.abs(stored_img.astype("f4") - img) + + diffs_rgba_above_atol = diffs_rgba.copy() + diffs_rgba_above_atol[diffs_rgba <= atol] = 0 + # magnify small values, making it easier to spot small errors diffs_rgba = ((diffs_rgba / 255) ** 0.25) * 255 # cast back to uint8 diffs_rgba = diffs_rgba.astype("u1") - # split into an rgb and an alpha diff - diffs = { - diffs_dir / f"{module}-rgb.png": diffs_rgba[..., :3], - diffs_dir / f"{module}-alpha.png": diffs_rgba[..., 3], - } - - for path, diff in diffs.items(): - if not is_similar: - imageio.imwrite(path, diff) - elif path.exists(): - path.unlink() + + diffs_rgba_above_atol = ((diffs_rgba_above_atol / 255) ** 0.25) * 255 + diffs_rgba_above_atol = diffs_rgba_above_atol.astype("u1") + # And highlight differences that are above the atol + imageio.imwrite(diffs_dir / f"{module}-rgb.png", diffs_rgba[..., :3]) + imageio.imwrite(diffs_dir / f"{module}-alpha.png", diffs_rgba[..., 3]) + imageio.imwrite( + diffs_dir / f"{module}-rgb-above_atol.png", diffs_rgba_above_atol[..., :3] + ) + imageio.imwrite( + diffs_dir / f"{module}-alpha-above_atol.png", diffs_rgba_above_atol[..., 3] + ) + imageio.imwrite(diffs_dir / f"{module}.png", img) @pytest.mark.parametrize("module", examples_to_run) diff --git a/examples/tests/testutils.py b/examples/tests/testutils.py index a07c0c44..1ffcdc4c 100644 --- a/examples/tests/testutils.py +++ b/examples/tests/testutils.py @@ -4,7 +4,7 @@ import wgpu -ROOT = Path(__file__).parent.parent # repo root +ROOT = Path(__file__).parent.parent.parent # repo root examples_dir = ROOT / "examples" screenshots_dir = examples_dir / "screenshots" diffs_dir = screenshots_dir / "diffs" diff --git a/pyproject.toml b/pyproject.toml index 447d64c5..3930688f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,6 @@ lint = ["ruff", "pre-commit"] tests = [ "numpy", "pytest", - "pytest-anyio", "psutil", "imageio", "anyio", diff --git a/tests/test_set_constant.py b/tests/test_set_constant.py index 0408a959..bd10208d 100644 --- a/tests/test_set_constant.py +++ b/tests/test_set_constant.py @@ -143,15 +143,39 @@ def test_normal_push_constants(): assert all(result == expected_result) -def test_render_bundle_push_constants_fails(): +def test_render_bundle_push_constants(): device, pipeline, render_pass_descriptor = setup_pipeline() - encoder = device.create_render_bundle_encoder( + vertex_call_buffer = device.create_buffer(size=COUNT * 4, usage="STORAGE|COPY_SRC") + bind_group = device.create_bind_group( + layout=pipeline.get_bind_group_layout(0), + entries=[ + {"binding": 0, "resource": {"buffer": vertex_call_buffer}}, + ], + ) + bundle_encoder = device.create_render_bundle_encoder( color_formats=[TextureFormat.rgba8unorm], ) - encoder.set_pipeline(pipeline) + bundle_encoder.set_pipeline(pipeline) + bundle_encoder.set_bind_group(0, bind_group) buffer = np.random.randint(0, 1_000_000, size=(2 * COUNT), dtype=np.uint32) - with pytest.raises(RuntimeError): - set_push_constants(encoder, "VERTEX", 0, COUNT * 4, buffer) + set_push_constants(bundle_encoder, "VERTEX", 0, COUNT * 4, buffer) + set_push_constants( + bundle_encoder, "FRAGMENT", COUNT * 4, COUNT * 4, buffer, COUNT * 4 + ) + bundle_encoder.draw(COUNT) + render_bundle = bundle_encoder.finish() + + # a different encoder to execute the bundle + encoder = device.create_command_encoder() + this_pass = encoder.begin_render_pass(**render_pass_descriptor) + this_pass.execute_bundles([render_bundle]) + this_pass.end() + device.queue.submit([encoder.finish()]) + + info_view = device.queue.read_buffer(vertex_call_buffer) + result = np.frombuffer(info_view, dtype=np.uint32) + expected_result = buffer[0:COUNT] + buffer[COUNT:] + assert all(result == expected_result) def test_bad_set_push_constants(): diff --git a/tests/test_wgpu_native_buffer.py b/tests/test_wgpu_native_buffer.py index f9281352..21bc0ae0 100644 --- a/tests/test_wgpu_native_buffer.py +++ b/tests/test_wgpu_native_buffer.py @@ -150,7 +150,7 @@ def test_consecutive_writes1(): # Write in parts for i in range(4): buf.map_sync("write") - buf.write_mapped(f"{i+1}".encode() * 8, i * 8) + buf.write_mapped(f"{i + 1}".encode() * 8, i * 8) buf.unmap() # Download from buffer to CPU @@ -160,7 +160,7 @@ def test_consecutive_writes1(): # Also in parts for i in range(4): data = device.queue.read_buffer(buf, i * 8, size=8) - assert data == f"{i+1}".encode() * 8 + assert data == f"{i + 1}".encode() * 8 @mark.skipif(not can_use_wgpu_lib, reason="Needs wgpu lib") @@ -177,7 +177,7 @@ def test_consecutive_writes2(): # Write in parts buf.map_sync("write") for i in range(4): - buf.write_mapped(f"{i+1}".encode() * 8, i * 8) + buf.write_mapped(f"{i + 1}".encode() * 8, i * 8) buf.unmap() # Download from buffer to CPU @@ -187,7 +187,7 @@ def test_consecutive_writes2(): # Also in parts for i in range(4): data = device.queue.read_buffer(buf, i * 8, size=8) - assert data == f"{i+1}".encode() * 8 + assert data == f"{i + 1}".encode() * 8 @mark.skipif(not can_use_wgpu_lib, reason="Needs wgpu lib") @@ -221,20 +221,20 @@ def test_consecutive_reads(): # Write using the queue. Do in parts, to touch those offsets too for i in range(4): - device.queue.write_buffer(buf, i * 8, f"{i+1}".encode() * 8) + device.queue.write_buffer(buf, i * 8, f"{i + 1}".encode() * 8) # Read in parts, the inefficient way for i in range(4): buf.map_sync("read") data = buf.read_mapped(i * 8, 8) - assert data == f"{i+1}".encode() * 8 + assert data == f"{i + 1}".encode() * 8 buf.unmap() # Read in parts, the efficient way buf.map_sync("read") for i in range(4): data = buf.read_mapped(i * 8, 8) - assert data == f"{i+1}".encode() * 8 + assert data == f"{i + 1}".encode() * 8 buf.unmap() @@ -549,9 +549,14 @@ def test_create_buffer_with_data(size): @pytest.mark.skip -def test_show_bug_wgpu_native_305_still_not_fixed(): - # When this bug is fixed, we can remove READ_NOSYNC, and just tread "READ" as if - # it were READ_NOSYNC. No need to handle the command buffer. +def test_that_passes_when_bug_wgpu_native_305_is_fixed(): + # See https://github.com/gfx-rs/wgpu-native/issues/305 + # If the bug is still there, this test will fail. Therefore its skipped. + # If this test passes (on multiple machines) the bug is likely fixed. + # When this bug is fixed, we can remove the command-buffer trick in _api.py, + # and enable this test to detect regressions. + + # Update device = wgpu.utils.get_default_device() data1 = b"abcdefghijkl" diff --git a/tests/test_wgpu_native_errors.py b/tests/test_wgpu_native_errors.py index 15006d77..90447787 100644 --- a/tests/test_wgpu_native_errors.py +++ b/tests/test_wgpu_native_errors.py @@ -67,14 +67,14 @@ def test_parse_shader_error2(caplog): Caused by: In wgpuDeviceCreateShaderModule - Shader '' parsing error: expected ',', found ';' + Shader '' parsing error: expected `,`, found ";" ┌─ wgsl:2:38 │ 2 │ @location(0) texcoord : vec2; - │ ^ expected ',' + │ ^ expected `,` - expected ',', found ';' + expected `,`, found ";" """ code = dedent(code) @@ -103,16 +103,14 @@ def test_parse_shader_error3(caplog): Caused by: In wgpuDeviceCreateShaderModule - Shader '' parsing error: unknown scalar type: 'f3' + Shader '' parsing error: unknown type: `f3` ┌─ wgsl:3:39 │ 3 │ @builtin(position) position: vec4, - │ ^^ unknown scalar type - │ - = note: Valid scalar types are f32, f64, i32, u32, bool + │ ^^ unknown type - unknown scalar type: 'f3' + unknown type: `f3` """ code = dedent(code) @@ -183,16 +181,19 @@ def test_validate_shader_error1(caplog): Caused by: In wgpuDeviceCreateShaderModule - Shader validation error: + Shader validation error: Entry point vs_main at Vertex is invalid ┌─ :10:20 │ 10 │ out.position = matrics * out.position; │ ^^^^^^^^^^^^^^^^^^^^^^ naga::Expression [7] + │ + = Expression [7] is invalid + = Operation Multiply can't work with [4] (of type Matrix { columns: Quad, rows: Quad, scalar: Scalar { kind: Float, width: 4 } }) and [6] (of type Vector { size: Tri, scalar: Scalar { kind: Float, width: 4 } }) Entry point vs_main at Vertex is invalid Expression [7] is invalid - Operation Multiply can't work with [4] and [6] + Operation Multiply can't work with [4] (of type Matrix { columns: Quad, rows: Quad, scalar: Scalar { kind: Float, width: 4 } }) and [6] (of type Vector { size: Tri, scalar: Scalar { kind: Float, width: 4 } }) """ code = dedent(code) @@ -233,11 +234,13 @@ def test_validate_shader_error2(caplog): Caused by: In wgpuDeviceCreateShaderModule - Shader validation error: + Shader validation error: Entry point fs_main at Vertex is invalid ┌─ :9:16 │ 9 │ return vec3(1.0, 0.0, 1.0); │ ^^^^^^^^^^^^^^^^^^^^^^^^ naga::Expression [8] + │ + = The `return` value Some([8]) does not match the function return value Entry point fs_main at Vertex is invalid diff --git a/tests/test_wgpu_vertex_instance.py b/tests/test_wgpu_vertex_instance.py index 518060c9..b2eaf453 100644 --- a/tests/test_wgpu_vertex_instance.py +++ b/tests/test_wgpu_vertex_instance.py @@ -8,9 +8,11 @@ from wgpu.backends.wgpu_native.extras import ( multi_draw_indexed_indirect, multi_draw_indirect, + multi_draw_indirect_count, + multi_draw_indexed_indirect_count, ) -MAX_INFO = 100 +MAX_INFO = 1000 if not can_use_wgpu_lib: pytest.skip("Skipping tests that need the wgpu lib", allow_module_level=True) @@ -68,7 +70,7 @@ class Runner: REQUIRED_FEATURES = ["indirect-first-instance"] - OPTIONAL_FEATURES = ["multi-draw-indirect"] # we'll be adding more + OPTIONAL_FEATURES = ["multi-draw-indirect", "multi-draw-indirect-count"] @classmethod def is_usable(cls): @@ -163,11 +165,39 @@ def __init__(self): # We're going to want to try calling these draw functions from a buffer, and it # would be nice to test that these buffers have an offset self.draw_data_buffer = self.device.create_buffer_with_data( - data=np.uint32([0, 0, *self.draw_args1, *self.draw_args2]), - usage="INDIRECT", + # The zeros at the beginning are to test "offset". + # The zeros at the end are because the _count methods require to buffer to + # be at least byte_offset + 16 * max_count bytes long + data=np.uint32([0, 0, *self.draw_args1, *self.draw_args2, *([0] * 50)]), + usage="INDIRECT", # copy dst for patching ) self.draw_data_buffer_indexed = self.device.create_buffer_with_data( - data=np.uint32([0, 0, *self.draw_indexed_args1, *self.draw_indexed_args2]), + # The zeros at the beginning are to test "offset". + # The zeros at the end are because the _count methods require to buffer to + # be at least byte_offset + 20 * max_count bytes long + data=np.uint32( + [0, 0, *self.draw_indexed_args1, *self.draw_indexed_args2, *([0] * 50)] + ), + usage="INDIRECT", + ) + + self.count_buffer = self.device.create_buffer_with_data( + data=(np.int32([10, 2])), usage="INDIRECT" + ) + self.draw_data_buffer_patched = self.device.create_buffer_with_data( + # The zeros at the beginning are to test the "offset". + # The zeros at the end are because the _count methods require to buffer to + # be at least byte_offset + 16 * max_count bytes long + data=np.uint32([10, 2, *self.draw_args1, *self.draw_args2, *([0] * 50)]), + usage="INDIRECT", # copy dst for patching + ) + self.draw_data_buffer_indexed_patched = self.device.create_buffer_with_data( + # The zeros at the beginning are to test "offset". + # The zeros at the end are because the _count methods require to buffer to + # be at least byte_offset + 20 * max_count bytes long + data=np.uint32( + [10, 2, *self.draw_indexed_args1, *self.draw_indexed_args2, *([0] * 50)] + ), usage="INDIRECT", ) @@ -211,7 +241,8 @@ def run_draw_test(self, draw_function, indexed, *, expected_result=None): expected_result = self.expected_result_draw_indexed else: expected_result = self.expected_result_draw - assert info_set == expected_result + if info_set != expected_result: + pytest.fail(f"Expected {sorted(expected_result)}\nGot {sorted(info_set)}") if not Runner.is_usable(): @@ -337,5 +368,41 @@ def draw(encoder): ) +@pytest.mark.parametrize("indexed", [False, True]) +@pytest.mark.parametrize("test_max_count", [False, True]) +def test_multi_draw_indirect_count(runner, test_max_count, indexed): + if "multi-draw-indirect-count" not in runner.device.features: + pytest.skip("Must have 'multi-draw-indirect-count' to run") + + if indexed: + function = multi_draw_indexed_indirect_count + buffer = runner.draw_data_buffer_indexed + else: + function = multi_draw_indirect_count + buffer = runner.draw_data_buffer + + # Either way, we're going to do 2 draws. But one via the max_count and one via the + # information in the buffer. + if test_max_count: + # We pull a count of 10, but we're limiting it to 2 via max_count + count_buffer_offset, max_count = 0, 2 + else: + # We pull a count of 2, and set the max_count to something bigger. Buffer + # is required to be big enough to handle max_count. + count_buffer_offset, max_count = 4, 10 + + def draw(encoder): + function( + encoder, + buffer, + offset=8, + count_buffer=runner.count_buffer, + count_buffer_offset=count_buffer_offset, + max_count=max_count, + ) + + runner.run_draw_test(draw, indexed) + + if __name__ == "__main__": run_tests(globals()) diff --git a/tests_mem/test_gui.py b/tests_mem/test_gui.py index 881da9fd..e85cc8c4 100644 --- a/tests_mem/test_gui.py +++ b/tests_mem/test_gui.py @@ -61,7 +61,7 @@ def test_release_canvas_context(n): "expected_counts_after_create": { "CanvasContext": (n, 0), }, - "ignore": {"CommandBuffer"}, + "ignore": {"CommandBuffer", "Buffer"}, } canvases = weakref.WeakSet() diff --git a/tests_mem/test_objects.py b/tests_mem/test_objects.py index 5a53a8cb..94303bbc 100644 --- a/tests_mem/test_objects.py +++ b/tests_mem/test_objects.py @@ -103,7 +103,8 @@ def test_release_buffer(n): @create_and_release def test_release_command_buffer(n): - # Note: a command encoder can only be used once (it gets destroyed on finish()) + # Note: a command encoder can only be used once (it gets destroyed on finish()), see test below. + # Finishing returns a command buffer, which gets destroyed on submit() to the queue. yield { "expected_counts_after_create": { "CommandBuffer": (n, n), @@ -112,7 +113,10 @@ def test_release_command_buffer(n): for i in range(n): command_encoder = DEVICE.create_command_encoder() - yield command_encoder.finish() + command_buffer = command_encoder.finish() + yield command_buffer + # to destroy the command buffer we submit it + DEVICE.queue.submit([command_buffer]) @create_and_release @@ -374,6 +378,20 @@ def test_release_texture_view(n): yield texture.create_view() +@create_and_release +def test_release_pipeline_cache(n): + # not implemented in wgpu-native yet + # part of CreateRenderPipeline and CreateComputePipeline + # https://github.com/gfx-rs/wgpu-native/blob/v24.0.0.1/src/lib.rs#L1988 + # https://github.com/gfx-rs/wgpu-native/blob/v24.0.0.1/src/lib.rs#L2292 + yield { + "expected_counts_after_create": { + "PipelineCache": (n, 0), + }, + } + pytest.skip("Not implemented in wgpu-native") + + # %% The end diff --git a/tests_mem/testutils.py b/tests_mem/testutils.py index 8683b2aa..da53373c 100644 --- a/tests_mem/testutils.py +++ b/tests_mem/testutils.py @@ -256,7 +256,9 @@ def core_test_func(): print(" more after release:", more3) # Check! - assert more3 == options["expected_counts_after_release"] + assert ( + more3 == options["expected_counts_after_release"] + ), f"Expected:\n{options['expected_counts_after_release']}\nGot:\n{more3}" # Print mem usage info if TEST_ITERS: diff --git a/tools/build_all_wheels.py b/tools/build_all_wheels.py index 8bd0328d..f08da689 100644 --- a/tools/build_all_wheels.py +++ b/tools/build_all_wheels.py @@ -104,14 +104,14 @@ # Simple check for sdist archive for archive_name in found_others: size = os.stat("dist/" + archive_name).st_size - print(f"{archive_name} ({size/1e6:0.2f} MB)") + print(f"{archive_name} ({size / 1e6:0.2f} MB)") assert size < 1e6, f"Did not expected {archive_name} to be this large" # Collect content of each wheel hash_to_file = {} for archive_name in found_wheels: size = os.stat("dist/" + archive_name).st_size - print(f"{archive_name} ({size/1e6:0.2f} MB)") + print(f"{archive_name} ({size / 1e6:0.2f} MB)") z = zipfile.ZipFile("dist/" + archive_name) flat_map = {os.path.basename(fi.filename): fi.filename for fi in z.filelist} lib_hashes = [] @@ -120,7 +120,7 @@ bb = z.read(flat_map[fname]) hash = hashlib.sha256(bb).hexdigest() lib_hashes.append(hash) - print(f" - {fname} ({len(bb)/1e6:0.2f} MB)\n {hash}") + print(f" - {fname} ({len(bb) / 1e6:0.2f} MB)\n {hash}") assert ( len(lib_hashes) == 1 ), f"Expected 1 lib per wheel, got {len(lib_hashes)} in {archive_name}" diff --git a/tools/download_wgpu_native.py b/tools/download_wgpu_native.py index dfc17c00..abb32b57 100644 --- a/tools/download_wgpu_native.py +++ b/tools/download_wgpu_native.py @@ -6,7 +6,9 @@ import platform from zipfile import ZipFile -import requests +# Import requests unless doing a noarch build +if os.getenv("WGPU_PY_BUILD_NOARCH", "").lower() not in ("1", "true"): + import requests DEFAULT_UPSTREAM = "gfx-rs/wgpu-native" diff --git a/tools/hatch_build.py b/tools/hatch_build.py index 0925d67d..2483bccf 100644 --- a/tools/hatch_build.py +++ b/tools/hatch_build.py @@ -42,8 +42,11 @@ def initialize(self, version, build_data): # We only do our thing when this is a wheel build from the repo. # If this is an sdist build, or a wheel build from an sdist, # we go pure-Python mode, and expect the user to set WGPU_LIB_PATH. + # We also allow building an arch-agnostic wheel explicitly, using an env var. - if self.target_name == "wheel" and is_git_repo(): + if os.getenv("WGPU_PY_BUILD_NOARCH", "").lower() in ("1", "true"): + pass # Explicitly disable including the lib + elif self.target_name == "wheel" and is_git_repo(): # Prepare check_git_status() remove_all_libs() diff --git a/wgpu/_classes.py b/wgpu/_classes.py index b7032135..3be506ff 100644 --- a/wgpu/_classes.py +++ b/wgpu/_classes.py @@ -87,11 +87,12 @@ class GPU: a backend-specific implementation. """ - # IDL: Promise requestAdapter(optional GPURequestAdapterOptions options = {}); -> GPUPowerPreference powerPreference, boolean forceFallbackAdapter = false + # IDL: Promise requestAdapter(optional GPURequestAdapterOptions options = {}); -> DOMString featureLevel = "core", GPUPowerPreference powerPreference, boolean forceFallbackAdapter = false, boolean xrCompatible = false @apidiff.change("arguments include canvas") def request_adapter_sync( self, *, + feaure_level: str = "core", power_preference: enums.PowerPreference = None, force_fallback_adapter: bool = False, canvas=None, @@ -109,11 +110,12 @@ def request_adapter_sync( canvas=canvas, ) - # IDL: Promise requestAdapter(optional GPURequestAdapterOptions options = {}); -> GPUPowerPreference powerPreference, boolean forceFallbackAdapter = false + # IDL: Promise requestAdapter(optional GPURequestAdapterOptions options = {}); -> DOMString featureLevel = "core", GPUPowerPreference powerPreference, boolean forceFallbackAdapter = false, boolean xrCompatible = false @apidiff.change("arguments include canvas") async def request_adapter_async( self, *, + feaure_level: str = "core", power_preference: enums.PowerPreference = None, force_fallback_adapter: bool = False, canvas=None, @@ -122,6 +124,8 @@ async def request_adapter_async( implementation, from which one can request a `GPUDevice`. Arguments: + feaure_level (str): The feature level "core" (default) or "compatibility". + This provides a way to opt into additional validation restrictions. power_preference (PowerPreference): "high-performance" or "low-power". force_fallback_adapter (bool): whether to use a (probably CPU-based) fallback adapter. @@ -272,6 +276,11 @@ def get_preferred_format(self, adapter): formats = capabilities["formats"] return formats[0] if formats else "bgra8-unorm" + # IDL: GPUCanvasConfiguration? getConfiguration(); + def get_configuration(self): + """Get the current configuration (or None if the context is not yet configured).""" + return self._config + # IDL: undefined configure(GPUCanvasConfiguration configuration); -> required GPUDevice device, required GPUTextureFormat format, GPUTextureUsageFlags usage = 0x10, sequence viewFormats = [], PredefinedColorSpace colorSpace = "srgb", GPUCanvasToneMapping toneMapping = {}, GPUCanvasAlphaMode alphaMode = "opaque" def configure( self, @@ -418,9 +427,11 @@ def _create_texture_bitmap(self): width, height = canvas.get_physical_size() width, height = max(width, 1), max(height, 1) + # Note that the label 'present' is used by read_texture() to determine + # that it can use a shared copy buffer. device = self._config["device"] self._texture = device.create_texture( - label="presentation-context", + label="present", size=(width, height, 1), format=self._config["format"], usage=self._config["usage"] | flags.TextureUsage.COPY_SRC, @@ -536,6 +547,18 @@ def description(self): """A textual description of the adapter.""" return self._info["description"] + # IDL: readonly attribute unsigned long subgroupMinSize; + @property + def subgroup_min_size(self): + """If the "subgroups" feature is supported, the minimum supported subgroup size for the adapter.""" + return self._info.get("subgroup_min_size", None) + + # IDL: readonly attribute unsigned long subgroupMaxSize; + @property + def subgroup_max_size(self): + """If the "subgroups" feature is supported, the maximum supported subgroup size for the adapter.""" + return self._info.get("subgroup_max_size", None) + class GPUAdapter: """Represents an abstract wgpu implementation. @@ -577,13 +600,13 @@ def limits(self): """A dict with limits for the adapter.""" return self._limits - # IDL: Promise requestDevice(optional GPUDeviceDescriptor descriptor = {}); -> USVString label = "", sequence requiredFeatures = [], record requiredLimits = {}, GPUQueueDescriptor defaultQueue = {} + # IDL: Promise requestDevice(optional GPUDeviceDescriptor descriptor = {}); -> USVString label = "", sequence requiredFeatures = [], record requiredLimits = {}, GPUQueueDescriptor defaultQueue = {} def request_device_sync( self, *, label: str = "", required_features: List[enums.FeatureName] = [], - required_limits: Dict[str, int] = {}, + required_limits: Dict[str, Union[None, int]] = {}, default_queue: structs.QueueDescriptor = {}, ): """Sync version of `request_device_async()`. @@ -592,13 +615,13 @@ def request_device_sync( """ raise NotImplementedError() - # IDL: Promise requestDevice(optional GPUDeviceDescriptor descriptor = {}); -> USVString label = "", sequence requiredFeatures = [], record requiredLimits = {}, GPUQueueDescriptor defaultQueue = {} + # IDL: Promise requestDevice(optional GPUDeviceDescriptor descriptor = {}); -> USVString label = "", sequence requiredFeatures = [], record requiredLimits = {}, GPUQueueDescriptor defaultQueue = {} async def request_device_async( self, *, label: str = "", required_features: List[enums.FeatureName] = [], - required_limits: Dict[str, int] = {}, + required_limits: Dict[str, Union[None, int]] = {}, default_queue: structs.QueueDescriptor = {}, ): """Request a `GPUDevice` from the adapter. @@ -723,6 +746,12 @@ def queue(self): """The default `GPUQueue` for this device.""" return self._queue + # IDL: [SameObject] readonly attribute GPUAdapterInfo adapterInfo; + @property + def adapter_info(self): + """The adapter.info dict.""" + return self._adapter.info + @apidiff.add("Too useful to not-have") @property def adapter(self): @@ -990,7 +1019,7 @@ def create_bind_group( """ raise NotImplementedError() - # IDL: GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor); -> USVString label = "", required sequence bindGroupLayouts + # IDL: GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor); -> USVString label = "", required sequence bindGroupLayouts def create_pipeline_layout( self, *, label: str = "", bind_group_layouts: List[GPUBindGroupLayout] ): @@ -1003,13 +1032,12 @@ def create_pipeline_layout( """ raise NotImplementedError() - # IDL: GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor); -> USVString label = "", required USVString code, object sourceMap, sequence compilationHints = [] + # IDL: GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor); -> USVString label = "", required USVString code, sequence compilationHints = [] def create_shader_module( self, *, label: str = "", code: str, - source_map: dict = optional, compilation_hints: List[structs.ShaderModuleCompilationHint] = [], ): """Create a `GPUShaderModule` object from shader source. @@ -1024,6 +1052,7 @@ def create_shader_module( 'comp', 'vert' or 'frag'. For SpirV the code must be bytes. compilation_hints: currently unused. """ + # Noe: compilation_hints has been removed: https://github.com/webgpu-native/webgpu-headers/pull/337 raise NotImplementedError() # IDL: GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor); -> USVString label = "", required (GPUPipelineLayout or GPUAutoLayoutMode) layout, required GPUProgrammableStage compute @@ -1549,13 +1578,14 @@ def usage(self): """The allowed usages for this texture.""" return self._tex_info["usage"] - # IDL: GPUTextureView createView(optional GPUTextureViewDescriptor descriptor = {}); -> USVString label = "", GPUTextureFormat format, GPUTextureViewDimension dimension, GPUTextureAspect aspect = "all", GPUIntegerCoordinate baseMipLevel = 0, GPUIntegerCoordinate mipLevelCount, GPUIntegerCoordinate baseArrayLayer = 0, GPUIntegerCoordinate arrayLayerCount + # IDL: GPUTextureView createView(optional GPUTextureViewDescriptor descriptor = {}); -> USVString label = "", GPUTextureFormat format, GPUTextureViewDimension dimension, GPUTextureUsageFlags usage = 0, GPUTextureAspect aspect = "all", GPUIntegerCoordinate baseMipLevel = 0, GPUIntegerCoordinate mipLevelCount, GPUIntegerCoordinate baseArrayLayer = 0, GPUIntegerCoordinate arrayLayerCount def create_view( self, *, label: str = "", format: enums.TextureFormat = optional, dimension: enums.TextureViewDimension = optional, + usage: flags.TextureUsage = 0, aspect: enums.TextureAspect = "all", base_mip_level: int = 0, mip_level_count: int = optional, @@ -1571,6 +1601,9 @@ def create_view( label (str): A human-readable label. Optional. format (enums.TextureFormat): What channels it stores and how. dimension (enums.TextureViewDimension): The dimensionality of the texture view. + usage (enums.TextureUsage): The allowed usage(s) for the texture view. + Must be a subset of the usage flags of the texture. + If 0, defaults to the full set of usage flags of the texture. aspect (enums.TextureAspect): Whether this view is used for depth, stencil, or all. Default all. base_mip_level (int): The starting mip level. Default 0. @@ -1970,11 +2003,11 @@ def copy_buffer_to_buffer( """ raise NotImplementedError() - # IDL: undefined copyBufferToTexture( GPUImageCopyBuffer source, GPUImageCopyTexture destination, GPUExtent3D copySize); + # IDL: undefined copyBufferToTexture( GPUTexelCopyBufferInfo source, GPUTexelCopyTextureInfo destination, GPUExtent3D copySize); def copy_buffer_to_texture( self, - source: structs.ImageCopyBuffer, - destination: structs.ImageCopyTexture, + source: structs.TexelCopyBufferInfo, + destination: structs.TexelCopyTextureInfo, copy_size: Union[List[int], structs.Extent3D], ): """Copy the contents of a buffer to a texture (view). @@ -1988,11 +2021,11 @@ def copy_buffer_to_texture( """ raise NotImplementedError() - # IDL: undefined copyTextureToBuffer( GPUImageCopyTexture source, GPUImageCopyBuffer destination, GPUExtent3D copySize); + # IDL: undefined copyTextureToBuffer( GPUTexelCopyTextureInfo source, GPUTexelCopyBufferInfo destination, GPUExtent3D copySize); def copy_texture_to_buffer( self, - source: structs.ImageCopyTexture, - destination: structs.ImageCopyBuffer, + source: structs.TexelCopyTextureInfo, + destination: structs.TexelCopyBufferInfo, copy_size: Union[List[int], structs.Extent3D], ): """Copy the contents of a texture (view) to a buffer. @@ -2006,11 +2039,11 @@ def copy_texture_to_buffer( """ raise NotImplementedError() - # IDL: undefined copyTextureToTexture( GPUImageCopyTexture source, GPUImageCopyTexture destination, GPUExtent3D copySize); + # IDL: undefined copyTextureToTexture( GPUTexelCopyTextureInfo source, GPUTexelCopyTextureInfo destination, GPUExtent3D copySize); def copy_texture_to_texture( self, - source: structs.ImageCopyTexture, - destination: structs.ImageCopyTexture, + source: structs.TexelCopyTextureInfo, + destination: structs.TexelCopyTextureInfo, copy_size: Union[List[int], structs.Extent3D], ): """Copy the contents of a texture (view) to another texture (view). @@ -2297,12 +2330,12 @@ def read_buffer(self, buffer, buffer_offset=0, size=None): """ raise NotImplementedError() - # IDL: undefined writeTexture( GPUImageCopyTexture destination, AllowSharedBufferSource data, GPUImageDataLayout dataLayout, GPUExtent3D size); + # IDL: undefined writeTexture( GPUTexelCopyTextureInfo destination, AllowSharedBufferSource data, GPUTexelCopyBufferLayout dataLayout, GPUExtent3D size); def write_texture( self, - destination: structs.ImageCopyTexture, + destination: structs.TexelCopyTextureInfo, data: memoryview, - data_layout: structs.ImageDataLayout, + data_layout: structs.TexelCopyBufferLayout, size: Union[List[int], structs.Extent3D], ): """Takes the data contents and schedules a write operation of @@ -2344,12 +2377,12 @@ def read_texture(self, source, data_layout, size): """ raise NotImplementedError() - # IDL: undefined copyExternalImageToTexture( GPUImageCopyExternalImage source, GPUImageCopyTextureTagged destination, GPUExtent3D copySize); + # IDL: undefined copyExternalImageToTexture( GPUCopyExternalImageSourceInfo source, GPUCopyExternalImageDestInfo destination, GPUExtent3D copySize); @apidiff.hide("Specific to browsers") def copy_external_image_to_texture( self, - source: structs.ImageCopyExternalImage, - destination: structs.ImageCopyTextureTagged, + source: structs.CopyExternalImageSourceInfo, + destination: structs.CopyExternalImageDestInfo, copy_size: Union[List[int], structs.Extent3D], ): raise NotImplementedError() diff --git a/wgpu/_coreutils.py b/wgpu/_coreutils.py index 27b1723f..b25536ac 100644 --- a/wgpu/_coreutils.py +++ b/wgpu/_coreutils.py @@ -9,6 +9,7 @@ import logging import importlib.resources from contextlib import ExitStack +from pathlib import Path # Our resources are most probably always on the file system. But in @@ -17,15 +18,52 @@ atexit.register(_resource_files.close) -def get_resource_filename(name): - """Get the filename to a wgpu resource.""" - if sys.version_info < (3, 9): - context = importlib.resources.path("wgpu.resources", name) - else: - ref = importlib.resources.files("wgpu.resources") / name - context = importlib.resources.as_file(ref) +def get_header_filename(name): + """Get the filename to a wgpu related header resource.""" + ref = importlib.resources.files("wgpu.resources") / name + context = importlib.resources.as_file(ref) path = _resource_files.enter_context(context) - return str(path) + if path.exists(): + return str(path) + + # conda or system based installations may have the headers in other + # locations + path = Path(sys.exec_prefix) / "include" / name + if path.exists(): + return str(path) + + # Windows conda file layout is slightly different and includes a + # Library before the include directory + path = Path(sys.exec_prefix) / "Library" / "include" / name + if path.exists(): + return str(path) + + raise RuntimeError(f"Could not find the requested header file {name}.") + + +def get_library_filename(name): + """Get the filename to a wgpu related library resource.""" + ref = importlib.resources.files("wgpu.resources") / name + context = importlib.resources.as_file(ref) + path = _resource_files.enter_context(context) + if path.exists(): + return str(path) + + # conda or system based installations may have the headers in other + # locations + # Question for other linux distributions, how can we detect if we should + # be using `lib` or `lib64`???? + path = Path(sys.exec_prefix) / "lib" / name + if path.exists(): + return str(path) + + # Windows conda file layout is slightly different and includes a + # Library before the include directory + path = Path(sys.exec_prefix) / "Library" / "bin" / name + if path.exists(): + return str(path) + + raise RuntimeError(f"Could not find the requested header file {name}.") class WGPULogger(logging.getLoggerClass()): diff --git a/wgpu/_version.py b/wgpu/_version.py index e5002df6..642f9dae 100644 --- a/wgpu/_version.py +++ b/wgpu/_version.py @@ -10,7 +10,7 @@ # This is the reference version number, to be bumped before each release. # The build system detects this definition when building a distribution. -__version__ = "0.19.3" +__version__ = "0.21.0" # Allow using nearly the same code in different projects project_name = "wgpu" diff --git a/wgpu/backends/wgpu_native/__init__.py b/wgpu/backends/wgpu_native/__init__.py index dc9116de..fd537f00 100644 --- a/wgpu/backends/wgpu_native/__init__.py +++ b/wgpu/backends/wgpu_native/__init__.py @@ -11,8 +11,8 @@ # The wgpu-native version that we target/expect -__version__ = "22.1.0.5" -__commit_sha__ = "fad19f5990d8eb9a6e942eb957344957193fe66d" +__version__ = "24.0.0.2" +__commit_sha__ = "a96fbecc2ef8f7fdf0bd1762b88508799471c923" version_info = tuple(map(int, __version__.split("."))) _check_expected_version(version_info) # produces a warning on mismatch diff --git a/wgpu/backends/wgpu_native/_api.py b/wgpu/backends/wgpu_native/_api.py index 4b2177ba..1dfe17b5 100644 --- a/wgpu/backends/wgpu_native/_api.py +++ b/wgpu/backends/wgpu_native/_api.py @@ -18,6 +18,7 @@ from __future__ import annotations import os +import time import logging from weakref import WeakKeyDictionary from typing import List, Dict, Union, Optional, NoReturn @@ -77,6 +78,8 @@ def print_struct(s, indent=""): print(indent + key + ": null") elif "'char *'" in repr(val): print(indent + key + ":", ffi.string(val).decode()) + elif "WGPUStringView" in repr(val): + print(indent + key + ":", from_c_string_view(val)) elif " *'" in repr(val): print(indent + key + ": pointer") elif "struct WGPU" in repr(val): @@ -232,12 +235,12 @@ def _get_override_constant_entries(field): for key, value in constants.items(): assert isinstance(key, (str, int)) assert isinstance(value, (int, float, bool)) - # H: nextInChain: WGPUChainedStruct *, key: char *, value: float + # H: nextInChain: WGPUChainedStruct *, key: WGPUStringView, value: float c_constant_entry = new_struct( "WGPUConstantEntry", - key=to_c_string(str(key)), - value=float(value), # not used: nextInChain + key=to_c_string_view(str(key)), + value=float(value), ) c_constant_entries.append(c_constant_entry) # We need to return and hold onto c_constant_entries in order to prevent the C @@ -246,23 +249,51 @@ def _get_override_constant_entries(field): return c_constants, c_constant_entries -def to_c_string(string: str): - return ffi.new("char []", string.encode()) - - -def to_c_string_or_null(string: Optional[str]): - return ffi.NULL if string is None else ffi.new("char []", string.encode()) - - -_empty_label = ffi.new("char []", b"") +# H: data: char *, length: int +_null_string = new_struct( + "WGPUStringView", + data=ffi.NULL, + length=lib.WGPU_STRLEN, +) +# H: data: char *, length: int +_empty_string = new_struct( + "WGPUStringView", + data=ffi.NULL, + length=0, +) -def to_c_label(label): - """Get the C representation of a label.""" - if not label: - return _empty_label +def to_c_string_view(string: str): + """Turn a string into a "WGPUStringView. None becomes the null-string.""" + if string is None: + # The null-string. wgpu-core interprets this different from the empty sting, + # e.g. when not-setting the trace path, it should be the null-string. + return _null_string + elif not string: + # The empty string + return _empty_string + else: + # A string with nonzero length + data = ffi.new("char []", string.encode()) # includes null terminator! + # length = len(data) - 1 # explicit length (minus null terminator) + length = lib.WGPU_STRLEN # Zero-terminated string + # H: data: char *, length: int + return new_struct( + "WGPUStringView", + data=data, + length=length, + ) + + +def from_c_string_view(struct): + if not struct or struct.data == ffi.NULL or struct.length == 0: + return "" + elif struct.length == lib.WGPU_STRLEN: + # null-terminated + return ffi.string(struct.data).decode(errors="ignore") else: - return to_c_string(label) + # explicit length + return ffi.string(struct.data, struct.length).decode(errors="ignore") def feature_flag_to_feature_names(flag): @@ -288,30 +319,70 @@ def _get_limits(id: int, device: bool = False, adapter: bool = False): """Gets the limits for a device or an adapter""" assert device + adapter == 1 # exactly one is set - # H: chain: WGPUChainedStructOut, limits: WGPUNativeLimits - c_supported_limits_extras = new_struct_p( - "WGPUSupportedLimitsExtras *", - # not used: chain - # not used: limits + # H: chain: WGPUChainedStructOut, maxPushConstantSize: int, maxNonSamplerBindings: int + c_limits_native = new_struct( + "WGPUNativeLimits", + # H: next: WGPUChainedStructOut *, sType: WGPUSType + chain=new_struct( + "WGPUChainedStructOut", + # not used: next + sType=lib.WGPUSType_NativeLimits, + ), + # not used: maxPushConstantSize + # not used: maxNonSamplerBindings ) - c_supported_limits_extras.chain.sType = lib.WGPUSType_SupportedLimitsExtras - # H: nextInChain: WGPUChainedStructOut *, limits: WGPULimits - c_supported_limits = new_struct_p( - "WGPUSupportedLimits *", - nextInChain=ffi.cast("WGPUChainedStructOut *", c_supported_limits_extras), - # not used: limits + # H: nextInChain: WGPUChainedStructOut *, maxTextureDimension1D: int, maxTextureDimension2D: int, maxTextureDimension3D: int, maxTextureArrayLayers: int, maxBindGroups: int, maxBindGroupsPlusVertexBuffers: int, maxBindingsPerBindGroup: int, maxDynamicUniformBuffersPerPipelineLayout: int, maxDynamicStorageBuffersPerPipelineLayout: int, maxSampledTexturesPerShaderStage: int, maxSamplersPerShaderStage: int, maxStorageBuffersPerShaderStage: int, maxStorageTexturesPerShaderStage: int, maxUniformBuffersPerShaderStage: int, maxUniformBufferBindingSize: int, maxStorageBufferBindingSize: int, minUniformBufferOffsetAlignment: int, minStorageBufferOffsetAlignment: int, maxVertexBuffers: int, maxBufferSize: int, maxVertexAttributes: int, maxVertexBufferArrayStride: int, maxInterStageShaderVariables: int, maxColorAttachments: int, maxColorAttachmentBytesPerSample: int, maxComputeWorkgroupStorageSize: int, maxComputeInvocationsPerWorkgroup: int, maxComputeWorkgroupSizeX: int, maxComputeWorkgroupSizeY: int, maxComputeWorkgroupSizeZ: int, maxComputeWorkgroupsPerDimension: int + c_limits = new_struct_p( + "WGPULimits *", + nextInChain=ffi.addressof(c_limits_native, "chain"), + # not used: maxTextureDimension1D + # not used: maxTextureDimension2D + # not used: maxTextureDimension3D + # not used: maxTextureArrayLayers + # not used: maxBindGroups + # not used: maxBindGroupsPlusVertexBuffers + # not used: maxBindingsPerBindGroup + # not used: maxDynamicUniformBuffersPerPipelineLayout + # not used: maxDynamicStorageBuffersPerPipelineLayout + # not used: maxSampledTexturesPerShaderStage + # not used: maxSamplersPerShaderStage + # not used: maxStorageBuffersPerShaderStage + # not used: maxStorageTexturesPerShaderStage + # not used: maxUniformBuffersPerShaderStage + # not used: maxUniformBufferBindingSize + # not used: maxStorageBufferBindingSize + # not used: minUniformBufferOffsetAlignment + # not used: minStorageBufferOffsetAlignment + # not used: maxVertexBuffers + # not used: maxBufferSize + # not used: maxVertexAttributes + # not used: maxVertexBufferArrayStride + # not used: maxInterStageShaderVariables + # not used: maxColorAttachments + # not used: maxColorAttachmentBytesPerSample + # not used: maxComputeWorkgroupStorageSize + # not used: maxComputeInvocationsPerWorkgroup + # not used: maxComputeWorkgroupSizeX + # not used: maxComputeWorkgroupSizeY + # not used: maxComputeWorkgroupSizeZ + # not used: maxComputeWorkgroupsPerDimension ) if adapter: - # H: WGPUBool f(WGPUAdapter adapter, WGPUSupportedLimits * limits) - libf.wgpuAdapterGetLimits(id, c_supported_limits) + # H: WGPUStatus f(WGPUAdapter adapter, WGPULimits * limits) + status = libf.wgpuAdapterGetLimits(id, c_limits) + if status != lib.WGPUStatus_Success: + raise RuntimeError("Error calling wgpuAdapterGetLimits") else: - # H: WGPUBool f(WGPUDevice device, WGPUSupportedLimits * limits) - libf.wgpuDeviceGetLimits(id, c_supported_limits) + # H: WGPUStatus f(WGPUDevice device, WGPULimits * limits) + status = libf.wgpuDeviceGetLimits(id, c_limits) + if status != lib.WGPUStatus_Success: + raise RuntimeError("Error calling wgpuDeviceGetLimits") key_value_pairs = [ - (to_snake_case(name, "-"), getattr(c_limits, name)) - for c_limits in (c_supported_limits.limits, c_supported_limits_extras.limits) - for name in dir(c_limits) + (to_snake_case(name, "-"), getattr(limits, name)) + for limits in (c_limits, c_limits_native) + for name in dir(limits) + if "chain" not in name.lower() # Skip the pointers ] limits = dict(sorted(key_value_pairs)) return limits @@ -331,13 +402,10 @@ def _get_features(id: int, device: bool = False, adapter: bool = False): features = set() # Standard features + not_supported_by_wgpu_native = {"subgroups"} for f in sorted(enums.FeatureName): - if f in [ - "clip-distances", - "dual-source-blending", - "texture-compression-bc-sliced-3d", - ]: - continue # not supported by wgpu-native yet + if f in not_supported_by_wgpu_native: + continue if has_feature(enummap[f"FeatureName.{f}"]): features.add(f) @@ -359,6 +427,7 @@ class GPU(classes.GPU): def request_adapter_sync( self, *, + feaure_level: str = "core", power_preference: enums.PowerPreference = None, force_fallback_adapter: bool = False, canvas=None, @@ -368,6 +437,7 @@ def request_adapter_sync( """ check_can_use_sync_variants() awaitable = self._request_adapter( + feaure_level=feaure_level, power_preference=power_preference, force_fallback_adapter=force_fallback_adapter, canvas=canvas, @@ -378,6 +448,7 @@ def request_adapter_sync( async def request_adapter_async( self, *, + feaure_level: str = "core", power_preference: enums.PowerPreference = None, force_fallback_adapter: bool = False, canvas=None, @@ -395,6 +466,7 @@ async def request_adapter_async( be left to None. If given, the object must implement ``WgpuCanvasInterface``. """ awaitable = self._request_adapter( + feaure_level=feaure_level, power_preference=power_preference, force_fallback_adapter=force_fallback_adapter, canvas=canvas, @@ -402,8 +474,29 @@ async def request_adapter_async( return await awaitable def _request_adapter( - self, *, power_preference=None, force_fallback_adapter=False, canvas=None + self, *, feaure_level, power_preference, force_fallback_adapter, canvas ): + # Similar to https://github.com/gfx-rs/wgpu?tab=readme-ov-file#environment-variables + # It seems that the environment variables are only respected in their + # testing environments maybe???? + # In Dec 2024 we couldn't get the use of their environment variables to work + # This should only be used in testing environments and API users + # should beware + # We chose the variable name WGPUPY_WGPU_ADAPTER_NAME instead WGPU_ADAPTER_NAME + # to avoid a clash + if adapter_name := os.getenv(("WGPUPY_WGPU_ADAPTER_NAME")): + adapters = self._enumerate_adapters() + adapters_llvm = [a for a in adapters if adapter_name in a.summary] + if not adapters_llvm: + raise ValueError(f"Adapter with name '{adapter_name}' not found.") + awaitable = WgpuAwaitable( + "llvm adapter", + callback=lambda: (), + finalizer=lambda x: x, + ) + awaitable.set_result(adapters_llvm[0]) + + return awaitable # ----- Surface ID # Get surface id that the adapter must be compatible with. If we @@ -424,41 +517,60 @@ def _request_adapter( backend = enum_str2int["BackendType"][force_backend] except KeyError: logger.warning( - f"Invalid value for WGPU_BACKEND_TYPE: '{force_backend}'.\n" - f"Valid values are: {list(enum_str2int['BackendType'].keys())}" + f"Invalid value for WGPU_BACKEND_TYPE: '{force_backend}'.\nValid values are: {list(enum_str2int['BackendType'].keys())}" ) else: logger.warning(f"Forcing backend: {force_backend} ({backend})") # ----- Request adapter - # H: nextInChain: WGPUChainedStruct *, compatibleSurface: WGPUSurface, powerPreference: WGPUPowerPreference, backendType: WGPUBackendType, forceFallbackAdapter: WGPUBool/int + c_feature_level = { + "core": lib.WGPUFeatureLevel_Core, + "compatibility": lib.WGPUFeatureLevel_Compatibility, + }[feaure_level] + + # H: nextInChain: WGPUChainedStruct *, featureLevel: WGPUFeatureLevel, powerPreference: WGPUPowerPreference, forceFallbackAdapter: WGPUBool/int, backendType: WGPUBackendType, compatibleSurface: WGPUSurface struct = new_struct_p( "WGPURequestAdapterOptions *", - compatibleSurface=surface_id, + # not used: nextInChain + featureLevel=c_feature_level, powerPreference=power_preference or "high-performance", forceFallbackAdapter=bool(force_fallback_adapter), backendType=backend, - # not used: nextInChain + compatibleSurface=surface_id, ) - @ffi.callback("void(WGPURequestAdapterStatus, WGPUAdapter, char *, void *)") - def callback(status, result, message, _userdata): - if status != 0: - msg = "-" if message == ffi.NULL else ffi.string(message).decode() + @ffi.callback( + "void(WGPURequestAdapterStatus, WGPUAdapter, WGPUStringView, void *, void *)" + ) + def request_adapter_callback(status, result, c_message, _userdata1, _userdata2): + if status != lib.WGPURequestAdapterStatus_Success: + msg = from_c_string_view(c_message) awaitable.set_error(f"Request adapter failed ({status}): {msg}") else: awaitable.set_result(result) + # H: nextInChain: WGPUChainedStruct *, mode: WGPUCallbackMode, callback: WGPURequestAdapterCallback, userdata1: void*, userdata2: void* + callback_info = new_struct( + "WGPURequestAdapterCallbackInfo", + # not used: nextInChain + mode=lib.WGPUCallbackMode_AllowProcessEvents, + callback=request_adapter_callback, + # not used: userdata1 + # not used: userdata2 + ) + def finalizer(adapter_id): return self._create_adapter(adapter_id) # Note that although we claim this is an asynchronous method, the callback # happens within libf.wgpuInstanceRequestAdapter - awaitable = WgpuAwaitable("request_adapter", callback, finalizer) + awaitable = WgpuAwaitable( + "request_adapter", request_adapter_callback, finalizer + ) - # H: void f(WGPUInstance instance, WGPURequestAdapterOptions const * options, WGPUInstanceRequestAdapterCallback callback, void * userdata) - libf.wgpuInstanceRequestAdapter(get_wgpu_instance(), struct, callback, ffi.NULL) + # H: WGPUFuture f(WGPUInstance instance, WGPURequestAdapterOptions const * options, WGPURequestAdapterCallbackInfo callbackInfo) + libf.wgpuInstanceRequestAdapter(get_wgpu_instance(), struct, callback_info) return awaitable @@ -490,7 +602,7 @@ def _enumerate_adapters(self): def _create_adapter(self, adapter_id): # ----- Get adapter info - # H: nextInChain: WGPUChainedStructOut *, vendor: char *, architecture: char *, device: char *, description: char *, backendType: WGPUBackendType, adapterType: WGPUAdapterType, vendorID: int, deviceID: int + # H: nextInChain: WGPUChainedStructOut *, vendor: WGPUStringView, architecture: WGPUStringView, device: WGPUStringView, description: WGPUStringView, backendType: WGPUBackendType, adapterType: WGPUAdapterType, vendorID: int, deviceID: int c_info = new_struct_p( "WGPUAdapterInfo *", # not used: nextInChain @@ -504,14 +616,14 @@ def _create_adapter(self, adapter_id): # not used: deviceID ) - # H: void f(WGPUAdapter adapter, WGPUAdapterInfo * info) - libf.wgpuAdapterGetInfo(adapter_id, c_info) + # H: WGPUStatus f(WGPUAdapter adapter, WGPUAdapterInfo * info) + status = libf.wgpuAdapterGetInfo(adapter_id, c_info) + if status != lib.WGPUStatus_Success: + raise RuntimeError("Error calling wgpuAdapterGetInfo") def to_py_str(key): - char_p = getattr(c_info, key) - if char_p: - return ffi.string(char_p).decode(errors="ignore") - return "" + string_view = getattr(c_info, key) + return from_c_string_view(string_view) # Populate a dict according to the WebGPU spec: https://gpuweb.github.io/gpuweb/#gpuadapterinfo # And add all other info we get from wgpu-native too. @@ -584,7 +696,7 @@ def _get_capabilities_screen(self, adapter): "present_modes": ["fifo"], } - # H: nextInChain: WGPUChainedStructOut *, usages: WGPUTextureUsageFlags/int, formatCount: int, formats: WGPUTextureFormat *, presentModeCount: int, presentModes: WGPUPresentMode *, alphaModeCount: int, alphaModes: WGPUCompositeAlphaMode * + # H: nextInChain: WGPUChainedStructOut *, usages: WGPUTextureUsage/int, formatCount: int, formats: WGPUTextureFormat *, presentModeCount: int, presentModes: WGPUPresentMode *, alphaModeCount: int, alphaModes: WGPUCompositeAlphaMode * c_capabilities = new_struct_p( "WGPUSurfaceCapabilities *", # not used: nextInChain @@ -597,8 +709,10 @@ def _get_capabilities_screen(self, adapter): # not used: alphaModes ) - # H: void f(WGPUSurface surface, WGPUAdapter adapter, WGPUSurfaceCapabilities * capabilities) - libf.wgpuSurfaceGetCapabilities(surface_id, adapter_id, c_capabilities) + # H: WGPUStatus f(WGPUSurface surface, WGPUAdapter adapter, WGPUSurfaceCapabilities * capabilities) + status = libf.wgpuSurfaceGetCapabilities(surface_id, adapter_id, c_capabilities) + if status != lib.WGPUStatus_Success: + raise RuntimeError("Error calling wgpuSurfaceGetCapabilities") # Convert to Python. capabilities = {} @@ -698,9 +812,10 @@ def _configure_screen( # Prepare config object - # H: nextInChain: WGPUChainedStruct *, device: WGPUDevice, format: WGPUTextureFormat, usage: WGPUTextureUsageFlags/int, viewFormatCount: int, viewFormats: WGPUTextureFormat *, alphaMode: WGPUCompositeAlphaMode, width: int, height: int, presentMode: WGPUPresentMode + # H: nextInChain: WGPUChainedStruct *, device: WGPUDevice, format: WGPUTextureFormat, usage: WGPUTextureUsage/int, width: int, height: int, viewFormatCount: int, viewFormats: WGPUTextureFormat *, alphaMode: WGPUCompositeAlphaMode, presentMode: WGPUPresentMode self._wgpu_config = new_struct_p( "WGPUSurfaceConfiguration *", + # not used: nextInChain device=device._internal, format=format, usage=usage, @@ -710,7 +825,6 @@ def _configure_screen( width=0, height=0, presentMode=c_present_mode, - # not used: nextInChain ) def _configure_screen_real(self, width, height): @@ -754,11 +868,11 @@ def _create_texture_screen(self): # Try to obtain a texture. # `If it fails, depending on status, we reconfigure and try again. - # H: texture: WGPUTexture, suboptimal: WGPUBool/int, status: WGPUSurfaceGetCurrentTextureStatus + # H: nextInChain: WGPUChainedStructOut *, texture: WGPUTexture, status: WGPUSurfaceGetCurrentTextureStatus surface_texture = new_struct_p( "WGPUSurfaceTexture *", + # not used: nextInChain # not used: texture - # not used: suboptimal # not used: status ) @@ -767,8 +881,12 @@ def _create_texture_screen(self): libf.wgpuSurfaceGetCurrentTexture(surface_id, surface_texture) status = surface_texture.status texture_id = surface_texture.texture - if status == lib.WGPUSurfaceGetCurrentTextureStatus_Success: - break # success + if status == lib.WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal: + break # Yay! Everything is good and we can render this frame. + elif status == lib.WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal: + # Still OK - the surface can present the frame, but in a suboptimal way. The surface may need reconfiguration. + logger.warning("The surface texture is suboptimal.") + break if texture_id: # H: void f(WGPUTexture texture) libf.wgpuTextureRelease(texture_id) @@ -786,6 +904,7 @@ def _create_texture_screen(self): else: # WGPUSurfaceGetCurrentTextureStatus_OutOfMemory # WGPUSurfaceGetCurrentTextureStatus_DeviceLost + # WGPUSurfaceGetCurrentTextureStatus_Error # Or if this is the second attempt. raise RuntimeError(f"Cannot get surface texture ({status}).") @@ -793,10 +912,6 @@ def _create_texture_screen(self): if not texture_id: raise RuntimeError("Cannot get surface texture (no texture)") - # Things look good, but texture may still be suboptimal, whatever that means - if surface_texture.suboptimal: - logger.warning("The surface texture is suboptimal.") - # Wrap it in a Python texture object # But we can also read them from the texture @@ -816,14 +931,14 @@ def _create_texture_screen(self): # H: WGPUTextureFormat f(WGPUTexture texture) c_format = libf.wgpuTextureGetFormat(texture_id) format = enum_int2str["TextureFormat"][c_format] - # H: WGPUTextureUsageFlags f(WGPUTexture texture) + # H: WGPUTextureUsage f(WGPUTexture texture) usage = libf.wgpuTextureGetUsage(texture_id) label = "" # Cannot yet set label, because it's not implemented in wgpu-native # label = "surface-texture" - # H: void f(WGPUTexture texture, char const * label) - # libf.wgpuTextureSetLabel(texture_id, to_c_label(label)) + # H: void f(WGPUTexture texture, WGPUStringView label) + # libf.wgpuTextureSetLabel(texture_id, to_c_string_view(label)) tex_info = { "size": (width, height, depth), @@ -838,8 +953,10 @@ def _create_texture_screen(self): return GPUTexture(label, texture_id, device, tex_info) def _present_screen(self): - # H: void f(WGPUSurface surface) - libf.wgpuSurfacePresent(self._surface_id) + # H: WGPUStatus f(WGPUSurface surface) + status = libf.wgpuSurfacePresent(self._surface_id) + if status != lib.WGPUStatus_Success: + raise RuntimeError("Error calling wgpuSurfacePresent") def _release(self): self._drop_texture() @@ -887,7 +1004,7 @@ def request_device_sync( *, label: str = "", required_features: List[enums.FeatureName] = [], - required_limits: Dict[str, int] = {}, + required_limits: Dict[str, Union[None, int]] = {}, default_queue: structs.QueueDescriptor = {}, ): check_can_use_sync_variants() @@ -903,7 +1020,7 @@ async def request_device_async( *, label: str = "", required_features: List[enums.FeatureName] = [], - required_limits: Dict[str, int] = {}, + required_limits: Dict[str, Union[None, int]] = {}, default_queue: structs.QueueDescriptor = {}, ): if default_queue: @@ -945,21 +1062,42 @@ def _request_device( # ----- Set limits - # H: chain: WGPUChainedStruct, limits: WGPUNativeLimits - c_required_limits_extras = new_struct_p( - "WGPURequiredLimitsExtras *", - # not used: chain - # not used: limits - ) - c_required_limits_extras.chain.sType = lib.WGPUSType_RequiredLimitsExtras - # H: nextInChain: WGPUChainedStruct *, limits: WGPULimits + # H: nextInChain: WGPUChainedStructOut *, maxTextureDimension1D: int, maxTextureDimension2D: int, maxTextureDimension3D: int, maxTextureArrayLayers: int, maxBindGroups: int, maxBindGroupsPlusVertexBuffers: int, maxBindingsPerBindGroup: int, maxDynamicUniformBuffersPerPipelineLayout: int, maxDynamicStorageBuffersPerPipelineLayout: int, maxSampledTexturesPerShaderStage: int, maxSamplersPerShaderStage: int, maxStorageBuffersPerShaderStage: int, maxStorageTexturesPerShaderStage: int, maxUniformBuffersPerShaderStage: int, maxUniformBufferBindingSize: int, maxStorageBufferBindingSize: int, minUniformBufferOffsetAlignment: int, minStorageBufferOffsetAlignment: int, maxVertexBuffers: int, maxBufferSize: int, maxVertexAttributes: int, maxVertexBufferArrayStride: int, maxInterStageShaderVariables: int, maxColorAttachments: int, maxColorAttachmentBytesPerSample: int, maxComputeWorkgroupStorageSize: int, maxComputeInvocationsPerWorkgroup: int, maxComputeWorkgroupSizeX: int, maxComputeWorkgroupSizeY: int, maxComputeWorkgroupSizeZ: int, maxComputeWorkgroupsPerDimension: int c_required_limits = new_struct_p( - "WGPURequiredLimits *", - nextInChain=ffi.cast("WGPUChainedStruct*", c_required_limits_extras), - # not used: limits + "WGPULimits *", + # not used: nextInChain + # not used: maxTextureDimension1D + # not used: maxTextureDimension2D + # not used: maxTextureDimension3D + # not used: maxTextureArrayLayers + # not used: maxBindGroups + # not used: maxBindGroupsPlusVertexBuffers + # not used: maxBindingsPerBindGroup + # not used: maxDynamicUniformBuffersPerPipelineLayout + # not used: maxDynamicStorageBuffersPerPipelineLayout + # not used: maxSampledTexturesPerShaderStage + # not used: maxSamplersPerShaderStage + # not used: maxStorageBuffersPerShaderStage + # not used: maxStorageTexturesPerShaderStage + # not used: maxUniformBuffersPerShaderStage + # not used: maxUniformBufferBindingSize + # not used: maxStorageBufferBindingSize + # not used: minUniformBufferOffsetAlignment + # not used: minStorageBufferOffsetAlignment + # not used: maxVertexBuffers + # not used: maxBufferSize + # not used: maxVertexAttributes + # not used: maxVertexBufferArrayStride + # not used: maxInterStageShaderVariables + # not used: maxColorAttachments + # not used: maxColorAttachmentBytesPerSample + # not used: maxComputeWorkgroupStorageSize + # not used: maxComputeInvocationsPerWorkgroup + # not used: maxComputeWorkgroupSizeX + # not used: maxComputeWorkgroupSizeY + # not used: maxComputeWorkgroupSizeZ + # not used: maxComputeWorkgroupsPerDimension ) - c_limits = c_required_limits.limits - c_limits_extras = c_required_limits_extras.limits def canonicalize_limit_name(name): if name in self._limits: @@ -984,35 +1122,48 @@ def canonicalize_limit_name(name): # setting it to {}, but the loop below goes just a little bit faster. required_limits = self._limits - for limit in (c_limits, c_limits_extras): - for key in dir(limit): - snake_key = to_snake_case(key, "-") - # Use the value in required_limits if it exists. Otherwise, the old value - try: - value = required_limits[snake_key] - except KeyError: - value = self._limits[snake_key] - setattr(limit, key, value) + for key in dir(c_required_limits): + snake_key = to_snake_case(key, "-") + # Skip the pointers + if "chain" in snake_key: + continue + # Use the value in required_limits if it exists. Otherwise, the old value + try: + value = required_limits[snake_key] + except KeyError: + value = self._limits[snake_key] + setattr(c_required_limits, key, value) + + # the native only limits are passed in via the next-in-chain struct + # H: chain: WGPUChainedStructOut, maxPushConstantSize: int, maxNonSamplerBindings: int + c_required_limits_native = new_struct( + "WGPUNativeLimits", + maxPushConstantSize=required_limits.get("max-push-constant-size", 0), + maxNonSamplerBindings=required_limits.get("max-non-sampler-bindings", 0), + # not used: chain + ) + c_required_limits_native.chain.next = ffi.NULL + c_required_limits_native.chain.sType = lib.WGPUSType_NativeLimits + + c_required_limits.nextInChain = ffi.addressof(c_required_limits_native, "chain") # ---- Set queue descriptor # Note that the default_queue arg is a descriptor (dict for QueueDescriptor), but is currently empty :) check_struct("QueueDescriptor", {}) - # H: nextInChain: WGPUChainedStruct *, label: char * + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView queue_struct = new_struct( "WGPUQueueDescriptor", - label=to_c_label("default_queue"), # not used: nextInChain + label=to_c_string_view("default_queue"), ) # ----- Compose device descriptor extras - c_trace_path = ffi.NULL - if trace_path: # no-cover - c_trace_path = to_c_string(trace_path) + c_trace_path = to_c_string_view(trace_path if trace_path else None) - # H: chain: WGPUChainedStruct, tracePath: char * + # H: chain: WGPUChainedStruct, tracePath: WGPUStringView extras = new_struct_p( "WGPUDeviceExtras *", tracePath=c_trace_path, @@ -1022,60 +1173,87 @@ def canonicalize_limit_name(name): # ----- Device lost - @ffi.callback("void(WGPUDeviceLostReason, char *, void *)") - def device_lost_callback(c_reason, c_message, userdata): + @ffi.callback( + "void(WGPUDevice const *, WGPUDeviceLostReason, WGPUStringView, void *, void *)" + ) + def device_lost_callback(c_device, c_reason, c_message, userdata1, userdata2): reason = enum_int2str["DeviceLostReason"].get(c_reason, "Unknown") - message = ffi.string(c_message).decode(errors="ignore") - msg = f"The WGPU device was lost ({reason}):\n{message}" + msg = from_c_string_view(c_message) # This is afaik an error that cannot usually be attributed to a specific call, # so we cannot raise it as an error. We log it instead. # WebGPU provides (promise-based) API for user-code to handle the error. # We might want to do something similar, once we have async figured out. - error_handler.log_error(msg) + error_handler.log_error(f"The WGPU device was lost ({reason}):\n{msg}") + + # H: nextInChain: WGPUChainedStruct *, mode: WGPUCallbackMode, callback: WGPUDeviceLostCallback, userdata1: void*, userdata2: void* + device_lost_callback_info = new_struct( + "WGPUDeviceLostCallbackInfo", + # not used: nextInChain + mode=lib.WGPUCallbackMode_AllowSpontaneous, + callback=device_lost_callback, + # not used: userdata1 + # not used: userdata2 + ) # ----- Uncaptured error # TODO: For some errors (seen for errors in wgsl, but not for some others) the error gets logged via the logger as well (duplicate). Probably an issue with wgpu-core. - @ffi.callback("void(WGPUErrorType, char *, void *)") - def uncaptured_error_callback(c_type, c_message, userdata): + @ffi.callback( + "void(WGPUDevice const *, WGPUErrorType, WGPUStringView, void *, void *)" + ) + def uncaptured_error_callback( + c_device, c_type, c_message, userdata1, userdata2 + ): error_type = enum_int2str["ErrorType"].get(c_type, "Unknown") - message = ffi.string(c_message).decode(errors="ignore") - message = "\n".join(line.rstrip() for line in message.splitlines()) - error_handler.handle_error(error_type, message) + msg = from_c_string_view(c_message) + msg = "\n".join(line.rstrip() for line in msg.splitlines()) + error_handler.handle_error(error_type, msg) - # H: nextInChain: WGPUChainedStruct *, callback: WGPUErrorCallback, userdata: void * + # H: nextInChain: WGPUChainedStruct *, callback: WGPUUncapturedErrorCallback, userdata1: void*, userdata2: void* uncaptured_error_callback_info = new_struct( "WGPUUncapturedErrorCallbackInfo", - callback=uncaptured_error_callback, - userdata=ffi.NULL, # not used: nextInChain + callback=uncaptured_error_callback, + # not used: userdata1 + # not used: userdata2 ) # ----- Request device - # H: nextInChain: WGPUChainedStruct *, label: char *, requiredFeatureCount: int, requiredFeatures: WGPUFeatureName *, requiredLimits: WGPURequiredLimits *, defaultQueue: WGPUQueueDescriptor, deviceLostCallback: WGPUDeviceLostCallback, deviceLostUserdata: void *, uncapturedErrorCallbackInfo: WGPUUncapturedErrorCallbackInfo + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView, requiredFeatureCount: int, requiredFeatures: WGPUFeatureName *, requiredLimits: WGPULimits *, defaultQueue: WGPUQueueDescriptor, deviceLostCallbackInfo: WGPUDeviceLostCallbackInfo, uncapturedErrorCallbackInfo: WGPUUncapturedErrorCallbackInfo struct = new_struct_p( "WGPUDeviceDescriptor *", - label=to_c_label(label), nextInChain=ffi.cast("WGPUChainedStruct * ", extras), + label=to_c_string_view(label), requiredFeatureCount=len(c_features), requiredFeatures=new_array("WGPUFeatureName[]", c_features), requiredLimits=c_required_limits, defaultQueue=queue_struct, - deviceLostCallback=device_lost_callback, + deviceLostCallbackInfo=device_lost_callback_info, uncapturedErrorCallbackInfo=uncaptured_error_callback_info, - # not used: deviceLostUserdata ) - @ffi.callback("void(WGPURequestDeviceStatus, WGPUDevice, char *, void *)") - def callback(status, result, message, userdata): - if status != 0: - msg = "-" if message == ffi.NULL else ffi.string(message).decode() + @ffi.callback( + "void(WGPURequestDeviceStatus, WGPUDevice, WGPUStringView, void *, void *)" + ) + def request_device_callback(status, result, c_message, userdata1, userdata2): + if status != lib.WGPURequestDeviceStatus_Success: + msg = from_c_string_view(c_message) awaitable.set_error(f"Request device failed ({status}): {msg}") else: awaitable.set_result(result) + # H: nextInChain: WGPUChainedStruct *, mode: WGPUCallbackMode, callback: WGPURequestDeviceCallback, userdata1: void*, userdata2: void* + callback_info = new_struct( + "WGPURequestDeviceCallbackInfo", + # not used: nextInChain + mode=lib.WGPUCallbackMode_AllowProcessEvents, + callback=request_device_callback, + # not used: userdata1 + # not used: userdata2 + ) + def finalizer(device_id): limits = _get_limits(device_id, device=True) features = _get_features(device_id, device=True) @@ -1091,10 +1269,10 @@ def finalizer(device_id): return device - awaitable = WgpuAwaitable("request_device", callback, finalizer) + awaitable = WgpuAwaitable("request_device", request_device_callback, finalizer) - # H: void f(WGPUAdapter adapter, WGPUDeviceDescriptor const * descriptor, WGPUAdapterRequestDeviceCallback callback, void * userdata) - libf.wgpuAdapterRequestDevice(self._internal, struct, callback, ffi.NULL) + # H: WGPUFuture f(WGPUAdapter adapter, WGPUDeviceDescriptor const * descriptor, WGPURequestDeviceCallbackInfo callbackInfo) + libf.wgpuAdapterRequestDevice(self._internal, struct, callback_info) return awaitable @@ -1111,17 +1289,18 @@ class GPUDevice(classes.GPUDevice, GPUObjectBase): # This flag should be deleted once create_compute_pipeline_async() and # create_render_pipeline_async() are actually implemented in the wgpu-native library. + # they now exist in the header, but are still unimplemented: https://github.com/gfx-rs/wgpu-native/blob/f29ebee88362934f8f9fab530f3ccb7fde2d49a9/src/unimplemented.rs#L66-L82 _CREATE_PIPELINE_ASYNC_IS_IMPLEMENTED = False def _poll(self): # Internal function if self._internal: - # H: WGPUBool f(WGPUDevice device, WGPUBool wait, WGPUWrappedSubmissionIndex const * wrappedSubmissionIndex) + # H: WGPUBool f(WGPUDevice device, WGPUBool wait, WGPUSubmissionIndex const * wrappedSubmissionIndex) libf.wgpuDevicePoll(self._internal, False, ffi.NULL) def _poll_wait(self): if self._internal: - # H: WGPUBool f(WGPUDevice device, WGPUBool wait, WGPUWrappedSubmissionIndex const * wrappedSubmissionIndex) + # H: WGPUBool f(WGPUDevice device, WGPUBool wait, WGPUSubmissionIndex const * wrappedSubmissionIndex) libf.wgpuDevicePoll(self._internal, True, ffi.NULL) def create_buffer( @@ -1138,14 +1317,14 @@ def _create_buffer(self, label, size, usage, mapped_at_creation): # Create a buffer object if isinstance(usage, str): usage = str_flag_to_int(flags.BufferUsage, usage) - # H: nextInChain: WGPUChainedStruct *, label: char *, usage: WGPUBufferUsageFlags/int, size: int, mappedAtCreation: WGPUBool/int + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView, usage: WGPUBufferUsage/int, size: int, mappedAtCreation: WGPUBool/int struct = new_struct_p( "WGPUBufferDescriptor *", - label=to_c_label(label), + # not used: nextInChain + label=to_c_string_view(label), size=size, usage=int(usage), mappedAtCreation=mapped_at_creation, - # not used: nextInChain ) map_state = ( enums.BufferMapState.mapped @@ -1204,17 +1383,17 @@ def create_texture( sample_count = 1 sample_count = int(sample_count) - # H: nextInChain: WGPUChainedStruct *, label: char *, usage: WGPUTextureUsageFlags/int, dimension: WGPUTextureDimension, size: WGPUExtent3D, format: WGPUTextureFormat, mipLevelCount: int, sampleCount: int, viewFormatCount: int, viewFormats: WGPUTextureFormat * + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView, usage: WGPUTextureUsage/int, dimension: WGPUTextureDimension, size: WGPUExtent3D, format: WGPUTextureFormat, mipLevelCount: int, sampleCount: int, viewFormatCount: int, viewFormats: WGPUTextureFormat * struct = new_struct_p( "WGPUTextureDescriptor *", - label=to_c_label(label), + # not used: nextInChain + label=to_c_string_view(label), size=c_size, mipLevelCount=mip_level_count, sampleCount=sample_count, dimension=dimension, format=format, usage=usage, - # not used: nextInChain # not used: viewFormatCount # not used: viewFormats ) @@ -1248,10 +1427,11 @@ def create_sampler( compare: enums.CompareFunction = optional, max_anisotropy: int = 1, ): - # H: nextInChain: WGPUChainedStruct *, label: char *, addressModeU: WGPUAddressMode, addressModeV: WGPUAddressMode, addressModeW: WGPUAddressMode, magFilter: WGPUFilterMode, minFilter: WGPUFilterMode, mipmapFilter: WGPUMipmapFilterMode, lodMinClamp: float, lodMaxClamp: float, compare: WGPUCompareFunction, maxAnisotropy: int + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView, addressModeU: WGPUAddressMode, addressModeV: WGPUAddressMode, addressModeW: WGPUAddressMode, magFilter: WGPUFilterMode, minFilter: WGPUFilterMode, mipmapFilter: WGPUMipmapFilterMode, lodMinClamp: float, lodMaxClamp: float, compare: WGPUCompareFunction, maxAnisotropy: int struct = new_struct_p( "WGPUSamplerDescriptor *", - label=to_c_label(label), + # not used: nextInChain + label=to_c_string_view(label), addressModeU=address_mode_u, addressModeV=address_mode_v, addressModeW=address_mode_w, @@ -1262,7 +1442,6 @@ def create_sampler( lodMaxClamp=lod_max_clamp, compare=0 if compare is None else compare, # 0 means undefined maxAnisotropy=max_anisotropy, - # not used: nextInChain ) # H: WGPUSampler f(WGPUDevice device, WGPUSamplerDescriptor const * descriptor) @@ -1285,10 +1464,10 @@ def create_bind_group_layout( # H: nextInChain: WGPUChainedStruct *, type: WGPUBufferBindingType, hasDynamicOffset: WGPUBool/int, minBindingSize: int buffer = new_struct( "WGPUBufferBindingLayout", + # not used: nextInChain type=info.get("type", "uniform"), hasDynamicOffset=info.get("has_dynamic_offset", False), minBindingSize=min_binding_size, - # not used: nextInChain ) elif "sampler" in entry: # It may be an empty dictionary info = entry["sampler"] @@ -1296,8 +1475,8 @@ def create_bind_group_layout( # H: nextInChain: WGPUChainedStruct *, type: WGPUSamplerBindingType sampler = new_struct( "WGPUSamplerBindingLayout", - type=info.get("type", "filtering"), # not used: nextInChain + type=info.get("type", "filtering"), ) elif "texture" in entry: # It may be an empty dictionary info = entry["texture"] @@ -1310,10 +1489,10 @@ def create_bind_group_layout( # H: nextInChain: WGPUChainedStruct *, sampleType: WGPUTextureSampleType, viewDimension: WGPUTextureViewDimension, multisampled: WGPUBool/int texture = new_struct( "WGPUTextureBindingLayout", + # not used: nextInChain sampleType=info.get("sample_type", "float"), viewDimension=view_dimension, multisampled=info.get("multisampled", False), - # not used: nextInChain ) elif "storage_texture" in entry: # format is required, so not empty info = entry["storage_texture"] @@ -1326,10 +1505,10 @@ def create_bind_group_layout( # H: nextInChain: WGPUChainedStruct *, access: WGPUStorageTextureAccess, format: WGPUTextureFormat, viewDimension: WGPUTextureViewDimension storage_texture = new_struct( "WGPUStorageTextureBindingLayout", + # not used: nextInChain access=info.get("access", "write-only"), viewDimension=view_dimension, format=info["format"], - # not used: nextInChain ) else: raise ValueError( @@ -1340,26 +1519,26 @@ def create_bind_group_layout( visibility = entry["visibility"] if isinstance(visibility, str): visibility = str_flag_to_int(flags.ShaderStage, visibility) - # H: nextInChain: WGPUChainedStruct *, binding: int, visibility: WGPUShaderStageFlags/int, buffer: WGPUBufferBindingLayout, sampler: WGPUSamplerBindingLayout, texture: WGPUTextureBindingLayout, storageTexture: WGPUStorageTextureBindingLayout + # H: nextInChain: WGPUChainedStruct *, binding: int, visibility: WGPUShaderStage/int, buffer: WGPUBufferBindingLayout, sampler: WGPUSamplerBindingLayout, texture: WGPUTextureBindingLayout, storageTexture: WGPUStorageTextureBindingLayout c_entry = new_struct( "WGPUBindGroupLayoutEntry", + # not used: nextInChain binding=int(entry["binding"]), visibility=int(visibility), buffer=buffer, sampler=sampler, texture=texture, storageTexture=storage_texture, - # not used: nextInChain ) c_entries_list.append(c_entry) - # H: nextInChain: WGPUChainedStruct *, label: char *, entryCount: int, entries: WGPUBindGroupLayoutEntry * + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView, entryCount: int, entries: WGPUBindGroupLayoutEntry * struct = new_struct_p( "WGPUBindGroupLayoutDescriptor *", - label=to_c_label(label), + # not used: nextInChain + label=to_c_string_view(label), entries=new_array("WGPUBindGroupLayoutEntry[]", c_entries_list), entryCount=len(c_entries_list), - # not used: nextInChain ) # Note: wgpu-core re-uses BindGroupLayouts with the same (or similar @@ -1391,50 +1570,50 @@ def create_bind_group( # H: nextInChain: WGPUChainedStruct *, binding: int, buffer: WGPUBuffer, offset: int, size: int, sampler: WGPUSampler, textureView: WGPUTextureView c_entry = new_struct( "WGPUBindGroupEntry", + # not used: nextInChain binding=int(entry["binding"]), buffer=ffi.NULL, offset=0, size=0, sampler=resource._internal, textureView=ffi.NULL, - # not used: nextInChain ) elif isinstance(resource, GPUTextureView): # H: nextInChain: WGPUChainedStruct *, binding: int, buffer: WGPUBuffer, offset: int, size: int, sampler: WGPUSampler, textureView: WGPUTextureView c_entry = new_struct( "WGPUBindGroupEntry", + # not used: nextInChain binding=int(entry["binding"]), buffer=ffi.NULL, offset=0, size=0, sampler=ffi.NULL, textureView=resource._internal, - # not used: nextInChain ) elif isinstance(resource, dict): # Buffer binding # H: nextInChain: WGPUChainedStruct *, binding: int, buffer: WGPUBuffer, offset: int, size: int, sampler: WGPUSampler, textureView: WGPUTextureView c_entry = new_struct( "WGPUBindGroupEntry", + # not used: nextInChain binding=int(entry["binding"]), buffer=resource["buffer"]._internal, offset=resource.get("offset", 0), size=resource.get("size", lib.WGPU_WHOLE_SIZE), sampler=ffi.NULL, textureView=ffi.NULL, - # not used: nextInChain ) else: raise TypeError(f"Unexpected resource type {type(resource)}") c_entries_list.append(c_entry) - # H: nextInChain: WGPUChainedStruct *, label: char *, layout: WGPUBindGroupLayout, entryCount: int, entries: WGPUBindGroupEntry * + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView, layout: WGPUBindGroupLayout, entryCount: int, entries: WGPUBindGroupEntry * struct = new_struct_p( "WGPUBindGroupDescriptor *", - label=to_c_label(label), + # not used: nextInChain + label=to_c_string_view(label), layout=layout._internal, entries=new_array("WGPUBindGroupEntry[]", c_entries_list), entryCount=len(c_entries_list), - # not used: nextInChain ) # H: WGPUBindGroup f(WGPUDevice device, WGPUBindGroupDescriptor const * descriptor) @@ -1479,13 +1658,13 @@ def _create_pipeline_layout( c_pipeline_layout_extras.chain.sType = lib.WGPUSType_PipelineLayoutExtras next_in_chain = ffi.cast("WGPUChainedStruct *", c_pipeline_layout_extras) - # H: nextInChain: WGPUChainedStruct *, label: char *, bindGroupLayoutCount: int, bindGroupLayouts: WGPUBindGroupLayout * + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView, bindGroupLayoutCount: int, bindGroupLayouts: WGPUBindGroupLayout * struct = new_struct_p( "WGPUPipelineLayoutDescriptor *", - label=to_c_label(label), + nextInChain=next_in_chain, + label=to_c_string_view(label), bindGroupLayouts=c_layout_array, bindGroupLayoutCount=len(bind_group_layouts), - nextInChain=next_in_chain, ) # H: WGPUPipelineLayout f(WGPUDevice device, WGPUPipelineLayoutDescriptor const * descriptor) @@ -1497,12 +1676,13 @@ def create_shader_module( *, label: str = "", code: str, - source_map: dict = optional, compilation_hints: List[structs.ShaderModuleCompilationHint] = [], ): - if compilation_hints: - for hint in compilation_hints: - check_struct("ShaderModuleCompilationHint", hint) + if False: + # Trick the check_struct check in the codegen. + # Compilation_hint are not used, but part of the WebGPU API (for now) + for compilation_hint in compilation_hints: + check_struct("ShaderModuleCompilationHint", compilation_hint) if isinstance(code, str): looks_like_wgsl = any( x in code for x in ("@compute", "@vertex", "@fragment") @@ -1523,17 +1703,18 @@ def create_shader_module( defines = [] if c_stage == flags.ShaderStage.VERTEX: defines.append( - # H: name: char *, value: char * + # H: name: WGPUStringView, value: WGPUStringView new_struct( "WGPUShaderDefine", - name=to_c_string("gl_VertexID"), - value=to_c_string("gl_VertexIndex"), + name=to_c_string_view("gl_VertexID"), + value=to_c_string_view("gl_VertexIndex"), ) ) - # H: chain: WGPUChainedStruct, stage: WGPUShaderStage, code: char *, defineCount: int, defines: WGPUShaderDefine * + # note, GLSL is a wgpu-native feature and still uses the older structure! + # H: chain: WGPUChainedStruct, stage: WGPUShaderStage/int, code: WGPUStringView, defineCount: int, defines: WGPUShaderDefine * source_struct = new_struct_p( "WGPUShaderModuleGLSLDescriptor *", - code=to_c_string(code), + code=to_c_string_view(code), stage=c_stage, defineCount=len(defines), defines=new_array("WGPUShaderDefine[]", defines), @@ -1543,14 +1724,14 @@ def create_shader_module( source_struct[0].chain.sType = lib.WGPUSType_ShaderModuleGLSLDescriptor else: # === WGSL - # H: chain: WGPUChainedStruct, code: char * + # H: chain: WGPUChainedStruct, code: WGPUStringView source_struct = new_struct_p( - "WGPUShaderModuleWGSLDescriptor *", - code=to_c_string(code), + "WGPUShaderSourceWGSL *", # not used: chain + code=to_c_string_view(code), ) source_struct[0].chain.next = ffi.NULL - source_struct[0].chain.sType = lib.WGPUSType_ShaderModuleWGSLDescriptor + source_struct[0].chain.sType = lib.WGPUSType_ShaderSourceWGSL elif isinstance(code, bytes): # === Spirv data = code @@ -1563,26 +1744,23 @@ def create_shader_module( data_u32 = ffi.cast("uint32_t *", data_u8) # H: chain: WGPUChainedStruct, codeSize: int, code: uint32_t * source_struct = new_struct_p( - "WGPUShaderModuleSPIRVDescriptor *", - code=data_u32, - codeSize=len(data) // 4, + "WGPUShaderSourceSPIRV *", # not used: chain + codeSize=len(data) // 4, + code=data_u32, ) source_struct[0].chain.next = ffi.NULL - source_struct[0].chain.sType = lib.WGPUSType_ShaderModuleSPIRVDescriptor + source_struct[0].chain.sType = lib.WGPUSType_ShaderSourceSPIRV else: raise TypeError( "Shader code must be str for WGSL or GLSL, or bytes for SpirV." ) - # Note, we could give hints here that specify entrypoint and pipelinelayout before compiling - # H: nextInChain: WGPUChainedStruct *, label: char *, hintCount: int, hints: WGPUShaderModuleCompilationHint * + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView struct = new_struct_p( "WGPUShaderModuleDescriptor *", - label=to_c_label(label), nextInChain=ffi.cast("WGPUChainedStruct *", source_struct), - hintCount=0, - hints=ffi.NULL, + label=to_c_string_view(label), ) # H: WGPUShaderModule f(WGPUDevice device, WGPUShaderModuleDescriptor const * descriptor) id = libf.wgpuDeviceCreateShaderModule(self._internal, struct) @@ -1619,15 +1797,25 @@ async def create_compute_pipeline_async( # This code is virtually identical to the code in create_render_pipeline_async. # Can they be merged?? @ffi.callback( - "void(WGPUCreatePipelineAsyncStatus, WGPUComputePipeline, char *, void *)" + "void(WGPUCreatePipelineAsyncStatus, WGPUComputePipeline, char *, void *, void *)" ) - def callback(status, result, message, _userdata): - if status != 0: - msg = "-" if message == ffi.NULL else ffi.string(message).decode() + def callback(status, result, c_message, _userdata1, _userdata2): + if status != lib.WGPUCreatePipelineAsyncStatus_Success: + msg = from_c_string_view(c_message) awaitable.set_error(f"create_compute_pipeline failed ({status}): {msg}") else: awaitable.set_result(result) + # H: nextInChain: WGPUChainedStruct *, mode: WGPUCallbackMode, callback: WGPUCreateComputePipelineAsyncCallback, userdata1: void*, userdata2: void* + callback_info = new_struct( + "WGPUCreateComputePipelineAsyncCallbackInfo", + # not used: nextInChain + mode=lib.WGPUCallbackMode_AllowProcessEvents, + callback=callback, + # not used: userdata1 + # not used: userdata2 + ) + def finalizer(id): return GPUComputePipeline(label, id, self) @@ -1635,9 +1823,9 @@ def finalizer(id): "create_compute_pipeline", callback, finalizer, self._device._poll ) - # H: void f(WGPUDevice device, WGPUComputePipelineDescriptor const * descriptor, WGPUDeviceCreateComputePipelineAsyncCallback callback, void * userdata) + # H: WGPUFuture f(WGPUDevice device, WGPUComputePipelineDescriptor const * descriptor, WGPUCreateComputePipelineAsyncCallbackInfo callbackInfo) libf.wgpuDeviceCreateComputePipelineAsync( - self._internal, descriptor, callback, ffi.NULL + self._internal, descriptor, callback_info ) return await awaitable @@ -1650,14 +1838,14 @@ def _create_compute_pipeline_descriptor( ): check_struct("ProgrammableStage", compute) c_constants, c_constant_entries = _get_override_constant_entries(compute) - # H: nextInChain: WGPUChainedStruct *, module: WGPUShaderModule, entryPoint: char *, constantCount: int, constants: WGPUConstantEntry * + # H: nextInChain: WGPUChainedStruct *, module: WGPUShaderModule, entryPoint: WGPUStringView, constantCount: int, constants: WGPUConstantEntry * c_compute_stage = new_struct( "WGPUProgrammableStageDescriptor", + # not used: nextInChain module=compute["module"]._internal, - entryPoint=to_c_string_or_null(compute.get("entry_point")), + entryPoint=to_c_string_view(compute.get("entry_point")), constantCount=len(c_constant_entries), constants=c_constants, - # not used: nextInChain ) if isinstance(layout, GPUPipelineLayout): @@ -1669,13 +1857,13 @@ def _create_compute_pipeline_descriptor( "create_compute_pipeline() 'layout' arg must be a GPUPipelineLayout or 'auto'" ) - # H: nextInChain: WGPUChainedStruct *, label: char *, layout: WGPUPipelineLayout, compute: WGPUProgrammableStageDescriptor + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView, layout: WGPUPipelineLayout, compute: WGPUProgrammableStageDescriptor struct = new_struct_p( "WGPUComputePipelineDescriptor *", - label=to_c_label(label), + # not used: nextInChain + label=to_c_string_view(label), layout=layout_id, compute=c_compute_stage, - # not used: nextInChain ) return struct @@ -1719,15 +1907,25 @@ async def create_render_pipeline_async( return GPURenderPipeline(label, id, self) @ffi.callback( - "void(WGPUCreatePipelineAsyncStatus, WGPURenderPipeline, char *, void *)" + "void(WGPUCreatePipelineAsyncStatus, WGPURenderPipeline, WGPUStringView, void *, void *)" ) - def callback(status, result, message, _userdata): - if status != 0: - msg = "-" if message == ffi.NULL else ffi.string(message).decode() + def callback(status, result, c_message, _userdata1, _userdata2): + if status != lib.WGPUCreatePipelineAsyncStatus_Success: + msg = from_c_string_view(c_message) awaitable.set_error(f"Create renderPipeline failed ({status}): {msg}") else: awaitable.set_result(result) + # H: nextInChain: WGPUChainedStruct *, mode: WGPUCallbackMode, callback: WGPUCreateRenderPipelineAsyncCallback, userdata1: void*, userdata2: void* + callback_info = new_struct( + "WGPUCreateRenderPipelineAsyncCallbackInfo", + # not used: nextInChain + mode=lib.WGPUCallbackMode_AllowProcessEvents, + callback=callback, + # not used: userdata1 + # not used: userdata2 + ) + def finalizer(id): return GPURenderPipeline(label, id, self) @@ -1735,9 +1933,11 @@ def finalizer(id): "create_render_pipeline", callback, finalizer, self._device._poll ) - # H: void f(WGPUDevice device, WGPURenderPipelineDescriptor const * descriptor, WGPUDeviceCreateRenderPipelineAsyncCallback callback, void * userdata) + # H: WGPUFuture f(WGPUDevice device, WGPURenderPipelineDescriptor const * descriptor, WGPUCreateRenderPipelineAsyncCallbackInfo callbackInfo) libf.wgpuDeviceCreateRenderPipelineAsync( - self._internal, descriptor, callback, ffi.NULL + self._internal, + descriptor, + callback_info, ) return await awaitable @@ -1768,26 +1968,27 @@ def _create_render_pipeline_descriptor( "WGPUVertexBufferLayout[]", c_vertex_buffer_layout_list ) c_vertex_constants, c_vertex_entries = _get_override_constant_entries(vertex) - # H: nextInChain: WGPUChainedStruct *, module: WGPUShaderModule, entryPoint: char *, constantCount: int, constants: WGPUConstantEntry *, bufferCount: int, buffers: WGPUVertexBufferLayout * + # H: nextInChain: WGPUChainedStruct *, module: WGPUShaderModule, entryPoint: WGPUStringView, constantCount: int, constants: WGPUConstantEntry *, bufferCount: int, buffers: WGPUVertexBufferLayout * c_vertex_state = new_struct( "WGPUVertexState", + # not used: nextInChain module=vertex["module"]._internal, - entryPoint=to_c_string_or_null(vertex.get("entry_point")), - buffers=c_vertex_buffer_descriptors_array, - bufferCount=len(c_vertex_buffer_layout_list), + entryPoint=to_c_string_view(vertex.get("entry_point")), constantCount=len(c_vertex_entries), constants=c_vertex_constants, - # not used: nextInChain + bufferCount=len(c_vertex_buffer_layout_list), + buffers=c_vertex_buffer_descriptors_array, ) - # H: nextInChain: WGPUChainedStruct *, topology: WGPUPrimitiveTopology, stripIndexFormat: WGPUIndexFormat, frontFace: WGPUFrontFace, cullMode: WGPUCullMode + # H: nextInChain: WGPUChainedStruct *, topology: WGPUPrimitiveTopology, stripIndexFormat: WGPUIndexFormat, frontFace: WGPUFrontFace, cullMode: WGPUCullMode, unclippedDepth: WGPUBool/int c_primitive_state = new_struct( "WGPUPrimitiveState", + # not used: nextInChain topology=primitive.get("topology", "triangle-list"), stripIndexFormat=primitive.get("strip_index_format", 0), frontFace=primitive.get("front_face", "ccw"), cullMode=primitive.get("cull_mode", "none"), - # not used: nextInChain + # not used: unclippedDepth ) c_depth_stencil_state = ffi.NULL @@ -1797,10 +1998,10 @@ def _create_render_pipeline_descriptor( # H: nextInChain: WGPUChainedStruct *, count: int, mask: int, alphaToCoverageEnabled: WGPUBool/int c_multisample_state = new_struct( "WGPUMultisampleState", + # not used: nextInChain count=multisample.get("count", 1), mask=multisample.get("mask", 0xFFFFFFFF), alphaToCoverageEnabled=multisample.get("alpha_to_coverage_enabled", False), - # not used: nextInChain ) c_fragment_state = ffi.NULL @@ -1816,16 +2017,16 @@ def _create_render_pipeline_descriptor( c_fragment_constants, c_fragment_entries = _get_override_constant_entries( fragment ) - # H: nextInChain: WGPUChainedStruct *, module: WGPUShaderModule, entryPoint: char *, constantCount: int, constants: WGPUConstantEntry *, targetCount: int, targets: WGPUColorTargetState * + # H: nextInChain: WGPUChainedStruct *, module: WGPUShaderModule, entryPoint: WGPUStringView, constantCount: int, constants: WGPUConstantEntry *, targetCount: int, targets: WGPUColorTargetState * c_fragment_state = new_struct_p( "WGPUFragmentState *", + # not used: nextInChain module=fragment["module"]._internal, - entryPoint=to_c_string_or_null(fragment.get("entry_point")), - targets=c_color_targets_array, - targetCount=len(c_color_targets_list), + entryPoint=to_c_string_view(fragment.get("entry_point")), constantCount=len(c_fragment_entries), constants=c_fragment_constants, - # not used: nextInChain + targetCount=len(c_color_targets_list), + targets=c_color_targets_array, ) if isinstance(layout, GPUPipelineLayout): @@ -1837,17 +2038,17 @@ def _create_render_pipeline_descriptor( "create_render_pipeline() 'layout' arg must be a GPUPipelineLayout or 'auto'" ) - # H: nextInChain: WGPUChainedStruct *, label: char *, layout: WGPUPipelineLayout, vertex: WGPUVertexState, primitive: WGPUPrimitiveState, depthStencil: WGPUDepthStencilState *, multisample: WGPUMultisampleState, fragment: WGPUFragmentState * + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView, layout: WGPUPipelineLayout, vertex: WGPUVertexState, primitive: WGPUPrimitiveState, depthStencil: WGPUDepthStencilState *, multisample: WGPUMultisampleState, fragment: WGPUFragmentState * struct = new_struct_p( "WGPURenderPipelineDescriptor *", - label=to_c_label(label), + # not used: nextInChain + label=to_c_string_view(label), layout=layout_id, vertex=c_vertex_state, primitive=c_primitive_state, depthStencil=c_depth_stencil_state, multisample=c_multisample_state, fragment=c_fragment_state, - # not used: nextInChain ) return struct @@ -1874,13 +2075,13 @@ def _create_color_target_state(self, target): color=c_color_blend, alpha=c_alpha_blend, ) - # H: nextInChain: WGPUChainedStruct *, format: WGPUTextureFormat, blend: WGPUBlendState *, writeMask: WGPUColorWriteMaskFlags/int + # H: nextInChain: WGPUChainedStruct *, format: WGPUTextureFormat, blend: WGPUBlendState *, writeMask: WGPUColorWriteMask/int c_color_state = new_struct( "WGPUColorTargetState", + # not used: nextInChain format=target["format"], blend=c_blend, writeMask=target.get("write_mask", 0xF), - # not used: nextInChain ) return c_color_state @@ -1896,7 +2097,7 @@ def _create_vertex_buffer_layout(self, buffer_des): ) c_attributes_list.append(c_attribute) c_attributes_array = new_array("WGPUVertexAttribute[]", c_attributes_list) - # H: arrayStride: int, stepMode: WGPUVertexStepMode, attributeCount: int, attributes: WGPUVertexAttribute * + # H: stepMode: WGPUVertexStepMode, arrayStride: int, attributeCount: int, attributes: WGPUVertexAttribute * c_vertex_buffer_descriptor = new_struct( "WGPUVertexBufferLayout", arrayStride=buffer_des["array_stride"], @@ -1929,9 +2130,10 @@ def _create_depth_stencil_state(self, depth_stencil): depthFailOp=stencil_back.get("depth_fail_op", "keep"), passOp=stencil_back.get("pass_op", "keep"), ) - # H: nextInChain: WGPUChainedStruct *, format: WGPUTextureFormat, depthWriteEnabled: WGPUBool/int, depthCompare: WGPUCompareFunction, stencilFront: WGPUStencilFaceState, stencilBack: WGPUStencilFaceState, stencilReadMask: int, stencilWriteMask: int, depthBias: int, depthBiasSlopeScale: float, depthBiasClamp: float + # H: nextInChain: WGPUChainedStruct *, format: WGPUTextureFormat, depthWriteEnabled: WGPUOptionalBool, depthCompare: WGPUCompareFunction, stencilFront: WGPUStencilFaceState, stencilBack: WGPUStencilFaceState, stencilReadMask: int, stencilWriteMask: int, depthBias: int, depthBiasSlopeScale: float, depthBiasClamp: float c_depth_stencil_state = new_struct_p( "WGPUDepthStencilState *", + # not used: nextInChain format=depth_stencil["format"], depthWriteEnabled=bool(depth_stencil.get("depth_write_enabled", False)), depthCompare=depth_stencil.get("depth_compare", "always"), @@ -1942,16 +2144,15 @@ def _create_depth_stencil_state(self, depth_stencil): depthBias=depth_stencil.get("depth_bias", 0), depthBiasSlopeScale=depth_stencil.get("depth_bias_slope_scale", 0), depthBiasClamp=depth_stencil.get("depth_bias_clamp", 0), - # not used: nextInChain ) return c_depth_stencil_state def create_command_encoder(self, *, label: str = ""): - # H: nextInChain: WGPUChainedStruct *, label: char * + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView struct = new_struct_p( "WGPUCommandEncoderDescriptor *", - label=to_c_label(label), # not used: nextInChain + label=to_c_string_view(label), ) # H: WGPUCommandEncoder f(WGPUDevice device, WGPUCommandEncoderDescriptor const * descriptor) @@ -1974,17 +2175,17 @@ def create_render_bundle_encoder( c_color_formats = new_array("WGPUTextureFormat[]", color_formats_list) color_formats_count = len(color_formats_list) - # H: nextInChain: WGPUChainedStruct *, label: char *, colorFormatCount: int, colorFormats: WGPUTextureFormat *, depthStencilFormat: WGPUTextureFormat, sampleCount: int, depthReadOnly: WGPUBool/int, stencilReadOnly: WGPUBool/int + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView, colorFormatCount: int, colorFormats: WGPUTextureFormat *, depthStencilFormat: WGPUTextureFormat, sampleCount: int, depthReadOnly: WGPUBool/int, stencilReadOnly: WGPUBool/int render_bundle_encoder_descriptor = new_struct_p( "WGPURenderBundleEncoderDescriptor *", - label=to_c_label(label), + # not used: nextInChain + label=to_c_string_view(label), colorFormatCount=color_formats_count, colorFormats=c_color_formats, depthStencilFormat=depth_stencil_format or 0, sampleCount=sample_count, depthReadOnly=depth_read_only, stencilReadOnly=stencil_read_only, - # not used: nextInChain ) # H: WGPURenderBundleEncoder f(WGPUDevice device, WGPURenderBundleEncoderDescriptor const * descriptor) render_bundle_encoder_id = libf.wgpuDeviceCreateRenderBundleEncoder( @@ -2026,13 +2227,13 @@ def _create_query_set(self, label, type, count, statistics): ) next_in_chain = ffi.cast("WGPUChainedStruct *", query_set_descriptor_extras) - # H: nextInChain: WGPUChainedStruct *, label: char *, type: WGPUQueryType, count: int + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView, type: WGPUQueryType, count: int query_set_descriptor = new_struct_p( "WGPUQuerySetDescriptor *", - label=to_c_label(label), + nextInChain=next_in_chain, + label=to_c_string_view(label), type=type, count=count, - nextInChain=next_in_chain, ) # H: WGPUQuerySet f(WGPUDevice device, WGPUQuerySetDescriptor const * descriptor) @@ -2074,7 +2275,7 @@ def __init__(self, label, internal, device, size, usage, map_state): self._mapped_status = 0, self.size, flags.MapMode.WRITE def _get_size(self): - # H: WGPUBufferUsageFlags f(WGPUBuffer buffer) + # H: WGPUBufferUsage f(WGPUBuffer buffer) return libf.wgpuBufferGetUsage(self._internal) def _check_range(self, offset, size): @@ -2145,25 +2346,42 @@ def _map(self, mode, offset=0, size=None): # Setup awaitable - @ffi.callback("void(WGPUBufferMapAsyncStatus, void*)") - def callback(status, _user_data): - if status != 0: - awaitable.set_error(f"Could not map buffer ({status}).") + @ffi.callback("void(WGPUMapAsyncStatus, WGPUStringView, void *, void *)") + def buffer_map_callback(status, c_message, _userdata1, _userdata2): + if status != lib.WGPUMapAsyncStatus_Success: + msg = from_c_string_view(c_message) + awaitable.set_error(f"Could not map buffer ({status} : {msg}).") else: awaitable.set_result(status) + # H: nextInChain: WGPUChainedStruct *, mode: WGPUCallbackMode, callback: WGPUBufferMapCallback, userdata1: void*, userdata2: void* + buffer_map_callback_info = new_struct( + "WGPUBufferMapCallbackInfo", + # not used: nextInChain + mode=lib.WGPUCallbackMode_AllowProcessEvents, + callback=buffer_map_callback, + # not used: userdata1 + # not used: userdata2 + ) + def finalizer(_status): self._map_state = enums.BufferMapState.mapped self._mapped_status = offset, offset + size, mode self._mapped_memoryviews = [] - awaitable = WgpuAwaitable("buffer.map", callback, finalizer, self._device._poll) + awaitable = WgpuAwaitable( + "buffer.map", buffer_map_callback, finalizer, self._device._poll + ) # Map it self._map_state = enums.BufferMapState.pending - # H: void f(WGPUBuffer buffer, WGPUMapModeFlags mode, size_t offset, size_t size, WGPUBufferMapAsyncCallback callback, void * userdata) + # H: WGPUFuture f(WGPUBuffer buffer, WGPUMapMode mode, size_t offset, size_t size, WGPUBufferMapCallbackInfo callbackInfo) libf.wgpuBufferMapAsync( - self._internal, map_mode, offset, size, callback, ffi.NULL + self._internal, + map_mode, + offset, + size, + buffer_map_callback_info, ) return awaitable @@ -2298,6 +2516,7 @@ def create_view( label: str = "", format: enums.TextureFormat = optional, dimension: enums.TextureViewDimension = optional, + usage: flags.TextureUsage = 0, aspect: enums.TextureAspect = "all", base_mip_level: int = 0, mip_level_count: int = optional, @@ -2325,10 +2544,11 @@ def create_view( elif dimension in ("2d-array", "cube-array"): array_layer_count = self._tex_info["size"][2] - base_array_layer - # H: nextInChain: WGPUChainedStruct *, label: char *, format: WGPUTextureFormat, dimension: WGPUTextureViewDimension, baseMipLevel: int, mipLevelCount: int, baseArrayLayer: int, arrayLayerCount: int, aspect: WGPUTextureAspect + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView, format: WGPUTextureFormat, dimension: WGPUTextureViewDimension, baseMipLevel: int, mipLevelCount: int, baseArrayLayer: int, arrayLayerCount: int, aspect: WGPUTextureAspect, usage: WGPUTextureUsage/int struct = new_struct_p( "WGPUTextureViewDescriptor *", - label=to_c_label(label), + # not used: nextInChain + label=to_c_string_view(label), format=format, dimension=dimension, aspect=aspect, @@ -2336,7 +2556,7 @@ def create_view( mipLevelCount=mip_level_count, baseArrayLayer=base_array_layer, arrayLayerCount=array_layer_count, - # not used: nextInChain + usage=usage, ) # H: WGPUTextureView f(WGPUTexture texture, WGPUTextureViewDescriptor const * descriptor) @@ -2405,7 +2625,7 @@ def _get_compilation_info(self): # else: # pass # - # H: void f(WGPUShaderModule shaderModule, WGPUShaderModuleGetCompilationInfoCallback callback, void * userdata) + # H: WGPUFuture f(WGPUShaderModule shaderModule, WGPUCompilationInfoCallbackInfo callbackInfo) # libf.wgpuShaderModuleGetCompilationInfo(self._internal, callback, ffi.NULL) # # self._device._poll() @@ -2522,7 +2742,9 @@ def _set_push_constants(self, visibility, offset, size_in_bytes, data, data_offs raise ValueError("size_in_bytes + data_offset is too large") c_data = ffi.cast("void *", address) # do we want to add data_offset? - # H: void wgpuRenderPassEncoderSetPushConstants(WGPURenderPassEncoder encoder, WGPUShaderStageFlags stages, uint32_t offset, uint32_t sizeBytes, void const * data) + # H: void wgpuComputePassEncoderSetPushConstants(WGPUComputePassEncoder encoder, uint32_t offset, uint32_t sizeBytes, void const * data) + # H: void wgpuRenderPassEncoderSetPushConstants(WGPURenderPassEncoder encoder, WGPUShaderStage stages, uint32_t offset, uint32_t sizeBytes, void const * data) + # H: void wgpuRenderBundleEncoderSetPushConstants(WGPURenderBundleEncoder encoder, WGPUShaderStage stages, uint32_t offset, uint32_t sizeBytes, void const * data) function = type(self)._set_push_constants_function if function is None: self._not_implemented("set_push_constants") @@ -2531,6 +2753,7 @@ def _set_push_constants(self, visibility, offset, size_in_bytes, data, data_offs def _begin_pipeline_statistics_query(self, query_set, query_index): # H: void wgpuComputePassEncoderBeginPipelineStatisticsQuery(WGPUComputePassEncoder computePassEncoder, WGPUQuerySet querySet, uint32_t queryIndex) # H: void wgpuRenderPassEncoderBeginPipelineStatisticsQuery(WGPURenderPassEncoder renderPassEncoder, WGPUQuerySet querySet, uint32_t queryIndex) + # H: void wgpuRenderPassEncoderBeginPipelineStatisticsQuery(WGPURenderPassEncoder renderPassEncoder, WGPUQuerySet querySet, uint32_t queryIndex) function = type(self)._begin_pipeline_statistics_query_function if function is None: self._not_implemented("begin_pipeline_statistics") @@ -2539,6 +2762,7 @@ def _begin_pipeline_statistics_query(self, query_set, query_index): def _end_pipeline_statistics_query(self): # H: void wgpuComputePassEncoderEndPipelineStatisticsQuery(WGPUComputePassEncoder computePassEncoder) # H: void wgpuRenderPassEncoderEndPipelineStatisticsQuery(WGPURenderPassEncoder renderPassEncoder) + # H: void wgpuRenderPassEncoderEndPipelineStatisticsQuery(WGPURenderPassEncoder renderPassEncoder) function = type(self)._end_pipeline_statistics_query_function if function is None: self._not_implemented("end_pipeline_statistics") @@ -2551,11 +2775,11 @@ def _not_implemented(self, name) -> NoReturn: class GPUDebugCommandsMixin(classes.GPUDebugCommandsMixin): # whole class is likely going to be solved better: https://github.com/pygfx/wgpu-py/pull/546 def push_debug_group(self, group_label: str): - c_group_label = to_c_string(group_label) - # H: void wgpuCommandEncoderPushDebugGroup(WGPUCommandEncoder commandEncoder, char const * groupLabel) - # H: void wgpuComputePassEncoderPushDebugGroup(WGPUComputePassEncoder computePassEncoder, char const * groupLabel) - # H: void wgpuRenderPassEncoderPushDebugGroup(WGPURenderPassEncoder renderPassEncoder, char const * groupLabel) - # H: void wgpuRenderBundleEncoderPushDebugGroup(WGPURenderBundleEncoder renderBundleEncoder, char const * groupLabel) + c_group_label = to_c_string_view(group_label) + # H: void wgpuCommandEncoderPushDebugGroup(WGPUCommandEncoder commandEncoder, WGPUStringView groupLabel) + # H: void wgpuComputePassEncoderPushDebugGroup(WGPUComputePassEncoder computePassEncoder, WGPUStringView groupLabel) + # H: void wgpuRenderPassEncoderPushDebugGroup(WGPURenderPassEncoder renderPassEncoder, WGPUStringView groupLabel) + # H: void wgpuRenderBundleEncoderPushDebugGroup(WGPURenderBundleEncoder renderBundleEncoder, WGPUStringView groupLabel) function = type(self)._push_debug_group_function function(self._internal, c_group_label) @@ -2568,11 +2792,11 @@ def pop_debug_group(self): function(self._internal) def insert_debug_marker(self, marker_label: str): - c_marker_label = to_c_string(marker_label) - # H: void wgpuCommandEncoderInsertDebugMarker(WGPUCommandEncoder commandEncoder, char const * markerLabel) - # H: void wgpuComputePassEncoderInsertDebugMarker(WGPUComputePassEncoder computePassEncoder, char const * markerLabel) - # H: void wgpuRenderPassEncoderInsertDebugMarker(WGPURenderPassEncoder renderPassEncoder, char const * markerLabel) - # H: void wgpuRenderBundleEncoderInsertDebugMarker(WGPURenderBundleEncoder renderBundleEncoder, char const * markerLabel) + c_marker_label = to_c_string_view(marker_label) + # H: void wgpuCommandEncoderInsertDebugMarker(WGPUCommandEncoder commandEncoder, WGPUStringView markerLabel) + # H: void wgpuComputePassEncoderInsertDebugMarker(WGPUComputePassEncoder computePassEncoder, WGPUStringView markerLabel) + # H: void wgpuRenderPassEncoderInsertDebugMarker(WGPURenderPassEncoder renderPassEncoder, WGPUStringView markerLabel) + # H: void wgpuRenderBundleEncoderInsertDebugMarker(WGPURenderBundleEncoder renderBundleEncoder, WGPUStringView markerLabel) function = type(self)._insert_debug_marker_function function(self._internal, c_marker_label) @@ -2697,12 +2921,12 @@ def begin_compute_pass( "end_of_pass_write_index", lib.WGPU_QUERY_SET_INDEX_UNDEFINED ), ) - # H: nextInChain: WGPUChainedStruct *, label: char *, timestampWrites: WGPUComputePassTimestampWrites * + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView, timestampWrites: WGPUComputePassTimestampWrites * struct = new_struct_p( "WGPUComputePassDescriptor *", - label=to_c_label(label), - timestampWrites=c_timestamp_writes_struct, # not used: nextInChain + label=to_c_string_view(label), + timestampWrites=c_timestamp_writes_struct, ) # H: WGPUComputePassEncoder f(WGPUCommandEncoder commandEncoder, WGPUComputePassDescriptor const * descriptor) raw_encoder = libf.wgpuCommandEncoderBeginComputePass(self._internal, struct) @@ -2753,16 +2977,16 @@ def begin_render_pass( if occlusion_query_set is not None: c_occlusion_query_set = occlusion_query_set._internal - # H: nextInChain: WGPUChainedStruct *, label: char *, colorAttachmentCount: int, colorAttachments: WGPURenderPassColorAttachment *, depthStencilAttachment: WGPURenderPassDepthStencilAttachment *, occlusionQuerySet: WGPUQuerySet, timestampWrites: WGPURenderPassTimestampWrites * + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView, colorAttachmentCount: int, colorAttachments: WGPURenderPassColorAttachment *, depthStencilAttachment: WGPURenderPassDepthStencilAttachment *, occlusionQuerySet: WGPUQuerySet, timestampWrites: WGPURenderPassTimestampWrites * struct = new_struct_p( "WGPURenderPassDescriptor *", - label=to_c_label(label), + # not used: nextInChain + label=to_c_string_view(label), colorAttachments=c_color_attachments_array, colorAttachmentCount=len(c_color_attachments_list), depthStencilAttachment=c_depth_stencil_attachment, timestampWrites=c_timestamp_writes_struct, occlusionQuerySet=c_occlusion_query_set, - # not used: nextInChain ) # H: WGPURenderPassEncoder f(WGPUCommandEncoder commandEncoder, WGPURenderPassDescriptor const * descriptor) @@ -2796,6 +3020,7 @@ def _create_render_pass_color_attachment(self, color_attachment): # H: nextInChain: WGPUChainedStruct *, view: WGPUTextureView, depthSlice: int, resolveTarget: WGPUTextureView, loadOp: WGPULoadOp, storeOp: WGPUStoreOp, clearValue: WGPUColor c_attachment = new_struct( "WGPURenderPassColorAttachment", + # not used: nextInChain view=texture_view_id, resolveTarget=c_resolve_target, loadOp=color_attachment["load_op"], @@ -2803,7 +3028,6 @@ def _create_render_pass_color_attachment(self, color_attachment): clearValue=c_clear_value, depthSlice=lib.WGPU_DEPTH_SLICE_UNDEFINED, # not implemented yet # not used: resolveTarget - # not used: nextInChain ) return c_attachment @@ -2921,12 +3145,12 @@ def copy_buffer_to_buffer( def copy_buffer_to_texture( self, - source: structs.ImageCopyBuffer, - destination: structs.ImageCopyTexture, + source: structs.TexelCopyBufferInfo, + destination: structs.TexelCopyTextureInfo, copy_size: Union[List[int], structs.Extent3D], ): - check_struct("ImageCopyBuffer", source) - check_struct("ImageCopyTexture", destination) + check_struct("TexelCopyBufferInfo", source) + check_struct("TexelCopyTextureInfo", destination) row_alignment = 256 bytes_per_row = int(source["bytes_per_row"]) @@ -2939,17 +3163,17 @@ def copy_buffer_to_texture( size = _tuple_from_extent3d(copy_size) + # H: layout: WGPUTexelCopyBufferLayout, buffer: WGPUBuffer c_source = new_struct_p( - "WGPUImageCopyBuffer *", - buffer=source["buffer"]._internal, - # H: nextInChain: WGPUChainedStruct *, offset: int, bytesPerRow: int, rowsPerImage: int + "WGPUTexelCopyBufferInfo *", + # H: offset: int, bytesPerRow: int, rowsPerImage: int layout=new_struct( - "WGPUTextureDataLayout", + "WGPUTexelCopyBufferLayout", offset=int(source.get("offset", 0)), bytesPerRow=bytes_per_row, rowsPerImage=int(source.get("rows_per_image", size[1])), - # not used: nextInChain ), + buffer=source["buffer"]._internal, ) ori = _tuple_from_origin3d(destination) @@ -2960,14 +3184,13 @@ def copy_buffer_to_texture( y=ori[1], z=ori[2], ) - # H: nextInChain: WGPUChainedStruct *, texture: WGPUTexture, mipLevel: int, origin: WGPUOrigin3D, aspect: WGPUTextureAspect + # H: texture: WGPUTexture, mipLevel: int, origin: WGPUOrigin3D, aspect: WGPUTextureAspect c_destination = new_struct_p( - "WGPUImageCopyTexture *", + "WGPUTexelCopyTextureInfo *", texture=destination["texture"]._internal, mipLevel=int(destination.get("mip_level", 0)), origin=c_origin, aspect=enums.TextureAspect.all, - # not used: nextInChain ) # H: width: int, height: int, depthOrArrayLayers: int @@ -2978,7 +3201,7 @@ def copy_buffer_to_texture( depthOrArrayLayers=size[2], ) - # H: void f(WGPUCommandEncoder commandEncoder, WGPUImageCopyBuffer const * source, WGPUImageCopyTexture const * destination, WGPUExtent3D const * copySize) + # H: void f(WGPUCommandEncoder commandEncoder, WGPUTexelCopyBufferInfo const * source, WGPUTexelCopyTextureInfo const * destination, WGPUExtent3D const * copySize) libf.wgpuCommandEncoderCopyBufferToTexture( self._internal, c_source, @@ -2988,12 +3211,12 @@ def copy_buffer_to_texture( def copy_texture_to_buffer( self, - source: structs.ImageCopyTexture, - destination: structs.ImageCopyBuffer, + source: structs.TexelCopyTextureInfo, + destination: structs.TexelCopyBufferInfo, copy_size: Union[List[int], structs.Extent3D], ): - check_struct("ImageCopyTexture", source) - check_struct("ImageCopyBuffer", destination) + check_struct("TexelCopyTextureInfo", source) + check_struct("TexelCopyBufferInfo", destination) row_alignment = 256 bytes_per_row = int(destination["bytes_per_row"]) @@ -3014,27 +3237,26 @@ def copy_texture_to_buffer( y=ori[1], z=ori[2], ) - # H: nextInChain: WGPUChainedStruct *, texture: WGPUTexture, mipLevel: int, origin: WGPUOrigin3D, aspect: WGPUTextureAspect + # H: texture: WGPUTexture, mipLevel: int, origin: WGPUOrigin3D, aspect: WGPUTextureAspect c_source = new_struct_p( - "WGPUImageCopyTexture *", + "WGPUTexelCopyTextureInfo *", texture=source["texture"]._internal, mipLevel=int(source.get("mip_level", 0)), origin=c_origin, aspect=0, - # not used: nextInChain ) + # H: layout: WGPUTexelCopyBufferLayout, buffer: WGPUBuffer c_destination = new_struct_p( - "WGPUImageCopyBuffer *", - buffer=destination["buffer"]._internal, - # H: nextInChain: WGPUChainedStruct *, offset: int, bytesPerRow: int, rowsPerImage: int + "WGPUTexelCopyBufferInfo *", + # H: offset: int, bytesPerRow: int, rowsPerImage: int layout=new_struct( - "WGPUTextureDataLayout", + "WGPUTexelCopyBufferLayout", offset=int(destination.get("offset", 0)), bytesPerRow=bytes_per_row, rowsPerImage=int(destination.get("rows_per_image", size[1])), - # not used: nextInChain ), + buffer=destination["buffer"]._internal, ) # H: width: int, height: int, depthOrArrayLayers: int @@ -3045,7 +3267,7 @@ def copy_texture_to_buffer( depthOrArrayLayers=size[2], ) - # H: void f(WGPUCommandEncoder commandEncoder, WGPUImageCopyTexture const * source, WGPUImageCopyBuffer const * destination, WGPUExtent3D const * copySize) + # H: void f(WGPUCommandEncoder commandEncoder, WGPUTexelCopyTextureInfo const * source, WGPUTexelCopyBufferInfo const * destination, WGPUExtent3D const * copySize) libf.wgpuCommandEncoderCopyTextureToBuffer( self._internal, c_source, @@ -3055,12 +3277,12 @@ def copy_texture_to_buffer( def copy_texture_to_texture( self, - source: structs.ImageCopyTexture, - destination: structs.ImageCopyTexture, + source: structs.TexelCopyTextureInfo, + destination: structs.TexelCopyTextureInfo, copy_size: Union[List[int], structs.Extent3D], ): - check_struct("ImageCopyTexture", source) - check_struct("ImageCopyTexture", destination) + check_struct("TexelCopyTextureInfo", source) + check_struct("TexelCopyTextureInfo", destination) if isinstance(source["texture"], GPUTextureView): raise ValueError("copy source texture must be a texture, not a view") @@ -3075,13 +3297,12 @@ def copy_texture_to_texture( y=ori[1], z=ori[2], ) - # H: nextInChain: WGPUChainedStruct *, texture: WGPUTexture, mipLevel: int, origin: WGPUOrigin3D, aspect: WGPUTextureAspect + # H: texture: WGPUTexture, mipLevel: int, origin: WGPUOrigin3D, aspect: WGPUTextureAspect c_source = new_struct_p( - "WGPUImageCopyTexture *", + "WGPUTexelCopyTextureInfo *", texture=source["texture"]._internal, mipLevel=int(source.get("mip_level", 0)), origin=c_origin1, - # not used: nextInChain # not used: aspect ) @@ -3093,13 +3314,12 @@ def copy_texture_to_texture( y=ori[1], z=ori[2], ) - # H: nextInChain: WGPUChainedStruct *, texture: WGPUTexture, mipLevel: int, origin: WGPUOrigin3D, aspect: WGPUTextureAspect + # H: texture: WGPUTexture, mipLevel: int, origin: WGPUOrigin3D, aspect: WGPUTextureAspect c_destination = new_struct_p( - "WGPUImageCopyTexture *", + "WGPUTexelCopyTextureInfo *", texture=destination["texture"]._internal, mipLevel=int(destination.get("mip_level", 0)), origin=c_origin2, - # not used: nextInChain # not used: aspect ) @@ -3112,7 +3332,7 @@ def copy_texture_to_texture( depthOrArrayLayers=size[2], ) - # H: void f(WGPUCommandEncoder commandEncoder, WGPUImageCopyTexture const * source, WGPUImageCopyTexture const * destination, WGPUExtent3D const * copySize) + # H: void f(WGPUCommandEncoder commandEncoder, WGPUTexelCopyTextureInfo const * source, WGPUTexelCopyTextureInfo const * destination, WGPUExtent3D const * copySize) libf.wgpuCommandEncoderCopyTextureToTexture( self._internal, c_source, @@ -3121,11 +3341,11 @@ def copy_texture_to_texture( ) def finish(self, *, label: str = ""): - # H: nextInChain: WGPUChainedStruct *, label: char * + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView struct = new_struct_p( "WGPUCommandBufferDescriptor *", - label=to_c_label(label), # not used: nextInChain + label=to_c_string_view(label), ) # H: WGPUCommandBuffer f(WGPUCommandEncoder commandEncoder, WGPUCommandBufferDescriptor const * descriptor) id = libf.wgpuCommandEncoderFinish(self._internal, struct) @@ -3167,7 +3387,7 @@ class GPUComputePassEncoder( _set_bind_group_function = libf.wgpuComputePassEncoderSetBindGroup _begin_pipeline_statistics_query_function = libf.wgpuComputePassEncoderBeginPipelineStatisticsQuery # fmt: skip _end_pipeline_statistics_query_function = libf.wgpuComputePassEncoderEndPipelineStatisticsQuery # fmt: skip - _set_push_constants_function = None # coming soon + _set_push_constants_function = libf.wgpuComputePassEncoderSetPushConstants # GPUObjectBaseMixin _release_function = libf.wgpuComputePassEncoderRelease @@ -3319,6 +3539,32 @@ def _multi_draw_indexed_indirect(self, buffer, offset, count): self._internal, buffer._internal, int(offset), int(count) ) + def _multi_draw_indirect_count( + self, buffer, offset, count_buffer, count_buffer_offset, max_count + ): + # H: void f(WGPURenderPassEncoder encoder, WGPUBuffer buffer, uint64_t offset, WGPUBuffer count_buffer, uint64_t count_buffer_offset, uint32_t max_count) + libf.wgpuRenderPassEncoderMultiDrawIndirectCount( + self._internal, + buffer._internal, + int(offset), + count_buffer._internal, + int(count_buffer_offset), + int(max_count), + ) + + def _multi_draw_indexed_indirect_count( + self, buffer, offset, count_buffer, count_buffer_offset, max_count + ): + # H: void f(WGPURenderPassEncoder encoder, WGPUBuffer buffer, uint64_t offset, WGPUBuffer count_buffer, uint64_t count_buffer_offset, uint32_t max_count) + libf.wgpuRenderPassEncoderMultiDrawIndexedIndirectCount( + self._internal, + buffer._internal, + int(offset), + count_buffer._internal, + int(count_buffer_offset), + int(max_count), + ) + def _maybe_keep_alive(self, object): pass @@ -3338,9 +3584,9 @@ class GPURenderBundleEncoder( # GPUBindingCommandsMixin _set_bind_group_function = libf.wgpuRenderBundleEncoderSetBindGroup - _set_push_constants_function = None - _begin_pipeline_statistics_query_function = None - _end_pipeline_statistics_query_function = None + _set_push_constants_function = libf.wgpuRenderBundleEncoderSetPushConstants + _begin_pipeline_statistics_query_function = libf.wgpuRenderPassEncoderBeginPipelineStatisticsQuery # fmt: skip + _end_pipeline_statistics_query_function = libf.wgpuRenderPassEncoderEndPipelineStatisticsQuery # fmt: skip # GPURenderCommandsMixin _set_pipeline_function = libf.wgpuRenderBundleEncoderSetPipeline @@ -3355,11 +3601,11 @@ class GPURenderBundleEncoder( _release_function = libf.wgpuRenderBundleEncoderRelease def finish(self, *, label: str = ""): - # H: nextInChain: WGPUChainedStruct *, label: char * + # H: nextInChain: WGPUChainedStruct *, label: WGPUStringView struct = new_struct_p( "WGPURenderBundleDescriptor *", - label=to_c_label(label), # not used: nextInChain + label=to_c_string_view(label), ) # H: WGPURenderBundle f(WGPURenderBundleEncoder renderBundleEncoder, WGPURenderBundleDescriptor const * descriptor) id = libf.wgpuRenderBundleEncoderFinish(self._internal, struct) @@ -3460,16 +3706,16 @@ def read_buffer(self, buffer, buffer_offset=0, size=None): def write_texture( self, - destination: structs.ImageCopyTexture, + destination: structs.TexelCopyTextureInfo, data: memoryview, - data_layout: structs.ImageDataLayout, + data_layout: structs.TexelCopyBufferLayout, size: Union[List[int], structs.Extent3D], ): # Note that the bytes_per_row restriction does not apply for # this function; wgpu-native deals with it. - check_struct("ImageCopyTexture", destination) - check_struct("ImageDataLayout", data_layout) + check_struct("TexelCopyTextureInfo", destination) + check_struct("TexelCopyBufferLayout", data_layout) if isinstance(destination["texture"], GPUTextureView): raise ValueError("copy destination texture must be a texture, not a view") @@ -3498,23 +3744,21 @@ def write_texture( y=ori[1], z=ori[2], ) - # H: nextInChain: WGPUChainedStruct *, texture: WGPUTexture, mipLevel: int, origin: WGPUOrigin3D, aspect: WGPUTextureAspect + # H: texture: WGPUTexture, mipLevel: int, origin: WGPUOrigin3D, aspect: WGPUTextureAspect c_destination = new_struct_p( - "WGPUImageCopyTexture *", + "WGPUTexelCopyTextureInfo *", texture=destination["texture"]._internal, mipLevel=destination.get("mip_level", 0), origin=c_origin, aspect=enums.TextureAspect.all, - # not used: nextInChain ) - # H: nextInChain: WGPUChainedStruct *, offset: int, bytesPerRow: int, rowsPerImage: int + # H: offset: int, bytesPerRow: int, rowsPerImage: int c_data_layout = new_struct_p( - "WGPUTextureDataLayout *", + "WGPUTexelCopyBufferLayout *", offset=data_layout.get("offset", 0), bytesPerRow=data_layout["bytes_per_row"], rowsPerImage=data_layout.get("rows_per_image", size[1]), - # not used: nextInChain ) # H: width: int, height: int, depthOrArrayLayers: int @@ -3525,11 +3769,13 @@ def write_texture( depthOrArrayLayers=size[2], ) - # H: void f(WGPUQueue queue, WGPUImageCopyTexture const * destination, void const * data, size_t dataSize, WGPUTextureDataLayout const * dataLayout, WGPUExtent3D const * writeSize) + # H: void f(WGPUQueue queue, WGPUTexelCopyTextureInfo const * destination, void const * data, size_t dataSize, WGPUTexelCopyBufferLayout const * dataLayout, WGPUExtent3D const * writeSize) libf.wgpuQueueWriteTexture( self._internal, c_destination, c_data, data_length, c_data_layout, c_size ) + _shared_copy_buffer = None, 0 + def read_texture(self, source, data_layout, size): # Note that the bytes_per_row restriction does not apply for # this function; we have to deal with it. @@ -3537,20 +3783,40 @@ def read_texture(self, source, data_layout, size): device = source["texture"]._device # Get and calculate striding info + # Note that full_stride (bytes per row) must be a multiple of 256 ori_offset = data_layout.get("offset", 0) ori_stride = data_layout["bytes_per_row"] extra_stride = (256 - ori_stride % 256) % 256 full_stride = ori_stride + extra_stride size = _tuple_from_extent3d(size) + data_length = full_stride * size[1] * size[2] # Create temporary buffer - data_length = full_stride * size[1] * size[2] - tmp_usage = flags.BufferUsage.COPY_DST | flags.BufferUsage.MAP_READ - tmp_buffer = device._create_buffer("", data_length, tmp_usage, False) + is_present_texture = source["texture"].label == "present" + copy_buffer = None + if is_present_texture: + copy_buffer, time_since_size_ok = self._shared_copy_buffer + if copy_buffer is None: + pass # No buffer + elif copy_buffer.size < data_length: + copy_buffer = None # Buffer too small + elif copy_buffer.size < data_length * 4: + self._shared_copy_buffer = copy_buffer, time.time() # Bufer size ok + elif time.time() - time_since_size_ok > 5.0: + copy_buffer = None # Too large too long + if copy_buffer is None: + buffer_size = data_length + buffer_size += (4096 - buffer_size % 4096) % 4096 + buf_usage = flags.BufferUsage.COPY_DST | flags.BufferUsage.MAP_READ + copy_buffer = device._create_buffer( + "copy-buffer", buffer_size, buf_usage, False + ) + if is_present_texture: + self._shared_copy_buffer = copy_buffer, time.time() destination = { - "buffer": tmp_buffer, + "buffer": copy_buffer, "offset": 0, "bytes_per_row": full_stride, # or WGPU_COPY_STRIDE_UNDEFINED ? "rows_per_image": data_layout.get("rows_per_image", size[1]), @@ -3562,25 +3828,43 @@ def read_texture(self, source, data_layout, size): command_buffer = encoder.finish() self.submit([command_buffer]) + awaitable = copy_buffer._map("READ_NOSYNC", 0, data_length) + # Download from mappable buffer - tmp_buffer._map("READ_NOSYNC").sync_wait() - data = tmp_buffer.read_mapped() + # Because we use `copy=False``, we *must* copy the data. + if copy_buffer.map_state == "pending": + awaitable.sync_wait() + mapped_data = copy_buffer.read_mapped(copy=False) - # Explicit drop. - tmp_buffer.destroy() + data_length2 = ori_stride * size[1] * size[2] + ori_offset - # Fix data strides if necessary - # Ugh, cannot do striding with memoryviews (yet: https://bugs.python.org/issue41226) - # and Numpy is not a dependency. + # Copy the data if extra_stride or ori_offset: - data_length2 = ori_stride * size[1] * size[2] + ori_offset - data2 = memoryview(bytearray(data_length2)).cast(data.format) + # Copy per row + data = memoryview(bytearray(data_length2)).cast(mapped_data.format) + i_start = ori_offset for i in range(size[1] * size[2]): - row = data[i * full_stride : i * full_stride + ori_stride] - i_start = ori_offset + i * ori_stride - i_end = ori_offset + i * ori_stride + ori_stride - data2[i_start:i_end] = row - data = data2 + row = mapped_data[i * full_stride : i * full_stride + ori_stride] + data[i_start : i_start + ori_stride] = row + i_start += ori_stride + else: + # Copy as a whole + data = memoryview(bytearray(mapped_data)).cast(mapped_data.format) + + # Alternative copy solution using Numpy. + # I expected this to be faster, but does not really seem to be. Seems not worth it + # since we technically don't depend on Numpy. Leaving here for reference. + # import numpy as np + # mapped_data = np.asarray(mapped_data)[:data_length] + # data = np.empty(data_length2, dtype=mapped_data.dtype) + # mapped_data.shape = -1, full_stride + # data.shape = -1, ori_stride + # data[:] = mapped_data[:, :ori_stride] + # data.shape = -1 + # data = memoryview(data) + + # Since we use read_mapped(copy=False), we must unmap it *after* we've copied the data. + copy_buffer.unmap() return data @@ -3594,25 +3878,40 @@ async def on_submitted_work_done_async(self): await awaitable def _on_submitted_work_done(self): - @ffi.callback("void(WGPUQueueWorkDoneStatus, void*)") - def callback(status, _user_data_p): - if status == 0: + @ffi.callback("void(WGPUQueueWorkDoneStatus, void *, void *)") + def work_done_callback(status, _userdata1, _userdata2): + if status == lib.WGPUQueueWorkDoneStatus_Success: awaitable.set_result(True) else: - result = {1: "Error", 2: "Unknown", 3: "DeviceLost"}.get( - status, "Other" - ) + result = { + lib.WGPUQueueWorkDoneStatus_InstanceDropped: "InstanceDropped", + lib.WGPUQueueWorkDoneStatus_Error: "Error", + lib.WGPUQueueWorkDoneStatus_Unknown: "Unknown", + }.get(status, "Other") awaitable.set_error(f"Queue work done status: {result}") + # H: nextInChain: WGPUChainedStruct *, mode: WGPUCallbackMode, callback: WGPUQueueWorkDoneCallback, userdata1: void*, userdata2: void* + work_done_callback_info = new_struct( + "WGPUQueueWorkDoneCallbackInfo", + # not used: nextInChain + mode=lib.WGPUCallbackMode_AllowProcessEvents, + callback=work_done_callback, + # not used: userdata1 + # not used: userdata2 + ) + def finalizer(_value): return None awaitable = WgpuAwaitable( - "on_submitted_work_done", callback, finalizer, self._device._poll_wait + "on_submitted_work_done", + work_done_callback, + finalizer, + self._device._poll_wait, ) - # H: void f(WGPUQueue queue, WGPUQueueOnSubmittedWorkDoneCallback callback, void * userdata) - libf.wgpuQueueOnSubmittedWorkDone(self._internal, callback, ffi.NULL) + # H: WGPUFuture f(WGPUQueue queue, WGPUQueueWorkDoneCallbackInfo callbackInfo) + libf.wgpuQueueOnSubmittedWorkDone(self._internal, work_done_callback_info) return awaitable diff --git a/wgpu/backends/wgpu_native/_ffi.py b/wgpu/backends/wgpu_native/_ffi.py index 60d7066a..2cc34397 100644 --- a/wgpu/backends/wgpu_native/_ffi.py +++ b/wgpu/backends/wgpu_native/_ffi.py @@ -4,7 +4,11 @@ import sys import logging -from ..._coreutils import get_resource_filename, logger_set_level_callbacks +from ..._coreutils import ( + get_library_filename, + logger_set_level_callbacks, + get_header_filename, +) from cffi import FFI, __version_info__ as cffi_version_info @@ -19,8 +23,8 @@ def get_wgpu_header(): """Read header file and strip some stuff that cffi would stumble on.""" return _get_wgpu_header( - get_resource_filename("webgpu.h"), - get_resource_filename("wgpu.h"), + get_header_filename("webgpu.h"), + get_header_filename("wgpu.h"), ) @@ -29,13 +33,33 @@ def _get_wgpu_header(*filenames): # Read files lines1 = [] for filename in filenames: - with open(filename) as f: - lines1.extend(f.readlines()) + with open(filename, "rb") as f: + lines1.extend( + f.read() + .decode() + .replace("\r\n", "\n") + .replace("\\\n", "") + .splitlines(True) + ) # Deal with pre-processor commands, because cffi cannot handle them. # Just removing them, plus a few extra lines, seems to do the trick. lines2 = [] for line in lines1: - if line.startswith("#define ") and len(line.split()) > 2 and "0x" in line: + if ( + line.startswith("#define ") + and len(line.split()) > 2 + and ("0x" in line or "_MAX" in line) + ): + # pattern to find: #define WGPU_CONSTANT (0x1234) + # we use ffi.sizeof() to hopefully get the correct max sizes per platform + max_size = hex((1 << ffi.sizeof("size_t") * 8) - 1) + max_32 = hex((1 << ffi.sizeof("uint32_t") * 8) - 1) + max_64 = hex((1 << ffi.sizeof("uint64_t") * 8) - 1) + line = ( + line.replace("SIZE_MAX", max_size) + .replace("UINT32_MAX", max_32) + .replace("UINT64_MAX", max_64) + ) line = line.replace("(", "").replace(")", "") elif line.startswith("#"): continue @@ -66,38 +90,44 @@ def get_wgpu_lib_path(): # Load the debug binary if requested debug_mode = os.getenv("WGPU_DEBUG", "").strip() == "1" - build = "debug" if debug_mode else "release" - - # Get lib filename for supported platforms - if sys.platform.startswith("win"): # no-cover - lib_filename = f"wgpu_native-{build}.dll" - elif sys.platform.startswith("darwin"): # no-cover - lib_filename = f"libwgpu_native-{build}.dylib" - elif sys.platform.startswith("linux"): # no-cover - lib_filename = f"libwgpu_native-{build}.so" - else: # no-cover - raise RuntimeError( - f"No WGPU library shipped for platform {sys.platform}. Set WGPU_LIB_PATH instead." - ) - - # Note that this can be a false positive, e.g. ARM linux. - embedded_path = get_resource_filename(lib_filename) - if not os.path.isfile(embedded_path): # no-cover - env_hint = "You can set the WGPU_LIB_PATH env var to the location of the wgpu-native library." - download_hint = _maybe_get_hint_on_download_script().strip() + candidate_builds = ["-debug" if debug_mode else "-release"] + if not debug_mode: + candidate_builds.append("") + + for build in candidate_builds: + # Get lib filename for supported platforms + if sys.platform.startswith("win"): # no-cover + lib_filename = f"wgpu_native{build}.dll" + elif sys.platform.startswith("darwin"): # no-cover + lib_filename = f"libwgpu_native{build}.dylib" + elif sys.platform.startswith("linux"): # no-cover + lib_filename = f"libwgpu_native{build}.so" + else: # no-cover + raise RuntimeError( + f"No WGPU library shipped for platform {sys.platform}. Set WGPU_LIB_PATH instead." + ) + + try: + embedded_path = get_library_filename(lib_filename) + return embedded_path + except RuntimeError: + pass + else: + main_hint = "Could not find WGPU library libwpgu_native." pip_hint = _maybe_get_pip_hint().strip() - hints = [pip_hint, download_hint, env_hint] + download_hint = _maybe_get_hint_on_download_script().strip() + env_hint = "You can set the WGPU_LIB_PATH env var to the location of the wgpu-native library." + + hints = [main_hint, pip_hint, download_hint, env_hint] hints = "\n".join([hint for hint in hints if hint]) - hints = "\n" + hints if hints else "" - raise RuntimeError(f"Could not find WGPU library in {embedded_path}.{hints}") - else: - return embedded_path + raise RuntimeError(hints) def _maybe_get_hint_on_download_script(): - root_dir = os.path.join(get_resource_filename(""), "..", "..") + lib_module = sys.modules[__name__.split(".")[0]] + lib_dir = os.path.abspath(os.path.dirname(lib_module.__file__)) filename = os.path.abspath( - os.path.join(root_dir, "tools", "download_wgpu_native.py") + os.path.join(lib_dir, "..", "tools", "download_wgpu_native.py") ) uses_repo = os.path.isfile(filename) @@ -166,12 +196,12 @@ def _check_expected_version(version_info): ) -@ffi.callback("void(WGPULogLevel, char *, void *)") -def _logger_callback(level, c_msg, userdata): +@ffi.callback("void(WGPULogLevel, WGPUStringView, void *)") +def _logger_callback(level, message, userdata): """Called when Rust emits a log message.""" # Make a copy of the msg. Rust reclaims the memory when this returns try: - msg = ffi.string(c_msg).decode(errors="ignore") + msg = ffi.string(message.data, message.length).decode(errors="ignore") except Exception: if sys.is_finalizing(): return # Python is shutting down diff --git a/wgpu/backends/wgpu_native/_helpers.py b/wgpu/backends/wgpu_native/_helpers.py index 6a77fc32..7a6d0f94 100644 --- a/wgpu/backends/wgpu_native/_helpers.py +++ b/wgpu/backends/wgpu_native/_helpers.py @@ -1,9 +1,13 @@ """Utilities used in the wgpu-native backend.""" -import ctypes import sys import time +import types +import ctypes +import inspect +import threading from queue import deque +from collections.abc import Generator import sniffio @@ -102,10 +106,10 @@ def get_surface_id_from_info(present_info): if sys.platform.startswith("win"): # no-cover GetModuleHandle = ctypes.windll.kernel32.GetModuleHandleW # noqa: N806 - struct = ffi.new("WGPUSurfaceDescriptorFromWindowsHWND *") + struct = ffi.new("WGPUSurfaceSourceWindowsHWND *") struct.hinstance = ffi.cast("void *", GetModuleHandle(lib_path)) struct.hwnd = ffi.cast("void *", int(present_info["window"])) - struct.chain.sType = lib.WGPUSType_SurfaceDescriptorFromWindowsHWND + struct.chain.sType = lib.WGPUSType_SurfaceSourceWindowsHWND elif sys.platform.startswith("darwin"): # no-cover # This is what the triangle example from wgpu-native does: @@ -154,28 +158,28 @@ def get_surface_id_from_info(present_info): cv.setLayer(metal_layer) cv.setWantsLayer(True) - struct = ffi.new("WGPUSurfaceDescriptorFromMetalLayer *") + struct = ffi.new("WGPUSurfaceSourceMetalLayer *") struct.layer = ffi.cast("void *", metal_layer.ptr.value) - struct.chain.sType = lib.WGPUSType_SurfaceDescriptorFromMetalLayer + struct.chain.sType = lib.WGPUSType_SurfaceSourceMetalLayer elif sys.platform.startswith("linux"): # no-cover platform = present_info.get("platform", "x11") if platform == "x11": - struct = ffi.new("WGPUSurfaceDescriptorFromXlibWindow *") + struct = ffi.new("WGPUSurfaceSourceXlibWindow *") struct.display = ffi.cast("void *", present_info["display"]) struct.window = int(present_info["window"]) - struct.chain.sType = lib.WGPUSType_SurfaceDescriptorFromXlibWindow + struct.chain.sType = lib.WGPUSType_SurfaceSourceXlibWindow elif platform == "wayland": - struct = ffi.new("WGPUSurfaceDescriptorFromWaylandSurface *") + struct = ffi.new("WGPUSurfaceSourceWaylandSurface *") struct.display = ffi.cast("void *", present_info["display"]) struct.surface = ffi.cast("void *", present_info["window"]) - struct.chain.sType = lib.WGPUSType_SurfaceDescriptorFromWaylandSurface + struct.chain.sType = lib.WGPUSType_SurfaceSourceWaylandSurface elif platform == "xcb": # todo: xcb untested - struct = ffi.new("WGPUSurfaceDescriptorFromXcbWindow *") + struct = ffi.new("WGPUSurfaceSourceXCBWindow *") struct.connection = ffi.cast("void *", present_info["connection"]) # ?? struct.window = int(present_info["window"]) - struct.chain.sType = lib.WGPUSType_SurfaceDescriptorFromXlibWindow + struct.chain.sType = lib.WGPUSType_SurfaceSourceXCBWindow else: raise RuntimeError("Unexpected Linux surface platform '{platform}'.") @@ -183,7 +187,7 @@ def get_surface_id_from_info(present_info): raise RuntimeError("Cannot get surface id: unsupported platform.") surface_descriptor = ffi.new("WGPUSurfaceDescriptor *") - surface_descriptor.label = ffi.NULL + surface_descriptor.label.data = ffi.NULL # not setting label for now surface_descriptor.nextInChain = ffi.cast("WGPUChainedStruct *", struct) return lib.wgpuInstanceCreateSurface(get_wgpu_instance(), surface_descriptor) @@ -255,14 +259,8 @@ def set_result(self, result): def set_error(self, error): self.result = (None, error) - def _is_done(self): - self.poll_function() - return self.result is not None - def _finish(self): try: - if not self.result: - raise RuntimeError(f"Waiting for {self.title} timed out.") result, error = self.result if error: raise RuntimeError(error) @@ -278,27 +276,60 @@ def sync_wait(self): elif not self.poll_function: raise RuntimeError("Expected callback to have already happened") else: - while not self._is_done(): - time.sleep(0) + backoff_time_generator = self._get_backoff_time_generator() + while True: + self.poll_function() + if self.result is not None: + break + time.sleep(next(backoff_time_generator)) + # We check the result after sleeping just in case another thread + # causes the callback to happen + if self.result is not None: + break + return self._finish() def __await__(self): # There is no documentation on what __await__() is supposed to return, but we - # can certainly copy from a function that *does* know what to return + # can certainly copy from a function that *does* know what to return. + # It would also be nice if wait_for_callback and sync_wait() could be merged, + # but Python has no wait of combining them. async def wait_for_callback(): - # In all the async cases that I've tried, the result is either already set, or - # resolves after the first call to the poll function. To make sure that our - # sleep-logic actually works, we always do at least one sleep call. - await async_sleep(0) if self.result is not None: - return - if not self.poll_function: + pass + elif not self.poll_function: raise RuntimeError("Expected callback to have already happened") - while not self._is_done(): - await async_sleep(0) - - yield from wait_for_callback().__await__() - return self._finish() + else: + backoff_time_generator = self._get_backoff_time_generator() + while True: + self.poll_function() + if self.result is not None: + break + await async_sleep(next(backoff_time_generator)) + # We check the result after sleeping just in case another + # flow of control causes the callback to happen + if self.result is not None: + break + return self._finish() + + return (yield from wait_for_callback().__await__()) + + def _get_backoff_time_generator(self) -> Generator[float, None, None]: + for _ in range(5): + yield 0 + for i in range(1, 20): + yield i / 2000.0 # ramp up from 0ms to 10ms + while True: + yield 0.01 + + +class ErrorSlot: + __slot__ = ["name", "type", "message"] + + def __init__(self, name): + self.name = name + self.type = type + self.message = None class ErrorHandler: @@ -308,33 +339,58 @@ class ErrorHandler: def __init__(self, logger): self._logger = logger - self._proxy_stack = deque() - self._proxy_messages = {} - self._error_message_counts = {} + # threadlocal -> deque -> ErrorSlot + self._per_thread_data = threading.local() + + def _get_proxy_stack(self): + try: + return self._per_thread_data.stack + except AttributeError: + stack = deque() + self._per_thread_data.stack = stack + self._per_thread_data.error_message_counts = {} + return stack def capture(self, name): """Capture incoming error messages instead of logging them directly.""" - self._proxy_stack.append(name) + # This codepath must be as fast as it can be + self._get_proxy_stack().append(ErrorSlot(name)) def release(self, name): """Release the given name, returning the last captured error.""" - n = self._proxy_stack.pop() - if n is not name: - messages = [m for _, m in self._proxy_message.values()] - self._proxy_messages.clear() - self._proxy_stack.clear() + # This codepath, with matching name, must be as fast as it can be + + proxy_stack = self._get_proxy_stack() + try: + error_slot = proxy_stack.pop() + except IndexError: + error_slot = ErrorSlot("notavalidname") + + if error_slot.name == name: + if error_slot.message is None: + return None + else: + return error_slot.type, error_slot.message + else: + # This should never happen, but if it does, we want to know. self._logger.error("ErrorHandler capture/release out of sync") - for message in messages: - self.log_error(message) - return self._proxy_messages.pop(name, None) + if error_slot.message: + self.log_error(error_slot.message) + while proxy_stack: + es = proxy_stack.pop() + if es.message: + self.log_error(es.message) + return None def handle_error(self, error_type: str, message: str): """Handle an error message.""" - if self._proxy_stack: - proxy_name = self._proxy_stack[-1] - if proxy_name in self._proxy_messages: - self.log_error(self._proxy_messages[proxy_name][1]) - self._proxy_messages[proxy_name] = error_type, message + proxy_stack = self._get_proxy_stack() + if proxy_stack: + error_slot = proxy_stack[-1] + if error_slot.message: + self.log_error(error_slot.message) + error_slot.type = error_type + error_slot.message = message else: self.log_error(message) @@ -344,8 +400,10 @@ def log_error(self, message): # digits in the message, because of id's getting renewed on # each draw. h = hash("".join(c for c in message if not c.isdigit())) - count = self._error_message_counts.get(h, 0) + 1 - self._error_message_counts[h] = count + self._get_proxy_stack() # make sure the error_message_counts attribute exists + error_message_counts = self._per_thread_data.error_message_counts + count = error_message_counts.get(h, 0) + 1 + error_message_counts[h] = count # Decide what to do if count == 1: @@ -388,10 +446,15 @@ def proxy_func(*args): error_type, message = error_type_msg cls = ERROR_TYPES.get(error_type, GPUError) wgpu_error = cls(message) - # The line below will be the bottom line in the traceback, - # so better make it informative! As far as I know there is - # no way to exclude this frame from the traceback. - raise wgpu_error # the frame above is more interesting ↑↑ + # Select the traceback object matching the call that raised the error. The + # traceback will still actually show the line where we raise below, but the + # bottommost line (which ppl look at first) will be correct. + f = inspect.currentframe() + f = f.f_back + tb = types.TracebackType(None, f, f.f_lasti, f.f_lineno) + # Raise message with alt traceback + wgpu_error = wgpu_error.with_traceback(tb) + raise wgpu_error return result proxy_func.__name__ = name @@ -415,24 +478,21 @@ def generate_report(): "allocated": struct.surfaces.numAllocated, "kept": struct.surfaces.numKeptFromUser, "released": struct.surfaces.numReleasedFromUser, - "error": struct.surfaces.numError, "element_size": struct.surfaces.elementSize, } - for backend in ("vulkan", "metal", "dx12", "gl"): - c_hub_report = getattr(struct, backend) - report[backend] = {} - for key in dir(c_hub_report): - c_registry_report = getattr(c_hub_report, key) - registry_report = { - "allocated": c_registry_report.numAllocated, - "kept": c_registry_report.numKeptFromUser, - "released": c_registry_report.numReleasedFromUser, - "error": c_registry_report.numError, - "element_size": c_registry_report.elementSize, - } - # if any(x!=0 for x in registry_report.values()): - report[backend][key] = registry_report + c_hub_report = struct.hub + report["hub"] = {} + for key in dir(c_hub_report): + c_registry_report = getattr(c_hub_report, key) + registry_report = { + "allocated": c_registry_report.numAllocated, + "kept": c_registry_report.numKeptFromUser, + "released": c_registry_report.numReleasedFromUser, + "element_size": c_registry_report.elementSize, + } + # if any(x!=0 for x in registry_report.values()): + report["hub"][key] = registry_report return report @@ -440,7 +500,7 @@ def generate_report(): class WgpuNativeCountsDiagnostics(DiagnosticsBase): def get_subscript(self): text = "" - text += " * The a, k, r, e are allocated, kept, released, and error, respectively.\n" + text += " * The a, k, r are allocated, kept, and released, respectively.\n" text += " * Reported memory does not include buffer/texture data.\n" return text @@ -451,9 +511,8 @@ def get_dict(self): # Names in the root of the report (backend-less) root_names = ["surfaces"] - # Get per-backend names and a list of backends - names = list(native_report["vulkan"].keys()) - backends = [name for name in native_report.keys() if name not in root_names] + # Get names and for other objects + names = list(native_report["hub"].keys()) # Get a mapping from native names to wgpu-py names name_map = {"surfaces": "CanvasContext"} @@ -469,17 +528,7 @@ def get_dict(self): # the number of objects "allocated" by wgpu-core. In practice, # wgpu-core can keep objects around for re-use, which is why "allocated" # and released" are not in this equation. - fields_to_add = ["kept", "error"] - - # Establish what backends are active - active_backends = [] - for backend in backends: - total = 0 - for name in names: - d = native_report[backend][name] - total += sum(d[k] for k in fields_to_add) - if total > 0: - active_backends.append(backend) + fields_to_add = ["kept"] # Process names in the root for name in root_names: @@ -489,39 +538,36 @@ def get_dict(self): "a": d["allocated"], "k": d["kept"], "r": d["released"], - "e": d["error"], "el_size": d["element_size"], } # Store in report report_name = name_map[name] result[report_name]["count"] = subtotal_count result[report_name]["mem"] = subtotal_count * d["element_size"] - result[report_name]["backend"] = {"": impl} + result[report_name]["hub"] = {"": impl} - # Iterate over backends + # Iterate over names for name in names: total_count = 0 total_mem = 0 implementations = {} - for backend in active_backends: - d = native_report[backend][name] - subtotal_count = sum(d[k] for k in fields_to_add) - subtotal_mem = subtotal_count * d["element_size"] - impl = { - "a": d["allocated"], - "k": d["kept"], - "r": d["released"], - "e": d["error"], - "el_size": d["element_size"], - } - total_count += subtotal_count - total_mem += subtotal_mem - implementations[backend] = impl + d = native_report["hub"][name] + subtotal_count = sum(d[k] for k in fields_to_add) + subtotal_mem = subtotal_count * d["element_size"] + impl = { + "a": d["allocated"], + "k": d["kept"], + "r": d["released"], + "el_size": d["element_size"], + } + total_count += subtotal_count + total_mem += subtotal_mem + implementations["hub"] = impl # Store in report report_name = name_map[name] result[report_name]["count"] = total_count result[report_name]["mem"] = total_mem - result[report_name]["backend"] = implementations + result[report_name]["hub"] = implementations # Add totals totals = {} diff --git a/wgpu/backends/wgpu_native/_mappings.py b/wgpu/backends/wgpu_native/_mappings.py index 976671cc..bb572893 100644 --- a/wgpu/backends/wgpu_native/_mappings.py +++ b/wgpu/backends/wgpu_native/_mappings.py @@ -3,107 +3,116 @@ # THIS CODE IS AUTOGENERATED - DO NOT EDIT -# There are 236 enum mappings +# There are 255 enum mappings enummap = { - "AddressMode.clamp-to-edge": 2, - "AddressMode.mirror-repeat": 1, - "AddressMode.repeat": 0, - "BlendFactor.constant": 11, - "BlendFactor.dst": 6, - "BlendFactor.dst-alpha": 8, - "BlendFactor.one": 1, - "BlendFactor.one-minus-constant": 12, - "BlendFactor.one-minus-dst": 7, - "BlendFactor.one-minus-dst-alpha": 9, - "BlendFactor.one-minus-src": 3, - "BlendFactor.one-minus-src-alpha": 5, - "BlendFactor.src": 2, - "BlendFactor.src-alpha": 4, - "BlendFactor.src-alpha-saturated": 10, - "BlendFactor.zero": 0, - "BlendOperation.add": 0, - "BlendOperation.max": 4, - "BlendOperation.min": 3, - "BlendOperation.reverse-subtract": 2, - "BlendOperation.subtract": 1, - "BufferBindingType.read-only-storage": 3, - "BufferBindingType.storage": 2, - "BufferBindingType.uniform": 1, - "BufferMapState.mapped": 2, - "BufferMapState.pending": 1, - "BufferMapState.unmapped": 0, + "AddressMode.clamp-to-edge": 1, + "AddressMode.mirror-repeat": 3, + "AddressMode.repeat": 2, + "BlendFactor.constant": 12, + "BlendFactor.dst": 7, + "BlendFactor.dst-alpha": 9, + "BlendFactor.one": 2, + "BlendFactor.one-minus-constant": 13, + "BlendFactor.one-minus-dst": 8, + "BlendFactor.one-minus-dst-alpha": 10, + "BlendFactor.one-minus-src": 4, + "BlendFactor.one-minus-src-alpha": 6, + "BlendFactor.one-minus-src1": 15, + "BlendFactor.one-minus-src1-alpha": 17, + "BlendFactor.src": 3, + "BlendFactor.src-alpha": 5, + "BlendFactor.src-alpha-saturated": 11, + "BlendFactor.src1": 14, + "BlendFactor.src1-alpha": 16, + "BlendFactor.zero": 1, + "BlendOperation.add": 1, + "BlendOperation.max": 5, + "BlendOperation.min": 4, + "BlendOperation.reverse-subtract": 3, + "BlendOperation.subtract": 2, + "BufferBindingType.read-only-storage": 4, + "BufferBindingType.storage": 3, + "BufferBindingType.uniform": 2, + "BufferMapState.mapped": 3, + "BufferMapState.pending": 2, + "BufferMapState.unmapped": 1, "CompareFunction.always": 8, - "CompareFunction.equal": 6, - "CompareFunction.greater": 4, - "CompareFunction.greater-equal": 5, + "CompareFunction.equal": 3, + "CompareFunction.greater": 5, + "CompareFunction.greater-equal": 7, "CompareFunction.less": 2, - "CompareFunction.less-equal": 3, + "CompareFunction.less-equal": 4, "CompareFunction.never": 1, - "CompareFunction.not-equal": 7, - "CompilationMessageType.error": 0, - "CompilationMessageType.info": 2, - "CompilationMessageType.warning": 1, - "CullMode.back": 2, - "CullMode.front": 1, - "CullMode.none": 0, + "CompareFunction.not-equal": 6, + "CompilationMessageType.error": 1, + "CompilationMessageType.info": 3, + "CompilationMessageType.warning": 2, + "CullMode.back": 3, + "CullMode.front": 2, + "CullMode.none": 1, "DeviceLostReason.destroyed": 2, "DeviceLostReason.unknown": 1, - "ErrorFilter.internal": 2, - "ErrorFilter.out-of-memory": 1, - "ErrorFilter.validation": 0, - "FeatureName.bgra8unorm-storage": 10, + "ErrorFilter.internal": 3, + "ErrorFilter.out-of-memory": 2, + "ErrorFilter.validation": 1, + "FeatureName.bgra8unorm-storage": 12, + "FeatureName.clip-distances": 15, "FeatureName.depth-clip-control": 1, "FeatureName.depth32float-stencil8": 2, - "FeatureName.float32-filterable": 11, - "FeatureName.indirect-first-instance": 7, - "FeatureName.rg11b10ufloat-renderable": 9, - "FeatureName.shader-f16": 8, - "FeatureName.texture-compression-astc": 6, + "FeatureName.dual-source-blending": 16, + "FeatureName.float32-blendable": 14, + "FeatureName.float32-filterable": 13, + "FeatureName.indirect-first-instance": 9, + "FeatureName.rg11b10ufloat-renderable": 11, + "FeatureName.shader-f16": 10, + "FeatureName.texture-compression-astc": 7, + "FeatureName.texture-compression-astc-sliced-3d": 8, "FeatureName.texture-compression-bc": 4, - "FeatureName.texture-compression-etc2": 5, + "FeatureName.texture-compression-bc-sliced-3d": 5, + "FeatureName.texture-compression-etc2": 6, "FeatureName.timestamp-query": 3, - "FilterMode.linear": 1, - "FilterMode.nearest": 0, - "FrontFace.ccw": 0, - "FrontFace.cw": 1, + "FilterMode.linear": 2, + "FilterMode.nearest": 1, + "FrontFace.ccw": 1, + "FrontFace.cw": 2, "IndexFormat.uint16": 1, "IndexFormat.uint32": 2, - "LoadOp.clear": 1, - "LoadOp.load": 2, - "MipmapFilterMode.linear": 1, - "MipmapFilterMode.nearest": 0, + "LoadOp.clear": 2, + "LoadOp.load": 1, + "MipmapFilterMode.linear": 2, + "MipmapFilterMode.nearest": 1, "PowerPreference.high-performance": 2, "PowerPreference.low-power": 1, - "PrimitiveTopology.line-list": 1, - "PrimitiveTopology.line-strip": 2, - "PrimitiveTopology.point-list": 0, - "PrimitiveTopology.triangle-list": 3, - "PrimitiveTopology.triangle-strip": 4, - "QueryType.occlusion": 0, - "QueryType.timestamp": 1, - "SamplerBindingType.comparison": 3, - "SamplerBindingType.filtering": 1, - "SamplerBindingType.non-filtering": 2, - "StencilOperation.decrement-clamp": 5, - "StencilOperation.decrement-wrap": 7, - "StencilOperation.increment-clamp": 4, - "StencilOperation.increment-wrap": 6, - "StencilOperation.invert": 3, - "StencilOperation.keep": 0, - "StencilOperation.replace": 2, - "StencilOperation.zero": 1, - "StorageTextureAccess.read-only": 2, - "StorageTextureAccess.read-write": 3, - "StorageTextureAccess.write-only": 1, + "PrimitiveTopology.line-list": 2, + "PrimitiveTopology.line-strip": 3, + "PrimitiveTopology.point-list": 1, + "PrimitiveTopology.triangle-list": 4, + "PrimitiveTopology.triangle-strip": 5, + "QueryType.occlusion": 1, + "QueryType.timestamp": 2, + "SamplerBindingType.comparison": 4, + "SamplerBindingType.filtering": 2, + "SamplerBindingType.non-filtering": 3, + "StencilOperation.decrement-clamp": 6, + "StencilOperation.decrement-wrap": 8, + "StencilOperation.increment-clamp": 5, + "StencilOperation.increment-wrap": 7, + "StencilOperation.invert": 4, + "StencilOperation.keep": 1, + "StencilOperation.replace": 3, + "StencilOperation.zero": 2, + "StorageTextureAccess.read-only": 3, + "StorageTextureAccess.read-write": 4, + "StorageTextureAccess.write-only": 2, "StoreOp.discard": 2, "StoreOp.store": 1, - "TextureAspect.all": 0, - "TextureAspect.depth-only": 2, - "TextureAspect.stencil-only": 1, - "TextureDimension.1d": 0, - "TextureDimension.2d": 1, - "TextureDimension.3d": 2, + "TextureAspect.all": 1, + "TextureAspect.depth-only": 3, + "TextureAspect.stencil-only": 2, + "TextureDimension.1d": 1, + "TextureDimension.2d": 2, + "TextureDimension.3d": 3, "TextureFormat.astc-10x10-unorm": 90, "TextureFormat.astc-10x10-unorm-srgb": 91, "TextureFormat.astc-10x5-unorm": 84, @@ -199,49 +208,59 @@ "TextureFormat.rgba8unorm": 18, "TextureFormat.rgba8unorm-srgb": 19, "TextureFormat.stencil8": 38, - "TextureSampleType.depth": 3, - "TextureSampleType.float": 1, - "TextureSampleType.sint": 4, - "TextureSampleType.uint": 5, - "TextureSampleType.unfilterable-float": 2, + "TextureSampleType.depth": 4, + "TextureSampleType.float": 2, + "TextureSampleType.sint": 5, + "TextureSampleType.uint": 6, + "TextureSampleType.unfilterable-float": 3, "TextureViewDimension.1d": 1, "TextureViewDimension.2d": 2, "TextureViewDimension.2d-array": 3, "TextureViewDimension.3d": 6, "TextureViewDimension.cube": 4, "TextureViewDimension.cube-array": 5, - "VertexFormat.float16x2": 17, - "VertexFormat.float16x4": 18, - "VertexFormat.float32": 19, - "VertexFormat.float32x2": 20, - "VertexFormat.float32x3": 21, - "VertexFormat.float32x4": 22, - "VertexFormat.sint16x2": 11, - "VertexFormat.sint16x4": 12, - "VertexFormat.sint32": 27, - "VertexFormat.sint32x2": 28, - "VertexFormat.sint32x3": 29, - "VertexFormat.sint32x4": 30, - "VertexFormat.sint8x2": 3, - "VertexFormat.sint8x4": 4, - "VertexFormat.snorm16x2": 15, - "VertexFormat.snorm16x4": 16, - "VertexFormat.snorm8x2": 7, - "VertexFormat.snorm8x4": 8, - "VertexFormat.uint16x2": 9, - "VertexFormat.uint16x4": 10, - "VertexFormat.uint32": 23, - "VertexFormat.uint32x2": 24, - "VertexFormat.uint32x3": 25, - "VertexFormat.uint32x4": 26, - "VertexFormat.uint8x2": 1, - "VertexFormat.uint8x4": 2, - "VertexFormat.unorm16x2": 13, - "VertexFormat.unorm16x4": 14, - "VertexFormat.unorm8x2": 5, - "VertexFormat.unorm8x4": 6, - "VertexStepMode.instance": 1, - "VertexStepMode.vertex": 0, + "VertexFormat.float16": 25, + "VertexFormat.float16x2": 26, + "VertexFormat.float16x4": 27, + "VertexFormat.float32": 28, + "VertexFormat.float32x2": 29, + "VertexFormat.float32x3": 30, + "VertexFormat.float32x4": 31, + "VertexFormat.sint16": 16, + "VertexFormat.sint16x2": 17, + "VertexFormat.sint16x4": 18, + "VertexFormat.sint32": 36, + "VertexFormat.sint32x2": 37, + "VertexFormat.sint32x3": 38, + "VertexFormat.sint32x4": 39, + "VertexFormat.sint8": 4, + "VertexFormat.sint8x2": 5, + "VertexFormat.sint8x4": 6, + "VertexFormat.snorm16": 22, + "VertexFormat.snorm16x2": 23, + "VertexFormat.snorm16x4": 24, + "VertexFormat.snorm8": 10, + "VertexFormat.snorm8x2": 11, + "VertexFormat.snorm8x4": 12, + "VertexFormat.uint16": 13, + "VertexFormat.uint16x2": 14, + "VertexFormat.uint16x4": 15, + "VertexFormat.uint32": 32, + "VertexFormat.uint32x2": 33, + "VertexFormat.uint32x3": 34, + "VertexFormat.uint32x4": 35, + "VertexFormat.uint8": 1, + "VertexFormat.uint8x2": 2, + "VertexFormat.uint8x4": 3, + "VertexFormat.unorm16": 19, + "VertexFormat.unorm16x2": 20, + "VertexFormat.unorm16x4": 21, + "VertexFormat.unorm8": 7, + "VertexFormat.unorm8x2": 8, + "VertexFormat.unorm8x4": 9, + "VertexFormat.unorm8x4-bgra": 41, + "VertexStepMode.instance": 3, + "VertexStepMode.vertex": 2, } # There are 47 struct-field enum mappings @@ -255,7 +274,6 @@ "CompilationMessage.type": "CompilationMessageType", "DepthStencilState.depthCompare": "CompareFunction", "DepthStencilState.format": "TextureFormat", - "ImageCopyTexture.aspect": "TextureAspect", "PrimitiveState.cullMode": "CullMode", "PrimitiveState.frontFace": "FrontFace", "PrimitiveState.stripIndexFormat": "IndexFormat", @@ -285,6 +303,7 @@ "StorageTextureBindingLayout.format": "TextureFormat", "StorageTextureBindingLayout.viewDimension": "TextureViewDimension", "SurfaceConfiguration.format": "TextureFormat", + "TexelCopyTextureInfo.aspect": "TextureAspect", "TextureBindingLayout.sampleType": "TextureSampleType", "TextureBindingLayout.viewDimension": "TextureViewDimension", "TextureDescriptor.dimension": "TextureDimension", @@ -324,6 +343,7 @@ "mappable-primary-buffers": 196622, "buffer-binding-array": 196623, "uniform-buffer-and-storage-texture-array-non-uniform-indexing": 196624, + "spirv-shader-passthrough": 196631, "vertex-attribute64bit": 196633, "texture-format-nv12": 196634, "ray-tracing-acceleration-structure": 196635, @@ -332,6 +352,11 @@ "shader-i16": 196638, "shader-primitive-index": 196639, "shader-early-depth-test": 196640, + "subgroup": 196641, + "subgroup-vertex": 196642, + "subgroup-barrier": 196643, + "timestamp-query-inside-encoders": 196644, + "timestamp-query-inside-passes": 196645, }, "PipelineStatisticName": { "vertex-shader-invocations": 0, @@ -355,22 +380,23 @@ 8: "OpenGLES", }, "AdapterType": { - 0: "DiscreteGPU", - 1: "IntegratedGPU", - 2: "CPU", - 3: "Unknown", + 1: "DiscreteGPU", + 2: "IntegratedGPU", + 3: "CPU", + 4: "Unknown", }, "ErrorType": { - 0: "NoError", - 1: "Validation", - 2: "OutOfMemory", - 3: "Internal", - 4: "Unknown", - 5: "DeviceLost", + 1: "NoError", + 2: "Validation", + 3: "OutOfMemory", + 4: "Internal", + 5: "Unknown", }, "DeviceLostReason": { 1: "unknown", 2: "destroyed", + 3: "InstanceDropped", + 4: "FailedCreation", }, "TextureFormat": { 0: "Undefined", @@ -471,15 +497,17 @@ 95: "astc-12x12-unorm-srgb", }, "TextureDimension": { - 0: "1d", - 1: "2d", - 2: "3d", + 0: "Undefined", + 1: "1d", + 2: "2d", + 3: "3d", }, "PresentMode": { - 0: "Fifo", - 1: "FifoRelaxed", - 2: "Immediate", - 3: "Mailbox", + 0: "Undefined", + 1: "Fifo", + 2: "FifoRelaxed", + 3: "Immediate", + 4: "Mailbox", }, "CompositeAlphaMode": { 0: "Auto", diff --git a/wgpu/backends/wgpu_native/extras.py b/wgpu/backends/wgpu_native/extras.py index 28aed319..1ebc0f97 100644 --- a/wgpu/backends/wgpu_native/extras.py +++ b/wgpu/backends/wgpu_native/extras.py @@ -101,6 +101,52 @@ def multi_draw_indexed_indirect(render_pass_encoder, buffer, *, offset=0, count) render_pass_encoder._multi_draw_indexed_indirect(buffer, offset, count) +def multi_draw_indirect_count( + render_pass_encoder, + buffer, + *, + offset=0, + count_buffer, + count_buffer_offset=0, + max_count, +): + """ + This is equivalent to: + + count = min(, max_count) + for i in range(count): + render_pass_encoder.draw(buffer, offset + i * 16) + + You must enable the feature "multi-draw-indirect-count" to use this function. + """ + render_pass_encoder._multi_draw_indirect_count( + buffer, offset, count_buffer, count_buffer_offset, max_count + ) + + +def multi_draw_indexed_indirect_count( + render_pass_encoder, + buffer, + *, + offset=0, + count_buffer, + count_buffer_offset=0, + max_count, +): + """ + This is equivalent to: + + count = min(, max_count) + for i in range(count): + render_pass_encoder.draw_indexed(buffer, offset + i * 20) + + You must enable the feature "multi-draw-indirect-count" to use this function. + """ + render_pass_encoder._multi_draw_indexed_indirect_count( + buffer, offset, count_buffer, count_buffer_offset, max_count + ) + + def create_statistics_query_set(device, *, label="", count: int, statistics): """ Create a query set that can collect the specified pipeline statistics. diff --git a/wgpu/enums.py b/wgpu/enums.py index ecfe47f0..5804eda7 100644 --- a/wgpu/enums.py +++ b/wgpu/enums.py @@ -70,14 +70,17 @@ class FeatureName(Enum): texture_compression_bc_sliced_d3 = "texture-compression-bc-sliced-3d" texture_compression_etc2 = "texture-compression-etc2" texture_compression_astc = "texture-compression-astc" + texture_compression_astc_sliced_d3 = "texture-compression-astc-sliced-3d" timestamp_query = "timestamp-query" indirect_first_instance = "indirect-first-instance" shader_f16 = "shader-f16" rg11b10ufloat_renderable = "rg11b10ufloat-renderable" bgra8unorm_storage = "bgra8unorm-storage" float32_filterable = "float32-filterable" + float32_blendable = "float32-blendable" clip_distances = "clip-distances" dual_source_blending = "dual-source-blending" + subgroups = "subgroups" class BufferMapState(Enum): @@ -337,22 +340,31 @@ class IndexFormat(Enum): class VertexFormat(Enum): + uint8 = "uint8" uint8x2 = "uint8x2" uint8x4 = "uint8x4" + sint8 = "sint8" sint8x2 = "sint8x2" sint8x4 = "sint8x4" + unorm8 = "unorm8" unorm8x2 = "unorm8x2" unorm8x4 = "unorm8x4" + snorm8 = "snorm8" snorm8x2 = "snorm8x2" snorm8x4 = "snorm8x4" + uint16 = "uint16" uint16x2 = "uint16x2" uint16x4 = "uint16x4" + sint16 = "sint16" sint16x2 = "sint16x2" sint16x4 = "sint16x4" + unorm16 = "unorm16" unorm16x2 = "unorm16x2" unorm16x4 = "unorm16x4" + snorm16 = "snorm16" snorm16x2 = "snorm16x2" snorm16x4 = "snorm16x4" + float16 = "float16" float16x2 = "float16x2" float16x4 = "float16x4" float32 = "float32" @@ -368,6 +380,7 @@ class VertexFormat(Enum): sint32x3 = "sint32x3" sint32x4 = "sint32x4" unorm10_10_10_2 = "unorm10-10-10-2" + unorm8x4_bgra = "unorm8x4-bgra" class VertexStepMode(Enum): diff --git a/wgpu/gui/qt.py b/wgpu/gui/qt.py index 8265678a..898e7121 100644 --- a/wgpu/gui/qt.py +++ b/wgpu/gui/qt.py @@ -124,9 +124,16 @@ def enable_hidpi(): except Exception: pass # fail on non-windows try: - QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) + # This flag is not needed on Qt6 + # But it has been definitely giving me a warning since PySide 6.6 + # I'm a little cautious of removing its application for much older + # PySide so I'm going to conditionally disable it for "newer" PySide + # hmaarrfk -- 2024/12 + # https://doc.qt.io/qt-6/highdpi.html + if qt_version_info < (6, 6): + QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) except Exception: - pass # fail on older Qt's + pass # fail on much older Qt's # If you import this module, you want to use wgpu in a way that does not suck diff --git a/wgpu/resources/codegen_report.md b/wgpu/resources/codegen_report.md index 279fba39..d046aced 100644 --- a/wgpu/resources/codegen_report.md +++ b/wgpu/resources/codegen_report.md @@ -1,9 +1,9 @@ # Code generation report ## Preparing -* The webgpu.idl defines 37 classes with 75 functions +* The webgpu.idl defines 37 classes with 76 functions * The webgpu.idl defines 5 flags, 34 enums, 60 structs -* The wgpu.h defines 199 functions -* The wgpu.h defines 7 flags, 52 enums, 93 structs +* The wgpu.h defines 211 functions +* The wgpu.h defines 7 flags, 58 enums, 101 structs ## Updating API * Wrote 5 flags to flags.py * Wrote 34 enums to enums.py @@ -18,23 +18,17 @@ * Diffs for GPUTextureView: add size, add texture * Diffs for GPUBindingCommandsMixin: change set_bind_group * Diffs for GPUQueue: add read_buffer, add read_texture, hide copy_external_image_to_texture -* Validated 37 classes, 121 methods, 46 properties +* Validated 37 classes, 122 methods, 49 properties ### Patching API for backends/wgpu_native/_api.py -* Validated 37 classes, 121 methods, 0 properties +* Validated 37 classes, 123 methods, 0 properties ## Validating backends/wgpu_native/_api.py -* Enum field FeatureName.texture-compression-bc-sliced-3d missing in wgpu.h -* Enum field FeatureName.clip-distances missing in wgpu.h -* Enum field FeatureName.dual-source-blending missing in wgpu.h +* Enum field FeatureName.subgroups missing in wgpu.h * Enum PipelineErrorReason missing in wgpu.h * Enum AutoLayoutMode missing in wgpu.h -* Enum field BlendFactor.src1 missing in wgpu.h -* Enum field BlendFactor.one-minus-src1 missing in wgpu.h -* Enum field BlendFactor.src1-alpha missing in wgpu.h -* Enum field BlendFactor.one-minus-src1-alpha missing in wgpu.h * Enum field VertexFormat.unorm10-10-10-2 missing in wgpu.h * Enum CanvasAlphaMode missing in wgpu.h * Enum CanvasToneMappingMode missing in wgpu.h -* Wrote 236 enum mappings and 47 struct-field mappings to wgpu_native/_mappings.py -* Validated 142 C function calls -* Not using 64 C functions -* Validated 82 C structs +* Wrote 255 enum mappings and 47 struct-field mappings to wgpu_native/_mappings.py +* Validated 148 C function calls +* Not using 72 C functions +* Validated 95 C structs diff --git a/wgpu/resources/webgpu.h b/wgpu/resources/webgpu.h index cb423fc0..084ac1bb 100644 --- a/wgpu/resources/webgpu.h +++ b/wgpu/resources/webgpu.h @@ -1,6 +1,6 @@ /** * Copyright 2019-2023 WebGPU-Native developers - * + * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,7 +8,7 @@ /** * \mainpage - * + * * **Important:** *This documentation is a Work In Progress.* * * This is the home of WebGPU C API specification. We define here the standard @@ -55,42 +55,91 @@ #include #include +#define _wgpu_COMMA , +#if defined(__cplusplus) +# if __cplusplus >= 201103L +# define _wgpu_MAKE_INIT_STRUCT(type, value) (type value) +# else +# define _wgpu_MAKE_INIT_STRUCT(type, value) value +# endif +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +# define _wgpu_MAKE_INIT_STRUCT(type, value) ((type) value) +#else +# define _wgpu_MAKE_INIT_STRUCT(type, value) value +#endif + /** * \defgroup Constants * \brief Constants. - * + * * @{ */ -#define WGPU_ARRAY_LAYER_COUNT_UNDEFINED (0xffffffffUL) -#define WGPU_COPY_STRIDE_UNDEFINED (0xffffffffUL) -#define WGPU_DEPTH_SLICE_UNDEFINED (0xffffffffUL) -#define WGPU_LIMIT_U32_UNDEFINED (0xffffffffUL) -#define WGPU_LIMIT_U64_UNDEFINED (0xffffffffffffffffULL) -#define WGPU_MIP_LEVEL_COUNT_UNDEFINED (0xffffffffUL) -#define WGPU_QUERY_SET_INDEX_UNDEFINED (0xffffffffUL) +#define WGPU_ARRAY_LAYER_COUNT_UNDEFINED (UINT32_MAX) +#define WGPU_COPY_STRIDE_UNDEFINED (UINT32_MAX) +#define WGPU_DEPTH_SLICE_UNDEFINED (UINT32_MAX) +#define WGPU_LIMIT_U32_UNDEFINED (UINT32_MAX) +#define WGPU_LIMIT_U64_UNDEFINED (UINT64_MAX) +#define WGPU_MIP_LEVEL_COUNT_UNDEFINED (UINT32_MAX) +#define WGPU_QUERY_SET_INDEX_UNDEFINED (UINT32_MAX) #define WGPU_WHOLE_MAP_SIZE (SIZE_MAX) -#define WGPU_WHOLE_SIZE (0xffffffffffffffffULL) +#define WGPU_WHOLE_SIZE (UINT64_MAX) /** @} */ /** - * \defgroup Typedefs - * \brief Utility typedefs. - * + * \defgroup UtilityTypes Utility Types + * * @{ */ -typedef uint32_t WGPUFlags; +typedef uint64_t WGPUFlags; typedef uint32_t WGPUBool; +/** + * Nullable value defining a pointer+length view into a UTF-8 encoded string. + * + * Values passed into the API may use the special length value @ref WGPU_STRLEN + * to indicate a null-terminated string. + * Non-null values passed out of the API (for example as callback arguments) + * always provide an explicit length and **may or may not be null-terminated**. + * + * Some inputs to the API accept null values. Those which do not accept null + * values "default" to the empty string when null values are passed. + * + * Values are encoded as follows: + * - `{NULL, WGPU_STRLEN}`: the null value. + * - `{non_null_pointer, WGPU_STRLEN}`: a null-terminated string view. + * - `{any, 0}`: the empty string. + * - `{NULL, non_zero_length}`: not allowed (null dereference). + * - `{non_null_pointer, non_zero_length}`: an explictly-sized string view with + * size `non_zero_length` (in bytes). + * + * For info on how this is used in various places, see \ref Strings. + */ +typedef struct WGPUStringView { + char const * WGPU_NULLABLE data; + size_t length; +} WGPUStringView; + +/** + * Sentinel value used in @ref WGPUStringView to indicate that the pointer + * is to a null-terminated string, rather than an explicitly-sized string. + */ +#define WGPU_STRLEN SIZE_MAX + +#define WGPU_STRING_VIEW_INIT _wgpu_MAKE_INIT_STRUCT(WGPUStringView, { \ + /*.data=*/NULL _wgpu_COMMA \ + /*.length=*/WGPU_STRLEN _wgpu_COMMA \ +}) + /** @} */ /** * \defgroup Objects * \brief Opaque, non-dispatchable handles to WebGPU objects. - * + * * @{ */ typedef struct WGPUAdapterImpl* WGPUAdapter WGPU_OBJECT_ATTRIBUTE; @@ -112,6 +161,9 @@ typedef struct WGPURenderPassEncoderImpl* WGPURenderPassEncoder WGPU_OBJECT_ATTR typedef struct WGPURenderPipelineImpl* WGPURenderPipeline WGPU_OBJECT_ATTRIBUTE; typedef struct WGPUSamplerImpl* WGPUSampler WGPU_OBJECT_ATTRIBUTE; typedef struct WGPUShaderModuleImpl* WGPUShaderModule WGPU_OBJECT_ATTRIBUTE; +/** + * An object used to continuously present image data to the user, see @ref Surfaces for more details. + */ typedef struct WGPUSurfaceImpl* WGPUSurface WGPU_OBJECT_ATTRIBUTE; typedef struct WGPUTextureImpl* WGPUTexture WGPU_OBJECT_ATTRIBUTE; typedef struct WGPUTextureViewImpl* WGPUTextureView WGPU_OBJECT_ATTRIBUTE; @@ -131,43 +183,43 @@ struct WGPUCompilationMessage; struct WGPUComputePassTimestampWrites; struct WGPUConstantEntry; struct WGPUExtent3D; -struct WGPUInstanceDescriptor; +struct WGPUFuture; +struct WGPUInstanceCapabilities; struct WGPULimits; struct WGPUMultisampleState; struct WGPUOrigin3D; struct WGPUPipelineLayoutDescriptor; -struct WGPUPrimitiveDepthClipControl; struct WGPUPrimitiveState; struct WGPUQuerySetDescriptor; struct WGPUQueueDescriptor; struct WGPURenderBundleDescriptor; struct WGPURenderBundleEncoderDescriptor; struct WGPURenderPassDepthStencilAttachment; -struct WGPURenderPassDescriptorMaxDrawCount; +struct WGPURenderPassMaxDrawCount; struct WGPURenderPassTimestampWrites; struct WGPURequestAdapterOptions; struct WGPUSamplerBindingLayout; struct WGPUSamplerDescriptor; -struct WGPUShaderModuleCompilationHint; -struct WGPUShaderModuleSPIRVDescriptor; -struct WGPUShaderModuleWGSLDescriptor; +struct WGPUShaderModuleDescriptor; +struct WGPUShaderSourceSPIRV; +struct WGPUShaderSourceWGSL; struct WGPUStencilFaceState; struct WGPUStorageTextureBindingLayout; +struct WGPUSupportedFeatures; +struct WGPUSupportedWGSLLanguageFeatures; struct WGPUSurfaceCapabilities; struct WGPUSurfaceConfiguration; struct WGPUSurfaceDescriptor; -struct WGPUSurfaceDescriptorFromAndroidNativeWindow; -struct WGPUSurfaceDescriptorFromCanvasHTMLSelector; -struct WGPUSurfaceDescriptorFromMetalLayer; -struct WGPUSurfaceDescriptorFromWaylandSurface; -struct WGPUSurfaceDescriptorFromWindowsHWND; -struct WGPUSurfaceDescriptorFromXcbWindow; -struct WGPUSurfaceDescriptorFromXlibWindow; +struct WGPUSurfaceSourceAndroidNativeWindow; +struct WGPUSurfaceSourceMetalLayer; +struct WGPUSurfaceSourceWaylandSurface; +struct WGPUSurfaceSourceWindowsHWND; +struct WGPUSurfaceSourceXCBWindow; +struct WGPUSurfaceSourceXlibWindow; struct WGPUSurfaceTexture; +struct WGPUTexelCopyBufferLayout; struct WGPUTextureBindingLayout; -struct WGPUTextureDataLayout; struct WGPUTextureViewDescriptor; -struct WGPUUncapturedErrorCallbackInfo; struct WGPUVertexAttribute; struct WGPUBindGroupDescriptor; struct WGPUBindGroupLayoutEntry; @@ -175,47 +227,67 @@ struct WGPUBlendState; struct WGPUCompilationInfo; struct WGPUComputePassDescriptor; struct WGPUDepthStencilState; -struct WGPUImageCopyBuffer; -struct WGPUImageCopyTexture; +struct WGPUDeviceDescriptor; +struct WGPUFutureWaitInfo; +struct WGPUInstanceDescriptor; struct WGPUProgrammableStageDescriptor; struct WGPURenderPassColorAttachment; -struct WGPURequiredLimits; -struct WGPUShaderModuleDescriptor; -struct WGPUSupportedLimits; +struct WGPUTexelCopyBufferInfo; +struct WGPUTexelCopyTextureInfo; struct WGPUTextureDescriptor; struct WGPUVertexBufferLayout; struct WGPUBindGroupLayoutDescriptor; struct WGPUColorTargetState; struct WGPUComputePipelineDescriptor; -struct WGPUDeviceDescriptor; struct WGPURenderPassDescriptor; struct WGPUVertexState; struct WGPUFragmentState; struct WGPURenderPipelineDescriptor; +// Callback info structure forward declarations +struct WGPUBufferMapCallbackInfo; +struct WGPUCompilationInfoCallbackInfo; +struct WGPUCreateComputePipelineAsyncCallbackInfo; +struct WGPUCreateRenderPipelineAsyncCallbackInfo; +struct WGPUDeviceLostCallbackInfo; +struct WGPUPopErrorScopeCallbackInfo; +struct WGPUQueueWorkDoneCallbackInfo; +struct WGPURequestAdapterCallbackInfo; +struct WGPURequestDeviceCallbackInfo; +struct WGPUUncapturedErrorCallbackInfo; + /** * \defgroup Enumerations * \brief Enums. - * + * * @{ */ typedef enum WGPUAdapterType { - WGPUAdapterType_DiscreteGPU = 0x00000000, - WGPUAdapterType_IntegratedGPU = 0x00000001, - WGPUAdapterType_CPU = 0x00000002, - WGPUAdapterType_Unknown = 0x00000003, + WGPUAdapterType_DiscreteGPU = 0x00000001, + WGPUAdapterType_IntegratedGPU = 0x00000002, + WGPUAdapterType_CPU = 0x00000003, + WGPUAdapterType_Unknown = 0x00000004, WGPUAdapterType_Force32 = 0x7FFFFFFF } WGPUAdapterType WGPU_ENUM_ATTRIBUTE; typedef enum WGPUAddressMode { - WGPUAddressMode_Repeat = 0x00000000, - WGPUAddressMode_MirrorRepeat = 0x00000001, - WGPUAddressMode_ClampToEdge = 0x00000002, + /** + * `0x00000000`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ + WGPUAddressMode_Undefined = 0x00000000, + WGPUAddressMode_ClampToEdge = 0x00000001, + WGPUAddressMode_Repeat = 0x00000002, + WGPUAddressMode_MirrorRepeat = 0x00000003, WGPUAddressMode_Force32 = 0x7FFFFFFF } WGPUAddressMode WGPU_ENUM_ATTRIBUTE; typedef enum WGPUBackendType { + /** + * `0x00000000`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ WGPUBackendType_Undefined = 0x00000000, WGPUBackendType_Null = 0x00000001, WGPUBackendType_WebGPU = 0x00000002, @@ -229,165 +301,277 @@ typedef enum WGPUBackendType { } WGPUBackendType WGPU_ENUM_ATTRIBUTE; typedef enum WGPUBlendFactor { - WGPUBlendFactor_Zero = 0x00000000, - WGPUBlendFactor_One = 0x00000001, - WGPUBlendFactor_Src = 0x00000002, - WGPUBlendFactor_OneMinusSrc = 0x00000003, - WGPUBlendFactor_SrcAlpha = 0x00000004, - WGPUBlendFactor_OneMinusSrcAlpha = 0x00000005, - WGPUBlendFactor_Dst = 0x00000006, - WGPUBlendFactor_OneMinusDst = 0x00000007, - WGPUBlendFactor_DstAlpha = 0x00000008, - WGPUBlendFactor_OneMinusDstAlpha = 0x00000009, - WGPUBlendFactor_SrcAlphaSaturated = 0x0000000A, - WGPUBlendFactor_Constant = 0x0000000B, - WGPUBlendFactor_OneMinusConstant = 0x0000000C, + /** + * `0x00000000`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ + WGPUBlendFactor_Undefined = 0x00000000, + WGPUBlendFactor_Zero = 0x00000001, + WGPUBlendFactor_One = 0x00000002, + WGPUBlendFactor_Src = 0x00000003, + WGPUBlendFactor_OneMinusSrc = 0x00000004, + WGPUBlendFactor_SrcAlpha = 0x00000005, + WGPUBlendFactor_OneMinusSrcAlpha = 0x00000006, + WGPUBlendFactor_Dst = 0x00000007, + WGPUBlendFactor_OneMinusDst = 0x00000008, + WGPUBlendFactor_DstAlpha = 0x00000009, + WGPUBlendFactor_OneMinusDstAlpha = 0x0000000A, + WGPUBlendFactor_SrcAlphaSaturated = 0x0000000B, + WGPUBlendFactor_Constant = 0x0000000C, + WGPUBlendFactor_OneMinusConstant = 0x0000000D, + WGPUBlendFactor_Src1 = 0x0000000E, + WGPUBlendFactor_OneMinusSrc1 = 0x0000000F, + WGPUBlendFactor_Src1Alpha = 0x00000010, + WGPUBlendFactor_OneMinusSrc1Alpha = 0x00000011, WGPUBlendFactor_Force32 = 0x7FFFFFFF } WGPUBlendFactor WGPU_ENUM_ATTRIBUTE; typedef enum WGPUBlendOperation { - WGPUBlendOperation_Add = 0x00000000, - WGPUBlendOperation_Subtract = 0x00000001, - WGPUBlendOperation_ReverseSubtract = 0x00000002, - WGPUBlendOperation_Min = 0x00000003, - WGPUBlendOperation_Max = 0x00000004, + /** + * `0x00000000`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ + WGPUBlendOperation_Undefined = 0x00000000, + WGPUBlendOperation_Add = 0x00000001, + WGPUBlendOperation_Subtract = 0x00000002, + WGPUBlendOperation_ReverseSubtract = 0x00000003, + WGPUBlendOperation_Min = 0x00000004, + WGPUBlendOperation_Max = 0x00000005, WGPUBlendOperation_Force32 = 0x7FFFFFFF } WGPUBlendOperation WGPU_ENUM_ATTRIBUTE; typedef enum WGPUBufferBindingType { - WGPUBufferBindingType_Undefined = 0x00000000, - WGPUBufferBindingType_Uniform = 0x00000001, - WGPUBufferBindingType_Storage = 0x00000002, - WGPUBufferBindingType_ReadOnlyStorage = 0x00000003, + /** + * `0x00000000`. + * Indicates that this @ref WGPUBufferBindingLayout member of + * its parent @ref WGPUBindGroupLayoutEntry is not used. + * (See also @ref SentinelValues.) + */ + WGPUBufferBindingType_BindingNotUsed = 0x00000000, + /** + * `0x00000001`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ + WGPUBufferBindingType_Undefined = 0x00000001, + WGPUBufferBindingType_Uniform = 0x00000002, + WGPUBufferBindingType_Storage = 0x00000003, + WGPUBufferBindingType_ReadOnlyStorage = 0x00000004, WGPUBufferBindingType_Force32 = 0x7FFFFFFF } WGPUBufferBindingType WGPU_ENUM_ATTRIBUTE; -typedef enum WGPUBufferMapAsyncStatus { - WGPUBufferMapAsyncStatus_Success = 0x00000000, - WGPUBufferMapAsyncStatus_ValidationError = 0x00000001, - WGPUBufferMapAsyncStatus_Unknown = 0x00000002, - WGPUBufferMapAsyncStatus_DeviceLost = 0x00000003, - WGPUBufferMapAsyncStatus_DestroyedBeforeCallback = 0x00000004, - WGPUBufferMapAsyncStatus_UnmappedBeforeCallback = 0x00000005, - WGPUBufferMapAsyncStatus_MappingAlreadyPending = 0x00000006, - WGPUBufferMapAsyncStatus_OffsetOutOfRange = 0x00000007, - WGPUBufferMapAsyncStatus_SizeOutOfRange = 0x00000008, - WGPUBufferMapAsyncStatus_Force32 = 0x7FFFFFFF -} WGPUBufferMapAsyncStatus WGPU_ENUM_ATTRIBUTE; - typedef enum WGPUBufferMapState { - WGPUBufferMapState_Unmapped = 0x00000000, - WGPUBufferMapState_Pending = 0x00000001, - WGPUBufferMapState_Mapped = 0x00000002, + WGPUBufferMapState_Unmapped = 0x00000001, + WGPUBufferMapState_Pending = 0x00000002, + WGPUBufferMapState_Mapped = 0x00000003, WGPUBufferMapState_Force32 = 0x7FFFFFFF } WGPUBufferMapState WGPU_ENUM_ATTRIBUTE; +/** + * The callback mode controls how a callback for an asynchronous operation may be fired. See @ref Asynchronous-Operations for how these are used. + */ +typedef enum WGPUCallbackMode { + /** + * `0x00000001`. + * Callbacks created with `WGPUCallbackMode_WaitAnyOnly`: + * - fire when the asynchronous operation's future is passed to a call to `::wgpuInstanceWaitAny` + * AND the operation has already completed or it completes inside the call to `::wgpuInstanceWaitAny`. + */ + WGPUCallbackMode_WaitAnyOnly = 0x00000001, + /** + * `0x00000002`. + * Callbacks created with `WGPUCallbackMode_AllowProcessEvents`: + * - fire for the same reasons as callbacks created with `WGPUCallbackMode_WaitAnyOnly` + * - fire inside a call to `::wgpuInstanceProcessEvents` if the asynchronous operation is complete. + */ + WGPUCallbackMode_AllowProcessEvents = 0x00000002, + /** + * `0x00000003`. + * Callbacks created with `WGPUCallbackMode_AllowSpontaneous`: + * - fire for the same reasons as callbacks created with `WGPUCallbackMode_AllowProcessEvents` + * - **may** fire spontaneously on an arbitrary or application thread, when the WebGPU implementations discovers that the asynchronous operation is complete. + * + * Implementations _should_ fire spontaneous callbacks as soon as possible. + * + * @note Because spontaneous callbacks may fire at an arbitrary time on an arbitrary thread, applications should take extra care when acquiring locks or mutating state inside the callback. It undefined behavior to re-entrantly call into the webgpu.h API if the callback fires while inside the callstack of another webgpu.h function that is not `wgpuInstanceWaitAny` or `wgpuInstanceProcessEvents`. + */ + WGPUCallbackMode_AllowSpontaneous = 0x00000003, + WGPUCallbackMode_Force32 = 0x7FFFFFFF +} WGPUCallbackMode WGPU_ENUM_ATTRIBUTE; + typedef enum WGPUCompareFunction { + /** + * `0x00000000`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ WGPUCompareFunction_Undefined = 0x00000000, WGPUCompareFunction_Never = 0x00000001, WGPUCompareFunction_Less = 0x00000002, - WGPUCompareFunction_LessEqual = 0x00000003, - WGPUCompareFunction_Greater = 0x00000004, - WGPUCompareFunction_GreaterEqual = 0x00000005, - WGPUCompareFunction_Equal = 0x00000006, - WGPUCompareFunction_NotEqual = 0x00000007, + WGPUCompareFunction_Equal = 0x00000003, + WGPUCompareFunction_LessEqual = 0x00000004, + WGPUCompareFunction_Greater = 0x00000005, + WGPUCompareFunction_NotEqual = 0x00000006, + WGPUCompareFunction_GreaterEqual = 0x00000007, WGPUCompareFunction_Always = 0x00000008, WGPUCompareFunction_Force32 = 0x7FFFFFFF } WGPUCompareFunction WGPU_ENUM_ATTRIBUTE; typedef enum WGPUCompilationInfoRequestStatus { - WGPUCompilationInfoRequestStatus_Success = 0x00000000, - WGPUCompilationInfoRequestStatus_Error = 0x00000001, - WGPUCompilationInfoRequestStatus_DeviceLost = 0x00000002, - WGPUCompilationInfoRequestStatus_Unknown = 0x00000003, + WGPUCompilationInfoRequestStatus_Success = 0x00000001, + WGPUCompilationInfoRequestStatus_InstanceDropped = 0x00000002, + WGPUCompilationInfoRequestStatus_Error = 0x00000003, + WGPUCompilationInfoRequestStatus_Unknown = 0x00000004, WGPUCompilationInfoRequestStatus_Force32 = 0x7FFFFFFF } WGPUCompilationInfoRequestStatus WGPU_ENUM_ATTRIBUTE; typedef enum WGPUCompilationMessageType { - WGPUCompilationMessageType_Error = 0x00000000, - WGPUCompilationMessageType_Warning = 0x00000001, - WGPUCompilationMessageType_Info = 0x00000002, + WGPUCompilationMessageType_Error = 0x00000001, + WGPUCompilationMessageType_Warning = 0x00000002, + WGPUCompilationMessageType_Info = 0x00000003, WGPUCompilationMessageType_Force32 = 0x7FFFFFFF } WGPUCompilationMessageType WGPU_ENUM_ATTRIBUTE; +/** + * Describes how frames are composited with other contents on the screen when `::wgpuSurfacePresent` is called. + */ typedef enum WGPUCompositeAlphaMode { + /** + * `0x00000000`. + * Lets the WebGPU implementation choose the best mode (supported, and with the best performance) between @ref WGPUCompositeAlphaMode_Opaque or @ref WGPUCompositeAlphaMode_Inherit. + */ WGPUCompositeAlphaMode_Auto = 0x00000000, + /** + * `0x00000001`. + * The alpha component of the image is ignored and teated as if it is always 1.0. + */ WGPUCompositeAlphaMode_Opaque = 0x00000001, + /** + * `0x00000002`. + * The alpha component is respected and non-alpha components are assumed to be already multiplied with the alpha component. For example, (0.5, 0, 0, 0.5) is semi-transparent bright red. + */ WGPUCompositeAlphaMode_Premultiplied = 0x00000002, + /** + * `0x00000003`. + * The alpha component is respected and non-alpha components are assumed to NOT be already multiplied with the alpha component. For example, (1.0, 0, 0, 0.5) is semi-transparent bright red. + */ WGPUCompositeAlphaMode_Unpremultiplied = 0x00000003, + /** + * `0x00000004`. + * The handling of the alpha component is unknown to WebGPU and should be handled by the application using system-specific APIs. This mode may be unavailable (for example on Wasm). + */ WGPUCompositeAlphaMode_Inherit = 0x00000004, WGPUCompositeAlphaMode_Force32 = 0x7FFFFFFF } WGPUCompositeAlphaMode WGPU_ENUM_ATTRIBUTE; typedef enum WGPUCreatePipelineAsyncStatus { - WGPUCreatePipelineAsyncStatus_Success = 0x00000000, - WGPUCreatePipelineAsyncStatus_ValidationError = 0x00000001, - WGPUCreatePipelineAsyncStatus_InternalError = 0x00000002, - WGPUCreatePipelineAsyncStatus_DeviceLost = 0x00000003, - WGPUCreatePipelineAsyncStatus_DeviceDestroyed = 0x00000004, + WGPUCreatePipelineAsyncStatus_Success = 0x00000001, + WGPUCreatePipelineAsyncStatus_InstanceDropped = 0x00000002, + WGPUCreatePipelineAsyncStatus_ValidationError = 0x00000003, + WGPUCreatePipelineAsyncStatus_InternalError = 0x00000004, WGPUCreatePipelineAsyncStatus_Unknown = 0x00000005, WGPUCreatePipelineAsyncStatus_Force32 = 0x7FFFFFFF } WGPUCreatePipelineAsyncStatus WGPU_ENUM_ATTRIBUTE; typedef enum WGPUCullMode { - WGPUCullMode_None = 0x00000000, - WGPUCullMode_Front = 0x00000001, - WGPUCullMode_Back = 0x00000002, + /** + * `0x00000000`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ + WGPUCullMode_Undefined = 0x00000000, + WGPUCullMode_None = 0x00000001, + WGPUCullMode_Front = 0x00000002, + WGPUCullMode_Back = 0x00000003, WGPUCullMode_Force32 = 0x7FFFFFFF } WGPUCullMode WGPU_ENUM_ATTRIBUTE; typedef enum WGPUDeviceLostReason { WGPUDeviceLostReason_Unknown = 0x00000001, WGPUDeviceLostReason_Destroyed = 0x00000002, + WGPUDeviceLostReason_InstanceDropped = 0x00000003, + WGPUDeviceLostReason_FailedCreation = 0x00000004, WGPUDeviceLostReason_Force32 = 0x7FFFFFFF } WGPUDeviceLostReason WGPU_ENUM_ATTRIBUTE; typedef enum WGPUErrorFilter { - WGPUErrorFilter_Validation = 0x00000000, - WGPUErrorFilter_OutOfMemory = 0x00000001, - WGPUErrorFilter_Internal = 0x00000002, + WGPUErrorFilter_Validation = 0x00000001, + WGPUErrorFilter_OutOfMemory = 0x00000002, + WGPUErrorFilter_Internal = 0x00000003, WGPUErrorFilter_Force32 = 0x7FFFFFFF } WGPUErrorFilter WGPU_ENUM_ATTRIBUTE; typedef enum WGPUErrorType { - WGPUErrorType_NoError = 0x00000000, - WGPUErrorType_Validation = 0x00000001, - WGPUErrorType_OutOfMemory = 0x00000002, - WGPUErrorType_Internal = 0x00000003, - WGPUErrorType_Unknown = 0x00000004, - WGPUErrorType_DeviceLost = 0x00000005, + WGPUErrorType_NoError = 0x00000001, + WGPUErrorType_Validation = 0x00000002, + WGPUErrorType_OutOfMemory = 0x00000003, + WGPUErrorType_Internal = 0x00000004, + WGPUErrorType_Unknown = 0x00000005, WGPUErrorType_Force32 = 0x7FFFFFFF } WGPUErrorType WGPU_ENUM_ATTRIBUTE; +/** + * See @ref WGPURequestAdapterOptions::featureLevel. + */ +typedef enum WGPUFeatureLevel { + /** + * `0x00000001`. + * "Compatibility" profile which can be supported on OpenGL ES 3.1. + */ + WGPUFeatureLevel_Compatibility = 0x00000001, + /** + * `0x00000002`. + * "Core" profile which can be supported on Vulkan/Metal/D3D12. + */ + WGPUFeatureLevel_Core = 0x00000002, + WGPUFeatureLevel_Force32 = 0x7FFFFFFF +} WGPUFeatureLevel WGPU_ENUM_ATTRIBUTE; + typedef enum WGPUFeatureName { WGPUFeatureName_Undefined = 0x00000000, WGPUFeatureName_DepthClipControl = 0x00000001, WGPUFeatureName_Depth32FloatStencil8 = 0x00000002, WGPUFeatureName_TimestampQuery = 0x00000003, WGPUFeatureName_TextureCompressionBC = 0x00000004, - WGPUFeatureName_TextureCompressionETC2 = 0x00000005, - WGPUFeatureName_TextureCompressionASTC = 0x00000006, - WGPUFeatureName_IndirectFirstInstance = 0x00000007, - WGPUFeatureName_ShaderF16 = 0x00000008, - WGPUFeatureName_RG11B10UfloatRenderable = 0x00000009, - WGPUFeatureName_BGRA8UnormStorage = 0x0000000A, - WGPUFeatureName_Float32Filterable = 0x0000000B, + WGPUFeatureName_TextureCompressionBCSliced3D = 0x00000005, + WGPUFeatureName_TextureCompressionETC2 = 0x00000006, + WGPUFeatureName_TextureCompressionASTC = 0x00000007, + WGPUFeatureName_TextureCompressionASTCSliced3D = 0x00000008, + WGPUFeatureName_IndirectFirstInstance = 0x00000009, + WGPUFeatureName_ShaderF16 = 0x0000000A, + WGPUFeatureName_RG11B10UfloatRenderable = 0x0000000B, + WGPUFeatureName_BGRA8UnormStorage = 0x0000000C, + WGPUFeatureName_Float32Filterable = 0x0000000D, + WGPUFeatureName_Float32Blendable = 0x0000000E, + WGPUFeatureName_ClipDistances = 0x0000000F, + WGPUFeatureName_DualSourceBlending = 0x00000010, WGPUFeatureName_Force32 = 0x7FFFFFFF } WGPUFeatureName WGPU_ENUM_ATTRIBUTE; typedef enum WGPUFilterMode { - WGPUFilterMode_Nearest = 0x00000000, - WGPUFilterMode_Linear = 0x00000001, + /** + * `0x00000000`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ + WGPUFilterMode_Undefined = 0x00000000, + WGPUFilterMode_Nearest = 0x00000001, + WGPUFilterMode_Linear = 0x00000002, WGPUFilterMode_Force32 = 0x7FFFFFFF } WGPUFilterMode WGPU_ENUM_ATTRIBUTE; typedef enum WGPUFrontFace { - WGPUFrontFace_CCW = 0x00000000, - WGPUFrontFace_CW = 0x00000001, + /** + * `0x00000000`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ + WGPUFrontFace_Undefined = 0x00000000, + WGPUFrontFace_CCW = 0x00000001, + WGPUFrontFace_CW = 0x00000002, WGPUFrontFace_Force32 = 0x7FFFFFFF } WGPUFrontFace WGPU_ENUM_ATTRIBUTE; typedef enum WGPUIndexFormat { + /** + * `0x00000000`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ WGPUIndexFormat_Undefined = 0x00000000, WGPUIndexFormat_Uint16 = 0x00000001, WGPUIndexFormat_Uint32 = 0x00000002, @@ -395,147 +579,318 @@ typedef enum WGPUIndexFormat { } WGPUIndexFormat WGPU_ENUM_ATTRIBUTE; typedef enum WGPULoadOp { + /** + * `0x00000000`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ WGPULoadOp_Undefined = 0x00000000, - WGPULoadOp_Clear = 0x00000001, - WGPULoadOp_Load = 0x00000002, + WGPULoadOp_Load = 0x00000001, + WGPULoadOp_Clear = 0x00000002, WGPULoadOp_Force32 = 0x7FFFFFFF } WGPULoadOp WGPU_ENUM_ATTRIBUTE; +typedef enum WGPUMapAsyncStatus { + WGPUMapAsyncStatus_Success = 0x00000001, + WGPUMapAsyncStatus_InstanceDropped = 0x00000002, + WGPUMapAsyncStatus_Error = 0x00000003, + WGPUMapAsyncStatus_Aborted = 0x00000004, + WGPUMapAsyncStatus_Unknown = 0x00000005, + WGPUMapAsyncStatus_Force32 = 0x7FFFFFFF +} WGPUMapAsyncStatus WGPU_ENUM_ATTRIBUTE; + typedef enum WGPUMipmapFilterMode { - WGPUMipmapFilterMode_Nearest = 0x00000000, - WGPUMipmapFilterMode_Linear = 0x00000001, + /** + * `0x00000000`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ + WGPUMipmapFilterMode_Undefined = 0x00000000, + WGPUMipmapFilterMode_Nearest = 0x00000001, + WGPUMipmapFilterMode_Linear = 0x00000002, WGPUMipmapFilterMode_Force32 = 0x7FFFFFFF } WGPUMipmapFilterMode WGPU_ENUM_ATTRIBUTE; +typedef enum WGPUOptionalBool { + WGPUOptionalBool_False = 0x00000000, + WGPUOptionalBool_True = 0x00000001, + WGPUOptionalBool_Undefined = 0x00000002, + WGPUOptionalBool_Force32 = 0x7FFFFFFF +} WGPUOptionalBool WGPU_ENUM_ATTRIBUTE; + +typedef enum WGPUPopErrorScopeStatus { + /** + * `0x00000001`. + * The error scope stack was successfully popped and a result was reported. + */ + WGPUPopErrorScopeStatus_Success = 0x00000001, + WGPUPopErrorScopeStatus_InstanceDropped = 0x00000002, + /** + * `0x00000003`. + * The error scope stack could not be popped, because it was empty. + */ + WGPUPopErrorScopeStatus_EmptyStack = 0x00000003, + WGPUPopErrorScopeStatus_Force32 = 0x7FFFFFFF +} WGPUPopErrorScopeStatus WGPU_ENUM_ATTRIBUTE; + typedef enum WGPUPowerPreference { + /** + * `0x00000000`. + * No preference. (See also @ref SentinelValues.) + */ WGPUPowerPreference_Undefined = 0x00000000, WGPUPowerPreference_LowPower = 0x00000001, WGPUPowerPreference_HighPerformance = 0x00000002, WGPUPowerPreference_Force32 = 0x7FFFFFFF } WGPUPowerPreference WGPU_ENUM_ATTRIBUTE; +/** + * Describes when and in which order frames are presented on the screen when `::wgpuSurfacePresent` is called. + */ typedef enum WGPUPresentMode { - WGPUPresentMode_Fifo = 0x00000000, - WGPUPresentMode_FifoRelaxed = 0x00000001, - WGPUPresentMode_Immediate = 0x00000002, - WGPUPresentMode_Mailbox = 0x00000003, + /** + * `0x00000000`. + * Present mode is not specified. Use the default. + */ + WGPUPresentMode_Undefined = 0x00000000, + /** + * `0x00000001`. + * The presentation of the image to the user waits for the next vertical blanking period to update in a first-in, first-out manner. + * Tearing cannot be observed and frame-loop will be limited to the display's refresh rate. + * This is the only mode that's always available. + */ + WGPUPresentMode_Fifo = 0x00000001, + /** + * `0x00000002`. + * The presentation of the image to the user tries to wait for the next vertical blanking period but may decide to not wait if a frame is presented late. + * Tearing can sometimes be observed but late-frame don't produce a full-frame stutter in the presentation. + * This is still a first-in, first-out mechanism so a frame-loop will be limited to the display's refresh rate. + */ + WGPUPresentMode_FifoRelaxed = 0x00000002, + /** + * `0x00000003`. + * The presentation of the image to the user is updated immediately without waiting for a vertical blank. + * Tearing can be observed but latency is minimized. + */ + WGPUPresentMode_Immediate = 0x00000003, + /** + * `0x00000004`. + * The presentation of the image to the user waits for the next vertical blanking period to update to the latest provided image. + * Tearing cannot be observed and a frame-loop is not limited to the display's refresh rate. + */ + WGPUPresentMode_Mailbox = 0x00000004, WGPUPresentMode_Force32 = 0x7FFFFFFF } WGPUPresentMode WGPU_ENUM_ATTRIBUTE; typedef enum WGPUPrimitiveTopology { - WGPUPrimitiveTopology_PointList = 0x00000000, - WGPUPrimitiveTopology_LineList = 0x00000001, - WGPUPrimitiveTopology_LineStrip = 0x00000002, - WGPUPrimitiveTopology_TriangleList = 0x00000003, - WGPUPrimitiveTopology_TriangleStrip = 0x00000004, + /** + * `0x00000000`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ + WGPUPrimitiveTopology_Undefined = 0x00000000, + WGPUPrimitiveTopology_PointList = 0x00000001, + WGPUPrimitiveTopology_LineList = 0x00000002, + WGPUPrimitiveTopology_LineStrip = 0x00000003, + WGPUPrimitiveTopology_TriangleList = 0x00000004, + WGPUPrimitiveTopology_TriangleStrip = 0x00000005, WGPUPrimitiveTopology_Force32 = 0x7FFFFFFF } WGPUPrimitiveTopology WGPU_ENUM_ATTRIBUTE; typedef enum WGPUQueryType { - WGPUQueryType_Occlusion = 0x00000000, - WGPUQueryType_Timestamp = 0x00000001, + WGPUQueryType_Occlusion = 0x00000001, + WGPUQueryType_Timestamp = 0x00000002, WGPUQueryType_Force32 = 0x7FFFFFFF } WGPUQueryType WGPU_ENUM_ATTRIBUTE; typedef enum WGPUQueueWorkDoneStatus { - WGPUQueueWorkDoneStatus_Success = 0x00000000, - WGPUQueueWorkDoneStatus_Error = 0x00000001, - WGPUQueueWorkDoneStatus_Unknown = 0x00000002, - WGPUQueueWorkDoneStatus_DeviceLost = 0x00000003, + WGPUQueueWorkDoneStatus_Success = 0x00000001, + WGPUQueueWorkDoneStatus_InstanceDropped = 0x00000002, + WGPUQueueWorkDoneStatus_Error = 0x00000003, + WGPUQueueWorkDoneStatus_Unknown = 0x00000004, WGPUQueueWorkDoneStatus_Force32 = 0x7FFFFFFF } WGPUQueueWorkDoneStatus WGPU_ENUM_ATTRIBUTE; typedef enum WGPURequestAdapterStatus { - WGPURequestAdapterStatus_Success = 0x00000000, - WGPURequestAdapterStatus_Unavailable = 0x00000001, - WGPURequestAdapterStatus_Error = 0x00000002, - WGPURequestAdapterStatus_Unknown = 0x00000003, + WGPURequestAdapterStatus_Success = 0x00000001, + WGPURequestAdapterStatus_InstanceDropped = 0x00000002, + WGPURequestAdapterStatus_Unavailable = 0x00000003, + WGPURequestAdapterStatus_Error = 0x00000004, + WGPURequestAdapterStatus_Unknown = 0x00000005, WGPURequestAdapterStatus_Force32 = 0x7FFFFFFF } WGPURequestAdapterStatus WGPU_ENUM_ATTRIBUTE; typedef enum WGPURequestDeviceStatus { - WGPURequestDeviceStatus_Success = 0x00000000, - WGPURequestDeviceStatus_Error = 0x00000001, - WGPURequestDeviceStatus_Unknown = 0x00000002, + WGPURequestDeviceStatus_Success = 0x00000001, + WGPURequestDeviceStatus_InstanceDropped = 0x00000002, + WGPURequestDeviceStatus_Error = 0x00000003, + WGPURequestDeviceStatus_Unknown = 0x00000004, WGPURequestDeviceStatus_Force32 = 0x7FFFFFFF } WGPURequestDeviceStatus WGPU_ENUM_ATTRIBUTE; typedef enum WGPUSType { - WGPUSType_Invalid = 0x00000000, - WGPUSType_SurfaceDescriptorFromMetalLayer = 0x00000001, - WGPUSType_SurfaceDescriptorFromWindowsHWND = 0x00000002, - WGPUSType_SurfaceDescriptorFromXlibWindow = 0x00000003, - WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector = 0x00000004, - WGPUSType_ShaderModuleSPIRVDescriptor = 0x00000005, - WGPUSType_ShaderModuleWGSLDescriptor = 0x00000006, - WGPUSType_PrimitiveDepthClipControl = 0x00000007, - WGPUSType_SurfaceDescriptorFromWaylandSurface = 0x00000008, - WGPUSType_SurfaceDescriptorFromAndroidNativeWindow = 0x00000009, - WGPUSType_SurfaceDescriptorFromXcbWindow = 0x0000000A, - WGPUSType_RenderPassDescriptorMaxDrawCount = 0x0000000F, + WGPUSType_ShaderSourceSPIRV = 0x00000001, + WGPUSType_ShaderSourceWGSL = 0x00000002, + WGPUSType_RenderPassMaxDrawCount = 0x00000003, + WGPUSType_SurfaceSourceMetalLayer = 0x00000004, + WGPUSType_SurfaceSourceWindowsHWND = 0x00000005, + WGPUSType_SurfaceSourceXlibWindow = 0x00000006, + WGPUSType_SurfaceSourceWaylandSurface = 0x00000007, + WGPUSType_SurfaceSourceAndroidNativeWindow = 0x00000008, + WGPUSType_SurfaceSourceXCBWindow = 0x00000009, WGPUSType_Force32 = 0x7FFFFFFF } WGPUSType WGPU_ENUM_ATTRIBUTE; typedef enum WGPUSamplerBindingType { - WGPUSamplerBindingType_Undefined = 0x00000000, - WGPUSamplerBindingType_Filtering = 0x00000001, - WGPUSamplerBindingType_NonFiltering = 0x00000002, - WGPUSamplerBindingType_Comparison = 0x00000003, + /** + * `0x00000000`. + * Indicates that this @ref WGPUSamplerBindingLayout member of + * its parent @ref WGPUBindGroupLayoutEntry is not used. + * (See also @ref SentinelValues.) + */ + WGPUSamplerBindingType_BindingNotUsed = 0x00000000, + /** + * `0x00000001`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ + WGPUSamplerBindingType_Undefined = 0x00000001, + WGPUSamplerBindingType_Filtering = 0x00000002, + WGPUSamplerBindingType_NonFiltering = 0x00000003, + WGPUSamplerBindingType_Comparison = 0x00000004, WGPUSamplerBindingType_Force32 = 0x7FFFFFFF } WGPUSamplerBindingType WGPU_ENUM_ATTRIBUTE; +/** + * Status code returned (synchronously) from many operations. Generally + * indicates an invalid input like an unknown enum value or @ref OutStructChainError. + * Read the function's documentation for specific error conditions. + */ +typedef enum WGPUStatus { + WGPUStatus_Success = 0x00000001, + WGPUStatus_Error = 0x00000002, + WGPUStatus_Force32 = 0x7FFFFFFF +} WGPUStatus WGPU_ENUM_ATTRIBUTE; + typedef enum WGPUStencilOperation { - WGPUStencilOperation_Keep = 0x00000000, - WGPUStencilOperation_Zero = 0x00000001, - WGPUStencilOperation_Replace = 0x00000002, - WGPUStencilOperation_Invert = 0x00000003, - WGPUStencilOperation_IncrementClamp = 0x00000004, - WGPUStencilOperation_DecrementClamp = 0x00000005, - WGPUStencilOperation_IncrementWrap = 0x00000006, - WGPUStencilOperation_DecrementWrap = 0x00000007, + /** + * `0x00000000`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ + WGPUStencilOperation_Undefined = 0x00000000, + WGPUStencilOperation_Keep = 0x00000001, + WGPUStencilOperation_Zero = 0x00000002, + WGPUStencilOperation_Replace = 0x00000003, + WGPUStencilOperation_Invert = 0x00000004, + WGPUStencilOperation_IncrementClamp = 0x00000005, + WGPUStencilOperation_DecrementClamp = 0x00000006, + WGPUStencilOperation_IncrementWrap = 0x00000007, + WGPUStencilOperation_DecrementWrap = 0x00000008, WGPUStencilOperation_Force32 = 0x7FFFFFFF } WGPUStencilOperation WGPU_ENUM_ATTRIBUTE; typedef enum WGPUStorageTextureAccess { - WGPUStorageTextureAccess_Undefined = 0x00000000, - WGPUStorageTextureAccess_WriteOnly = 0x00000001, - WGPUStorageTextureAccess_ReadOnly = 0x00000002, - WGPUStorageTextureAccess_ReadWrite = 0x00000003, + /** + * `0x00000000`. + * Indicates that this @ref WGPUStorageTextureBindingLayout member of + * its parent @ref WGPUBindGroupLayoutEntry is not used. + * (See also @ref SentinelValues.) + */ + WGPUStorageTextureAccess_BindingNotUsed = 0x00000000, + /** + * `0x00000001`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ + WGPUStorageTextureAccess_Undefined = 0x00000001, + WGPUStorageTextureAccess_WriteOnly = 0x00000002, + WGPUStorageTextureAccess_ReadOnly = 0x00000003, + WGPUStorageTextureAccess_ReadWrite = 0x00000004, WGPUStorageTextureAccess_Force32 = 0x7FFFFFFF } WGPUStorageTextureAccess WGPU_ENUM_ATTRIBUTE; typedef enum WGPUStoreOp { + /** + * `0x00000000`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ WGPUStoreOp_Undefined = 0x00000000, WGPUStoreOp_Store = 0x00000001, WGPUStoreOp_Discard = 0x00000002, WGPUStoreOp_Force32 = 0x7FFFFFFF } WGPUStoreOp WGPU_ENUM_ATTRIBUTE; +/** + * The status enum for `::wgpuSurfaceGetCurrentTexture`. + */ typedef enum WGPUSurfaceGetCurrentTextureStatus { - WGPUSurfaceGetCurrentTextureStatus_Success = 0x00000000, - WGPUSurfaceGetCurrentTextureStatus_Timeout = 0x00000001, - WGPUSurfaceGetCurrentTextureStatus_Outdated = 0x00000002, - WGPUSurfaceGetCurrentTextureStatus_Lost = 0x00000003, - WGPUSurfaceGetCurrentTextureStatus_OutOfMemory = 0x00000004, - WGPUSurfaceGetCurrentTextureStatus_DeviceLost = 0x00000005, + /** + * `0x00000001`. + * Yay! Everything is good and we can render this frame. + */ + WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal = 0x00000001, + /** + * `0x00000002`. + * Still OK - the surface can present the frame, but in a suboptimal way. The surface may need reconfiguration. + */ + WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal = 0x00000002, + /** + * `0x00000003`. + * Some operation timed out while trying to acquire the frame. + */ + WGPUSurfaceGetCurrentTextureStatus_Timeout = 0x00000003, + /** + * `0x00000004`. + * The surface is too different to be used, compared to when it was originally created. + */ + WGPUSurfaceGetCurrentTextureStatus_Outdated = 0x00000004, + /** + * `0x00000005`. + * The connection to whatever owns the surface was lost. + */ + WGPUSurfaceGetCurrentTextureStatus_Lost = 0x00000005, + /** + * `0x00000006`. + * The system ran out of memory. + */ + WGPUSurfaceGetCurrentTextureStatus_OutOfMemory = 0x00000006, + /** + * `0x00000007`. + * The @ref WGPUDevice configured on the @ref WGPUSurface was lost. + */ + WGPUSurfaceGetCurrentTextureStatus_DeviceLost = 0x00000007, + /** + * `0x00000008`. + * The surface is not configured, or there was an @ref OutStructChainError. + */ + WGPUSurfaceGetCurrentTextureStatus_Error = 0x00000008, WGPUSurfaceGetCurrentTextureStatus_Force32 = 0x7FFFFFFF } WGPUSurfaceGetCurrentTextureStatus WGPU_ENUM_ATTRIBUTE; typedef enum WGPUTextureAspect { - WGPUTextureAspect_All = 0x00000000, - WGPUTextureAspect_StencilOnly = 0x00000001, - WGPUTextureAspect_DepthOnly = 0x00000002, + /** + * `0x00000000`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ + WGPUTextureAspect_Undefined = 0x00000000, + WGPUTextureAspect_All = 0x00000001, + WGPUTextureAspect_StencilOnly = 0x00000002, + WGPUTextureAspect_DepthOnly = 0x00000003, WGPUTextureAspect_Force32 = 0x7FFFFFFF } WGPUTextureAspect WGPU_ENUM_ATTRIBUTE; typedef enum WGPUTextureDimension { - WGPUTextureDimension_1D = 0x00000000, - WGPUTextureDimension_2D = 0x00000001, - WGPUTextureDimension_3D = 0x00000002, + /** + * `0x00000000`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ + WGPUTextureDimension_Undefined = 0x00000000, + WGPUTextureDimension_1D = 0x00000001, + WGPUTextureDimension_2D = 0x00000002, + WGPUTextureDimension_3D = 0x00000003, WGPUTextureDimension_Force32 = 0x7FFFFFFF } WGPUTextureDimension WGPU_ENUM_ATTRIBUTE; typedef enum WGPUTextureFormat { + /** + * `0x00000000`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ WGPUTextureFormat_Undefined = 0x00000000, WGPUTextureFormat_R8Unorm = 0x00000001, WGPUTextureFormat_R8Snorm = 0x00000002, @@ -636,16 +991,31 @@ typedef enum WGPUTextureFormat { } WGPUTextureFormat WGPU_ENUM_ATTRIBUTE; typedef enum WGPUTextureSampleType { - WGPUTextureSampleType_Undefined = 0x00000000, - WGPUTextureSampleType_Float = 0x00000001, - WGPUTextureSampleType_UnfilterableFloat = 0x00000002, - WGPUTextureSampleType_Depth = 0x00000003, - WGPUTextureSampleType_Sint = 0x00000004, - WGPUTextureSampleType_Uint = 0x00000005, + /** + * `0x00000000`. + * Indicates that this @ref WGPUTextureBindingLayout member of + * its parent @ref WGPUBindGroupLayoutEntry is not used. + * (See also @ref SentinelValues.) + */ + WGPUTextureSampleType_BindingNotUsed = 0x00000000, + /** + * `0x00000001`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ + WGPUTextureSampleType_Undefined = 0x00000001, + WGPUTextureSampleType_Float = 0x00000002, + WGPUTextureSampleType_UnfilterableFloat = 0x00000003, + WGPUTextureSampleType_Depth = 0x00000004, + WGPUTextureSampleType_Sint = 0x00000005, + WGPUTextureSampleType_Uint = 0x00000006, WGPUTextureSampleType_Force32 = 0x7FFFFFFF } WGPUTextureSampleType WGPU_ENUM_ATTRIBUTE; typedef enum WGPUTextureViewDimension { + /** + * `0x00000000`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ WGPUTextureViewDimension_Undefined = 0x00000000, WGPUTextureViewDimension_1D = 0x00000001, WGPUTextureViewDimension_2D = 0x00000002, @@ -657,148 +1027,241 @@ typedef enum WGPUTextureViewDimension { } WGPUTextureViewDimension WGPU_ENUM_ATTRIBUTE; typedef enum WGPUVertexFormat { - WGPUVertexFormat_Undefined = 0x00000000, - WGPUVertexFormat_Uint8x2 = 0x00000001, - WGPUVertexFormat_Uint8x4 = 0x00000002, - WGPUVertexFormat_Sint8x2 = 0x00000003, - WGPUVertexFormat_Sint8x4 = 0x00000004, - WGPUVertexFormat_Unorm8x2 = 0x00000005, - WGPUVertexFormat_Unorm8x4 = 0x00000006, - WGPUVertexFormat_Snorm8x2 = 0x00000007, - WGPUVertexFormat_Snorm8x4 = 0x00000008, - WGPUVertexFormat_Uint16x2 = 0x00000009, - WGPUVertexFormat_Uint16x4 = 0x0000000A, - WGPUVertexFormat_Sint16x2 = 0x0000000B, - WGPUVertexFormat_Sint16x4 = 0x0000000C, - WGPUVertexFormat_Unorm16x2 = 0x0000000D, - WGPUVertexFormat_Unorm16x4 = 0x0000000E, - WGPUVertexFormat_Snorm16x2 = 0x0000000F, - WGPUVertexFormat_Snorm16x4 = 0x00000010, - WGPUVertexFormat_Float16x2 = 0x00000011, - WGPUVertexFormat_Float16x4 = 0x00000012, - WGPUVertexFormat_Float32 = 0x00000013, - WGPUVertexFormat_Float32x2 = 0x00000014, - WGPUVertexFormat_Float32x3 = 0x00000015, - WGPUVertexFormat_Float32x4 = 0x00000016, - WGPUVertexFormat_Uint32 = 0x00000017, - WGPUVertexFormat_Uint32x2 = 0x00000018, - WGPUVertexFormat_Uint32x3 = 0x00000019, - WGPUVertexFormat_Uint32x4 = 0x0000001A, - WGPUVertexFormat_Sint32 = 0x0000001B, - WGPUVertexFormat_Sint32x2 = 0x0000001C, - WGPUVertexFormat_Sint32x3 = 0x0000001D, - WGPUVertexFormat_Sint32x4 = 0x0000001E, + WGPUVertexFormat_Uint8 = 0x00000001, + WGPUVertexFormat_Uint8x2 = 0x00000002, + WGPUVertexFormat_Uint8x4 = 0x00000003, + WGPUVertexFormat_Sint8 = 0x00000004, + WGPUVertexFormat_Sint8x2 = 0x00000005, + WGPUVertexFormat_Sint8x4 = 0x00000006, + WGPUVertexFormat_Unorm8 = 0x00000007, + WGPUVertexFormat_Unorm8x2 = 0x00000008, + WGPUVertexFormat_Unorm8x4 = 0x00000009, + WGPUVertexFormat_Snorm8 = 0x0000000A, + WGPUVertexFormat_Snorm8x2 = 0x0000000B, + WGPUVertexFormat_Snorm8x4 = 0x0000000C, + WGPUVertexFormat_Uint16 = 0x0000000D, + WGPUVertexFormat_Uint16x2 = 0x0000000E, + WGPUVertexFormat_Uint16x4 = 0x0000000F, + WGPUVertexFormat_Sint16 = 0x00000010, + WGPUVertexFormat_Sint16x2 = 0x00000011, + WGPUVertexFormat_Sint16x4 = 0x00000012, + WGPUVertexFormat_Unorm16 = 0x00000013, + WGPUVertexFormat_Unorm16x2 = 0x00000014, + WGPUVertexFormat_Unorm16x4 = 0x00000015, + WGPUVertexFormat_Snorm16 = 0x00000016, + WGPUVertexFormat_Snorm16x2 = 0x00000017, + WGPUVertexFormat_Snorm16x4 = 0x00000018, + WGPUVertexFormat_Float16 = 0x00000019, + WGPUVertexFormat_Float16x2 = 0x0000001A, + WGPUVertexFormat_Float16x4 = 0x0000001B, + WGPUVertexFormat_Float32 = 0x0000001C, + WGPUVertexFormat_Float32x2 = 0x0000001D, + WGPUVertexFormat_Float32x3 = 0x0000001E, + WGPUVertexFormat_Float32x4 = 0x0000001F, + WGPUVertexFormat_Uint32 = 0x00000020, + WGPUVertexFormat_Uint32x2 = 0x00000021, + WGPUVertexFormat_Uint32x3 = 0x00000022, + WGPUVertexFormat_Uint32x4 = 0x00000023, + WGPUVertexFormat_Sint32 = 0x00000024, + WGPUVertexFormat_Sint32x2 = 0x00000025, + WGPUVertexFormat_Sint32x3 = 0x00000026, + WGPUVertexFormat_Sint32x4 = 0x00000027, + WGPUVertexFormat_Unorm10_10_10_2 = 0x00000028, + WGPUVertexFormat_Unorm8x4BGRA = 0x00000029, WGPUVertexFormat_Force32 = 0x7FFFFFFF } WGPUVertexFormat WGPU_ENUM_ATTRIBUTE; typedef enum WGPUVertexStepMode { - WGPUVertexStepMode_Vertex = 0x00000000, - WGPUVertexStepMode_Instance = 0x00000001, - WGPUVertexStepMode_VertexBufferNotUsed = 0x00000002, + /** + * `0x00000000`. + * This @ref WGPUVertexBufferLayout is a "hole" in the @ref WGPUVertexState `buffers` array. + * (See also @ref SentinelValues.) + */ + WGPUVertexStepMode_VertexBufferNotUsed = 0x00000000, + /** + * `0x00000001`. + * Indicates no value is passed for this argument. See @ref SentinelValues. + */ + WGPUVertexStepMode_Undefined = 0x00000001, + WGPUVertexStepMode_Vertex = 0x00000002, + WGPUVertexStepMode_Instance = 0x00000003, WGPUVertexStepMode_Force32 = 0x7FFFFFFF } WGPUVertexStepMode WGPU_ENUM_ATTRIBUTE; -typedef enum WGPUWGSLFeatureName { - WGPUWGSLFeatureName_Undefined = 0x00000000, - WGPUWGSLFeatureName_ReadonlyAndReadwriteStorageTextures = 0x00000001, - WGPUWGSLFeatureName_Packed4x8IntegerDotProduct = 0x00000002, - WGPUWGSLFeatureName_UnrestrictedPointerParameters = 0x00000003, - WGPUWGSLFeatureName_PointerCompositeAccess = 0x00000004, - WGPUWGSLFeatureName_Force32 = 0x7FFFFFFF -} WGPUWGSLFeatureName WGPU_ENUM_ATTRIBUTE; +typedef enum WGPUWGSLLanguageFeatureName { + WGPUWGSLLanguageFeatureName_ReadonlyAndReadwriteStorageTextures = 0x00000001, + WGPUWGSLLanguageFeatureName_Packed4x8IntegerDotProduct = 0x00000002, + WGPUWGSLLanguageFeatureName_UnrestrictedPointerParameters = 0x00000003, + WGPUWGSLLanguageFeatureName_PointerCompositeAccess = 0x00000004, + WGPUWGSLLanguageFeatureName_Force32 = 0x7FFFFFFF +} WGPUWGSLLanguageFeatureName WGPU_ENUM_ATTRIBUTE; + +/** + * Status returned from a call to ::wgpuInstanceWaitAny. + */ +typedef enum WGPUWaitStatus { + /** + * `0x00000001`. + * At least one WGPUFuture completed successfully. + */ + WGPUWaitStatus_Success = 0x00000001, + /** + * `0x00000002`. + * No WGPUFutures completed within the timeout. + */ + WGPUWaitStatus_TimedOut = 0x00000002, + /** + * `0x00000003`. + * A @ref Timed-Wait was performed when WGPUInstanceFeatures::timedWaitAnyEnable is false. + */ + WGPUWaitStatus_UnsupportedTimeout = 0x00000003, + /** + * `0x00000004`. + * The number of futures waited on in a @ref Timed-Wait is greater than the supported WGPUInstanceFeatures::timedWaitAnyMaxCount. + */ + WGPUWaitStatus_UnsupportedCount = 0x00000004, + /** + * `0x00000005`. + * An invalid wait was performed with @ref Mixed-Sources. + */ + WGPUWaitStatus_UnsupportedMixedSources = 0x00000005, + WGPUWaitStatus_Force32 = 0x7FFFFFFF +} WGPUWaitStatus WGPU_ENUM_ATTRIBUTE; /** @} */ /** * \defgroup Bitflags - * \brief Enum used as bit flags. - * + * \brief Type and constant definitions for bitflag types. + * * @{ */ -typedef enum WGPUBufferUsage { - WGPUBufferUsage_None = 0x00000000, - WGPUBufferUsage_MapRead = 0x00000001, - WGPUBufferUsage_MapWrite = 0x00000002, - WGPUBufferUsage_CopySrc = 0x00000004, - WGPUBufferUsage_CopyDst = 0x00000008, - WGPUBufferUsage_Index = 0x00000010, - WGPUBufferUsage_Vertex = 0x00000020, - WGPUBufferUsage_Uniform = 0x00000040, - WGPUBufferUsage_Storage = 0x00000080, - WGPUBufferUsage_Indirect = 0x00000100, - WGPUBufferUsage_QueryResolve = 0x00000200, - WGPUBufferUsage_Force32 = 0x7FFFFFFF -} WGPUBufferUsage WGPU_ENUM_ATTRIBUTE; -typedef WGPUFlags WGPUBufferUsageFlags WGPU_ENUM_ATTRIBUTE; - -typedef enum WGPUColorWriteMask { - WGPUColorWriteMask_None = 0x00000000, - WGPUColorWriteMask_Red = 0x00000001, - WGPUColorWriteMask_Green = 0x00000002, - WGPUColorWriteMask_Blue = 0x00000004, - WGPUColorWriteMask_Alpha = 0x00000008, - WGPUColorWriteMask_All = WGPUColorWriteMask_None | WGPUColorWriteMask_Red | WGPUColorWriteMask_Green | WGPUColorWriteMask_Blue | WGPUColorWriteMask_Alpha, - WGPUColorWriteMask_Force32 = 0x7FFFFFFF -} WGPUColorWriteMask WGPU_ENUM_ATTRIBUTE; -typedef WGPUFlags WGPUColorWriteMaskFlags WGPU_ENUM_ATTRIBUTE; - -typedef enum WGPUMapMode { - WGPUMapMode_None = 0x00000000, - WGPUMapMode_Read = 0x00000001, - WGPUMapMode_Write = 0x00000002, - WGPUMapMode_Force32 = 0x7FFFFFFF -} WGPUMapMode WGPU_ENUM_ATTRIBUTE; -typedef WGPUFlags WGPUMapModeFlags WGPU_ENUM_ATTRIBUTE; - -typedef enum WGPUShaderStage { - WGPUShaderStage_None = 0x00000000, - WGPUShaderStage_Vertex = 0x00000001, - WGPUShaderStage_Fragment = 0x00000002, - WGPUShaderStage_Compute = 0x00000004, - WGPUShaderStage_Force32 = 0x7FFFFFFF -} WGPUShaderStage WGPU_ENUM_ATTRIBUTE; -typedef WGPUFlags WGPUShaderStageFlags WGPU_ENUM_ATTRIBUTE; - -typedef enum WGPUTextureUsage { - WGPUTextureUsage_None = 0x00000000, - WGPUTextureUsage_CopySrc = 0x00000001, - WGPUTextureUsage_CopyDst = 0x00000002, - WGPUTextureUsage_TextureBinding = 0x00000004, - WGPUTextureUsage_StorageBinding = 0x00000008, - WGPUTextureUsage_RenderAttachment = 0x00000010, - WGPUTextureUsage_Force32 = 0x7FFFFFFF -} WGPUTextureUsage WGPU_ENUM_ATTRIBUTE; -typedef WGPUFlags WGPUTextureUsageFlags WGPU_ENUM_ATTRIBUTE; +typedef WGPUFlags WGPUBufferUsage; +static const WGPUBufferUsage WGPUBufferUsage_None = 0x0000000000000000; +static const WGPUBufferUsage WGPUBufferUsage_MapRead = 0x0000000000000001; +static const WGPUBufferUsage WGPUBufferUsage_MapWrite = 0x0000000000000002; +static const WGPUBufferUsage WGPUBufferUsage_CopySrc = 0x0000000000000004; +static const WGPUBufferUsage WGPUBufferUsage_CopyDst = 0x0000000000000008; +static const WGPUBufferUsage WGPUBufferUsage_Index = 0x0000000000000010; +static const WGPUBufferUsage WGPUBufferUsage_Vertex = 0x0000000000000020; +static const WGPUBufferUsage WGPUBufferUsage_Uniform = 0x0000000000000040; +static const WGPUBufferUsage WGPUBufferUsage_Storage = 0x0000000000000080; +static const WGPUBufferUsage WGPUBufferUsage_Indirect = 0x0000000000000100; +static const WGPUBufferUsage WGPUBufferUsage_QueryResolve = 0x0000000000000200; + +typedef WGPUFlags WGPUColorWriteMask; +static const WGPUColorWriteMask WGPUColorWriteMask_None = 0x0000000000000000; +static const WGPUColorWriteMask WGPUColorWriteMask_Red = 0x0000000000000001; +static const WGPUColorWriteMask WGPUColorWriteMask_Green = 0x0000000000000002; +static const WGPUColorWriteMask WGPUColorWriteMask_Blue = 0x0000000000000004; +static const WGPUColorWriteMask WGPUColorWriteMask_Alpha = 0x0000000000000008; +static const WGPUColorWriteMask WGPUColorWriteMask_All = 0x000000000000000F /* Red | Green | Blue | Alpha */; + +typedef WGPUFlags WGPUMapMode; +static const WGPUMapMode WGPUMapMode_None = 0x0000000000000000; +static const WGPUMapMode WGPUMapMode_Read = 0x0000000000000001; +static const WGPUMapMode WGPUMapMode_Write = 0x0000000000000002; + +typedef WGPUFlags WGPUShaderStage; +static const WGPUShaderStage WGPUShaderStage_None = 0x0000000000000000; +static const WGPUShaderStage WGPUShaderStage_Vertex = 0x0000000000000001; +static const WGPUShaderStage WGPUShaderStage_Fragment = 0x0000000000000002; +static const WGPUShaderStage WGPUShaderStage_Compute = 0x0000000000000004; + +typedef WGPUFlags WGPUTextureUsage; +static const WGPUTextureUsage WGPUTextureUsage_None = 0x0000000000000000; +static const WGPUTextureUsage WGPUTextureUsage_CopySrc = 0x0000000000000001; +static const WGPUTextureUsage WGPUTextureUsage_CopyDst = 0x0000000000000002; +static const WGPUTextureUsage WGPUTextureUsage_TextureBinding = 0x0000000000000004; +static const WGPUTextureUsage WGPUTextureUsage_StorageBinding = 0x0000000000000008; +static const WGPUTextureUsage WGPUTextureUsage_RenderAttachment = 0x0000000000000010; /** @} */ typedef void (*WGPUProc)(void) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUDeviceLostCallback)(WGPUDeviceLostReason reason, char const * message, void * userdata) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUErrorCallback)(WGPUErrorType type, char const * message, void * userdata) WGPU_FUNCTION_ATTRIBUTE; /** * \defgroup Callbacks * \brief Callbacks through which asynchronous functions return. - * + * * @{ */ - -typedef void (*WGPUAdapterRequestDeviceCallback)(WGPURequestDeviceStatus status, WGPUDevice device, char const * message, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUBufferMapAsyncCallback)(WGPUBufferMapAsyncStatus status, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUDeviceCreateComputePipelineAsyncCallback)(WGPUCreatePipelineAsyncStatus status, WGPUComputePipeline pipeline, char const * message, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUDeviceCreateRenderPipelineAsyncCallback)(WGPUCreatePipelineAsyncStatus status, WGPURenderPipeline pipeline, char const * message, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUInstanceRequestAdapterCallback)(WGPURequestAdapterStatus status, WGPUAdapter adapter, char const * message, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUQueueOnSubmittedWorkDoneCallback)(WGPUQueueWorkDoneStatus status, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUShaderModuleGetCompilationInfoCallback)(WGPUCompilationInfoRequestStatus status, struct WGPUCompilationInfo const * compilationInfo, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; - +/** + * @param message + * This parameter is @ref PassedWithoutOwnership. + */ +typedef void (*WGPUBufferMapCallback)(WGPUMapAsyncStatus status, WGPUStringView message, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; +/** + * @param compilationInfo + * This parameter is @ref PassedWithoutOwnership. + */ +typedef void (*WGPUCompilationInfoCallback)(WGPUCompilationInfoRequestStatus status, struct WGPUCompilationInfo const * compilationInfo, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; +/** + * @param pipeline + * This parameter is @ref PassedWithOwnership. + */ +typedef void (*WGPUCreateComputePipelineAsyncCallback)(WGPUCreatePipelineAsyncStatus status, WGPUComputePipeline pipeline, WGPUStringView message, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; +/** + * @param pipeline + * This parameter is @ref PassedWithOwnership. + */ +typedef void (*WGPUCreateRenderPipelineAsyncCallback)(WGPUCreatePipelineAsyncStatus status, WGPURenderPipeline pipeline, WGPUStringView message, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; +/** + * @param device + * Reference to the device which was lost. If, and only if, the `reason` is @ref WGPUDeviceLostReason_FailedCreation, this is a non-null pointer to a null @ref WGPUDevice. + * This parameter is @ref PassedWithoutOwnership. + * + * @param message + * This parameter is @ref PassedWithoutOwnership. + */ +typedef void (*WGPUDeviceLostCallback)(WGPUDevice const * device, WGPUDeviceLostReason reason, WGPUStringView message, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; +/** + * @param status + * See @ref WGPUPopErrorScopeStatus. + * + * @param type + * The type of the error caught by the scope, or @ref WGPUErrorType_NoError if there was none. + * If the `status` is not @ref WGPUPopErrorScopeStatus_Success, this is @ref WGPUErrorType_NoError. + * + * @param message + * If the `type` is not @ref WGPUErrorType_NoError, this is a non-empty @ref LocalizableHumanReadableMessageString; + * otherwise, this is an empty string. + * This parameter is @ref PassedWithoutOwnership. + */ +typedef void (*WGPUPopErrorScopeCallback)(WGPUPopErrorScopeStatus status, WGPUErrorType type, WGPUStringView message, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; +typedef void (*WGPUQueueWorkDoneCallback)(WGPUQueueWorkDoneStatus status, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; +/** + * @param adapter + * This parameter is @ref PassedWithOwnership. + * + * @param message + * This parameter is @ref PassedWithoutOwnership. + */ +typedef void (*WGPURequestAdapterCallback)(WGPURequestAdapterStatus status, WGPUAdapter adapter, WGPUStringView message, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; +/** + * @param device + * This parameter is @ref PassedWithOwnership. + * + * @param message + * This parameter is @ref PassedWithoutOwnership. + */ +typedef void (*WGPURequestDeviceCallback)(WGPURequestDeviceStatus status, WGPUDevice device, WGPUStringView message, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; +/** + * @param device + * This parameter is @ref PassedWithoutOwnership. + * + * @param message + * This parameter is @ref PassedWithoutOwnership. + */ +typedef void (*WGPUUncapturedErrorCallback)(WGPUDevice const * device, WGPUErrorType type, WGPUStringView message, WGPU_NULLABLE void* userdata1, WGPU_NULLABLE void* userdata2) WGPU_FUNCTION_ATTRIBUTE; /** @} */ /** * \defgroup ChainedStructures Chained Structures * \brief Structures used to extend descriptors. - * + * * @{ */ @@ -818,15 +1281,115 @@ typedef struct WGPUChainedStructOut { /** * \defgroup Structures * \brief Descriptors and other transparent structures. - * + * + * @{ + */ + + /** + * \defgroup WGPUCallbackInfo + * \brief Callback info structures that are used in asynchronous functions. + * * @{ */ +typedef struct WGPUBufferMapCallbackInfo { + WGPUChainedStruct const * nextInChain; + WGPUCallbackMode mode; + WGPUBufferMapCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPUBufferMapCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +typedef struct WGPUCompilationInfoCallbackInfo { + WGPUChainedStruct const * nextInChain; + WGPUCallbackMode mode; + WGPUCompilationInfoCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPUCompilationInfoCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +typedef struct WGPUCreateComputePipelineAsyncCallbackInfo { + WGPUChainedStruct const * nextInChain; + WGPUCallbackMode mode; + WGPUCreateComputePipelineAsyncCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPUCreateComputePipelineAsyncCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +typedef struct WGPUCreateRenderPipelineAsyncCallbackInfo { + WGPUChainedStruct const * nextInChain; + WGPUCallbackMode mode; + WGPUCreateRenderPipelineAsyncCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPUCreateRenderPipelineAsyncCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +typedef struct WGPUDeviceLostCallbackInfo { + WGPUChainedStruct const * nextInChain; + WGPUCallbackMode mode; + WGPUDeviceLostCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPUDeviceLostCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +typedef struct WGPUPopErrorScopeCallbackInfo { + WGPUChainedStruct const * nextInChain; + WGPUCallbackMode mode; + WGPUPopErrorScopeCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPUPopErrorScopeCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +typedef struct WGPUQueueWorkDoneCallbackInfo { + WGPUChainedStruct const * nextInChain; + WGPUCallbackMode mode; + WGPUQueueWorkDoneCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPUQueueWorkDoneCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +typedef struct WGPURequestAdapterCallbackInfo { + WGPUChainedStruct const * nextInChain; + WGPUCallbackMode mode; + WGPURequestAdapterCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPURequestAdapterCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +typedef struct WGPURequestDeviceCallbackInfo { + WGPUChainedStruct const * nextInChain; + WGPUCallbackMode mode; + WGPURequestDeviceCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPURequestDeviceCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +typedef struct WGPUUncapturedErrorCallbackInfo { + WGPUChainedStruct const * nextInChain; + WGPUUncapturedErrorCallback callback; + WGPU_NULLABLE void* userdata1; + WGPU_NULLABLE void* userdata2; +} WGPUUncapturedErrorCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; + +/** @} */ + typedef struct WGPUAdapterInfo { WGPUChainedStructOut * nextInChain; - char const * vendor; - char const * architecture; - char const * device; - char const * description; + /** + * This is an \ref OutputString. + */ + WGPUStringView vendor; + /** + * This is an \ref OutputString. + */ + WGPUStringView architecture; + /** + * This is an \ref OutputString. + */ + WGPUStringView device; + /** + * This is an \ref OutputString. + */ + WGPUStringView description; WGPUBackendType backendType; WGPUAdapterType adapterType; uint32_t vendorID; @@ -858,8 +1421,11 @@ typedef struct WGPUBufferBindingLayout { typedef struct WGPUBufferDescriptor { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; - WGPUBufferUsageFlags usage; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; + WGPUBufferUsage usage; uint64_t size; WGPUBool mappedAtCreation; } WGPUBufferDescriptor WGPU_STRUCTURE_ATTRIBUTE; @@ -873,25 +1439,48 @@ typedef struct WGPUColor { typedef struct WGPUCommandBufferDescriptor { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; } WGPUCommandBufferDescriptor WGPU_STRUCTURE_ATTRIBUTE; typedef struct WGPUCommandEncoderDescriptor { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; } WGPUCommandEncoderDescriptor WGPU_STRUCTURE_ATTRIBUTE; typedef struct WGPUCompilationMessage { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * message; + /** + * A @ref LocalizableHumanReadableMessageString. + * + * This is an \ref OutputString. + */ + WGPUStringView message; + /** + * Severity level of the message. + */ WGPUCompilationMessageType type; + /** + * Line number where the message is attached, starting at 1. + */ uint64_t lineNum; + /** + * Offset in UTF-8 code units (bytes) from the beginning of the line, starting at 1. + */ uint64_t linePos; + /** + * Offset in UTF-8 code units (bytes) from the beginning of the shader code, starting at 0. + */ uint64_t offset; + /** + * Length in UTF-8 code units (bytes) of the span the message corresponds to. + */ uint64_t length; - uint64_t utf16LinePos; - uint64_t utf16Offset; - uint64_t utf16Length; } WGPUCompilationMessage WGPU_STRUCTURE_ATTRIBUTE; typedef struct WGPUComputePassTimestampWrites { @@ -902,7 +1491,10 @@ typedef struct WGPUComputePassTimestampWrites { typedef struct WGPUConstantEntry { WGPUChainedStruct const * nextInChain; - char const * key; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView key; double value; } WGPUConstantEntry WGPU_STRUCTURE_ATTRIBUTE; @@ -912,11 +1504,35 @@ typedef struct WGPUExtent3D { uint32_t depthOrArrayLayers; } WGPUExtent3D WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPUInstanceDescriptor { - WGPUChainedStruct const * nextInChain; -} WGPUInstanceDescriptor WGPU_STRUCTURE_ATTRIBUTE; +/** + * Opaque handle to an asynchronous operation. See @ref Asynchronous-Operations for more information. + */ +typedef struct WGPUFuture { + /** + * Opaque id of the @ref WGPUFuture + */ + uint64_t id; +} WGPUFuture WGPU_STRUCTURE_ATTRIBUTE; + +/** + * Features enabled on the WGPUInstance + */ +typedef struct WGPUInstanceCapabilities { + /** This struct chain is used as mutable in some places and immutable in others. */ + WGPUChainedStructOut * nextInChain; + /** + * Enable use of ::wgpuInstanceWaitAny with `timeoutNS > 0`. + */ + WGPUBool timedWaitAnyEnable; + /** + * The maximum number @ref WGPUFutureWaitInfo supported in a call to ::wgpuInstanceWaitAny with `timeoutNS > 0`. + */ + size_t timedWaitAnyMaxCount; +} WGPUInstanceCapabilities WGPU_STRUCTURE_ATTRIBUTE; typedef struct WGPULimits { + /** This struct chain is used as mutable in some places and immutable in others. */ + WGPUChainedStructOut * nextInChain; uint32_t maxTextureDimension1D; uint32_t maxTextureDimension2D; uint32_t maxTextureDimension3D; @@ -939,7 +1555,6 @@ typedef struct WGPULimits { uint64_t maxBufferSize; uint32_t maxVertexAttributes; uint32_t maxVertexBufferArrayStride; - uint32_t maxInterStageShaderComponents; uint32_t maxInterStageShaderVariables; uint32_t maxColorAttachments; uint32_t maxColorAttachmentBytesPerSample; @@ -966,44 +1581,55 @@ typedef struct WGPUOrigin3D { typedef struct WGPUPipelineLayoutDescriptor { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; size_t bindGroupLayoutCount; WGPUBindGroupLayout const * bindGroupLayouts; } WGPUPipelineLayoutDescriptor WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPUPrimitiveDepthClipControl { - WGPUChainedStruct chain; - WGPUBool unclippedDepth; -} WGPUPrimitiveDepthClipControl WGPU_STRUCTURE_ATTRIBUTE; - typedef struct WGPUPrimitiveState { WGPUChainedStruct const * nextInChain; WGPUPrimitiveTopology topology; WGPUIndexFormat stripIndexFormat; WGPUFrontFace frontFace; WGPUCullMode cullMode; + WGPUBool unclippedDepth; } WGPUPrimitiveState WGPU_STRUCTURE_ATTRIBUTE; typedef struct WGPUQuerySetDescriptor { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; WGPUQueryType type; uint32_t count; } WGPUQuerySetDescriptor WGPU_STRUCTURE_ATTRIBUTE; typedef struct WGPUQueueDescriptor { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; } WGPUQueueDescriptor WGPU_STRUCTURE_ATTRIBUTE; typedef struct WGPURenderBundleDescriptor { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; } WGPURenderBundleDescriptor WGPU_STRUCTURE_ATTRIBUTE; typedef struct WGPURenderBundleEncoderDescriptor { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; size_t colorFormatCount; WGPUTextureFormat const * colorFormats; WGPUTextureFormat depthStencilFormat; @@ -1024,10 +1650,10 @@ typedef struct WGPURenderPassDepthStencilAttachment { WGPUBool stencilReadOnly; } WGPURenderPassDepthStencilAttachment WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPURenderPassDescriptorMaxDrawCount { +typedef struct WGPURenderPassMaxDrawCount { WGPUChainedStruct chain; uint64_t maxDrawCount; -} WGPURenderPassDescriptorMaxDrawCount WGPU_STRUCTURE_ATTRIBUTE; +} WGPURenderPassMaxDrawCount WGPU_STRUCTURE_ATTRIBUTE; typedef struct WGPURenderPassTimestampWrites { WGPUQuerySet querySet; @@ -1037,10 +1663,28 @@ typedef struct WGPURenderPassTimestampWrites { typedef struct WGPURequestAdapterOptions { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE WGPUSurface compatibleSurface; + /** + * "Feature level" for the adapter request. If an adapter is returned, it must support the features and limits in the requested feature level. + * + * Implementations may ignore @ref WGPUFeatureLevel_Compatibility and provide @ref WGPUFeatureLevel_Core instead. @ref WGPUFeatureLevel_Core is the default in the JS API, but in C, this field is **required** (must not be undefined). + */ + WGPUFeatureLevel featureLevel; WGPUPowerPreference powerPreference; - WGPUBackendType backendType; + /** + * If true, requires the adapter to be a "fallback" adapter as defined by the JS spec. + * If this is not possible, the request returns null. + */ WGPUBool forceFallbackAdapter; + /** + * If set, requires the adapter to have a particular backend type. + * If this is not possible, the request returns null. + */ + WGPUBackendType backendType; + /** + * If set, requires the adapter to be able to output to a particular surface. + * If this is not possible, the request returns null. + */ + WGPU_NULLABLE WGPUSurface compatibleSurface; } WGPURequestAdapterOptions WGPU_STRUCTURE_ATTRIBUTE; typedef struct WGPUSamplerBindingLayout { @@ -1050,7 +1694,10 @@ typedef struct WGPUSamplerBindingLayout { typedef struct WGPUSamplerDescriptor { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; WGPUAddressMode addressModeU; WGPUAddressMode addressModeV; WGPUAddressMode addressModeW; @@ -1063,22 +1710,27 @@ typedef struct WGPUSamplerDescriptor { uint16_t maxAnisotropy; } WGPUSamplerDescriptor WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPUShaderModuleCompilationHint { +typedef struct WGPUShaderModuleDescriptor { WGPUChainedStruct const * nextInChain; - char const * entryPoint; - WGPUPipelineLayout layout; -} WGPUShaderModuleCompilationHint WGPU_STRUCTURE_ATTRIBUTE; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; +} WGPUShaderModuleDescriptor WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPUShaderModuleSPIRVDescriptor { +typedef struct WGPUShaderSourceSPIRV { WGPUChainedStruct chain; uint32_t codeSize; uint32_t const * code; -} WGPUShaderModuleSPIRVDescriptor WGPU_STRUCTURE_ATTRIBUTE; +} WGPUShaderSourceSPIRV WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPUShaderModuleWGSLDescriptor { +typedef struct WGPUShaderSourceWGSL { WGPUChainedStruct chain; - char const * code; -} WGPUShaderModuleWGSLDescriptor WGPU_STRUCTURE_ATTRIBUTE; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView code; +} WGPUShaderSourceWGSL WGPU_STRUCTURE_ATTRIBUTE; typedef struct WGPUStencilFaceState { WGPUCompareFunction compare; @@ -1094,80 +1746,207 @@ typedef struct WGPUStorageTextureBindingLayout { WGPUTextureViewDimension viewDimension; } WGPUStorageTextureBindingLayout WGPU_STRUCTURE_ATTRIBUTE; +typedef struct WGPUSupportedFeatures { + size_t featureCount; + WGPUFeatureName const * features; +} WGPUSupportedFeatures WGPU_STRUCTURE_ATTRIBUTE; + +typedef struct WGPUSupportedWGSLLanguageFeatures { + size_t featureCount; + WGPUWGSLLanguageFeatureName const * features; +} WGPUSupportedWGSLLanguageFeatures WGPU_STRUCTURE_ATTRIBUTE; + +/** + * Filled by `::wgpuSurfaceGetCapabilities` with what's supported for `::wgpuSurfaceConfigure` for a pair of @ref WGPUSurface and @ref WGPUAdapter. + */ typedef struct WGPUSurfaceCapabilities { WGPUChainedStructOut * nextInChain; - WGPUTextureUsageFlags usages; + /** + * The bit set of supported @ref WGPUTextureUsage bits. + * Guaranteed to contain @ref WGPUTextureUsage_RenderAttachment. + */ + WGPUTextureUsage usages; + /** + * A list of supported @ref WGPUTextureFormat values, in order of preference. + */ size_t formatCount; WGPUTextureFormat const * formats; + /** + * A list of supported @ref WGPUPresentMode values. + * Guaranteed to contain @ref WGPUPresentMode_Fifo. + */ size_t presentModeCount; WGPUPresentMode const * presentModes; + /** + * A list of supported @ref WGPUCompositeAlphaMode values. + * @ref WGPUCompositeAlphaMode_Auto will be an alias for the first element and will never be present in this array. + */ size_t alphaModeCount; WGPUCompositeAlphaMode const * alphaModes; } WGPUSurfaceCapabilities WGPU_STRUCTURE_ATTRIBUTE; +/** + * Options to `::wgpuSurfaceConfigure` for defining how a @ref WGPUSurface will be rendered to and presented to the user. + * See @ref Surface-Configuration for more details. + */ typedef struct WGPUSurfaceConfiguration { WGPUChainedStruct const * nextInChain; + /** + * The @ref WGPUDevice to use to render to surface's textures. + */ WGPUDevice device; + /** + * The @ref WGPUTextureFormat of the surface's textures. + */ WGPUTextureFormat format; - WGPUTextureUsageFlags usage; + /** + * The @ref WGPUTextureUsage of the surface's textures. + */ + WGPUTextureUsage usage; + /** + * The width of the surface's textures. + */ + uint32_t width; + /** + * The height of the surface's textures. + */ + uint32_t height; + /** + * The additional @ref WGPUTextureFormat for @ref WGPUTextureView format reinterpretation of the surface's textures. + */ size_t viewFormatCount; WGPUTextureFormat const * viewFormats; + /** + * How the surface's frames will be composited on the screen. + */ WGPUCompositeAlphaMode alphaMode; - uint32_t width; - uint32_t height; + /** + * When and in which order the surface's frames will be shown on the screen. Defaults to @ref WGPUPresentMode_Fifo. + */ WGPUPresentMode presentMode; } WGPUSurfaceConfiguration WGPU_STRUCTURE_ATTRIBUTE; +/** + * The root descriptor for the creation of an @ref WGPUSurface with `::wgpuInstanceCreateSurface`. + * It isn't sufficient by itself and must have one of the `WGPUSurfaceSource*` in its chain. + * See @ref Surface-Creation for more details. + */ typedef struct WGPUSurfaceDescriptor { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; + /** + * Label used to refer to the object. + * + * This is a \ref NonNullInputString. + */ + WGPUStringView label; } WGPUSurfaceDescriptor WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPUSurfaceDescriptorFromAndroidNativeWindow { +/** + * Chained in @ref WGPUSurfaceDescriptor to make an @ref WGPUSurface wrapping an Android [`ANativeWindow`](https://developer.android.com/ndk/reference/group/a-native-window). + */ +typedef struct WGPUSurfaceSourceAndroidNativeWindow { WGPUChainedStruct chain; + /** + * The pointer to the [`ANativeWindow`](https://developer.android.com/ndk/reference/group/a-native-window) that will be wrapped by the @ref WGPUSurface. + */ void * window; -} WGPUSurfaceDescriptorFromAndroidNativeWindow WGPU_STRUCTURE_ATTRIBUTE; - -typedef struct WGPUSurfaceDescriptorFromCanvasHTMLSelector { - WGPUChainedStruct chain; - char const * selector; -} WGPUSurfaceDescriptorFromCanvasHTMLSelector WGPU_STRUCTURE_ATTRIBUTE; +} WGPUSurfaceSourceAndroidNativeWindow WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPUSurfaceDescriptorFromMetalLayer { +/** + * Chained in @ref WGPUSurfaceDescriptor to make an @ref WGPUSurface wrapping a [`CAMetalLayer`](https://developer.apple.com/documentation/quartzcore/cametallayer?language=objc). + */ +typedef struct WGPUSurfaceSourceMetalLayer { WGPUChainedStruct chain; + /** + * The pointer to the [`CAMetalLayer`](https://developer.apple.com/documentation/quartzcore/cametallayer?language=objc) that will be wrapped by the @ref WGPUSurface. + */ void * layer; -} WGPUSurfaceDescriptorFromMetalLayer WGPU_STRUCTURE_ATTRIBUTE; +} WGPUSurfaceSourceMetalLayer WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPUSurfaceDescriptorFromWaylandSurface { +/** + * Chained in @ref WGPUSurfaceDescriptor to make an @ref WGPUSurface wrapping a [Wayland](https://wayland.freedesktop.org/) [`wl_surface`](https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_surface). + */ +typedef struct WGPUSurfaceSourceWaylandSurface { WGPUChainedStruct chain; + /** + * A [`wl_display`](https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_display) for this Wayland instance. + */ void * display; + /** + * A [`wl_surface`](https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_surface) that will be wrapped by the @ref WGPUSurface + */ void * surface; -} WGPUSurfaceDescriptorFromWaylandSurface WGPU_STRUCTURE_ATTRIBUTE; +} WGPUSurfaceSourceWaylandSurface WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPUSurfaceDescriptorFromWindowsHWND { +/** + * Chained in @ref WGPUSurfaceDescriptor to make an @ref WGPUSurface wrapping a Windows [`HWND`](https://learn.microsoft.com/en-us/windows/apps/develop/ui-input/retrieve-hwnd). + */ +typedef struct WGPUSurfaceSourceWindowsHWND { WGPUChainedStruct chain; + /** + * The [`HINSTANCE`](https://learn.microsoft.com/en-us/windows/win32/learnwin32/winmain--the-application-entry-point) for this application. + * Most commonly `GetModuleHandle(nullptr)`. + */ void * hinstance; + /** + * The [`HWND`](https://learn.microsoft.com/en-us/windows/apps/develop/ui-input/retrieve-hwnd) that will be wrapped by the @ref WGPUSurface. + */ void * hwnd; -} WGPUSurfaceDescriptorFromWindowsHWND WGPU_STRUCTURE_ATTRIBUTE; +} WGPUSurfaceSourceWindowsHWND WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPUSurfaceDescriptorFromXcbWindow { +/** + * Chained in @ref WGPUSurfaceDescriptor to make an @ref WGPUSurface wrapping an [XCB](https://xcb.freedesktop.org/) `xcb_window_t`. + */ +typedef struct WGPUSurfaceSourceXCBWindow { WGPUChainedStruct chain; + /** + * The `xcb_connection_t` for the connection to the X server. + */ void * connection; + /** + * The `xcb_window_t` for the window that will be wrapped by the @ref WGPUSurface. + */ uint32_t window; -} WGPUSurfaceDescriptorFromXcbWindow WGPU_STRUCTURE_ATTRIBUTE; +} WGPUSurfaceSourceXCBWindow WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPUSurfaceDescriptorFromXlibWindow { +/** + * Chained in @ref WGPUSurfaceDescriptor to make an @ref WGPUSurface wrapping an [Xlib](https://www.x.org/releases/current/doc/libX11/libX11/libX11.html) `Window`. + */ +typedef struct WGPUSurfaceSourceXlibWindow { WGPUChainedStruct chain; + /** + * A pointer to the [`Display`](https://www.x.org/releases/current/doc/libX11/libX11/libX11.html#Opening_the_Display) connected to the X server. + */ void * display; + /** + * The [`Window`](https://www.x.org/releases/current/doc/libX11/libX11/libX11.html#Creating_Windows) that will be wrapped by the @ref WGPUSurface. + */ uint64_t window; -} WGPUSurfaceDescriptorFromXlibWindow WGPU_STRUCTURE_ATTRIBUTE; +} WGPUSurfaceSourceXlibWindow WGPU_STRUCTURE_ATTRIBUTE; +/** + * Queried each frame from a @ref WGPUSurface to get a @ref WGPUTexture to render to along with some metadata. + * See @ref Surface-Presenting for more details. + */ typedef struct WGPUSurfaceTexture { + WGPUChainedStructOut * nextInChain; + /** + * The @ref WGPUTexture representing the frame that will be shown on the surface. + * It is @ref ReturnedWithOwnership from @ref wgpuSurfaceGetCurrentTexture. + */ WGPUTexture texture; - WGPUBool suboptimal; + /** + * Whether the call to `::wgpuSurfaceGetCurrentTexture` succeeded and a hint as to why it might not have. + */ WGPUSurfaceGetCurrentTextureStatus status; } WGPUSurfaceTexture WGPU_STRUCTURE_ATTRIBUTE; +typedef struct WGPUTexelCopyBufferLayout { + uint64_t offset; + uint32_t bytesPerRow; + uint32_t rowsPerImage; +} WGPUTexelCopyBufferLayout WGPU_STRUCTURE_ATTRIBUTE; + typedef struct WGPUTextureBindingLayout { WGPUChainedStruct const * nextInChain; WGPUTextureSampleType sampleType; @@ -1175,16 +1954,12 @@ typedef struct WGPUTextureBindingLayout { WGPUBool multisampled; } WGPUTextureBindingLayout WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPUTextureDataLayout { - WGPUChainedStruct const * nextInChain; - uint64_t offset; - uint32_t bytesPerRow; - uint32_t rowsPerImage; -} WGPUTextureDataLayout WGPU_STRUCTURE_ATTRIBUTE; - typedef struct WGPUTextureViewDescriptor { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; WGPUTextureFormat format; WGPUTextureViewDimension dimension; uint32_t baseMipLevel; @@ -1192,14 +1967,9 @@ typedef struct WGPUTextureViewDescriptor { uint32_t baseArrayLayer; uint32_t arrayLayerCount; WGPUTextureAspect aspect; + WGPUTextureUsage usage; } WGPUTextureViewDescriptor WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPUUncapturedErrorCallbackInfo { - WGPUChainedStruct const * nextInChain; - WGPUErrorCallback callback; - void * userdata; -} WGPUUncapturedErrorCallbackInfo WGPU_STRUCTURE_ATTRIBUTE; - typedef struct WGPUVertexAttribute { WGPUVertexFormat format; uint64_t offset; @@ -1208,7 +1978,10 @@ typedef struct WGPUVertexAttribute { typedef struct WGPUBindGroupDescriptor { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; WGPUBindGroupLayout layout; size_t entryCount; WGPUBindGroupEntry const * entries; @@ -1217,7 +1990,7 @@ typedef struct WGPUBindGroupDescriptor { typedef struct WGPUBindGroupLayoutEntry { WGPUChainedStruct const * nextInChain; uint32_t binding; - WGPUShaderStageFlags visibility; + WGPUShaderStage visibility; WGPUBufferBindingLayout buffer; WGPUSamplerBindingLayout sampler; WGPUTextureBindingLayout texture; @@ -1237,14 +2010,17 @@ typedef struct WGPUCompilationInfo { typedef struct WGPUComputePassDescriptor { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; WGPU_NULLABLE WGPUComputePassTimestampWrites const * timestampWrites; } WGPUComputePassDescriptor WGPU_STRUCTURE_ATTRIBUTE; typedef struct WGPUDepthStencilState { WGPUChainedStruct const * nextInChain; WGPUTextureFormat format; - WGPUBool depthWriteEnabled; + WGPUOptionalBool depthWriteEnabled; WGPUCompareFunction depthCompare; WGPUStencilFaceState stencilFront; WGPUStencilFaceState stencilBack; @@ -1255,24 +2031,49 @@ typedef struct WGPUDepthStencilState { float depthBiasClamp; } WGPUDepthStencilState WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPUImageCopyBuffer { +typedef struct WGPUDeviceDescriptor { WGPUChainedStruct const * nextInChain; - WGPUTextureDataLayout layout; - WGPUBuffer buffer; -} WGPUImageCopyBuffer WGPU_STRUCTURE_ATTRIBUTE; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; + size_t requiredFeatureCount; + WGPUFeatureName const * requiredFeatures; + WGPU_NULLABLE WGPULimits const * requiredLimits; + WGPUQueueDescriptor defaultQueue; + WGPUDeviceLostCallbackInfo deviceLostCallbackInfo; + WGPUUncapturedErrorCallbackInfo uncapturedErrorCallbackInfo; +} WGPUDeviceDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +/** + * Struct holding a future to wait on, and a `completed` boolean flag. + */ +typedef struct WGPUFutureWaitInfo { + /** + * The future to wait on. + */ + WGPUFuture future; + /** + * Whether or not the future completed. + */ + WGPUBool completed; +} WGPUFutureWaitInfo WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPUImageCopyTexture { +typedef struct WGPUInstanceDescriptor { WGPUChainedStruct const * nextInChain; - WGPUTexture texture; - uint32_t mipLevel; - WGPUOrigin3D origin; - WGPUTextureAspect aspect; -} WGPUImageCopyTexture WGPU_STRUCTURE_ATTRIBUTE; + /** + * Instance features to enable + */ + WGPUInstanceCapabilities features; +} WGPUInstanceDescriptor WGPU_STRUCTURE_ATTRIBUTE; typedef struct WGPUProgrammableStageDescriptor { WGPUChainedStruct const * nextInChain; WGPUShaderModule module; - WGPU_NULLABLE char const * entryPoint; + /** + * This is a \ref NullableInputString. + */ + WGPUStringView entryPoint; size_t constantCount; WGPUConstantEntry const * constants; } WGPUProgrammableStageDescriptor WGPU_STRUCTURE_ATTRIBUTE; @@ -1287,27 +2088,25 @@ typedef struct WGPURenderPassColorAttachment { WGPUColor clearValue; } WGPURenderPassColorAttachment WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPURequiredLimits { - WGPUChainedStruct const * nextInChain; - WGPULimits limits; -} WGPURequiredLimits WGPU_STRUCTURE_ATTRIBUTE; - -typedef struct WGPUShaderModuleDescriptor { - WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; - size_t hintCount; - WGPUShaderModuleCompilationHint const * hints; -} WGPUShaderModuleDescriptor WGPU_STRUCTURE_ATTRIBUTE; +typedef struct WGPUTexelCopyBufferInfo { + WGPUTexelCopyBufferLayout layout; + WGPUBuffer buffer; +} WGPUTexelCopyBufferInfo WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPUSupportedLimits { - WGPUChainedStructOut * nextInChain; - WGPULimits limits; -} WGPUSupportedLimits WGPU_STRUCTURE_ATTRIBUTE; +typedef struct WGPUTexelCopyTextureInfo { + WGPUTexture texture; + uint32_t mipLevel; + WGPUOrigin3D origin; + WGPUTextureAspect aspect; +} WGPUTexelCopyTextureInfo WGPU_STRUCTURE_ATTRIBUTE; typedef struct WGPUTextureDescriptor { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; - WGPUTextureUsageFlags usage; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; + WGPUTextureUsage usage; WGPUTextureDimension dimension; WGPUExtent3D size; WGPUTextureFormat format; @@ -1318,48 +2117,55 @@ typedef struct WGPUTextureDescriptor { } WGPUTextureDescriptor WGPU_STRUCTURE_ATTRIBUTE; typedef struct WGPUVertexBufferLayout { - uint64_t arrayStride; + /** + * The step mode for the vertex buffer. If @ref WGPUVertexStepMode_VertexBufferNotUsed, + * indicates a "hole" in the parent @ref WGPUVertexState `buffers` array: + * the pipeline does not use a vertex buffer at this `location`. + */ WGPUVertexStepMode stepMode; + uint64_t arrayStride; size_t attributeCount; WGPUVertexAttribute const * attributes; } WGPUVertexBufferLayout WGPU_STRUCTURE_ATTRIBUTE; typedef struct WGPUBindGroupLayoutDescriptor { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; size_t entryCount; WGPUBindGroupLayoutEntry const * entries; } WGPUBindGroupLayoutDescriptor WGPU_STRUCTURE_ATTRIBUTE; typedef struct WGPUColorTargetState { WGPUChainedStruct const * nextInChain; + /** + * The texture format of the target. If @ref WGPUTextureFormat_Undefined, + * indicates a "hole" in the parent @ref WGPUFragmentState `targets` array: + * the pipeline does not output a value at this `location`. + */ WGPUTextureFormat format; WGPU_NULLABLE WGPUBlendState const * blend; - WGPUColorWriteMaskFlags writeMask; + WGPUColorWriteMask writeMask; } WGPUColorTargetState WGPU_STRUCTURE_ATTRIBUTE; typedef struct WGPUComputePipelineDescriptor { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; WGPU_NULLABLE WGPUPipelineLayout layout; WGPUProgrammableStageDescriptor compute; } WGPUComputePipelineDescriptor WGPU_STRUCTURE_ATTRIBUTE; -typedef struct WGPUDeviceDescriptor { - WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; - size_t requiredFeatureCount; - WGPUFeatureName const * requiredFeatures; - WGPU_NULLABLE WGPURequiredLimits const * requiredLimits; - WGPUQueueDescriptor defaultQueue; - WGPUDeviceLostCallback deviceLostCallback; - void * deviceLostUserdata; - WGPUUncapturedErrorCallbackInfo uncapturedErrorCallbackInfo; -} WGPUDeviceDescriptor WGPU_STRUCTURE_ATTRIBUTE; - typedef struct WGPURenderPassDescriptor { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; size_t colorAttachmentCount; WGPURenderPassColorAttachment const * colorAttachments; WGPU_NULLABLE WGPURenderPassDepthStencilAttachment const * depthStencilAttachment; @@ -1370,7 +2176,10 @@ typedef struct WGPURenderPassDescriptor { typedef struct WGPUVertexState { WGPUChainedStruct const * nextInChain; WGPUShaderModule module; - WGPU_NULLABLE char const * entryPoint; + /** + * This is a \ref NullableInputString. + */ + WGPUStringView entryPoint; size_t constantCount; WGPUConstantEntry const * constants; size_t bufferCount; @@ -1380,7 +2189,10 @@ typedef struct WGPUVertexState { typedef struct WGPUFragmentState { WGPUChainedStruct const * nextInChain; WGPUShaderModule module; - WGPU_NULLABLE char const * entryPoint; + /** + * This is a \ref NullableInputString. + */ + WGPUStringView entryPoint; size_t constantCount; WGPUConstantEntry const * constants; size_t targetCount; @@ -1389,7 +2201,10 @@ typedef struct WGPUFragmentState { typedef struct WGPURenderPipelineDescriptor { WGPUChainedStruct const * nextInChain; - WGPU_NULLABLE char const * label; + /** + * This is a \ref NonNullInputString. + */ + WGPUStringView label; WGPU_NULLABLE WGPUPipelineLayout layout; WGPUVertexState vertex; WGPUPrimitiveState primitive; @@ -1406,236 +2221,1007 @@ extern "C" { #if !defined(WGPU_SKIP_PROCS) +/** + * Proc pointer type for @ref wgpuCreateInstance: + * > @copydoc wgpuCreateInstance + */ typedef WGPUInstance (*WGPUProcCreateInstance)(WGPU_NULLABLE WGPUInstanceDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; -typedef WGPUProc (*WGPUProcGetProcAddress)(WGPUDevice device, char const * procName) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuGetInstanceCapabilities: + * > @copydoc wgpuGetInstanceCapabilities + */ +typedef WGPUStatus (*WGPUProcGetInstanceCapabilities)(WGPUInstanceCapabilities * capabilities) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuGetProcAddress: + * > @copydoc wgpuGetProcAddress + */ +typedef WGPUProc (*WGPUProcGetProcAddress)(WGPUStringView procName) WGPU_FUNCTION_ATTRIBUTE; // Procs of Adapter -typedef size_t (*WGPUProcAdapterEnumerateFeatures)(WGPUAdapter adapter, WGPUFeatureName * features) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcAdapterGetInfo)(WGPUAdapter adapter, WGPUAdapterInfo * info) WGPU_FUNCTION_ATTRIBUTE; -typedef WGPUBool (*WGPUProcAdapterGetLimits)(WGPUAdapter adapter, WGPUSupportedLimits * limits) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuAdapterGetFeatures: + * > @copydoc wgpuAdapterGetFeatures + */ +typedef void (*WGPUProcAdapterGetFeatures)(WGPUAdapter adapter, WGPUSupportedFeatures * features) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuAdapterGetInfo: + * > @copydoc wgpuAdapterGetInfo + */ +typedef WGPUStatus (*WGPUProcAdapterGetInfo)(WGPUAdapter adapter, WGPUAdapterInfo * info) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuAdapterGetLimits: + * > @copydoc wgpuAdapterGetLimits + */ +typedef WGPUStatus (*WGPUProcAdapterGetLimits)(WGPUAdapter adapter, WGPULimits * limits) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuAdapterHasFeature: + * > @copydoc wgpuAdapterHasFeature + */ typedef WGPUBool (*WGPUProcAdapterHasFeature)(WGPUAdapter adapter, WGPUFeatureName feature) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcAdapterRequestDevice)(WGPUAdapter adapter, WGPU_NULLABLE WGPUDeviceDescriptor const * descriptor, WGPUAdapterRequestDeviceCallback callback, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcAdapterReference)(WGPUAdapter adapter) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuAdapterRequestDevice: + * > @copydoc wgpuAdapterRequestDevice + */ +typedef WGPUFuture (*WGPUProcAdapterRequestDevice)(WGPUAdapter adapter, WGPU_NULLABLE WGPUDeviceDescriptor const * descriptor, WGPURequestDeviceCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuAdapterAddRef. + * > @copydoc wgpuAdapterAddRef + */ +typedef void (*WGPUProcAdapterAddRef)(WGPUAdapter adapter) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuAdapterRelease. + * > @copydoc wgpuAdapterRelease + */ typedef void (*WGPUProcAdapterRelease)(WGPUAdapter adapter) WGPU_FUNCTION_ATTRIBUTE; // Procs of AdapterInfo +/** + * Proc pointer type for @ref wgpuAdapterInfoFreeMembers: + * > @copydoc wgpuAdapterInfoFreeMembers + */ typedef void (*WGPUProcAdapterInfoFreeMembers)(WGPUAdapterInfo adapterInfo) WGPU_FUNCTION_ATTRIBUTE; // Procs of BindGroup -typedef void (*WGPUProcBindGroupSetLabel)(WGPUBindGroup bindGroup, char const * label) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcBindGroupReference)(WGPUBindGroup bindGroup) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuBindGroupSetLabel: + * > @copydoc wgpuBindGroupSetLabel + */ +typedef void (*WGPUProcBindGroupSetLabel)(WGPUBindGroup bindGroup, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuBindGroupAddRef. + * > @copydoc wgpuBindGroupAddRef + */ +typedef void (*WGPUProcBindGroupAddRef)(WGPUBindGroup bindGroup) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuBindGroupRelease. + * > @copydoc wgpuBindGroupRelease + */ typedef void (*WGPUProcBindGroupRelease)(WGPUBindGroup bindGroup) WGPU_FUNCTION_ATTRIBUTE; // Procs of BindGroupLayout -typedef void (*WGPUProcBindGroupLayoutSetLabel)(WGPUBindGroupLayout bindGroupLayout, char const * label) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcBindGroupLayoutReference)(WGPUBindGroupLayout bindGroupLayout) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuBindGroupLayoutSetLabel: + * > @copydoc wgpuBindGroupLayoutSetLabel + */ +typedef void (*WGPUProcBindGroupLayoutSetLabel)(WGPUBindGroupLayout bindGroupLayout, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuBindGroupLayoutAddRef. + * > @copydoc wgpuBindGroupLayoutAddRef + */ +typedef void (*WGPUProcBindGroupLayoutAddRef)(WGPUBindGroupLayout bindGroupLayout) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuBindGroupLayoutRelease. + * > @copydoc wgpuBindGroupLayoutRelease + */ typedef void (*WGPUProcBindGroupLayoutRelease)(WGPUBindGroupLayout bindGroupLayout) WGPU_FUNCTION_ATTRIBUTE; // Procs of Buffer +/** + * Proc pointer type for @ref wgpuBufferDestroy: + * > @copydoc wgpuBufferDestroy + */ typedef void (*WGPUProcBufferDestroy)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuBufferGetConstMappedRange: + * > @copydoc wgpuBufferGetConstMappedRange + */ typedef void const * (*WGPUProcBufferGetConstMappedRange)(WGPUBuffer buffer, size_t offset, size_t size) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuBufferGetMapState: + * > @copydoc wgpuBufferGetMapState + */ typedef WGPUBufferMapState (*WGPUProcBufferGetMapState)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuBufferGetMappedRange: + * > @copydoc wgpuBufferGetMappedRange + */ typedef void * (*WGPUProcBufferGetMappedRange)(WGPUBuffer buffer, size_t offset, size_t size) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuBufferGetSize: + * > @copydoc wgpuBufferGetSize + */ typedef uint64_t (*WGPUProcBufferGetSize)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; -typedef WGPUBufferUsageFlags (*WGPUProcBufferGetUsage)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcBufferMapAsync)(WGPUBuffer buffer, WGPUMapModeFlags mode, size_t offset, size_t size, WGPUBufferMapAsyncCallback callback, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcBufferSetLabel)(WGPUBuffer buffer, char const * label) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcBufferUnmap)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcBufferReference)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcBufferRelease)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; - -// Procs of CommandBuffer -typedef void (*WGPUProcCommandBufferSetLabel)(WGPUCommandBuffer commandBuffer, char const * label) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcCommandBufferReference)(WGPUCommandBuffer commandBuffer) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuBufferGetUsage: + * > @copydoc wgpuBufferGetUsage + */ +typedef WGPUBufferUsage (*WGPUProcBufferGetUsage)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuBufferMapAsync: + * > @copydoc wgpuBufferMapAsync + */ +typedef WGPUFuture (*WGPUProcBufferMapAsync)(WGPUBuffer buffer, WGPUMapMode mode, size_t offset, size_t size, WGPUBufferMapCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuBufferSetLabel: + * > @copydoc wgpuBufferSetLabel + */ +typedef void (*WGPUProcBufferSetLabel)(WGPUBuffer buffer, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuBufferUnmap: + * > @copydoc wgpuBufferUnmap + */ +typedef void (*WGPUProcBufferUnmap)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuBufferAddRef. + * > @copydoc wgpuBufferAddRef + */ +typedef void (*WGPUProcBufferAddRef)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuBufferRelease. + * > @copydoc wgpuBufferRelease + */ +typedef void (*WGPUProcBufferRelease)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of CommandBuffer +/** + * Proc pointer type for @ref wgpuCommandBufferSetLabel: + * > @copydoc wgpuCommandBufferSetLabel + */ +typedef void (*WGPUProcCommandBufferSetLabel)(WGPUCommandBuffer commandBuffer, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuCommandBufferAddRef. + * > @copydoc wgpuCommandBufferAddRef + */ +typedef void (*WGPUProcCommandBufferAddRef)(WGPUCommandBuffer commandBuffer) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuCommandBufferRelease. + * > @copydoc wgpuCommandBufferRelease + */ typedef void (*WGPUProcCommandBufferRelease)(WGPUCommandBuffer commandBuffer) WGPU_FUNCTION_ATTRIBUTE; // Procs of CommandEncoder +/** + * Proc pointer type for @ref wgpuCommandEncoderBeginComputePass: + * > @copydoc wgpuCommandEncoderBeginComputePass + */ typedef WGPUComputePassEncoder (*WGPUProcCommandEncoderBeginComputePass)(WGPUCommandEncoder commandEncoder, WGPU_NULLABLE WGPUComputePassDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuCommandEncoderBeginRenderPass: + * > @copydoc wgpuCommandEncoderBeginRenderPass + */ typedef WGPURenderPassEncoder (*WGPUProcCommandEncoderBeginRenderPass)(WGPUCommandEncoder commandEncoder, WGPURenderPassDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuCommandEncoderClearBuffer: + * > @copydoc wgpuCommandEncoderClearBuffer + */ typedef void (*WGPUProcCommandEncoderClearBuffer)(WGPUCommandEncoder commandEncoder, WGPUBuffer buffer, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuCommandEncoderCopyBufferToBuffer: + * > @copydoc wgpuCommandEncoderCopyBufferToBuffer + */ typedef void (*WGPUProcCommandEncoderCopyBufferToBuffer)(WGPUCommandEncoder commandEncoder, WGPUBuffer source, uint64_t sourceOffset, WGPUBuffer destination, uint64_t destinationOffset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcCommandEncoderCopyBufferToTexture)(WGPUCommandEncoder commandEncoder, WGPUImageCopyBuffer const * source, WGPUImageCopyTexture const * destination, WGPUExtent3D const * copySize) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcCommandEncoderCopyTextureToBuffer)(WGPUCommandEncoder commandEncoder, WGPUImageCopyTexture const * source, WGPUImageCopyBuffer const * destination, WGPUExtent3D const * copySize) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcCommandEncoderCopyTextureToTexture)(WGPUCommandEncoder commandEncoder, WGPUImageCopyTexture const * source, WGPUImageCopyTexture const * destination, WGPUExtent3D const * copySize) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuCommandEncoderCopyBufferToTexture: + * > @copydoc wgpuCommandEncoderCopyBufferToTexture + */ +typedef void (*WGPUProcCommandEncoderCopyBufferToTexture)(WGPUCommandEncoder commandEncoder, WGPUTexelCopyBufferInfo const * source, WGPUTexelCopyTextureInfo const * destination, WGPUExtent3D const * copySize) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuCommandEncoderCopyTextureToBuffer: + * > @copydoc wgpuCommandEncoderCopyTextureToBuffer + */ +typedef void (*WGPUProcCommandEncoderCopyTextureToBuffer)(WGPUCommandEncoder commandEncoder, WGPUTexelCopyTextureInfo const * source, WGPUTexelCopyBufferInfo const * destination, WGPUExtent3D const * copySize) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuCommandEncoderCopyTextureToTexture: + * > @copydoc wgpuCommandEncoderCopyTextureToTexture + */ +typedef void (*WGPUProcCommandEncoderCopyTextureToTexture)(WGPUCommandEncoder commandEncoder, WGPUTexelCopyTextureInfo const * source, WGPUTexelCopyTextureInfo const * destination, WGPUExtent3D const * copySize) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuCommandEncoderFinish: + * > @copydoc wgpuCommandEncoderFinish + */ typedef WGPUCommandBuffer (*WGPUProcCommandEncoderFinish)(WGPUCommandEncoder commandEncoder, WGPU_NULLABLE WGPUCommandBufferDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcCommandEncoderInsertDebugMarker)(WGPUCommandEncoder commandEncoder, char const * markerLabel) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuCommandEncoderInsertDebugMarker: + * > @copydoc wgpuCommandEncoderInsertDebugMarker + */ +typedef void (*WGPUProcCommandEncoderInsertDebugMarker)(WGPUCommandEncoder commandEncoder, WGPUStringView markerLabel) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuCommandEncoderPopDebugGroup: + * > @copydoc wgpuCommandEncoderPopDebugGroup + */ typedef void (*WGPUProcCommandEncoderPopDebugGroup)(WGPUCommandEncoder commandEncoder) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcCommandEncoderPushDebugGroup)(WGPUCommandEncoder commandEncoder, char const * groupLabel) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuCommandEncoderPushDebugGroup: + * > @copydoc wgpuCommandEncoderPushDebugGroup + */ +typedef void (*WGPUProcCommandEncoderPushDebugGroup)(WGPUCommandEncoder commandEncoder, WGPUStringView groupLabel) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuCommandEncoderResolveQuerySet: + * > @copydoc wgpuCommandEncoderResolveQuerySet + */ typedef void (*WGPUProcCommandEncoderResolveQuerySet)(WGPUCommandEncoder commandEncoder, WGPUQuerySet querySet, uint32_t firstQuery, uint32_t queryCount, WGPUBuffer destination, uint64_t destinationOffset) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcCommandEncoderSetLabel)(WGPUCommandEncoder commandEncoder, char const * label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuCommandEncoderSetLabel: + * > @copydoc wgpuCommandEncoderSetLabel + */ +typedef void (*WGPUProcCommandEncoderSetLabel)(WGPUCommandEncoder commandEncoder, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuCommandEncoderWriteTimestamp: + * > @copydoc wgpuCommandEncoderWriteTimestamp + */ typedef void (*WGPUProcCommandEncoderWriteTimestamp)(WGPUCommandEncoder commandEncoder, WGPUQuerySet querySet, uint32_t queryIndex) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcCommandEncoderReference)(WGPUCommandEncoder commandEncoder) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuCommandEncoderAddRef. + * > @copydoc wgpuCommandEncoderAddRef + */ +typedef void (*WGPUProcCommandEncoderAddRef)(WGPUCommandEncoder commandEncoder) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuCommandEncoderRelease. + * > @copydoc wgpuCommandEncoderRelease + */ typedef void (*WGPUProcCommandEncoderRelease)(WGPUCommandEncoder commandEncoder) WGPU_FUNCTION_ATTRIBUTE; // Procs of ComputePassEncoder +/** + * Proc pointer type for @ref wgpuComputePassEncoderDispatchWorkgroups: + * > @copydoc wgpuComputePassEncoderDispatchWorkgroups + */ typedef void (*WGPUProcComputePassEncoderDispatchWorkgroups)(WGPUComputePassEncoder computePassEncoder, uint32_t workgroupCountX, uint32_t workgroupCountY, uint32_t workgroupCountZ) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuComputePassEncoderDispatchWorkgroupsIndirect: + * > @copydoc wgpuComputePassEncoderDispatchWorkgroupsIndirect + */ typedef void (*WGPUProcComputePassEncoderDispatchWorkgroupsIndirect)(WGPUComputePassEncoder computePassEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuComputePassEncoderEnd: + * > @copydoc wgpuComputePassEncoderEnd + */ typedef void (*WGPUProcComputePassEncoderEnd)(WGPUComputePassEncoder computePassEncoder) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcComputePassEncoderInsertDebugMarker)(WGPUComputePassEncoder computePassEncoder, char const * markerLabel) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuComputePassEncoderInsertDebugMarker: + * > @copydoc wgpuComputePassEncoderInsertDebugMarker + */ +typedef void (*WGPUProcComputePassEncoderInsertDebugMarker)(WGPUComputePassEncoder computePassEncoder, WGPUStringView markerLabel) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuComputePassEncoderPopDebugGroup: + * > @copydoc wgpuComputePassEncoderPopDebugGroup + */ typedef void (*WGPUProcComputePassEncoderPopDebugGroup)(WGPUComputePassEncoder computePassEncoder) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcComputePassEncoderPushDebugGroup)(WGPUComputePassEncoder computePassEncoder, char const * groupLabel) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuComputePassEncoderPushDebugGroup: + * > @copydoc wgpuComputePassEncoderPushDebugGroup + */ +typedef void (*WGPUProcComputePassEncoderPushDebugGroup)(WGPUComputePassEncoder computePassEncoder, WGPUStringView groupLabel) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuComputePassEncoderSetBindGroup: + * > @copydoc wgpuComputePassEncoderSetBindGroup + */ typedef void (*WGPUProcComputePassEncoderSetBindGroup)(WGPUComputePassEncoder computePassEncoder, uint32_t groupIndex, WGPU_NULLABLE WGPUBindGroup group, size_t dynamicOffsetCount, uint32_t const * dynamicOffsets) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcComputePassEncoderSetLabel)(WGPUComputePassEncoder computePassEncoder, char const * label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuComputePassEncoderSetLabel: + * > @copydoc wgpuComputePassEncoderSetLabel + */ +typedef void (*WGPUProcComputePassEncoderSetLabel)(WGPUComputePassEncoder computePassEncoder, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuComputePassEncoderSetPipeline: + * > @copydoc wgpuComputePassEncoderSetPipeline + */ typedef void (*WGPUProcComputePassEncoderSetPipeline)(WGPUComputePassEncoder computePassEncoder, WGPUComputePipeline pipeline) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcComputePassEncoderReference)(WGPUComputePassEncoder computePassEncoder) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuComputePassEncoderAddRef. + * > @copydoc wgpuComputePassEncoderAddRef + */ +typedef void (*WGPUProcComputePassEncoderAddRef)(WGPUComputePassEncoder computePassEncoder) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuComputePassEncoderRelease. + * > @copydoc wgpuComputePassEncoderRelease + */ typedef void (*WGPUProcComputePassEncoderRelease)(WGPUComputePassEncoder computePassEncoder) WGPU_FUNCTION_ATTRIBUTE; // Procs of ComputePipeline +/** + * Proc pointer type for @ref wgpuComputePipelineGetBindGroupLayout: + * > @copydoc wgpuComputePipelineGetBindGroupLayout + */ typedef WGPUBindGroupLayout (*WGPUProcComputePipelineGetBindGroupLayout)(WGPUComputePipeline computePipeline, uint32_t groupIndex) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcComputePipelineSetLabel)(WGPUComputePipeline computePipeline, char const * label) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcComputePipelineReference)(WGPUComputePipeline computePipeline) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuComputePipelineSetLabel: + * > @copydoc wgpuComputePipelineSetLabel + */ +typedef void (*WGPUProcComputePipelineSetLabel)(WGPUComputePipeline computePipeline, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuComputePipelineAddRef. + * > @copydoc wgpuComputePipelineAddRef + */ +typedef void (*WGPUProcComputePipelineAddRef)(WGPUComputePipeline computePipeline) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuComputePipelineRelease. + * > @copydoc wgpuComputePipelineRelease + */ typedef void (*WGPUProcComputePipelineRelease)(WGPUComputePipeline computePipeline) WGPU_FUNCTION_ATTRIBUTE; // Procs of Device +/** + * Proc pointer type for @ref wgpuDeviceCreateBindGroup: + * > @copydoc wgpuDeviceCreateBindGroup + */ typedef WGPUBindGroup (*WGPUProcDeviceCreateBindGroup)(WGPUDevice device, WGPUBindGroupDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceCreateBindGroupLayout: + * > @copydoc wgpuDeviceCreateBindGroupLayout + */ typedef WGPUBindGroupLayout (*WGPUProcDeviceCreateBindGroupLayout)(WGPUDevice device, WGPUBindGroupLayoutDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceCreateBuffer: + * > @copydoc wgpuDeviceCreateBuffer + */ typedef WGPUBuffer (*WGPUProcDeviceCreateBuffer)(WGPUDevice device, WGPUBufferDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceCreateCommandEncoder: + * > @copydoc wgpuDeviceCreateCommandEncoder + */ typedef WGPUCommandEncoder (*WGPUProcDeviceCreateCommandEncoder)(WGPUDevice device, WGPU_NULLABLE WGPUCommandEncoderDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceCreateComputePipeline: + * > @copydoc wgpuDeviceCreateComputePipeline + */ typedef WGPUComputePipeline (*WGPUProcDeviceCreateComputePipeline)(WGPUDevice device, WGPUComputePipelineDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcDeviceCreateComputePipelineAsync)(WGPUDevice device, WGPUComputePipelineDescriptor const * descriptor, WGPUDeviceCreateComputePipelineAsyncCallback callback, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceCreateComputePipelineAsync: + * > @copydoc wgpuDeviceCreateComputePipelineAsync + */ +typedef WGPUFuture (*WGPUProcDeviceCreateComputePipelineAsync)(WGPUDevice device, WGPUComputePipelineDescriptor const * descriptor, WGPUCreateComputePipelineAsyncCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceCreatePipelineLayout: + * > @copydoc wgpuDeviceCreatePipelineLayout + */ typedef WGPUPipelineLayout (*WGPUProcDeviceCreatePipelineLayout)(WGPUDevice device, WGPUPipelineLayoutDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceCreateQuerySet: + * > @copydoc wgpuDeviceCreateQuerySet + */ typedef WGPUQuerySet (*WGPUProcDeviceCreateQuerySet)(WGPUDevice device, WGPUQuerySetDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceCreateRenderBundleEncoder: + * > @copydoc wgpuDeviceCreateRenderBundleEncoder + */ typedef WGPURenderBundleEncoder (*WGPUProcDeviceCreateRenderBundleEncoder)(WGPUDevice device, WGPURenderBundleEncoderDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceCreateRenderPipeline: + * > @copydoc wgpuDeviceCreateRenderPipeline + */ typedef WGPURenderPipeline (*WGPUProcDeviceCreateRenderPipeline)(WGPUDevice device, WGPURenderPipelineDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcDeviceCreateRenderPipelineAsync)(WGPUDevice device, WGPURenderPipelineDescriptor const * descriptor, WGPUDeviceCreateRenderPipelineAsyncCallback callback, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceCreateRenderPipelineAsync: + * > @copydoc wgpuDeviceCreateRenderPipelineAsync + */ +typedef WGPUFuture (*WGPUProcDeviceCreateRenderPipelineAsync)(WGPUDevice device, WGPURenderPipelineDescriptor const * descriptor, WGPUCreateRenderPipelineAsyncCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceCreateSampler: + * > @copydoc wgpuDeviceCreateSampler + */ typedef WGPUSampler (*WGPUProcDeviceCreateSampler)(WGPUDevice device, WGPU_NULLABLE WGPUSamplerDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceCreateShaderModule: + * > @copydoc wgpuDeviceCreateShaderModule + */ typedef WGPUShaderModule (*WGPUProcDeviceCreateShaderModule)(WGPUDevice device, WGPUShaderModuleDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceCreateTexture: + * > @copydoc wgpuDeviceCreateTexture + */ typedef WGPUTexture (*WGPUProcDeviceCreateTexture)(WGPUDevice device, WGPUTextureDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceDestroy: + * > @copydoc wgpuDeviceDestroy + */ typedef void (*WGPUProcDeviceDestroy)(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; -typedef size_t (*WGPUProcDeviceEnumerateFeatures)(WGPUDevice device, WGPUFeatureName * features) WGPU_FUNCTION_ATTRIBUTE; -typedef WGPUBool (*WGPUProcDeviceGetLimits)(WGPUDevice device, WGPUSupportedLimits * limits) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceGetAdapterInfo: + * > @copydoc wgpuDeviceGetAdapterInfo + */ +typedef WGPUAdapterInfo (*WGPUProcDeviceGetAdapterInfo)(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceGetFeatures: + * > @copydoc wgpuDeviceGetFeatures + */ +typedef void (*WGPUProcDeviceGetFeatures)(WGPUDevice device, WGPUSupportedFeatures * features) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceGetLimits: + * > @copydoc wgpuDeviceGetLimits + */ +typedef WGPUStatus (*WGPUProcDeviceGetLimits)(WGPUDevice device, WGPULimits * limits) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceGetLostFuture: + * > @copydoc wgpuDeviceGetLostFuture + */ +typedef WGPUFuture (*WGPUProcDeviceGetLostFuture)(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceGetQueue: + * > @copydoc wgpuDeviceGetQueue + */ typedef WGPUQueue (*WGPUProcDeviceGetQueue)(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceHasFeature: + * > @copydoc wgpuDeviceHasFeature + */ typedef WGPUBool (*WGPUProcDeviceHasFeature)(WGPUDevice device, WGPUFeatureName feature) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcDevicePopErrorScope)(WGPUDevice device, WGPUErrorCallback callback, void * userdata) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDevicePopErrorScope: + * > @copydoc wgpuDevicePopErrorScope + */ +typedef WGPUFuture (*WGPUProcDevicePopErrorScope)(WGPUDevice device, WGPUPopErrorScopeCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDevicePushErrorScope: + * > @copydoc wgpuDevicePushErrorScope + */ typedef void (*WGPUProcDevicePushErrorScope)(WGPUDevice device, WGPUErrorFilter filter) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcDeviceSetLabel)(WGPUDevice device, char const * label) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcDeviceReference)(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceSetLabel: + * > @copydoc wgpuDeviceSetLabel + */ +typedef void (*WGPUProcDeviceSetLabel)(WGPUDevice device, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceAddRef. + * > @copydoc wgpuDeviceAddRef + */ +typedef void (*WGPUProcDeviceAddRef)(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuDeviceRelease. + * > @copydoc wgpuDeviceRelease + */ typedef void (*WGPUProcDeviceRelease)(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; // Procs of Instance +/** + * Proc pointer type for @ref wgpuInstanceCreateSurface: + * > @copydoc wgpuInstanceCreateSurface + */ typedef WGPUSurface (*WGPUProcInstanceCreateSurface)(WGPUInstance instance, WGPUSurfaceDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; -typedef WGPUBool (*WGPUProcInstanceHasWGSLLanguageFeature)(WGPUInstance instance, WGPUWGSLFeatureName feature) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuInstanceGetWGSLLanguageFeatures: + * > @copydoc wgpuInstanceGetWGSLLanguageFeatures + */ +typedef WGPUStatus (*WGPUProcInstanceGetWGSLLanguageFeatures)(WGPUInstance instance, WGPUSupportedWGSLLanguageFeatures * features) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuInstanceHasWGSLLanguageFeature: + * > @copydoc wgpuInstanceHasWGSLLanguageFeature + */ +typedef WGPUBool (*WGPUProcInstanceHasWGSLLanguageFeature)(WGPUInstance instance, WGPUWGSLLanguageFeatureName feature) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuInstanceProcessEvents: + * > @copydoc wgpuInstanceProcessEvents + */ typedef void (*WGPUProcInstanceProcessEvents)(WGPUInstance instance) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcInstanceRequestAdapter)(WGPUInstance instance, WGPU_NULLABLE WGPURequestAdapterOptions const * options, WGPUInstanceRequestAdapterCallback callback, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcInstanceReference)(WGPUInstance instance) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuInstanceRequestAdapter: + * > @copydoc wgpuInstanceRequestAdapter + */ +typedef WGPUFuture (*WGPUProcInstanceRequestAdapter)(WGPUInstance instance, WGPU_NULLABLE WGPURequestAdapterOptions const * options, WGPURequestAdapterCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuInstanceWaitAny: + * > @copydoc wgpuInstanceWaitAny + */ +typedef WGPUWaitStatus (*WGPUProcInstanceWaitAny)(WGPUInstance instance, size_t futureCount, WGPU_NULLABLE WGPUFutureWaitInfo * futures, uint64_t timeoutNS) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuInstanceAddRef. + * > @copydoc wgpuInstanceAddRef + */ +typedef void (*WGPUProcInstanceAddRef)(WGPUInstance instance) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuInstanceRelease. + * > @copydoc wgpuInstanceRelease + */ typedef void (*WGPUProcInstanceRelease)(WGPUInstance instance) WGPU_FUNCTION_ATTRIBUTE; // Procs of PipelineLayout -typedef void (*WGPUProcPipelineLayoutSetLabel)(WGPUPipelineLayout pipelineLayout, char const * label) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcPipelineLayoutReference)(WGPUPipelineLayout pipelineLayout) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuPipelineLayoutSetLabel: + * > @copydoc wgpuPipelineLayoutSetLabel + */ +typedef void (*WGPUProcPipelineLayoutSetLabel)(WGPUPipelineLayout pipelineLayout, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuPipelineLayoutAddRef. + * > @copydoc wgpuPipelineLayoutAddRef + */ +typedef void (*WGPUProcPipelineLayoutAddRef)(WGPUPipelineLayout pipelineLayout) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuPipelineLayoutRelease. + * > @copydoc wgpuPipelineLayoutRelease + */ typedef void (*WGPUProcPipelineLayoutRelease)(WGPUPipelineLayout pipelineLayout) WGPU_FUNCTION_ATTRIBUTE; // Procs of QuerySet +/** + * Proc pointer type for @ref wgpuQuerySetDestroy: + * > @copydoc wgpuQuerySetDestroy + */ typedef void (*WGPUProcQuerySetDestroy)(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuQuerySetGetCount: + * > @copydoc wgpuQuerySetGetCount + */ typedef uint32_t (*WGPUProcQuerySetGetCount)(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuQuerySetGetType: + * > @copydoc wgpuQuerySetGetType + */ typedef WGPUQueryType (*WGPUProcQuerySetGetType)(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcQuerySetSetLabel)(WGPUQuerySet querySet, char const * label) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcQuerySetReference)(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuQuerySetSetLabel: + * > @copydoc wgpuQuerySetSetLabel + */ +typedef void (*WGPUProcQuerySetSetLabel)(WGPUQuerySet querySet, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuQuerySetAddRef. + * > @copydoc wgpuQuerySetAddRef + */ +typedef void (*WGPUProcQuerySetAddRef)(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuQuerySetRelease. + * > @copydoc wgpuQuerySetRelease + */ typedef void (*WGPUProcQuerySetRelease)(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; // Procs of Queue -typedef void (*WGPUProcQueueOnSubmittedWorkDone)(WGPUQueue queue, WGPUQueueOnSubmittedWorkDoneCallback callback, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcQueueSetLabel)(WGPUQueue queue, char const * label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuQueueOnSubmittedWorkDone: + * > @copydoc wgpuQueueOnSubmittedWorkDone + */ +typedef WGPUFuture (*WGPUProcQueueOnSubmittedWorkDone)(WGPUQueue queue, WGPUQueueWorkDoneCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuQueueSetLabel: + * > @copydoc wgpuQueueSetLabel + */ +typedef void (*WGPUProcQueueSetLabel)(WGPUQueue queue, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuQueueSubmit: + * > @copydoc wgpuQueueSubmit + */ typedef void (*WGPUProcQueueSubmit)(WGPUQueue queue, size_t commandCount, WGPUCommandBuffer const * commands) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuQueueWriteBuffer: + * > @copydoc wgpuQueueWriteBuffer + */ typedef void (*WGPUProcQueueWriteBuffer)(WGPUQueue queue, WGPUBuffer buffer, uint64_t bufferOffset, void const * data, size_t size) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcQueueWriteTexture)(WGPUQueue queue, WGPUImageCopyTexture const * destination, void const * data, size_t dataSize, WGPUTextureDataLayout const * dataLayout, WGPUExtent3D const * writeSize) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcQueueReference)(WGPUQueue queue) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuQueueWriteTexture: + * > @copydoc wgpuQueueWriteTexture + */ +typedef void (*WGPUProcQueueWriteTexture)(WGPUQueue queue, WGPUTexelCopyTextureInfo const * destination, void const * data, size_t dataSize, WGPUTexelCopyBufferLayout const * dataLayout, WGPUExtent3D const * writeSize) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuQueueAddRef. + * > @copydoc wgpuQueueAddRef + */ +typedef void (*WGPUProcQueueAddRef)(WGPUQueue queue) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuQueueRelease. + * > @copydoc wgpuQueueRelease + */ typedef void (*WGPUProcQueueRelease)(WGPUQueue queue) WGPU_FUNCTION_ATTRIBUTE; // Procs of RenderBundle -typedef void (*WGPUProcRenderBundleSetLabel)(WGPURenderBundle renderBundle, char const * label) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcRenderBundleReference)(WGPURenderBundle renderBundle) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderBundleSetLabel: + * > @copydoc wgpuRenderBundleSetLabel + */ +typedef void (*WGPUProcRenderBundleSetLabel)(WGPURenderBundle renderBundle, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderBundleAddRef. + * > @copydoc wgpuRenderBundleAddRef + */ +typedef void (*WGPUProcRenderBundleAddRef)(WGPURenderBundle renderBundle) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderBundleRelease. + * > @copydoc wgpuRenderBundleRelease + */ typedef void (*WGPUProcRenderBundleRelease)(WGPURenderBundle renderBundle) WGPU_FUNCTION_ATTRIBUTE; // Procs of RenderBundleEncoder +/** + * Proc pointer type for @ref wgpuRenderBundleEncoderDraw: + * > @copydoc wgpuRenderBundleEncoderDraw + */ typedef void (*WGPUProcRenderBundleEncoderDraw)(WGPURenderBundleEncoder renderBundleEncoder, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderBundleEncoderDrawIndexed: + * > @copydoc wgpuRenderBundleEncoderDrawIndexed + */ typedef void (*WGPUProcRenderBundleEncoderDrawIndexed)(WGPURenderBundleEncoder renderBundleEncoder, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t baseVertex, uint32_t firstInstance) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderBundleEncoderDrawIndexedIndirect: + * > @copydoc wgpuRenderBundleEncoderDrawIndexedIndirect + */ typedef void (*WGPUProcRenderBundleEncoderDrawIndexedIndirect)(WGPURenderBundleEncoder renderBundleEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderBundleEncoderDrawIndirect: + * > @copydoc wgpuRenderBundleEncoderDrawIndirect + */ typedef void (*WGPUProcRenderBundleEncoderDrawIndirect)(WGPURenderBundleEncoder renderBundleEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderBundleEncoderFinish: + * > @copydoc wgpuRenderBundleEncoderFinish + */ typedef WGPURenderBundle (*WGPUProcRenderBundleEncoderFinish)(WGPURenderBundleEncoder renderBundleEncoder, WGPU_NULLABLE WGPURenderBundleDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcRenderBundleEncoderInsertDebugMarker)(WGPURenderBundleEncoder renderBundleEncoder, char const * markerLabel) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderBundleEncoderInsertDebugMarker: + * > @copydoc wgpuRenderBundleEncoderInsertDebugMarker + */ +typedef void (*WGPUProcRenderBundleEncoderInsertDebugMarker)(WGPURenderBundleEncoder renderBundleEncoder, WGPUStringView markerLabel) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderBundleEncoderPopDebugGroup: + * > @copydoc wgpuRenderBundleEncoderPopDebugGroup + */ typedef void (*WGPUProcRenderBundleEncoderPopDebugGroup)(WGPURenderBundleEncoder renderBundleEncoder) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcRenderBundleEncoderPushDebugGroup)(WGPURenderBundleEncoder renderBundleEncoder, char const * groupLabel) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderBundleEncoderPushDebugGroup: + * > @copydoc wgpuRenderBundleEncoderPushDebugGroup + */ +typedef void (*WGPUProcRenderBundleEncoderPushDebugGroup)(WGPURenderBundleEncoder renderBundleEncoder, WGPUStringView groupLabel) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderBundleEncoderSetBindGroup: + * > @copydoc wgpuRenderBundleEncoderSetBindGroup + */ typedef void (*WGPUProcRenderBundleEncoderSetBindGroup)(WGPURenderBundleEncoder renderBundleEncoder, uint32_t groupIndex, WGPU_NULLABLE WGPUBindGroup group, size_t dynamicOffsetCount, uint32_t const * dynamicOffsets) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderBundleEncoderSetIndexBuffer: + * > @copydoc wgpuRenderBundleEncoderSetIndexBuffer + */ typedef void (*WGPUProcRenderBundleEncoderSetIndexBuffer)(WGPURenderBundleEncoder renderBundleEncoder, WGPUBuffer buffer, WGPUIndexFormat format, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcRenderBundleEncoderSetLabel)(WGPURenderBundleEncoder renderBundleEncoder, char const * label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderBundleEncoderSetLabel: + * > @copydoc wgpuRenderBundleEncoderSetLabel + */ +typedef void (*WGPUProcRenderBundleEncoderSetLabel)(WGPURenderBundleEncoder renderBundleEncoder, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderBundleEncoderSetPipeline: + * > @copydoc wgpuRenderBundleEncoderSetPipeline + */ typedef void (*WGPUProcRenderBundleEncoderSetPipeline)(WGPURenderBundleEncoder renderBundleEncoder, WGPURenderPipeline pipeline) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderBundleEncoderSetVertexBuffer: + * > @copydoc wgpuRenderBundleEncoderSetVertexBuffer + */ typedef void (*WGPUProcRenderBundleEncoderSetVertexBuffer)(WGPURenderBundleEncoder renderBundleEncoder, uint32_t slot, WGPU_NULLABLE WGPUBuffer buffer, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcRenderBundleEncoderReference)(WGPURenderBundleEncoder renderBundleEncoder) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderBundleEncoderAddRef. + * > @copydoc wgpuRenderBundleEncoderAddRef + */ +typedef void (*WGPUProcRenderBundleEncoderAddRef)(WGPURenderBundleEncoder renderBundleEncoder) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderBundleEncoderRelease. + * > @copydoc wgpuRenderBundleEncoderRelease + */ typedef void (*WGPUProcRenderBundleEncoderRelease)(WGPURenderBundleEncoder renderBundleEncoder) WGPU_FUNCTION_ATTRIBUTE; // Procs of RenderPassEncoder +/** + * Proc pointer type for @ref wgpuRenderPassEncoderBeginOcclusionQuery: + * > @copydoc wgpuRenderPassEncoderBeginOcclusionQuery + */ typedef void (*WGPUProcRenderPassEncoderBeginOcclusionQuery)(WGPURenderPassEncoder renderPassEncoder, uint32_t queryIndex) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderDraw: + * > @copydoc wgpuRenderPassEncoderDraw + */ typedef void (*WGPUProcRenderPassEncoderDraw)(WGPURenderPassEncoder renderPassEncoder, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderDrawIndexed: + * > @copydoc wgpuRenderPassEncoderDrawIndexed + */ typedef void (*WGPUProcRenderPassEncoderDrawIndexed)(WGPURenderPassEncoder renderPassEncoder, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t baseVertex, uint32_t firstInstance) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderDrawIndexedIndirect: + * > @copydoc wgpuRenderPassEncoderDrawIndexedIndirect + */ typedef void (*WGPUProcRenderPassEncoderDrawIndexedIndirect)(WGPURenderPassEncoder renderPassEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderDrawIndirect: + * > @copydoc wgpuRenderPassEncoderDrawIndirect + */ typedef void (*WGPUProcRenderPassEncoderDrawIndirect)(WGPURenderPassEncoder renderPassEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderEnd: + * > @copydoc wgpuRenderPassEncoderEnd + */ typedef void (*WGPUProcRenderPassEncoderEnd)(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderEndOcclusionQuery: + * > @copydoc wgpuRenderPassEncoderEndOcclusionQuery + */ typedef void (*WGPUProcRenderPassEncoderEndOcclusionQuery)(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderExecuteBundles: + * > @copydoc wgpuRenderPassEncoderExecuteBundles + */ typedef void (*WGPUProcRenderPassEncoderExecuteBundles)(WGPURenderPassEncoder renderPassEncoder, size_t bundleCount, WGPURenderBundle const * bundles) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcRenderPassEncoderInsertDebugMarker)(WGPURenderPassEncoder renderPassEncoder, char const * markerLabel) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderInsertDebugMarker: + * > @copydoc wgpuRenderPassEncoderInsertDebugMarker + */ +typedef void (*WGPUProcRenderPassEncoderInsertDebugMarker)(WGPURenderPassEncoder renderPassEncoder, WGPUStringView markerLabel) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderPopDebugGroup: + * > @copydoc wgpuRenderPassEncoderPopDebugGroup + */ typedef void (*WGPUProcRenderPassEncoderPopDebugGroup)(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcRenderPassEncoderPushDebugGroup)(WGPURenderPassEncoder renderPassEncoder, char const * groupLabel) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderPushDebugGroup: + * > @copydoc wgpuRenderPassEncoderPushDebugGroup + */ +typedef void (*WGPUProcRenderPassEncoderPushDebugGroup)(WGPURenderPassEncoder renderPassEncoder, WGPUStringView groupLabel) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderSetBindGroup: + * > @copydoc wgpuRenderPassEncoderSetBindGroup + */ typedef void (*WGPUProcRenderPassEncoderSetBindGroup)(WGPURenderPassEncoder renderPassEncoder, uint32_t groupIndex, WGPU_NULLABLE WGPUBindGroup group, size_t dynamicOffsetCount, uint32_t const * dynamicOffsets) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderSetBlendConstant: + * > @copydoc wgpuRenderPassEncoderSetBlendConstant + */ typedef void (*WGPUProcRenderPassEncoderSetBlendConstant)(WGPURenderPassEncoder renderPassEncoder, WGPUColor const * color) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderSetIndexBuffer: + * > @copydoc wgpuRenderPassEncoderSetIndexBuffer + */ typedef void (*WGPUProcRenderPassEncoderSetIndexBuffer)(WGPURenderPassEncoder renderPassEncoder, WGPUBuffer buffer, WGPUIndexFormat format, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcRenderPassEncoderSetLabel)(WGPURenderPassEncoder renderPassEncoder, char const * label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderSetLabel: + * > @copydoc wgpuRenderPassEncoderSetLabel + */ +typedef void (*WGPUProcRenderPassEncoderSetLabel)(WGPURenderPassEncoder renderPassEncoder, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderSetPipeline: + * > @copydoc wgpuRenderPassEncoderSetPipeline + */ typedef void (*WGPUProcRenderPassEncoderSetPipeline)(WGPURenderPassEncoder renderPassEncoder, WGPURenderPipeline pipeline) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderSetScissorRect: + * > @copydoc wgpuRenderPassEncoderSetScissorRect + */ typedef void (*WGPUProcRenderPassEncoderSetScissorRect)(WGPURenderPassEncoder renderPassEncoder, uint32_t x, uint32_t y, uint32_t width, uint32_t height) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderSetStencilReference: + * > @copydoc wgpuRenderPassEncoderSetStencilReference + */ typedef void (*WGPUProcRenderPassEncoderSetStencilReference)(WGPURenderPassEncoder renderPassEncoder, uint32_t reference) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderSetVertexBuffer: + * > @copydoc wgpuRenderPassEncoderSetVertexBuffer + */ typedef void (*WGPUProcRenderPassEncoderSetVertexBuffer)(WGPURenderPassEncoder renderPassEncoder, uint32_t slot, WGPU_NULLABLE WGPUBuffer buffer, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderSetViewport: + * > @copydoc wgpuRenderPassEncoderSetViewport + */ typedef void (*WGPUProcRenderPassEncoderSetViewport)(WGPURenderPassEncoder renderPassEncoder, float x, float y, float width, float height, float minDepth, float maxDepth) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcRenderPassEncoderReference)(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderAddRef. + * > @copydoc wgpuRenderPassEncoderAddRef + */ +typedef void (*WGPUProcRenderPassEncoderAddRef)(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPassEncoderRelease. + * > @copydoc wgpuRenderPassEncoderRelease + */ typedef void (*WGPUProcRenderPassEncoderRelease)(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; // Procs of RenderPipeline +/** + * Proc pointer type for @ref wgpuRenderPipelineGetBindGroupLayout: + * > @copydoc wgpuRenderPipelineGetBindGroupLayout + */ typedef WGPUBindGroupLayout (*WGPUProcRenderPipelineGetBindGroupLayout)(WGPURenderPipeline renderPipeline, uint32_t groupIndex) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcRenderPipelineSetLabel)(WGPURenderPipeline renderPipeline, char const * label) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcRenderPipelineReference)(WGPURenderPipeline renderPipeline) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPipelineSetLabel: + * > @copydoc wgpuRenderPipelineSetLabel + */ +typedef void (*WGPUProcRenderPipelineSetLabel)(WGPURenderPipeline renderPipeline, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPipelineAddRef. + * > @copydoc wgpuRenderPipelineAddRef + */ +typedef void (*WGPUProcRenderPipelineAddRef)(WGPURenderPipeline renderPipeline) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuRenderPipelineRelease. + * > @copydoc wgpuRenderPipelineRelease + */ typedef void (*WGPUProcRenderPipelineRelease)(WGPURenderPipeline renderPipeline) WGPU_FUNCTION_ATTRIBUTE; // Procs of Sampler -typedef void (*WGPUProcSamplerSetLabel)(WGPUSampler sampler, char const * label) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcSamplerReference)(WGPUSampler sampler) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuSamplerSetLabel: + * > @copydoc wgpuSamplerSetLabel + */ +typedef void (*WGPUProcSamplerSetLabel)(WGPUSampler sampler, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuSamplerAddRef. + * > @copydoc wgpuSamplerAddRef + */ +typedef void (*WGPUProcSamplerAddRef)(WGPUSampler sampler) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuSamplerRelease. + * > @copydoc wgpuSamplerRelease + */ typedef void (*WGPUProcSamplerRelease)(WGPUSampler sampler) WGPU_FUNCTION_ATTRIBUTE; // Procs of ShaderModule -typedef void (*WGPUProcShaderModuleGetCompilationInfo)(WGPUShaderModule shaderModule, WGPUShaderModuleGetCompilationInfoCallback callback, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcShaderModuleSetLabel)(WGPUShaderModule shaderModule, char const * label) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcShaderModuleReference)(WGPUShaderModule shaderModule) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuShaderModuleGetCompilationInfo: + * > @copydoc wgpuShaderModuleGetCompilationInfo + */ +typedef WGPUFuture (*WGPUProcShaderModuleGetCompilationInfo)(WGPUShaderModule shaderModule, WGPUCompilationInfoCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuShaderModuleSetLabel: + * > @copydoc wgpuShaderModuleSetLabel + */ +typedef void (*WGPUProcShaderModuleSetLabel)(WGPUShaderModule shaderModule, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuShaderModuleAddRef. + * > @copydoc wgpuShaderModuleAddRef + */ +typedef void (*WGPUProcShaderModuleAddRef)(WGPUShaderModule shaderModule) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuShaderModuleRelease. + * > @copydoc wgpuShaderModuleRelease + */ typedef void (*WGPUProcShaderModuleRelease)(WGPUShaderModule shaderModule) WGPU_FUNCTION_ATTRIBUTE; +// Procs of SupportedFeatures +/** + * Proc pointer type for @ref wgpuSupportedFeaturesFreeMembers: + * > @copydoc wgpuSupportedFeaturesFreeMembers + */ +typedef void (*WGPUProcSupportedFeaturesFreeMembers)(WGPUSupportedFeatures supportedFeatures) WGPU_FUNCTION_ATTRIBUTE; + +// Procs of SupportedWGSLLanguageFeatures +/** + * Proc pointer type for @ref wgpuSupportedWGSLLanguageFeaturesFreeMembers: + * > @copydoc wgpuSupportedWGSLLanguageFeaturesFreeMembers + */ +typedef void (*WGPUProcSupportedWGSLLanguageFeaturesFreeMembers)(WGPUSupportedWGSLLanguageFeatures supportedWGSLLanguageFeatures) WGPU_FUNCTION_ATTRIBUTE; + // Procs of Surface +/** + * Proc pointer type for @ref wgpuSurfaceConfigure: + * > @copydoc wgpuSurfaceConfigure + */ typedef void (*WGPUProcSurfaceConfigure)(WGPUSurface surface, WGPUSurfaceConfiguration const * config) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcSurfaceGetCapabilities)(WGPUSurface surface, WGPUAdapter adapter, WGPUSurfaceCapabilities * capabilities) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuSurfaceGetCapabilities: + * > @copydoc wgpuSurfaceGetCapabilities + */ +typedef WGPUStatus (*WGPUProcSurfaceGetCapabilities)(WGPUSurface surface, WGPUAdapter adapter, WGPUSurfaceCapabilities * capabilities) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuSurfaceGetCurrentTexture: + * > @copydoc wgpuSurfaceGetCurrentTexture + */ typedef void (*WGPUProcSurfaceGetCurrentTexture)(WGPUSurface surface, WGPUSurfaceTexture * surfaceTexture) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcSurfacePresent)(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcSurfaceSetLabel)(WGPUSurface surface, char const * label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuSurfacePresent: + * > @copydoc wgpuSurfacePresent + */ +typedef WGPUStatus (*WGPUProcSurfacePresent)(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuSurfaceSetLabel: + * > @copydoc wgpuSurfaceSetLabel + */ +typedef void (*WGPUProcSurfaceSetLabel)(WGPUSurface surface, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuSurfaceUnconfigure: + * > @copydoc wgpuSurfaceUnconfigure + */ typedef void (*WGPUProcSurfaceUnconfigure)(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcSurfaceReference)(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuSurfaceAddRef. + * > @copydoc wgpuSurfaceAddRef + */ +typedef void (*WGPUProcSurfaceAddRef)(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuSurfaceRelease. + * > @copydoc wgpuSurfaceRelease + */ typedef void (*WGPUProcSurfaceRelease)(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; // Procs of SurfaceCapabilities +/** + * Proc pointer type for @ref wgpuSurfaceCapabilitiesFreeMembers: + * > @copydoc wgpuSurfaceCapabilitiesFreeMembers + */ typedef void (*WGPUProcSurfaceCapabilitiesFreeMembers)(WGPUSurfaceCapabilities surfaceCapabilities) WGPU_FUNCTION_ATTRIBUTE; // Procs of Texture +/** + * Proc pointer type for @ref wgpuTextureCreateView: + * > @copydoc wgpuTextureCreateView + */ typedef WGPUTextureView (*WGPUProcTextureCreateView)(WGPUTexture texture, WGPU_NULLABLE WGPUTextureViewDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuTextureDestroy: + * > @copydoc wgpuTextureDestroy + */ typedef void (*WGPUProcTextureDestroy)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuTextureGetDepthOrArrayLayers: + * > @copydoc wgpuTextureGetDepthOrArrayLayers + */ typedef uint32_t (*WGPUProcTextureGetDepthOrArrayLayers)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuTextureGetDimension: + * > @copydoc wgpuTextureGetDimension + */ typedef WGPUTextureDimension (*WGPUProcTextureGetDimension)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuTextureGetFormat: + * > @copydoc wgpuTextureGetFormat + */ typedef WGPUTextureFormat (*WGPUProcTextureGetFormat)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuTextureGetHeight: + * > @copydoc wgpuTextureGetHeight + */ typedef uint32_t (*WGPUProcTextureGetHeight)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuTextureGetMipLevelCount: + * > @copydoc wgpuTextureGetMipLevelCount + */ typedef uint32_t (*WGPUProcTextureGetMipLevelCount)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuTextureGetSampleCount: + * > @copydoc wgpuTextureGetSampleCount + */ typedef uint32_t (*WGPUProcTextureGetSampleCount)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; -typedef WGPUTextureUsageFlags (*WGPUProcTextureGetUsage)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuTextureGetUsage: + * > @copydoc wgpuTextureGetUsage + */ +typedef WGPUTextureUsage (*WGPUProcTextureGetUsage)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuTextureGetWidth: + * > @copydoc wgpuTextureGetWidth + */ typedef uint32_t (*WGPUProcTextureGetWidth)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcTextureSetLabel)(WGPUTexture texture, char const * label) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcTextureReference)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuTextureSetLabel: + * > @copydoc wgpuTextureSetLabel + */ +typedef void (*WGPUProcTextureSetLabel)(WGPUTexture texture, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuTextureAddRef. + * > @copydoc wgpuTextureAddRef + */ +typedef void (*WGPUProcTextureAddRef)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuTextureRelease. + * > @copydoc wgpuTextureRelease + */ typedef void (*WGPUProcTextureRelease)(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; // Procs of TextureView -typedef void (*WGPUProcTextureViewSetLabel)(WGPUTextureView textureView, char const * label) WGPU_FUNCTION_ATTRIBUTE; -typedef void (*WGPUProcTextureViewReference)(WGPUTextureView textureView) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuTextureViewSetLabel: + * > @copydoc wgpuTextureViewSetLabel + */ +typedef void (*WGPUProcTextureViewSetLabel)(WGPUTextureView textureView, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuTextureViewAddRef. + * > @copydoc wgpuTextureViewAddRef + */ +typedef void (*WGPUProcTextureViewAddRef)(WGPUTextureView textureView) WGPU_FUNCTION_ATTRIBUTE; +/** + * Proc pointer type for @ref wgpuTextureViewRelease. + * > @copydoc wgpuTextureViewRelease + */ typedef void (*WGPUProcTextureViewRelease)(WGPUTextureView textureView) WGPU_FUNCTION_ATTRIBUTE; #endif // !defined(WGPU_SKIP_PROCS) @@ -1644,11 +3230,28 @@ typedef void (*WGPUProcTextureViewRelease)(WGPUTextureView textureView) WGPU_FUN /** * \defgroup GlobalFunctions Global Functions * \brief Functions that are not specific to an object. - * + * * @{ */ +/** + * Create a WGPUInstance + */ WGPU_EXPORT WGPUInstance wgpuCreateInstance(WGPU_NULLABLE WGPUInstanceDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT WGPUProc wgpuGetProcAddress(WGPUDevice device, char const * procName) WGPU_FUNCTION_ATTRIBUTE; +/** + * Query the supported instance capabilities. + * + * @param capabilities + * The supported instance capabilities + * + * @returns + * Indicates if there was an @ref OutStructChainError. + */ +WGPU_EXPORT WGPUStatus wgpuGetInstanceCapabilities(WGPUInstanceCapabilities * capabilities) WGPU_FUNCTION_ATTRIBUTE; +/** + * Returns the "procedure address" (function pointer) of the named function. + * The result must be cast to the appropriate proc pointer type. + */ +WGPU_EXPORT WGPUProc wgpuGetProcAddress(WGPUStringView procName) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1656,22 +3259,39 @@ WGPU_EXPORT WGPUProc wgpuGetProcAddress(WGPUDevice device, char const * procName /** * \defgroup Methods * \brief Functions that are relative to a specific object. - * + * * @{ */ /** * \defgroup WGPUAdapterMethods WGPUAdapter methods * \brief Functions whose first argument has type WGPUAdapter. - * + * * @{ */ -WGPU_EXPORT size_t wgpuAdapterEnumerateFeatures(WGPUAdapter adapter, WGPUFeatureName * features) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuAdapterGetInfo(WGPUAdapter adapter, WGPUAdapterInfo * info) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT WGPUBool wgpuAdapterGetLimits(WGPUAdapter adapter, WGPUSupportedLimits * limits) WGPU_FUNCTION_ATTRIBUTE; +/** + * Get the list of @ref WGPUFeatureName values supported by the adapter. + * + * @param features + * This parameter is @ref ReturnedWithOwnership. + */ +WGPU_EXPORT void wgpuAdapterGetFeatures(WGPUAdapter adapter, WGPUSupportedFeatures * features) WGPU_FUNCTION_ATTRIBUTE; +/** + * @param info + * This parameter is @ref ReturnedWithOwnership. + * + * @returns + * Indicates if there was an @ref OutStructChainError. + */ +WGPU_EXPORT WGPUStatus wgpuAdapterGetInfo(WGPUAdapter adapter, WGPUAdapterInfo * info) WGPU_FUNCTION_ATTRIBUTE; +/** + * @returns + * Indicates if there was an @ref OutStructChainError. + */ +WGPU_EXPORT WGPUStatus wgpuAdapterGetLimits(WGPUAdapter adapter, WGPULimits * limits) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT WGPUBool wgpuAdapterHasFeature(WGPUAdapter adapter, WGPUFeatureName feature) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuAdapterRequestDevice(WGPUAdapter adapter, WGPU_NULLABLE WGPUDeviceDescriptor const * descriptor, WGPUAdapterRequestDeviceCallback callback, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuAdapterReference(WGPUAdapter adapter) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUFuture wgpuAdapterRequestDevice(WGPUAdapter adapter, WGPU_NULLABLE WGPUDeviceDescriptor const * descriptor, WGPURequestDeviceCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuAdapterAddRef(WGPUAdapter adapter) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuAdapterRelease(WGPUAdapter adapter) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1680,9 +3300,12 @@ WGPU_EXPORT void wgpuAdapterRelease(WGPUAdapter adapter) WGPU_FUNCTION_ATTRIBUTE /** * \defgroup WGPUAdapterInfoMethods WGPUAdapterInfo methods * \brief Functions whose first argument has type WGPUAdapterInfo. - * + * * @{ */ +/** + * Frees array members of WGPUAdapterInfo which were allocated by the API. + */ WGPU_EXPORT void wgpuAdapterInfoFreeMembers(WGPUAdapterInfo adapterInfo) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1691,11 +3314,11 @@ WGPU_EXPORT void wgpuAdapterInfoFreeMembers(WGPUAdapterInfo adapterInfo) WGPU_FU /** * \defgroup WGPUBindGroupMethods WGPUBindGroup methods * \brief Functions whose first argument has type WGPUBindGroup. - * + * * @{ */ -WGPU_EXPORT void wgpuBindGroupSetLabel(WGPUBindGroup bindGroup, char const * label) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuBindGroupReference(WGPUBindGroup bindGroup) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuBindGroupSetLabel(WGPUBindGroup bindGroup, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuBindGroupAddRef(WGPUBindGroup bindGroup) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuBindGroupRelease(WGPUBindGroup bindGroup) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1704,11 +3327,11 @@ WGPU_EXPORT void wgpuBindGroupRelease(WGPUBindGroup bindGroup) WGPU_FUNCTION_ATT /** * \defgroup WGPUBindGroupLayoutMethods WGPUBindGroupLayout methods * \brief Functions whose first argument has type WGPUBindGroupLayout. - * + * * @{ */ -WGPU_EXPORT void wgpuBindGroupLayoutSetLabel(WGPUBindGroupLayout bindGroupLayout, char const * label) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuBindGroupLayoutReference(WGPUBindGroupLayout bindGroupLayout) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuBindGroupLayoutSetLabel(WGPUBindGroupLayout bindGroupLayout, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuBindGroupLayoutAddRef(WGPUBindGroupLayout bindGroupLayout) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuBindGroupLayoutRelease(WGPUBindGroupLayout bindGroupLayout) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1717,19 +3340,49 @@ WGPU_EXPORT void wgpuBindGroupLayoutRelease(WGPUBindGroupLayout bindGroupLayout) /** * \defgroup WGPUBufferMethods WGPUBuffer methods * \brief Functions whose first argument has type WGPUBuffer. - * + * * @{ */ WGPU_EXPORT void wgpuBufferDestroy(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +/** + * @param offset + * Byte offset relative to the beginning of the buffer. + * + * @param size + * Byte size of the range to get. The returned pointer is valid for exactly this many bytes. + * + * @returns + * Returns a const pointer to beginning of the mapped range. + * It must not be written; writing to this range causes undefined behavior. + * Returns `NULL` with @ref ImplementationDefinedLogging if: + * + * - There is any content-timeline error as defined in the WebGPU specification for `getMappedRange()` (alignments, overlaps, etc.) + * **except** for overlaps with other *const* ranges, which are allowed in C. + * (JS does not allow this because const ranges do not exist.) + */ WGPU_EXPORT void const * wgpuBufferGetConstMappedRange(WGPUBuffer buffer, size_t offset, size_t size) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT WGPUBufferMapState wgpuBufferGetMapState(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +/** + * @param offset + * Byte offset relative to the beginning of the buffer. + * + * @param size + * Byte size of the range to get. The returned pointer is valid for exactly this many bytes. + * + * @returns + * Returns a mutable pointer to beginning of the mapped range. + * Returns `NULL` with @ref ImplementationDefinedLogging if: + * + * - There is any content-timeline error as defined in the WebGPU specification for `getMappedRange()` (alignments, overlaps, etc.) + * - The buffer is not mapped with @ref WGPUMapMode_Write. + */ WGPU_EXPORT void * wgpuBufferGetMappedRange(WGPUBuffer buffer, size_t offset, size_t size) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT uint64_t wgpuBufferGetSize(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT WGPUBufferUsageFlags wgpuBufferGetUsage(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuBufferMapAsync(WGPUBuffer buffer, WGPUMapModeFlags mode, size_t offset, size_t size, WGPUBufferMapAsyncCallback callback, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuBufferSetLabel(WGPUBuffer buffer, char const * label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUBufferUsage wgpuBufferGetUsage(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUFuture wgpuBufferMapAsync(WGPUBuffer buffer, WGPUMapMode mode, size_t offset, size_t size, WGPUBufferMapCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuBufferSetLabel(WGPUBuffer buffer, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuBufferUnmap(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuBufferReference(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuBufferAddRef(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuBufferRelease(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1738,11 +3391,11 @@ WGPU_EXPORT void wgpuBufferRelease(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE; /** * \defgroup WGPUCommandBufferMethods WGPUCommandBuffer methods * \brief Functions whose first argument has type WGPUCommandBuffer. - * + * * @{ */ -WGPU_EXPORT void wgpuCommandBufferSetLabel(WGPUCommandBuffer commandBuffer, char const * label) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuCommandBufferReference(WGPUCommandBuffer commandBuffer) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandBufferSetLabel(WGPUCommandBuffer commandBuffer, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandBufferAddRef(WGPUCommandBuffer commandBuffer) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuCommandBufferRelease(WGPUCommandBuffer commandBuffer) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1751,24 +3404,24 @@ WGPU_EXPORT void wgpuCommandBufferRelease(WGPUCommandBuffer commandBuffer) WGPU_ /** * \defgroup WGPUCommandEncoderMethods WGPUCommandEncoder methods * \brief Functions whose first argument has type WGPUCommandEncoder. - * + * * @{ */ WGPU_EXPORT WGPUComputePassEncoder wgpuCommandEncoderBeginComputePass(WGPUCommandEncoder commandEncoder, WGPU_NULLABLE WGPUComputePassDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT WGPURenderPassEncoder wgpuCommandEncoderBeginRenderPass(WGPUCommandEncoder commandEncoder, WGPURenderPassDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuCommandEncoderClearBuffer(WGPUCommandEncoder commandEncoder, WGPUBuffer buffer, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuCommandEncoderCopyBufferToBuffer(WGPUCommandEncoder commandEncoder, WGPUBuffer source, uint64_t sourceOffset, WGPUBuffer destination, uint64_t destinationOffset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuCommandEncoderCopyBufferToTexture(WGPUCommandEncoder commandEncoder, WGPUImageCopyBuffer const * source, WGPUImageCopyTexture const * destination, WGPUExtent3D const * copySize) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuCommandEncoderCopyTextureToBuffer(WGPUCommandEncoder commandEncoder, WGPUImageCopyTexture const * source, WGPUImageCopyBuffer const * destination, WGPUExtent3D const * copySize) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuCommandEncoderCopyTextureToTexture(WGPUCommandEncoder commandEncoder, WGPUImageCopyTexture const * source, WGPUImageCopyTexture const * destination, WGPUExtent3D const * copySize) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderCopyBufferToTexture(WGPUCommandEncoder commandEncoder, WGPUTexelCopyBufferInfo const * source, WGPUTexelCopyTextureInfo const * destination, WGPUExtent3D const * copySize) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderCopyTextureToBuffer(WGPUCommandEncoder commandEncoder, WGPUTexelCopyTextureInfo const * source, WGPUTexelCopyBufferInfo const * destination, WGPUExtent3D const * copySize) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderCopyTextureToTexture(WGPUCommandEncoder commandEncoder, WGPUTexelCopyTextureInfo const * source, WGPUTexelCopyTextureInfo const * destination, WGPUExtent3D const * copySize) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT WGPUCommandBuffer wgpuCommandEncoderFinish(WGPUCommandEncoder commandEncoder, WGPU_NULLABLE WGPUCommandBufferDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuCommandEncoderInsertDebugMarker(WGPUCommandEncoder commandEncoder, char const * markerLabel) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderInsertDebugMarker(WGPUCommandEncoder commandEncoder, WGPUStringView markerLabel) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuCommandEncoderPopDebugGroup(WGPUCommandEncoder commandEncoder) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuCommandEncoderPushDebugGroup(WGPUCommandEncoder commandEncoder, char const * groupLabel) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderPushDebugGroup(WGPUCommandEncoder commandEncoder, WGPUStringView groupLabel) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuCommandEncoderResolveQuerySet(WGPUCommandEncoder commandEncoder, WGPUQuerySet querySet, uint32_t firstQuery, uint32_t queryCount, WGPUBuffer destination, uint64_t destinationOffset) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuCommandEncoderSetLabel(WGPUCommandEncoder commandEncoder, char const * label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderSetLabel(WGPUCommandEncoder commandEncoder, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuCommandEncoderWriteTimestamp(WGPUCommandEncoder commandEncoder, WGPUQuerySet querySet, uint32_t queryIndex) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuCommandEncoderReference(WGPUCommandEncoder commandEncoder) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuCommandEncoderAddRef(WGPUCommandEncoder commandEncoder) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuCommandEncoderRelease(WGPUCommandEncoder commandEncoder) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1777,19 +3430,19 @@ WGPU_EXPORT void wgpuCommandEncoderRelease(WGPUCommandEncoder commandEncoder) WG /** * \defgroup WGPUComputePassEncoderMethods WGPUComputePassEncoder methods * \brief Functions whose first argument has type WGPUComputePassEncoder. - * + * * @{ */ WGPU_EXPORT void wgpuComputePassEncoderDispatchWorkgroups(WGPUComputePassEncoder computePassEncoder, uint32_t workgroupCountX, uint32_t workgroupCountY, uint32_t workgroupCountZ) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuComputePassEncoderDispatchWorkgroupsIndirect(WGPUComputePassEncoder computePassEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuComputePassEncoderEnd(WGPUComputePassEncoder computePassEncoder) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuComputePassEncoderInsertDebugMarker(WGPUComputePassEncoder computePassEncoder, char const * markerLabel) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePassEncoderInsertDebugMarker(WGPUComputePassEncoder computePassEncoder, WGPUStringView markerLabel) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuComputePassEncoderPopDebugGroup(WGPUComputePassEncoder computePassEncoder) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuComputePassEncoderPushDebugGroup(WGPUComputePassEncoder computePassEncoder, char const * groupLabel) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePassEncoderPushDebugGroup(WGPUComputePassEncoder computePassEncoder, WGPUStringView groupLabel) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuComputePassEncoderSetBindGroup(WGPUComputePassEncoder computePassEncoder, uint32_t groupIndex, WGPU_NULLABLE WGPUBindGroup group, size_t dynamicOffsetCount, uint32_t const * dynamicOffsets) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuComputePassEncoderSetLabel(WGPUComputePassEncoder computePassEncoder, char const * label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePassEncoderSetLabel(WGPUComputePassEncoder computePassEncoder, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuComputePassEncoderSetPipeline(WGPUComputePassEncoder computePassEncoder, WGPUComputePipeline pipeline) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuComputePassEncoderReference(WGPUComputePassEncoder computePassEncoder) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePassEncoderAddRef(WGPUComputePassEncoder computePassEncoder) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuComputePassEncoderRelease(WGPUComputePassEncoder computePassEncoder) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1798,12 +3451,12 @@ WGPU_EXPORT void wgpuComputePassEncoderRelease(WGPUComputePassEncoder computePas /** * \defgroup WGPUComputePipelineMethods WGPUComputePipeline methods * \brief Functions whose first argument has type WGPUComputePipeline. - * + * * @{ */ WGPU_EXPORT WGPUBindGroupLayout wgpuComputePipelineGetBindGroupLayout(WGPUComputePipeline computePipeline, uint32_t groupIndex) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuComputePipelineSetLabel(WGPUComputePipeline computePipeline, char const * label) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuComputePipelineReference(WGPUComputePipeline computePipeline) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePipelineSetLabel(WGPUComputePipeline computePipeline, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuComputePipelineAddRef(WGPUComputePipeline computePipeline) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuComputePipelineRelease(WGPUComputePipeline computePipeline) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1812,7 +3465,7 @@ WGPU_EXPORT void wgpuComputePipelineRelease(WGPUComputePipeline computePipeline) /** * \defgroup WGPUDeviceMethods WGPUDevice methods * \brief Functions whose first argument has type WGPUDevice. - * + * * @{ */ WGPU_EXPORT WGPUBindGroup wgpuDeviceCreateBindGroup(WGPUDevice device, WGPUBindGroupDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; @@ -1820,24 +3473,40 @@ WGPU_EXPORT WGPUBindGroupLayout wgpuDeviceCreateBindGroupLayout(WGPUDevice devic WGPU_EXPORT WGPUBuffer wgpuDeviceCreateBuffer(WGPUDevice device, WGPUBufferDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT WGPUCommandEncoder wgpuDeviceCreateCommandEncoder(WGPUDevice device, WGPU_NULLABLE WGPUCommandEncoderDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT WGPUComputePipeline wgpuDeviceCreateComputePipeline(WGPUDevice device, WGPUComputePipelineDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuDeviceCreateComputePipelineAsync(WGPUDevice device, WGPUComputePipelineDescriptor const * descriptor, WGPUDeviceCreateComputePipelineAsyncCallback callback, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUFuture wgpuDeviceCreateComputePipelineAsync(WGPUDevice device, WGPUComputePipelineDescriptor const * descriptor, WGPUCreateComputePipelineAsyncCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT WGPUPipelineLayout wgpuDeviceCreatePipelineLayout(WGPUDevice device, WGPUPipelineLayoutDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT WGPUQuerySet wgpuDeviceCreateQuerySet(WGPUDevice device, WGPUQuerySetDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT WGPURenderBundleEncoder wgpuDeviceCreateRenderBundleEncoder(WGPUDevice device, WGPURenderBundleEncoderDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT WGPURenderPipeline wgpuDeviceCreateRenderPipeline(WGPUDevice device, WGPURenderPipelineDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuDeviceCreateRenderPipelineAsync(WGPUDevice device, WGPURenderPipelineDescriptor const * descriptor, WGPUDeviceCreateRenderPipelineAsyncCallback callback, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUFuture wgpuDeviceCreateRenderPipelineAsync(WGPUDevice device, WGPURenderPipelineDescriptor const * descriptor, WGPUCreateRenderPipelineAsyncCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT WGPUSampler wgpuDeviceCreateSampler(WGPUDevice device, WGPU_NULLABLE WGPUSamplerDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT WGPUShaderModule wgpuDeviceCreateShaderModule(WGPUDevice device, WGPUShaderModuleDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT WGPUTexture wgpuDeviceCreateTexture(WGPUDevice device, WGPUTextureDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuDeviceDestroy(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT size_t wgpuDeviceEnumerateFeatures(WGPUDevice device, WGPUFeatureName * features) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT WGPUBool wgpuDeviceGetLimits(WGPUDevice device, WGPUSupportedLimits * limits) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUAdapterInfo wgpuDeviceGetAdapterInfo(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +/** + * Get the list of @ref WGPUFeatureName values supported by the device. + * + * @param features + * This parameter is @ref ReturnedWithOwnership. + */ +WGPU_EXPORT void wgpuDeviceGetFeatures(WGPUDevice device, WGPUSupportedFeatures * features) WGPU_FUNCTION_ATTRIBUTE; +/** + * @returns + * Indicates if there was an @ref OutStructChainError. + */ +WGPU_EXPORT WGPUStatus wgpuDeviceGetLimits(WGPUDevice device, WGPULimits * limits) WGPU_FUNCTION_ATTRIBUTE; +/** + * @returns + * The @ref WGPUFuture for the device-lost event of the device. + */ +WGPU_EXPORT WGPUFuture wgpuDeviceGetLostFuture(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT WGPUQueue wgpuDeviceGetQueue(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT WGPUBool wgpuDeviceHasFeature(WGPUDevice device, WGPUFeatureName feature) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuDevicePopErrorScope(WGPUDevice device, WGPUErrorCallback callback, void * userdata) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUFuture wgpuDevicePopErrorScope(WGPUDevice device, WGPUPopErrorScopeCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuDevicePushErrorScope(WGPUDevice device, WGPUErrorFilter filter) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuDeviceSetLabel(WGPUDevice device, char const * label) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuDeviceReference(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuDeviceSetLabel(WGPUDevice device, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuDeviceAddRef(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuDeviceRelease(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1846,14 +3515,38 @@ WGPU_EXPORT void wgpuDeviceRelease(WGPUDevice device) WGPU_FUNCTION_ATTRIBUTE; /** * \defgroup WGPUInstanceMethods WGPUInstance methods * \brief Functions whose first argument has type WGPUInstance. - * + * * @{ */ +/** + * Creates a @ref WGPUSurface, see @ref Surface-Creation for more details. + * + * @param descriptor + * The description of the @ref WGPUSurface to create. + * + * @returns + * A new @ref WGPUSurface for this descriptor (or an error @ref WGPUSurface). + */ WGPU_EXPORT WGPUSurface wgpuInstanceCreateSurface(WGPUInstance instance, WGPUSurfaceDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT WGPUBool wgpuInstanceHasWGSLLanguageFeature(WGPUInstance instance, WGPUWGSLFeatureName feature) WGPU_FUNCTION_ATTRIBUTE; +/** + * Get the list of @ref WGPUWGSLLanguageFeatureName values supported by the instance. + */ +WGPU_EXPORT WGPUStatus wgpuInstanceGetWGSLLanguageFeatures(WGPUInstance instance, WGPUSupportedWGSLLanguageFeatures * features) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUBool wgpuInstanceHasWGSLLanguageFeature(WGPUInstance instance, WGPUWGSLLanguageFeatureName feature) WGPU_FUNCTION_ATTRIBUTE; +/** + * Processes asynchronous events on this `WGPUInstance`, calling any callbacks for asynchronous operations created with `::WGPUCallbackMode_AllowProcessEvents`. + * + * See @ref Process-Events for more information. + */ WGPU_EXPORT void wgpuInstanceProcessEvents(WGPUInstance instance) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuInstanceRequestAdapter(WGPUInstance instance, WGPU_NULLABLE WGPURequestAdapterOptions const * options, WGPUInstanceRequestAdapterCallback callback, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuInstanceReference(WGPUInstance instance) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUFuture wgpuInstanceRequestAdapter(WGPUInstance instance, WGPU_NULLABLE WGPURequestAdapterOptions const * options, WGPURequestAdapterCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +/** + * Wait for at least one WGPUFuture in `futures` to complete, and call callbacks of the respective completed asynchronous operations. + * + * See @ref Wait-Any for more information. + */ +WGPU_EXPORT WGPUWaitStatus wgpuInstanceWaitAny(WGPUInstance instance, size_t futureCount, WGPU_NULLABLE WGPUFutureWaitInfo * futures, uint64_t timeoutNS) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuInstanceAddRef(WGPUInstance instance) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuInstanceRelease(WGPUInstance instance) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1862,11 +3555,11 @@ WGPU_EXPORT void wgpuInstanceRelease(WGPUInstance instance) WGPU_FUNCTION_ATTRIB /** * \defgroup WGPUPipelineLayoutMethods WGPUPipelineLayout methods * \brief Functions whose first argument has type WGPUPipelineLayout. - * + * * @{ */ -WGPU_EXPORT void wgpuPipelineLayoutSetLabel(WGPUPipelineLayout pipelineLayout, char const * label) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuPipelineLayoutReference(WGPUPipelineLayout pipelineLayout) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuPipelineLayoutSetLabel(WGPUPipelineLayout pipelineLayout, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuPipelineLayoutAddRef(WGPUPipelineLayout pipelineLayout) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuPipelineLayoutRelease(WGPUPipelineLayout pipelineLayout) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1875,14 +3568,14 @@ WGPU_EXPORT void wgpuPipelineLayoutRelease(WGPUPipelineLayout pipelineLayout) WG /** * \defgroup WGPUQuerySetMethods WGPUQuerySet methods * \brief Functions whose first argument has type WGPUQuerySet. - * + * * @{ */ WGPU_EXPORT void wgpuQuerySetDestroy(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT uint32_t wgpuQuerySetGetCount(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT WGPUQueryType wgpuQuerySetGetType(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuQuerySetSetLabel(WGPUQuerySet querySet, char const * label) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuQuerySetReference(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuQuerySetSetLabel(WGPUQuerySet querySet, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuQuerySetAddRef(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuQuerySetRelease(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1891,15 +3584,19 @@ WGPU_EXPORT void wgpuQuerySetRelease(WGPUQuerySet querySet) WGPU_FUNCTION_ATTRIB /** * \defgroup WGPUQueueMethods WGPUQueue methods * \brief Functions whose first argument has type WGPUQueue. - * + * * @{ */ -WGPU_EXPORT void wgpuQueueOnSubmittedWorkDone(WGPUQueue queue, WGPUQueueOnSubmittedWorkDoneCallback callback, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuQueueSetLabel(WGPUQueue queue, char const * label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUFuture wgpuQueueOnSubmittedWorkDone(WGPUQueue queue, WGPUQueueWorkDoneCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuQueueSetLabel(WGPUQueue queue, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuQueueSubmit(WGPUQueue queue, size_t commandCount, WGPUCommandBuffer const * commands) WGPU_FUNCTION_ATTRIBUTE; +/** + * Produces a @ref DeviceError both content-timeline (`size` alignment) and device-timeline + * errors defined by the WebGPU specification. + */ WGPU_EXPORT void wgpuQueueWriteBuffer(WGPUQueue queue, WGPUBuffer buffer, uint64_t bufferOffset, void const * data, size_t size) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuQueueWriteTexture(WGPUQueue queue, WGPUImageCopyTexture const * destination, void const * data, size_t dataSize, WGPUTextureDataLayout const * dataLayout, WGPUExtent3D const * writeSize) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuQueueReference(WGPUQueue queue) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuQueueWriteTexture(WGPUQueue queue, WGPUTexelCopyTextureInfo const * destination, void const * data, size_t dataSize, WGPUTexelCopyBufferLayout const * dataLayout, WGPUExtent3D const * writeSize) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuQueueAddRef(WGPUQueue queue) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuQueueRelease(WGPUQueue queue) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1908,11 +3605,11 @@ WGPU_EXPORT void wgpuQueueRelease(WGPUQueue queue) WGPU_FUNCTION_ATTRIBUTE; /** * \defgroup WGPURenderBundleMethods WGPURenderBundle methods * \brief Functions whose first argument has type WGPURenderBundle. - * + * * @{ */ -WGPU_EXPORT void wgpuRenderBundleSetLabel(WGPURenderBundle renderBundle, char const * label) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuRenderBundleReference(WGPURenderBundle renderBundle) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleSetLabel(WGPURenderBundle renderBundle, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleAddRef(WGPURenderBundle renderBundle) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderBundleRelease(WGPURenderBundle renderBundle) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1921,7 +3618,7 @@ WGPU_EXPORT void wgpuRenderBundleRelease(WGPURenderBundle renderBundle) WGPU_FUN /** * \defgroup WGPURenderBundleEncoderMethods WGPURenderBundleEncoder methods * \brief Functions whose first argument has type WGPURenderBundleEncoder. - * + * * @{ */ WGPU_EXPORT void wgpuRenderBundleEncoderDraw(WGPURenderBundleEncoder renderBundleEncoder, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) WGPU_FUNCTION_ATTRIBUTE; @@ -1929,15 +3626,15 @@ WGPU_EXPORT void wgpuRenderBundleEncoderDrawIndexed(WGPURenderBundleEncoder rend WGPU_EXPORT void wgpuRenderBundleEncoderDrawIndexedIndirect(WGPURenderBundleEncoder renderBundleEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderBundleEncoderDrawIndirect(WGPURenderBundleEncoder renderBundleEncoder, WGPUBuffer indirectBuffer, uint64_t indirectOffset) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT WGPURenderBundle wgpuRenderBundleEncoderFinish(WGPURenderBundleEncoder renderBundleEncoder, WGPU_NULLABLE WGPURenderBundleDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuRenderBundleEncoderInsertDebugMarker(WGPURenderBundleEncoder renderBundleEncoder, char const * markerLabel) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleEncoderInsertDebugMarker(WGPURenderBundleEncoder renderBundleEncoder, WGPUStringView markerLabel) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderBundleEncoderPopDebugGroup(WGPURenderBundleEncoder renderBundleEncoder) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuRenderBundleEncoderPushDebugGroup(WGPURenderBundleEncoder renderBundleEncoder, char const * groupLabel) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleEncoderPushDebugGroup(WGPURenderBundleEncoder renderBundleEncoder, WGPUStringView groupLabel) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderBundleEncoderSetBindGroup(WGPURenderBundleEncoder renderBundleEncoder, uint32_t groupIndex, WGPU_NULLABLE WGPUBindGroup group, size_t dynamicOffsetCount, uint32_t const * dynamicOffsets) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderBundleEncoderSetIndexBuffer(WGPURenderBundleEncoder renderBundleEncoder, WGPUBuffer buffer, WGPUIndexFormat format, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuRenderBundleEncoderSetLabel(WGPURenderBundleEncoder renderBundleEncoder, char const * label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleEncoderSetLabel(WGPURenderBundleEncoder renderBundleEncoder, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderBundleEncoderSetPipeline(WGPURenderBundleEncoder renderBundleEncoder, WGPURenderPipeline pipeline) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderBundleEncoderSetVertexBuffer(WGPURenderBundleEncoder renderBundleEncoder, uint32_t slot, WGPU_NULLABLE WGPUBuffer buffer, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuRenderBundleEncoderReference(WGPURenderBundleEncoder renderBundleEncoder) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderBundleEncoderAddRef(WGPURenderBundleEncoder renderBundleEncoder) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderBundleEncoderRelease(WGPURenderBundleEncoder renderBundleEncoder) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1946,7 +3643,7 @@ WGPU_EXPORT void wgpuRenderBundleEncoderRelease(WGPURenderBundleEncoder renderBu /** * \defgroup WGPURenderPassEncoderMethods WGPURenderPassEncoder methods * \brief Functions whose first argument has type WGPURenderPassEncoder. - * + * * @{ */ WGPU_EXPORT void wgpuRenderPassEncoderBeginOcclusionQuery(WGPURenderPassEncoder renderPassEncoder, uint32_t queryIndex) WGPU_FUNCTION_ATTRIBUTE; @@ -1957,19 +3654,19 @@ WGPU_EXPORT void wgpuRenderPassEncoderDrawIndirect(WGPURenderPassEncoder renderP WGPU_EXPORT void wgpuRenderPassEncoderEnd(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderPassEncoderEndOcclusionQuery(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderPassEncoderExecuteBundles(WGPURenderPassEncoder renderPassEncoder, size_t bundleCount, WGPURenderBundle const * bundles) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuRenderPassEncoderInsertDebugMarker(WGPURenderPassEncoder renderPassEncoder, char const * markerLabel) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderInsertDebugMarker(WGPURenderPassEncoder renderPassEncoder, WGPUStringView markerLabel) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderPassEncoderPopDebugGroup(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuRenderPassEncoderPushDebugGroup(WGPURenderPassEncoder renderPassEncoder, char const * groupLabel) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderPushDebugGroup(WGPURenderPassEncoder renderPassEncoder, WGPUStringView groupLabel) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderPassEncoderSetBindGroup(WGPURenderPassEncoder renderPassEncoder, uint32_t groupIndex, WGPU_NULLABLE WGPUBindGroup group, size_t dynamicOffsetCount, uint32_t const * dynamicOffsets) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderPassEncoderSetBlendConstant(WGPURenderPassEncoder renderPassEncoder, WGPUColor const * color) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderPassEncoderSetIndexBuffer(WGPURenderPassEncoder renderPassEncoder, WGPUBuffer buffer, WGPUIndexFormat format, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuRenderPassEncoderSetLabel(WGPURenderPassEncoder renderPassEncoder, char const * label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderSetLabel(WGPURenderPassEncoder renderPassEncoder, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderPassEncoderSetPipeline(WGPURenderPassEncoder renderPassEncoder, WGPURenderPipeline pipeline) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderPassEncoderSetScissorRect(WGPURenderPassEncoder renderPassEncoder, uint32_t x, uint32_t y, uint32_t width, uint32_t height) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderPassEncoderSetStencilReference(WGPURenderPassEncoder renderPassEncoder, uint32_t reference) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderPassEncoderSetVertexBuffer(WGPURenderPassEncoder renderPassEncoder, uint32_t slot, WGPU_NULLABLE WGPUBuffer buffer, uint64_t offset, uint64_t size) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderPassEncoderSetViewport(WGPURenderPassEncoder renderPassEncoder, float x, float y, float width, float height, float minDepth, float maxDepth) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuRenderPassEncoderReference(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPassEncoderAddRef(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderPassEncoderRelease(WGPURenderPassEncoder renderPassEncoder) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1978,12 +3675,12 @@ WGPU_EXPORT void wgpuRenderPassEncoderRelease(WGPURenderPassEncoder renderPassEn /** * \defgroup WGPURenderPipelineMethods WGPURenderPipeline methods * \brief Functions whose first argument has type WGPURenderPipeline. - * + * * @{ */ WGPU_EXPORT WGPUBindGroupLayout wgpuRenderPipelineGetBindGroupLayout(WGPURenderPipeline renderPipeline, uint32_t groupIndex) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuRenderPipelineSetLabel(WGPURenderPipeline renderPipeline, char const * label) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuRenderPipelineReference(WGPURenderPipeline renderPipeline) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPipelineSetLabel(WGPURenderPipeline renderPipeline, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuRenderPipelineAddRef(WGPURenderPipeline renderPipeline) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuRenderPipelineRelease(WGPURenderPipeline renderPipeline) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -1992,11 +3689,11 @@ WGPU_EXPORT void wgpuRenderPipelineRelease(WGPURenderPipeline renderPipeline) WG /** * \defgroup WGPUSamplerMethods WGPUSampler methods * \brief Functions whose first argument has type WGPUSampler. - * + * * @{ */ -WGPU_EXPORT void wgpuSamplerSetLabel(WGPUSampler sampler, char const * label) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuSamplerReference(WGPUSampler sampler) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuSamplerSetLabel(WGPUSampler sampler, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuSamplerAddRef(WGPUSampler sampler) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuSamplerRelease(WGPUSampler sampler) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -2005,30 +3702,108 @@ WGPU_EXPORT void wgpuSamplerRelease(WGPUSampler sampler) WGPU_FUNCTION_ATTRIBUTE /** * \defgroup WGPUShaderModuleMethods WGPUShaderModule methods * \brief Functions whose first argument has type WGPUShaderModule. - * + * * @{ */ -WGPU_EXPORT void wgpuShaderModuleGetCompilationInfo(WGPUShaderModule shaderModule, WGPUShaderModuleGetCompilationInfoCallback callback, WGPU_NULLABLE void * userdata) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuShaderModuleSetLabel(WGPUShaderModule shaderModule, char const * label) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuShaderModuleReference(WGPUShaderModule shaderModule) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUFuture wgpuShaderModuleGetCompilationInfo(WGPUShaderModule shaderModule, WGPUCompilationInfoCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuShaderModuleSetLabel(WGPUShaderModule shaderModule, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuShaderModuleAddRef(WGPUShaderModule shaderModule) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuShaderModuleRelease(WGPUShaderModule shaderModule) WGPU_FUNCTION_ATTRIBUTE; /** @} */ +/** + * \defgroup WGPUSupportedFeaturesMethods WGPUSupportedFeatures methods + * \brief Functions whose first argument has type WGPUSupportedFeatures. + * + * @{ + */ +/** + * Frees array members of WGPUSupportedFeatures which were allocated by the API. + */ +WGPU_EXPORT void wgpuSupportedFeaturesFreeMembers(WGPUSupportedFeatures supportedFeatures) WGPU_FUNCTION_ATTRIBUTE; +/** @} */ + + + +/** + * \defgroup WGPUSupportedWGSLLanguageFeaturesMethods WGPUSupportedWGSLLanguageFeatures methods + * \brief Functions whose first argument has type WGPUSupportedWGSLLanguageFeatures. + * + * @{ + */ +/** + * Frees array members of WGPUSupportedWGSLLanguageFeatures which were allocated by the API. + */ +WGPU_EXPORT void wgpuSupportedWGSLLanguageFeaturesFreeMembers(WGPUSupportedWGSLLanguageFeatures supportedWGSLLanguageFeatures) WGPU_FUNCTION_ATTRIBUTE; +/** @} */ + + + /** * \defgroup WGPUSurfaceMethods WGPUSurface methods * \brief Functions whose first argument has type WGPUSurface. - * + * * @{ */ +/** + * Configures parameters for rendering to `surface`. + * Produces a @ref DeviceError for all content-timeline errors defined by the WebGPU specification. + * + * See @ref Surface-Configuration for more details. + * + * @param config + * The new configuration to use. + */ WGPU_EXPORT void wgpuSurfaceConfigure(WGPUSurface surface, WGPUSurfaceConfiguration const * config) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuSurfaceGetCapabilities(WGPUSurface surface, WGPUAdapter adapter, WGPUSurfaceCapabilities * capabilities) WGPU_FUNCTION_ATTRIBUTE; +/** + * Provides information on how `adapter` is able to use `surface`. + * See @ref Surface-Capabilities for more details. + * + * @param adapter + * The @ref WGPUAdapter to get capabilities for presenting to this @ref WGPUSurface. + * + * @param capabilities + * The structure to fill capabilities in. + * It may contain memory allocations so `::wgpuSurfaceCapabilitiesFreeMembers` must be called to avoid memory leaks. + * This parameter is @ref ReturnedWithOwnership. + * + * @returns + * Indicates if there was an @ref OutStructChainError. + */ +WGPU_EXPORT WGPUStatus wgpuSurfaceGetCapabilities(WGPUSurface surface, WGPUAdapter adapter, WGPUSurfaceCapabilities * capabilities) WGPU_FUNCTION_ATTRIBUTE; +/** + * Returns the @ref WGPUTexture to render to `surface` this frame along with metadata on the frame. + * Returns `NULL` and @ref WGPUSurfaceGetCurrentTextureStatus_Error if the surface is not configured. + * + * See @ref Surface-Presenting for more details. + * + * @param surfaceTexture + * The structure to fill the @ref WGPUTexture and metadata in. + */ WGPU_EXPORT void wgpuSurfaceGetCurrentTexture(WGPUSurface surface, WGPUSurfaceTexture * surfaceTexture) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuSurfacePresent(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuSurfaceSetLabel(WGPUSurface surface, char const * label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Shows `surface`'s current texture to the user. + * See @ref Surface-Presenting for more details. + * + * @returns + * Returns @ref WGPUStatus_Error if the surface doesn't have a current texture. + */ +WGPU_EXPORT WGPUStatus wgpuSurfacePresent(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; +/** + * Modifies the label used to refer to `surface`. + * + * @param label + * The new label. + */ +WGPU_EXPORT void wgpuSurfaceSetLabel(WGPUSurface surface, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +/** + * Removes the configuration for `surface`. + * See @ref Surface-Configuration for more details. + */ WGPU_EXPORT void wgpuSurfaceUnconfigure(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuSurfaceReference(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuSurfaceAddRef(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuSurfaceRelease(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -2037,9 +3812,12 @@ WGPU_EXPORT void wgpuSurfaceRelease(WGPUSurface surface) WGPU_FUNCTION_ATTRIBUTE /** * \defgroup WGPUSurfaceCapabilitiesMethods WGPUSurfaceCapabilities methods * \brief Functions whose first argument has type WGPUSurfaceCapabilities. - * + * * @{ */ +/** + * Frees array members of WGPUSurfaceCapabilities which were allocated by the API. + */ WGPU_EXPORT void wgpuSurfaceCapabilitiesFreeMembers(WGPUSurfaceCapabilities surfaceCapabilities) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -2048,7 +3826,7 @@ WGPU_EXPORT void wgpuSurfaceCapabilitiesFreeMembers(WGPUSurfaceCapabilities surf /** * \defgroup WGPUTextureMethods WGPUTexture methods * \brief Functions whose first argument has type WGPUTexture. - * + * * @{ */ WGPU_EXPORT WGPUTextureView wgpuTextureCreateView(WGPUTexture texture, WGPU_NULLABLE WGPUTextureViewDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE; @@ -2059,10 +3837,10 @@ WGPU_EXPORT WGPUTextureFormat wgpuTextureGetFormat(WGPUTexture texture) WGPU_FUN WGPU_EXPORT uint32_t wgpuTextureGetHeight(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT uint32_t wgpuTextureGetMipLevelCount(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT uint32_t wgpuTextureGetSampleCount(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT WGPUTextureUsageFlags wgpuTextureGetUsage(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT WGPUTextureUsage wgpuTextureGetUsage(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT uint32_t wgpuTextureGetWidth(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuTextureSetLabel(WGPUTexture texture, char const * label) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuTextureReference(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuTextureSetLabel(WGPUTexture texture, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuTextureAddRef(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuTextureRelease(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE; /** @} */ @@ -2071,11 +3849,11 @@ WGPU_EXPORT void wgpuTextureRelease(WGPUTexture texture) WGPU_FUNCTION_ATTRIBUTE /** * \defgroup WGPUTextureViewMethods WGPUTextureView methods * \brief Functions whose first argument has type WGPUTextureView. - * + * * @{ */ -WGPU_EXPORT void wgpuTextureViewSetLabel(WGPUTextureView textureView, char const * label) WGPU_FUNCTION_ATTRIBUTE; -WGPU_EXPORT void wgpuTextureViewReference(WGPUTextureView textureView) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuTextureViewSetLabel(WGPUTextureView textureView, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE; +WGPU_EXPORT void wgpuTextureViewAddRef(WGPUTextureView textureView) WGPU_FUNCTION_ATTRIBUTE; WGPU_EXPORT void wgpuTextureViewRelease(WGPUTextureView textureView) WGPU_FUNCTION_ATTRIBUTE; /** @} */ diff --git a/wgpu/resources/webgpu.idl b/wgpu/resources/webgpu.idl index 95f93322..cbc5c8d8 100644 --- a/wgpu/resources/webgpu.idl +++ b/wgpu/resources/webgpu.idl @@ -1,4 +1,4 @@ -// Copyright (C) [2024] World Wide Web Consortium, +// Copyright (C) [2025] World Wide Web Consortium, // (Massachusetts Institute of Technology, European Research Consortium for // Informatics and Mathematics, Keio University, Beihang). // All Rights Reserved. @@ -43,7 +43,6 @@ interface GPUSupportedLimits { readonly attribute unsigned long long maxBufferSize; readonly attribute unsigned long maxVertexAttributes; readonly attribute unsigned long maxVertexBufferArrayStride; - readonly attribute unsigned long maxInterStageShaderComponents; readonly attribute unsigned long maxInterStageShaderVariables; readonly attribute unsigned long maxColorAttachments; readonly attribute unsigned long maxColorAttachmentBytesPerSample; @@ -71,6 +70,8 @@ interface GPUAdapterInfo { readonly attribute DOMString architecture; readonly attribute DOMString device; readonly attribute DOMString description; + readonly attribute unsigned long subgroupMinSize; + readonly attribute unsigned long subgroupMaxSize; }; interface mixin NavigatorGPU { @@ -87,8 +88,10 @@ interface GPU { }; dictionary GPURequestAdapterOptions { + DOMString featureLevel = "core"; GPUPowerPreference powerPreference; boolean forceFallbackAdapter = false; + boolean xrCompatible = false; }; enum GPUPowerPreference { @@ -109,7 +112,7 @@ interface GPUAdapter { dictionary GPUDeviceDescriptor : GPUObjectDescriptorBase { sequence requiredFeatures = []; - record requiredLimits = {}; + record requiredLimits = {}; GPUQueueDescriptor defaultQueue = {}; }; @@ -120,20 +123,24 @@ enum GPUFeatureName { "texture-compression-bc-sliced-3d", "texture-compression-etc2", "texture-compression-astc", + "texture-compression-astc-sliced-3d", "timestamp-query", "indirect-first-instance", "shader-f16", "rg11b10ufloat-renderable", "bgra8unorm-storage", "float32-filterable", + "float32-blendable", "clip-distances", "dual-source-blending", + "subgroups", }; [Exposed=(Window, Worker), SecureContext] interface GPUDevice : EventTarget { [SameObject] readonly attribute GPUSupportedFeatures features; [SameObject] readonly attribute GPUSupportedLimits limits; + [SameObject] readonly attribute GPUAdapterInfo adapterInfo; [SameObject] readonly attribute GPUQueue queue; @@ -264,6 +271,7 @@ dictionary GPUTextureViewDescriptor : GPUObjectDescriptorBase { GPUTextureFormat format; GPUTextureViewDimension dimension; + GPUTextureUsageFlags usage = 0; GPUTextureAspect aspect = "all"; GPUIntegerCoordinate baseMipLevel = 0; GPUIntegerCoordinate mipLevelCount; @@ -575,7 +583,7 @@ GPUPipelineLayout includes GPUObjectBase; dictionary GPUPipelineLayoutDescriptor : GPUObjectDescriptorBase { - required sequence bindGroupLayouts; + required sequence bindGroupLayouts; }; [Exposed=(Window, Worker), SecureContext] @@ -587,7 +595,6 @@ GPUShaderModule includes GPUObjectBase; dictionary GPUShaderModuleDescriptor : GPUObjectDescriptorBase { required USVString code; - object sourceMap; sequence compilationHints = []; }; @@ -648,7 +655,7 @@ interface mixin GPUPipelineBase { dictionary GPUProgrammableStage { required GPUShaderModule module; USVString entryPoint; - record constants; + record constants = {}; }; typedef double GPUPipelineConstantValue; // May represent WGSL's bool, f32, i32, u32, and f16 if enabled. @@ -816,22 +823,31 @@ enum GPUIndexFormat { }; enum GPUVertexFormat { + "uint8", "uint8x2", "uint8x4", + "sint8", "sint8x2", "sint8x4", + "unorm8", "unorm8x2", "unorm8x4", + "snorm8", "snorm8x2", "snorm8x4", + "uint16", "uint16x2", "uint16x4", + "sint16", "sint16x2", "sint16x4", + "unorm16", "unorm16x2", "unorm16x4", + "snorm16", "snorm16x2", "snorm16x4", + "float16", "float16x2", "float16x4", "float32", @@ -847,6 +863,7 @@ enum GPUVertexFormat { "sint32x3", "sint32x4", "unorm10-10-10-2", + "unorm8x4-bgra", }; enum GPUVertexStepMode { @@ -872,26 +889,26 @@ dictionary GPUVertexAttribute { required GPUIndex32 shaderLocation; }; -dictionary GPUImageDataLayout { +dictionary GPUTexelCopyBufferLayout { GPUSize64 offset = 0; GPUSize32 bytesPerRow; GPUSize32 rowsPerImage; }; -dictionary GPUImageCopyBuffer - : GPUImageDataLayout { +dictionary GPUTexelCopyBufferInfo + : GPUTexelCopyBufferLayout { required GPUBuffer buffer; }; -dictionary GPUImageCopyTexture { +dictionary GPUTexelCopyTextureInfo { required GPUTexture texture; GPUIntegerCoordinate mipLevel = 0; GPUOrigin3D origin = {}; GPUTextureAspect aspect = "all"; }; -dictionary GPUImageCopyTextureTagged - : GPUImageCopyTexture { +dictionary GPUCopyExternalImageDestInfo + : GPUTexelCopyTextureInfo { PredefinedColorSpace colorSpace = "srgb"; boolean premultipliedAlpha = false; }; @@ -902,10 +919,10 @@ typedef (ImageBitmap or HTMLVideoElement or VideoFrame or HTMLCanvasElement or - OffscreenCanvas) GPUImageCopyExternalImageSource; + OffscreenCanvas) GPUCopyExternalImageSource; -dictionary GPUImageCopyExternalImage { - required GPUImageCopyExternalImageSource source; +dictionary GPUCopyExternalImageSourceInfo { + required GPUCopyExternalImageSource source; GPUOrigin2D origin = {}; boolean flipY = false; }; @@ -935,18 +952,18 @@ interface GPUCommandEncoder { GPUSize64 size); undefined copyBufferToTexture( - GPUImageCopyBuffer source, - GPUImageCopyTexture destination, + GPUTexelCopyBufferInfo source, + GPUTexelCopyTextureInfo destination, GPUExtent3D copySize); undefined copyTextureToBuffer( - GPUImageCopyTexture source, - GPUImageCopyBuffer destination, + GPUTexelCopyTextureInfo source, + GPUTexelCopyBufferInfo destination, GPUExtent3D copySize); undefined copyTextureToTexture( - GPUImageCopyTexture source, - GPUImageCopyTexture destination, + GPUTexelCopyTextureInfo source, + GPUTexelCopyTextureInfo destination, GPUExtent3D copySize); undefined clearBuffer( @@ -1151,14 +1168,14 @@ interface GPUQueue { optional GPUSize64 size); undefined writeTexture( - GPUImageCopyTexture destination, + GPUTexelCopyTextureInfo destination, AllowSharedBufferSource data, - GPUImageDataLayout dataLayout, + GPUTexelCopyBufferLayout dataLayout, GPUExtent3D size); undefined copyExternalImageToTexture( - GPUImageCopyExternalImage source, - GPUImageCopyTextureTagged destination, + GPUCopyExternalImageSourceInfo source, + GPUCopyExternalImageDestInfo destination, GPUExtent3D copySize); }; GPUQueue includes GPUObjectBase; @@ -1190,6 +1207,7 @@ interface GPUCanvasContext { undefined configure(GPUCanvasConfiguration configuration); undefined unconfigure(); + GPUCanvasConfiguration? getConfiguration(); GPUTexture getCurrentTexture(); }; @@ -1280,7 +1298,6 @@ dictionary GPUUncapturedErrorEventInit : EventInit { }; partial interface GPUDevice { - [Exposed=(Window, Worker)] attribute EventHandler onuncapturederror; }; diff --git a/wgpu/resources/wgpu.h b/wgpu/resources/wgpu.h index 28a51f62..6cee9d15 100644 --- a/wgpu/resources/wgpu.h +++ b/wgpu/resources/wgpu.h @@ -6,10 +6,9 @@ typedef enum WGPUNativeSType { // Start at 0003 since that's allocated range for wgpu-native WGPUSType_DeviceExtras = 0x00030001, - WGPUSType_RequiredLimitsExtras = 0x00030002, + WGPUSType_NativeLimits = 0x00030002, WGPUSType_PipelineLayoutExtras = 0x00030003, WGPUSType_ShaderModuleGLSLDescriptor = 0x00030004, - WGPUSType_SupportedLimitsExtras = 0x00030005, WGPUSType_InstanceExtras = 0x00030006, WGPUSType_BindGroupEntryExtras = 0x00030007, WGPUSType_BindGroupLayoutEntryExtras = 0x00030008, @@ -31,8 +30,6 @@ typedef enum WGPUNativeFeature { WGPUNativeFeature_PartiallyBoundBindingArray = 0x0003000A, WGPUNativeFeature_TextureFormat16bitNorm = 0x0003000B, WGPUNativeFeature_TextureCompressionAstcHdr = 0x0003000C, - // TODO: requires wgpu.h api change - // WGPUNativeFeature_TimestampQueryInsidePasses = 0x0003000D, WGPUNativeFeature_MappablePrimaryBuffers = 0x0003000E, WGPUNativeFeature_BufferBindingArray = 0x0003000F, WGPUNativeFeature_UniformBufferAndStorageTextureArrayNonUniformIndexing = 0x00030010, @@ -43,7 +40,7 @@ typedef enum WGPUNativeFeature { // WGPUNativeFeature_PolygonModePoint = 0x00030014, // WGPUNativeFeature_ConservativeRasterization = 0x00030015, // WGPUNativeFeature_ClearTexture = 0x00030016, - // WGPUNativeFeature_SpirvShaderPassthrough = 0x00030017, + WGPUNativeFeature_SpirvShaderPassthrough = 0x00030017, // WGPUNativeFeature_Multiview = 0x00030018, WGPUNativeFeature_VertexAttribute64bit = 0x00030019, WGPUNativeFeature_TextureFormatNv12 = 0x0003001A, @@ -53,6 +50,11 @@ typedef enum WGPUNativeFeature { WGPUNativeFeature_ShaderI16 = 0x0003001E, WGPUNativeFeature_ShaderPrimitiveIndex = 0x0003001F, WGPUNativeFeature_ShaderEarlyDepthTest = 0x00030020, + WGPUNativeFeature_Subgroup = 0x00030021, + WGPUNativeFeature_SubgroupVertex = 0x00030022, + WGPUNativeFeature_SubgroupBarrier = 0x00030023, + WGPUNativeFeature_TimestampQueryInsideEncoders = 0x00030024, + WGPUNativeFeature_TimestampQueryInsidePasses = 0x00030025, WGPUNativeFeature_Force32 = 0x7FFFFFFF } WGPUNativeFeature; @@ -66,30 +68,26 @@ typedef enum WGPULogLevel { WGPULogLevel_Force32 = 0x7FFFFFFF } WGPULogLevel; -typedef enum WGPUInstanceBackend { - WGPUInstanceBackend_All = 0x00000000, - WGPUInstanceBackend_Vulkan = 1 << 0, - WGPUInstanceBackend_GL = 1 << 1, - WGPUInstanceBackend_Metal = 1 << 2, - WGPUInstanceBackend_DX12 = 1 << 3, - WGPUInstanceBackend_DX11 = 1 << 4, - WGPUInstanceBackend_BrowserWebGPU = 1 << 5, - WGPUInstanceBackend_Primary = WGPUInstanceBackend_Vulkan | WGPUInstanceBackend_Metal | - WGPUInstanceBackend_DX12 | - WGPUInstanceBackend_BrowserWebGPU, - WGPUInstanceBackend_Secondary = WGPUInstanceBackend_GL | WGPUInstanceBackend_DX11, - WGPUInstanceBackend_Force32 = 0x7FFFFFFF -} WGPUInstanceBackend; -typedef WGPUFlags WGPUInstanceBackendFlags; - -typedef enum WGPUInstanceFlag { - WGPUInstanceFlag_Default = 0x00000000, - WGPUInstanceFlag_Debug = 1 << 0, - WGPUInstanceFlag_Validation = 1 << 1, - WGPUInstanceFlag_DiscardHalLabels = 1 << 2, - WGPUInstanceFlag_Force32 = 0x7FFFFFFF -} WGPUInstanceFlag; -typedef WGPUFlags WGPUInstanceFlags; +typedef WGPUFlags WGPUInstanceBackend; +static const WGPUInstanceBackend WGPUInstanceBackend_All = 0x00000000; +static const WGPUInstanceBackend WGPUInstanceBackend_Vulkan = 1 << 0; +static const WGPUInstanceBackend WGPUInstanceBackend_GL = 1 << 1; +static const WGPUInstanceBackend WGPUInstanceBackend_Metal = 1 << 2; +static const WGPUInstanceBackend WGPUInstanceBackend_DX12 = 1 << 3; +static const WGPUInstanceBackend WGPUInstanceBackend_DX11 = 1 << 4; +static const WGPUInstanceBackend WGPUInstanceBackend_BrowserWebGPU = 1 << 5; +// Vulkan, Metal, DX12 and BrowserWebGPU +static const WGPUInstanceBackend WGPUInstanceBackend_Primary = (1 << 0) | (1 << 2) | (1 << 3) | (1 << 5); +// GL and DX11 +static const WGPUInstanceBackend WGPUInstanceBackend_Secondary = (1 << 1) | (1 << 4); +static const WGPUInstanceBackend WGPUInstanceBackend_Force32 = 0x7FFFFFFF; + +typedef WGPUFlags WGPUInstanceFlag; +static const WGPUInstanceFlag WGPUInstanceFlag_Default = 0x00000000; +static const WGPUInstanceFlag WGPUInstanceFlag_Debug = 1 << 0; +static const WGPUInstanceFlag WGPUInstanceFlag_Validation = 1 << 1; +static const WGPUInstanceFlag WGPUInstanceFlag_DiscardHalLabels = 1 << 2; +static const WGPUInstanceFlag WGPUInstanceFlag_Force32 = 0x7FFFFFFF; typedef enum WGPUDx12Compiler { WGPUDx12Compiler_Undefined = 0x00000000, @@ -122,36 +120,28 @@ typedef enum WGPUNativeQueryType { typedef struct WGPUInstanceExtras { WGPUChainedStruct chain; - WGPUInstanceBackendFlags backends; - WGPUInstanceFlags flags; + WGPUInstanceBackend backends; + WGPUInstanceFlag flags; WGPUDx12Compiler dx12ShaderCompiler; WGPUGles3MinorVersion gles3MinorVersion; - const char * dxilPath; - const char * dxcPath; + WGPUStringView dxilPath; + WGPUStringView dxcPath; } WGPUInstanceExtras; typedef struct WGPUDeviceExtras { WGPUChainedStruct chain; - const char * tracePath; + WGPUStringView tracePath; } WGPUDeviceExtras; typedef struct WGPUNativeLimits { + /** This struct chain is used as mutable in some places and immutable in others. */ + WGPUChainedStructOut chain; uint32_t maxPushConstantSize; uint32_t maxNonSamplerBindings; } WGPUNativeLimits; -typedef struct WGPURequiredLimitsExtras { - WGPUChainedStruct chain; - WGPUNativeLimits limits; -} WGPURequiredLimitsExtras; - -typedef struct WGPUSupportedLimitsExtras { - WGPUChainedStructOut chain; - WGPUNativeLimits limits; -} WGPUSupportedLimitsExtras; - typedef struct WGPUPushConstantRange { - WGPUShaderStageFlags stages; + WGPUShaderStage stages; uint32_t start; uint32_t end; } WGPUPushConstantRange; @@ -164,29 +154,29 @@ typedef struct WGPUPipelineLayoutExtras { typedef uint64_t WGPUSubmissionIndex; -typedef struct WGPUWrappedSubmissionIndex { - WGPUQueue queue; - WGPUSubmissionIndex submissionIndex; -} WGPUWrappedSubmissionIndex; - typedef struct WGPUShaderDefine { - char const * name; - char const * value; + WGPUStringView name; + WGPUStringView value; } WGPUShaderDefine; typedef struct WGPUShaderModuleGLSLDescriptor { WGPUChainedStruct chain; WGPUShaderStage stage; - char const * code; + WGPUStringView code; uint32_t defineCount; WGPUShaderDefine * defines; } WGPUShaderModuleGLSLDescriptor; +typedef struct WGPUShaderModuleDescriptorSpirV { + WGPUStringView label; + uint32_t sourceSize; + uint32_t const * source; +} WGPUShaderModuleDescriptorSpirV; + typedef struct WGPURegistryReport { size_t numAllocated; size_t numKeptFromUser; size_t numReleasedFromUser; - size_t numError; size_t elementSize; } WGPURegistryReport; @@ -202,6 +192,7 @@ typedef struct WGPUHubReport { WGPURegistryReport renderBundles; WGPURegistryReport renderPipelines; WGPURegistryReport computePipelines; + WGPURegistryReport pipelineCaches; WGPURegistryReport querySets; WGPURegistryReport buffers; WGPURegistryReport textures; @@ -211,16 +202,12 @@ typedef struct WGPUHubReport { typedef struct WGPUGlobalReport { WGPURegistryReport surfaces; - WGPUBackendType backendType; - WGPUHubReport vulkan; - WGPUHubReport metal; - WGPUHubReport dx12; - WGPUHubReport gl; + WGPUHubReport hub; } WGPUGlobalReport; typedef struct WGPUInstanceEnumerateAdapterOptions { WGPUChainedStruct const * nextInChain; - WGPUInstanceBackendFlags backends; + WGPUInstanceBackend backends; } WGPUInstanceEnumerateAdapterOptions; typedef struct WGPUBindGroupEntryExtras { @@ -249,7 +236,7 @@ typedef struct WGPUSurfaceConfigurationExtras { uint32_t desiredMaximumFrameLatency; } WGPUSurfaceConfigurationExtras WGPU_STRUCTURE_ATTRIBUTE; -typedef void (*WGPULogCallback)(WGPULogLevel level, char const * message, void * userdata); +typedef void (*WGPULogCallback)(WGPULogLevel level, WGPUStringView message, void * userdata); typedef enum WGPUNativeTextureFormat { // From Features::TEXTURE_FORMAT_16BIT_NORM @@ -273,7 +260,8 @@ size_t wgpuInstanceEnumerateAdapters(WGPUInstance instance, WGPU_NULLABLE WGPUIn WGPUSubmissionIndex wgpuQueueSubmitForIndex(WGPUQueue queue, size_t commandCount, WGPUCommandBuffer const * commands); // Returns true if the queue is empty, or false if there are more queue submissions still in flight. -WGPUBool wgpuDevicePoll(WGPUDevice device, WGPUBool wait, WGPU_NULLABLE WGPUWrappedSubmissionIndex const * wrappedSubmissionIndex); +WGPUBool wgpuDevicePoll(WGPUDevice device, WGPUBool wait, WGPU_NULLABLE WGPUSubmissionIndex const * wrappedSubmissionIndex); +WGPUShaderModule wgpuDeviceCreateShaderModuleSpirV(WGPUDevice device, WGPUShaderModuleDescriptorSpirV const * descriptor); void wgpuSetLogCallback(WGPULogCallback callback, void * userdata); @@ -281,7 +269,9 @@ void wgpuSetLogLevel(WGPULogLevel level); uint32_t wgpuGetVersion(void); -void wgpuRenderPassEncoderSetPushConstants(WGPURenderPassEncoder encoder, WGPUShaderStageFlags stages, uint32_t offset, uint32_t sizeBytes, void const * data); +void wgpuRenderPassEncoderSetPushConstants(WGPURenderPassEncoder encoder, WGPUShaderStage stages, uint32_t offset, uint32_t sizeBytes, void const * data); +void wgpuComputePassEncoderSetPushConstants(WGPUComputePassEncoder encoder, uint32_t offset, uint32_t sizeBytes, void const * data); +void wgpuRenderBundleEncoderSetPushConstants(WGPURenderBundleEncoder encoder, WGPUShaderStage stages, uint32_t offset, uint32_t sizeBytes, void const * data); void wgpuRenderPassEncoderMultiDrawIndirect(WGPURenderPassEncoder encoder, WGPUBuffer buffer, uint64_t offset, uint32_t count); void wgpuRenderPassEncoderMultiDrawIndexedIndirect(WGPURenderPassEncoder encoder, WGPUBuffer buffer, uint64_t offset, uint32_t count); @@ -294,6 +284,9 @@ void wgpuComputePassEncoderEndPipelineStatisticsQuery(WGPUComputePassEncoder com void wgpuRenderPassEncoderBeginPipelineStatisticsQuery(WGPURenderPassEncoder renderPassEncoder, WGPUQuerySet querySet, uint32_t queryIndex); void wgpuRenderPassEncoderEndPipelineStatisticsQuery(WGPURenderPassEncoder renderPassEncoder); +void wgpuComputePassEncoderWriteTimestamp(WGPUComputePassEncoder computePassEncoder, WGPUQuerySet querySet, uint32_t queryIndex); +void wgpuRenderPassEncoderWriteTimestamp(WGPURenderPassEncoder renderPassEncoder, WGPUQuerySet querySet, uint32_t queryIndex); + #ifdef __cplusplus } // extern "C" #endif diff --git a/wgpu/structs.py b/wgpu/structs.py index 857a34c7..6983956f 100644 --- a/wgpu/structs.py +++ b/wgpu/structs.py @@ -48,16 +48,14 @@ def __repr__(self): "ComputePassDescriptor", "ComputePassTimestampWrites", "ComputePipelineDescriptor", + "CopyExternalImageDestInfo", + "CopyExternalImageSourceInfo", "DepthStencilState", "DeviceDescriptor", "Extent3D", "ExternalTextureBindingLayout", "ExternalTextureDescriptor", "FragmentState", - "ImageCopyBuffer", - "ImageCopyExternalImage", - "ImageCopyTexture", - "ImageDataLayout", "MultisampleState", "Origin2D", "Origin3D", @@ -82,6 +80,9 @@ def __repr__(self): "ShaderModuleDescriptor", "StencilFaceState", "StorageTextureBindingLayout", + "TexelCopyBufferInfo", + "TexelCopyBufferLayout", + "TexelCopyTextureInfo", "TextureBindingLayout", "TextureDescriptor", "TextureViewDescriptor", @@ -92,23 +93,27 @@ def __repr__(self): ] +#: * featureLevel :: str = "core" #: * powerPreference :: :obj:`enums.PowerPreference ` #: * forceFallbackAdapter :: bool = false +#: * xrCompatible :: bool = false RequestAdapterOptions = Struct( "RequestAdapterOptions", + feature_level="str", power_preference="enums.PowerPreference", force_fallback_adapter="bool", + xr_compatible="bool", ) #: * label :: str = "" #: * requiredFeatures :: List[:obj:`enums.FeatureName `] = [] -#: * requiredLimits :: Dict[str, int] = {} +#: * requiredLimits :: Dict[str, Union[None, int]] = {} #: * defaultQueue :: :obj:`structs.QueueDescriptor ` = {} DeviceDescriptor = Struct( "DeviceDescriptor", label="str", required_features="List[enums.FeatureName]", - required_limits="Dict[str, int]", + required_limits="Dict[str, Union[None, int]]", default_queue="structs.QueueDescriptor", ) @@ -147,6 +152,7 @@ def __repr__(self): #: * label :: str = "" #: * format :: :obj:`enums.TextureFormat ` #: * dimension :: :obj:`enums.TextureViewDimension ` +#: * usage :: :obj:`flags.TextureUsage ` = 0 #: * aspect :: :obj:`enums.TextureAspect ` = "all" #: * baseMipLevel :: int = 0 #: * mipLevelCount :: int @@ -157,6 +163,7 @@ def __repr__(self): label="str", format="enums.TextureFormat", dimension="enums.TextureViewDimension", + usage="flags.TextureUsage", aspect="enums.TextureAspect", base_mip_level="int", mip_level_count="int", @@ -304,13 +311,11 @@ def __repr__(self): #: * label :: str = "" #: * code :: str -#: * sourceMap :: dict #: * compilationHints :: List[:obj:`structs.ShaderModuleCompilationHint `] = [] ShaderModuleDescriptor = Struct( "ShaderModuleDescriptor", label="str", code="str", - source_map="dict", compilation_hints="List[structs.ShaderModuleCompilationHint]", ) @@ -330,7 +335,7 @@ def __repr__(self): #: * module :: :class:`GPUShaderModule ` #: * entryPoint :: str -#: * constants :: Dict[str, float] +#: * constants :: Dict[str, float] = {} ProgrammableStage = Struct( "ProgrammableStage", module="GPUShaderModule", @@ -392,7 +397,7 @@ def __repr__(self): #: * module :: :class:`GPUShaderModule ` #: * entryPoint :: str -#: * constants :: Dict[str, float] +#: * constants :: Dict[str, float] = {} #: * targets :: List[:obj:`structs.ColorTargetState `] FragmentState = Struct( "FragmentState", @@ -468,7 +473,7 @@ def __repr__(self): #: * module :: :class:`GPUShaderModule ` #: * entryPoint :: str -#: * constants :: Dict[str, float] +#: * constants :: Dict[str, float] = {} #: * buffers :: List[:obj:`structs.VertexBufferLayout `] = [] VertexState = Struct( "VertexState", @@ -501,8 +506,8 @@ def __repr__(self): #: * offset :: int = 0 #: * bytesPerRow :: int #: * rowsPerImage :: int -ImageDataLayout = Struct( - "ImageDataLayout", +TexelCopyBufferLayout = Struct( + "TexelCopyBufferLayout", offset="int", bytes_per_row="int", rows_per_image="int", @@ -512,8 +517,8 @@ def __repr__(self): #: * bytesPerRow :: int #: * rowsPerImage :: int #: * buffer :: :class:`GPUBuffer ` -ImageCopyBuffer = Struct( - "ImageCopyBuffer", +TexelCopyBufferInfo = Struct( + "TexelCopyBufferInfo", offset="int", bytes_per_row="int", rows_per_image="int", @@ -524,19 +529,35 @@ def __repr__(self): #: * mipLevel :: int = 0 #: * origin :: Union[List[int], :obj:`structs.Origin3D `] = {} #: * aspect :: :obj:`enums.TextureAspect ` = "all" -ImageCopyTexture = Struct( - "ImageCopyTexture", +TexelCopyTextureInfo = Struct( + "TexelCopyTextureInfo", texture="GPUTexture", mip_level="int", origin="Union[List[int], structs.Origin3D]", aspect="enums.TextureAspect", ) +#: * texture :: :class:`GPUTexture ` +#: * mipLevel :: int = 0 +#: * origin :: Union[List[int], :obj:`structs.Origin3D `] = {} +#: * aspect :: :obj:`enums.TextureAspect ` = "all" +#: * colorSpace :: str = "srgb" +#: * premultipliedAlpha :: bool = false +CopyExternalImageDestInfo = Struct( + "CopyExternalImageDestInfo", + texture="GPUTexture", + mip_level="int", + origin="Union[List[int], structs.Origin3D]", + aspect="enums.TextureAspect", + color_space="str", + premultiplied_alpha="bool", +) + #: * source :: Union[memoryview, object] #: * origin :: Union[List[int], :obj:`structs.Origin2D `] = {} #: * flipY :: bool = false -ImageCopyExternalImage = Struct( - "ImageCopyExternalImage", +CopyExternalImageSourceInfo = Struct( + "CopyExternalImageSourceInfo", source="Union[memoryview, object]", origin="Union[List[int], structs.Origin2D]", flip_y="bool", diff --git a/wgpu/utils/compute.py b/wgpu/utils/compute.py index 0166b33b..705b1384 100644 --- a/wgpu/utils/compute.py +++ b/wgpu/utils/compute.py @@ -7,7 +7,7 @@ import wgpu.utils -def compute_with_buffers(input_arrays, output_arrays, shader, n=None): +def compute_with_buffers(input_arrays, output_arrays, shader, constants=None, n=None): """Apply the given compute shader to the given input_arrays and return output arrays. Both input and output arrays are represented on the GPU using storage buffer objects. @@ -29,6 +29,7 @@ def compute_with_buffers(input_arrays, output_arrays, shader, n=None): of a memoryview. Note that any buffer that is NOT in the output arrays dict will be considered readonly in the shader. shader (str or bytes): The shader as a string of WGSL code or SpirV bytes. + constants (dict, optional): provide override constants n (int, tuple, optional): The dispatch counts. Can be an int or a 3-tuple of ints to specify (x, y, z). If not given or None, the length of the first output array type is used. @@ -164,10 +165,18 @@ def compute_with_buffers(input_arrays, output_arrays, shader, n=None): ) bind_group = device.create_bind_group(layout=bind_group_layout, entries=bindings) + compute = { + "module": cshader, + "entry_point": "main", + } + + if constants: + compute["constants"] = constants + # Create a pipeline and "run it" compute_pipeline = device.create_compute_pipeline( layout=pipeline_layout, - compute={"module": cshader, "entry_point": "main"}, + compute=compute, ) command_encoder = device.create_command_encoder() compute_pass = command_encoder.begin_compute_pass() diff --git a/wgpu/utils/imgui/__init__.py b/wgpu/utils/imgui/__init__.py index 4138061b..a6819300 100644 --- a/wgpu/utils/imgui/__init__.py +++ b/wgpu/utils/imgui/__init__.py @@ -1,2 +1,3 @@ from .imgui_backend import ImguiWgpuBackend # noqa: F401 from .imgui_renderer import ImguiRenderer # noqa: F401 +from .stats import Stats # noqa: F401 diff --git a/wgpu/utils/imgui/imgui_renderer.py b/wgpu/utils/imgui/imgui_renderer.py index 053af617..658a4d11 100644 --- a/wgpu/utils/imgui/imgui_renderer.py +++ b/wgpu/utils/imgui/imgui_renderer.py @@ -70,16 +70,23 @@ def __init__( # Prepare present context self._canvas_context = canvas.get_context("wgpu") - if render_target_format is None: - # todo: not sure if this is the correct format, maybe we should expose it in the public API - render_target_format = self._canvas_context.get_preferred_format( - device.adapter - ) - # if the canvas is not configured, we configure it self. - # todo: maybe we should just raise an error if the canvas is not configured? if self._canvas_context._config is None: + if render_target_format is None: + render_target_format = self._canvas_context.get_preferred_format( + device.adapter + ) self._canvas_context.configure(device=device, format=render_target_format) + else: + config_format = self._canvas_context._config.get("format") + if ( + render_target_format is not None + and config_format != render_target_format + ): + raise ValueError( + "The canvas is already configured with a different format." + ) + render_target_format = config_format self._imgui_context = imgui.create_context() imgui.set_current_context(self._imgui_context) @@ -207,7 +214,7 @@ def _on_key(self, event): event["stop_propagation"] = True def _on_wheel(self, event): - self._backend.io.add_mouse_wheel_event(event["dx"] / 100, event["dy"] / 100) + self._backend.io.add_mouse_wheel_event(event["dx"] / 100, -event["dy"] / 100) if self._backend.io.want_capture_mouse: event["stop_propagation"] = True diff --git a/wgpu/utils/imgui/stats.py b/wgpu/utils/imgui/stats.py new file mode 100644 index 00000000..b3e04915 --- /dev/null +++ b/wgpu/utils/imgui/stats.py @@ -0,0 +1,180 @@ +import time + +from wgpu.utils.imgui import ImguiRenderer +from imgui_bundle import imgui +import numpy as np + + +class Stats: + """A Stats helper which displays performance statistics such + as FPS and draw time on the screen. + + Parameters + ---------- + device : wgpu.Device + The device to use for rendering the stats. + canvas : wgpu.gui.WgpuCanvasBase + The canvas to render the stats on. + foreground : tuple(4) + The color of the text. + background : tuple(4) + The color of the background. + align : str + The alignment of the stats window, either "left" or "right". Default is "left". + auto_render : bool + If True, the render method will be called automatically. Default is True. + + """ + + def __init__( + self, + device, + canvas, + *, + foreground=(0, 1, 0, 1), + background=(0, 0.2, 0, 0.5), + align="left", + auto_render=True, + ): + self._foreground = foreground + self._background = background + self._align = align + + self._renderer = ImguiRenderer(device, canvas) + + self._renderer.set_gui(self._draw_imgui) + + canvas.add_event_handler(self._on_mouse, "pointer_down", order=-200) + + # flag used to skip the first frame + # which typically has all the CPU->GPU transfer and + # shader compilation overhead + self._init = False + + # performance trackers + self._tmin = 1e10 + self._tmax = 0 + self._tbegin = None + self._tprev = self._tbegin + self._frames = 0 + self._fmin = 1e10 + self._fmax = 0 + # Sentinel value of None indicates that the fps has never been computed + self._fps = None + + self._fps_samples = np.zeros(100, dtype=np.float32) + self._ms_samples = np.zeros(100, dtype=np.float32) + + self._mode = 0 + self._auto_render = auto_render + + def _draw_imgui(self): + imgui.new_frame() + + imgui.set_next_window_size((130, 0), imgui.Cond_.always) + if self._align == "right": + pos = imgui.get_io().display_size.x - 130 + else: + pos = 0 + + imgui.set_next_window_pos((pos, 0), imgui.Cond_.always) + + imgui.push_style_color(imgui.Col_.window_bg, self._background) + + imgui.begin( + "stats", + True, + flags=imgui.WindowFlags_.no_move + | imgui.WindowFlags_.no_resize + | imgui.WindowFlags_.no_collapse + | imgui.WindowFlags_.no_scrollbar + | imgui.WindowFlags_.no_title_bar, + ) + + imgui.push_style_color(imgui.Col_.text, self._foreground) + if self._mode == 0: + if self._fps is not None: + ms = self._ms_samples[-1] + text = f"{int(ms)} ms ({self._tmin}-{self._tmax})" + text += f"\n{self._fps} fps ({self._fmin}-{self._fmax})" + imgui.text(text) + + elif self._mode == 1: + imgui.text(f"{self._fps} fps({self._fmin}-{self._fmax})") + imgui.plot_histogram("##", self._fps_samples, graph_size=(115, 25)) + elif self._mode == 2: + ms = self._ms_samples[-1] + imgui.text(f"{int(ms)} ms({self._tmin}-{self._tmax})") + imgui.plot_lines("##", self._ms_samples, graph_size=(115, 25)) + + imgui.pop_style_color() + + imgui.end() + + imgui.pop_style_color() + + imgui.end_frame() + imgui.render() + return imgui.get_draw_data() + + def _on_mouse(self, event): + if self._renderer.backend.io.want_capture_mouse: + self._mode = (self._mode + 1) % 3 + event["stop_propagation"] = True + + @property + def auto_render(self): + """If True, the render method will be called automatically. Default is True.""" + return self._auto_render + + @auto_render.setter + def auto_render(self, value): + self._auto_render = bool(value) + + def start(self): + if not self._init: + return + + self._tbegin = time.perf_counter_ns() + if self._tprev is None: + self._tprev = self._tbegin + + def stop(self): + if not self._init: + self._init = True + return + + t = time.perf_counter_ns() + self._frames += 1 + + delta = round((t - self._tbegin) / 1_000_000) + self._tmin = min(self._tmin, delta) + self._tmax = max(self._tmax, delta) + + if t >= self._tprev + 1_000_000_000: + # update FPS counter whenever a second has passed + fps = round(self._frames / ((t - self._tprev) / 1_000_000_000)) + self._tprev = t + self._frames = 0 + self._fmin = min(self._fmin, fps) + self._fmax = max(self._fmax, fps) + self._fps = fps + + # update fps samples, remove last element + self._fps_samples = np.roll(self._fps_samples, -1) + self._fps_samples[-1] = fps + + self._ms_samples = np.roll(self._ms_samples, -1) + self._ms_samples[-1] = delta + + if self._auto_render: + self.render() + + def render(self): + self._renderer.render() + + def __enter__(self): + self.start() + + def __exit__(self, *exc): + self.stop()