Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
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
1 change: 1 addition & 0 deletions codegen/wgpu_native_patcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ def write_mappings():
("NativeFeature", True),
("PipelineStatisticName", True),
("Dx12Compiler", False),
("PolygonMode", False),
):
pylines.append(f' "{name}":' + " {")
for key, val in hp.enums[name].items():
Expand Down
6 changes: 4 additions & 2 deletions docs/backends.rst
Original file line number Diff line number Diff line change
Expand Up @@ -317,18 +317,20 @@ given in a different order in the list.

:param encoder: The ComputePassEncoder or RenderPassEncoder.

.. py:function:: wgpu.backends.wgpu_native.set_instance_extras(backends, flags, dx12_compiler, gles3_minor_version, fence_behavior, dxil_path, dxc_path, dxc_max_shader_model)
.. py:function:: wgpu.backends.wgpu_native.set_instance_extras(backends, flags, dx12_compiler, gles3_minor_version, fence_behavior, dxc_path, dxc_max_shader_model, budget_for_device_creation, budget_for_device_loss)

Sets the global instance with extras. Needs to be called before instance is created (in enumerate_adapters or request_adapter).
Most of these options are for specific backends, and might not create an instance or crash when used in the wrong combinations.

:param backends: bitflags as list[str], which backends to enable on the instance level. Defaults to ``["All"]``. Can be any combination of ``["Vulkan", "GL", "Metal", "DX12", "BrowserWebGPU"]`` or the premade combinations ``["All", "Primary", "secondary"]``. Note that your device needs to support these backends, for detailed information see https://docs.rs/wgpu/latest/wgpu/struct.Backends.html
:param flags: bitflags as list[str], debug flags for the compiler. Defaults to ``["Default"]``, can be any combination of ``["Debug", "Validation", "DiscardHalLabels"]``.
:param dx12_compiler: enum/str, either "Fxc", "Dxc" or "Undefined". Defaults to "Fxc" same as "Undefined". Dxc requires additional library files.
:param gles3_minor_version: enum/int 0, 1 or 2. Defaults to "Atomic" (handled by driver).
:param fence_behavior: enum/int, "Normal" or "AutoFinish", Default to "Normal".
:param dxil_path: str, path to dxil.dll, defaults to ``None``. None looks in the resource directory.
:param dxc_path: str, path to dxcompiler.dll, defaults to ``None``. None looks in the resource directory.
:param dxc_max_shader_model: float between 6.0 and 6.7, Maximum shader model the given dll supports. Defaults to 6.5.
:param budget_for_device_creation: Optional[int], between 0 and 100, to specify memory budget threshold for when creating resources (buffer, textures...) will fail. Defaults to None.
:param budget_for_device_loss: Optional[int], between 0 and 100, to specify memory budget threshold when the device will be lost. Defaults to None.

Use like the following before the instance is created, which happens during request_adapter or enumerate_adapters.

Expand Down
5 changes: 4 additions & 1 deletion examples/extras_dxc.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
"DX12"
], # using the env var `WGPU_BACKEND_TYPE` happens later during request_device, so you can only select backends that are requested for the instance
dx12_compiler="Dxc", # request the Dxc compiler to be used
# dxil_path and dxc_path can be set for a custom Dxc location
# dxc_path can be set for a custom Dxc location
dxc_max_shader_model=6.7,
# by setting these limits to percentages 0..100 you will get a Validation Error, should too much memory be requested.
budget_for_device_creation=99,
budget_for_device_loss=97,
)


