22from imgui_bundle import imgui as ig #TODO: rename (git mv) the file instead.
33from .utils import UniformArray
44from wgpu .utils .imgui import ImguiWgpuBackend
5+ from dataclasses import dataclass
56
67
78# could imgui become just another RenderPass after Image? I got to understand backend vs renderer first.
89# make become part of .passes??
910# todo: raise error if imgui isn't installed (only if this module is required?)
1011
1112
12- def parse_constants (code :str , common_code ) -> list [tuple [int , str , int | float , str ]]:
13+ @dataclass
14+ class ShaderConstant :
15+ renderpass_pass : str #maybe this is a RenderPass pointer?
16+ line_number : int
17+ original_line : str
18+ name : str
19+ value : int | float
20+ shader_dtype : str # float, int, vec2, vec3, bool etc.
21+
22+ def c_type_format (self ) -> str :
23+ # based on these for the memoryview cast:
24+ # https://docs.python.org/3/library/struct.html#format-characters
25+ if self .shader_dtype == "float" :
26+ return "f"
27+ elif self .shader_dtype == "int" :
28+ return "i"
29+ elif self .shader_dtype == "uint" :
30+ return "I"
31+ # add more types as needed
32+ return "?"
33+
34+ def parse_constants (code :str , common_code ) -> list [ShaderConstant ]:
1335 # todo:
1436 # WGSL variants??
1537 # re/tree-sitter/loops and functions?
@@ -22,12 +44,12 @@ def parse_constants(code:str, common_code) -> list[tuple[int, str, int|float, st
2244 # mataches the macro: #define NAME VALUE
2345 # TODO there can be characters in numerical literals, such as x and o for hex and octal representation or e for scientific notation
2446 # technically the macros can also be an expression that is evaluated to be a number... such as # define DOF 10..0/30.0 - so how do we deal with that?
25- define_pattern = re .compile (r"#define\s+(\w+)\s+([\d.]+)" )
47+ define_pattern = re .compile (r"#\s* define\s+(\w+)\s+([\d.]+)" ) #for numerical literals right now.
2648 if_def_template = r"#(el)?if\s+" #preprocessor ifdef blocks can't become uniforms. replacing these dynamically will be difficult.
2749
2850 constants = []
2951 for li , line in enumerate (code .splitlines ()):
30- match = define_pattern .match (line .rstrip ())
52+ match = define_pattern .match (line .strip ())
3153 if match :
3254 name , value = match .groups ()
3355 if_def_pattern = re .compile (if_def_template + name )
@@ -38,17 +60,26 @@ def parse_constants(code:str, common_code) -> list[tuple[int, str, int|float, st
3860
3961 if "." in value : #value.isdecimal?
4062 # TODO: wgsl needs to be more specific (f32 for example?) - but there is no preprocessor anyways...
41- dtype = "f " #default float (32bit)
63+ dtype = "float " #default float (32bit)
4264 value = float (value )
43- elif value .isdecimal : # value.isalum ?
44- dtype = "I " # "big I (32bit)"
65+ elif value .isdecimal () : # value.isnumeric ?
66+ dtype = "int " # "big I (32bit)"
4567 value = int (value )
4668 else :
4769 # TODO complexer types?
4870 print (f"can't parse type for constant { name } with value { value } , skipping" )
4971 continue
72+
73+ constant = ShaderConstant (
74+ renderpass_pass = "image" , # TODO: shouldn't be names.
75+ line_number = li ,
76+ original_line = line .strip (),
77+ name = name ,
78+ value = value ,
79+ shader_dtype = dtype
80+ )
5081 # todo: remove lines here? (comment out better)
51- constants .append (( li , name , value , dtype )) # what about line to remove?
82+ constants .append (constant )
5283 print (f"In line { li } found constant: { name } with value: { value } of dtype { dtype } " )
5384
5485 # maybe just named tuple instead of dataclass?
@@ -57,23 +88,21 @@ def parse_constants(code:str, common_code) -> list[tuple[int, str, int|float, st
5788def make_uniform (constants ) -> UniformArray :
5889 arr_data = []
5990 for constant in constants :
60- _ , name , value , dtype = constant
61- arr_data .append (tuple ([name , dtype , 1 ]))
91+ arr_data .append (tuple ([constant .name , constant .c_type_format (), 1 ]))
6292 data = UniformArray (* arr_data )
6393
6494 # init data
6595 for constant in constants :
66- _ , name , value , dtype = constant
67- data [name ] = value
68-
96+ data [constant .name ] = constant .value
97+
6998 # TODO:
7099 # is there issues with padding? (maybe solve in the class)
71100 # figure out order due to padding/alignment: https://www.w3.org/TR/WGSL/#alignment-and-size
72101 # return a UniformArray object (cycling import?)
73102 # (does this need to be a class to update the values?)
74103 return data
75104
76- def construct_imports (constants , constant_binding_idx = 10 ) -> str :
105+ def construct_imports (constants : list [ ShaderConstant ] , constant_binding_idx = 10 ) -> str :
77106 # codegen the import block for this uniform (including binding? - which number?)
78107 # could be part of the UniformArray class maybe?
79108 # to be pasted near the top of the fragment shader code.
@@ -84,17 +113,8 @@ def construct_imports(constants, constant_binding_idx=10) -> str:
84113 var_init_lines = []
85114 var_mapping_lines = []
86115 for const in constants :
87- _ , name , value , dtype = const
88- # TODO: refactor to dtype map or something more useful -.-
89- if dtype == "f" :
90- dtype = "float"
91- elif dtype == "I" :
92- dtype = "int"
93- else :
94- # shouldn't happen
95- continue
96- var_init_lines .append (f"{ dtype } { name } ;" )
97- var_mapping_lines .append (f"# define { name } const_input.{ name } " )
116+ var_init_lines .append (f"{ const .shader_dtype } { const .name } ;" )
117+ var_mapping_lines .append (f"# define { const .name } const_input.{ const .name } " )
98118
99119 code_construct = f"""
100120 uniform struct ConstantInput {{
@@ -114,7 +134,7 @@ def update_gui():
114134 pass
115135
116136
117- def gui (constants , constants_data ):
137+ def gui (constants : list [ ShaderConstant ] , constants_data : UniformArray ):
118138 ig .new_frame ()
119139 ig .set_next_window_pos ((0 , 0 ), ig .Cond_ .appearing )
120140 ig .set_next_window_size ((400 , 0 ), ig .Cond_ .appearing )
@@ -126,11 +146,10 @@ def gui(constants, constants_data):
126146
127147 # create the sliders?
128148 for const in constants :
129- li , name , value , dtype = const
130- if dtype == "f" :
131- _ , constants_data [name ] = ig .slider_float (name , constants_data [name ], 0 , value * 2.0 )
132- elif dtype == "I" :
133- _ , constants_data [name ] = ig .slider_int (name , constants_data [name ], 0 , value * 2 )
149+ if const .shader_dtype == "float" :
150+ _ , constants_data [const .name ] = ig .slider_float (const .name , constants_data [const .name ], 0 , const .value * 2.0 )
151+ elif const .shader_dtype == "int" :
152+ _ , constants_data [const .name ] = ig .slider_int (const .name , constants_data [const .name ], 0 , const .value * 2 )
134153 # TODO: improve min/max for negatives
135154
136155 ig .end ()
0 commit comments