def call_function(self, function): if function.name == "glViewport": print ' bool reshape_window = false;' print ' if (x + width > glretrace::window_width) {' print ' glretrace::window_width = x + width;' print ' reshape_window = true;' print ' }' print ' if (y + height > glretrace::window_height) {' print ' glretrace::window_height = y + height;' print ' reshape_window = true;' print ' }' print ' if (reshape_window) {' print ' // XXX: does not always work' print ' glretrace::drawable->resize(glretrace::window_width, glretrace::window_height);' print ' reshape_window = false;' print ' }' if function.name == "glEnd": print ' glretrace::insideGlBeginEnd = false;' Retracer.call_function(self, function) if function.name == "glBegin": print ' glretrace::insideGlBeginEnd = true;' elif function.name.startswith('gl'): # glGetError is not allowed inside glBegin/glEnd print ' glretrace::checkGlError(call.no);' if function.name == 'glFlush': print ' if (!glretrace::double_buffer) {' print ' glretrace::frame_complete(call.no);' print ' }'
def call_function(self, function): if function.name == "glViewport": print ' bool reshape_window = false;' print ' if (x + width > glretrace::window_width) {' print ' glretrace::window_width = x + width;' print ' reshape_window = true;' print ' }' print ' if (y + height > glretrace::window_height) {' print ' glretrace::window_height = y + height;' print ' reshape_window = true;' print ' }' print ' if (reshape_window) {' print ' // XXX: does not always work' print ' glretrace::drawable->resize(glretrace::window_width, glretrace::window_height);' print ' reshape_window = false;' print ' }' if function.name == "glEnd": print ' glretrace::insideGlBeginEnd = false;' Retracer.call_function(self, function) if function.name == "glBegin": print ' glretrace::insideGlBeginEnd = true;' else: # glGetError is not allowed inside glBegin/glEnd print ' glretrace::checkGlError();'
def extract_arg(self, function, arg, arg_type, lvalue, rvalue): if function.name in self.array_pointer_function_names and arg.name == 'pointer': print ' %s = static_cast<%s>(%s.toPointer());' % (lvalue, arg_type, rvalue) return if function.name in self.draw_elements_function_names and arg.name == 'indices': print ' %s = %s.toPointer();' % (lvalue, rvalue) return if arg.type is glapi.GLlocation \ and 'program' not in [arg.name for arg in function.args]: print ' GLint program = -1;' print ' glGetIntegerv(GL_CURRENT_PROGRAM, &program);' if arg.type is glapi.GLlocationARB \ and 'programObj' not in [arg.name for arg in function.args]: print ' GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);' Retracer.extract_arg(self, function, arg, arg_type, lvalue, rvalue) # Don't try to use more samples than the implementation supports if arg.name == 'samples': assert arg.type is glapi.GLsizei print ' GLint max_samples = 0;' print ' glGetIntegerv(GL_MAX_SAMPLES, &max_samples);' print ' if (samples > max_samples) {' print ' samples = max_samples;' print ' }'
def retraceApi(self, api): print ''' static HINSTANCE g_hDll = NULL; static PROC __getPublicProcAddress(LPCSTR lpProcName) { if (!g_hDll) { char szDll[MAX_PATH] = {0}; if (!GetSystemDirectoryA(szDll, MAX_PATH)) { return NULL; } strcat(szDll, "\\\\%s"); g_hDll = LoadLibraryA(szDll); if (!g_hDll) { return NULL; } } return GetProcAddress(g_hDll, lpProcName); } ''' % api.name dispatcher = Dispatcher() dispatcher.dispatch_api(api) Retracer.retraceApi(self, api)
def retrace_function_body(self, function): is_array_pointer = function.name in self.array_pointer_function_names is_draw_array = function.name in self.draw_array_function_names is_draw_elements = function.name in self.draw_elements_function_names if is_array_pointer or is_draw_array or is_draw_elements: print ' if (glretrace::parser.version < 1) {' if is_array_pointer or is_draw_array: print ' GLint __array_buffer = 0;' print ' glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);' print ' if (!__array_buffer) {' self.fail_function(function) print ' }' if is_draw_elements: print ' GLint __element_array_buffer = 0;' print ' glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);' print ' if (!__element_array_buffer) {' self.fail_function(function) print ' }' print ' }' Retracer.retrace_function_body(self, function) if function.name in ('glFlush', 'glFinish'): print ' if (!glretrace::double_buffer) {' print ' glretrace::frame_complete(call.no);' print ' }' if function.name == 'glReadPixels': print ' glFinish();' print ' glretrace::snapshot(call.no);'
def extractArg(self, function, arg, arg_type, lvalue, rvalue): if function.name in self.array_pointer_function_names and arg.name == 'pointer': print ' %s = static_cast<%s>(retrace::toPointer(%s, true));' % (lvalue, arg_type, rvalue) return if function.name in self.draw_elements_function_names and arg.name == 'indices' or\ function.name in self.draw_indirect_function_names and arg.name == 'indirect': self.extractOpaqueArg(function, arg, arg_type, lvalue, rvalue) return # Handle pointer with offsets into the current pack pixel buffer # object. if function.name in self.pack_function_names and arg.output: self.extractOpaqueArg(function, arg, arg_type, lvalue, rvalue) return if arg.type is glapi.GLlocation \ and 'program' not in function.argNames(): print ' GLint program = -1;' print ' glGetIntegerv(GL_CURRENT_PROGRAM, &program);' if arg.type is glapi.GLlocationARB \ and 'programObj' not in function.argNames(): print ' GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);' Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue) # Don't try to use more samples than the implementation supports if arg.name == 'samples': assert arg.type is glapi.GLsizei print ' GLint max_samples = 0;' print ' glGetIntegerv(GL_MAX_SAMPLES, &max_samples);' print ' if (samples > max_samples) {' print ' samples = max_samples;' print ' }'
def extract_arg(self, function, arg, arg_type, lvalue, rvalue): if function.name in self.array_pointer_function_names and arg.name == "pointer": print " %s = static_cast<%s>(%s.toPointer());" % (lvalue, arg_type, rvalue) return if function.name in self.draw_elements_function_names and arg.name == "indices": self.extract_opaque_arg(function, arg, arg_type, lvalue, rvalue) return if arg.type is glapi.GLlocation and "program" not in [arg.name for arg in function.args]: print " GLint program = -1;" print " glGetIntegerv(GL_CURRENT_PROGRAM, &program);" if arg.type is glapi.GLlocationARB and "programObj" not in [arg.name for arg in function.args]: print " GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);" Retracer.extract_arg(self, function, arg, arg_type, lvalue, rvalue) # Don't try to use more samples than the implementation supports if arg.name == "samples": assert arg.type is glapi.GLsizei print " GLint max_samples = 0;" print " glGetIntegerv(GL_MAX_SAMPLES, &max_samples);" print " if (samples > max_samples) {" print " samples = max_samples;" print " }"
def retrace_function_body(self, function): is_array_pointer = function.name in self.array_pointer_function_names is_draw_array = function.name in self.draw_array_function_names is_draw_elements = function.name in self.draw_elements_function_names if is_array_pointer or is_draw_array or is_draw_elements: print ' if (Trace::Parser::version < 1) {' if is_array_pointer or is_draw_array: print ' GLint __array_buffer = 0;' print ' glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);' print ' if (!__array_buffer) {' self.fail_function(function) print ' }' if is_draw_elements: print ' GLint __element_array_buffer = 0;' print ' glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);' print ' if (!__element_array_buffer) {' self.fail_function(function) print ' }' print ' }' Retracer.retrace_function_body(self, function)
def retrace_function_body(self, function): is_array_pointer = function.name in self.array_pointer_function_names is_draw_array = function.name in self.draw_array_function_names is_draw_elements = function.name in self.draw_elements_function_names is_misc_draw = function.name in self.misc_draw_function_names if is_array_pointer or is_draw_array or is_draw_elements: print " if (glretrace::parser.version < 1) {" if is_array_pointer or is_draw_array: print " GLint __array_buffer = 0;" print " glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);" print " if (!__array_buffer) {" self.fail_function(function) print " }" if is_draw_elements: print " GLint __element_array_buffer = 0;" print " glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);" print " if (!__element_array_buffer) {" self.fail_function(function) print " }" print " }" # When no pack buffer object is bound, the pack functions are no-ops. if function.name in self.pack_function_names: print " GLint __pack_buffer = 0;" print " glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &__pack_buffer);" print " if (!__pack_buffer) {" if function.name == "glReadPixels": print " glFinish();" print " if (glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAME ||" print " glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAMEBUFFER) {" print " glretrace::snapshot(call.no);" print " }" print " return;" print " }" # Pre-snapshots if function.name in self.bind_framebuffer_function_names: print " if (glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAMEBUFFER) {" print " glretrace::snapshot(call.no - 1);" print " }" if function.name == "glFrameTerminatorGREMEDY": print " glretrace::frame_complete(call);" return Retracer.retrace_function_body(self, function) # Post-snapshots if function.name in ("glFlush", "glFinish"): print " if (!glretrace::double_buffer) {" print " glretrace::frame_complete(call);" print " }" if is_draw_array or is_draw_elements or is_misc_draw: print " if (glretrace::snapshot_frequency == glretrace::FREQUENCY_DRAW) {" print " glretrace::snapshot(call.no);" print " }"
def extractArg(self, function, arg, arg_type, lvalue, rvalue): if function.name in self.array_pointer_function_names and arg.name == 'pointer': print ' %s = static_cast<%s>(retrace::toPointer(%s, true));' % (lvalue, arg_type, rvalue) return if function.name in self.draw_elements_function_names and arg.name == 'indices' or\ function.name in self.draw_indirect_function_names and arg.name == 'indirect': self.extractOpaqueArg(function, arg, arg_type, lvalue, rvalue) return # Handle pointer with offsets into the current pack pixel buffer # object. if function.name in self.pack_function_names and arg.output: assert isinstance(arg_type, (stdapi.Pointer, stdapi.Array, stdapi.Blob, stdapi.Opaque)) print ' %s = static_cast<%s>((%s).toPointer());' % (lvalue, arg_type, rvalue) return if arg.type is glapi.GLlocation \ and 'program' not in function.argNames(): # Determine the active program for uniforms swizzling print ' GLint program = -1;' print ' if (glretrace::insideList) {' print ' // glUseProgram & glUseProgramObjectARB are display-list-able' print r' glretrace::Context *currentContext = glretrace::getCurrentContext();' print ' program = _program_map[currentContext->activeProgram];' print ' } else {' print ' GLint pipeline = 0;' print ' if (_pipelineHasBeenBound) {' print ' glGetIntegerv(GL_PROGRAM_PIPELINE_BINDING, &pipeline);' print ' }' print ' if (pipeline) {' print ' glGetProgramPipelineiv(pipeline, GL_ACTIVE_PROGRAM, &program);' print ' } else {' print ' glGetIntegerv(GL_CURRENT_PROGRAM, &program);' print ' }' print ' }' print if arg.type is glapi.GLlocationARB \ and 'programObj' not in function.argNames(): print ' GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);' Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue) # Don't try to use more samples than the implementation supports if arg.name == 'samples': assert arg.type is glapi.GLsizei print ' GLint max_samples = 0;' print ' glGetIntegerv(GL_MAX_SAMPLES, &max_samples);' print ' if (samples > max_samples) {' print ' samples = max_samples;' print ' }' # These parameters are referred beyond the call life-time # TODO: Replace ad-hoc solution for bindable parameters with general one if function.name in ('glFeedbackBuffer', 'glSelectBuffer') and arg.output: print ' _allocator.bind(%s);' % arg.name
def retraceApi(self, api): # Ensure pack function have side effects abort = False for function in api.getAllFunctions(): if not function.sideeffects and self.pack_function_regex.match(function.name): sys.stderr.write('error: function %s must have sideeffects\n' % function.name) abort = True if abort: sys.exit(1) Retracer.retraceApi(self, api)
def extractArg(self, function, arg, arg_type, lvalue, rvalue): if function.name in self.array_pointer_function_names and arg.name == "pointer": print " %s = static_cast<%s>(retrace::toPointer(%s, true));" % (lvalue, arg_type, rvalue) return if ( function.name in self.draw_elements_function_names and arg.name == "indices" or function.name in self.draw_indirect_function_names and arg.name == "indirect" ): self.extractOpaqueArg(function, arg, arg_type, lvalue, rvalue) return # Handle pointer with offsets into the current pack pixel buffer # object. if function.name in self.pack_function_names and arg.output: assert isinstance(arg_type, (stdapi.Pointer, stdapi.Array, stdapi.Blob, stdapi.Opaque)) print " %s = static_cast<%s>((%s).toPointer());" % (lvalue, arg_type, rvalue) return if arg.type is glapi.GLlocation and "program" not in function.argNames(): # Determine the active program for uniforms swizzling print " GLint program = -1;" print " GLint pipeline = 0;" print " if (_pipelineHasBeenBound) {" print " glGetIntegerv(GL_PROGRAM_PIPELINE_BINDING, &pipeline);" print " }" print " if (pipeline) {" print " glGetProgramPipelineiv(pipeline, GL_ACTIVE_PROGRAM, &program);" print " } else {" print " glGetIntegerv(GL_CURRENT_PROGRAM, &program);" print " }" print if arg.type is glapi.GLlocationARB and "programObj" not in function.argNames(): print " GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);" Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue) # Don't try to use more samples than the implementation supports if arg.name == "samples": assert arg.type is glapi.GLsizei print " GLint max_samples = 0;" print " glGetIntegerv(GL_MAX_SAMPLES, &max_samples);" print " if (samples > max_samples) {" print " samples = max_samples;" print " }" # These parameters are referred beyond the call life-time # TODO: Replace ad-hoc solution for bindable parameters with general one if function.name in ("glFeedbackBuffer", "glSelectBuffer") and arg.output: print " _allocator.bind(%s);" % arg.name
def retraceFunctionBody(self, function): is_array_pointer = function.name in self.array_pointer_function_names is_draw_arrays = self.draw_arrays_function_regex.match(function.name) is not None is_draw_elements = self.draw_elements_function_regex.match(function.name) is not None is_draw_indirect = self.draw_indirect_function_regex.match(function.name) is not None is_misc_draw = self.misc_draw_function_regex.match(function.name) # For backwards compatibility with old traces where non VBO drawing was supported if (is_array_pointer or is_draw_arrays or is_draw_elements) and not is_draw_indirect: print ' if (retrace::parser->getVersion() < 1) {' if is_array_pointer or is_draw_arrays: print ' GLint _array_buffer = 0;' print ' glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &_array_buffer);' print ' if (!_array_buffer) {' self.failFunction(function) print ' }' if is_draw_elements: print ' GLint _element_array_buffer = 0;' print ' glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &_element_array_buffer);' print ' if (!_element_array_buffer) {' self.failFunction(function) print ' }' print ' }' # When no pack buffer object is bound, the pack functions are no-ops. if self.pack_function_regex.match(function.name): print ' GLint _pack_buffer = 0;' print ' glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &_pack_buffer);' print ' if (!_pack_buffer) {' print ' return;' print ' }' # Pre-snapshots if self.bind_framebuffer_function_regex.match(function.name): print ' assert(call.flags & trace::CALL_FLAG_SWAP_RENDERTARGET);' if function.name == 'glStringMarkerGREMEDY': return if function.name == 'glFrameTerminatorGREMEDY': print ' glretrace::frame_complete(call);' return Retracer.retraceFunctionBody(self, function) # Post-snapshots if function.name in ('glFlush', 'glFinish'): print ' if (!retrace::doubleBuffer) {' print ' glretrace::frame_complete(call);' print ' }' if is_draw_arrays or is_draw_elements or is_misc_draw: print ' assert(call.flags & trace::CALL_FLAG_RENDER);'
def extractArg(self, function, arg, arg_type, lvalue, rvalue): if function.name in self.array_pointer_function_names and arg.name == 'pointer': print ' %s = static_cast<%s>(retrace::toPointer(%s, true));' % (lvalue, arg_type, rvalue) return if self.draw_elements_function_regex.match(function.name) and arg.name == 'indices' or\ self.draw_indirect_function_regex.match(function.name) and arg.name == 'indirect': self.extractOpaqueArg(function, arg, arg_type, lvalue, rvalue) return # Handle pointer with offsets into the current pack pixel buffer # object. if self.pack_function_regex.match(function.name) and arg.output: assert isinstance(arg_type, (stdapi.Pointer, stdapi.Array, stdapi.Blob, stdapi.Opaque)) print ' %s = static_cast<%s>((%s).toPointer());' % (lvalue, arg_type, rvalue) return if function.name.startswith('glGetQueryObject') and arg.output: print ' %s = static_cast<%s>((%s).toPointer());' % (lvalue, arg_type, rvalue) return if (arg.type.depends(glapi.GLlocation) or \ arg.type.depends(glapi.GLsubroutine)) \ and 'program' not in function.argNames(): # Determine the active program for uniforms swizzling print ' GLint program = _getActiveProgram();' if arg.type is glapi.GLlocationARB \ and 'programObj' not in function.argNames(): print ' GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);' Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue) # Don't try to use more samples than the implementation supports if arg.name == 'samples': if function.name == 'glRasterSamplesEXT': assert arg.type is glapi.GLuint print ' GLint max_samples = 0;' print ' glGetIntegerv(GL_MAX_RASTER_SAMPLES_EXT, &max_samples);' print ' if (samples > static_cast<GLuint>(max_samples)) {' print ' samples = static_cast<GLuint>(max_samples);' print ' }' else: assert arg.type is glapi.GLsizei print ' GLint max_samples = 0;' print ' glGetIntegerv(GL_MAX_SAMPLES, &max_samples);' print ' if (samples > max_samples) {' print ' samples = max_samples;' print ' }' # These parameters are referred beyond the call life-time # TODO: Replace ad-hoc solution for bindable parameters with general one if function.name in ('glFeedbackBuffer', 'glSelectBuffer') and arg.output: print ' _allocator.bind(%s);' % arg.name
def retraceFunctionBody(self, function): is_array_pointer = function.name in self.array_pointer_function_names is_draw_array = function.name in self.draw_array_function_names is_draw_elements = function.name in self.draw_elements_function_names is_misc_draw = function.name in self.misc_draw_function_names if is_array_pointer or is_draw_array or is_draw_elements: print ' if (retrace::parser.version < 1) {' if is_array_pointer or is_draw_array: print ' GLint _array_buffer = 0;' print ' glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &_array_buffer);' print ' if (!_array_buffer) {' self.failFunction(function) print ' }' if is_draw_elements: print ' GLint _element_array_buffer = 0;' print ' glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &_element_array_buffer);' print ' if (!_element_array_buffer) {' self.failFunction(function) print ' }' print ' }' # When no pack buffer object is bound, the pack functions are no-ops. if function.name in self.pack_function_names: print ' GLint _pack_buffer = 0;' print ' glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &_pack_buffer);' print ' if (!_pack_buffer) {' print ' return;' print ' }' # Pre-snapshots if function.name in self.bind_framebuffer_function_names: print ' assert(call.flags & trace::CALL_FLAG_SWAP_RENDERTARGET);' if function.name == 'glStringMarkerGREMEDY': return if function.name == 'glFrameTerminatorGREMEDY': print ' glretrace::frame_complete(call);' return Retracer.retraceFunctionBody(self, function) # Post-snapshots if function.name in ('glFlush', 'glFinish'): print ' if (!retrace::doubleBuffer) {' print ' glretrace::frame_complete(call);' print ' }' if is_draw_array or is_draw_elements or is_misc_draw: print ' assert(call.flags & trace::CALL_FLAG_RENDER);'
def extract_arg(self, function, arg, arg_type, lvalue, rvalue): if function.name in self.array_pointer_function_names and arg.name == 'pointer': print ' %s = %s.blob();' % (lvalue, rvalue) return if function.name in self.draw_elements_function_names and arg.name == 'indices': print ' %s = %s.blob();' % (lvalue, rvalue) return if function.name.startswith('glUniform') and function.args[0].name == arg.name == 'location': print ' GLint program = -1;' print ' glGetIntegerv(GL_CURRENT_PROGRAM, &program);' Retracer.extract_arg(self, function, arg, arg_type, lvalue, rvalue)
def extractArg(self, function, arg, arg_type, lvalue, rvalue): if function.name in self.array_pointer_function_names and arg.name == 'pointer': print ' %s = static_cast<%s>(retrace::toPointer(%s, true));' % (lvalue, arg_type, rvalue) return if function.name in self.draw_elements_function_names and arg.name == 'indices' or\ function.name in self.draw_indirect_function_names and arg.name == 'indirect': self.extractOpaqueArg(function, arg, arg_type, lvalue, rvalue) return # Handle pointer with offsets into the current pack pixel buffer # object. if function.name in self.pack_function_names and arg.output: assert isinstance(arg_type, (stdapi.Pointer, stdapi.Array, stdapi.Blob, stdapi.Opaque)) print ' %s = static_cast<%s>((%s).toPointer());' % (lvalue, arg_type, rvalue) return if arg.type is glapi.GLlocation \ and 'program' not in function.argNames(): print ' GLint program = -1;' print ' glGetIntegerv(GL_CURRENT_PROGRAM, &program);' if arg.type is glapi.GLlocationARB \ and 'programObj' not in function.argNames(): print ' GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);' Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue) # Don't try to use more samples than the implementation supports if arg.name == 'samples': assert arg.type is glapi.GLsizei print ' GLint max_samples = 0;' print ' glGetIntegerv(GL_MAX_SAMPLES, &max_samples);' print ' if (samples > max_samples) {' print ' samples = max_samples;' print ' }' # These parameters are referred beyond the call life-time # TODO: Replace ad-hoc solution for bindable parameters with general one if function.name in ('glFeedbackBuffer', 'glSelectBuffer') and arg.output: print ' _allocator.bind(%s);' % arg.name
def invokeFunction(self, function): # Infer the drawable size from GL calls if function.name == "glViewport": print ' glretrace::updateDrawable(x + width, y + height);' if function.name == "glViewportArray": # We are concerned about drawables so only care for the first viewport print ' if (first == 0 && count > 0) {' print ' GLfloat x = v[0], y = v[1], w = v[2], h = v[3];' print ' glretrace::updateDrawable(x + w, y + h);' print ' }' if function.name == "glViewportIndexedf": print ' if (index == 0) {' print ' glretrace::updateDrawable(x + w, y + h);' print ' }' if function.name == "glViewportIndexedfv": print ' if (index == 0) {' print ' GLfloat x = v[0], y = v[1], w = v[2], h = v[3];' print ' glretrace::updateDrawable(x + w, y + h);' print ' }' if function.name in ('glBlitFramebuffer', 'glBlitFramebufferEXT'): # Some applications do all their rendering in a framebuffer, and # then just blit to the drawable without ever calling glViewport. print ' glretrace::updateDrawable(std::max(dstX0, dstX1), std::max(dstY0, dstY1));' if function.name == "glEnd": print ' glretrace::insideGlBeginEnd = false;' if function.name.startswith('gl') and not function.name.startswith('glX'): print r' if (retrace::debug && !glretrace::currentContext) {' print r' retrace::warning(call) << "no current context\n";' print r' }' if function.name == 'memcpy': print ' if (!dest || !src || !n) return;' # Skip glEnable/Disable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB) as we don't # faithfully set the CONTEXT_DEBUG_BIT_ARB flags on context creation. if function.name in ('glEnable', 'glDisable'): print ' if (cap == GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB) return;' # Destroy the buffer mapping if function.name in self.unmap_function_names: print r' GLvoid *ptr = NULL;' if function.name == 'glUnmapBuffer': print r' glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &ptr);' elif function.name == 'glUnmapBufferARB': print r' glGetBufferPointervARB(target, GL_BUFFER_MAP_POINTER_ARB, &ptr);' elif function.name == 'glUnmapBufferOES': print r' glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &ptr);' elif function.name == 'glUnmapNamedBufferEXT': print r' glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &ptr);' elif function.name == 'glUnmapObjectBufferATI': # TODO pass else: assert False print r' if (ptr) {' print r' retrace::delRegionByPointer(ptr);' print r' } else {' print r' retrace::warning(call) << "no current context\n";' print r' }' if function.name in ('glBindProgramPipeline', 'glBindProgramPipelineEXT'): # Note if glBindProgramPipeline has ever been called print r' if (pipeline) {' print r' _pipelineHasBeenBound = true;' print r' }' profileDraw = ( function.name in self.draw_array_function_names or function.name in self.draw_elements_function_names or function.name in self.draw_indirect_function_names or function.name in self.misc_draw_function_names or function.name == 'glBegin' ) if function.name in ('glUseProgram', 'glUseProgramObjectARB'): print r' if (glretrace::currentContext) {' print r' glretrace::currentContext->activeProgram = call.arg(0).toUInt();' print r' }' # Only profile if not inside a list as the queries get inserted into list if function.name == 'glNewList': print r' glretrace::insideList = true;' if function.name == 'glEndList': print r' glretrace::insideList = false;' if function.name != 'glEnd': print r' if (!glretrace::insideList && !glretrace::insideGlBeginEnd && retrace::profiling) {' if profileDraw: print r' glretrace::beginProfile(call, true);' else: print r' glretrace::beginProfile(call, false);' print r' }' if function.name == 'glCreateShaderProgramv': # When dumping state, break down glCreateShaderProgramv so that the # shader source can be recovered. print r' if (retrace::dumpingState) {' print r' GLuint _shader = glCreateShader(type);' print r' if (_shader) {' print r' glShaderSource(_shader, count, strings, NULL);' print r' glCompileShader(_shader);' print r' const GLuint _program = glCreateProgram();' print r' if (_program) {' print r' GLint compiled = GL_FALSE;' print r' glGetShaderiv(_shader, GL_COMPILE_STATUS, &compiled);' print r' glProgramParameteri(_program, GL_PROGRAM_SEPARABLE, GL_TRUE);' print r' if (compiled) {' print r' glAttachShader(_program, _shader);' print r' glLinkProgram(_program);' print r' //glDetachShader(_program, _shader);' print r' }' print r' //append-shader-info-log-to-program-info-log' print r' }' print r' //glDeleteShader(_shader);' print r' _result = _program;' print r' } else {' print r' _result = 0;' print r' }' print r' } else {' Retracer.invokeFunction(self, function) print r' }' else: Retracer.invokeFunction(self, function) if function.name == "glBegin": print ' glretrace::insideGlBeginEnd = true;' print r' if (!glretrace::insideList && !glretrace::insideGlBeginEnd && retrace::profiling) {' if profileDraw: print r' glretrace::endProfile(call, true);' else: print r' glretrace::endProfile(call, false);' print r' }' # Error checking if function.name.startswith('gl'): # glGetError is not allowed inside glBegin/glEnd print ' if (retrace::debug && !glretrace::insideGlBeginEnd) {' print ' glretrace::checkGlError(call);' if function.name in ('glProgramStringARB', 'glProgramStringNV'): print r' GLint error_position = -1;' print r' glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);' print r' if (error_position != -1) {' print r' const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);' print r' retrace::warning(call) << error_string << "\n";' print r' }' if function.name == 'glCompileShader': print r' GLint compile_status = 0;' print r' glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);' print r' if (!compile_status) {' print r' GLint info_log_length = 0;' print r' glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name in ('glLinkProgram', 'glCreateShaderProgramv', 'glCreateShaderProgramEXT'): if function.name != 'glLinkProgram': print r' GLuint program = _result;' print r' GLint link_status = 0;' print r' glGetProgramiv(program, GL_LINK_STATUS, &link_status);' print r' if (!link_status) {' print r' GLint info_log_length = 0;' print r' glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetProgramInfoLog(program, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name == 'glCompileShaderARB': print r' GLint compile_status = 0;' print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);' print r' if (!compile_status) {' print r' GLint info_log_length = 0;' print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name == 'glLinkProgramARB': print r' GLint link_status = 0;' print r' glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);' print r' if (!link_status) {' print r' GLint info_log_length = 0;' print r' glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name in self.map_function_names: print r' if (!_result) {' print r' retrace::warning(call) << "failed to map buffer\n";' print r' }' if function.name in self.unmap_function_names and function.type is not stdapi.Void: print r' if (!_result) {' print r' retrace::warning(call) << "failed to unmap buffer\n";' print r' }' if function.name in ('glGetAttribLocation', 'glGetAttribLocationARB'): print r' GLint _origResult = call.ret->toSInt();' print r' if (_result != _origResult) {' print r' retrace::warning(call) << "vertex attrib location mismatch " << _origResult << " -> " << _result << "\n";' print r' }' if function.name in ('glCheckFramebufferStatus', 'glCheckFramebufferStatusEXT', 'glCheckNamedFramebufferStatusEXT'): print r' GLint _origResult = call.ret->toSInt();' print r' if (_origResult == GL_FRAMEBUFFER_COMPLETE &&' print r' _result != GL_FRAMEBUFFER_COMPLETE) {' print r' retrace::warning(call) << "incomplete framebuffer (" << glstate::enumToString(_result) << ")\n";' print r' }' print ' }' # Query the buffer length for whole buffer mappings if function.name in self.map_function_names: if 'length' in function.argNames(): assert 'BufferRange' in function.name else: assert 'BufferRange' not in function.name print r' GLint length = 0;' if function.name in ('glMapBuffer', 'glMapBufferOES'): print r' glGetBufferParameteriv(target, GL_BUFFER_SIZE, &length);' elif function.name == 'glMapBufferARB': print r' glGetBufferParameterivARB(target, GL_BUFFER_SIZE_ARB, &length);' elif function.name == 'glMapNamedBufferEXT': print r' glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_SIZE, &length);' elif function.name == 'glMapObjectBufferATI': print r' glGetObjectBufferivATI(buffer, GL_OBJECT_BUFFER_SIZE_ATI, &length);' else: assert False
def invokeFunction(self, function): # Infer the drawable size from GL calls if function.name == "glViewport": print ' glretrace::updateDrawable(x + width, y + height);' if function.name == "glViewportArray": # We are concerned about drawables so only care for the first viewport print ' if (first == 0 && count > 0) {' print ' GLfloat x = v[0], y = v[1], w = v[2], h = v[3];' print ' glretrace::updateDrawable(x + w, y + h);' print ' }' if function.name == "glViewportIndexedf": print ' if (index == 0) {' print ' glretrace::updateDrawable(x + w, y + h);' print ' }' if function.name == "glViewportIndexedfv": print ' if (index == 0) {' print ' GLfloat x = v[0], y = v[1], w = v[2], h = v[3];' print ' glretrace::updateDrawable(x + w, y + h);' print ' }' if function.name in ('glBlitFramebuffer', 'glBlitFramebufferEXT'): # Some applications do all their rendering in a framebuffer, and # then just blit to the drawable without ever calling glViewport. print ' glretrace::updateDrawable(std::max(dstX0, dstX1), std::max(dstY0, dstY1));' if function.name == "glEnd": print ' glretrace::insideGlBeginEnd = false;' if function.name.startswith('gl') and not function.name.startswith('glX'): print r' if (!glretrace::context && !glretrace::benchmark && !retrace::profiling) {' print r' retrace::warning(call) << "no current context\n";' print r' }' if function.name == 'memcpy': print ' if (!dest || !src || !n) return;' # Destroy the buffer mapping if function.name in self.unmap_function_names: print r' GLvoid *ptr = NULL;' if function.name == 'glUnmapBuffer': print r' glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &ptr);' elif function.name == 'glUnmapBufferARB': print r' glGetBufferPointervARB(target, GL_BUFFER_MAP_POINTER_ARB, &ptr);' elif function.name == 'glUnmapBufferOES': print r' glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &ptr);' elif function.name == 'glUnmapNamedBufferEXT': print r' glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &ptr);' elif function.name == 'glUnmapObjectBufferATI': # TODO pass else: assert False print r' if (ptr) {' print r' retrace::delRegionByPointer(ptr);' print r' } else {' print r' retrace::warning(call) << "no current context\n";' print r' }' Retracer.invokeFunction(self, function) # Error checking if function.name == "glBegin": print ' glretrace::insideGlBeginEnd = true;' elif function.name.startswith('gl'): # glGetError is not allowed inside glBegin/glEnd print ' if (!glretrace::benchmark && !retrace::profiling && !glretrace::insideGlBeginEnd) {' print ' glretrace::checkGlError(call);' if function.name in ('glProgramStringARB', 'glProgramStringNV'): print r' GLint error_position = -1;' print r' glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);' print r' if (error_position != -1) {' print r' const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);' print r' retrace::warning(call) << error_string << "\n";' print r' }' if function.name == 'glCompileShader': print r' GLint compile_status = 0;' print r' glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);' print r' if (!compile_status) {' print r' GLint info_log_length = 0;' print r' glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name == 'glLinkProgram': print r' GLint link_status = 0;' print r' glGetProgramiv(program, GL_LINK_STATUS, &link_status);' print r' if (!link_status) {' print r' GLint info_log_length = 0;' print r' glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetProgramInfoLog(program, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name == 'glCompileShaderARB': print r' GLint compile_status = 0;' print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);' print r' if (!compile_status) {' print r' GLint info_log_length = 0;' print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name == 'glLinkProgramARB': print r' GLint link_status = 0;' print r' glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);' print r' if (!link_status) {' print r' GLint info_log_length = 0;' print r' glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name in self.map_function_names: print r' if (!__result) {' print r' retrace::warning(call) << "failed to map buffer\n";' print r' }' if function.name in self.unmap_function_names and function.type is not stdapi.Void: print r' if (!__result) {' print r' retrace::warning(call) << "failed to unmap buffer\n";' print r' }' if function.name in ('glGetAttribLocation', 'glGetAttribLocationARB'): print r' GLint __orig_result = call.ret->toSInt();' print r' if (__result != __orig_result) {' print r' retrace::warning(call) << "vertex attrib location mismatch " << __orig_result << " -> " << __result << "\n";' print r' }' if function.name in ('glCheckFramebufferStatus', 'glCheckFramebufferStatusEXT', 'glCheckNamedFramebufferStatusEXT'): print r' GLint __orig_result = call.ret->toSInt();' print r' if (__orig_result == GL_FRAMEBUFFER_COMPLETE &&' print r' __result != GL_FRAMEBUFFER_COMPLETE) {' print r' retrace::warning(call) << "incomplete framebuffer (" << glstate::enumToString(__result) << ")\n";' print r' }' print ' }' # Query the buffer length for whole buffer mappings if function.name in self.map_function_names: if 'length' in function.argNames(): assert 'BufferRange' in function.name else: assert 'BufferRange' not in function.name print r' GLint length = 0;' if function.name in ('glMapBuffer', 'glMapBufferOES'): print r' glGetBufferParameteriv(target, GL_BUFFER_SIZE, &length);' elif function.name == 'glMapBufferARB': print r' glGetBufferParameterivARB(target, GL_BUFFER_SIZE_ARB, &length);' elif function.name == 'glMapNamedBufferEXT': print r' glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_SIZE, &length);' elif function.name == 'glMapObjectBufferATI': print r' glGetObjectBufferivATI(buffer, GL_OBJECT_BUFFER_SIZE_ATI, &length);' else: assert False
def invokeFunction(self, function): # Infer the drawable size from GL calls if function.name == "glViewport": print ' glretrace::updateDrawable(x + width, y + height);' if function.name == "glViewportArrayv": # We are concerned about drawables so only care for the first viewport print ' if (first == 0 && count > 0) {' print ' GLfloat x = v[0], y = v[1], w = v[2], h = v[3];' print ' glretrace::updateDrawable(x + w, y + h);' print ' }' if function.name == "glViewportIndexedf": print ' if (index == 0) {' print ' glretrace::updateDrawable(x + w, y + h);' print ' }' if function.name == "glViewportIndexedfv": print ' if (index == 0) {' print ' GLfloat x = v[0], y = v[1], w = v[2], h = v[3];' print ' glretrace::updateDrawable(x + w, y + h);' print ' }' if function.name in ('glBlitFramebuffer', 'glBlitFramebufferEXT'): # Some applications do all their rendering in a framebuffer, and # then just blit to the drawable without ever calling glViewport. print ' glretrace::updateDrawable(std::max(dstX0, dstX1), std::max(dstY0, dstY1));' if function.name == "glEnd": print r' if (currentContext) {' print r' currentContext->insideBeginEnd = false;' print r' }' if function.name == 'memcpy': print ' if (!dest || !src || !n) return;' # Skip glEnable/Disable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB) as we don't # faithfully set the CONTEXT_DEBUG_BIT_ARB flags on context creation. if function.name in ('glEnable', 'glDisable'): print ' if (cap == GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB) return;' # Destroy the buffer mapping if self.unmap_function_regex.match(function.name): print r' GLvoid *ptr = NULL;' if function.name == 'glUnmapBuffer': print r' glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &ptr);' elif function.name == 'glUnmapBufferARB': print r' glGetBufferPointervARB(target, GL_BUFFER_MAP_POINTER_ARB, &ptr);' elif function.name == 'glUnmapBufferOES': print r' glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &ptr);' elif function.name == 'glUnmapNamedBuffer': print r' glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &ptr);' elif function.name == 'glUnmapNamedBufferEXT': print r' glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &ptr);' elif function.name == 'glUnmapObjectBufferATI': # TODO pass else: assert False print r' if (ptr) {' print r' retrace::delRegionByPointer(ptr);' print r' } else {' print r' retrace::warning(call) << "failed to get mapped pointer\n";' print r' }' # Implicit destruction of buffer mappings # TODO: handle BufferData variants # TODO: don't rely on GL_ARB_direct_state_access if function.name in ('glDeleteBuffers', 'glDeleteBuffersARB'): print r' if (currentContext->features().ARB_direct_state_access) {' print r' for (GLsizei i = 0; i < n; ++i) {' print r' GLvoid *ptr = nullptr;' print r' glGetNamedBufferPointerv(buffers[i], GL_BUFFER_MAP_POINTER, &ptr);' print r' if (ptr) {' print r' retrace::delRegionByPointer(ptr);' print r' }' print r' }' print r' }' if function.name.startswith('glCopyImageSubData'): print r' if (srcTarget == GL_RENDERBUFFER || dstTarget == GL_RENDERBUFFER) {' print r' retrace::warning(call) << " renderbuffer targets unsupported (https://github.com/apitrace/apitrace/issues/404)\n";' print r' }' is_draw_arrays = self.draw_arrays_function_regex.match(function.name) is not None is_draw_elements = self.draw_elements_function_regex.match(function.name) is not None is_misc_draw = self.misc_draw_function_regex.match(function.name) is not None profileDraw = ( is_draw_arrays or is_draw_elements or is_misc_draw or function.name == 'glBegin' or function.name.startswith('glDispatchCompute') ) # Keep track of current program/pipeline if function.name in ('glUseProgram', 'glUseProgramObjectARB'): print r' if (currentContext) {' print r' currentContext->currentUserProgram = call.arg(0).toUInt();' print r' currentContext->currentProgram = %s;' % function.args[0].name print r' }' if function.name in ('glBindProgramPipeline', 'glBindProgramPipelineEXT'): print r' if (currentContext) {' print r' currentContext->currentPipeline = %s;' % function.args[0].name print r' }' # Only profile if not inside a list as the queries get inserted into list if function.name == 'glNewList': print r' if (currentContext) {' print r' currentContext->insideList = true;' print r' }' if function.name == 'glEndList': print r' if (currentContext) {' print r' currentContext->insideList = false;' print r' }' if function.name == 'glBegin' or \ is_draw_arrays or \ is_draw_elements or \ function.name.startswith('glBeginTransformFeedback'): print r' if (retrace::debug) {' print r' _validateActiveProgram(call);' print r' }' if function.name != 'glEnd': print r' if (currentContext && !currentContext->insideList && !currentContext->insideBeginEnd && retrace::profiling) {' if profileDraw: print r' glretrace::beginProfile(call, true);' else: print r' glretrace::beginProfile(call, false);' print r' }' if function.name in ('glCreateShaderProgramv', 'glCreateShaderProgramEXT', 'glCreateShaderProgramvEXT'): # When dumping state, break down glCreateShaderProgram* so that the # shader source can be recovered. print r' if (retrace::dumpingState) {' print r' GLuint _shader = glCreateShader(type);' print r' if (_shader) {' if not function.name.startswith('glCreateShaderProgramv'): print r' GLsizei count = 1;' print r' const GLchar **strings = &string;' print r' glShaderSource(_shader, count, strings, NULL);' print r' glCompileShader(_shader);' print r' const GLuint _program = glCreateProgram();' print r' if (_program) {' print r' GLint compiled = GL_FALSE;' print r' glGetShaderiv(_shader, GL_COMPILE_STATUS, &compiled);' if function.name == 'glCreateShaderProgramvEXT': print r' glProgramParameteriEXT(_program, GL_PROGRAM_SEPARABLE, GL_TRUE);' else: print r' glProgramParameteri(_program, GL_PROGRAM_SEPARABLE, GL_TRUE);' print r' if (compiled) {' print r' glAttachShader(_program, _shader);' print r' glLinkProgram(_program);' print r' if (false) glDetachShader(_program, _shader);' print r' }' print r' // TODO: append shader info log to program info log' print r' }' print r' glDeleteShader(_shader);' print r' _result = _program;' print r' } else {' print r' _result = 0;' print r' }' print r' } else {' Retracer.invokeFunction(self, function) print r' }' elif function.name in ('glDetachShader', 'glDetachObjectARB'): print r' if (!retrace::dumpingState) {' Retracer.invokeFunction(self, function) print r' }' elif function.name == 'glClientWaitSync': print r' _result = glretrace::clientWaitSync(call, sync, flags, timeout);' print r' (void)_result;' elif function.name == 'glGetSynciv': print r' if (pname == GL_SYNC_STATUS &&' print r' bufSize >= 1 &&' print r' values != NULL &&' print r' call.arg(4)[0].toSInt() == GL_SIGNALED) {' print r' // Fence was signalled, so ensure it happened here' print r' glretrace::blockOnFence(call, sync, GL_SYNC_FLUSH_COMMANDS_BIT);' print r' (void)length;' print r' }' else: Retracer.invokeFunction(self, function) # Ensure this context flushes before switching to another thread to # prevent deadlock. # TODO: Defer flushing until another thread actually invokes # ClientWaitSync. if function.name.startswith("glFenceSync"): print ' if (currentContext) {' print ' currentContext->needsFlush = true;' print ' }' if function.name in ("glFlush", "glFinish"): print ' if (currentContext) {' print ' currentContext->needsFlush = false;' print ' }' if function.name == "glBegin": print ' if (currentContext) {' print ' currentContext->insideBeginEnd = true;' print ' }' print r' if (currentContext && !currentContext->insideList && !currentContext->insideBeginEnd && retrace::profiling) {' if profileDraw: print r' glretrace::endProfile(call, true);' else: print r' glretrace::endProfile(call, false);' print r' }' # Error checking if function.name.startswith('gl'): # glGetError is not allowed inside glBegin/glEnd print ' if (retrace::debug && currentContext && !currentContext->insideBeginEnd) {' print ' glretrace::checkGlError(call);' if function.name in ('glProgramStringARB', 'glLoadProgramNV'): print r' GLint error_position = -1;' print r' glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);' print r' if (error_position != -1) {' print r' const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);' print r' retrace::warning(call) << "error in position " << error_position << ": " << error_string << "\n";' print r' }' if function.name == 'glCompileShader': print r' GLint compile_status = 0;' print r' glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);' print r' if (!compile_status) {' print r' retrace::warning(call) << "compilation failed\n";' print r' }' print r' GLint info_log_length = 0;' print r' glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);' print r' if (info_log_length > 1) {' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name in ('glLinkProgram', 'glCreateShaderProgramv', 'glCreateShaderProgramEXT', 'glCreateShaderProgramvEXT', 'glProgramBinary', 'glProgramBinaryOES'): if function.name.startswith('glCreateShaderProgram'): print r' GLuint program = _result;' print r' GLint link_status = 0;' print r' glGetProgramiv(program, GL_LINK_STATUS, &link_status);' print r' if (!link_status) {' print r' retrace::warning(call) << "link failed\n";' print r' }' print r' GLint info_log_length = 0;' print r' glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);' print r' if (info_log_length > 1) {' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetProgramInfoLog(program, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name == 'glCompileShaderARB': print r' GLint compile_status = 0;' print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);' print r' if (!compile_status) {' print r' retrace::warning(call) << "compilation failed\n";' print r' }' print r' GLint info_log_length = 0;' print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);' print r' if (info_log_length > 1) {' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name == 'glLinkProgramARB': print r' GLint link_status = 0;' print r' glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);' print r' if (!link_status) {' print r' retrace::warning(call) << "link failed\n";' print r' }' print r' GLint info_log_length = 0;' print r' glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);' print r' if (info_log_length > 1) {' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if self.map_function_regex.match(function.name): print r' if (!_result) {' print r' retrace::warning(call) << "failed to map buffer\n";' print r' }' if self.unmap_function_regex.match(function.name) and function.type is not stdapi.Void: print r' if (!_result) {' print r' retrace::warning(call) << "failed to unmap buffer\n";' print r' }' if function.name in ('glGetAttribLocation', 'glGetAttribLocationARB'): print r' GLint _origResult = call.ret->toSInt();' print r' if (_result != _origResult) {' print r' retrace::warning(call) << "vertex attrib location mismatch " << _origResult << " -> " << _result << "\n";' print r' }' if function.name in ('glCheckFramebufferStatus', 'glCheckFramebufferStatusEXT', 'glCheckNamedFramebufferStatus', 'glCheckNamedFramebufferStatusEXT'): print r' GLint _origResult = call.ret->toSInt();' print r' if (_origResult == GL_FRAMEBUFFER_COMPLETE &&' print r' _result != GL_FRAMEBUFFER_COMPLETE) {' print r' retrace::warning(call) << "incomplete framebuffer (" << glstate::enumToString(_result) << ")\n";' print r' }' print ' }' # Query the buffer length for whole buffer mappings if self.map_function_regex.match(function.name): if 'length' in function.argNames(): assert 'BufferRange' in function.name else: assert 'BufferRange' not in function.name print r' GLint length = 0;' if function.name in ('glMapBuffer', 'glMapBufferOES'): print r' glGetBufferParameteriv(target, GL_BUFFER_SIZE, &length);' elif function.name == 'glMapBufferARB': print r' glGetBufferParameterivARB(target, GL_BUFFER_SIZE_ARB, &length);' elif function.name == 'glMapNamedBuffer': print r' glGetNamedBufferParameteriv(buffer, GL_BUFFER_SIZE, &length);' elif function.name == 'glMapNamedBufferEXT': print r' glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_SIZE, &length);' elif function.name == 'glMapObjectBufferATI': print r' glGetObjectBufferivATI(buffer, GL_OBJECT_BUFFER_SIZE_ATI, &length);' else: assert False
def invokeFunction(self, function): # Infer the drawable size from GL calls if function.name == "glViewport": print ' glretrace::updateDrawable(x + width, y + height);' if function.name == "glViewportArray": # We are concerned about drawables so only care for the first viewport print ' if (first == 0 && count > 0) {' print ' GLfloat x = v[0], y = v[1], w = v[2], h = v[3];' print ' glretrace::updateDrawable(x + w, y + h);' print ' }' if function.name == "glViewportIndexedf": print ' if (index == 0) {' print ' glretrace::updateDrawable(x + w, y + h);' print ' }' if function.name == "glViewportIndexedfv": print ' if (index == 0) {' print ' GLfloat x = v[0], y = v[1], w = v[2], h = v[3];' print ' glretrace::updateDrawable(x + w, y + h);' print ' }' if function.name in ('glBlitFramebuffer', 'glBlitFramebufferEXT'): # Some applications do all their rendering in a framebuffer, and # then just blit to the drawable without ever calling glViewport. print ' glretrace::updateDrawable(std::max(dstX0, dstX1), std::max(dstY0, dstY1));' if function.name.startswith( 'gl') and not function.name.startswith('glX'): print r' glretrace::Context *currentContext = glretrace::getCurrentContext();' print r' if (retrace::debug && !currentContext) {' print r' retrace::warning(call) << "no current context\n";' print r' }' if function.name == "glEnd": print r' if (currentContext) {' print r' currentContext->insideBeginEnd = false;' print r' }' if function.name == 'memcpy': print ' if (!dest || !src || !n) return;' # Skip glEnable/Disable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB) as we don't # faithfully set the CONTEXT_DEBUG_BIT_ARB flags on context creation. if function.name in ('glEnable', 'glDisable'): print ' if (cap == GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB) return;' # Destroy the buffer mapping if self.unmap_function_regex.match(function.name): print r' GLvoid *ptr = NULL;' if function.name == 'glUnmapBuffer': print r' glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &ptr);' elif function.name == 'glUnmapBufferARB': print r' glGetBufferPointervARB(target, GL_BUFFER_MAP_POINTER_ARB, &ptr);' elif function.name == 'glUnmapBufferOES': print r' glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &ptr);' elif function.name == 'glUnmapNamedBuffer': print r' glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &ptr);' elif function.name == 'glUnmapNamedBuffer': print r' glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &ptr);' elif function.name == 'glUnmapNamedBufferEXT': print r' glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &ptr);' elif function.name == 'glUnmapObjectBufferATI': # TODO pass else: assert False print r' if (ptr) {' print r' retrace::delRegionByPointer(ptr);' print r' } else {' print r' retrace::warning(call) << "failed to get mapped pointer\n";' print r' }' if function.name in ('glBindProgramPipeline', 'glBindProgramPipelineEXT'): # Note if glBindProgramPipeline has ever been called print r' if (pipeline) {' print r' _pipelineHasBeenBound = true;' print r' }' is_draw_arrays = self.draw_arrays_function_regex.match( function.name) is not None is_draw_elements = self.draw_elements_function_regex.match( function.name) is not None is_misc_draw = self.misc_draw_function_regex.match( function.name) is not None profileDraw = (is_draw_arrays or is_draw_elements or is_misc_draw or function.name == 'glBegin') # Keep track of active program for call lists if function.name in ('glUseProgram', 'glUseProgramObjectARB'): print r' if (currentContext) {' print r' currentContext->activeProgram = call.arg(0).toUInt();' print r' }' # Only profile if not inside a list as the queries get inserted into list if function.name == 'glNewList': print r' if (currentContext) {' print r' currentContext->insideList = true;' print r' }' if function.name == 'glEndList': print r' if (currentContext) {' print r' currentContext->insideList = false;' print r' }' if function.name == 'glBegin' or \ is_draw_arrays or \ is_draw_elements or \ function.name.startswith('glBeginTransformFeedback'): print r' if (retrace::debug) {' print r' _validateActiveProgram(call);' print r' }' if function.name != 'glEnd': print r' if (currentContext && !currentContext->insideList && !currentContext->insideBeginEnd && retrace::profiling) {' if profileDraw: print r' glretrace::beginProfile(call, true);' else: print r' glretrace::beginProfile(call, false);' print r' }' if function.name in ('glCreateShaderProgramv', 'glCreateShaderProgramEXT', 'glCreateShaderProgramvEXT'): # When dumping state, break down glCreateShaderProgram* so that the # shader source can be recovered. print r' if (retrace::dumpingState) {' print r' GLuint _shader = glCreateShader(type);' print r' if (_shader) {' if not function.name.startswith('glCreateShaderProgramv'): print r' GLsizei count = 1;' print r' const GLchar **strings = &string;' print r' glShaderSource(_shader, count, strings, NULL);' print r' glCompileShader(_shader);' print r' const GLuint _program = glCreateProgram();' print r' if (_program) {' print r' GLint compiled = GL_FALSE;' print r' glGetShaderiv(_shader, GL_COMPILE_STATUS, &compiled);' if function.name == 'glCreateShaderProgramvEXT': print r' glProgramParameteriEXT(_program, GL_PROGRAM_SEPARABLE, GL_TRUE);' else: print r' glProgramParameteri(_program, GL_PROGRAM_SEPARABLE, GL_TRUE);' print r' if (compiled) {' print r' glAttachShader(_program, _shader);' print r' glLinkProgram(_program);' print r' if (false) glDetachShader(_program, _shader);' print r' }' print r' // TODO: append shader info log to program info log' print r' }' print r' glDeleteShader(_shader);' print r' _result = _program;' print r' } else {' print r' _result = 0;' print r' }' print r' } else {' Retracer.invokeFunction(self, function) print r' }' elif function.name in ('glDetachShader', 'glDetachObjectARB'): print r' if (!retrace::dumpingState) {' Retracer.invokeFunction(self, function) print r' }' elif function.name == 'glClientWaitSync': print r' _result = glretrace::clientWaitSync(call, sync, flags, timeout);' print r' (void)_result;' elif function.name == 'glGetSynciv': print r' if (pname == GL_SYNC_STATUS &&' print r' bufSize >= 1 &&' print r' values != NULL &&' print r' call.arg(4)[0].toSInt() == GL_SIGNALED) {' print r' // Fence was signalled, so ensure it happened here' print r' glretrace::blockOnFence(call, sync, GL_SYNC_FLUSH_COMMANDS_BIT);' print r' (void)length;' print r' }' else: Retracer.invokeFunction(self, function) if function.name == "glBegin": print ' if (currentContext) {' print ' currentContext->insideBeginEnd = true;' print ' }' print r' if (currentContext && !currentContext->insideList && !currentContext->insideBeginEnd && retrace::profiling) {' if profileDraw: print r' glretrace::endProfile(call, true);' else: print r' glretrace::endProfile(call, false);' print r' }' # Error checking if function.name.startswith('gl'): # glGetError is not allowed inside glBegin/glEnd print ' if (retrace::debug && currentContext && !currentContext->insideBeginEnd) {' print ' glretrace::checkGlError(call);' if function.name in ('glProgramStringARB', 'glLoadProgramNV'): print r' GLint error_position = -1;' print r' glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);' print r' if (error_position != -1) {' print r' const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);' print r' retrace::warning(call) << "error in position " << error_position << ": " << error_string << "\n";' print r' }' if function.name == 'glCompileShader': print r' GLint compile_status = 0;' print r' glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);' print r' if (!compile_status) {' print r' retrace::warning(call) << "compilation failed\n";' print r' }' print r' GLint info_log_length = 0;' print r' glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);' print r' if (info_log_length > 1) {' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name in ('glLinkProgram', 'glCreateShaderProgramv', 'glCreateShaderProgramEXT', 'glCreateShaderProgramvEXT', 'glProgramBinary', 'glProgramBinaryOES'): if function.name.startswith('glCreateShaderProgram'): print r' GLuint program = _result;' print r' GLint link_status = 0;' print r' glGetProgramiv(program, GL_LINK_STATUS, &link_status);' print r' if (!link_status) {' print r' retrace::warning(call) << "link failed\n";' print r' }' print r' GLint info_log_length = 0;' print r' glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);' print r' if (info_log_length > 1) {' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetProgramInfoLog(program, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name == 'glCompileShaderARB': print r' GLint compile_status = 0;' print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);' print r' if (!compile_status) {' print r' retrace::warning(call) << "compilation failed\n";' print r' }' print r' GLint info_log_length = 0;' print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);' print r' if (info_log_length > 1) {' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name == 'glLinkProgramARB': print r' GLint link_status = 0;' print r' glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);' print r' if (!link_status) {' print r' retrace::warning(call) << "link failed\n";' print r' }' print r' GLint info_log_length = 0;' print r' glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);' print r' if (info_log_length > 1) {' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if self.map_function_regex.match(function.name): print r' if (!_result) {' print r' retrace::warning(call) << "failed to map buffer\n";' print r' }' if self.unmap_function_regex.match( function.name) and function.type is not stdapi.Void: print r' if (!_result) {' print r' retrace::warning(call) << "failed to unmap buffer\n";' print r' }' if function.name in ('glGetAttribLocation', 'glGetAttribLocationARB'): print r' GLint _origResult = call.ret->toSInt();' print r' if (_result != _origResult) {' print r' retrace::warning(call) << "vertex attrib location mismatch " << _origResult << " -> " << _result << "\n";' print r' }' if function.name in ('glCheckFramebufferStatus', 'glCheckFramebufferStatusEXT', 'glCheckNamedFramebufferStatus', 'glCheckNamedFramebufferStatusEXT'): print r' GLint _origResult = call.ret->toSInt();' print r' if (_origResult == GL_FRAMEBUFFER_COMPLETE &&' print r' _result != GL_FRAMEBUFFER_COMPLETE) {' print r' retrace::warning(call) << "incomplete framebuffer (" << glstate::enumToString(_result) << ")\n";' print r' }' print ' }' # Query the buffer length for whole buffer mappings if self.map_function_regex.match(function.name): if 'length' in function.argNames(): assert 'BufferRange' in function.name else: assert 'BufferRange' not in function.name print r' GLint length = 0;' if function.name in ('glMapBuffer', 'glMapBufferOES'): print r' glGetBufferParameteriv(target, GL_BUFFER_SIZE, &length);' elif function.name == 'glMapBufferARB': print r' glGetBufferParameterivARB(target, GL_BUFFER_SIZE_ARB, &length);' elif function.name == 'glMapNamedBuffer': print r' glGetNamedBufferParameteriv(buffer, GL_BUFFER_SIZE, &length);' elif function.name == 'glMapNamedBufferEXT': print r' glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_SIZE, &length);' elif function.name == 'glMapObjectBufferATI': print r' glGetObjectBufferivATI(buffer, GL_OBJECT_BUFFER_SIZE_ATI, &length);' else: assert False
def call_function(self, function): # Infer the drawable size from GL calls if function.name == "glViewport": print ' glretrace::updateDrawable(x + width, y + height);' if function.name in ('glBlitFramebuffer', 'glBlitFramebufferEXT'): # Some applications do all their rendering in a framebuffer, and # then just blit to the drawable without ever calling glViewport. print ' glretrace::updateDrawable(std::max(dstX0, dstX1), std::max(dstY0, dstY1));' if function.name == "glEnd": print ' glretrace::insideGlBeginEnd = false;' if function.name == 'memcpy': print ' if (!dest || !src || !n) return;' Retracer.call_function(self, function) # Error checking if function.name == "glBegin": print ' glretrace::insideGlBeginEnd = true;' elif function.name.startswith('gl'): # glGetError is not allowed inside glBegin/glEnd print ' if (!glretrace::benchmark && !glretrace::insideGlBeginEnd) {' print ' glretrace::checkGlError(call);' if function.name in ('glProgramStringARB', 'glProgramStringNV'): print r' GLint error_position = -1;' print r' glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);' print r' if (error_position != -1) {' print r' const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);' print r' retrace::warning(call) << error_string << "\n";' print r' }' if function.name == 'glCompileShader': print r' GLint compile_status = 0;' print r' glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);' print r' if (!compile_status) {' print r' GLint info_log_length = 0;' print r' glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name == 'glLinkProgram': print r' GLint link_status = 0;' print r' glGetProgramiv(program, GL_LINK_STATUS, &link_status);' print r' if (!link_status) {' print r' GLint info_log_length = 0;' print r' glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetProgramInfoLog(program, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name == 'glCompileShaderARB': print r' GLint compile_status = 0;' print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);' print r' if (!compile_status) {' print r' GLint info_log_length = 0;' print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name == 'glLinkProgramARB': print r' GLint link_status = 0;' print r' glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);' print r' if (!link_status) {' print r' GLint info_log_length = 0;' print r' glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);' print r' retrace::warning(call) << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name in self.map_function_names: print r' if (!__result) {' print r' retrace::warning(call) << "failed to map buffer\n";' print r' }' if function.name in ('glGetAttribLocation', 'glGetAttribLocationARB'): print r' GLint __orig_result = call.ret->toSInt();' print r' if (__result != __orig_result) {' print r' retrace::warning(call) << "vertex attrib location mismatch " << __orig_result << " -> " << __result << "\n";' print r' }' if function.name in ('glCheckFramebufferStatus', 'glCheckFramebufferStatusEXT', 'glCheckNamedFramebufferStatusEXT'): print r' GLint __orig_result = call.ret->toSInt();' print r' if (__orig_result == GL_FRAMEBUFFER_COMPLETE &&' print r' __result != GL_FRAMEBUFFER_COMPLETE) {' print r' retrace::warning(call) << "incomplete framebuffer (" << glstate::enumToString(__result) << ")\n";' print r' }' print ' }' # Update buffer mappings if function.name in self.map_function_names: print r' if (__result) {' print r' unsigned long long __address = call.ret->toUIntPtr();' if 'BufferRange' not in function.name: print r' GLint length = 0;' if function.name == 'glMapBuffer': print r' glGetBufferParameteriv(target, GL_BUFFER_SIZE, &length);' elif function.name == 'glMapBufferARB': print r' glGetBufferParameterivARB(target, GL_BUFFER_SIZE_ARB, &length);' elif function.name == 'glMapNamedBufferEXT': print r' glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_SIZE, &length);' else: assert False print r' retrace::addRegion(__address, __result, length);' print r' }' if function.name in self.unmap_function_names: print r' GLvoid *ptr = NULL;' if function.name == 'glUnmapBuffer': print r' glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &ptr);' elif function.name == 'glUnmapBufferARB': print r' glGetBufferPointervARB(target, GL_BUFFER_MAP_POINTER_ARB, &ptr);' elif function.name == 'glUnmapNamedBufferEXT': print r' glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &ptr);' else: assert False print r' if (ptr) {' print r' retrace::delRegionByPointer(ptr);' print r' }'
def retraceFunctionBody(self, function): is_array_pointer = function.name in self.array_pointer_function_names is_draw_arrays = self.draw_arrays_function_regex.match(function.name) is not None is_draw_elements = self.draw_elements_function_regex.match(function.name) is not None is_draw_indirect = self.draw_indirect_function_regex.match(function.name) is not None is_misc_draw = self.misc_draw_function_regex.match(function.name) if function.name.startswith('gl') and not function.name.startswith('glX'): # The Windows OpenGL runtime will skip calls when there's no # context bound to the current context, but this might cause # crashes on other systems, particularly with NVIDIA Linux drivers. print r' glretrace::Context *currentContext = glretrace::getCurrentContext();' print r' if (!currentContext) {' print r' if (retrace::debug) {' print r' retrace::warning(call) << "no current context\n";' print r' }' print r'#ifndef _WIN32' print r' return;' print r'#endif' print r' }' print r' if (retrace::markers) {' print r' glretrace::insertCallMarker(call, currentContext);' print r' }' # For backwards compatibility with old traces where non VBO drawing was supported if (is_array_pointer or is_draw_arrays or is_draw_elements) and not is_draw_indirect: print ' if (retrace::parser->getVersion() < 1) {' if is_array_pointer or is_draw_arrays: print ' GLint _array_buffer = 0;' print ' glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &_array_buffer);' print ' if (!_array_buffer) {' self.failFunction(function) print ' }' if is_draw_elements: print ' GLint _element_array_buffer = 0;' print ' glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &_element_array_buffer);' print ' if (!_element_array_buffer) {' self.failFunction(function) print ' }' print ' }' # When no pack buffer object is bound, the pack functions are no-ops. if self.pack_function_regex.match(function.name): print r' GLint _pack_buffer = 0;' print r' if (currentContext->features().pixel_buffer_object) {' print r' glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &_pack_buffer);' print r' }' print r' if (!_pack_buffer) {' print r' return;' print r' }' # When no query buffer object is bound, glGetQueryObject is a no-op. if function.name.startswith('glGetQueryObject'): print r' GLint _query_buffer = 0;' print r' if (currentContext->features().query_buffer_object) {' print r' glGetIntegerv(GL_QUERY_BUFFER_BINDING, &_query_buffer);' print r' }' print r' if (!_query_buffer) {' print r' return;' print r' }' # Pre-snapshots if self.bind_framebuffer_function_regex.match(function.name): print ' assert(call.flags & trace::CALL_FLAG_SWAP_RENDERTARGET);' if function.name == 'glStringMarkerGREMEDY': return if function.name == 'glFrameTerminatorGREMEDY': print ' glretrace::frame_complete(call);' return Retracer.retraceFunctionBody(self, function) # Post-snapshots if function.name in ('glFlush', 'glFinish'): print ' if (!retrace::doubleBuffer) {' print ' glretrace::frame_complete(call);' print ' }' if is_draw_arrays or is_draw_elements or is_misc_draw: print ' assert(call.flags & trace::CALL_FLAG_RENDER);'
def call_function(self, function): # Infer the drawable size from GL calls if function.name == "glViewport": print " glretrace::updateDrawable(x + width, y + height);" if function.name in ("glBlitFramebuffer", "glBlitFramebufferEXT"): # Some applications do all their rendering in a framebuffer, and # then just blit to the drawable without ever calling glViewport. print " glretrace::updateDrawable(std::max(dstX0, dstX1), std::max(dstY0, dstY1));" if function.name == "glEnd": print " glretrace::insideGlBeginEnd = false;" if function.name == "memcpy": print " if (!dest || !src || !n) return;" Retracer.call_function(self, function) # Error checking if function.name == "glBegin": print " glretrace::insideGlBeginEnd = true;" elif function.name.startswith("gl"): # glGetError is not allowed inside glBegin/glEnd print " if (!glretrace::benchmark && !glretrace::insideGlBeginEnd) {" print " glretrace::checkGlError(call);" if function.name in ("glProgramStringARB", "glProgramStringNV"): print r" GLint error_position = -1;" print r" glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);" print r" if (error_position != -1) {" print r" const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);" print r' retrace::warning(call) << error_string << "\n";' print r" }" if function.name == "glCompileShader": print r" GLint compile_status = 0;" print r" glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);" print r" if (!compile_status) {" print r" GLint info_log_length = 0;" print r" glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);" print r" GLchar *infoLog = new GLchar[info_log_length];" print r" glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);" print r' retrace::warning(call) << infoLog << "\n";' print r" delete [] infoLog;" print r" }" if function.name == "glLinkProgram": print r" GLint link_status = 0;" print r" glGetProgramiv(program, GL_LINK_STATUS, &link_status);" print r" if (!link_status) {" print r" GLint info_log_length = 0;" print r" glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);" print r" GLchar *infoLog = new GLchar[info_log_length];" print r" glGetProgramInfoLog(program, info_log_length, NULL, infoLog);" print r' retrace::warning(call) << infoLog << "\n";' print r" delete [] infoLog;" print r" }" if function.name == "glCompileShaderARB": print r" GLint compile_status = 0;" print r" glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);" print r" if (!compile_status) {" print r" GLint info_log_length = 0;" print r" glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);" print r" GLchar *infoLog = new GLchar[info_log_length];" print r" glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);" print r' retrace::warning(call) << infoLog << "\n";' print r" delete [] infoLog;" print r" }" if function.name == "glLinkProgramARB": print r" GLint link_status = 0;" print r" glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);" print r" if (!link_status) {" print r" GLint info_log_length = 0;" print r" glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);" print r" GLchar *infoLog = new GLchar[info_log_length];" print r" glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);" print r' retrace::warning(call) << infoLog << "\n";' print r" delete [] infoLog;" print r" }" if function.name in self.map_function_names: print r" if (!__result) {" print r' retrace::warning(call) << "failed to map buffer\n";' print r" }" if function.name in ("glGetAttribLocation", "glGetAttribLocationARB"): print r" GLint __orig_result = call.ret->toSInt();" print r" if (__result != __orig_result) {" print r' retrace::warning(call) << "vertex attrib location mismatch " << __orig_result << " -> " << __result << "\n";' print r" }" if function.name in ( "glCheckFramebufferStatus", "glCheckFramebufferStatusEXT", "glCheckNamedFramebufferStatusEXT", ): print r" GLint __orig_result = call.ret->toSInt();" print r" if (__orig_result == GL_FRAMEBUFFER_COMPLETE &&" print r" __result != GL_FRAMEBUFFER_COMPLETE) {" print r' retrace::warning(call) << "incomplete framebuffer (" << glstate::enumToString(__result) << ")\n";' print r" }" print " }" # Update buffer mappings if function.name in self.map_function_names: print r" if (__result) {" print r" unsigned long long __address = call.ret->toUIntPtr();" if "BufferRange" not in function.name: print r" GLint length = 0;" if function.name == "glMapBuffer": print r" glGetBufferParameteriv(target, GL_BUFFER_SIZE, &length);" elif function.name == "glMapBufferARB": print r" glGetBufferParameterivARB(target, GL_BUFFER_SIZE_ARB, &length);" elif function.name == "glMapNamedBufferEXT": print r" glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_SIZE, &length);" else: assert False print r" retrace::addRegion(__address, __result, length);" print r" }" if function.name in self.unmap_function_names: print r" GLvoid *ptr = NULL;" if function.name == "glUnmapBuffer": print r" glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &ptr);" elif function.name == "glUnmapBufferARB": print r" glGetBufferPointervARB(target, GL_BUFFER_MAP_POINTER_ARB, &ptr);" elif function.name == "glUnmapNamedBufferEXT": print r" glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &ptr);" else: assert False print r" if (ptr) {" print r" retrace::delRegionByPointer(ptr);" print r" }"
def retrace_function(self, function): Retracer.retrace_function(self, function)
def call_function(self, function): if function.name == "glViewport": print ' if (glretrace::drawable) {' print ' int drawable_width = x + width;' print ' int drawable_height = y + height;' print ' if (drawable_width > (int)glretrace::drawable->width ||' print ' drawable_height > (int)glretrace::drawable->height) {' print ' glretrace::drawable->resize(drawable_width, drawable_height);' print ' if (!glretrace::drawable->visible) {' print ' glretrace::drawable->show();' print ' }' print ' glScissor(0, 0, drawable_width, drawable_height);' print ' }' print ' }' if function.name == "glEnd": print ' glretrace::insideGlBeginEnd = false;' if function.name == 'memcpy': print ' if (!dest || !src || !n) return;' Retracer.call_function(self, function) # Error checking if function.name == "glBegin": print ' glretrace::insideGlBeginEnd = true;' elif function.name.startswith('gl'): # glGetError is not allowed inside glBegin/glEnd print ' if (!glretrace::benchmark && !glretrace::insideGlBeginEnd) {' print ' glretrace::checkGlError(call);' if function.name in ('glProgramStringARB', 'glProgramStringNV'): print r' GLint error_position = -1;' print r' glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);' print r' if (error_position != -1) {' print r' const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);' print r' std::cerr << call.no << ": warning: " << error_string << "\n";' print r' }' if function.name == 'glCompileShader': print r' GLint compile_status = 0;' print r' glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);' print r' if (!compile_status) {' print r' GLint info_log_length = 0;' print r' glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);' print r' std::cerr << call.no << ": warning: " << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name == 'glLinkProgram': print r' GLint link_status = 0;' print r' glGetProgramiv(program, GL_LINK_STATUS, &link_status);' print r' if (!link_status) {' print r' GLint info_log_length = 0;' print r' glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetProgramInfoLog(program, info_log_length, NULL, infoLog);' print r' std::cerr << call.no << ": warning: " << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name == 'glCompileShaderARB': print r' GLint compile_status = 0;' print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);' print r' if (!compile_status) {' print r' GLint info_log_length = 0;' print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);' print r' std::cerr << call.no << ": warning: " << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name == 'glLinkProgramARB': print r' GLint link_status = 0;' print r' glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);' print r' if (!link_status) {' print r' GLint info_log_length = 0;' print r' glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);' print r' GLchar *infoLog = new GLchar[info_log_length];' print r' glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);' print r' std::cerr << call.no << ": warning: " << infoLog << "\n";' print r' delete [] infoLog;' print r' }' if function.name in ('glMapBuffer', 'glMapBufferARB', 'glMapBufferRange', 'glMapNamedBufferEXT', 'glMapNamedBufferRangeEXT'): print r' if (!__result) {' print r' std::cerr << call.no << ": warning: failed to map buffer\n";' print r' }' if function.name in ('glGetAttribLocation', 'glGetAttribLocationARB'): print r' GLint __orig_result = call.ret->toSInt();' print r' if (__result != __orig_result) {' print r' std::cerr << call.no << ": warning vertex attrib location mismatch " << __orig_result << " -> " << __result << "\n";' print r' }' print ' }'
def retraceApi(self, api): dispatcher = DllDispatcher() dispatcher.dispatchApi(api) Retracer.retraceApi(self, api)
def retraceFunction(self, function): Retracer.retraceFunction(self, function)
def call_function(self, function): if function.name == "glViewport": print " if (glretrace::drawable) {" print " int drawable_width = x + width;" print " int drawable_height = y + height;" print " if (drawable_width > (int)glretrace::drawable->width ||" print " drawable_height > (int)glretrace::drawable->height) {" print " glretrace::drawable->resize(drawable_width, drawable_height);" print " if (!glretrace::drawable->visible) {" print " glretrace::drawable->show();" print " }" print " glScissor(0, 0, drawable_width, drawable_height);" print " }" print " }" if function.name == "glEnd": print " glretrace::insideGlBeginEnd = false;" if function.name == "memcpy": print " if (!dest || !src || !n) return;" Retracer.call_function(self, function) # Error checking if function.name == "glBegin": print " glretrace::insideGlBeginEnd = true;" elif function.name.startswith("gl"): # glGetError is not allowed inside glBegin/glEnd print " if (!glretrace::benchmark && !glretrace::insideGlBeginEnd) {" print " glretrace::checkGlError(call);" if function.name in ("glProgramStringARB", "glProgramStringNV"): print r" GLint error_position = -1;" print r" glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);" print r" if (error_position != -1) {" print r" const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);" print r' std::cerr << call.no << ": warning: " << error_string << "\n";' print r" }" if function.name == "glCompileShader": print r" GLint compile_status = 0;" print r" glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);" print r" if (!compile_status) {" print r" GLint info_log_length = 0;" print r" glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);" print r" GLchar *infoLog = new GLchar[info_log_length];" print r" glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);" print r' std::cerr << call.no << ": warning: " << infoLog << "\n";' print r" delete [] infoLog;" print r" }" if function.name == "glLinkProgram": print r" GLint link_status = 0;" print r" glGetProgramiv(program, GL_LINK_STATUS, &link_status);" print r" if (!link_status) {" print r" GLint info_log_length = 0;" print r" glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);" print r" GLchar *infoLog = new GLchar[info_log_length];" print r" glGetProgramInfoLog(program, info_log_length, NULL, infoLog);" print r' std::cerr << call.no << ": warning: " << infoLog << "\n";' print r" delete [] infoLog;" print r" }" if function.name == "glCompileShaderARB": print r" GLint compile_status = 0;" print r" glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);" print r" if (!compile_status) {" print r" GLint info_log_length = 0;" print r" glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);" print r" GLchar *infoLog = new GLchar[info_log_length];" print r" glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);" print r' std::cerr << call.no << ": warning: " << infoLog << "\n";' print r" delete [] infoLog;" print r" }" if function.name == "glLinkProgramARB": print r" GLint link_status = 0;" print r" glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);" print r" if (!link_status) {" print r" GLint info_log_length = 0;" print r" glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);" print r" GLchar *infoLog = new GLchar[info_log_length];" print r" glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);" print r' std::cerr << call.no << ": warning: " << infoLog << "\n";' print r" delete [] infoLog;" print r" }" if function.name in ( "glMapBuffer", "glMapBufferARB", "glMapBufferRange", "glMapNamedBufferEXT", "glMapNamedBufferRangeEXT", ): print r" if (!__result) {" print r' std::cerr << call.no << ": warning: failed to map buffer\n";' print r" }" if function.name in ("glGetAttribLocation", "glGetAttribLocationARB"): print r" GLint __orig_result = call.ret->toSInt();" print r" if (__result != __orig_result) {" print r' std::cerr << call.no << ": warning vertex attrib location mismatch " << __orig_result << " -> " << __result << "\n";' print r" }" if function.name in ( "glCheckFramebufferStatus", "glCheckFramebufferStatusEXT", "glCheckNamedFramebufferStatusEXT", ): print r" GLint __orig_result = call.ret->toSInt();" print r" if (__orig_result == GL_FRAMEBUFFER_COMPLETE &&" print r" __result != GL_FRAMEBUFFER_COMPLETE) {" print r' std::cerr << call.no << ": incomplete framebuffer (" << __result << ")\n";' print r" }" print " }"
def invokeFunction(self, function): # Infer the drawable size from GL calls if function.name == "glViewport": print " glretrace::updateDrawable(x + width, y + height);" if function.name == "glViewportArray": # We are concerned about drawables so only care for the first viewport print " if (first == 0 && count > 0) {" print " GLfloat x = v[0], y = v[1], w = v[2], h = v[3];" print " glretrace::updateDrawable(x + w, y + h);" print " }" if function.name == "glViewportIndexedf": print " if (index == 0) {" print " glretrace::updateDrawable(x + w, y + h);" print " }" if function.name == "glViewportIndexedfv": print " if (index == 0) {" print " GLfloat x = v[0], y = v[1], w = v[2], h = v[3];" print " glretrace::updateDrawable(x + w, y + h);" print " }" if function.name in ("glBlitFramebuffer", "glBlitFramebufferEXT"): # Some applications do all their rendering in a framebuffer, and # then just blit to the drawable without ever calling glViewport. print " glretrace::updateDrawable(std::max(dstX0, dstX1), std::max(dstY0, dstY1));" if function.name == "glEnd": print " glretrace::insideGlBeginEnd = false;" if function.name.startswith("gl") and not function.name.startswith("glX"): print r" if (retrace::debug && !glretrace::getCurrentContext()) {" print r' retrace::warning(call) << "no current context\n";' print r" }" if function.name == "memcpy": print " if (!dest || !src || !n) return;" # Skip glEnable/Disable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB) as we don't # faithfully set the CONTEXT_DEBUG_BIT_ARB flags on context creation. if function.name in ("glEnable", "glDisable"): print " if (cap == GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB) return;" # Destroy the buffer mapping if self.unmap_function_regex.match(function.name): print r" GLvoid *ptr = NULL;" if function.name == "glUnmapBuffer": print r" glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &ptr);" elif function.name == "glUnmapBufferARB": print r" glGetBufferPointervARB(target, GL_BUFFER_MAP_POINTER_ARB, &ptr);" elif function.name == "glUnmapBufferOES": print r" glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &ptr);" elif function.name == "glUnmapNamedBuffer": print r" glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &ptr);" elif function.name == "glUnmapNamedBuffer": print r" glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &ptr);" elif function.name == "glUnmapNamedBufferEXT": print r" glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &ptr);" elif function.name == "glUnmapObjectBufferATI": # TODO pass else: assert False print r" if (ptr) {" print r" retrace::delRegionByPointer(ptr);" print r" } else {" print r' retrace::warning(call) << "failed to get mapped pointer\n";' print r" }" if function.name in ("glBindProgramPipeline", "glBindProgramPipelineEXT"): # Note if glBindProgramPipeline has ever been called print r" if (pipeline) {" print r" _pipelineHasBeenBound = true;" print r" }" is_draw_arrays = self.draw_arrays_function_regex.match(function.name) is not None is_draw_elements = self.draw_elements_function_regex.match(function.name) is not None is_misc_draw = self.misc_draw_function_regex.match(function.name) is not None profileDraw = is_draw_arrays or is_draw_elements or is_misc_draw or function.name == "glBegin" # Keep track of active program for call lists if function.name in ("glUseProgram", "glUseProgramObjectARB"): print r" glretrace::Context *currentContext = glretrace::getCurrentContext();" print r" if (currentContext) {" print r" currentContext->activeProgram = call.arg(0).toUInt();" print r" }" # Only profile if not inside a list as the queries get inserted into list if function.name == "glNewList": print r" glretrace::insideList = true;" if function.name == "glEndList": print r" glretrace::insideList = false;" if ( function.name == "glBegin" or is_draw_arrays or is_draw_elements or function.name.startswith("glBeginTransformFeedback") ): print r" if (retrace::debug && !glretrace::insideGlBeginEnd && glretrace::getCurrentContext()) {" print r" _validateActiveProgram(call);" print r" }" if function.name != "glEnd": print r" if (!glretrace::insideList && !glretrace::insideGlBeginEnd && retrace::profiling) {" if profileDraw: print r" glretrace::beginProfile(call, true);" else: print r" glretrace::beginProfile(call, false);" print r" }" if function.name in ("glCreateShaderProgramv", "glCreateShaderProgramEXT", "glCreateShaderProgramvEXT"): # When dumping state, break down glCreateShaderProgram* so that the # shader source can be recovered. print r" if (retrace::dumpingState) {" print r" GLuint _shader = glCreateShader(type);" print r" if (_shader) {" if not function.name.startswith("glCreateShaderProgramv"): print r" GLsizei count = 1;" print r" const GLchar **strings = &string;" print r" glShaderSource(_shader, count, strings, NULL);" print r" glCompileShader(_shader);" print r" const GLuint _program = glCreateProgram();" print r" if (_program) {" print r" GLint compiled = GL_FALSE;" print r" glGetShaderiv(_shader, GL_COMPILE_STATUS, &compiled);" if function.name == "glCreateShaderProgramvEXT": print r" glProgramParameteriEXT(_program, GL_PROGRAM_SEPARABLE, GL_TRUE);" else: print r" glProgramParameteri(_program, GL_PROGRAM_SEPARABLE, GL_TRUE);" print r" if (compiled) {" print r" glAttachShader(_program, _shader);" print r" glLinkProgram(_program);" print r" if (false) glDetachShader(_program, _shader);" print r" }" print r" // TODO: append shader info log to program info log" print r" }" print r" glDeleteShader(_shader);" print r" _result = _program;" print r" } else {" print r" _result = 0;" print r" }" print r" } else {" Retracer.invokeFunction(self, function) print r" }" elif function.name in ("glDetachShader", "glDetachObjectARB"): print r" if (!retrace::dumpingState) {" Retracer.invokeFunction(self, function) print r" }" elif function.name == "glClientWaitSync": print r" _result = glretrace::clientWaitSync(call, sync, flags, timeout);" print r" (void)_result;" elif function.name == "glGetSynciv": print r" if (pname == GL_SYNC_STATUS &&" print r" bufSize >= 1 &&" print r" values != NULL &&" print r" call.arg(4)[0].toSInt() == GL_SIGNALED) {" print r" // Fence was signalled, so ensure it happened here" print r" glretrace::blockOnFence(call, sync, GL_SYNC_FLUSH_COMMANDS_BIT);" print r" (void)length;" print r" }" else: Retracer.invokeFunction(self, function) if function.name == "glBegin": print " glretrace::insideGlBeginEnd = true;" print r" if (!glretrace::insideList && !glretrace::insideGlBeginEnd && retrace::profiling) {" if profileDraw: print r" glretrace::endProfile(call, true);" else: print r" glretrace::endProfile(call, false);" print r" }" # Error checking if function.name.startswith("gl"): # glGetError is not allowed inside glBegin/glEnd print " if (retrace::debug && !glretrace::insideGlBeginEnd && glretrace::getCurrentContext()) {" print " glretrace::checkGlError(call);" if function.name in ("glProgramStringARB", "glLoadProgramNV"): print r" GLint error_position = -1;" print r" glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);" print r" if (error_position != -1) {" print r" const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);" print r' retrace::warning(call) << "error in position " << error_position << ": " << error_string << "\n";' print r" }" if function.name == "glCompileShader": print r" GLint compile_status = 0;" print r" glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);" print r" if (!compile_status) {" print r' retrace::warning(call) << "compilation failed\n";' print r" }" print r" GLint info_log_length = 0;" print r" glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);" print r" if (info_log_length > 1) {" print r" GLchar *infoLog = new GLchar[info_log_length];" print r" glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);" print r' retrace::warning(call) << infoLog << "\n";' print r" delete [] infoLog;" print r" }" if function.name in ( "glLinkProgram", "glCreateShaderProgramv", "glCreateShaderProgramEXT", "glCreateShaderProgramvEXT", "glProgramBinary", "glProgramBinaryOES", ): if function.name.startswith("glCreateShaderProgram"): print r" GLuint program = _result;" print r" GLint link_status = 0;" print r" glGetProgramiv(program, GL_LINK_STATUS, &link_status);" print r" if (!link_status) {" print r' retrace::warning(call) << "link failed\n";' print r" }" print r" GLint info_log_length = 0;" print r" glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);" print r" if (info_log_length > 1) {" print r" GLchar *infoLog = new GLchar[info_log_length];" print r" glGetProgramInfoLog(program, info_log_length, NULL, infoLog);" print r' retrace::warning(call) << infoLog << "\n";' print r" delete [] infoLog;" print r" }" if function.name == "glCompileShaderARB": print r" GLint compile_status = 0;" print r" glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);" print r" if (!compile_status) {" print r' retrace::warning(call) << "compilation failed\n";' print r" }" print r" GLint info_log_length = 0;" print r" glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);" print r" if (info_log_length > 1) {" print r" GLchar *infoLog = new GLchar[info_log_length];" print r" glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);" print r' retrace::warning(call) << infoLog << "\n";' print r" delete [] infoLog;" print r" }" if function.name == "glLinkProgramARB": print r" GLint link_status = 0;" print r" glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);" print r" if (!link_status) {" print r' retrace::warning(call) << "link failed\n";' print r" }" print r" GLint info_log_length = 0;" print r" glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);" print r" if (info_log_length > 1) {" print r" GLchar *infoLog = new GLchar[info_log_length];" print r" glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);" print r' retrace::warning(call) << infoLog << "\n";' print r" delete [] infoLog;" print r" }" if self.map_function_regex.match(function.name): print r" if (!_result) {" print r' retrace::warning(call) << "failed to map buffer\n";' print r" }" if self.unmap_function_regex.match(function.name) and function.type is not stdapi.Void: print r" if (!_result) {" print r' retrace::warning(call) << "failed to unmap buffer\n";' print r" }" if function.name in ("glGetAttribLocation", "glGetAttribLocationARB"): print r" GLint _origResult = call.ret->toSInt();" print r" if (_result != _origResult) {" print r' retrace::warning(call) << "vertex attrib location mismatch " << _origResult << " -> " << _result << "\n";' print r" }" if function.name in ( "glCheckFramebufferStatus", "glCheckFramebufferStatusEXT", "glCheckNamedFramebufferStatus", "glCheckNamedFramebufferStatusEXT", ): print r" GLint _origResult = call.ret->toSInt();" print r" if (_origResult == GL_FRAMEBUFFER_COMPLETE &&" print r" _result != GL_FRAMEBUFFER_COMPLETE) {" print r' retrace::warning(call) << "incomplete framebuffer (" << glstate::enumToString(_result) << ")\n";' print r" }" print " }" # Query the buffer length for whole buffer mappings if self.map_function_regex.match(function.name): if "length" in function.argNames(): assert "BufferRange" in function.name else: assert "BufferRange" not in function.name print r" GLint length = 0;" if function.name in ("glMapBuffer", "glMapBufferOES"): print r" glGetBufferParameteriv(target, GL_BUFFER_SIZE, &length);" elif function.name == "glMapBufferARB": print r" glGetBufferParameterivARB(target, GL_BUFFER_SIZE_ARB, &length);" elif function.name == "glMapNamedBuffer": print r" glGetNamedBufferParameteriv(buffer, GL_BUFFER_SIZE, &length);" elif function.name == "glMapNamedBufferEXT": print r" glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_SIZE, &length);" elif function.name == "glMapObjectBufferATI": print r" glGetObjectBufferivATI(buffer, GL_OBJECT_BUFFER_SIZE_ATI, &length);" else: assert False
def retraceApi(self, api): for module in api.modules: dispatcher = DllDispatcher() dispatcher.dispatchModule(module) Retracer.retraceApi(self, api)
def retraceFunctionBody(self, function): is_array_pointer = function.name in self.array_pointer_function_names is_draw_array = function.name in self.draw_array_function_names is_draw_elements = function.name in self.draw_elements_function_names is_misc_draw = function.name in self.misc_draw_function_names if is_array_pointer or is_draw_array or is_draw_elements: print ' if (retrace::parser.version < 1) {' if is_array_pointer or is_draw_array: print ' GLint _array_buffer = 0;' print ' glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &_array_buffer);' print ' if (!_array_buffer) {' self.failFunction(function) print ' }' if is_draw_elements: print ' GLint _element_array_buffer = 0;' print ' glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &_element_array_buffer);' print ' if (!_element_array_buffer) {' self.failFunction(function) print ' }' print ' }' if is_array_pointer: print ' GLint bRemoveVBO = false, uPrevVBO = 0;' print ' GLuint optr = (GLuint)retrace::toPointer(call.arg(call.args.size()-1),false);' print ' if(optr>16*1024*1024){' print ' glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &uPrevVBO);' print ' if(uPrevVBO){ bRemoveVBO = true; glBindBuffer(GL_ARRAY_BUFFER,0);' #print ' std::cout << "glretrace: temporarily unbinding VBO for glXYZPointer\\n"; print ' }' print ' }' # When no pack buffer object is bound, the pack functions are no-ops. if function.name in self.pack_function_names: print ' GLint _pack_buffer = 0;' print ' glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &_pack_buffer);' print ' if (!_pack_buffer) {' print ' return;' print ' }' # Pre-snapshots if function.name in self.bind_framebuffer_function_names: print ' assert(call.flags & trace::CALL_FLAG_SWAP_RENDERTARGET);' if function.name == 'glStringMarkerGREMEDY': return if function.name == 'glFrameTerminatorGREMEDY': print ' glretrace::frame_complete(call);' return Retracer.retraceFunctionBody(self, function) if is_array_pointer: print ' if(bRemoveVBO) glBindBuffer(GL_ARRAY_BUFFER,uPrevVBO);' # Post-snapshots if function.name in ('glFlush', 'glFinish'): print ' if (!retrace::doubleBuffer) {' print ' glretrace::frame_complete(call);' print ' }' if is_draw_array or is_draw_elements or is_misc_draw: print ' assert(call.flags & trace::CALL_FLAG_RENDER);'