1919import logging
2020import ctypes .util
2121from weakref import WeakKeyDictionary
22- from typing import List , Dict , Union
22+ from typing import List , Dict , Optional , Union
2323
2424from ... import classes , flags , enums , structs
2525from ..._coreutils import str_flag_to_int
@@ -172,6 +172,36 @@ def _tuple_from_color(rgba):
172172 return _tuple_from_tuple_or_dict (rgba , "rgba" )
173173
174174
175+ def _get_override_constant_entries (field ):
176+ constants = field .get ("constants" )
177+ if not constants :
178+ return ffi .NULL , []
179+ c_constant_entries = []
180+ for key , value in constants .items ():
181+ assert isinstance (key , (str , int ))
182+ assert isinstance (value , (int , float , bool ))
183+ # H: nextInChain: WGPUChainedStruct *, key: char *, value: float
184+ c_constant_entry = new_struct (
185+ "WGPUConstantEntry" ,
186+ key = to_c_string (str (key )),
187+ value = float (value ),
188+ # not used: nextInChain
189+ )
190+ c_constant_entries .append (c_constant_entry )
191+ # We need to return and hold onto c_constant_entries in order to prevent the C
192+ # strings from being GC'ed.
193+ c_constants = ffi .new ("WGPUConstantEntry[]" , c_constant_entries )
194+ return c_constants , c_constant_entries
195+
196+
197+ def to_c_string (string : str ):
198+ return ffi .new ("char []" , string .encode ())
199+
200+
201+ def to_c_string_or_null (string : Optional [str ]):
202+ return ffi .NULL if string is None else ffi .new ("char []" , string .encode ())
203+
204+
175205_empty_label = ffi .new ("char []" , b"" )
176206
177207
@@ -180,7 +210,7 @@ def to_c_label(label):
180210 if not label :
181211 return _empty_label
182212 else :
183- return ffi . new ( "char []" , label . encode () )
213+ return to_c_string ( label )
184214
185215
186216def feature_flag_to_feature_names (flag ):
@@ -945,7 +975,7 @@ def canonicalize_limit_name(name):
945975
946976 c_trace_path = ffi .NULL
947977 if trace_path : # no-cover
948- c_trace_path = ffi . new ( "char []" , trace_path . encode () )
978+ c_trace_path = to_c_string ( trace_path )
949979
950980 # H: chain: WGPUChainedStruct, tracePath: char *
951981 extras = new_struct_p (
@@ -1485,15 +1515,15 @@ def create_shader_module(
14851515 # H: name: char *, value: char *
14861516 new_struct (
14871517 "WGPUShaderDefine" ,
1488- name = ffi .new ("char []" , "gl_VertexID" . encode () ),
1489- value = ffi .new ("char []" , "gl_VertexIndex" . encode () ),
1518+ name = ffi .new ("char []" , b "gl_VertexID" ),
1519+ value = ffi .new ("char []" , b "gl_VertexIndex" ),
14901520 )
14911521 )
14921522 c_defines = ffi .new ("WGPUShaderDefine []" , defines )
14931523 # H: chain: WGPUChainedStruct, stage: WGPUShaderStage, code: char *, defineCount: int, defines: WGPUShaderDefine *
14941524 source_struct = new_struct_p (
14951525 "WGPUShaderModuleGLSLDescriptor *" ,
1496- code = ffi . new ( "char []" , code . encode () ),
1526+ code = to_c_string ( code ),
14971527 stage = c_stage ,
14981528 defineCount = len (defines ),
14991529 defines = c_defines ,
@@ -1506,7 +1536,7 @@ def create_shader_module(
15061536 # H: chain: WGPUChainedStruct, code: char *
15071537 source_struct = new_struct_p (
15081538 "WGPUShaderModuleWGSLDescriptor *" ,
1509- code = ffi . new ( "char []" , code . encode () ),
1539+ code = to_c_string ( code ),
15101540 # not used: chain
15111541 )
15121542 source_struct [0 ].chain .next = ffi .NULL
@@ -1558,14 +1588,15 @@ def create_compute_pipeline(
15581588 compute : "structs.ProgrammableStage" ,
15591589 ):
15601590 check_struct ("ProgrammableStage" , compute )
1591+ c_constants , c_constant_entries = _get_override_constant_entries (compute )
15611592 # H: nextInChain: WGPUChainedStruct *, module: WGPUShaderModule, entryPoint: char *, constantCount: int, constants: WGPUConstantEntry *
15621593 c_compute_stage = new_struct (
15631594 "WGPUProgrammableStageDescriptor" ,
15641595 module = compute ["module" ]._internal ,
1565- entryPoint = ffi .new ("char []" , compute ["entry_point" ].encode ()),
1596+ entryPoint = to_c_string_or_null (compute .get ("entry_point" )),
1597+ constantCount = len (c_constant_entries ),
1598+ constants = c_constants ,
15661599 # not used: nextInChain
1567- # not used: constantCount
1568- # not used: constants
15691600 )
15701601
15711602 if isinstance (layout , GPUPipelineLayout ):
@@ -1643,16 +1674,17 @@ def create_render_pipeline(
16431674 c_vertex_buffer_descriptors_array = ffi .new (
16441675 "WGPUVertexBufferLayout []" , c_vertex_buffer_layout_list
16451676 )
1677+ c_vertex_constants , c_vertex_entries = _get_override_constant_entries (vertex )
16461678 # H: nextInChain: WGPUChainedStruct *, module: WGPUShaderModule, entryPoint: char *, constantCount: int, constants: WGPUConstantEntry *, bufferCount: int, buffers: WGPUVertexBufferLayout *
16471679 c_vertex_state = new_struct (
16481680 "WGPUVertexState" ,
16491681 module = vertex ["module" ]._internal ,
1650- entryPoint = ffi . new ( "char []" , vertex [ " entry_point"]. encode ( )),
1682+ entryPoint = to_c_string_or_null ( vertex . get ( " entry_point" )),
16511683 buffers = c_vertex_buffer_descriptors_array ,
16521684 bufferCount = len (c_vertex_buffer_layout_list ),
1685+ constantCount = len (c_vertex_entries ),
1686+ constants = c_vertex_constants ,
16531687 # not used: nextInChain
1654- # not used: constantCount
1655- # not used: constants
16561688 )
16571689
16581690 # H: nextInChain: WGPUChainedStruct *, topology: WGPUPrimitiveTopology, stripIndexFormat: WGPUIndexFormat, frontFace: WGPUFrontFace, cullMode: WGPUCullMode
@@ -1753,16 +1785,19 @@ def create_render_pipeline(
17531785 "WGPUColorTargetState []" , c_color_targets_list
17541786 )
17551787 check_struct ("FragmentState" , fragment )
1788+ c_fragment_constants , c_fragment_entries = _get_override_constant_entries (
1789+ fragment
1790+ )
17561791 # H: nextInChain: WGPUChainedStruct *, module: WGPUShaderModule, entryPoint: char *, constantCount: int, constants: WGPUConstantEntry *, targetCount: int, targets: WGPUColorTargetState *
17571792 c_fragment_state = new_struct_p (
17581793 "WGPUFragmentState *" ,
17591794 module = fragment ["module" ]._internal ,
1760- entryPoint = ffi . new ( "char []" , fragment [ " entry_point"]. encode ( )),
1795+ entryPoint = to_c_string_or_null ( fragment . get ( " entry_point" )),
17611796 targets = c_color_targets_array ,
17621797 targetCount = len (c_color_targets_list ),
1798+ constantCount = len (c_fragment_entries ),
1799+ constants = c_fragment_constants ,
17631800 # not used: nextInChain
1764- # not used: constantCount
1765- # not used: constants
17661801 )
17671802
17681803 if isinstance (layout , GPUPipelineLayout ):
@@ -2315,7 +2350,7 @@ def set_bind_group(
23152350class GPUDebugCommandsMixin (classes .GPUDebugCommandsMixin ):
23162351 # whole class is likely going to solved better: https://github.com/pygfx/wgpu-py/pull/546
23172352 def push_debug_group (self , group_label ):
2318- c_group_label = ffi . new ( "char []" , group_label . encode () )
2353+ c_group_label = to_c_string ( group_label )
23192354 # H: void wgpuCommandEncoderPushDebugGroup(WGPUCommandEncoder commandEncoder, char const * groupLabel)
23202355 # H: void wgpuComputePassEncoderPushDebugGroup(WGPUComputePassEncoder computePassEncoder, char const * groupLabel)
23212356 # H: void wgpuRenderPassEncoderPushDebugGroup(WGPURenderPassEncoder renderPassEncoder, char const * groupLabel)
@@ -2332,7 +2367,7 @@ def pop_debug_group(self):
23322367 function (self ._internal )
23332368
23342369 def insert_debug_marker (self , marker_label ):
2335- c_marker_label = ffi . new ( "char []" , marker_label . encode () )
2370+ c_marker_label = to_c_string ( marker_label )
23362371 # H: void wgpuCommandEncoderInsertDebugMarker(WGPUCommandEncoder commandEncoder, char const * markerLabel)
23372372 # H: void wgpuComputePassEncoderInsertDebugMarker(WGPUComputePassEncoder computePassEncoder, char const * markerLabel)
23382373 # H: void wgpuRenderPassEncoderInsertDebugMarker(WGPURenderPassEncoder renderPassEncoder, char const * markerLabel)
0 commit comments