Blame src/gallium/tools/trace/dump_state.py

Packit Service 5cb53b
#! /usr/libexec/platform-python
Packit 8f2243
##########################################################################
Packit 8f2243
# 
Packit 8f2243
# Copyright 2008-2013, VMware, Inc.
Packit 8f2243
# All Rights Reserved.
Packit 8f2243
# 
Packit 8f2243
# Permission is hereby granted, free of charge, to any person obtaining a
Packit 8f2243
# copy of this software and associated documentation files (the
Packit 8f2243
# "Software"), to deal in the Software without restriction, including
Packit 8f2243
# without limitation the rights to use, copy, modify, merge, publish,
Packit 8f2243
# distribute, sub license, and/or sell copies of the Software, and to
Packit 8f2243
# permit persons to whom the Software is furnished to do so, subject to
Packit 8f2243
# the following conditions:
Packit 8f2243
# 
Packit 8f2243
# The above copyright notice and this permission notice (including the
Packit 8f2243
# next paragraph) shall be included in all copies or substantial portions
Packit 8f2243
# of the Software.
Packit 8f2243
# 
Packit 8f2243
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
Packit 8f2243
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit 8f2243
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
Packit 8f2243
# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
Packit 8f2243
# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
Packit 8f2243
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
Packit 8f2243
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Packit 8f2243
# 
Packit 8f2243
##########################################################################
Packit 8f2243
Packit 8f2243
Packit 8f2243
import sys
Packit 8f2243
import struct
Packit 8f2243
import json
Packit 8f2243
import binascii
Packit 8f2243
import re
Packit 8f2243
import copy
Packit 8f2243
Packit 8f2243
import model
Packit 8f2243
import parse as parser
Packit 8f2243
Packit 8f2243
Packit 8f2243
try:
Packit 8f2243
    from struct import unpack_from
Packit 8f2243
except ImportError:
Packit 8f2243
    def unpack_from(fmt, buf, offset=0):
Packit 8f2243
        size = struct.calcsize(fmt)
Packit 8f2243
        return struct.unpack(fmt, buf[offset:offset + size])
Packit 8f2243
Packit 8f2243
#
Packit 8f2243
# Some constants
Packit 8f2243
#
Packit 8f2243
PIPE_BUFFER = 0
Packit 8f2243
PIPE_SHADER_VERTEX   = 0
Packit 8f2243
PIPE_SHADER_FRAGMENT = 1
Packit 8f2243
PIPE_SHADER_GEOMETRY = 2
Packit 8f2243
PIPE_SHADER_COMPUTE  = 3
Packit 8f2243
PIPE_SHADER_TYPES    = 4
Packit 8f2243
Packit 8f2243
Packit 8f2243
def serialize(obj):
Packit 8f2243
    '''JSON serializer function for non-standard Python objects.'''
Packit 8f2243
Packit 8f2243
    if isinstance(obj, bytearray):
Packit 8f2243
        # TODO: Decide on a single way of dumping blobs
Packit 8f2243
        if False:
Packit 8f2243
            # Don't dump full blobs, but merely a description of their size and
Packit 8f2243
            # CRC32 hash.
Packit 8f2243
            crc32 = binascii.crc32(obj)
Packit 8f2243
            if crc32 < 0:
Packit 8f2243
                crc32 += 0x100000000
Packit 8f2243
            return 'blob(size=%u,crc32=0x%08x)' % (len(obj), crc32)
Packit 8f2243
        if True:
Packit 8f2243
            # Dump blobs as an array of 16byte hexadecimals
Packit 8f2243
            res = []
Packit 8f2243
            for i in range(0, len(obj), 16):
Packit 8f2243
                res.append(binascii.b2a_hex(obj[i: i+16]))
Packit 8f2243
            return res
Packit 8f2243
        # Dump blobs as a single hexadecimal string
Packit 8f2243
        return binascii.b2a_hex(obj)
Packit 8f2243
Packit 8f2243
    # If the object has a __json__ method, use it.
Packit 8f2243
    try:
Packit 8f2243
        method = obj.__json__
Packit 8f2243
    except AttributeError:
Packit 8f2243
        raise TypeError(obj)
Packit 8f2243
    else:
Packit 8f2243
        return method()
Packit 8f2243
Packit 8f2243
Packit 8f2243
class Struct:
Packit 8f2243
    """C-like struct.
Packit 8f2243
    
Packit 8f2243
    Python doesn't have C structs, but do its dynamic nature, any object is
Packit 8f2243
    pretty close.
Packit 8f2243
    """
Packit 8f2243
Packit 8f2243
    def __json__(self):
Packit 8f2243
        '''Convert the structure to a standard Python dict, so it can be
Packit 8f2243
        serialized.'''
Packit 8f2243
Packit 8f2243
        obj = {}
Packit 8f2243
        for name, value in self.__dict__.items():
Packit 8f2243
            if not name.startswith('_'):
Packit 8f2243
                obj[name] = value
Packit 8f2243
        return obj
Packit 8f2243
Packit 8f2243
    def __repr__(self):
Packit 8f2243
        return repr(self.__json__())
