Exemple #1
0
 def loadHooks(self):
   target   = self.target
   config   = self.target.config
   lib      = self.target.library
   platform = self.target.project.platform
   
   # Collect hooks in various locations
   for fileName in config.get("hooks", []):
     Log.notice("Parsing hooks from '%s'." % fileName)
     source = self.readSource(fileName)
     functions = Parser.parseSource(source).functions.values()
     if not functions:
       Log.warn("No hooks found.")
     for f in functions:
       Log.debug("%s %s(%s)" % (f.type, f.name, ", ".join(["%s %s" % (t.type, p) for p, t in f.parameters.items()])))
     for function in functions:
       if not function.body:
         Log.warn("Hook function '%s' has no body." % function.name)
         continue
       if function.name.startswith("@"):
         lib.hooks[function.name] = function.body
         continue
       else:
         try:
           name, hookName = function.name.split(".", 1)
           if not name in lib.functions:
             target.fail("Function '%s' referred by hook function '%s' does not exist." % (name, function.name))
           if not hookName.startswith("@") and not hookName in lib.functions[name].parameters:
             target.fail("Parameter '%s' referred by hook function '%s' does not exist." % (hookName, function.name))
           lib.functions[name].hooks[hookName] = function.body
         except ValueError:
           target.fail("Hook function name '%s' is not valid." % function.name)
Exemple #2
0
def generate(project, options, args):
    """Generate a target from a project. [target]"""
    if not args:
        fail("Generation target missing. Use one of %s" %
             ", ".join(project.targets.keys()))

    if not project.targets:
        fail("Project file name missing.")

    config = project.config

    for targetName in args:
        if not targetName in project.targets:
            fail("No such target. Use one of %s" %
                 ", ".join(project.targets.keys()))

        # Generate the target
        target = project.targets[targetName]
        projectName = config.name.lower() + "-" + targetName
        targetPath = options.output and options.output or projectName

        Log.notice(
            heading("Generating '%s' from project '%s'" %
                    (targetName, config.name)))

        target.generate(projectName, targetPath)
        Log.notice("Target '%s' created at '%s'." % (projectName, targetPath))
Exemple #3
0
  def prepareTarget(targetName):
    if targetName in project.targets:
      return
      
    if not targetName in Target.targets:
      fail("Bad target name '%s'." % targetName)
      return
      
    targetClass = Target.targets[targetName]
    for dep in targetClass.dependencies:
      if not dep in project.targets:
        prepareTarget(dep)

    Log.notice("Preparing target %d of %d: %s." % (len(project.targets) + 1, len(targetNames), targetName))
    target = targetClass(project)
    target.prepare()
    target.validate()
    project.targets[targetName] = target
Exemple #4
0
    def prepareTarget(targetName):
        if targetName in project.targets:
            return

        if not targetName in Target.targets:
            fail("Bad target name '%s'." % targetName)
            return

        targetClass = Target.targets[targetName]
        for dep in targetClass.dependencies:
            if not dep in project.targets:
                prepareTarget(dep)

        Log.notice("Preparing target %d of %d: %s." %
                   (len(project.targets) + 1, len(targetNames), targetName))
        target = targetClass(project)
        target.prepare()
        target.validate()
        project.targets[targetName] = target
Exemple #5
0
def show(project, options, args):
  """Show information about a project target. [target]"""
  commands = [
    "all",
    "config",
    "functions",
    "constants",
    "typedefs"
  ]
  
  if not args:
    fail("Show what? Use one of %s" % ", ".join(commands))
  
  command, args = args[0], args[1:]
    
  if not command in commands:
    fail("Show what? Use one of %s" % ", ".join(commands))
  
  if not project.targets:
    fail("Project file name missing.")

  config = project.config
  lib    = project.library
  
  if "code" in project.targets:
    lib = project.targets["code"].library
  
  if args:
    config = project.targets[args[0]].config
    lib    = project.targets[args[0]].library
    
  if command == "config" or command == "all":
    Log.notice("Configuration:")
    print config.save()
  if command == "functions" or command == "all":
    Log.notice("%d functions:" % len(lib.functions))
    for name, function in lib.functions.items():
      params = []
      for paramName, param in sorted(function.parameters.items()):
        params.append("%s %s" % (param.type, param.name))
      params = ", ".join(params)
      print "%s %s(%s)" % (function.type, function.name, params)
  if command == "constants" or command == "all":
    Log.notice("%d constants:" % len(lib.constants))
    for constName, constValue in sorted(lib.constants.items()):
      print "%-40s %-8s (0x%x)" % (constName, constValue, constValue)
  if command == "typedefs" or command == "all":
    Log.notice("%d typedefs:" % len(lib.typeDefs))
    for tdName, tdValue in sorted(lib.typeDefs.items()):
      print "%-40s %s" % (tdName, tdValue)
