Implement python script to remove wine requirement
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
This commit is contained in:
parent
74224a6077
commit
a10cd3c227
291
tools/sc/FidelityFX_SC.py
Executable file
291
tools/sc/FidelityFX_SC.py
Executable file
|
@ -0,0 +1,291 @@
|
||||||
|
#!/bin/python
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import mmap
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
def hash_file(path):
|
||||||
|
algorithm = hashlib.md5()
|
||||||
|
with open(path, 'rb') as file:
|
||||||
|
with mmap.mmap(file.fileno(), 0, prot=mmap.PROT_READ) as memory:
|
||||||
|
algorithm.update(memory)
|
||||||
|
return algorithm.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def append_resources(code, name, data, key, resource_name):
|
||||||
|
if not key in data:
|
||||||
|
return
|
||||||
|
|
||||||
|
for res in data[key]:
|
||||||
|
if res['name'][-2:] == '_t':
|
||||||
|
res['name'] = res['name'][:-2]
|
||||||
|
|
||||||
|
data[key].sort(key=lambda res: res['binding'])
|
||||||
|
|
||||||
|
code.append('static const char* g_{0}_{1}ResourceNames[] ='.format(name, resource_name))
|
||||||
|
code.append('{ ' + ', '.join(['"{0}"'.format(res['name']) for res in data[key]]) + ', };')
|
||||||
|
code.append('static const uint32_t g_{0}_{1}ResourceBindings[] ='.format(name, resource_name))
|
||||||
|
code.append('{ ' + ', '.join([str(res['binding']) for res in data[key]]) + ', };')
|
||||||
|
code.append('static const uint32_t g_{0}_{1}ResourceCounts[] ='.format(name, resource_name))
|
||||||
|
code.append('{ ' + ', '.join(['1' for res in data[key]]) + ', };')
|
||||||
|
code.append('static const uint32_t g_{0}_{1}ResourceSets[] ='.format(name, resource_name))
|
||||||
|
code.append('{ ' + ', '.join([str(res['set']) for res in data[key]]) + ', };')
|
||||||
|
code.append('')
|
||||||
|
|
||||||
|
|
||||||
|
def process(file, name, args, output, optimization, reflection):
|
||||||
|
spirv_path = os.path.join(output, name + '.spv')
|
||||||
|
subprocess.run(['glslangValidator', '-V', *args, '-o', spirv_path, file])
|
||||||
|
|
||||||
|
if optimization:
|
||||||
|
optimized_spirv_path = spirv_path + '_opt'
|
||||||
|
subprocess.run(['spirv-opt', '-Os', spirv_path, '-o', optimized_spirv_path])
|
||||||
|
os.rename(optimized_spirv_path, spirv_path)
|
||||||
|
|
||||||
|
spirv_hash = hash_file(spirv_path)
|
||||||
|
name = '{0}_{1}'.format(name, str(spirv_hash))
|
||||||
|
hash_path = os.path.join(output, name + '.spv')
|
||||||
|
|
||||||
|
if os.path.exists(hash_path):
|
||||||
|
os.remove(spirv_path)
|
||||||
|
return name, dict()
|
||||||
|
else:
|
||||||
|
os.rename(spirv_path, hash_path)
|
||||||
|
spirv_path = hash_path
|
||||||
|
|
||||||
|
spirv = list()
|
||||||
|
with open(spirv_path, 'rb') as spirv_file:
|
||||||
|
spirv = list(spirv_file.read())
|
||||||
|
|
||||||
|
data = dict()
|
||||||
|
if reflection:
|
||||||
|
json_path = os.path.join(output, name + '.json')
|
||||||
|
subprocess.run(['spirv-cross', '-V', spirv_path, '--reflect', '--output', json_path])
|
||||||
|
|
||||||
|
with open(json_path) as json_file:
|
||||||
|
data = json.load(json_file)
|
||||||
|
|
||||||
|
os.remove(json_path)
|
||||||
|
|
||||||
|
code = ['// {0}.h.'.format(name), '// Auto generated by FidelityFX-SC.py.', '']
|
||||||
|
|
||||||
|
append_resources(code, name, data, 'separate_samplers', 'Sampler')
|
||||||
|
append_resources(code, name, data, 'combined_samplers', 'CombinedSampler')
|
||||||
|
append_resources(code, name, data, 'separate_images', 'SampledImage')
|
||||||
|
append_resources(code, name, data, 'images', 'StorageImage')
|
||||||
|
append_resources(code, name, data, 'uniform_texel_buffers', 'UniformTexelBuffer')
|
||||||
|
append_resources(code, name, data, 'storage_texel_buffers', 'StorageTexelBuffer')
|
||||||
|
append_resources(code, name, data, 'ubos', 'UniformBuffer')
|
||||||
|
append_resources(code, name, data, 'sbos', 'StorageBuffer')
|
||||||
|
append_resources(code, name, data, 'inputs', 'InputAttachment')
|
||||||
|
append_resources(code, name, data, 'acceleration_structures', 'AccelerationStructure')
|
||||||
|
|
||||||
|
code.append('static const uint32_t g_{0}_size = {1};'.format(name, len(spirv)))
|
||||||
|
code.append('')
|
||||||
|
code.append('static const unsigned char g_{0}_data[] = '.format(name) + '{')
|
||||||
|
|
||||||
|
for i in range(0, len(spirv), 16):
|
||||||
|
line = ','.join(map('0x{0:02x}'.format, spirv[i:i + 16]))
|
||||||
|
if i + 16 < len(spirv):
|
||||||
|
line = line + ','
|
||||||
|
code.append(line)
|
||||||
|
|
||||||
|
code.append('};')
|
||||||
|
code_path = os.path.join(output, name + '.h')
|
||||||
|
with open(code_path, 'w') as code_file:
|
||||||
|
code_file.write('\n'.join(code))
|
||||||
|
|
||||||
|
return name, data
|
||||||
|
|
||||||
|
|
||||||
|
def append_resources_info(code, resources_name, resource_name):
|
||||||
|
code.append('\tconst uint32_t num{0}Resources;'.format(resources_name))
|
||||||
|
code.append('\tconst char** {0}ResourceNames;'.format(resource_name))
|
||||||
|
code.append('\tconst uint32_t* {0}ResourceBindings;'.format(resource_name))
|
||||||
|
code.append('\tconst uint32_t* {0}ResourceCounts;'.format(resource_name))
|
||||||
|
code.append('\tconst uint32_t* {0}ResourceSets;'.format(resource_name))
|
||||||
|
code.append('')
|
||||||
|
|
||||||
|
|
||||||
|
def append_info_resource(code, name, data, key, resource_name):
|
||||||
|
if key in data:
|
||||||
|
code.append('\t\t{0},'.format(str(len(data[key]))))
|
||||||
|
code.append('\t\tg_{0}_{1}ResourceNames,'.format(name, resource_name))
|
||||||
|
code.append('\t\tg_{0}_{1}ResourceBindings,'.format(name, resource_name))
|
||||||
|
code.append('\t\tg_{0}_{1}ResourceCounts,'.format(name, resource_name))
|
||||||
|
code.append('\t\tg_{0}_{1}ResourceSets,'.format(name, resource_name))
|
||||||
|
else:
|
||||||
|
code.append('\t\t0, 0, 0, 0, 0,')
|
||||||
|
|
||||||
|
|
||||||
|
def append_info(code, name, data):
|
||||||
|
code.append('\t{')
|
||||||
|
code.append('\t\tg_{0}_size,'.format(name))
|
||||||
|
code.append('\t\tg_{0}_data,'.format(name))
|
||||||
|
|
||||||
|
append_info_resource(code, name, data, 'separate_samplers', 'Sampler')
|
||||||
|
append_info_resource(code, name, data, 'combined_samplers', 'CombinedSampler')
|
||||||
|
append_info_resource(code, name, data, 'separate_images', 'SampledImage')
|
||||||
|
append_info_resource(code, name, data, 'images', 'StorageImage')
|
||||||
|
append_info_resource(code, name, data, 'uniform_texel_buffers', 'UniformTexelBuffer')
|
||||||
|
append_info_resource(code, name, data, 'storage_texel_buffers', 'StorageTexelBuffer')
|
||||||
|
append_info_resource(code, name, data, 'ubos', 'UniformBuffer')
|
||||||
|
append_info_resource(code, name, data, 'ssbos', 'StorageBuffer')
|
||||||
|
append_info_resource(code, name, data, 'inputs', 'InputAttachment')
|
||||||
|
append_info_resource(code, name, data, 'acceleration_structures', 'AccelerationStructure')
|
||||||
|
|
||||||
|
code.append('\t},')
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
permutations = list()
|
||||||
|
permutations.append(list())
|
||||||
|
permutation_variables = list()
|
||||||
|
|
||||||
|
for definition in args.definitions:
|
||||||
|
name, value = definition.split('=')
|
||||||
|
|
||||||
|
if value[0] == '{' and value[-1] == '}':
|
||||||
|
values = value[1:-1].split(',')
|
||||||
|
new_permutations = list()
|
||||||
|
permutation_variables.append(name)
|
||||||
|
|
||||||
|
for val in values:
|
||||||
|
for permutation in permutations:
|
||||||
|
new_permutation = permutation.copy()
|
||||||
|
new_permutation.append("-D{0}={1}".format(name, val))
|
||||||
|
new_permutations.append(new_permutation)
|
||||||
|
|
||||||
|
permutations = new_permutations
|
||||||
|
else:
|
||||||
|
for permutation in permutations:
|
||||||
|
permutation.append("-D{0}={1}".format(name, value))
|
||||||
|
|
||||||
|
for permutation in permutations:
|
||||||
|
permutation.append('-e')
|
||||||
|
permutation.append(args.entry_point)
|
||||||
|
permutation.append('-I{0}'.format(args.includes))
|
||||||
|
permutation.append('-S')
|
||||||
|
permutation.append(args.stage)
|
||||||
|
permutation.append('--target-env')
|
||||||
|
permutation.append(args.target_env)
|
||||||
|
|
||||||
|
if args.undefinitions is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for undefinition in args.undefinitions:
|
||||||
|
permutation.append("-U{0}".format(undefinition))
|
||||||
|
|
||||||
|
optimization = (args.optimization == 's')
|
||||||
|
for j, file in enumerate(args.files):
|
||||||
|
if len(args.files) == 1:
|
||||||
|
file_name = args.name
|
||||||
|
else:
|
||||||
|
file_name = '{0}_{1}'.format(args.name, str(j))
|
||||||
|
|
||||||
|
if len(permutations) > 0:
|
||||||
|
code_name = '{0}_permutations.h'.format(file_name)
|
||||||
|
else:
|
||||||
|
code_name = '{0}.h'.format(file_name)
|
||||||
|
|
||||||
|
code = list()
|
||||||
|
code_path = os.path.join(args.output, code_name)
|
||||||
|
|
||||||
|
names = list()
|
||||||
|
datas = list()
|
||||||
|
for i, permutation in enumerate(permutations):
|
||||||
|
name, data = process(file, file_name, permutation, args.output, optimization, args.reflection)
|
||||||
|
names.append(name)
|
||||||
|
datas.append(data)
|
||||||
|
|
||||||
|
for name in names:
|
||||||
|
spirv_path = os.path.join(args.output, name + '.spv')
|
||||||
|
if os.path.exists(spirv_path):
|
||||||
|
os.remove(spirv_path)
|
||||||
|
|
||||||
|
infos = list()
|
||||||
|
indices = [names.index(name) for name in names]
|
||||||
|
indirections = list()
|
||||||
|
|
||||||
|
for i, index in enumerate(indices):
|
||||||
|
if i == index:
|
||||||
|
code.append('#include "{0}.h"'.format(names[index]))
|
||||||
|
indirections.append(len(infos))
|
||||||
|
infos.append({ 'name': names[index], 'data': datas[index] })
|
||||||
|
else:
|
||||||
|
indirections.append(None)
|
||||||
|
|
||||||
|
for i, index in enumerate(indices):
|
||||||
|
if indirections[i] is None:
|
||||||
|
indirections[i] = indirections[index]
|
||||||
|
|
||||||
|
code.append('')
|
||||||
|
code.append('typedef union {0}_PermutationKey '.format(file_name) + '{')
|
||||||
|
code.append('\tstruct {')
|
||||||
|
|
||||||
|
for variable in permutation_variables:
|
||||||
|
code.append('\t\tuint32_t {0} : 1;'.format(variable))
|
||||||
|
|
||||||
|
code.append('\t};')
|
||||||
|
code.append('\tuint32_t index;')
|
||||||
|
code.append('}' + ' {0}_PermutationKey;'.format(file_name))
|
||||||
|
code.append('')
|
||||||
|
|
||||||
|
code.append('typedef struct {0}_PermutationInfo '.format(file_name) + '{')
|
||||||
|
code.append('\tconst uint32_t blobSize;')
|
||||||
|
code.append('\tconst unsigned char* blobData;')
|
||||||
|
code.append('')
|
||||||
|
|
||||||
|
append_resources_info(code, 'Sampler', 'sampler')
|
||||||
|
append_resources_info(code, 'CombinedSampler', 'combinedSampler')
|
||||||
|
append_resources_info(code, 'SampledImage', 'sampledImage')
|
||||||
|
append_resources_info(code, 'StorageImage', 'storageImage')
|
||||||
|
append_resources_info(code, 'UniformTexelBuffer', 'uniformTexelBuffer')
|
||||||
|
append_resources_info(code, 'StorageTexelBuffer', 'storageTexelBuffer')
|
||||||
|
append_resources_info(code, 'UniformBuffer', 'uniformBuffer')
|
||||||
|
append_resources_info(code, 'StorageBuffer', 'storageBuffer')
|
||||||
|
append_resources_info(code, 'InputAttachment', 'inputAttachment')
|
||||||
|
append_resources_info(code, 'RTAccelerationStructure', 'rtAccelerationStructure')
|
||||||
|
|
||||||
|
code.append('}' + ' {0}_PermutationInfo;'.format(file_name))
|
||||||
|
code.append('')
|
||||||
|
|
||||||
|
code.append('static const uint32_t g_{0}_IndirectionTable[] = '.format(file_name) + '{')
|
||||||
|
for index in indirections:
|
||||||
|
code.append('\t{0},'.format(index))
|
||||||
|
code.append('};')
|
||||||
|
code.append('')
|
||||||
|
|
||||||
|
code.append('static const {0}_PermutationInfo g_{0}_PermutationInfo[] = '.format(file_name) + '{')
|
||||||
|
for info in infos:
|
||||||
|
append_info(code, info['name'], info['data'])
|
||||||
|
code.append('};')
|
||||||
|
|
||||||
|
with open(code_path, 'w') as code_file:
|
||||||
|
code_file.write('\n'.join(code))
|
||||||
|
|
||||||
|
with open(code_path + '.d', 'w') as code_file:
|
||||||
|
code_file.write('{0}:'.format(code_name))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('files', metavar='FILE', type=str, nargs='+')
|
||||||
|
parser.add_argument('-compiler', choices=['glslang'])
|
||||||
|
parser.add_argument('-deps', choices=['gcc'])
|
||||||
|
parser.add_argument('-D', action='append', dest='definitions')
|
||||||
|
parser.add_argument('-e', dest='entry_point')
|
||||||
|
parser.add_argument('-I', dest='includes')
|
||||||
|
parser.add_argument('-name')
|
||||||
|
parser.add_argument('-O', choices=['d', 's'], dest='optimization')
|
||||||
|
parser.add_argument('-output')
|
||||||
|
parser.add_argument('-reflection', action='store_true')
|
||||||
|
parser.add_argument('-S', dest='stage')
|
||||||
|
parser.add_argument('--target-env', dest='target_env')
|
||||||
|
parser.add_argument('-U', action='append', dest='undefinitions')
|
||||||
|
main(parser.parse_args())
|
||||||
|
|
|
@ -1,2 +1,7 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
wine $(dirname "$0")/FidelityFX_SC.exe $@
|
|
||||||
|
### Run the original binary via wine:
|
||||||
|
# wine $(dirname "$0")/FidelityFX_SC.exe $@
|
||||||
|
|
||||||
|
### Run the reverse-engineered python script:
|
||||||
|
python $(dirname $0)/FidelityFX_SC.py $@
|
||||||
|
|
Loading…
Reference in New Issue
Block a user