Packit 8f2243
Packit 8f2243
Packit 8f2243
class Translator(model.Visitor):
Packit 8f2243
    """Translate model arguments into regular Python objects"""
Packit 8f2243
Packit 8f2243
    def __init__(self, interpreter):
Packit 8f2243
        self.interpreter = interpreter
Packit 8f2243
        self.result = None
Packit 8f2243
Packit 8f2243
    def visit(self, node):
Packit 8f2243
        self.result = None
Packit 8f2243
        node.visit(self)
Packit 8f2243
        return self.result
Packit 8f2243
        
Packit 8f2243
    def visit_literal(self, node):
Packit 8f2243
        self.result = node.value
Packit 8f2243
    
Packit 8f2243
    def visit_blob(self, node):
Packit 8f2243
        self.result = node
Packit 8f2243
    
Packit 8f2243
    def visit_named_constant(self, node):
Packit 8f2243
        self.result = node.name
Packit 8f2243
    
Packit 8f2243
    def visit_array(self, node):
Packit 8f2243
        array = []
Packit 8f2243
        for element in node.elements:
Packit 8f2243
            array.append(self.visit(element))
Packit 8f2243
        self.result = array
Packit 8f2243
    
Packit 8f2243
    def visit_struct(self, node):
Packit 8f2243
        struct = Struct()
Packit 8f2243
        for member_name, member_node in node.members:
Packit 8f2243
            member_name = member_name.replace('.', '_')
Packit 8f2243
            member_value = self.visit(member_node)
Packit 8f2243
            setattr(struct, member_name, member_value)
Packit 8f2243
        self.result = struct
Packit 8f2243
    
Packit 8f2243
    def visit_pointer(self, node):
Packit 8f2243
        self.result = self.interpreter.lookup_object(node.address)
Packit 8f2243
Packit 8f2243
Packit 8f2243
class Dispatcher:
Packit 8f2243
    '''Base class for classes whose methods can dispatch Gallium calls.'''
Packit 8f2243
    
Packit 8f2243
    def __init__(self, interpreter):
Packit 8f2243
        self.interpreter = interpreter
Packit 8f2243
        
Packit 8f2243
Packit 8f2243
class Global(Dispatcher):
Packit 8f2243
    '''Global name space.
Packit 8f2243
Packit 8f2243
    For calls that are not associated with objects, i.e, functions and not
Packit 8f2243
    methods.
Packit 8f2243
    '''
Packit 8f2243
Packit 8f2243
    def pipe_screen_create(self):
Packit 8f2243
        return Screen(self.interpreter)
Packit 8f2243
    
Packit 8f2243
    def pipe_context_create(self, screen):
Packit 8f2243
        return screen.context_create()
Packit 8f2243
Packit 8f2243
    
Packit 8f2243
class Transfer:
Packit 8f2243
    '''pipe_transfer'''
Packit 8f2243
Packit 8f2243
    def __init__(self, resource, usage, subresource, box):
Packit 8f2243
        self.resource = resource
Packit 8f2243
        self.usage = usage
Packit 8f2243
        self.subresource = subresource
Packit 8f2243
        self.box = box
Packit 8f2243
Packit 8f2243
Packit 8f2243
class Screen(Dispatcher):
Packit 8f2243
    '''pipe_screen'''
Packit 8f2243
    
Packit 8f2243
    def __init__(self, interpreter):
Packit 8f2243
        Dispatcher.__init__(self, interpreter)
Packit 8f2243
Packit 8f2243
    def destroy(self):
Packit 8f2243
        pass
Packit 8f2243
Packit 8f2243
    def context_create(self, priv=None, flags=0):
Packit 8f2243
        return Context(self.interpreter)
Packit 8f2243
    
Packit 8f2243
    def is_format_supported(self, format, target, sample_count, bind, geom_flags):
Packit 8f2243
        pass
Packit 8f2243
    
Packit 8f2243
    def resource_create(self, templat):
Packit 8f2243
        resource = templat
Packit 8f2243
        # Normalize state to avoid spurious differences
Packit 8f2243
        if resource.nr_samples == 0:
Packit 8f2243
            resource.nr_samples = 1
Packit 8f2243
        if resource.target == PIPE_BUFFER:
Packit 8f2243
            # We will keep track of buffer contents
Packit 8f2243
            resource.data = bytearray(resource.width)
Packit 8f2243
            # Ignore format
Packit 8f2243
            del resource.format
Packit 8f2243
        return resource
Packit 8f2243
Packit 8f2243
    def resource_destroy(self, resource):
Packit 8f2243
        self.interpreter.unregister_object(resource)
Packit 8f2243
Packit 8f2243
    def fence_finish(self, fence, timeout=None):
Packit 8f2243
        pass
Packit 8f2243
    
Packit 8f2243
    def fence_signalled(self, fence):
Packit 8f2243
        pass
Packit 8f2243
    
Packit 8f2243
    def fence_reference(self, dst, src):
Packit 8f2243
        pass
Packit 8f2243
    
Packit 8f2243
    def flush_frontbuffer(self, resource):
Packit 8f2243
        pass
Packit 8f2243
Packit 8f2243
Packit 8f2243
class Context(Dispatcher):
Packit 8f2243
    '''pipe_context'''