Exemple #6
0
    def loadHooks(self):
        target = self.target
        config = self.target.config
        lib = self.target.library
        platform = self.target.project.platform

        # Collect hooks in various locations
        for fileName in config.get("hooks", []):
            Log.notice("Parsing hooks from '%s'." % fileName)
            source = self.readSource(fileName)
            functions = Parser.parseSource(source).functions.values()
            if not functions:
                Log.warn("No hooks found.")
            for f in functions:
                Log.debug("%s %s(%s)" % (f.type, f.name, ", ".join(
                    ["%s %s" % (t.type, p) for p, t in f.parameters.items()])))
            for function in functions:
                if not function.body:
                    Log.warn("Hook function '%s' has no body." % function.name)
                    continue
                if function.name.startswith("@"):
                    lib.hooks[function.name] = function.body
                    continue
                else:
                    try:
                        name, hookName = function.name.split(".", 1)
                        if not name in lib.functions:
                            target.fail(
                                "Function '%s' referred by hook function '%s' does not exist."
                                % (name, function.name))
                        if not hookName.startswith(
                                "@"
                        ) and not hookName in lib.functions[name].parameters:
                            target.fail(
                                "Parameter '%s' referred by hook function '%s' does not exist."
                                % (hookName, function.name))
                        lib.functions[name].hooks[hookName] = function.body
                    except ValueError:
                        target.fail("Hook function name '%s' is not valid." %
                                    function.name)
Exemple #7
0
def generate(project, options, args):
  """Generate a target from a project. [target]"""
  if not args:
    fail("Generation target missing. Use one of %s" % ", ".join(project.targets.keys()))
    
  if not project.targets:
    fail("Project file name missing.")

  config = project.config

  for targetName in args:
    if not targetName in project.targets:
      fail("No such target. Use one of %s" % ", ".join(project.targets.keys()))
      
    # Generate the target
    target      = project.targets[targetName]
    projectName = config.name.lower() + "-" + targetName
    targetPath  = options.output and options.output or projectName

    Log.notice(heading("Generating '%s' from project '%s'" % (targetName, config.name)))
    
    target.generate(projectName, targetPath)
    Log.notice("Target '%s' created at '%s'." % (projectName, targetPath))
Exemple #8
0
def show(project, options, args):
    """Show information about a project target. [target]"""
    commands = ["all", "config", "functions", "constants", "typedefs"]

    if not args:
        fail("Show what? Use one of %s" % ", ".join(commands))

    command, args = args[0], args[1:]

    if not command in commands:
        fail("Show what? Use one of %s" % ", ".join(commands))

    if not project.targets:
        fail("Project file name missing.")

    config = project.config
    lib = project.library

    if "code" in project.targets:
        lib = project.targets["code"].library

    if args:
        config = project.targets[args[0]].config
        lib = project.targets[args[0]].library

    if command == "config" or command == "all":
        Log.notice("Configuration:")
        print config.save()
    if command == "functions" or command == "all":
        Log.notice("%d functions:" % len(lib.functions))
        for name, function in lib.functions.items():
            params = []
            for paramName, param in sorted(function.parameters.items()):
                params.append("%s %s" % (param.type, param.name))
            params = ", ".join(params)
            print "%s %s(%s)" % (function.type, function.name, params)
    if command == "constants" or command == "all":
        Log.notice("%d constants:" % len(lib.constants))
        for constName, constValue in sorted(lib.constants.items()):
            print "%-40s %-8s (0x%x)" % (constName, constValue, constValue)
    if command == "typedefs" or command == "all":
        Log.notice("%d typedefs:" % len(lib.typeDefs))
        for tdName, tdValue in sorted(lib.typeDefs.items()):
            print "%-40s %s" % (tdName, tdValue)
