def __init__(self, args): self.output = args.output self.reader = trace_reader.TraceReader(args.trace) self.src = Source() self.context_map = {} self.next_id = 0 self.ctx = None self.call_index = 0 self.enable_png_texture_dump = args.png_textures
def main(): # TODO deduplicate with gen2 parser = argparse.ArgumentParser() parser.add_argument('build_dir') parser.add_argument('source_dir') args = parser.parse_args() path = os.path.join(args.build_dir, 'glmeta.py') functions, enums = load_glinfo(args) with open(path, 'w') as wfile: src = Source() src.add('from pumpkinpy.types import Function, Param, Type') src.add('FUNCTIONS = (') for func in functions: src.add(' {},'.format(func)) src.add(')') src.add('ENUMS = {') for key, value in enums.items(): src.add(" '{}': {},".format(key, value)) src.add('}') for key, value in enums.items(): src.add('{} = {}'.format(key, value)) wfile.write(src.text())
def gen_dump_cc(): # Yes, this is Python code that generates C++ code that generates # C++ code. I'm sorry :( src = Source() src.add_cxx_include('pumpkintown_dump.hh') src.add_cxx_include('cstdio', system=True) src.add_cxx_include('pumpkintown_gl_enum.hh') src.add_cxx_include('pumpkintown_function_structs.hh') src.add_cxx_include('pumpkintown_function_id.hh') src.add('namespace pumpkintown {') src.add('void Dump::dump_one() {') src.add(' switch (iter_.function_id()) {') src.add(' case FunctionId::Invalid:') src.add(' break;') for func in FUNCTIONS: src.add(' case FunctionId::{}:'.format(func.name)) if not func.is_replayable(): src.add(' break;') continue if func.custom_io: src.add(' break;') continue src.add(' {') if func.params: src.add(' {} fn;'.format(func.cxx_struct_name())) src.add(' fn.read(iter_.file());') args = [] placeholders = [] src.add(' printf("{\\n");') for param in func.params: if param.array: src.add(' printf(" const {} {}[] = {{\\n");'.format( param.array, param.name)) src.add(' for (uint64_t i = 0; i < fn.{}_length; i++) {{'.format( param.name)) src.add(' printf(" {},\\n", fn.{}[i]);'.format( param.array_element_printf(), param.name)) src.add(' }') src.add(' printf(" }\\n");') placeholders.append(param.name) elif param.ptype.ctype == 'GLenum': args.append('lookup_gl_enum_string(fn.{})'.format(param.name)) placeholders.append('%s') else: args.append('fn.{}'.format(param.name)) placeholders.append(param.ptype.printf) src.add(' printf(" {}({});\\n"{}{});'.format( func.name, ', '.join(placeholders), ', ' if func.params else '', ', '.join(args))) src.add(' printf("}\\n");') src.add(' break;') src.add(' }') src.add(' }') src.add('}') src.add('}') return src
def gen_any_header(): types = [AnyType('bool'), AnyType('char'), AnyType('float'), AnyType('double')] for num in (8, 16, 32, 64): types.append(AnyType('int{}_t'.format(num))) types.append(AnyType('uint{}_t'.format(num))) src = Source() src.add_cxx_include('cstdint', system=True) src.add_cxx_include('sstream', system=True) src.add_cxx_include('string', system=True) src.add('class Any {') src.add(' public:') src.add(' enum class Type {') for typ in types: src.add(' {},'.format(typ.enum_name)) src.add(' };') # Constructors src.add(' Any() = default;') for typ in types: src.add(' Any(const {} value) : type_(Type::{}) {{'.format( typ.ctype, typ.enum_name)) src.add(' value_.{} = value;'.format(typ.union_name)) src.add(' }') # Accessors for typ in types: src.add(' {} as_{}() const {{'.format(typ.ctype, typ.short_name)) src.add(' if (type_ != Type::{}) {{'.format(typ.enum_name)) src.add(' throw std::runtime_error("wrong Any type");') src.add(' }') src.add(' return value_.{};'.format(typ.union_name)) src.add(' }') # String conversion src.add(' std::string to_string() const {') src.add(' std::ostringstream ss;') src.add(' switch (type_) {') for typ in types: src.add(' case Type::{}:'.format(typ.enum_name)) src.add(' ss << value_.{};'.format(typ.union_name)) src.add(' return ss.str();') src.add(' }') src.add(' return "error";') src.add(' }') src.add(' private:') # Union src.add(' union {') for typ in types: src.add(' {} {};'.format(typ.ctype, typ.union_name)) src.add(' } value_;') # Discriminator src.add(' Type type_;') src.add('};') src.add_guard('PUMPKINTOWN_ANY_HH_') return src
def gen_express_source(): src = Source() src.add_cxx_include('epoxy/egl.h', system=True) src.add_cxx_include('epoxy/gl.h', system=True) src.add_cxx_include('pumpkintown_express.hh') src.add('namespace pumpkintown {') src.add('void Express::dispatch() {') for func in FUNCTIONS: if not func.is_replayable(): continue # TODO if func.name in ('glBindShadingRateImageNV', 'glBufferAttachMemoryNV', 'glDrawMeshTasksIndirectNV', 'glDrawMeshTasksNV', 'glFramebufferFetchBarrierEXT', 'glMultiDrawMeshTasksIndirectCountNV', 'glMultiDrawMeshTasksIndirectNV', 'glNamedBufferAttachMemoryNV', 'glNamedRenderbufferStorageMultisampleAdvancedAMD', 'glRenderbufferStorageMultisampleAdvancedAMD', 'glResetMemoryObjectParameterNV', 'glScissorExclusiveNV', 'glShadingRateImageBarrierNV', 'glShadingRateSampleOrderNV', 'glTexAttachMemoryNV', 'glTextureAttachMemoryNV'): continue if func.name in ('eglCreateContext', 'eglMakeCurrent'): continue if func.name.startswith('glX'): continue src.add(' if (iter_.function() == "{}") {{'.format(func.name)) if func.name == 'glShaderSource': src.add(' shader_source();') else: if func.name.startswith('glGen'): src.add(' uint32_arrays_[arg(1)] = ' 'std::vector<uint32_t>{};') src.add(' uint32_arrays_[arg(1)].resize(to_uint32(arg(0)));') args = [] for index, param in enumerate(func.params): arg = 'arg({})'.format(index) stype = param.ptype.stype if param.array: args.append('{} == "null" ? nullptr : ' '{}_arrays_.at({}).data()'.format( arg, param.array.replace('_t', ''), arg)) elif param.offset: args.append('to_offset({})'.format(arg)) elif stype and stype != 'const void*': args.append('to_{}({})'.format( stype.replace('_t', ''), arg)) args = ', '.join(args) capture = '' if func.has_return(): capture = 'vars_[iter_.return_value()] = ' src.add(' {}{}({});'.format(capture, func.name, args)) src.add(' return;') src.add(' }') src.add(' if (iter_.function() == "context_create") {') src.add(' create_context();') src.add(' return;') src.add(' }') src.add(' if (iter_.function() == "make_current") {') src.add(' make_context_current();') src.add(' return;') src.add(' }') src.add(' fprintf(stderr, "unhandled function: %s\\n", iter_.function().c_str());') src.add('}') src.add('}') return src
def gen_replay_source(): src = Source() src.add_cxx_include('pumpkintown_replay.hh') src.add_cxx_include('vector', system=True) src.add_cxx_include('waffle-1/waffle.h', system=True) src.add_cxx_include('pumpkintown_function_id.hh') src.add_cxx_include('pumpkintown_function_structs.hh') src.add_cxx_include('pumpkintown_gl_functions.hh') src.add_cxx_include('pumpkintown_gl_types.hh') src.add('namespace pumpkintown {') src.add('void Replay::replay_one() {') src.add(' switch (iter_.function_id()) {') src.add(' case FunctionId::Invalid:') src.add(' break;') for func in FUNCTIONS: src.add(' case FunctionId::{}:'.format(func.name)) if func.no_replay: src.add(' iter_.skip();') src.add(' break;') if func.name == 'glXSwapBuffers': src.add(' printf("{}\\n");'.format(func.name)) src.add(' waffle_window_swap_buffers(window_);') src.add(' break;') continue elif not func.is_replayable(): src.add(' printf("{}\\n");'.format(func.name)) src.add(' printf("stub\\n");') src.add(' break;') continue src.add(' {') if not func.is_empty(): src.add(' {} fn;'.format(func.cxx_struct_name())) src.add(' fn.read_from_file(iter_.file());') src.add(' printf("%s\\n", fn.to_string().c_str());') if func.custom_replay: src.add(' custom_{}(fn);'.format(func.name)) else: src.add(' {}({});'.format( func.name, ', '.join('fn.' + param.name for param in func.params))) src.add(' break;') src.add(' }') src.add(' }') src.add('}') src.add('}') return src
def gen_gl_functions_source(): src = Source() src.add_cxx_include('pumpkintown_gl_functions.hh') src.add_cxx_include('waffle-1/waffle.h', system=True) src.add('namespace pumpkintown {') for func in FUNCTIONS: src.add('{} {}({}) {{'.format( func.return_type.ctype, func.name, ', '.join(param.cxx() for param in func.params))) src.add(func.cxx_function_type_alias()) src.add(' Fn fn = reinterpret_cast<Fn>(waffle_get_proc_address("{}"));'.format( func.name)) src.add(' {}fn({});'.format( 'return ' if func.has_return() else '', ', '.join(param.name for param in func.params))) src.add('}') src.add('}') return src
def gen_trace_source(): src = Source() src.add_cxx_include('pumpkintown_trace_gen.hh') src.add_cxx_include('cstring', system=True) src.add_cxx_include('mutex', system=True) src.add_cxx_include('pumpkintown_function_structs.hh') src.add_cxx_include('pumpkintown_dlib.hh') src.add_cxx_include('pumpkintown_serialize.hh') src.add_cxx_include('pumpkintown_trace.hh') src.add(' static std::mutex mutex;') for func in FUNCTIONS: src.add('{} {{'.format(func.cxx_decl())) if True: src.add(' pumpkintown::print_tids();') if True: src.add(' fprintf(stderr, "{}\\n");'.format(func.name)) # Call the real function and capture its return value if it has one src.add(' {}pumpkintown::real::{}({});'.format( 'auto return_value = ' if func.has_return() else '', func.name, ', '.join(param.name for param in func.params))) # Optional custom actions if func.trace_append: src.add(' pumpkintown::trace_append_{}({});'.format( func.name, func.cxx_call_args())) src.add(' std::lock_guard<std::mutex> lock(mutex);') # Store the function ID src.add(' pumpkintown::begin_message("{}");'.format( func.name)) if func.is_replayable() and not func.is_empty(): src.add(' pumpkintown::{} fn;'.format(func.cxx_struct_name())) if func.has_return() and func.return_type.stype: src.add(' fn.return_value = return_value;') for param in func.params: if param.array: src.add(' fn.{0} = reinterpret_cast<const {1}*>({0});'.format( param.name, param.array)) else: src.add(' fn.{0} = {0};'.format(param.name)) if func.has_array_params() and not func.custom_io: src.add(' fn.finalize();') src.add(' pumpkintown::serialize()->write(fn.num_bytes());') src.add(' fn.write_to_file(pumpkintown::serialize()->file());') # Prevent double free for param in func.params: if param.array: src.add(' fn.{} = nullptr;'.format(param.name)) else: src.add(' pumpkintown::serialize()->write(static_cast<uint64_t>(0));') # Return the real function's result if it has one if func.has_return(): src.add(' return return_value;') src.add('}') src.add('extern "C" void* glXGetProcAddress(const char* name) {') for func in FUNCTIONS: src.add(' if (strcmp(name, "{}") == 0) {{'.format(func.name)) src.add(' return reinterpret_cast<void*>(&{});'.format(func.name)) src.add(' }') src.add(' fprintf(stderr, "unknown function: %s\\n", name);') src.add(' return nullptr;') src.add('}') src.add('extern "C" void* glXGetProcAddressARB(const char* name) {') src.add(' return glXGetProcAddress(name);') src.add('}') # Add pumpkintown::real:: implementations src.add('namespace pumpkintown {') src.add('namespace real {') for func in FUNCTIONS: src.add('{} {{'.format(func.cxx_decl())) # Declare Function pointer type src.add(' ' + func.cxx_function_type_alias()) # Static function pointer to the "real" call src.add(' static Fn real_fn = reinterpret_cast<Fn>(get_real_proc_addr("{}"));'.format(func.name)) # Call the real function and return its value if it has one src.add(' {}real_fn({});'.format( 'return ' if func.has_return() else '', ', '.join(param.name for param in func.params))) src.add('}') src.add('}') src.add('}') return src
def gen_function_structs_source(): src = Source() src.add_cxx_include('pumpkintown_function_structs.hh') src.add_cxx_include('sstream', system=True) src.add_cxx_include('pumpkintown_gl_enum.hh') src.add_cxx_include('pumpkintown_gl_util.hh') src.add_cxx_include('pumpkintown_io.hh') src.add('namespace pumpkintown {') # TODO(nicholasbishop): currently the format is a little # inefficient for pointers. We read and write them as part of # the struct, but the actual values aren't used. # # TODO(nicholasbishop): byte order for func in FUNCTIONS: if not func.is_replayable() or func.is_empty(): continue if func.custom_io: continue if func.has_array_params(): src.add('{0}::~{0}() {{'.format(func.cxx_struct_name())) for param in func.params: if param.array: src.add(' delete[] {};'.format(param.name)) src.add('}') src.add('uint64_t {}::num_bytes() const {{'.format(func.cxx_struct_name())) size_args = ['sizeof(*this)'] for param in func.params: if param.array: size_args.append('({0}_length * sizeof(*{0}))'.format(param.name)) src.add(' return {};'.format(' + '.join(size_args))) src.add('}') src.add('std::string {}::to_string() const {{'.format(func.cxx_struct_name())) src.add(' std::string result = "{}(";'.format(func.name)) first = True for param in func.params: if first: first = False else: src.add(' result += ", ";') if param.array: pass elif param.custom_print: src.add(' result += {}({});'.format( param.custom_print, param.name)) elif param.offset: src.add(' {') src.add(' std::ostringstream oss;') src.add(' oss << {};'.format(param.name)) src.add(' result += oss.str();') src.add(' }') elif param.ptype.ctype == 'GLenum': src.add(' result += lookup_gl_enum_string({});'.format(param.name)) else: src.add(' result += pumpkintown::to_string({});'.format(param.name)) src.add(' std::string return_string;') if func.has_return(): src.add(' return_string = " -> " + pumpkintown::to_string(return_value);') src.add(' return result + ")" + return_string;'.format(func.name)) src.add('}') src.add('void {}::read_from_file(FILE* f) {{'.format(func.cxx_struct_name())) src.add(' read_exact(f, this, sizeof(*this));') for param in func.params: if param.array: src.add(' if ({}_length > 0) {{'.format(param.name)) src.add(' {0}* {1}_tmp = new {0}[{1}_length];'.format( param.array, param.name)) src.add(' read_exact(f, {0}_tmp, {0}_length * sizeof(*{0}));'.format( param.name)) src.add(' {0} = {0}_tmp;'.format(param.name)) src.add(' } else {') src.add(' {} = nullptr;'.format(param.name)) src.add(' }') src.add('}') src.add('void {}::write_to_file(FILE* f) {{'.format(func.cxx_struct_name())) src.add(' write_exact(f, this, sizeof(*this));') for param in func.params: if param.array: src.add(' write_exact(f, {0}, {0}_length * sizeof(*{0}));'.format( param.name)) src.add(' fflush(f);') src.add('}') src.add('}') return src
def gen_function_structs_header(): src = Source() src.add_cxx_include('cstdio', system=True) src.add_cxx_include('cstdint', system=True) src.add_cxx_include('string', system=True) src.add('namespace pumpkintown {') for func in FUNCTIONS: if func.is_empty(): continue src.add('struct __attribute__((__packed__)) {} {{'.format( func.cxx_struct_name())) if func.has_array_params(): src.add(' ~{}();'.format(func.cxx_struct_name())) src.add(' void finalize();') src.add(' uint64_t num_bytes() const;') src.add(' std::string to_string() const;') src.add(' void read_from_file(FILE* f);') src.add(' void write_to_file(FILE* f);') if func.has_return() and func.return_type.stype: src.add(' {} return_value;'.format(func.return_type.stype)) for param in func.params: if param.array: src.add(' uint64_t {}_length;'.format(param.name)) src.add(' const {}* {};'.format(param.array, param.name)) elif param.offset: src.add(' {} {};'.format(param.offset, param.name)) else: src.add(' {} {};'.format(param.ptype.stype, param.name)) src.add('};') src.add('}') src.add_guard('PUMPKINTOWN_FUNCTION_STRUCTS_HH_') return src
def gen_function_id_source(): src = Source() src.add_cxx_include('pumpkintown_function_id.hh') src.add('namespace pumpkintown {') src.add('FunctionId function_id_from_name(const std::string& name) {') for func in FUNCTIONS: src.add(' if (name == "{}") {{'.format(func.name)) src.add(' return FunctionId::{};'.format(func.name)) src.add('}') src.add(' return FunctionId::Invalid;') src.add('}') src.add('}') return src
def gen_function_id_header(): src = Source() src.add_cxx_include('cstdint', system=True) src.add_cxx_include('string', system=True) src.add('namespace pumpkintown {') src.add('enum class FunctionId : uint16_t {') src.add(' Invalid = 0,') for func in FUNCTIONS: src.add(' {} = {},'.format(func.name, func.function_id)) src.add('};') src.add('FunctionId function_id_from_name(const std::string& name);') src.add('}') src.add_guard('PUMPKINTOWN_FUNCTION_ID_HH_') return src
def gen_gl_enum_source(): enum_map = {} for name, value in ENUMS.items(): if value in enum_map: enum_map[value].append(name) else: enum_map[value] = [name] src = Source() src.add_cxx_include('pumpkintown_gl_enum.hh') src.add('namespace pumpkintown {') src.add('const char* lookup_gl_enum_string(const int64_t val) {') src.add(' switch(val) {') for value, names in enum_map.items(): # Skip GL_TIMEOUT_IGNORED, it's too big for an int64_t if value >= 0xffffffffffffffff: continue if value >= 0: value = '0x{:x}'.format(value) src.add(' case {}:'.format(value)) src.add(' return "{}";'.format('/'.join(names))) src.add(' }') src.add(' return "unknown-GLenum";') src.add('}') src.add('}') return src
def gen_gl_enum_header(): src = Source() src.add_cxx_include('cstdint', system=True) for name, value in ENUMS.items(): if value >= 0: value = '0x{:x}'.format(value) src.add('constexpr auto {} = {};'.format(name, value)) # TODO(nicholasbishop): should the enum be namespaced as well? src.add('namespace pumpkintown {') src.add('const char* lookup_gl_enum_string(int64_t val);') src.add('}') src.add_guard('PUMPKINTOWN_GL_ENUM_HH_') return src
class Exploder: def __init__(self, args): self.output = args.output self.reader = trace_reader.TraceReader(args.trace) self.src = Source() self.context_map = {} self.next_id = 0 self.ctx = None self.call_index = 0 self.enable_png_texture_dump = args.png_textures def take_id(self): nid = self.next_id self.next_id += 1 return nid def save_texture_png(self, call): width = call.fields['width'] height = call.fields['height'] size = (width, height) pixels = call.fields['pixels'] fmt = call.fields['format'] typ = call.fields['type'] if not pixels: return if fmt == glmeta.GL_RGBA and typ == glmeta.GL_UNSIGNED_BYTE: mode = 'RGBA' elif fmt == glmeta.GL_RGB and typ == glmeta.GL_UNSIGNED_BYTE: mode = 'RGB' elif fmt == glmeta.GL_RGBA and typ == glmeta.GL_FLOAT: mode = 'F' elif fmt == glmeta.GL_RED and typ == glmeta.GL_UNSIGNED_BYTE: mode = 'L' elif fmt == glmeta.GL_BGRA and typ == glmeta.GL_UNSIGNED_BYTE: # TODO mode = 'RGBA' else: raise ValueError(hex(fmt), hex(typ)) img = PIL.Image.frombytes(mode, size, pixels, decoder_name='raw') path = os.path.join(self.output, 'tex_{:04}.png'.format(self.call_index)) with open(path, 'wb') as wfile: img.save(wfile) def save_raw(self, prefix, index, data): if not data: return ext = 'raw' if prefix == 'shader': ext = 'txt' name = '{}_{:04}.{}'.format(prefix, index, ext) path = os.path.join(self.output, name) with open(path, 'wb') as wfile: wfile.write(data) return name def create_context(self, call): var = f'ctx{self.take_id()}' orig_share_ctx = call.fields.get('share_context') share_ctx = 'null' if orig_share_ctx: share_ctx = self.context_map[orig_share_ctx].var res = self.context_map[orig_share_ctx].res else: res = Resources() self.src.add(f'context_create {share_ctx} -> {var}') self.context_map[call.fields['return_value']] = Context(var, res) def make_context_current(self, call): orig_ctx = call.fields['ctx'] if orig_ctx == 0: context = 'null' self.ctx = None else: context = self.context_map[orig_ctx].var self.ctx = self.context_map[orig_ctx] self.src.add(f'make_current {context}') def standard_gen(self, call): count = call.fields['n'] var = f'id{self.take_id()}' self.src.add(f'{call.func.name} {count} {var}') def standard_delete(self, call): # TODO pass def buffer_data(self, call): index = self.take_id() save_name = self.save_raw('buf', index, call.fields['data']) target = hex(call.fields['target']) size = call.fields['size'] data = f'file:{save_name}' usage = hex(call.fields['usage']) self.src.add(f'glBufferData {target} {size} {data} {usage}') def tex_image(self, call): index = self.take_id() save_name = self.save_raw('tex', index, call.fields['pixels']) args = [] for param in call.func.params: if param.name == 'pixels': if call.fields['pixels_length'] == 0: args.append('null') else: args.append(f'file:{save_name}') else: args.append(hex(call.fields[param.name])) args = ' '.join(args) self.src.add(f'{call.func.name} {args}') def shader_source(self, call): index = self.take_id() save_path = self.save_raw('shader', index, call.fields['source'].encode('utf-8')) shader = call.fields['shader'] shader = self.ctx.res.shaders[shader] self.src.add(f'glShaderSource {shader} file:{save_path}') def program_binary(self, call): index = self.take_id() save_path = self.save_raw('program', index, call.fields['binary']) self.src.add(f'const auto vec = read_all("{save_path}");') fmt = call.fields['binaryFormat'] length = call.fields['length'] program = self.ctx.res.programs[call.fields['program']] self.src.add( f'glProgramBinary({program}, {fmt}, vec.data(), {length});') def standard_create(self, call): prefix = 'glCreate' name = call.func.name[len(prefix):].lower() args = [] for param in call.func.params: args.append(hex(call.fields[param.name])) args = ' '.join(args) var = f'{name}{self.take_id()}' self.src.add(f'{call.func.name} {args} -> {var}') self.ctx.res[name][call.return_value] = var def use_program(self, call): program = call.fields['program'] if program != 0: program = self.ctx.res.programs[program] self.src.add(f'glUseProgram {program}') def check_gl_errors(self, call): self.src.add(' check_gl_error();') if call.func.name == 'glLinkProgram': program = call.fields['program'] if program != 0: program = self.ctx.res.programs[program] self.src.add(f' check_program_link({program});') elif call.func.name == 'glCompileShader': shader = call.fields['shader'] if shader != 0: shader = self.ctx.res.shaders[shader] self.src.add(f' check_shader_compile({shader});') def handle_call(self, call): name = call.func.name #self.src.add(f' fprintf(stderr, "{self.call_index} {name}\\n");') if self.enable_png_texture_dump and name in ('glTexSubImage2D', 'glTexImage2D'): self.save_texture_png(call) if name in ('glXCreateNewContext', 'glXCreateContextAttribsARB', 'eglCreateContext'): self.create_context(call) elif name in ('glXMakeContextCurrent', 'eglMakeCurrent'): self.make_context_current(call) elif name in ('glGenBuffers', 'glGenTextures', 'glGenFramebuffers', 'glGenVertexArrays', 'glGenRenderbuffers'): self.standard_gen(call) elif name in ('glDeleteTextures', ): self.standard_delete(call) elif name in ('glCreateProgram', 'glCreateShader'): self.standard_create(call) elif name == 'glUseProgram': self.use_program(call) elif name in ('glTexImage2D', 'glTexSubImage2D'): self.tex_image(call) elif name == 'glBufferData': self.buffer_data(call) elif name == 'glShaderSource': self.shader_source(call) elif name == 'glProgramBinary': self.program_binary(call) elif name in ('glXWaitGL', 'glXWaitX', 'glXSwapIntervalMESA', 'eglGetCurrentContext', 'eglGetCurrentSurface'): # TODO pass else: args = [] for param in call.func.params: field = call.fields[param.name] if param.resource: if field == 0: args.append(0) else: args.append(self.ctx.res[param.resource][field]) elif param.array: arr = f'arr{self.take_id()}' length = call.fields[f'{param.name}_length'] values = ' '.join(str(elem) for elem in field) self.src.add(f'array {arr} {param.array} {values}') args.append(arr) elif param.offset: args.append(str(field)) elif isinstance(field, float): args.append(str(field)) else: args.append(hex(field)) args = ' '.join(args) self.src.add(f'{name} {args}') #self.check_gl_errors(call) # if name == 'glDrawElements' and self.call_index > 25000: # self.src.add(f' capture("fbo{self.call_index}.png");') self.call_index += 1 def explode(self): try: while True: call = self.reader.read() if call: self.handle_call(call) except StopIteration: pass path = os.path.join(self.output, 'trace') with open(path, 'w') as wfile: wfile.write(self.src.text())
def gen_gl_functions_header(): src = Source() src.add_cxx_include('pumpkintown_gl_types.hh') src.add('namespace pumpkintown {') for func in FUNCTIONS: src.add('{} {}({});'.format( func.return_type.ctype, func.name, ', '.join(param.ptype.ctype for param in func.params))) src.add('}') src.add_guard('PUMPKINTOWN_GL_FUNCTIONS_HH_') return src
def gen_trace_header(): src = Source() src.add('#ifndef PUMPKINTOWN_GL_GEN_HH_') src.add('#define PUMPKINTOWN_GL_GEN_HH_') src.add_cxx_include('pumpkintown_gl_types.hh') src.add(gen_exports()) src.add('namespace pumpkintown {') src.add('namespace real {') for func in FUNCTIONS: src.add(func.cxx_prototype()) src.add('}') src.add('}') src.add('#endif') return src