Packit 8f2243
Packit 8f2243
    # Internal methods variable should be prefixed with '_'
Packit 8f2243
    
Packit 8f2243
    def __init__(self, interpreter):
Packit 8f2243
        Dispatcher.__init__(self, interpreter)
Packit 8f2243
Packit 8f2243
        # Setup initial state
Packit 8f2243
        self._state = Struct()
Packit 8f2243
        self._state.scissors = []
Packit 8f2243
        self._state.viewports = []
Packit 8f2243
        self._state.vertex_buffers = []
Packit 8f2243
        self._state.vertex_elements = []
Packit 8f2243
        self._state.vs = Struct()
Packit 8f2243
        self._state.gs = Struct()
Packit 8f2243
        self._state.fs = Struct()
Packit 8f2243
        self._state.vs.shader = None
Packit 8f2243
        self._state.gs.shader = None
Packit 8f2243
        self._state.fs.shader = None
Packit 8f2243
        self._state.vs.sampler = []
Packit 8f2243
        self._state.gs.sampler = []
Packit 8f2243
        self._state.fs.sampler = []
Packit 8f2243
        self._state.vs.sampler_views = []
Packit 8f2243
        self._state.gs.sampler_views = []
Packit 8f2243
        self._state.fs.sampler_views = []
Packit 8f2243
        self._state.vs.constant_buffer = []
Packit 8f2243
        self._state.gs.constant_buffer = []
Packit 8f2243
        self._state.fs.constant_buffer = []
Packit 8f2243
        self._state.render_condition_condition = 0
Packit 8f2243
        self._state.render_condition_mode = 0
Packit 8f2243
Packit 8f2243
        self._draw_no = 0
Packit 8f2243
Packit 8f2243
    def destroy(self):
Packit 8f2243
        pass
Packit 8f2243
    
Packit 8f2243
    def create_blend_state(self, state):
Packit 8f2243
        # Normalize state to avoid spurious differences
Packit 8f2243
        if not state.logicop_enable:
Packit 8f2243
            del state.logicop_func
Packit 8f2243
        if not state.rt[0].blend_enable:
Packit 8f2243
            del state.rt[0].rgb_src_factor
Packit 8f2243
            del state.rt[0].rgb_dst_factor
Packit 8f2243
            del state.rt[0].rgb_func
Packit 8f2243
            del state.rt[0].alpha_src_factor
Packit 8f2243
            del state.rt[0].alpha_dst_factor
Packit 8f2243
            del state.rt[0].alpha_func
Packit 8f2243
        return state
Packit 8f2243
Packit 8f2243
    def bind_blend_state(self, state):
Packit 8f2243
        # Normalize state
Packit 8f2243
        self._state.blend = state
Packit 8f2243
Packit 8f2243
    def delete_blend_state(self, state):
Packit 8f2243
        pass
Packit 8f2243
    
Packit 8f2243
    def create_sampler_state(self, state):
Packit 8f2243
        return state
Packit 8f2243
Packit 8f2243
    def delete_sampler_state(self, state):
Packit 8f2243
        pass
Packit 8f2243
Packit 8f2243
    def bind_sampler_states(self, shader, start, num_states, states):
Packit 8f2243
        # FIXME: Handle non-zero start
Packit 8f2243
        assert start == 0
Packit 8f2243
        self._get_stage_state(shader).sampler = states
Packit 8f2243
Packit 8f2243
    def bind_vertex_sampler_states(self, num_states, states):
Packit 8f2243
        # XXX: deprecated method
Packit 8f2243
        self._state.vs.sampler = states
Packit 8f2243
Packit 8f2243
    def bind_geometry_sampler_states(self, num_states, states):
Packit 8f2243
        # XXX: deprecated method
Packit 8f2243
        self._state.gs.sampler = states
Packit 8f2243
Packit 8f2243
    def bind_fragment_sampler_states(self, num_states, states):
Packit 8f2243
        # XXX: deprecated method
Packit 8f2243
        self._state.fs.sampler = states
Packit 8f2243
        
Packit 8f2243
    def create_rasterizer_state(self, state):
Packit 8f2243
        return state
Packit 8f2243
Packit 8f2243
    def bind_rasterizer_state(self, state):
Packit 8f2243
        self._state.rasterizer = state
Packit 8f2243
        
Packit 8f2243
    def delete_rasterizer_state(self, state):
Packit 8f2243
        pass
Packit 8f2243
    
Packit 8f2243
    def create_depth_stencil_alpha_state(self, state):
Packit 8f2243
        # Normalize state to avoid spurious differences
Packit 8f2243
        if not state.alpha.enabled:
Packit 8f2243
            del state.alpha.func
Packit 8f2243
            del state.alpha.ref_value
Packit 8f2243
        for i in range(2):
Packit 8f2243
            if not state.stencil[i].enabled:
Packit 8f2243
                del state.stencil[i].func
Packit 8f2243
        return state
Packit 8f2243
Packit 8f2243
    def bind_depth_stencil_alpha_state(self, state):
Packit 8f2243
        self._state.depth_stencil_alpha = state
Packit 8f2243
            