Exemple #9
0
def generateReport(project, trace, traceFileName, path, format):
  if traceFileName:
    title = "OpenGL ES performance report for %s" % os.path.basename(traceFileName)
  else:
    title = "OpenGL ES performance report"

  Log.notice(title)
  
  g = ReportGenerator.ReportGenerator(project, trace, title, path, format)

  # Calculate GLES specific stats
  GlesTraceOperations.calculateStatistics(project, trace)

  # Calculate general stats
  g.calculateStatistics()

  # Add some general information first
  section = g.report.create(Report.Section, "General statistics")
  table   = g.createGeneralStatisticsTable()
  auxiliaryTable = g.createAuxiliaryStatisticsTable()
  histogramTable = g.createCallHistogramTable()
  
  if traceFileName:
    table.addRow("File name", traceFileName)

  section.add(table)
  section.add(auxiliaryTable)
  section.add(histogramTable)
  
  # Add a section about the used render targets
  addRenderTargetSection(g)
  
  # Add an overall timeline of all events
  g.report.add(g.createEventPlot("Event distribution", trace.events))

  # Add a graph about the event type distribution
  g.report.add(g.createEventFrequencyPlot("Operation distribution", trace.events))
  
  # Add overview section
  overviewSection = g.report.create(Report.Section, "Overview")
  
  # Frame thumbnails
  thumbnailSection = overviewSection.create(Report.Section, "Selected frames")
  thumbnails       = g.createEventThumbnails([f.swapEvent for f in g.interestingFrames])
  
  for frame, thumbnail in zip(g.interestingFrames, thumbnails):
    thumbnailSection.create(Report.Link, "#frame%d" % (frame.number + 1), thumbnail)

  # Textures
  textureLoaders = GlesTraceOperations.getTextureLoaders(project, trace)
  
  if textureLoaders:
    textureSection = overviewSection.create(Report.Section, "Loaded textures")
    task           = Task.startTask("load-textures", "Loading textures", len(textureLoaders))
    for event, func in textureLoaders:
      task.step()
      image = func().convert("RGBA")
      fn = os.path.join(path, "texture%03d.png" % event.seq)
      image.save(fn)
      textureSection.create(Report.Image, fn)

  # FPS
  data = [1.0 / f.duration for f in g.frames]
  plot = g.createPlot("Frames per second", range(len(g.frames)), data)
  overviewSection.add(plot)

  # Render calls
  data = [len(f.events) for f in g.frames]
  plot = g.createPlot("Number of API calls per frame", range(len(g.frames)), data)
  overviewSection.add(plot)

  # Overdraw
  data = [f.swapEvent.sensorData.get("draw_ratio", 0) for f in g.frames]
  plot = g.createPlot("Draw ratio", range(len(g.frames)), data)
  overviewSection.add(plot)

  # Fragment count
  data = [f.swapEvent.sensorData.get("rasterizer_pixels", 0) for f in g.frames]
  plot = g.createPlot("Rasterized fragments per frame", range(len(g.frames)), data)
  overviewSection.add(plot)

  # Texture reads
  data = [f.swapEvent.sensorData.get("rasterizer_texel_fetches", 0) for f in g.frames]
  plot = g.createPlot("Texel fetches per frame", range(len(g.frames)), data)
  overviewSection.add(plot)

  # Texture uploads
  data = [f.swapEvent.sensorData.get("texel_uploads", 0) for f in g.frames]
  plot = g.createPlot("Texel uploads per frame", range(len(g.frames)), data)
  overviewSection.add(plot)

  # Now go over each interesting frame
  task               = Task.startTask("frame-report", "Generating report", len(g.interestingFrames))
  frameDetailSection = g.report.create(Report.Section, "Detailed frame statistics")
  
  for frame in g.interestingFrames:
    task.step()
    frameSection = g.createFrameSection(frame)
    
    # Add some custom plots
    plot = g.createSensorPlot(frame, "rasterizer_pixels")
    frameSection.add(plot)
    plot = g.createSensorPlot(frame, "rasterizer_texel_fetches")
    frameSection.add(plot)
    plot = g.createSensorPlot(frame, "texel_uploads")
    frameSection.add(plot)
    
    # Now go over the individual render calls + the swap event
    for event in frame.renderEvents + [frame.swapEvent]:
      eventSection = g.createEventSection(event)
      frameSection.add(eventSection)

    frameDetailSection.add(frameSection)

  # Add the checklist result
  g.report.add(g.createChecklistSection("Performance Checklist", GlesChecklist.checklistItems))

  # Finalize the report
  task.finish()
  g.generate()
Exemple #10
0
 def reportInfo(self, msg):
   for line in str(msg).rstrip().split("\n"):
     Log.notice(line)