Expand Down
8 changes: 3 additions & 5 deletions tests/test_wgpu_native_basics.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,8 +414,8 @@ def are_features_wgpu_legal(features):
def test_features_are_legal():
# A standard feature. Probably exists
assert are_features_wgpu_legal(["shader-f16"])
# Two common extension features
assert are_features_wgpu_legal(["multi-draw-indirect", "vertex-writable-storage"])
# A common extension feature
assert are_features_wgpu_legal(["vertex-writable-storage"])
# An uncommon extension feature. Certainly not on a mac.
assert are_features_wgpu_legal(["pipeline-statistics-query"])
assert are_features_wgpu_legal(
Expand All @@ -429,9 +429,7 @@ def test_features_are_legal():

def test_features_are_illegal():
# writable is misspelled
assert not are_features_wgpu_legal(
["multi-draw-indirect", "vertex-writeable-storage"]
)
assert not are_features_wgpu_legal(["vertex-writeable-storage"])
assert not are_features_wgpu_legal(["my-made-up-feature"])


Expand Down
29 changes: 9 additions & 20 deletions tests/test_wgpu_native_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from testutils import run_tests
from pytest import raises


dedent = lambda s: s.replace("\n ", "\n").strip()


Expand Down Expand Up @@ -36,9 +35,6 @@ def test_parse_shader_error1(caplog):
9 │ out.invalid_attr = vec4<f32>(0.0, 0.0, 1.0);
│ ^^^^^^^^^^^^ invalid accessor


invalid field accessor `invalid_attr`
"""

code = dedent(code)
Expand All @@ -47,6 +43,7 @@ def test_parse_shader_error1(caplog):
device.create_shader_module(code=code)

error = err.value.message
error = error.rstrip("\n")
assert error == expected, f"Expected:\n\n{expected}"


Expand All @@ -72,9 +69,6 @@ def test_parse_shader_error2(caplog):
2 │ @location(0) texcoord : vec2<f32>;
│ ^ expected `,`


expected `,`, found ";"
"""

code = dedent(code)
Expand All @@ -83,6 +77,7 @@ def test_parse_shader_error2(caplog):
device.create_shader_module(code=code)

error = err.value.message
error = error.rstrip("\n")
assert error == expected, f"Expected:\n\n{expected}"


Expand All @@ -108,9 +103,6 @@ def test_parse_shader_error3(caplog):
3 │ @builtin(position) position: vec4<f3>,
│ ^^ unknown type


unknown type: `f3`
"""

code = dedent(code)
Expand All @@ -119,6 +111,7 @@ def test_parse_shader_error3(caplog):
device.create_shader_module(code=code)

error = err.value.message
error = error.rstrip("\n")
assert error == expected, f"Expected:\n\n{expected}"


Expand All @@ -140,9 +133,6 @@ def test_parse_shader_error4(caplog):
In wgpuDeviceCreateShaderModule

Shader '' parsing error: Index 4 is out of bounds for expression [10]


Index 4 is out of bounds for expression [10]
"""

code = dedent(code)
Expand All @@ -151,6 +141,7 @@ def test_parse_shader_error4(caplog):
device.create_shader_module(code=code)

error = err.value.message
error = error.rstrip("\n") # seems to have tailing newlines sometimes?
assert error == expected, f"Expected:\n\n{expected}"


Expand Down Expand Up @@ -191,9 +182,8 @@ def test_validate_shader_error1(caplog):
= 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] (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 } })
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 } })
"""

code = dedent(code)
Expand Down Expand Up @@ -227,7 +217,7 @@ def test_validate_shader_error2(caplog):
}
"""

expected1 = """Returning Some(Vector { size: Tri, scalar: Scalar { kind: Float, width: 4 } }) where Some(Vector { size: Quad, scalar: Scalar { kind: Float, width: 4 } }) is expected"""
expected1 = """Returning Some(Handle([3])) where Some([0]) is expected"""
expected2 = """
Validation Error

Expand All @@ -240,11 +230,10 @@ def test_validate_shader_error2(caplog):
9 │ return vec3<f32>(1.0, 0.0, 1.0);
│ ^^^^^^^^^^^^^^^^^^^^^^^^ naga::ir::Expression [8]
= The `return` value Some([8]) does not match the function return value
= The `return` expression Some([8]) does not match the declared return type Some([0])


Entry point fs_main at Vertex is invalid
The `return` value Some([8]) does not match the function return value
The `return` expression Some([8]) does not match the declared return type Some([0])
"""

code = dedent(code)
Expand Down
8 changes: 1 addition & 7 deletions tests/test_wgpu_vertex_instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@

class Runner:
REQUIRED_FEATURES = ["indirect-first-instance"]
OPTIONAL_FEATURES = ["multi-draw-indirect", "multi-draw-indirect-count"]
OPTIONAL_FEATURES = ["multi-draw-indirect-count"]

@classmethod
def is_usable(cls):
Expand Down Expand Up @@ -263,9 +263,6 @@ def draw(encoder):


def test_multi_draw_indirect(runner):
if "multi-draw-indirect" not in runner.device.features:
pytest.skip("Must have 'multi-draw-indirect' to run")

def draw(encoder):
multi_draw_indirect(encoder, runner.draw_data_buffer, offset=8, count=2)

Expand Down Expand Up @@ -329,9 +326,6 @@ def draw(encoder):


def test_multi_draw_indexed_indirect(runner):
if "multi-draw-indirect" not in runner.device.features:
pytest.skip("Must have 'multi-draw-indirect' to run")