Packit 8f2243
    def delete_depth_stencil_alpha_state(self, state):
Packit 8f2243
        pass
Packit 8f2243
Packit 8f2243
    _tokenLabelRE = re.compile('^\s*\d+: ', re.MULTILINE)
Packit 8f2243
Packit 8f2243
    def _create_shader_state(self, state):
Packit 8f2243
        # Strip the labels from the tokens
Packit 8f2243
        if state.tokens is not None:
Packit 8f2243
            state.tokens = self._tokenLabelRE.sub('', state.tokens)
Packit 8f2243
        return state
Packit 8f2243
Packit 8f2243
    create_vs_state = _create_shader_state
Packit 8f2243
    create_gs_state = _create_shader_state
Packit 8f2243
    create_fs_state = _create_shader_state
Packit 8f2243
    
Packit 8f2243
    def bind_vs_state(self, state):
Packit 8f2243
        self._state.vs.shader = state
Packit 8f2243
Packit 8f2243
    def bind_gs_state(self, state):
Packit 8f2243
        self._state.gs.shader = state
Packit 8f2243
        
Packit 8f2243
    def bind_fs_state(self, state):
Packit 8f2243
        self._state.fs.shader = state
Packit 8f2243
        
Packit 8f2243
    def _delete_shader_state(self, state):
Packit 8f2243
        return state
Packit 8f2243
Packit 8f2243
    delete_vs_state = _delete_shader_state
Packit 8f2243
    delete_gs_state = _delete_shader_state
Packit 8f2243
    delete_fs_state = _delete_shader_state
Packit 8f2243
Packit 8f2243
    def set_blend_color(self, state):
Packit 8f2243
        self._state.blend_color = state
Packit 8f2243
Packit 8f2243
    def set_stencil_ref(self, state):
Packit 8f2243
        self._state.stencil_ref = state
Packit 8f2243
Packit 8f2243
    def set_clip_state(self, state):
Packit 8f2243
        self._state.clip = state
Packit 8f2243
Packit 8f2243
    def _dump_constant_buffer(self, buffer):
Packit 8f2243
        if not self.interpreter.verbosity(2):
Packit 8f2243
            return
Packit 8f2243
Packit 8f2243
        data = self.real.buffer_read(buffer)
Packit 8f2243
        format = '4f'
Packit 8f2243
        index = 0
Packit 8f2243
        for offset in range(0, len(data), struct.calcsize(format)):
Packit 8f2243
            x, y, z, w = unpack_from(format, data, offset)
Packit 8f2243
            sys.stdout.write('\tCONST[%2u] = {%10.4f, %10.4f, %10.4f, %10.4f}\n' % (index, x, y, z, w))
Packit 8f2243
            index += 1
Packit 8f2243
        sys.stdout.flush()
Packit 8f2243
Packit 8f2243
    def _get_stage_state(self, shader):
Packit 8f2243
        if shader == PIPE_SHADER_VERTEX:
Packit 8f2243
            return self._state.vs
Packit 8f2243
        if shader == PIPE_SHADER_GEOMETRY:
Packit 8f2243
            return self._state.gs
Packit 8f2243
        if shader == PIPE_SHADER_FRAGMENT:
Packit 8f2243
            return self._state.fs
Packit 8f2243
        assert False
Packit 8f2243
Packit 8f2243
    def set_constant_buffer(self, shader, index, constant_buffer):
Packit 8f2243
        self._update(self._get_stage_state(shader).constant_buffer, index, 1, [constant_buffer])
Packit 8f2243
Packit 8f2243
    def set_framebuffer_state(self, state):
Packit 8f2243
        self._state.fb = state
Packit 8f2243
Packit 8f2243
    def set_polygon_stipple(self, state):
Packit 8f2243
        self._state.polygon_stipple = state
Packit 8f2243
Packit 8f2243
    def _update(self, array, start_slot, num_slots, states):
Packit 8f2243
        if not isinstance(states, list):
Packit 8f2243
            # XXX: trace is not serializing multiple scissors/viewports properly yet
Packit 8f2243
            num_slots = 1
Packit 8f2243
            states = [states]
Packit 8f2243
        while len(array) < start_slot + num_slots:
Packit 8f2243
            array.append(None)
Packit 8f2243
        for i in range(num_slots):
Packit 8f2243
            array[start_slot + i] = states[i]
Packit 8f2243
Packit 8f2243
    def set_scissor_states(self, start_slot, num_scissors, states):
Packit 8f2243
        self._update(self._state.scissors, start_slot, num_scissors, states)
Packit 8f2243
Packit 8f2243
    def set_viewport_states(self, start_slot, num_viewports, states):
Packit 8f2243
        self._update(self._state.viewports, start_slot, num_viewports, states)
Packit 8f2243
Packit 8f2243
    def create_sampler_view(self, resource, templ):
Packit 8f2243
        templ.resource = resource
Packit 8f2243
        return templ
Packit 8f2243
Packit 8f2243
    def sampler_view_destroy(self, view):
Packit 8f2243
        pass
Packit 8f2243
Packit 8f2243
    def set_sampler_views(self, shader, start, num, views):
Packit 8f2243
        # FIXME: Handle non-zero start
