Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
77 changes: 77 additions & 0 deletions tests/test_wgpu_native_basics.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,5 +481,82 @@ def test_limits_are_not_legal():
assert not are_limits_wgpu_legal({"max-bind-group": 8})


def test_bind_group_resources():
# make sure every resource type can be created in a bind group.
device = wgpu.utils.get_default_device()

sampler = device.create_sampler()
texture1 = device.create_texture(
label="texture1",
size=(8, 8, 1),
format=wgpu.TextureFormat.rgba8unorm,
usage=wgpu.TextureUsage.TEXTURE_BINDING | wgpu.TextureUsage.COPY_DST,
)
texture2 = device.create_texture(
label="texture2",
size=(8, 8, 1),
format=wgpu.TextureFormat.rgba8unorm,
usage=wgpu.TextureUsage.TEXTURE_BINDING | wgpu.TextureUsage.COPY_DST,
)
texture_view = texture2.create_view()

buffer = device.create_buffer(
size=256,
usage=wgpu.BufferUsage.UNIFORM,
)

entires = [
wgpu.structs.BindGroupEntry(binding=0, resource=sampler),
wgpu.structs.BindGroupEntry(binding=1, resource=texture1),
wgpu.structs.BindGroupEntry(binding=2, resource=texture_view),
wgpu.structs.BindGroupEntry(
binding=3,
resource=buffer,
),
wgpu.structs.BindGroupEntry(
binding=4,
resource=wgpu.structs.BufferBinding(
buffer=buffer,
),
),
# maybe external texture one day
]

# maybe we should write a bit of compute shader so we can use auto layout mode instead.
layout_entries = [
wgpu.BindGroupLayoutEntry(
binding=0,
visibility=wgpu.ShaderStage.COMPUTE,
sampler=wgpu.structs.SamplerBindingLayout(),
),
wgpu.BindGroupLayoutEntry(
binding=1,
visibility=wgpu.ShaderStage.COMPUTE,
texture=wgpu.structs.TextureBindingLayout(),
),
wgpu.BindGroupLayoutEntry(
binding=2,
visibility=wgpu.ShaderStage.COMPUTE,
texture=wgpu.structs.TextureBindingLayout(),
),
wgpu.BindGroupLayoutEntry(
binding=3,
visibility=wgpu.ShaderStage.COMPUTE,
buffer=wgpu.structs.BufferBindingLayout(),
),
wgpu.BindGroupLayoutEntry(
binding=4,
visibility=wgpu.ShaderStage.COMPUTE,
buffer=wgpu.structs.BufferBindingLayout(),
),
]

layout = device.create_bind_group_layout(entries=layout_entries)

bind_group = device.create_bind_group(layout=layout, entries=entires)

assert bind_group


if __name__ == "__main__":
run_tests(globals())
2 changes: 1 addition & 1 deletion wgpu/_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,7 @@ def create_bind_group(
layout (GPUBindGroupLayout): The layout (abstract representation)
for this bind group.
entries (list): A list of `structs.BindGroupEntry`s. The ``resource`` field
is either `GPUSampler`, `GPUTextureView` or `structs.BufferBinding`.
is either `GPUBuffer`, `GPUSampler`, `GPUTexture`, `GPUTextureView` or `structs.BufferBinding`.

Example entry dicts:

Expand Down
10 changes: 8 additions & 2 deletions wgpu/backends/wgpu_native/_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1699,9 +1699,10 @@ def create_bind_group(
entries: Sequence[structs.BindGroupEntryStruct],
) -> GPUBindGroup:
c_entries_list = []
_keep_alive = []
for entry in entries:
check_struct("BindGroupEntry", entry)
# The resource can be a buffer, sampler, texture view, or buffer descriptor
# The resource can be a buffer, sampler, texture, texture view, or buffer descriptor
resource = entry["resource"]
if isinstance(resource, GPUBuffer):
# H: nextInChain: WGPUChainedStruct *, binding: int, buffer: WGPUBuffer, offset: int, size: int, sampler: WGPUSampler, textureView: WGPUTextureView
Expand All @@ -1727,7 +1728,11 @@ def create_bind_group(
sampler=resource._internal,
textureView=ffi.NULL,
)
elif isinstance(resource, GPUTextureView):
elif isinstance(resource, (GPUTextureView, GPUTexture)):
if type(resource) is GPUTexture:
# also see https://github.com/pygfx/wgpu-py/issues/825
resource = resource.create_view()
_keep_alive.append(resource)
# H: nextInChain: WGPUChainedStruct *, binding: int, buffer: WGPUBuffer, offset: int, size: int, sampler: WGPUSampler, textureView: WGPUTextureView
c_entry = new_struct(
"WGPUBindGroupEntry",
Expand Down Expand Up @@ -1767,6 +1772,7 @@ def create_bind_group(

# H: WGPUBindGroup f(WGPUDevice device, WGPUBindGroupDescriptor const * descriptor)
id = libf.wgpuDeviceCreateBindGroup(self._internal, struct)
del _keep_alive
return GPUBindGroup(label, id, self)

def create_pipeline_layout(
Expand Down
Loading