def draw(encoder):
multi_draw_indexed_indirect(
encoder, runner.draw_data_buffer_indexed, offset=8, count=2
Expand Down
23 changes: 18 additions & 5 deletions tests_mem/test_destroy.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,27 @@ def test_destroy_device(n):
for i in range(n):
d = adapter.request_device_sync()
d.destroy()
# NOTE: destroy is not yet implemented in wgpu-native - this does not actually do anything yet
# d.destroy() # fine to call multiple times

# Uncomment the following lines to see. These are commented because it makes wgpu-core create a buffer.
# error = None
# try:
# d.create_buffer(size=128, usage=wgpu.BufferUsage.UNIFORM)
# except wgpu.GPUValidationError as err:
# error = err
# assert error and "device is lost" in error.message.lower()

yield d


@create_and_release
def test_destroy_query_set(n):
yield {}
yield {
"expected_counts_after_create": {"QuerySet": (n, 0)},
}
for i in range(n):
qs = DEVICE.create_query_set(type=wgpu.QueryType.occlusion, count=2)
qs.destroy()
# NOTE: destroy is not yet implemented in wgpu-native - this does not actually do anything yet
yield qs


Expand All @@ -56,11 +66,12 @@ def test_destroy_buffer(n):
# can still be queries from wgpu-native, but it cannot be used.

# Uncomment the following lines to see. These are commented because it makes wgpu-core create a command-buffer.
# error = None
# try:
# b.map_sync("READ")
# except wgpu.GPUValidationError as err:
# error = err
# assert "destroyed" in error.message.lower()
# assert error and "destroyed" in error.message.lower()

yield b

Expand All @@ -77,11 +88,13 @@ def test_destroy_texture(n):
t.destroy()

# Uncomment the following lines to see. These are commented because the views are created at the native side, but we never store them, but we also don't release them.
# error = None
# try:
# t.create_view()
# except wgpu.GPUValidationError as err:
# error = err
# assert "destroyed" in error.message.lower()
# assert error and "destroyed" in error.message.lower()

yield t


Expand Down
2 changes: 1 addition & 1 deletion tests_mem/test_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def test_release_command_encoder(n):
yield {
"expected_counts_after_create": {
"CommandEncoder": (n, 0),
"CommandBuffer": (0, n),
# "CommandBuffer": (0, n),
},
}

Expand Down
3 changes: 0 additions & 3 deletions tools/download_dxc.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,8 @@ def main(version=None):
print(f"Downloading {url}")
download_file(url, zip_filename)
compiler_file = "dxcompiler.dll"
signing_file = "dxil.dll" # in v26 this won't be needed anymore
print(f"Extracting {compiler_file} to {RESOURCE_DIR}")
extract_file(zip_filename, compiler_file, RESOURCE_DIR)
print(f"Extracting {signing_file} to {RESOURCE_DIR}")
extract_file(zip_filename, signing_file, RESOURCE_DIR)

# cleanup of tempfile?
# os.remove(zip_filename)
Expand Down
8 changes: 5 additions & 3 deletions wgpu/_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1146,12 +1146,14 @@ def create_render_pipeline(
vertex (structs.VertexState): Describes the vertex shader entry point of the
pipeline and its input buffer layouts.
primitive (structs.PrimitiveState): Describes the primitive-related properties
of the pipeline. If `strip_index_format` is present (which means the
of the pipeline. If ``strip_index_format`` is present (which means the
primitive topology is a strip), and the drawCall is indexed, the
vertex index list is split into sub-lists using the maximum value of this
index format as a separator. Example: a list with values
`[1, 2, 65535, 4, 5, 6]` of type "uint16" will be split in sub-lists
`[1, 2]` and `[4, 5, 6]`.
``[1, 2, 65535, 4, 5, 6]`` of type "uint16" will be split in sub-lists
``[1, 2]`` and ``[4, 5, 6]``.
If the native-only features "polygon-mode-line" or "polygon-mode-point" are requested, an additional field in the primitive state
``polygon_mode`` can be set to "line" or "point" respectively. However this requires the use of a dict and not `structs.PrimitiveState`.
depth_stencil (structs.DepthStencilState): Describes the optional depth-stencil
properties, including the testing, operations, and bias. Optional.
multisample (structs.MultisampleState): Describes the multi-sampling properties of the pipeline.
Expand Down
4 changes: 2 additions & 2 deletions wgpu/backends/wgpu_native/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@


# The wgpu-native version that we target/expect
__version__ = "25.0.2.2"
__commit_sha__ = "a2f5109b0da3c87d356a6a876f5b203c6a68924a"
__version__ = "27.0.2.0"
__commit_sha__ = "74f8c24c903b6352d09f1928c56962ce06f77a4d"
version_info = tuple(map(int, __version__.split("."))) # noqa: RUF048
_check_expected_version(version_info) # produces a warning on mismatch

Expand Down
Loading
Loading