Packit 8f2243
        assert start == 0
Packit 8f2243
        self._get_stage_state(shader).sampler_views = views
Packit 8f2243
Packit 8f2243
    def set_fragment_sampler_views(self, num, views):
Packit 8f2243
        # XXX: deprecated
Packit 8f2243
        self._state.fs.sampler_views = views
Packit 8f2243
Packit 8f2243
    def set_geometry_sampler_views(self, num, views):
Packit 8f2243
        # XXX: deprecated
Packit 8f2243
        self._state.gs.sampler_views = views
Packit 8f2243
Packit 8f2243
    def set_vertex_sampler_views(self, num, views):
Packit 8f2243
        # XXX: deprecated
Packit 8f2243
        self._state.vs.sampler_views = views
Packit 8f2243
Packit 8f2243
    def set_vertex_buffers(self, start_slot, num_buffers, buffers):
Packit 8f2243
        self._update(self._state.vertex_buffers, start_slot, num_buffers, buffers)
Packit 8f2243
            
Packit 8f2243
    def create_vertex_elements_state(self, num_elements, elements):
Packit 8f2243
        return elements[0:num_elements]
Packit 8f2243
Packit 8f2243
    def bind_vertex_elements_state(self, state):
Packit 8f2243
        self._state.vertex_elements = state
Packit 8f2243
Packit 8f2243
    def delete_vertex_elements_state(self, state):
Packit 8f2243
        pass
Packit 8f2243
Packit 8f2243
    def set_index_buffer(self, ib):
Packit 8f2243
        self._state.index_buffer = ib
Packit 8f2243
Packit 8f2243
    # Don't dump more than this number of indices/vertices
Packit 8f2243
    MAX_ELEMENTS = 16
Packit 8f2243
Packit 8f2243
    def _merge_indices(self, info):
Packit 8f2243
        '''Merge the vertices into our state.'''
Packit 8f2243
Packit 8f2243
        index_size = self._state.index_buffer.index_size
Packit 8f2243
        
Packit 8f2243
        format = {
Packit 8f2243
            1: 'B',
Packit 8f2243
            2: 'H',
Packit 8f2243
            4: 'I',
Packit 8f2243
        }[index_size]
Packit 8f2243
Packit 8f2243
        assert struct.calcsize(format) == index_size
Packit 8f2243
Packit 8f2243
        if self._state.index_buffer.buffer is None:
Packit 8f2243
            # Could happen with index in user memory
Packit 8f2243
            return 0, 0
Packit 8f2243
Packit 8f2243
        data = self._state.index_buffer.buffer.data
Packit 8f2243
        max_index, min_index = 0, 0xffffffff
Packit 8f2243
Packit 8f2243
        count = min(info.count, self.MAX_ELEMENTS)
Packit 8f2243
        indices = []
Packit 8f2243
        for i in xrange(info.start, info.start + count):
Packit 8f2243
            offset = self._state.index_buffer.offset + i*index_size
Packit 8f2243
            if offset + index_size > len(data):
Packit 8f2243
                index = 0
Packit 8f2243
            else:
Packit 8f2243
                index, = unpack_from(format, data, offset)
Packit 8f2243
            indices.append(index)
Packit 8f2243
            min_index = min(min_index, index)
Packit 8f2243
            max_index = max(max_index, index)
Packit 8f2243
Packit 8f2243
        self._state.indices = indices
Packit 8f2243
Packit 8f2243
        return min_index + info.index_bias, max_index + info.index_bias
Packit 8f2243
Packit 8f2243
    def _merge_vertices(self, start, count):
Packit 8f2243
        '''Merge the vertices into our state.'''
Packit 8f2243
Packit 8f2243
        count = min(count, self.MAX_ELEMENTS)
Packit 8f2243
        vertices = []
Packit 8f2243
        for index in xrange(start, start + count):
Packit 8f2243
            if index >= start + 16:
Packit 8f2243
                sys.stdout.write('\t...\n')
Packit 8f2243
                break
Packit 8f2243
            vertex = []
Packit 8f2243
            for velem in self._state.vertex_elements:
Packit 8f2243
                vbuf = self._state.vertex_buffers[velem.vertex_buffer_index]
Packit 8f2243
                resource = vbuf.buffer_resource
Packit 8f2243
                if resource is None:
Packit 8f2243
                    continue
Packit 8f2243
Packit 8f2243
                data = resource.data
Packit 8f2243
Packit 8f2243
                offset = vbuf.buffer_offset + velem.src_offset + vbuf.stride*index
