Refactor cg2glsl.py.

This commit is contained in:
Felix Laurie von Massenbach 2015-08-08 20:53:17 +01:00
parent da4cc54b8c
commit f272431b5d
1 changed files with 104 additions and 141 deletions

View File

@ -25,21 +25,18 @@ def log(*arg):
print(*arg) print(*arg)
def remove_comments(source_lines):
ret = []
killed_comments = [line.split('//')[0] for line in source_lines]
for i in filter(lambda line: len(line) > 0, killed_comments):
ret.append(i)
return ret
def keep_line_if(func, lines): def keep_line_if(func, lines):
ret = [] ret = []
for i in filter(func, lines): for line in filter(func, lines):
ret.append(i) ret.append(line)
return ret return ret
def remove_comments(source_lines):
lines_without_comments = [line.split('//')[0] for line in source_lines]
return keep_line_if(lambda line: line, lines_without_comments)
def replace_global_in(source): def replace_global_in(source):
split_source = source.split('\n') split_source = source.split('\n')
replace_table = [ replace_table = [
@ -53,45 +50,44 @@ def replace_global_in(source):
for line in split_source: for line in split_source:
if ('//var' in line) or ('#var' in line): if ('//var' in line) or ('#var' in line):
for index, replace in enumerate(replace_table): for index, replace in enumerate(replace_table):
orig = line.split(' ')[2] orig = line.split()[2]
if replace[0] == orig: if replace[0] == orig:
replace_table[index] = (line.split(':')[2].split(' ')[1], replace_table[index][1]) replace_table[index] = (line.split(':')[2].split(' ')[1], replace_table[index][1])
log('Replace globals:', replace_table) log('Replace globals:', replace_table)
for replace in replace_table: for orig, new in replace_table:
if replace[0]: if orig:
source = source.replace(replace[0], replace[1]) source = source.replace(orig, new)
return source return source
def replace_global_vertex(source): def replace_global_vertex(source):
source = replace_global_in(source) source = replace_global_in(source)
replace_table = [ replace_table = [
('attribute', 'COMPAT_ATTRIBUTE'), ('attribute', 'COMPAT_ATTRIBUTE'),
('varying', 'COMPAT_VARYING'), ('varying', 'COMPAT_VARYING'),
('texture2D', 'COMPAT_TEXTURE'), ('texture2D', 'COMPAT_TEXTURE'),
('POSITION', 'VertexCoord'), ('POSITION', 'VertexCoord'),
('TEXCOORD1', 'LUTTexCoord'), ('TEXCOORD1', 'LUTTexCoord'),
('TEXCOORD0', 'TexCoord'), ('TEXCOORD0', 'TexCoord'),
('TEXCOORD', 'TexCoord'), ('TEXCOORD', 'TexCoord'),
('uniform vec4 _modelViewProj1[4];', ''), ('uniform vec4 _modelViewProj1[4];', ''),
('_modelViewProj1', 'MVPMatrix'), ('_modelViewProj1', 'MVPMatrix'),
('_IN1._mvp_matrix[0]', 'MVPMatrix[0]'), ('_IN1._mvp_matrix[0]', 'MVPMatrix[0]'),
('_IN1._mvp_matrix[1]', 'MVPMatrix[1]'), ('_IN1._mvp_matrix[1]', 'MVPMatrix[1]'),
('_IN1._mvp_matrix[2]', 'MVPMatrix[2]'), ('_IN1._mvp_matrix[2]', 'MVPMatrix[2]'),
('_IN1._mvp_matrix[3]', 'MVPMatrix[3]'), ('_IN1._mvp_matrix[3]', 'MVPMatrix[3]'),
('FrameCount', 'float(FrameCount)'), ('FrameCount', 'float(FrameCount)'),
('FrameDirection', 'float(FrameDirection)'), ('FrameDirection', 'float(FrameDirection)'),
('input', 'input_dummy'), # 'input' is reserved in GLSL. ('input', 'input_dummy'), # 'input' is reserved in GLSL.
('output', 'output_dummy'), # 'output' is reserved in GLSL. ('output', 'output_dummy'), # 'output' is reserved in GLSL.
] ]
for replacement in replace_table: for orig, new in replace_table:
source = source.replace(replacement[0], replacement[1]) source = source.replace(orig, new)
return source return source
@ -110,15 +106,15 @@ def translate_varyings(varyings, source, direction):
def no_uniform(elem): def no_uniform(elem):
banned = [ banned = [
'_video_size', '_video_size',
'_texture_size', '_texture_size',
'_output_size', '_output_size',
'_output_dummy_size', '_output_dummy_size',
'_frame_count', '_frame_count',
'_frame_direction', '_frame_direction',
'_mvp_matrix', '_mvp_matrix',
'_vertex_coord', '_vertex_coord',
'sampler2D' 'sampler2D'
] ]
for ban in banned: for ban in banned:
@ -142,7 +138,7 @@ def destructify_varyings(source, direction):
struct_types = [] struct_types = []
for line in source[1:]: for line in source[1:]:
if 'struct' in line: if 'struct' in line:
struct_type = line.split(' ')[1] struct_type = line.split()[1]
if struct_type not in struct_types: if struct_type not in struct_types:
struct_types.append(struct_type) struct_types.append(struct_type)
@ -161,7 +157,7 @@ def destructify_varyings(source, direction):
lines = ['COMPAT_VARYING ' + string for string in source[(i + 1):j]] lines = ['COMPAT_VARYING ' + string for string in source[(i + 1):j]]
varyings.extend(lines) varyings.extend(lines)
names = [string.strip().split(' ')[1].split(';')[0].strip() for string in source[(i + 1):j]] names = [string.split()[1].split(';')[0].strip() for string in source[(i + 1):j]]
varyings_name.extend(names) varyings_name.extend(names)
log('Found elements in struct', struct + ':', names) log('Found elements in struct', struct + ':', names)
last_struct_decl_line = j last_struct_decl_line = j
@ -183,16 +179,13 @@ def destructify_varyings(source, direction):
# the actual varyings we just declared ... # the actual varyings we just declared ...
# Globals only come before main() ... # Globals only come before main() ...
# Make sure to only look after all struct declarations as there might be overlap. # Make sure to only look after all struct declarations as there might be overlap.
for line in source[last_struct_decl_line:]: for line in remove_comments(source[last_struct_decl_line:]):
if 'void main()' in line: if 'void main()' in line:
break break
for struct in struct_types: for struct in struct_types:
if struct in line: if struct in line:
decomment_line = line.split('//')[0].strip() variable = line.split()[1].split(';')[0]
if len(decomment_line) == 0:
continue
variable = decomment_line.split(' ')[1].split(';')[0]
# Only redirect if the struct is actually used as vertex output. # Only redirect if the struct is actually used as vertex output.
for vout_line in vout_lines: for vout_line in vout_lines:
@ -218,7 +211,7 @@ def destructify_varyings(source, direction):
for varying_name in varyings_dict: for varying_name in varyings_dict:
trans_from = variable + '.' + varying_name trans_from = variable + '.' + varying_name
trans_to = varyings_dict[varying_name] trans_to = varyings_dict[varying_name]
source[index] = source[index].replace(trans_from, trans_to); source[index] = source[index].replace(trans_from, trans_to)
for index, _ in enumerate(source): for index, _ in enumerate(source):
for varying_name in varyings_name: for varying_name in varyings_name:
@ -337,19 +330,19 @@ def replace_varyings(source):
uniforms = [] uniforms = []
for index, line in enumerate(source): for index, line in enumerate(source):
if (('//var' in line) or ('#var' in line)) and ('$vin.' in line): if (('//var' in line) or ('#var' in line)) and ('$vin.' in line):
orig = line.split(' ')[2] orig = line.split()[2]
translated = translate_varying(orig) translated = translate_varying(orig)
if translated != orig and translated not in attribs: if translated != orig and translated not in attribs:
cg_attrib = line.split(':')[2].split(' ')[1] cg_attrib = line.split(':')[2].split(' ')[1]
if len(cg_attrib.strip()) > 0: if cg_attrib:
translations.append((cg_attrib, translated)) translations.append((cg_attrib, translated))
attribs.append(translated) attribs.append(translated)
elif ('//var' in line) or ('#var' in line): elif ('//var' in line) or ('#var' in line):
orig = line.split(' ')[2] orig = line.split()[2]
translated = translate_texture_size(orig) translated = translate_texture_size(orig)
if translated != orig and translated not in uniforms: if translated != orig and translated not in uniforms:
cg_uniform = line.split(':')[2].split(' ')[1] cg_uniform = line.split(':')[2].split(' ')[1]
if len(cg_uniform.strip()) > 0: if cg_uniform:
translations.append((cg_uniform, translated)) translations.append((cg_uniform, translated))
uniforms.append(translated) uniforms.append(translated)
@ -372,6 +365,51 @@ def replace_varyings(source):
return ret return ret
def fix_samplers(log_prefix, ref_index, source):
translations = []
added_samplers = []
translated_samplers = []
uniforms = []
struct_texunit0 = False # If True, we have to append uniform sampler2D Texture manually ...
for line in source:
if ('TEXUNIT0' in line) and ('semantic' not in line):
main_sampler = (line.split(':')[2].split(' ')[1], 'Texture')
if main_sampler[0]:
translations.append(main_sampler)
log(log_prefix, 'Sampler:', main_sampler[0], '->', main_sampler[1])
struct_texunit0 = '.' in main_sampler[0]
elif ('//var sampler2D' in line) or ('#var sampler2D' in line):
cg_texture = line.split()[2]
translated = translate_texture(cg_texture)
orig_name = translated
new_name = line.split(':')[2].split(' ')[1]
log(log_prefix, 'Sampler:', new_name, '->', orig_name)
if new_name:
if translated != cg_texture and translated not in translated_samplers:
translated_samplers.append(translated)
added_samplers.append('uniform sampler2D ' + translated + ';')
translations.append((new_name, orig_name))
elif ('//var' in line) or ('#var' in line):
orig = line.split()[2]
translated = translate_texture_size(orig)
if translated != orig and translated not in uniforms:
cg_uniform = line.split(':')[2].split(' ')[1]
if cg_uniform:
translations.append((cg_uniform, translated))
uniforms.append(translated)
for sampler in added_samplers:
source.insert(ref_index, sampler)
if struct_texunit0:
source.insert(ref_index, 'uniform sampler2D Texture;')
for index, line in enumerate(source):
for orig, new in translations:
log(log_prefix, 'Translation:', orig, '->', new)
source[index] = source[index].replace(orig, new)
return source
def hack_source_vertex(source): def hack_source_vertex(source):
ref_index = 0 ref_index = 0
for index, line in enumerate(source): for index, line in enumerate(source):
@ -387,37 +425,7 @@ def hack_source_vertex(source):
break break
# Fix samplers in vertex shader (supported by GLSL). # Fix samplers in vertex shader (supported by GLSL).
translations = [] source = fix_samplers('Vertex:', ref_index, source)
added_samplers = []
translated_samplers = []
struct_texunit0 = False # If True, we have to append uniform sampler2D Texture manually ...
for line in source:
if ('TEXUNIT0' in line) and ('semantic' not in line):
main_sampler = (line.split(':')[2].split(' ')[1], 'Texture')
if len(main_sampler[0]) > 0:
translations.append(main_sampler)
log('Vertex: Sampler:', main_sampler[0], '->', main_sampler[1])
struct_texunit0 = '.' in main_sampler[0]
elif ('//var sampler2D' in line) or ('#var sampler2D' in line):
cg_texture = line.split(' ')[2]
translated = translate_texture(cg_texture)
orig_name = translated
new_name = line.split(':')[2].split(' ')[1]
log('Vertex: Sampler:', new_name, '->', orig_name)
if len(new_name) > 0:
if translated != cg_texture and translated not in translated_samplers:
translated_samplers.append(translated)
added_samplers.append('uniform sampler2D ' + translated + ';')
translations.append((new_name, orig_name))
for sampler in added_samplers:
source.insert(ref_index, sampler)
if struct_texunit0:
source.insert(ref_index, 'uniform sampler2D Texture;')
for index, line in enumerate(source):
for translation in translations:
source[index] = source[index].replace(translation[0], translation[1])
source = destructify_varyings(source, '$vout.') source = destructify_varyings(source, '$vout.')
source = replace_varyings(source) source = replace_varyings(source)
return source return source
@ -426,13 +434,13 @@ def hack_source_vertex(source):
def replace_global_fragment(source): def replace_global_fragment(source):
source = replace_global_in(source) source = replace_global_in(source)
replace_table = [ replace_table = [
('varying', 'COMPAT_VARYING'), ('varying', 'COMPAT_VARYING'),
('texture2D', 'COMPAT_TEXTURE'), ('texture2D', 'COMPAT_TEXTURE'),
('FrameCount', 'float(FrameCount)'), ('FrameCount', 'float(FrameCount)'),
('FrameDirection', 'float(FrameDirection)'), ('FrameDirection', 'float(FrameDirection)'),
('input', 'input_dummy'), ('input', 'input_dummy'),
('output', 'output_dummy'), # 'output' is reserved in GLSL. ('output', 'output_dummy'), # 'output' is reserved in GLSL.
('gl_FragColor', 'FragColor'), ('gl_FragColor', 'FragColor'),
] ]
for replacement in replace_table: for replacement in replace_table:
@ -487,54 +495,9 @@ def hack_source_fragment(source):
ref_index = index ref_index = index
break break
translations = [] source = fix_samplers('Fragment:', ref_index, source)
added_samplers = [] source = destructify_varyings(source, '$vin.')
translated_samplers = [] return source
uniforms = []
struct_texunit0 = False # If True, we have to append uniform sampler2D Texture manually ...
for line in source:
if ('TEXUNIT0' in line) and ('semantic' not in line):
main_sampler = (line.split(':')[2].split(' ')[1], 'Texture')
if len(main_sampler[0]) > 0:
translations.append(main_sampler)
log('Fragment: Sampler:', main_sampler[0], '->', main_sampler[1])
struct_texunit0 = '.' in main_sampler[0]
elif ('//var sampler2D' in line) or ('#var sampler2D' in line):
cg_texture = line.split(' ')[2]
translated = translate_texture(cg_texture)
orig_name = translated
new_name = line.split(':')[2].split(' ')[1]
log('Fragment: Sampler:', new_name, '->', orig_name)
if len(new_name) > 0:
if translated != cg_texture and translated not in translated_samplers:
translated_samplers.append(translated)
added_samplers.append('uniform sampler2D ' + translated + ';')
translations.append((new_name, orig_name))
elif ('//var' in line) or ('#var' in line):
orig = line.split(' ')[2]
translated = translate_texture_size(orig)
if translated != orig and translated not in uniforms:
cg_uniform = line.split(':')[2].split(' ')[1]
if len(cg_uniform.strip()) > 0:
translations.append((cg_uniform, translated))
uniforms.append(translated)
for sampler in added_samplers:
source.insert(ref_index, sampler)
for uniform in uniforms:
source.insert(ref_index, 'uniform COMPAT_PRECISION vec2 ' + uniform + ';')
if struct_texunit0:
source.insert(ref_index, 'uniform sampler2D Texture;')
ret = []
for line in source:
for translation in translations:
log('Translation:', translation[0], '->', translation[1])
line = line.replace(translation[0], translation[1])
ret.append(line)
ret = destructify_varyings(ret, '$vin.')
return ret
def validate_shader(source, target): def validate_shader(source, target):