diff --git a/wgpu/backends/wgpu_native/_api.py b/wgpu/backends/wgpu_native/_api.py index 8e34d6de..3b9779d5 100644 --- a/wgpu/backends/wgpu_native/_api.py +++ b/wgpu/backends/wgpu_native/_api.py @@ -842,7 +842,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): @@ -1072,6 +1095,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) @@ -1891,15 +1917,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) @@ -2121,13 +2147,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, *, @@ -2185,54 +2211,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 @@ -2264,12 +2272,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): @@ -2286,30 +2288,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): @@ -2465,6 +2455,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 ): @@ -2857,14 +2850,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, @@ -2882,6 +2867,9 @@ class GPUComputePassEncoder( # GPUBindingCommandsMixin _set_bind_group_function = libf.wgpuComputePassEncoderSetBindGroup + # GPUObjectBaseMixin + _release_function = libf.wgpuComputePassEncoderRelease + _ended = False def set_pipeline(self, pipeline): @@ -2909,14 +2897,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, @@ -2943,6 +2926,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): @@ -2985,6 +2971,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): @@ -3032,12 +3019,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, @@ -3064,6 +3045,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( @@ -3073,16 +3057,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) @@ -3301,22 +3284,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 @@ -3324,12 +3301,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 09cd37c4..a1b88315 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