svga: detect constant color writes in fragment shaders
Examine the fragment shader to try to detect TGSI shaders which use "MOV OUT[0], CONST[i]" to write a constant value for the fragment color. In this case, all fragments will have the same color (unless blending is enabled). This is a common case for OpenGL code such as: glColor(), glBegin(), glVertex(), ..., glEnd() when lighting/fog/etc are disabled. In this case, the Mesa/gallium state tracker actually generates a simple "MOV OUT[0], CONST[i]" fragment shader. This will be used by the next commit to avoid provoking vertex conversion (creating/rewriting an index buffer) when drawing flat-shaded primitives. Reviewed-by: Charmaine Lee <charmainel@vmware.com> Reviewed-by: José Fonseca <jfonseca@vmware.com>
This commit is contained in:
parent
df0f817e31
commit
1082735bb6
|
@ -155,6 +155,9 @@ struct svga_shader_variant
|
|||
* applied to any of the varyings.
|
||||
*/
|
||||
|
||||
/** Is the color output just a constant value? (fragment shader only) */
|
||||
boolean constant_color_output;
|
||||
|
||||
/** For FS-based polygon stipple */
|
||||
unsigned pstipple_sampler_unit;
|
||||
|
||||
|
|
|
@ -240,6 +240,13 @@ svga_tgsi_vgpu9_translate(struct svga_context *svga,
|
|||
|
||||
variant->pstipple_sampler_unit = emit.pstipple_sampler_unit;
|
||||
|
||||
/* If there was exactly one write to a fragment shader output register
|
||||
* and it came from a constant buffer, we know all fragments will have
|
||||
* the same color (except for blending).
|
||||
*/
|
||||
variant->constant_color_output =
|
||||
emit.constant_color_output && emit.num_output_writes == 1;
|
||||
|
||||
#if 0
|
||||
if (!svga_shader_verify(variant->tokens, variant->nr_tokens) ||
|
||||
SVGA_DEBUG & DEBUG_TGSI) {
|
||||
|
|
|
@ -84,6 +84,9 @@ struct svga_shader_emitter
|
|||
|
||||
int dynamic_branching_level;
|
||||
|
||||
unsigned num_output_writes;
|
||||
boolean constant_color_output;
|
||||
|
||||
boolean in_main_func;
|
||||
|
||||
boolean created_common_immediate;
|
||||
|
|
|
@ -99,6 +99,7 @@ translate_dst_register( struct svga_shader_emitter *emit,
|
|||
* Need to lookup a table built at decl time:
|
||||
*/
|
||||
dest = emit->output_map[reg->Register.Index];
|
||||
emit->num_output_writes++;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -2102,6 +2103,29 @@ emit_simple_instruction(struct svga_shader_emitter *emit,
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* TGSI_OPCODE_MOVE is only special-cased here to detect the
|
||||
* svga_fragment_shader::constant_color_output case.
|
||||
*/
|
||||
static boolean
|
||||
emit_mov(struct svga_shader_emitter *emit,
|
||||
const struct tgsi_full_instruction *insn)
|
||||
{
|
||||
const struct tgsi_full_src_register *src = &insn->Src[0];
|
||||
const struct tgsi_full_dst_register *dst = &insn->Dst[0];
|
||||
|
||||
if (emit->unit == PIPE_SHADER_FRAGMENT &&
|
||||
dst->Register.File == TGSI_FILE_OUTPUT &&
|
||||
dst->Register.Index == 0 &&
|
||||
src->Register.File == TGSI_FILE_CONSTANT &&
|
||||
!src->Register.Indirect) {
|
||||
emit->constant_color_output = TRUE;
|
||||
}
|
||||
|
||||
return emit_simple_instruction(emit, SVGA3DOP_MOV, insn);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Translate/emit TGSI DDX, DDY instructions.
|
||||
*/
|
||||
|
@ -3045,6 +3069,9 @@ svga_emit_instruction(struct svga_shader_emitter *emit,
|
|||
case TGSI_OPCODE_SSG:
|
||||
return emit_ssg( emit, insn );
|
||||
|
||||
case TGSI_OPCODE_MOV:
|
||||
return emit_mov( emit, insn );
|
||||
|
||||
default:
|
||||
{
|
||||
unsigned opcode = translate_opcode(insn->Instruction.Opcode);
|
||||
|
|
|
@ -202,6 +202,9 @@ struct svga_shader_emitter_v10
|
|||
/* user clip plane constant slot indexes */
|
||||
unsigned clip_plane_const[PIPE_MAX_CLIP_PLANES];
|
||||
|
||||
unsigned num_output_writes;
|
||||
boolean constant_color_output;
|
||||
|
||||
boolean uses_flat_interp;
|
||||
|
||||
/* For all shaders: const reg index for RECT coord scaling */
|
||||
|
@ -913,6 +916,8 @@ emit_dst_register(struct svga_shader_emitter_v10 *emit,
|
|||
*/
|
||||
assert(sem_name == TGSI_SEMANTIC_COLOR);
|
||||
index = emit->info.output_semantic_index[index];
|
||||
|
||||
emit->num_output_writes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5572,6 +5577,29 @@ emit_simple(struct svga_shader_emitter_v10 *emit,
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* We only special case the MOV instruction to try to detect constant
|
||||
* color writes in the fragment shader.
|
||||
*/
|
||||
static boolean
|
||||
emit_mov(struct svga_shader_emitter_v10 *emit,
|
||||
const struct tgsi_full_instruction *inst)
|
||||
{
|
||||
const struct tgsi_full_src_register *src = &inst->Src[0];
|
||||
const struct tgsi_full_dst_register *dst = &inst->Dst[0];
|
||||
|
||||
if (emit->unit == PIPE_SHADER_FRAGMENT &&
|
||||
dst->Register.File == TGSI_FILE_OUTPUT &&
|
||||
dst->Register.Index == 0 &&
|
||||
src->Register.File == TGSI_FILE_CONSTANT &&
|
||||
!src->Register.Indirect) {
|
||||
emit->constant_color_output = TRUE;
|
||||
}
|
||||
|
||||
return emit_simple(emit, inst);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Emit a simple VGPU10 instruction which writes to multiple dest registers,
|
||||
* where TGSI only uses one dest register.
|
||||
|
@ -5652,7 +5680,6 @@ emit_vgpu10_instruction(struct svga_shader_emitter_v10 *emit,
|
|||
case TGSI_OPCODE_MAD:
|
||||
case TGSI_OPCODE_MAX:
|
||||
case TGSI_OPCODE_MIN:
|
||||
case TGSI_OPCODE_MOV:
|
||||
case TGSI_OPCODE_MUL:
|
||||
case TGSI_OPCODE_NOP:
|
||||
case TGSI_OPCODE_NOT:
|
||||
|
@ -5677,7 +5704,8 @@ emit_vgpu10_instruction(struct svga_shader_emitter_v10 *emit,
|
|||
/* simple instructions */
|
||||
return emit_simple(emit, inst);
|
||||
|
||||
|
||||
case TGSI_OPCODE_MOV:
|
||||
return emit_mov(emit, inst);
|
||||
case TGSI_OPCODE_EMIT:
|
||||
return emit_vertex(emit, inst);
|
||||
case TGSI_OPCODE_ENDPRIM:
|
||||
|
@ -6762,6 +6790,13 @@ svga_tgsi_vgpu10_translate(struct svga_context *svga,
|
|||
|
||||
variant->pstipple_sampler_unit = emit->fs.pstipple_sampler_unit;
|
||||
|
||||
/* If there was exactly one write to a fragment shader output register
|
||||
* and it came from a constant buffer, we know all fragments will have
|
||||
* the same color (except for blending).
|
||||
*/
|
||||
variant->constant_color_output =
|
||||
emit->constant_color_output && emit->num_output_writes == 1;
|
||||
|
||||
/** keep track in the variant if flat interpolation is used
|
||||
* for any of the varyings.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue