diff --git a/wgpu/backends/wgpu_native/_api.py b/wgpu/backends/wgpu_native/_api.py index d082fa3f..a12ab152 100644 --- a/wgpu/backends/wgpu_native/_api.py +++ b/wgpu/backends/wgpu_native/_api.py @@ -812,7 +812,30 @@ def _release(self): class GPUObjectBase(classes.GPUObjectBase): - pass + def _release(self): + if self._internal is not None and libf is not None: + self._internal, internal = None, self._internal + # H: void wgpuDeviceRelease(WGPUDevice device) + # H: void wgpuBufferRelease(WGPUBuffer buffer) + # H: void wgpuTextureRelease(WGPUTexture texture) + # H: void wgpuTextureViewRelease(WGPUTextureView textureView) + # H: void wgpuSamplerRelease(WGPUSampler sampler) + # H: void wgpuBindGroupLayoutRelease(WGPUBindGroupLayout bindGroupLayout) + # H: void wgpuBindGroupRelease(WGPUBindGroup bindGroup) + # H: void wgpuPipelineLayoutRelease(WGPUPipelineLayout pipelineLayout) + # H: void wgpuShaderModuleRelease(WGPUShaderModule shaderModule) + # H: void wgpuComputePipelineRelease(WGPUComputePipeline computePipeline) + # H: void wgpuRenderPipelineRelease(WGPURenderPipeline renderPipeline) + # H: void wgpuCommandBufferRelease(WGPUCommandBuffer commandBuffer) + # H: void wgpuCommandEncoderRelease(WGPUCommandEncoder commandEncoder) + # H: void wgpuComputePassEncoderRelease(WGPUComputePassEncoder computePassEncoder) + # H: void wgpuRenderPassEncoderRelease(WGPURenderPassEncoder renderPassEncoder) + # H: void wgpuRenderBundleEncoderRelease(WGPURenderBundleEncoder renderBundleEncoder) + # H: void wgpuQueueRelease(WGPUQueue queue) + # H: void wgpuRenderBundleRelease(WGPURenderBundle renderBundle) + # H: void wgpuQuerySetRelease(WGPUQuerySet querySet) + function = type(self)._release_function + function(internal) class GPUAdapterInfo(classes.GPUAdapterInfo): @@ -1042,6 +1065,9 @@ def _release(self): class GPUDevice(classes.GPUDevice, GPUObjectBase): + # GPUObjectBaseMixin + _release_function = libf.wgpuDeviceRelease + def __init__(self, label, internal, adapter, features, limits, queue): super().__init__(label, internal, adapter, features, limits, queue) @@ -1856,15 +1882,15 @@ def destroy(self): def _release(self): if self._queue is not None: - self._queue._release() - self._queue = None - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPUDevice device) - libf.wgpuDeviceRelease(internal) + queue, self._queue = self._queue, None + queue._release() + super()._release() class GPUBuffer(classes.GPUBuffer, GPUObjectBase): + # GPUObjectBaseMixin + _release_function = libf.wgpuBufferRelease + def __init__(self, label, internal, device, size, usage, map_state): super().__init__(label, internal, device, size, usage, map_state) @@ -2086,13 +2112,13 @@ def destroy(self): def _release(self): self._release_memoryviews() - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPUBuffer buffer) - libf.wgpuBufferRelease(internal) + super()._release() class GPUTexture(classes.GPUTexture, GPUObjectBase): + # GPUObjectBaseMixin + _release_function = libf.wgpuTextureRelease + def create_view( self, *, @@ -2150,54 +2176,36 @@ def destroy(self): # H: void f(WGPUTexture texture) libf.wgpuTextureDestroy(internal) - def _release(self): - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPUTexture texture) - libf.wgpuTextureRelease(internal) - class GPUTextureView(classes.GPUTextureView, GPUObjectBase): - def _release(self): - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPUTextureView textureView) - libf.wgpuTextureViewRelease(internal) + # GPUObjectBaseMixin + _release_function = libf.wgpuTextureViewRelease class GPUSampler(classes.GPUSampler, GPUObjectBase): - def _release(self): - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPUSampler sampler) - libf.wgpuSamplerRelease(internal) + # GPUObjectBaseMixin + _release_function = libf.wgpuSamplerRelease class GPUBindGroupLayout(classes.GPUBindGroupLayout, GPUObjectBase): - def _release(self): - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPUBindGroupLayout bindGroupLayout) - libf.wgpuBindGroupLayoutRelease(internal) + # GPUObjectBaseMixin + _release_function = libf.wgpuBindGroupLayoutRelease class GPUBindGroup(classes.GPUBindGroup, GPUObjectBase): - def _release(self): - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPUBindGroup bindGroup) - libf.wgpuBindGroupRelease(internal) + # GPUObjectBaseMixin + _release_function = libf.wgpuBindGroupRelease class GPUPipelineLayout(classes.GPUPipelineLayout, GPUObjectBase): - def _release(self): - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPUPipelineLayout pipelineLayout) - libf.wgpuPipelineLayoutRelease(internal) + # GPUObjectBaseMixin + _release_function = libf.wgpuPipelineLayoutRelease class GPUShaderModule(classes.GPUShaderModule, GPUObjectBase): + # GPUObjectBaseMixin + _release_function = libf.wgpuShaderModuleRelease + def get_compilation_info(self): # Here's a little setup to implement this method. Unfortunately, # this is not yet implemented in wgpu-native. Another problem @@ -2229,12 +2237,6 @@ def get_compilation_info(self): return [] - def _release(self): - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPUShaderModule shaderModule) - libf.wgpuShaderModuleRelease(internal) - class GPUPipelineBase(classes.GPUPipelineBase): def get_bind_group_layout(self, index): @@ -2251,30 +2253,18 @@ def get_bind_group_layout(self, index): class GPUComputePipeline(classes.GPUComputePipeline, GPUPipelineBase, GPUObjectBase): - def _release(self): - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPUComputePipeline computePipeline) - libf.wgpuComputePipelineRelease(internal) + # GPUObjectBaseMixin + _release_function = libf.wgpuComputePipelineRelease class GPURenderPipeline(classes.GPURenderPipeline, GPUPipelineBase, GPUObjectBase): - def _release(self): - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPURenderPipeline renderPipeline) - libf.wgpuRenderPipelineRelease(internal) + # GPUObjectBaseMixin + _release_function = libf.wgpuRenderPipelineRelease class GPUCommandBuffer(classes.GPUCommandBuffer, GPUObjectBase): - def _release(self): - # Note that command buffers get destroyed when they are submitted. - # In earlier versions we had to take this into account by setting - # _internal to None. That seems not necessary anymore. - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPUCommandBuffer commandBuffer) - libf.wgpuCommandBufferRelease(internal) + # GPUObjectBaseMixin + _release_function = libf.wgpuCommandBufferRelease class GPUCommandsMixin(classes.GPUCommandsMixin): @@ -2430,6 +2420,9 @@ class GPUCommandEncoder( _pop_debug_group_function = libf.wgpuCommandEncoderPopDebugGroup _insert_debug_marker_function = libf.wgpuCommandEncoderInsertDebugMarker + # GPUObjectBaseMixin + _release_function = libf.wgpuCommandEncoderRelease + def begin_compute_pass( self, *, label="", timestamp_writes: "structs.ComputePassTimestampWrites" = None ): @@ -2822,14 +2815,6 @@ def resolve_query_set( int(destination_offset), ) - def _release(self): - # Note that the native object gets destroyed on finish. - # Also see GPUCommandBuffer._release() - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPUCommandEncoder commandEncoder) - libf.wgpuCommandEncoderRelease(internal) - class GPUComputePassEncoder( classes.GPUComputePassEncoder, @@ -2847,6 +2832,9 @@ class GPUComputePassEncoder( # GPUBindingCommandsMixin _set_bind_group_function = libf.wgpuComputePassEncoderSetBindGroup + # GPUObjectBaseMixin + _release_function = libf.wgpuComputePassEncoderRelease + _ended = False def set_pipeline(self, pipeline): @@ -2874,14 +2862,9 @@ def end(self): libf.wgpuComputePassEncoderEnd(self._internal) self._ended = True # Need to release, see https://github.com/gfx-rs/wgpu-native/issues/412 + # As of wgpu-native v22.1.0.5, this bug is still present. self._release() - def _release(self): - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPUComputePassEncoder computePassEncoder) - libf.wgpuComputePassEncoderRelease(internal) - class GPURenderPassEncoder( classes.GPURenderPassEncoder, @@ -2908,6 +2891,9 @@ class GPURenderPassEncoder( _draw_indexed_function = libf.wgpuRenderPassEncoderDrawIndexed _draw_indexed_indirect_function = libf.wgpuRenderPassEncoderDrawIndexedIndirect + # GPUObjectBaseMixin + _release_function = libf.wgpuRenderPassEncoderRelease + _ended = False def set_viewport(self, x, y, width, height, min_depth, max_depth): @@ -2950,6 +2936,7 @@ def end(self): libf.wgpuRenderPassEncoderEnd(self._internal) self._ended = True # Need to release, see https://github.com/gfx-rs/wgpu-native/issues/412 + # As of wgpu-native v22.1.0.5, this bug is still present. self._release() def execute_bundles(self, bundles): @@ -2997,12 +2984,6 @@ def _set_push_constants(self, visibility, offset, size_in_bytes, data, data_offs self._internal, int(visibility), offset, size, c_data + data_offset ) - def _release(self): - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPURenderPassEncoder renderPassEncoder) - libf.wgpuRenderPassEncoderRelease(internal) - class GPURenderBundleEncoder( classes.GPURenderBundleEncoder, @@ -3029,6 +3010,9 @@ class GPURenderBundleEncoder( _draw_indexed_function = libf.wgpuRenderBundleEncoderDrawIndexed _draw_indexed_indirect_function = libf.wgpuRenderBundleEncoderDrawIndexedIndirect + # GPUObjectBaseMixin + _release_function = libf.wgpuRenderBundleEncoderRelease + def finish(self, *, label=""): # H: nextInChain: WGPUChainedStruct *, label: char * struct = new_struct_p( @@ -3038,16 +3022,15 @@ def finish(self, *, label=""): ) # H: WGPURenderBundle f(WGPURenderBundleEncoder renderBundleEncoder, WGPURenderBundleDescriptor const * descriptor) id = libf.wgpuRenderBundleEncoderFinish(self._internal, struct) + # The other encoders require that we call self._release() when + # we're done with it. But that doesn't seem to be an issue here. return GPURenderBundle(label, id, self._device) - def _release(self): - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPURenderBundleEncoder renderBundleEncoder) - libf.wgpuRenderBundleEncoderRelease(internal) - class GPUQueue(classes.GPUQueue, GPUObjectBase): + # GPUObjectBaseMixin + _release_function = libf.wgpuQueueRelease + def submit(self, command_buffers): command_buffer_ids = [cb._internal for cb in command_buffers] c_command_buffers = ffi.new("WGPUCommandBuffer []", command_buffer_ids) @@ -3266,22 +3249,16 @@ def callback(status_, user_data_p): if status != 0: raise RuntimeError(f"Queue work done status: {status}") - def _release(self): - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPUQueue queue) - libf.wgpuQueueRelease(internal) - class GPURenderBundle(classes.GPURenderBundle, GPUObjectBase): - def _release(self): - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPURenderBundle renderBundle) - libf.wgpuRenderBundleRelease(internal) + # GPUObjectBaseMixin + _release_function = libf.wgpuRenderBundleRelease class GPUQuerySet(classes.GPUQuerySet, GPUObjectBase): + # GPUObjectBaseMixin + _release_function = libf.wgpuQuerySetRelease + def destroy(self): # Note: not yet implemented in wgpu-core, the wgpu-native func is a noop internal = self._internal @@ -3289,12 +3266,6 @@ def destroy(self): # H: void f(WGPUQuerySet querySet) libf.wgpuQuerySetDestroy(internal) - def _release(self): - if self._internal is not None and libf is not None: - self._internal, internal = None, self._internal - # H: void f(WGPUQuerySet querySet) - libf.wgpuQuerySetRelease(internal) - # %% Subclasses that don't need anything else diff --git a/wgpu/resources/codegen_report.md b/wgpu/resources/codegen_report.md index a61155dc..a8a7aee2 100644 --- a/wgpu/resources/codegen_report.md +++ b/wgpu/resources/codegen_report.md @@ -20,7 +20,7 @@ * Diffs for GPUQueue: add read_buffer, add read_texture, hide copy_external_image_to_texture * Validated 37 classes, 112 methods, 45 properties ### Patching API for backends/wgpu_native/_api.py -* Validated 37 classes, 114 methods, 0 properties +* Validated 37 classes, 98 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