Packit 8f2243
                format = {
Packit 8f2243
                    'PIPE_FORMAT_R32_FLOAT': 'f',
Packit 8f2243
                    'PIPE_FORMAT_R32G32_FLOAT': '2f',
Packit 8f2243
                    'PIPE_FORMAT_R32G32B32_FLOAT': '3f',
Packit 8f2243
                    'PIPE_FORMAT_R32G32B32A32_FLOAT': '4f',
Packit 8f2243
                    'PIPE_FORMAT_R32_UINT': 'I',
Packit 8f2243
                    'PIPE_FORMAT_R32G32_UINT': '2I',
Packit 8f2243
                    'PIPE_FORMAT_R32G32B32_UINT': '3I',
Packit 8f2243
                    'PIPE_FORMAT_R32G32B32A32_UINT': '4I',
Packit 8f2243
                    'PIPE_FORMAT_R8_UINT': 'B',
Packit 8f2243
                    'PIPE_FORMAT_R8G8_UINT': '2B',
Packit 8f2243
                    'PIPE_FORMAT_R8G8B8_UINT': '3B',
Packit 8f2243
                    'PIPE_FORMAT_R8G8B8A8_UINT': '4B',
Packit 8f2243
                    'PIPE_FORMAT_A8R8G8B8_UNORM': '4B',
Packit 8f2243
                    'PIPE_FORMAT_R8G8B8A8_UNORM': '4B',
Packit 8f2243
                    'PIPE_FORMAT_B8G8R8A8_UNORM': '4B',
Packit 8f2243
                    'PIPE_FORMAT_R16G16B16_SNORM': '3h',
Packit 8f2243
                }[velem.src_format]
Packit 8f2243
Packit 8f2243
                data = resource.data
Packit 8f2243
                attribute = unpack_from(format, data, offset)
Packit 8f2243
                vertex.append(attribute)
Packit 8f2243
Packit 8f2243
            vertices.append(vertex)
Packit 8f2243
Packit 8f2243
        self._state.vertices = vertices
Packit 8f2243
Packit 8f2243
    def render_condition(self, query, condition = 0, mode = 0):
Packit 8f2243
        self._state.render_condition_query = query
Packit 8f2243
        self._state.render_condition_condition = condition
Packit 8f2243
        self._state.render_condition_mode = mode
Packit 8f2243
Packit 8f2243
    def set_stream_output_targets(self, num_targets, tgs, offsets):
Packit 8f2243
        self._state.so_targets = tgs
Packit 8f2243
        self._state.offsets = offsets
Packit 8f2243
Packit 8f2243
    def draw_vbo(self, info):
Packit 8f2243
        self._draw_no += 1
Packit 8f2243
Packit 8f2243
        if self.interpreter.call_no < self.interpreter.options.call and \
Packit 8f2243
            self._draw_no < self.interpreter.options.draw:
Packit 8f2243
                return
Packit 8f2243
Packit 8f2243
        # Merge the all draw state
Packit 8f2243
Packit 8f2243
        self._state.draw = info
Packit 8f2243
Packit 8f2243
        if info.index_size != 0:
Packit 8f2243
            min_index, max_index = self._merge_indices(info)
Packit 8f2243
        else:
Packit 8f2243
            min_index = info.start
Packit 8f2243
            max_index = info.start + info.count - 1
Packit 8f2243
        self._merge_vertices(min_index, max_index - min_index + 1)
Packit 8f2243
Packit 8f2243
        self._dump_state()
Packit 8f2243
Packit 8f2243
    _dclRE = re.compile('^DCL\s+(IN|OUT|SAMP|SVIEW)\[([0-9]+)\].*$', re.MULTILINE)
Packit 8f2243
Packit 8f2243
    def _normalize_stage_state(self, stage):
Packit 8f2243
Packit 8f2243
        registers = {}
Packit 8f2243
Packit 8f2243
        if stage.shader is not None and stage.shader.tokens is not None:
Packit 8f2243
            for mo in self._dclRE.finditer(stage.shader.tokens):
Packit 8f2243
                file_ = mo.group(1)
Packit 8f2243
                index = mo.group(2)
Packit 8f2243
                register = registers.setdefault(file_, set())
Packit 8f2243
                register.add(int(index))
Packit 8f2243
Packit 8f2243
        if 'SAMP' in registers and 'SVIEW' not in registers:
Packit 8f2243
            registers['SVIEW'] = registers['SAMP']
Packit 8f2243
Packit 8f2243
        mapping = [
Packit 8f2243
            #("CONST", "constant_buffer"),
Packit 8f2243
            ("SAMP", "sampler"),
Packit 8f2243
            ("SVIEW", "sampler_views"),
Packit 8f2243
        ]
Packit 8f2243
Packit 8f2243
        for fileName, attrName in mapping:
Packit 8f2243
            register = registers.setdefault(fileName, set())
Packit 8f2243
            attr = getattr(stage, attrName)
Packit 8f2243
            for index in range(len(attr)):
Packit 8f2243
                if index not in register:
Packit 8f2243
                    attr[index] = None
Packit 8f2243
            while attr and attr[-1] is None:
Packit 8f2243
                attr.pop()
Packit 8f2243
Packit 8f2243
    def _dump_state(self):
Packit 8f2243
        '''Dump our state to JSON and terminate.'''
Packit 8f2243
Packit 8f2243
        state = copy.deepcopy(self._state)
Packit 8f2243
Packit 8f2243
        self._normalize_stage_state(state.vs)
Packit 8f2243
        self._normalize_stage_state(state.gs)
Packit 8f2243
        self._normalize_stage_state(state.fs)
Packit 8f2243
Packit 8f2243
        json.dump(
Packit 8f2243
            obj = state,
Packit 8f2243
            fp = sys.stdout,
Packit 8f2243
            default = serialize,
Packit 8f2243
            sort_keys = True,
Packit 8f2243
            indent = 4,
Packit 8f2243
            separators = (',', ': ')
Packit 8f2243
        )
