From 58ea42b7db72586563914dea6fed9656caaf7678 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 3 Nov 2011 17:40:56 -0600 Subject: [PATCH] svga: implement generic variable index remapping MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The state tracker may generate shaders that use generic vs outputs / fs inputs like: DCL IN[0], GENERIC[0] DCL IN[1], GENERIC[10] DCL IN[2], GENERIC[11] This patch remaps 0, 10, 11 to small integers like 1, 2, 3 so that we stay inside the SVGA3D limit (8). The remapping is done to both the vertex shader outputs and the fragment shader inputs. The same mapping must be used for a vs/fs pair. Note that 'union svga_compile_key' is now 'struct svga_compile_key' because we needed to add the register remapping table. The change in size isn't really significant though (it's not a search key). Also, add assertions when building up SVGA3D src/dst registers to we don't try to store too large of value for the bitfield size. Reviewed-by: José Fonseca --- src/gallium/drivers/svga/svga_context.h | 6 ++ src/gallium/drivers/svga/svga_pipe_fs.c | 4 + src/gallium/drivers/svga/svga_state_fs.c | 3 +- src/gallium/drivers/svga/svga_state_vs.c | 6 +- src/gallium/drivers/svga/svga_swtnl_state.c | 17 ++-- src/gallium/drivers/svga/svga_tgsi.c | 92 ++++++++++++++++++- src/gallium/drivers/svga/svga_tgsi.h | 27 +++++- .../drivers/svga/svga_tgsi_decl_sm30.c | 19 ++-- src/gallium/drivers/svga/svga_tgsi_emit.h | 12 ++- 9 files changed, 165 insertions(+), 21 deletions(-) diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h index 47e08ba68e1..86e5f23ffa3 100644 --- a/src/gallium/drivers/svga/svga_context.h +++ b/src/gallium/drivers/svga/svga_context.h @@ -36,6 +36,7 @@ #include "tgsi/tgsi_scan.h" #include "svga_state.h" +#include "svga_tgsi.h" #include "svga_hw_reg.h" #include "svga3d_shaderdefs.h" @@ -66,6 +67,11 @@ struct svga_shader struct svga_fragment_shader { struct svga_shader base; + + /** Mask of which generic varying variables are read by this shader */ + unsigned generic_inputs; + /** Table mapping original TGSI generic indexes to low integers */ + int8_t generic_remap_table[MAX_GENERIC_VARYING]; }; struct svga_vertex_shader diff --git a/src/gallium/drivers/svga/svga_pipe_fs.c b/src/gallium/drivers/svga/svga_pipe_fs.c index 347341eaaa7..1eb28617b6a 100644 --- a/src/gallium/drivers/svga/svga_pipe_fs.c +++ b/src/gallium/drivers/svga/svga_pipe_fs.c @@ -59,6 +59,10 @@ svga_create_fs_state(struct pipe_context *pipe, fs->base.id = svga->debug.shader_id++; + fs->generic_inputs = svga_get_generic_inputs_mask(&fs->base.info); + + svga_remap_generics(fs->generic_inputs, fs->generic_remap_table); + if (SVGA_DEBUG & DEBUG_TGSI || 0) { debug_printf("%s id: %u, inputs: %u, outputs: %u\n", __FUNCTION__, fs->base.id, diff --git a/src/gallium/drivers/svga/svga_state_fs.c b/src/gallium/drivers/svga/svga_state_fs.c index e5fb4d1c6e5..c95d82fc00e 100644 --- a/src/gallium/drivers/svga/svga_state_fs.c +++ b/src/gallium/drivers/svga/svga_state_fs.c @@ -116,6 +116,7 @@ fail: */ static enum pipe_error make_fs_key(const struct svga_context *svga, + struct svga_fragment_shader *fs, struct svga_fs_compile_key *key) { int i; @@ -215,7 +216,7 @@ emit_hw_fs(struct svga_context *svga, unsigned dirty) * SVGA_NEW_NEED_SWTNL * SVGA_NEW_SAMPLER */ - ret = make_fs_key( svga, &key ); + ret = make_fs_key( svga, fs, &key ); if (ret != PIPE_OK) return ret; diff --git a/src/gallium/drivers/svga/svga_state_vs.c b/src/gallium/drivers/svga/svga_state_vs.c index 0b3b5418e3b..3d3caea7449 100644 --- a/src/gallium/drivers/svga/svga_state_vs.c +++ b/src/gallium/drivers/svga/svga_state_vs.c @@ -107,7 +107,7 @@ fail: return ret; } -/* SVGA_NEW_PRESCALE, SVGA_NEW_RAST, SVGA_NEW_ZERO_STRIDE +/* SVGA_NEW_PRESCALE, SVGA_NEW_RAST, SVGA_NEW_ZERO_STRIDE, SVGA_NEW_FS */ static void make_vs_key(struct svga_context *svga, struct svga_vs_compile_key *key) @@ -119,6 +119,9 @@ make_vs_key(struct svga_context *svga, struct svga_vs_compile_key *key) svga->curr.zero_stride_vertex_elements; key->num_zero_stride_vertex_elements = svga->curr.num_zero_stride_vertex_elements; + + /* SVGA_NEW_FS */ + key->fs_generic_inputs = svga->curr.fs->generic_inputs; } @@ -166,6 +169,7 @@ struct svga_tracked_state svga_hw_vs = { "vertex shader (hwtnl)", (SVGA_NEW_VS | + SVGA_NEW_FS | SVGA_NEW_PRESCALE | SVGA_NEW_NEED_SWTNL | SVGA_NEW_ZERO_STRIDE), diff --git a/src/gallium/drivers/svga/svga_swtnl_state.c b/src/gallium/drivers/svga/svga_swtnl_state.c index cd1aa637a27..ade5ab9f999 100644 --- a/src/gallium/drivers/svga/svga_swtnl_state.c +++ b/src/gallium/drivers/svga/svga_swtnl_state.c @@ -31,7 +31,7 @@ #include "svga_context.h" #include "svga_swtnl.h" #include "svga_state.h" - +#include "svga_tgsi.h" #include "svga_swtnl_private.h" @@ -169,13 +169,15 @@ svga_swtnl_update_vdecl( struct svga_context *svga ) nr_decls++; for (i = 0; i < fs->base.info.num_inputs; i++) { - unsigned name = fs->base.info.input_semantic_name[i]; - unsigned index = fs->base.info.input_semantic_index[i]; - src = draw_find_shader_output(draw, name, index); + const unsigned sem_name = fs->base.info.input_semantic_name[i]; + const unsigned sem_index = fs->base.info.input_semantic_index[i]; + + src = draw_find_shader_output(draw, sem_name, sem_index); + vdecl[nr_decls].array.offset = offset; - vdecl[nr_decls].identity.usageIndex = fs->base.info.input_semantic_index[i]; + vdecl[nr_decls].identity.usageIndex = sem_index; - switch (name) { + switch (sem_name) { case TGSI_SEMANTIC_COLOR: draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src); vdecl[nr_decls].identity.usage = SVGA3D_DECLUSAGE_COLOR; @@ -187,7 +189,8 @@ svga_swtnl_update_vdecl( struct svga_context *svga ) draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src); vdecl[nr_decls].identity.usage = SVGA3D_DECLUSAGE_TEXCOORD; vdecl[nr_decls].identity.type = SVGA3D_DECLTYPE_FLOAT4; - vdecl[nr_decls].identity.usageIndex += 1; + vdecl[nr_decls].identity.usageIndex = + svga_remap_generic_index(fs->generic_remap_table, sem_index); offset += 16; nr_decls++; break; diff --git a/src/gallium/drivers/svga/svga_tgsi.c b/src/gallium/drivers/svga/svga_tgsi.c index 90a84230c98..821def4a3a6 100644 --- a/src/gallium/drivers/svga/svga_tgsi.c +++ b/src/gallium/drivers/svga/svga_tgsi.c @@ -30,6 +30,7 @@ #include "tgsi/tgsi_parse.h" #include "tgsi/tgsi_dump.h" #include "tgsi/tgsi_scan.h" +#include "util/u_math.h" #include "util/u_memory.h" #include "util/u_bitmask.h" @@ -156,7 +157,82 @@ static boolean svga_shader_emit_header( struct svga_shader_emitter *emit ) } +/** + * Use the shader info to generate a bitmask indicating which generic + * inputs are used by the shader. A set bit indicates that GENERIC[i] + * is used. + */ +unsigned +svga_get_generic_inputs_mask(const struct tgsi_shader_info *info) +{ + unsigned i, mask = 0x0; + + for (i = 0; i < info->num_inputs; i++) { + if (info->input_semantic_name[i] == TGSI_SEMANTIC_GENERIC) { + unsigned j = info->input_semantic_index[i]; + assert(j < sizeof(mask) * 8); + mask |= 1 << j; + } + } + return mask; +} + + +/** + * Given a mask of used generic variables (as returned by the above functions) + * fill in a table which maps those indexes to small integers. + * This table is used by the remap_generic_index() function in + * svga_tgsi_decl_sm30.c + * Example: if generics_mask = binary(1010) it means that GENERIC[1] and + * GENERIC[3] are used. The remap_table will contain: + * table[1] = 0; + * table[3] = 1; + * The remaining table entries will be filled in with the next unused + * generic index (in this example, 2). + */ +void +svga_remap_generics(unsigned generics_mask, + int8_t remap_table[MAX_GENERIC_VARYING]) +{ + /* Note texcoord[0] is reserved so start at 1 */ + unsigned count = 1, i; + + for (i = 0; i < MAX_GENERIC_VARYING; i++) { + remap_table[i] = -1; + } + + /* for each bit set in generic_mask */ + while (generics_mask) { + unsigned index = ffs(generics_mask) - 1; + remap_table[index] = count++; + generics_mask &= ~(1 << index); + } + + for (i = 0; i < MAX_GENERIC_VARYING; i++) { + if (remap_table[i] == -1) + remap_table[i] = count; + } +} + + +/** + * Use the generic remap table to map a TGSI generic varying variable + * index to a small integer. + */ +int +svga_remap_generic_index(const int8_t remap_table[MAX_GENERIC_VARYING], + int generic_index) +{ + assert(generic_index < MAX_GENERIC_VARYING); + + if (generic_index >= MAX_GENERIC_VARYING) { + /* just don't return a random/garbage value */ + generic_index = MAX_GENERIC_VARYING - 1; + } + + return remap_table[generic_index]; +} /* Parse TGSI shader and translate to SVGA/DX9 serialized @@ -168,7 +244,7 @@ static boolean svga_shader_emit_header( struct svga_shader_emitter *emit ) */ static struct svga_shader_result * svga_tgsi_translate( const struct svga_shader *shader, - union svga_compile_key key, + struct svga_compile_key key, unsigned unit ) { struct svga_shader_result *result = NULL; @@ -248,9 +324,13 @@ struct svga_shader_result * svga_translate_fragment_program( const struct svga_fragment_shader *fs, const struct svga_fs_compile_key *fkey ) { - union svga_compile_key key; + struct svga_compile_key key; + memcpy(&key.fkey, fkey, sizeof *fkey); + memcpy(key.generic_remap_table, fs->generic_remap_table, + sizeof(fs->generic_remap_table)); + return svga_tgsi_translate( &fs->base, key, PIPE_SHADER_FRAGMENT ); @@ -260,9 +340,15 @@ struct svga_shader_result * svga_translate_vertex_program( const struct svga_vertex_shader *vs, const struct svga_vs_compile_key *vkey ) { - union svga_compile_key key; + struct svga_compile_key key; + memcpy(&key.vkey, vkey, sizeof *vkey); + /* Note: we could alternately store the remap table in the vkey but + * that would make it larger. We just regenerate it here instead. + */ + svga_remap_generics(vkey->fs_generic_inputs, key.generic_remap_table); + return svga_tgsi_translate( &vs->base, key, PIPE_SHADER_VERTEX ); diff --git a/src/gallium/drivers/svga/svga_tgsi.h b/src/gallium/drivers/svga/svga_tgsi.h index 214e113aaaa..01367e971da 100644 --- a/src/gallium/drivers/svga/svga_tgsi.h +++ b/src/gallium/drivers/svga/svga_tgsi.h @@ -30,6 +30,13 @@ #include "svga_hw_reg.h" + +/** + * We use a 32-bit mask to keep track of the generic indexes. + */ +#define MAX_GENERIC_VARYING 32 + + struct svga_fragment_shader; struct svga_vertex_shader; struct svga_shader; @@ -39,6 +46,7 @@ struct tgsi_token; struct svga_vs_compile_key { + unsigned fs_generic_inputs; unsigned zero_stride_vertex_elements; unsigned need_prescale:1; unsigned allow_psiz:1; @@ -67,9 +75,10 @@ struct svga_fs_compile_key } tex[PIPE_MAX_SAMPLERS]; }; -union svga_compile_key { +struct svga_compile_key { struct svga_vs_compile_key vkey; struct svga_fs_compile_key fkey; + int8_t generic_remap_table[MAX_GENERIC_VARYING]; }; struct svga_shader_result @@ -78,7 +87,7 @@ struct svga_shader_result /* Parameters used to generate this compilation result: */ - union svga_compile_key key; + struct svga_compile_key key; /* Compiled shader tokens: */ @@ -140,4 +149,18 @@ svga_translate_vertex_program( const struct svga_vertex_shader *fs, void svga_destroy_shader_result( struct svga_shader_result *result ); +unsigned +svga_get_generic_inputs_mask(const struct tgsi_shader_info *info); + +unsigned +svga_get_generic_outputs_mask(const struct tgsi_shader_info *info); + +void +svga_remap_generics(unsigned generics_mask, + int8_t remap_table[MAX_GENERIC_VARYING]); + +int +svga_remap_generic_index(const int8_t remap_table[MAX_GENERIC_VARYING], + int generic_index); + #endif diff --git a/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c b/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c index 6f408704863..0ed12ac26de 100644 --- a/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c +++ b/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c @@ -30,7 +30,9 @@ #include "svga_tgsi_emit.h" -static boolean translate_vs_ps_semantic( struct tgsi_declaration_semantic semantic, + +static boolean translate_vs_ps_semantic( struct svga_shader_emitter *emit, + struct tgsi_declaration_semantic semantic, unsigned *usage, unsigned *idx ) { @@ -58,7 +60,8 @@ static boolean translate_vs_ps_semantic( struct tgsi_declaration_semantic semant *usage = SVGA3D_DECLUSAGE_PSIZE; break; case TGSI_SEMANTIC_GENERIC: - *idx = semantic.Index + 1; /* texcoord[0] is reserved for fog & position */ + *idx = svga_remap_generic_index(emit->key.generic_remap_table, + semantic.Index); *usage = SVGA3D_DECLUSAGE_TEXCOORD; break; case TGSI_SEMANTIC_NORMAL: @@ -84,6 +87,10 @@ static boolean emit_decl( struct svga_shader_emitter *emit, SVGA3DOpDclArgs dcl; SVGA3dShaderInstToken opcode; + /* check values against bitfield sizes */ + assert(index < 16); + assert(usage <= SVGA3D_DECLUSAGE_MAX); + opcode = inst_token( SVGA3DOP_DCL ); dcl.values[0] = 0; dcl.values[1] = 0; @@ -181,7 +188,7 @@ static boolean ps30_input( struct svga_shader_emitter *emit, else if (emit->key.fkey.light_twoside && (semantic.Name == TGSI_SEMANTIC_COLOR)) { - if (!translate_vs_ps_semantic( semantic, &usage, &index )) + if (!translate_vs_ps_semantic( emit, semantic, &usage, &index )) return FALSE; emit->internal_color_idx[emit->internal_color_count] = idx; @@ -195,7 +202,7 @@ static boolean ps30_input( struct svga_shader_emitter *emit, return FALSE; semantic.Name = TGSI_SEMANTIC_BCOLOR; - if (!translate_vs_ps_semantic( semantic, &usage, &index )) + if (!translate_vs_ps_semantic( emit, semantic, &usage, &index )) return FALSE; if (emit->ps30_input_count >= SVGA3D_INPUTREG_MAX) @@ -234,7 +241,7 @@ static boolean ps30_input( struct svga_shader_emitter *emit, } else { - if (!translate_vs_ps_semantic( semantic, &usage, &index )) + if (!translate_vs_ps_semantic( emit, semantic, &usage, &index )) return FALSE; if (emit->ps30_input_count >= SVGA3D_INPUTREG_MAX) @@ -398,7 +405,7 @@ static boolean vs30_output( struct svga_shader_emitter *emit, dcl.values[0] = 0; dcl.values[1] = 0; - if (!translate_vs_ps_semantic( semantic, &usage, &index )) + if (!translate_vs_ps_semantic( emit, semantic, &usage, &index )) return FALSE; if (emit->vs30_output_count >= SVGA3D_OUTPUTREG_MAX) diff --git a/src/gallium/drivers/svga/svga_tgsi_emit.h b/src/gallium/drivers/svga/svga_tgsi_emit.h index 8ff25d678dc..943433d9558 100644 --- a/src/gallium/drivers/svga/svga_tgsi_emit.h +++ b/src/gallium/drivers/svga/svga_tgsi_emit.h @@ -54,7 +54,7 @@ struct svga_shader_emitter char *buf; char *ptr; - union svga_compile_key key; + struct svga_compile_key key; struct tgsi_shader_info info; int unit; @@ -262,6 +262,11 @@ dst_register( unsigned file, { SVGA3dShaderDestToken dest; + /* check values against bitfield sizes */ + assert(number < (1 << 11)); + assert((file >> 3) < 4); + assert((file & 0x7) < 8); + dest.value = 0; dest.num = number; dest.type_upper = file >> 3; @@ -291,6 +296,11 @@ src_token( unsigned file, int number ) { SVGA3dShaderSrcToken src; + /* check values against bitfield sizes */ + assert(number < (1 << 11)); + assert((file >> 3) < 4); + assert((file & 0x7) < 8); + src.value = 0; src.num = number; src.type_upper = file >> 3; -- 2.30.2