Exemple #11
0
def create(project, options, args):
  """Create a new Tracy project. [config file] [targets]"""
  
  if not args or len(args) < 1:
    fail("Configuration file name missing.")

  configName  = args[0]
  targetNames = args[1:]

  # Load the configuration file
  project.config.loadFile(configName)
  for path in project.config.paths:
    Resource.paths.append(path)
  config = project.config

  try:
    # Create the platform and read it's configuration if it exists.
    platform = Platform.platforms[options.platform](config)
  except KeyError:
    fail("No such platform. Use one of %s" % ", ".join(Platform.platforms.keys()))

  projectName = config.name.lower()

  Log.notice(heading("Creating Tracy project '%s' for %s" % (projectName, platform.name)))
  
  # Initialize the project
  lib = Library.Library(name = config.name)
  project.library  = lib
  project.platform = platform
  
  def prepareTarget(targetName):
    if targetName in project.targets:
      return
      
    if not targetName in Target.targets:
      fail("Bad target name '%s'." % targetName)
      return
      
    targetClass = Target.targets[targetName]
    for dep in targetClass.dependencies:
      if not dep in project.targets:
        prepareTarget(dep)

    Log.notice("Preparing target %d of %d: %s." % (len(project.targets) + 1, len(targetNames), targetName))
    target = targetClass(project)
    target.prepare()
    target.validate()
    project.targets[targetName] = target
  
  # Prepare the targets
  if not targetNames:
    targetNames = Target.targets.keys()
    
  for targetName in targetNames:
    prepareTarget(targetName)

  # Save the project
  projectPath = options.output and options.output or ("%s.tcy" % projectName)
  project.save(projectPath)
  
  Log.notice("Tracy project '%s' saved to '%s'." % (projectName, projectPath))
Exemple #12
0
def sync(options, target, args):
  """Synchronize the makefile"""
  f = open("Makefile", "w")
  Generator.generateMakefile(f)
  f.close()
  Log.notice("Makefile synchronized")