Packit 8f2243
Packit 8f2243
        sys.exit(0)
Packit 8f2243
Packit 8f2243
    def resource_copy_region(self, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box):
Packit 8f2243
        if dst.target == PIPE_BUFFER or src.target == PIPE_BUFFER:
Packit 8f2243
            assert dst.target == PIPE_BUFFER and src.target == PIPE_BUFFER
Packit 8f2243
            assert dst_level == 0
Packit 8f2243
            assert dsty == 0
Packit 8f2243
            assert dstz == 0
Packit 8f2243
            assert src_level == 0
Packit 8f2243
            assert src_box.y == 0
Packit 8f2243
            assert src_box.z == 0
Packit 8f2243
            assert src_box.height == 1
Packit 8f2243
            assert src_box.depth == 1
Packit 8f2243
            dst.data[dstx : dstx + src_box.width] = src.data[src_box.x : src_box.x + src_box.width]
Packit 8f2243
        pass
Packit 8f2243
Packit 8f2243
    def is_resource_referenced(self, texture, face, level):
Packit 8f2243
        pass
Packit 8f2243
    
Packit 8f2243
    def get_transfer(self, texture, sr, usage, box):
Packit 8f2243
        if texture is None:
Packit 8f2243
            return None
Packit 8f2243
        transfer = Transfer(texture, sr, usage, box)
Packit 8f2243
        return transfer
Packit 8f2243
    
Packit 8f2243
    def tex_transfer_destroy(self, transfer):
Packit 8f2243
        self.interpreter.unregister_object(transfer)
Packit 8f2243
Packit 8f2243
    def buffer_subdata(self, resource, usage, data, box=None, offset=None, size=None, level=None, stride=None, layer_stride=None):
Packit 8f2243
        if box is not None:
Packit 8f2243
            # XXX trace_context_transfer_unmap generates brokens buffer_subdata
Packit 8f2243
            assert offset is None
Packit 8f2243
            assert size is None
Packit 8f2243
            assert level == 0
Packit 8f2243
            offset = box.x
Packit 8f2243
            size = box.width
Packit 8f2243
            box = None
Packit 8f2243
Packit 8f2243
        if resource is not None and resource.target == PIPE_BUFFER:
Packit 8f2243
            data = data.getValue()
Packit 8f2243
            assert len(data) >= size
Packit 8f2243
            assert offset + size <= len(resource.data)
Packit 8f2243
            resource.data[offset : offset + size] = data[:size]
Packit 8f2243
Packit 8f2243
    def texture_subdata(self, resource, level, usage, box, data, stride, layer_stride):
Packit 8f2243
        pass
Packit 8f2243
Packit 8f2243
    def transfer_inline_write(self, resource, level, usage, box, stride, layer_stride, data):
Packit 8f2243
        if resource is not None and resource.target == PIPE_BUFFER:
Packit 8f2243
            data = data.getValue()
Packit 8f2243
            assert len(data) >= box.width
Packit 8f2243
            assert box.x + box.width <= len(resource.data)
Packit 8f2243
            resource.data[box.x : box.x + box.width] = data[:box.width]
Packit 8f2243
Packit 8f2243
    def flush(self, flags):
Packit 8f2243
        # Return a fake fence
Packit 8f2243
        return self.interpreter.call_no
Packit 8f2243
Packit 8f2243
    def clear(self, buffers, color, depth, stencil):
Packit 8f2243
        pass
Packit 8f2243
        
Packit 8f2243
    def clear_render_target(self, dst, rgba, dstx, dsty, width, height):
Packit 8f2243
        pass
Packit 8f2243
Packit 8f2243
    def clear_depth_stencil(self, dst, clear_flags, depth, stencil, dstx, dsty, width, height):
Packit 8f2243
        pass
Packit 8f2243
Packit 8f2243
    def create_surface(self, resource, surf_tmpl):
Packit 8f2243
        assert resource is not None
Packit 8f2243
        surf_tmpl.resource = resource
Packit 8f2243
        return surf_tmpl
Packit 8f2243
Packit 8f2243
    def surface_destroy(self, surface):
Packit 8f2243
        self.interpreter.unregister_object(surface)
Packit 8f2243
Packit 8f2243
    def create_query(self, query_type, index):
Packit 8f2243
        return query_type
Packit 8f2243
    
Packit 8f2243
    def destroy_query(self, query):
Packit 8f2243
        pass
Packit 8f2243
Packit 8f2243
    def begin_query(self, query):
Packit 8f2243
        pass
Packit 8f2243
Packit 8f2243
    def end_query(self, query):
Packit 8f2243
        pass
Packit 8f2243
Packit 8f2243
    def create_stream_output_target(self, res, buffer_offset, buffer_size):
Packit 8f2243
        so_target = Struct()
Packit 8f2243
        so_target.resource = res
Packit 8f2243
        so_target.offset = buffer_offset
Packit 8f2243
        so_target.size = buffer_size
Packit 8f2243
        return so_target
