@@ -44,6 +44,7 @@ def preconfigure_default_device(
4444 adapter : GPUAdapter | None = None ,
4545 # Device arguments
4646 label : str | None = None ,
47+ preferred_features : set [str ] | None = None ,
4748 required_features : set [enums .FeatureNameEnum ] | None = None ,
4849 required_limits : dict [str , int | None ] | None = None ,
4950 # default_queue: structs.QueueDescriptorStruct | None = None,
@@ -58,7 +59,7 @@ def preconfigure_default_device(
5859 use wgpu can each require the features they need. For required features
5960 the union of set features is used. For required limits the minimum of
6061 each set limit is used. For the other arguments, the last set value is
61- used, and a warning is logged when a value is overriden .
62+ used, and a warning is logged when a value is overridden .
6263
6364 Arguments:
6465 caller_info (str): A very brief description of the code that calls
@@ -74,9 +75,12 @@ def preconfigure_default_device(
7475 Setting the adapter overrules all other adapter settings
7576 (feature_level, power_preference, force_fallback_adapter, canvas).
7677 label (str): A human-readable label for the device.
77- required_features (list of str): the features (extensions) that you need.
78- Features can also be discarded by prefixing them with '!'. This is not recommended
79- unless for testing and very specific use-cases.
78+ preferred_features (set of str): the features (extensions) that you want but do not strictly need.
79+ Check ``device.features`` for its success. Backend-specific / native features are allowed too.
80+ Preferred features can also be discarded by prefixing them with '!'.
81+ required_features (set of str): the features (extensions) that you need.
82+ Required features can also be discarded by prefixing them with '!'. This is not recommended
83+ except for testing and very specific use-cases. Only official features (from ``wgpu.FeatureName``) are allowed.
8084 required_limits (dict): the various limits that you want to apply.
8185 Limits can also be discarded by setting their value to None.
8286 """
@@ -98,6 +102,8 @@ def preconfigure_default_device(
98102
99103 if isinstance (required_features , (tuple , list )):
100104 required_features = set (required_features )
105+ if isinstance (preferred_features , (tuple , list )):
106+ preferred_features = set (preferred_features )
101107
102108 ak , dk = self ._adapter_kwargs , self ._device_kwargs
103109
@@ -108,6 +114,7 @@ def preconfigure_default_device(
108114 (ak , "canvas" , canvas , None , None ),
109115 (ak , "adapter" , adapter , GPUAdapter , None ),
110116 (dk , "label" , label , str , None ),
117+ (dk , "preferred_features" , preferred_features , set , None ),
111118 (dk , "required_features" , required_features , set , enums .FeatureName ),
112119 (dk , "required_limits" , required_limits , dict , None ),
113120 ]:
@@ -127,8 +134,11 @@ def preconfigure_default_device(
127134 for value in values :
128135 value = value .lstrip ("!" )
129136 if value not in arg_values :
137+ tip = ""
138+ if arg_name == "required_features" :
139+ tip = f" If { value !r} is a native feature, use it in preferred_features instead."
130140 raise ValueError (
131- f"preconfigure_default_device ({ caller_info } ): { what } must be a one of { set ( arg_values ) } , but got { value !r} ."
141+ f"preconfigure_default_device ({ caller_info } ): { what } must be a one of { arg_values } , but got { value !r} .{ tip } "
132142 )
133143 if isinstance (arg_value , set ):
134144 cur_value = arg_dict .setdefault (arg_name , set ())
@@ -195,12 +205,20 @@ def get_default_device(self) -> GPUDevice:
195205 The default device can be configured at import-time using ``preconfigure_default_device()``.
196206 """
197207 if self ._the_device is None :
208+ # Get adapter
198209 adapter : GPUAdapter = self ._adapter_kwargs .pop ("adapter" , None )
199210 if adapter is None :
200211 adapter = wgpu .gpu .request_adapter_sync (** self ._adapter_kwargs )
201- self ._the_device = adapter .request_device_sync (** self ._device_kwargs )
212+ # Handle preferred features
213+ kwargs = self ._device_kwargs .copy ()
214+ required_features = kwargs .get ("required_features" , set ())
215+ extra_features = kwargs .pop ("preferred_features" , set ()) & adapter .features
216+ kwargs ["required_features" ] = required_features | extra_features
217+ # Create device
218+ self ._the_device = adapter .request_device_sync (** kwargs )
202219 self ._adapter_kwargs .clear ()
203220 self ._device_kwargs .clear ()
221+
204222 return self ._the_device
205223
206224
0 commit comments