2015-12-03 02:36:18 +01:00
import os
2017-03-15 12:30:14 +01:00
import arm . utils
2017-12-20 15:37:58 +01:00
import arm . assets as assets
2015-12-03 02:36:18 +01:00
2016-10-19 13:28:06 +02:00
def write_data ( res , defs , json_data , base_name ) :
2016-09-28 00:00:59 +02:00
# Define
sres = { }
res [ ' shader_datas ' ] . append ( sres )
2015-12-03 02:36:18 +01:00
2016-09-28 00:00:59 +02:00
shader_id = base_name
2015-12-03 02:36:18 +01:00
2016-09-28 00:00:59 +02:00
sres [ ' name ' ] = shader_id
sres [ ' contexts ' ] = [ ]
2015-12-03 02:36:18 +01:00
2017-12-20 15:37:58 +01:00
asset = assets . shader_passes_assets [ base_name ]
2016-09-28 00:00:59 +02:00
# Parse
for c in json_data [ ' contexts ' ] :
con = { }
sres [ ' contexts ' ] . append ( con )
con [ ' name ' ] = c [ ' name ' ]
con [ ' constants ' ] = [ ]
con [ ' texture_units ' ] = [ ]
2017-05-25 16:48:41 +02:00
con [ ' vertex_structure ' ] = [ ]
2015-12-17 20:07:23 +01:00
2016-09-28 00:00:59 +02:00
# Names
2017-12-20 15:37:58 +01:00
con [ ' vertex_shader ' ] = c [ ' vertex_shader ' ] . rsplit ( ' . ' , 1 ) [ 0 ] . split ( ' / ' ) [ - 1 ]
if con [ ' vertex_shader ' ] not in asset :
asset . append ( con [ ' vertex_shader ' ] )
con [ ' fragment_shader ' ] = c [ ' fragment_shader ' ] . rsplit ( ' . ' , 1 ) [ 0 ] . split ( ' / ' ) [ - 1 ]
if con [ ' fragment_shader ' ] not in asset :
asset . append ( con [ ' fragment_shader ' ] )
2015-12-17 20:07:23 +01:00
2016-09-28 00:00:59 +02:00
if ' geometry_shader ' in c :
2017-12-20 15:37:58 +01:00
con [ ' geometry_shader ' ] = c [ ' geometry_shader ' ] . rsplit ( ' . ' , 1 ) [ 0 ] . split ( ' / ' ) [ - 1 ]
if con [ ' geometry_shader ' ] not in asset :
asset . append ( con [ ' geometry_shader ' ] )
2016-09-28 00:00:59 +02:00
if ' tesscontrol_shader ' in c :
2017-12-20 15:37:58 +01:00
con [ ' tesscontrol_shader ' ] = c [ ' tesscontrol_shader ' ] . rsplit ( ' . ' , 1 ) [ 0 ] . split ( ' / ' ) [ - 1 ]
if con [ ' tesscontrol_shader ' ] not in asset :
asset . append ( con [ ' tesscontrol_shader ' ] )
2016-09-28 00:00:59 +02:00
if ' tesseval_shader ' in c :
2017-12-20 15:37:58 +01:00
con [ ' tesseval_shader ' ] = c [ ' tesseval_shader ' ] . rsplit ( ' . ' , 1 ) [ 0 ] . split ( ' / ' ) [ - 1 ]
if con [ ' tesseval_shader ' ] not in asset :
asset . append ( con [ ' tesseval_shader ' ] )
2015-12-17 20:07:23 +01:00
2016-09-28 00:00:59 +02:00
# Params
2016-10-17 12:02:41 +02:00
params = [ ' depth_write ' , ' compare_mode ' , ' stencil_mode ' , \
' stencil_pass ' , ' stencil_fail ' , ' stencil_reference_value ' , \
' stencil_read_mask ' , ' stencil_write_mask ' , ' cull_mode ' , \
' blend_source ' , ' blend_destination ' , ' blend_operation ' , \
' alpha_blend_source ' , ' alpha_blend_destination ' , ' alpha_blend_operation ' \
' color_write_red ' , ' color_write_green ' , ' color_write_blue ' , \
2017-05-20 19:07:15 +02:00
' color_write_alpha ' , ' conservative_raster ' ]
2016-10-17 12:02:41 +02:00
for p in params :
if p in c :
con [ p ] = c [ p ]
2016-01-28 00:58:00 +01:00
2016-09-28 00:00:59 +02:00
# Parse shaders
2017-12-20 15:37:58 +01:00
with open ( c [ ' vertex_shader ' ] ) as f :
vert = f . read ( ) . splitlines ( )
with open ( c [ ' fragment_shader ' ] ) as f :
frag = f . read ( ) . splitlines ( )
2016-10-17 00:02:51 +02:00
2017-05-25 16:48:41 +02:00
parse_shader ( sres , c , con , defs , vert , True ) # Parse attribs for vertex shader
2016-09-28 00:00:59 +02:00
parse_shader ( sres , c , con , defs , frag , False )
2016-10-25 16:15:07 +02:00
2016-09-28 00:00:59 +02:00
if ' geometry_shader ' in c :
2017-12-20 15:37:58 +01:00
with open ( c [ ' geometry_shader ' ] ) as f :
geom = f . read ( ) . splitlines ( )
2016-09-28 00:00:59 +02:00
parse_shader ( sres , c , con , defs , geom , False )
2016-10-25 16:15:07 +02:00
2016-09-28 00:00:59 +02:00
if ' tesscontrol_shader ' in c :
2017-12-20 15:37:58 +01:00
with open ( c [ ' tesscontrol_shader ' ] ) as f :
tesc = f . read ( ) . splitlines ( )
2016-09-28 00:00:59 +02:00
parse_shader ( sres , c , con , defs , tesc , False )
2016-10-25 16:15:07 +02:00
2016-09-28 00:00:59 +02:00
if ' tesseval_shader ' in c :
2017-12-20 15:37:58 +01:00
with open ( c [ ' tesseval_shader ' ] ) as f :
tese = f . read ( ) . splitlines ( )
2016-09-28 00:00:59 +02:00
parse_shader ( sres , c , con , defs , tese , False )
2016-01-28 00:58:00 +01:00
2016-09-28 00:00:59 +02:00
def parse_shader ( sres , c , con , defs , lines , parse_attributes ) :
2016-10-19 13:28:06 +02:00
skip_till_endif = 0
skip_else = False
2016-09-28 00:00:59 +02:00
vertex_structure_parsed = False
vertex_structure_parsing = False
2016-12-02 00:13:09 +01:00
stack = [ ]
2016-09-28 00:00:59 +02:00
if parse_attributes == False :
vertex_structure_parsed = True
for line in lines :
line = line . lstrip ( )
2016-12-02 00:13:09 +01:00
# Preprocessor
if line . startswith ( ' #ifdef ' ) or line . startswith ( ' #ifndef ' ) :
2016-09-28 00:00:59 +02:00
s = line . split ( ' ' ) [ 1 ]
2017-12-13 14:21:42 +01:00
found = s in defs
2016-12-02 00:13:09 +01:00
if line . startswith ( ' #ifndef ' ) :
found = not found
2017-01-14 17:37:18 +01:00
if found == False :
2016-12-02 00:13:09 +01:00
stack . append ( 0 )
else :
stack . append ( 1 )
2016-09-28 00:00:59 +02:00
continue
2016-01-28 00:58:00 +01:00
2016-12-02 00:13:09 +01:00
if line . startswith ( ' #else ' ) :
stack [ - 1 ] = 1 - stack [ - 1 ]
2016-09-28 00:00:59 +02:00
continue
2016-01-28 00:58:00 +01:00
2016-12-02 00:13:09 +01:00
if line . startswith ( ' #endif ' ) :
stack . pop ( )
2016-09-28 00:00:59 +02:00
continue
2015-12-17 20:07:23 +01:00
2016-12-02 00:13:09 +01:00
if len ( stack ) > 0 and stack [ - 1 ] == 0 :
2016-09-28 00:00:59 +02:00
continue
2016-07-20 17:33:17 +02:00
2016-12-02 00:13:09 +01:00
2016-09-28 00:00:59 +02:00
if vertex_structure_parsed == False and line . startswith ( ' in ' ) :
vertex_structure_parsing = True
vd = { }
s = line . split ( ' ' )
vd [ ' size ' ] = int ( s [ 1 ] [ - 1 : ] )
vd [ ' name ' ] = s [ 2 ] [ : - 1 ]
2017-05-25 16:48:41 +02:00
con [ ' vertex_structure ' ] . append ( vd )
2016-09-28 00:00:59 +02:00
if vertex_structure_parsing == True and len ( line ) > 0 and line . startswith ( ' // ' ) == False and line . startswith ( ' in ' ) == False :
vertex_structure_parsed = True
2016-05-19 22:22:41 +02:00
2016-10-17 17:39:40 +02:00
if line . startswith ( ' uniform ' ) or line . startswith ( ' //!uniform ' ) : # Uniforms included from header files
2016-09-28 00:00:59 +02:00
s = line . split ( ' ' )
2016-10-09 16:06:18 +02:00
# uniform sampler2D myname;
# uniform layout(RGBA8) image3D myname;
if s [ 1 ] . startswith ( ' layout ' ) :
ctype = s [ 2 ]
cid = s [ 3 ] [ : - 1 ]
else :
ctype = s [ 1 ]
cid = s [ 2 ] [ : - 1 ]
2016-09-28 00:00:59 +02:00
found = False # Unique check
2017-08-03 14:01:04 +02:00
if ctype == ' sampler2D ' or ctype == ' sampler2DShadow ' or ctype == ' sampler3D ' or ctype == ' samplerCube ' or ctype == ' image2D ' or ctype == ' uimage2D ' or ctype == ' image3D ' or ctype == ' uimage3D ' : # Texture unit
2016-10-09 16:06:18 +02:00
for tu in con [ ' texture_units ' ] : # Texture already present
2016-09-28 00:00:59 +02:00
if tu [ ' name ' ] == cid :
found = True
break
if found == False :
tu = { }
tu [ ' name ' ] = cid
2016-10-09 16:06:18 +02:00
# sampler2D / image2D
2017-08-03 14:01:04 +02:00
if ctype == ' image2D ' or ctype == ' uimage2D ' or ctype == ' image3D ' or ctype == ' uimage3D ' :
2016-10-09 16:06:18 +02:00
tu [ ' is_image ' ] = True
2016-09-28 00:00:59 +02:00
# Check for link
for l in c [ ' links ' ] :
if l [ ' name ' ] == cid :
valid_link = True
2016-10-12 17:52:27 +02:00
2016-09-28 00:00:59 +02:00
if ' ifdef ' in l :
2016-10-12 17:52:27 +02:00
def_found = False
2016-09-28 00:00:59 +02:00
for d in defs :
for link_def in l [ ' ifdef ' ] :
if d == link_def :
2016-10-12 17:52:27 +02:00
def_found = True
2016-09-28 00:00:59 +02:00
break
2016-10-12 17:52:27 +02:00
if def_found :
2016-09-28 00:00:59 +02:00
break
2016-10-12 17:52:27 +02:00
if not def_found :
valid_link = False
if ' ifndef ' in l :
def_found = False
for d in defs :
2016-11-08 15:14:56 +01:00
for link_def in l [ ' ifndef ' ] :
2016-10-12 17:52:27 +02:00
if d == link_def :
def_found = True
break
if def_found :
break
if def_found :
valid_link = False
2016-09-28 00:00:59 +02:00
if valid_link :
tu [ ' link ' ] = l [ ' link ' ]
break
con [ ' texture_units ' ] . append ( tu )
else : # Constant
if cid . find ( ' [ ' ) != - 1 : # Float arrays
cid = cid . split ( ' [ ' ) [ 0 ]
2017-04-12 13:25:09 +02:00
ctype = ' floats '
2016-09-28 00:00:59 +02:00
for const in con [ ' constants ' ] :
if const [ ' name ' ] == cid :
found = True
break
if found == False :
const = { }
const [ ' type ' ] = ctype
const [ ' name ' ] = cid
# Check for link
for l in c [ ' links ' ] :
if l [ ' name ' ] == cid :
valid_link = True
2016-10-12 17:52:27 +02:00
2016-09-28 00:00:59 +02:00
if ' ifdef ' in l :
2016-10-12 17:52:27 +02:00
def_found = False
2016-09-28 00:00:59 +02:00
for d in defs :
2016-10-12 17:52:27 +02:00
for link_def in l [ ' ifdef ' ] :
if d == link_def :
def_found = True
2016-09-28 00:00:59 +02:00
break
2016-10-12 17:52:27 +02:00
if def_found :
2016-09-28 00:00:59 +02:00
break
2016-10-12 17:52:27 +02:00
if not def_found :
valid_link = False
if ' ifndef ' in l :
def_found = False
for d in defs :
2016-11-05 20:57:04 +01:00
for link_def in l [ ' ifndef ' ] :
2016-10-12 17:52:27 +02:00
if d == link_def :
def_found = True
break
if def_found :
break
if def_found :
valid_link = False
2016-09-28 00:00:59 +02:00
if valid_link :
const [ ' link ' ] = l [ ' link ' ]
break
con [ ' constants ' ] . append ( const )
2015-12-17 20:07:23 +01:00
2017-12-13 14:21:42 +01:00
def make ( res , base_name , json_data , fp , defs ) :
2016-10-19 13:28:06 +02:00
write_data ( res , defs , json_data , base_name )