Exemple #13
0
  def prepare(self):
    # Shorthand for various objects
    config = self.config
    lib    = self.library
    
    # Parse the sources
    for fileName in config.get("apiheaders", []):
      Log.notice("Parsing functions from '%s'." % fileName)
      source = self.parserTool.readSource(fileName)
      newLib = Parser.parseSource(source)
      for f in newLib.functions.values():
        f.headerName = fileName
      for f in newLib.functions.values():
        Log.debug("%s %s(%s)" % (f.type, f.name, ", ".join(["%s %s" % (t.type, p) for p, t in f.parameters.items()])))
      if not newLib.functions:
        Log.warn("No new functions found.")
      else:
        Log.notice("%d functions found." % len(newLib.functions))
      lib.merge(newLib)

    # Load the hooks
    self.parserTool.loadHooks()

    def parseBool(s):
      return bool(int(s))

    # Read the typemap
    for typeDecl, mapping in self.config.types.items():
      attrs = self.config.types[typeDecl].attrs
      name, type = Parser.parseVariableDeclaration(typeDecl + " dummy")
      assert name == "dummy"
      # If this is a class mapping, create the class if it doesn't already exist
      if mapping == "object":
        if not mapping in self.library.classes:
          cls = Library.Class(type)
          if "namespace" in attrs:
            cls.namespacePath = attrs["namespace"].split(".")
          self.library.classes[type] = cls
      # Patch the default decoration hint into all matching types
      if "decorationhint" in attrs:
          for function in self.library.functions.values():
              for t in [p.type for p in function.parameters.values()] + [function.type]:
                  if t == type:
                      t.decorationHint = attrs["decorationhint"]
      self.library.typeMap[type] = str(mapping)

    # Patch in some function-specific attributes
    for function in config.functions.keys():
      if not function in lib.functions:
        self.fail("Attributes specified for non-existent function '%s'." % function)
      attrs = config.functions[function].attrs
      if "terminator" in attrs:
        lib.functions[function].isTerminator         = parseBool(attrs["terminator"])
      if "generate" in attrs:
        lib.functions[function].generate             = parseBool(attrs["generate"])
      if "runtimestate" in attrs:
        lib.functions[function].runtimeStateTracking = parseBool(attrs["runtimestate"])
      if "framemarker" in attrs:
        lib.functions[function].isFrameMarker        = parseBool(attrs["framemarker"])
      if "staticlinkage" in attrs:
        lib.functions[function].staticLinkage        = parseBool(attrs["staticlinkage"])
      if "rendercall" in attrs:
        lib.functions[function].isRenderCall         = parseBool(attrs["rendercall"])
      if "passthrough" in attrs:
        lib.functions[function].passthrough          = parseBool(attrs["passthrough"])
        
      if not isinstance(config.functions[function], Config.Group):
        self.fail("Syntax error: State map definition for function '%s' is missing braces." % function)
        
      # Argument to state mapping
      reservedNames = ["@return", "@modify", "@set", "@get", "@copy"]
      funcAttrs = attrs
      for arg, parameter in config.functions[function].items():
        # Check that this is a valid parameter
        if not arg in reservedNames and not arg in lib.functions[function].parameters:
          self.fail("State mapping for nonexistent parameter '%s' of function '%s' specified." % (arg, function))

        if arg in ["@copy"] and parseBool(funcAttrs.get("runtimestate", "0")):
          Log.warn("Function %s state relation %s not implemented for runtime state tracking." % (function, arg))
          
        # Read the parameter-specific attributes
        attrs = config.functions[function][arg].attrs
        if "decoration" in attrs:
          lib.functions[function].parameters[arg].decoration     = attrs["decoration"]
        if "decorationhint" in attrs:
          lib.functions[function].parameters[arg].decorationHint = attrs["decorationhint"]
        if "out" in attrs:
          lib.functions[function].parameters[arg].isOut          = parseBool(attrs["out"])
        if "object_class" in attrs:
          # Create a function-local type so that this parameter type is an object only for this function
          if arg == "@return":
            type = lib.functions[function].type
          else:
            type = lib.functions[function].parameters[arg].type
          # Override the type's name so that it will refer to the new object class
          # while still using the original C type under the hood
          newType = copy.deepcopy(type)
          newType.isObject = True
          newType.name = attrs["object_class"]
          if arg == "@return":
            lib.functions[function].type = newType
          else:
            lib.functions[function].parameters[arg].type = newType
          # Check that this class exists
          classType = Library.Type(attrs["object_class"])
          if not classType in self.library.classes:
            self.fail("Undefined object class '%s'." % classType)
          
        # Do we have a meta type?
        if "metatype" in config.functions[function][arg]:
          metaGroup = config.functions[function][arg].metatype
          
          try:
            metaType = Library.MetaType(metaGroup.attrs["class"])
          except KeyError:
            self.fail("Meta type for parameter '%s' does not define class." % arg)
            
          # Is this an array parameter?
          if metaType.name == "array":
            metaType.values["size"]       = Library.MetaValue("size",       metaGroup.attrs.get("size", 1))
            if "type" in metaGroup.attrs:
              metaType.values["type"]     = Library.MetaValue("type",       metaGroup.attrs["type"])
              if metaGroup.attrs["type"] == "object":
                if not "object_class" in metaGroup.attrs:
                  self.fail("Required metatype attribute object_class missing")
                metaType.values["object_class"] = Library.MetaValue("object_class", metaGroup.attrs["object_class"])
          # How about an image parameter?
          elif metaType.name == "image":
            metaType.values["stride"]     = Library.MetaValue("stride",     metaGroup.attrs.get("stride", "width"))
            metaType.values["height"]     = Library.MetaValue("height",     metaGroup.attrs.get("height", "height"))
            metaType.values["components"] = Library.MetaValue("components", metaGroup.attrs.get("components", "1"))
            metaType.values["type"]       = Library.MetaValue("type",       metaGroup.attrs.get("type", "byte"))
          else:
            self.fail("Unknown meta type class '%s'." % metaclass)
          
          Log.debug("Meta type: %s.%s: %s" % (function, arg, metaType.name))
            
          # Get the conditions for different meta values
          if isinstance(metaGroup, Config.List):
            for item in metaGroup:
              predicate      = item.attrs["condition"]
              predicateValue = item.attrs["value"]
              result         = item.attrs["result"]
              metaType.values[item].addPredicate(predicate, predicateValue, result)
              Log.debug("Meta type condition: If %s is %s, then %s = %s" % (predicate, predicateValue, item, result))
          elif isinstance(metaGroup, Config.Group):
            Log.error("Meta type variations for parameter '%s' represented in a group instead of a list." % arg)
              
          # Record the meta type
          lib.functions[function].parameters[arg].metaType = metaType
        
        # Is this a short-hand state mapping?
        try:
          path = parameter.split(".")
        except AttributeError:
          # Try the expanded form of a nested attribute set
          try:
            path = (config.functions[function][arg].state).split(".")
          except AttributeError:
            path = []

        # Check that we even have a state structure
        if path and not "state" in config:
          Log.warn("State structure not defined.")
          continue
            
        # Parse special state mapping relations
        relation   = None
        checkPaths = []
        if arg == "@copy":
          relation   = Library.StateRelationCopy(attrs["src"].split("."), attrs["dest"].split("."))
          checkPaths = [relation.sourcePath, relation.destPath]
        elif arg == "@get":
          relation   = Library.StateRelationGet(path)
          checkPaths = [relation.path]
        elif arg == "@set":
          relation   = Library.StateRelationSet(path)
          checkPaths = [relation.path]
        elif arg == "@modify":
          relation   = Library.StateRelationModify(path)
          checkPaths = [relation.path]
        # Empty mapping?
        elif not "".join(path):
          continue
          
        if relation:
          for path in checkPaths:
            if traverseStatePath(config, path) is None:
              self.fail("Relation state path '%s' for function '%s' does not exist." % (".".join(path), function))
          Log.debug("State relation: %s %s" % (function, relation))
          lib.functions[function].stateRelations.append(relation)
          continue
          
        Log.debug("State mapping: %s.%s -> %s" % (function, arg, ".".join(path)))

        # Determine the parameter type
        type = None

        if arg == "@return":
          type = lib.functions[function].type
        else:
          type = lib.functions[function].parameters[arg].type      

        # If this is a runtime mapping, check that the parameter is of a supported type
        if lib.functions[function].runtimeStateTracking and type and \
           lib.getNativeType(type) in ["float", "double"]:
          self.fail("Values of type '%s' can not be saved to the runtime state tree" % type)
          continue
          
        node = traverseStatePath(config, path)
        if node is None:
          self.fail("State path '%s' for function '%s' does not exist." % (".".join(path), function))
          
        # Save the mapping
        if arg == "@return":
          lib.functions[function].retStateRelation = Library.StateRelationSet(path)
        else:
          lib.functions[function].parameters[arg].stateRelation = Library.StateRelationSet(path)
