summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--native/driver/etna_pipe.c21
-rw-r--r--tools/data/viv_gallium_state.txt27
-rwxr-xr-xtools/gen_weave_state.py70
3 files changed, 91 insertions, 27 deletions
diff --git a/native/driver/etna_pipe.c b/native/driver/etna_pipe.c
index 2b853e5..c901651 100644
--- a/native/driver/etna_pipe.c
+++ b/native/driver/etna_pipe.c
@@ -226,7 +226,7 @@ static void reset_context(struct pipe_context *pipe)
ETNA_COALESCE_STATE_UPDATE(state_name, e->gpu3d.dest_field, 1)
uint32_t last_reg, last_fixp, span_start;
- ETNA_COALESCE_STATE_OPEN(400); /* worst case */
+ ETNA_COALESCE_STATE_OPEN(400); /* keep this number above "Total state updates (fixed)" from gen_weave_state tool */
/* below code generated by gen_weave_state.py, keep this in sync with sync_context! */
/* begin only EMIT_STATE -- make sure no new etna_reserve calls are done here directly
* or indirectly */
@@ -411,6 +411,17 @@ static void sync_context(struct pipe_context *pipe)
e->gpu3d.dest_field = (src_value); \
}
+ /* Update vertex elements. This is different from any of the other states, in that
+ * a) the number of vertex elements written matters: so write only active ones
+ * b) the vertex element states must all be written: do not skip entries that stay the same
+ */
+ if(dirty & (ETNA_STATE_VERTEX_ELEMENTS))
+ {
+ /* Special case: vertex elements must always be sent in full */
+ /*00600*/ etna_set_state_multi(ctx, VIVS_FE_VERTEX_ELEMENT_CONFIG(0), e->vertex_elements->num_elements, e->vertex_elements->FE_VERTEX_ELEMENT_CONFIG);
+ memcpy(e->gpu3d.FE_VERTEX_ELEMENT_CONFIG, e->vertex_elements->FE_VERTEX_ELEMENT_CONFIG, e->vertex_elements->num_elements * 4);
+ }
+
/* The following code is originally generated by gen_merge_state.py, to
* emit state in increasing order of address (this makes it possible to merge
* consecutive register updates into one SET_STATE command)
@@ -425,14 +436,8 @@ static void sync_context(struct pipe_context *pipe)
* - ETNA_STATE_TS
* - removed ETNA_STATE_BASE_SETUP statements -- these are guaranteed to not change anyway
*/
- if(dirty & (ETNA_STATE_VERTEX_ELEMENTS))
- {
- /* Special case: vertex elements must always be sent in full */
- /*00600*/ etna_set_state_multi(ctx, VIVS_FE_VERTEX_ELEMENT_CONFIG(0), e->vertex_elements->num_elements, e->vertex_elements->FE_VERTEX_ELEMENT_CONFIG);
- memcpy(e->gpu3d.FE_VERTEX_ELEMENT_CONFIG, e->vertex_elements->FE_VERTEX_ELEMENT_CONFIG, e->vertex_elements->num_elements * 4);
- }
uint32_t last_reg, last_fixp, span_start;
- ETNA_COALESCE_STATE_OPEN(400); /* worst case */
+ ETNA_COALESCE_STATE_OPEN(400); /* keep this number above "Total state updates (fixed)" from gen_weave_state tool */
/* begin only EMIT_STATE -- make sure no new etna_reserve calls are done here directly
* or indirectly */
if(dirty & (ETNA_STATE_INDEX_BUFFER))
diff --git a/tools/data/viv_gallium_state.txt b/tools/data/viv_gallium_state.txt
index b8db770..707cba1 100644
--- a/tools/data/viv_gallium_state.txt
+++ b/tools/data/viv_gallium_state.txt
@@ -2,6 +2,9 @@
# <struct_name> <source_spec> <dirtybit>
# TODO: specify how to combine fields (if not simply |)
+# Mark large, dynamically sized state areas such as shader code
+# and parameters with DYNAMIC.
+
base_setup_state base_setup. ETNA_STATE_BASE_SETUP
PA.W_CLIP_LIMIT
GL.VERTEX_ELEMENT_CONFIG
@@ -19,7 +22,7 @@ rasterizer_state rasterizer-> ETNA_STATE_RASTERIZER
SE.SCISSOR_TOP
SE.SCISSOR_RIGHT
SE.SCISSOR_BOTTOM
- VS.OUTPUT_COUNT Added to shader state output count
+ VS.OUTPUT_COUNT # Added to shader state output count
depth_stencil_alpha_state depth_stencil_alpha-> ETNA_STATE_DSA
PE.DEPTH_CONFIG
@@ -60,15 +63,15 @@ sample_mask sample_mask. ETNA_STATE_SAMPLE_MASK
GL.MULTI_SAMPLE_CONFIG
sampler_state sampler[{0}]-> ETNA_STATE_SAMPLERS
- TE.SAMPLER.CONFIG0 Set to 0 for inactive samplers
- TE.SAMPLER.LOD_CONFIG Only set for active samplers
+ TE.SAMPLER.CONFIG0 # Set to 0 for inactive samplers
+ TE.SAMPLER.LOD_CONFIG # Only set for active samplers
sampler_view sampler_view[{0}]. ETNA_STATE_SAMPLER_VIEWS
- TE.SAMPLER.CONFIG0 Only set for active samplers
- TE.SAMPLER.LOD_CONFIG Only set for active samplers
- TE.SAMPLER.SIZE Only set for active samplers
- TE.SAMPLER.LOG_SIZE Only set for active samplers
- TE.SAMPLER.LOD_ADDR Only set for active samplers
+ TE.SAMPLER.CONFIG0 # Only set for active samplers
+ TE.SAMPLER.LOD_CONFIG # Only set for active samplers
+ TE.SAMPLER.SIZE # Only set for active samplers
+ TE.SAMPLER.LOG_SIZE # Only set for active samplers
+ TE.SAMPLER.LOD_ADDR # Only set for active samplers
framebuffer_state framebuffer. ETNA_STATE_FRAMEBUFFER
GL.MULTI_SAMPLE_CONFIG
@@ -128,12 +131,12 @@ shader_state shader_state. ETNA_STATE_SHADER
GL.VARYING_TOTAL_COMPONENTS
GL.VARYING_NUM_COMPONENTS
GL.VARYING_COMPONENT_USE
- VS.INST_MEM
- PS.INST_MEM
+ VS.INST_MEM DYNAMIC
+ PS.INST_MEM DYNAMIC
shader_state shader_state-> ETNA_STATE_VS_UNIFORMS
- VS.UNIFORMS
+ VS.UNIFORMS DYNAMIC
shader_state shader_state-> ETNA_STATE_PS_UNIFORMS
- PS.UNIFORMS
+ PS.UNIFORMS DYNAMIC
diff --git a/tools/gen_weave_state.py b/tools/gen_weave_state.py
index 9b86c75..abc6e93 100755
--- a/tools/gen_weave_state.py
+++ b/tools/gen_weave_state.py
@@ -26,6 +26,7 @@ from __future__ import print_function, division, unicode_literals
import argparse
from collections import defaultdict
import sys
+import operator
# Parse rules-ng-ng format for state space
from etnaviv.util import rnndb_path
from etnaviv.parse_rng import parse_rng_file, format_path, BitSet, Domain, Stripe, Register, Array, BaseType
@@ -76,23 +77,50 @@ def rnn_strides(path):
raise ValueError
return offset, strides
+class FieldAttributes(object):
+ def __init__(self):
+ # Set defaults
+ # Mark large, dynamically sized state areas such as shader code
+ # and parameters with DYNAMIC.
+ self.dynamic = False
+
+ def __eq__(self, other):
+ return self.dynamic == other.dynamic
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+def parse_field_attributes(line):
+ field_attributes = FieldAttributes()
+ for token in line:
+ if token == 'DYNAMIC':
+ field_attributes.dynamic = True
+ else:
+ print('Unknown field attribute %s' % token)
+ exit(1)
+ return field_attributes
+
def main():
args = parse_args()
state_xml = parse_rng_file(args.rules_file)
state_map = state_xml.lookup_domain('VIVS')
out = sys.stdout
+
# Read input file
with open(args.input, 'r') as f:
fields = None
recordname = None
data = []
for line in f:
+ (line, _, _) = line.partition('#')
line = line.rstrip()
- if not line or line.startswith('#'):
+ if not line:
continue
if line.startswith(' '):
+ # If line starts with four spaces this is a field
+ # specification.
line = line.strip().split()
- fields.append(line[0])
+ field_attr = parse_field_attributes(line[1:])
+ fields.append((line[0], field_attr))
else:
if recordname is not None:
data.append([recordname, fields])
@@ -100,18 +128,28 @@ def main():
recordname = line.strip()
if recordname is not None:
data.append([recordname, fields])
- # Preprocess input file, look up field names and sort by offset
+
+ # Preprocess input file, look up field names and sort by register offset
recs_by_offset = defaultdict(list)
field_by_offset = {}
+ field_attrs_by_offset = {}
for rec in data:
rec_info = rec[0].split()
- for field in rec[1]:
+ for field,field_attr in rec[1]:
path = rnn_lookup(state_map, field)
offset, strides = rnn_strides(path)
- #print(field, '%05x' % offset, strides)
field_by_offset[offset] = (field, path, strides)
recs_by_offset[offset].append(rec_info)
- # Emit weave state
+ if not offset in field_attrs_by_offset:
+ field_attrs_by_offset[offset] = field_attr
+ else:
+ # if this field is specified in multiple state atoms,
+ # the attributes must be equal for each
+ if field_attrs_by_offset[offset] != field_attr:
+ print('Field attribute conflict for %s' % field)
+ exit(1)
+
+ # Emit weave state code
print('/* Weave state */')
offsets = sorted(field_by_offset.keys())
last_dirty_bits = None
@@ -186,7 +224,7 @@ def main():
out.write(' ' * indent)
out.write('}\n')
- # Emit reset state function
+ # Emit reset state function code
# This function pushes the current context structure to the gpu
print()
print('/* Reset state */')
@@ -244,6 +282,24 @@ def main():
out.write(' ' * indent)
out.write('}\n')
+ # Generate statistics
+ total_updates_fixed = 0
+ total_updates_dynamic = 0
+ for offset in offsets:
+ (name, path, strides) = field_by_offset[offset]
+ state_count = reduce(operator.mul, (length for (stride,length) in strides), 1)
+ attrs = field_attrs_by_offset[offset]
+
+ if not attrs.dynamic:
+ total_updates_fixed += state_count
+ else:
+ total_updates_dynamic += state_count
+ print()
+ print('/* Statistics')
+ print(' Total state updates (fixed): %i' % total_updates_fixed)
+ print(' Maximum state updates (dynamic): %i' % total_updates_dynamic)
+ print('*/')
+
if __name__ == '__main__':
main()