From f7f6964534494c48b1e429bb58952665d00a9291 Mon Sep 17 00:00:00 2001 From: Almar Klein Date: Wed, 25 Sep 2024 14:35:20 +0200 Subject: [PATCH] Logic to disable sync method for portability testing --- wgpu/backends/wgpu_native/_api.py | 77 +++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 25 deletions(-) diff --git a/wgpu/backends/wgpu_native/_api.py b/wgpu/backends/wgpu_native/_api.py index f372fd61..dc97f3f4 100644 --- a/wgpu/backends/wgpu_native/_api.py +++ b/wgpu/backends/wgpu_native/_api.py @@ -45,6 +45,9 @@ # %% Helper functions and objects +def check_can_use_sync_variants(): + if False: # placeholder, let's implement a little wgpu config thingy + raise RuntimeError("Disallowed use of '_sync' API.") # Object to be able to bind the lifetime of objects to other objects _refs_per_struct = WeakKeyDictionary() @@ -307,6 +310,19 @@ class GPU(classes.GPU): def request_adapter_sync( self, *, power_preference=None, force_fallback_adapter=False, canvas=None + ): + """Async version of ``request_adapter_async()``. + This is the implementation based on wgpu-native. + """ + check_can_use_sync_variants() + return self._request_adapter( + power_preference=power_preference, + force_fallback_adapter=force_fallback_adapter, + canvas=canvas, + ) + + async def request_adapter_async( + self, *, power_preference=None, force_fallback_adapter=False, canvas=None ): """Create a `GPUAdapter`, the object that represents an abstract wgpu implementation, from which one can request a `GPUDevice`. @@ -320,7 +336,15 @@ def request_adapter_sync( canvas (WgpuCanvasInterface): The canvas that the adapter should be able to render to. This can typically be left to None. """ + return self._request_adapter( + power_preference=power_preference, + force_fallback_adapter=force_fallback_adapter, + canvas=canvas, + ) # no-cover + def _request_adapter( + self, *, power_preference=None, force_fallback_adapter=False, canvas=None + ): # ----- Surface ID # Get surface id that the adapter must be compatible with. If we @@ -383,22 +407,20 @@ def callback(status, result, message, userdata): return self._create_adapter(adapter_id) - async def request_adapter_async( - self, *, power_preference=None, force_fallback_adapter=False, canvas=None - ): - """Async version of ``request_adapter()``. + def enumerate_adapters_sync(self): + """Sync version of ``enumerate_adapters_async()``. This is the implementation based on wgpu-native. """ - return self.request_adapter_sync( - power_preference=power_preference, - force_fallback_adapter=force_fallback_adapter, - canvas=canvas, - ) # no-cover + check_can_use_sync_variants() + return self._enumerate_adapters() - def enumerate_adapters_sync(self): + async def enumerate_adapters_async(self): """Get a list of adapter objects available on the current system. This is the implementation based on wgpu-native. """ + return self._enumerate_adapters() + + def _enumerate_adapters(self): # The first call is to get the number of adapters, and the second call # is to get the actual adapters. Note that the second arg (now NULL) can # be a `WGPUInstanceEnumerateAdapterOptions` to filter by backend. @@ -410,12 +432,6 @@ def enumerate_adapters_sync(self): libf.wgpuInstanceEnumerateAdapters(instance, ffi.NULL, adapters) return [self._create_adapter(adapter) for adapter in adapters] - async def enumerate_adapters_async(self): - """Async version of ``enumerate_adapters_sync()``. - This is the implementation based on wgpu-native. - """ - return self.enumerate_adapters_sync() - def _create_adapter(self, adapter_id): # ----- Get adapter info @@ -823,6 +839,7 @@ def request_device_sync( required_limits: "Dict[str, int]" = {}, default_queue: "structs.QueueDescriptor" = {}, ): + check_can_use_sync_variants() if default_queue: check_struct("QueueDescriptor", default_queue) return self._request_device( @@ -1854,6 +1871,7 @@ def create_query_set(self, *, label="", type: "enums.QueryType", count: int): return GPUQuerySet(label, query_id, self._internal, type, count) def _get_lost_sync(self): + check_can_use_sync_variants() raise NotImplementedError() async def _get_lost_async(self): @@ -1918,6 +1936,13 @@ def _check_range(self, offset, size): return offset, size def map_sync(self, mode, offset=0, size=None): + check_can_use_sync_variants() + return self._map(mode, offset, size) + + async def map_async(self, mode, offset=0, size=None): + return self._map(mode, offset, size) # for now + + def _map(self, mode, offset=0, size=None): sync_on_read = True # Check mode @@ -1967,9 +1992,6 @@ def callback(status_, user_data_p): self._mapped_status = offset, offset + size, mode self._mapped_memoryviews = [] - async def map_async(self, mode, offset=0, size=None): - return self.map_sync(mode, offset, size) # for now - def unmap(self): if self._map_state != enums.BufferMapState.mapped: raise RuntimeError("Can only unmap a buffer if its currently mapped.") @@ -2193,7 +2215,14 @@ class GPUShaderModule(classes.GPUShaderModule, GPUObjectBase): _release_function = libf.wgpuShaderModuleRelease def get_compilation_info_sync(self): - # Here's a little setup to implement this method. Unfortunately, + check_can_use_sync_variants() + return self._get_compilation_info() + + async def get_compilation_info_async(self): + return self._get_compilation_info() + + 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 # is that if there is an error in the shader source, we raise # an exception, so the user never gets a GPUShaderModule object @@ -2223,9 +2252,6 @@ def get_compilation_info_sync(self): return [] - async def get_compilation_info_async(self): - return self.get_compilation_info_sync() - class GPUPipelineBase(classes.GPUPipelineBase): def get_bind_group_layout(self, index): @@ -3098,7 +3124,7 @@ def read_buffer(self, buffer, buffer_offset=0, size=None): self.submit([command_buffer]) # Download from mappable buffer - tmp_buffer.map_sync("READ_NOSYNC") + tmp_buffer._map("READ_NOSYNC") data = tmp_buffer.read_mapped() # Explicit drop. @@ -3202,7 +3228,7 @@ def read_texture(self, source, data_layout, size): self.submit([command_buffer]) # Download from mappable buffer - tmp_buffer.map_sync("READ_NOSYNC") + tmp_buffer._map("READ_NOSYNC") data = tmp_buffer.read_mapped() # Explicit drop. @@ -3227,6 +3253,7 @@ def read_texture(self, source, data_layout, size): return data def on_submitted_work_done_sync(self): + check_can_use_sync_variants() # In JS, this returns a Promise that can be awaited to (async) wait # for the work that is currently in the pipeline. We need to figure out # how to expose these async parts.