Exemple #14
0
    def prepare(self):
        # Shorthand for various objects
        config = self.config
        lib = self.library

        # Parse the sources
        for fileName in config.get("apiheaders", []):
            Log.notice("Parsing functions from '%s'." % fileName)
            source = self.parserTool.readSource(fileName)
            newLib = Parser.parseSource(source)
            for f in newLib.functions.values():
                f.headerName = fileName
            for f in newLib.functions.values():
                Log.debug("%s %s(%s)" % (f.type, f.name, ", ".join(
                    ["%s %s" % (t.type, p) for p, t in f.parameters.items()])))
            if not newLib.functions:
                Log.warn("No new functions found.")
            else:
                Log.notice("%d functions found." % len(newLib.functions))
            lib.merge(newLib)

        # Load the hooks
        self.parserTool.loadHooks()

        def parseBool(s):
            return bool(int(s))

        # Read the typemap
        for typeDecl, mapping in self.config.types.items():
            attrs = self.config.types[typeDecl].attrs
            name, type = Parser.parseVariableDeclaration(typeDecl + " dummy")
            assert name == "dummy"
            # If this is a class mapping, create the class if it doesn't already exist
            if mapping == "object":
                if not mapping in self.library.classes:
                    cls = Library.Class(type)
                    if "namespace" in attrs:
                        cls.namespacePath = attrs["namespace"].split(".")
                    self.library.classes[type] = cls
            # Patch the default decoration hint into all matching types
            if "decorationhint" in attrs:
                for function in self.library.functions.values():
                    for t in [p.type for p in function.parameters.values()
                              ] + [function.type]:
                        if t == type:
                            t.decorationHint = attrs["decorationhint"]
            self.library.typeMap[type] = str(mapping)

        # Patch in some function-specific attributes
        for function in config.functions.keys():
            if not function in lib.functions:
                self.fail(
                    "Attributes specified for non-existent function '%s'." %
                    function)
            attrs = config.functions[function].attrs
            if "terminator" in attrs:
                lib.functions[function].isTerminator = parseBool(
                    attrs["terminator"])
            if "generate" in attrs:
                lib.functions[function].generate = parseBool(attrs["generate"])
            if "runtimestate" in attrs:
                lib.functions[function].runtimeStateTracking = parseBool(
                    attrs["runtimestate"])
            if "framemarker" in attrs:
                lib.functions[function].isFrameMarker = parseBool(
                    attrs["framemarker"])
            if "staticlinkage" in attrs:
                lib.functions[function].staticLinkage = parseBool(
                    attrs["staticlinkage"])
            if "rendercall" in attrs:
                lib.functions[function].isRenderCall = parseBool(
                    attrs["rendercall"])
            if "passthrough" in attrs:
                lib.functions[function].passthrough = parseBool(
                    attrs["passthrough"])

            if not isinstance(config.functions[function], Config.Group):
                self.fail(
                    "Syntax error: State map definition for function '%s' is missing braces."
                    % function)

            # Argument to state mapping
            reservedNames = ["@return", "@modify", "@set", "@get", "@copy"]
            funcAttrs = attrs
            for arg, parameter in config.functions[function].items():
                # Check that this is a valid parameter
                if not arg in reservedNames and not arg in lib.functions[
                        function].parameters:
                    self.fail(
                        "State mapping for nonexistent parameter '%s' of function '%s' specified."
                        % (arg, function))

                if arg in ["@copy"] and parseBool(
                        funcAttrs.get("runtimestate", "0")):
                    Log.warn(
                        "Function %s state relation %s not implemented for runtime state tracking."
                        % (function, arg))

                # Read the parameter-specific attributes
                attrs = config.functions[function][arg].attrs
                if "decoration" in attrs:
                    lib.functions[function].parameters[arg].decoration = attrs[
                        "decoration"]
                if "decorationhint" in attrs:
                    lib.functions[function].parameters[
                        arg].decorationHint = attrs["decorationhint"]
                if "out" in attrs:
                    lib.functions[function].parameters[arg].isOut = parseBool(
                        attrs["out"])
                if "object_class" in attrs:
                    # Create a function-local type so that this parameter type is an object only for this function
                    if arg == "@return":
                        type = lib.functions[function].type
                    else:
                        type = lib.functions[function].parameters[arg].type
                    # Override the type's name so that it will refer to the new object class
                    # while still using the original C type under the hood
                    newType = copy.deepcopy(type)
                    newType.isObject = True
                    newType.name = attrs["object_class"]
                    if arg == "@return":
                        lib.functions[function].type = newType
                    else:
                        lib.functions[function].parameters[arg].type = newType
                    # Check that this class exists
                    classType = Library.Type(attrs["object_class"])
                    if not classType in self.library.classes:
                        self.fail("Undefined object class '%s'." % classType)

                # Do we have a meta type?
                if "metatype" in config.functions[function][arg]:
                    metaGroup = config.functions[function][arg].metatype

                    try:
                        metaType = Library.MetaType(metaGroup.attrs["class"])
                    except KeyError:
                        self.fail(
                            "Meta type for parameter '%s' does not define class."
                            % arg)

                    # Is this an array parameter?
                    if metaType.name == "array":
                        metaType.values["size"] = Library.MetaValue(
                            "size", metaGroup.attrs.get("size", 1))
                        if "type" in metaGroup.attrs:
                            metaType.values["type"] = Library.MetaValue(
                                "type", metaGroup.attrs["type"])
                            if metaGroup.attrs["type"] == "object":
                                if not "object_class" in metaGroup.attrs:
                                    self.fail(
                                        "Required metatype attribute object_class missing"
                                    )
                                metaType.values[
                                    "object_class"] = Library.MetaValue(
                                        "object_class",
                                        metaGroup.attrs["object_class"])
                    # How about an image parameter?
                    elif metaType.name == "image":
                        metaType.values["stride"] = Library.MetaValue(
                            "stride", metaGroup.attrs.get("stride", "width"))
                        metaType.values["height"] = Library.MetaValue(
                            "height", metaGroup.attrs.get("height", "height"))
                        metaType.values["components"] = Library.MetaValue(
                            "components",
                            metaGroup.attrs.get("components", "1"))
                        metaType.values["type"] = Library.MetaValue(
                            "type", metaGroup.attrs.get("type", "byte"))
                    else:
                        self.fail("Unknown meta type class '%s'." % metaclass)

                    Log.debug("Meta type: %s.%s: %s" %
                              (function, arg, metaType.name))

                    # Get the conditions for different meta values
                    if isinstance(metaGroup, Config.List):
                        for item in metaGroup:
                            predicate = item.attrs["condition"]
                            predicateValue = item.attrs["value"]
                            result = item.attrs["result"]
                            metaType.values[item].addPredicate(
                                predicate, predicateValue, result)
                            Log.debug(
                                "Meta type condition: If %s is %s, then %s = %s"
                                % (predicate, predicateValue, item, result))
                    elif isinstance(metaGroup, Config.Group):
                        Log.error(
                            "Meta type variations for parameter '%s' represented in a group instead of a list."
                            % arg)

                    # Record the meta type
                    lib.functions[function].parameters[arg].metaType = metaType

                # Is this a short-hand state mapping?
                try:
                    path = parameter.split(".")
                except AttributeError:
                    # Try the expanded form of a nested attribute set
                    try:
                        path = (
                            config.functions[function][arg].state).split(".")
                    except AttributeError:
                        path = []

                # Check that we even have a state structure
                if path and not "state" in config:
                    Log.warn("State structure not defined.")
                    continue

                # Parse special state mapping relations
                relation = None
                checkPaths = []
                if arg == "@copy":
                    relation = Library.StateRelationCopy(
                        attrs["src"].split("."), attrs["dest"].split("."))
                    checkPaths = [relation.sourcePath, relation.destPath]
                elif arg == "@get":
                    relation = Library.StateRelationGet(path)
                    checkPaths = [relation.path]
                elif arg == "@set":
                    relation = Library.StateRelationSet(path)
                    checkPaths = [relation.path]
                elif arg == "@modify":
                    relation = Library.StateRelationModify(path)
                    checkPaths = [relation.path]
                # Empty mapping?
                elif not "".join(path):
                    continue

                if relation:
                    for path in checkPaths:
                        if traverseStatePath(config, path) is None:
                            self.fail(
                                "Relation state path '%s' for function '%s' does not exist."
                                % (".".join(path), function))
                    Log.debug("State relation: %s %s" % (function, relation))
                    lib.functions[function].stateRelations.append(relation)
                    continue

                Log.debug("State mapping: %s.%s -> %s" %
                          (function, arg, ".".join(path)))

                # Determine the parameter type
                type = None

                if arg == "@return":
                    type = lib.functions[function].type
                else:
                    type = lib.functions[function].parameters[arg].type

                # If this is a runtime mapping, check that the parameter is of a supported type
                if lib.functions[function].runtimeStateTracking and type and \
                   lib.getNativeType(type) in ["float", "double"]:
                    self.fail(
                        "Values of type '%s' can not be saved to the runtime state tree"
                        % type)
                    continue

                node = traverseStatePath(config, path)
                if node is None:
                    self.fail(
                        "State path '%s' for function '%s' does not exist." %
                        (".".join(path), function))

                # Save the mapping
                if arg == "@return":
                    lib.functions[
                        function].retStateRelation = Library.StateRelationSet(
                            path)
                else:
                    lib.functions[function].parameters[
                        arg].stateRelation = Library.StateRelationSet(path)
