Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multi_draw_indirect_counter #594

Closed
wants to merge 55 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
ee28841
multi_draw_indirect_counter
fyellin Sep 20, 2024
53cccea
Add documentation.
fyellin Sep 20, 2024
021241e
Bring back the bug. I accidentally indented a line a code and it ende…
fyellin Sep 20, 2024
2bd5408
Update to show everything reported by bug report. Note that "indexed…
fyellin Sep 20, 2024
7559673
Merge branch 'main' into mdi_count
fyellin Sep 22, 2024
62b1cff
Merge branch 'main' into mdi_count
fyellin Sep 24, 2024
b6565e7
Add blank line where needed.
fyellin Sep 24, 2024
f5f0b60
Update backends.rst
fyellin Sep 25, 2024
55603b8
Merge branch 'main' into mdi_count
fyellin Sep 26, 2024
611ed30
Merge branch 'main' into mdi_count
fyellin Sep 29, 2024
7f2364c
Merge branch 'main' into mdi_count
fyellin Oct 1, 2024
7f3cf38
Merge remote-tracking branch 'fyellin/mdi_count' into mdi_count
fyellin Oct 1, 2024
a91ca7e
Merge branch 'main' into mdi_count
fyellin Oct 1, 2024
6ba3a21
Merge branch 'main' into mdi_count
fyellin Oct 2, 2024
cde77ea
Merge branch 'main' into mdi_count
fyellin Oct 3, 2024
992b183
Merge branch 'main' into mdi_count
fyellin Oct 7, 2024
7713ae1
Merge branch 'main' into mdi_count
fyellin Oct 8, 2024
473c8a1
Merge branch 'main' into mdi_count
fyellin Oct 8, 2024
c9455da
Merge branch 'main' into mdi_count
fyellin Oct 17, 2024
28daa0b
Merge branch 'main' into mdi_count
fyellin Oct 22, 2024
30dde9b
Merge tag 'v0.19.0' into mdi_count
fyellin Nov 4, 2024
8c14145
Merge branch 'main' into mdi_count
fyellin Nov 5, 2024
2843620
Merge branch 'main' into mdi_count
fyellin Nov 8, 2024
719d32a
Fix codegen
fyellin Nov 8, 2024
a464d6b
Merge branch 'main' into mdi_count
fyellin Nov 23, 2024
f32a6d7
Merge branch 'main' into mdi_count
fyellin Dec 11, 2024
b8e1a78
Update codegen
fyellin Dec 11, 2024
dad4343
Bring sleep back to WgpuAwaitable. Slowly back off on the amount of …
fyellin Dec 28, 2024
7a9cef4
Stop setting AA_EnableHighDpiScaling since Qt Says it is not needed (…
hmaarrfk Dec 29, 2024
c0b4efc
remove unneeded pytest-anyio package (#658)
hmaarrfk Dec 30, 2024
ae7efc5
Actually run the tests instead of fully skipping them (#659)
hmaarrfk Dec 30, 2024
8a0b267
Improve state of the art for screenshot testing (#555)
hmaarrfk Jan 3, 2025
0cb6a48
use default lavapipe for screenshot (#660)
Vipitis Jan 16, 2025
af0cd04
fix one typo in _helpers.py (#661)
hmaarrfk Jan 16, 2025
7813bd6
Fix typo (#662)
patrini32 Jan 16, 2025
3a495bd
Improve error handling (#667)
almarklein Jan 27, 2025
fbec37c
Improve docs regarding drives on Linux (#668)
almarklein Jan 27, 2025
11bb195
Add patches for conda compatibility (#666)
hmaarrfk Jan 27, 2025
63d70c0
Allow disabling downloading lib when creating wheel (#669)
almarklein Jan 31, 2025
9fd7664
Add Imgui based Stats component (#670)
panxinmiao Feb 15, 2025
7183e50
examples/imgui_cmap_picker.py - update for imgui bundle 1.6.2 (#671)
pthom Feb 20, 2025
836972e
Auto render Stats (#674)
panxinmiao Feb 22, 2025
0feda8e
add simple matmul example (#677)
kushalkolar Feb 27, 2025
8b61daa
pass constants to compute helper (#676)
kushalkolar Feb 28, 2025
3a61de5
fix imgui scroll (#678)
panxinmiao Mar 2, 2025
1f86cd4
Improve performance for 'bitmap' render method (#680)
almarklein Mar 12, 2025
4fb7d7b
Bump version (#681)
almarklein Mar 14, 2025
f20ec99
Release notes (#682)
almarklein Mar 14, 2025
7fb1c53
update to wgpu-native 24.0.0.2 (#673)
Vipitis Mar 17, 2025
c55e848
Update to latest IDL (#684)
almarklein Mar 17, 2025
499b701
Bump version (#685)
almarklein Mar 17, 2025
266f496
fix newlines (#686)
Vipitis Mar 17, 2025
c37b28a
Merge branch 'mdi_count'
fyellin Mar 18, 2025
9322686
Merge
fyellin Mar 18, 2025
8974472
Remove no-longer-needed-comment
fyellin Mar 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/screenshots.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
51 changes: 51 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
7 changes: 6 additions & 1 deletion codegen/apipatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 7 additions & 1 deletion codegen/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
62 changes: 51 additions & 11 deletions codegen/hparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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.
Expand Down Expand Up @@ -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)
1 change: 1 addition & 0 deletions codegen/idlparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ def resolve_type(self, typename):
"AllowSharedBufferSource": "memoryview",
"GPUPipelineConstantValue": "float",
"GPUExternalTexture": "object",
"undefined": "None",
}
name = pythonmap.get(name, name)

Expand Down
8 changes: 4 additions & 4 deletions codegen/tests/test_codegen_rspatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand All @@ -72,15 +72,15 @@ 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

# 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

Expand Down
81 changes: 50 additions & 31 deletions codegen/wgpu_native_patcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -290,42 +291,47 @@ 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
if "_new_struct" in line:
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."""

Expand Down Expand Up @@ -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 = []
Expand Down
Loading
Loading