Packit 8f2243
Packit 8f2243
Packit 8f2243
class Interpreter(parser.TraceDumper):
Packit 8f2243
    '''Specialization of a trace parser that interprets the calls as it goes
Packit 8f2243
    along.'''
Packit 8f2243
    
Packit 8f2243
    ignoredCalls = set((
Packit 8f2243
            ('pipe_screen', 'is_format_supported'),
Packit 8f2243
            ('pipe_screen', 'get_name'),
Packit 8f2243
            ('pipe_screen', 'get_vendor'),
Packit 8f2243
            ('pipe_screen', 'get_param'),
Packit 8f2243
            ('pipe_screen', 'get_paramf'),
Packit 8f2243
            ('pipe_screen', 'get_shader_param'),
Packit 8f2243
            ('pipe_context', 'clear_render_target'), # XXX workaround trace bugs
Packit 8f2243
    ))
Packit 8f2243
Packit 8f2243
    def __init__(self, stream, options):
Packit 8f2243
        parser.TraceDumper.__init__(self, stream, sys.stderr)
Packit 8f2243
        self.options = options
Packit 8f2243
        self.objects = {}
Packit 8f2243
        self.result = None
Packit 8f2243
        self.globl = Global(self)
Packit 8f2243
        self.call_no = None
Packit 8f2243
Packit 8f2243
    def register_object(self, address, object):
Packit 8f2243
        self.objects[address] = object
Packit 8f2243
        
Packit 8f2243
    def unregister_object(self, object):
Packit 8f2243
        # TODO
Packit 8f2243
        pass
Packit 8f2243
Packit 8f2243
    def lookup_object(self, address):
Packit 8f2243
        try:
Packit 8f2243
            return self.objects[address]
Packit 8f2243
        except KeyError:
Packit 8f2243
            # Could happen, e.g., with user memory pointers
Packit 8f2243
            return address
Packit 8f2243
    
Packit 8f2243
    def interpret(self, trace):
Packit 8f2243
        for call in trace.calls:
Packit 8f2243
            self.interpret_call(call)
Packit 8f2243
Packit 8f2243
    def handle_call(self, call):
Packit 8f2243
        if (call.klass, call.method) in self.ignoredCalls:
Packit 8f2243
            return
Packit 8f2243
Packit 8f2243
        self.call_no = call.no
Packit 8f2243
Packit 8f2243
        if self.verbosity(1):
Packit 8f2243
            # Write the call to stderr (as stdout would corrupt the JSON output)
Packit 8f2243
            sys.stderr.flush()
Packit 8f2243
            sys.stdout.flush()
Packit 8f2243
            parser.TraceDumper.handle_call(self, call)
Packit 8f2243
            sys.stderr.flush()
Packit 8f2243
            sys.stdout.flush()
Packit 8f2243
        
Packit 8f2243
        args = [(str(name), self.interpret_arg(arg)) for name, arg in call.args] 
Packit 8f2243
        
Packit 8f2243
        if call.klass:
Packit 8f2243
            name, obj = args[0]
Packit 8f2243
            args = args[1:]
Packit 8f2243
        else:
Packit 8f2243
            obj = self.globl
Packit 8f2243
            
Packit 8f2243
        method = getattr(obj, call.method)
Packit 8f2243
        ret = method(**dict(args))
Packit 8f2243
        
Packit 8f2243
        # Keep track of created pointer objects.
Packit 8f2243
        if call.ret and isinstance(call.ret, model.Pointer):
Packit 8f2243
            if ret is None:
Packit 8f2243
                sys.stderr.write('warning: NULL returned\n')
Packit 8f2243
            self.register_object(call.ret.address, ret)
Packit 8f2243
Packit 8f2243
        self.call_no = None
Packit 8f2243
Packit 8f2243
    def interpret_arg(self, node):
Packit 8f2243
        translator = Translator(self)
Packit 8f2243
        return translator.visit(node)
Packit 8f2243
Packit 8f2243
    def verbosity(self, level):
Packit 8f2243
        return self.options.verbosity >= level
Packit 8f2243
    
Packit 8f2243
Packit 8f2243
class Main(parser.Main):
Packit 8f2243
Packit 8f2243
    def get_optparser(self):
Packit 8f2243
        '''Custom options.'''
Packit 8f2243
Packit 8f2243
        optparser = parser.Main.get_optparser(self)
Packit 8f2243
        optparser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbosity", help="no messages")
Packit 8f2243
        optparser.add_option("-v", "--verbose", action="count", dest="verbosity", default=0, help="increase verbosity level")
Packit 8f2243
        optparser.add_option("-c", "--call", action="store", type="int", dest="call", default=0xffffffff, help="dump on this call")
Packit 8f2243
        optparser.add_option("-d", "--draw", action="store", type="int", dest="draw", default=0xffffffff, help="dump on this draw")
Packit 8f2243
        return optparser
Packit 8f2243
Packit 8f2243
    def process_arg(self, stream, options):
Packit 8f2243
        parser = Interpreter(stream, options)
Packit 8f2243
        parser.parse()
Packit 8f2243
Packit 8f2243
Packit 8f2243
if __name__ == '__main__':
Packit 8f2243
    Main().main()