Exemple #15
0
def create(project, options, args):
    """Create a new Tracy project. [config file] [targets]"""

    if not args or len(args) < 1:
        fail("Configuration file name missing.")

    configName = args[0]
    targetNames = args[1:]

    # Load the configuration file
    project.config.loadFile(configName)
    for path in project.config.paths:
        Resource.paths.append(path)
    config = project.config

    try:
        # Create the platform and read it's configuration if it exists.
        platform = Platform.platforms[options.platform](config)
    except KeyError:
        fail("No such platform. Use one of %s" %
             ", ".join(Platform.platforms.keys()))

    projectName = config.name.lower()

    Log.notice(
        heading("Creating Tracy project '%s' for %s" %
                (projectName, platform.name)))

    # Initialize the project
    lib = Library.Library(name=config.name)
    project.library = lib
    project.platform = platform

    def prepareTarget(targetName):
        if targetName in project.targets:
            return

        if not targetName in Target.targets:
            fail("Bad target name '%s'." % targetName)
            return

        targetClass = Target.targets[targetName]
        for dep in targetClass.dependencies:
            if not dep in project.targets:
                prepareTarget(dep)

        Log.notice("Preparing target %d of %d: %s." %
                   (len(project.targets) + 1, len(targetNames), targetName))
        target = targetClass(project)
        target.prepare()
        target.validate()
        project.targets[targetName] = target

    # Prepare the targets
    if not targetNames:
        targetNames = Target.targets.keys()

    for targetName in targetNames:
        prepareTarget(targetName)

    # Save the project
    projectPath = options.output and options.output or ("%s.tcy" % projectName)
    project.save(projectPath)

    Log.notice("Tracy project '%s' saved to '%s'." %
               (projectName, projectPath))
Exemple #16
0
def sync(options, target, args):
    """Synchronize the makefile"""
    f = open("Makefile", "w")
    Generator.generateMakefile(f)
    f.close()
    Log.notice("Makefile synchronized")