aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/svga
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2015-10-22 15:36:25 -0600
committerBrian Paul <[email protected]>2015-10-22 17:19:20 -0600
commit1082735bb69e9f64cb3991a52f0e270902917855 (patch)
tree6d7be9330902c673435dc050545953e22b773846 /src/gallium/drivers/svga
parentdf0f817e311dbf9af110779086a27429905b1faf (diff)
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 <[email protected]> Reviewed-by: José Fonseca <[email protected]>
Diffstat (limited to 'src/gallium/drivers/svga')
-rw-r--r--src/gallium/drivers/svga/svga_shader.h3
-rw-r--r--src/gallium/drivers/svga/svga_tgsi.c7
-rw-r--r--src/gallium/drivers/svga/svga_tgsi_emit.h3
-rw-r--r--src/gallium/drivers/svga/svga_tgsi_insn.c27
-rw-r--r--src/gallium/drivers/svga/svga_tgsi_vgpu10.c39
5 files changed, 77 insertions, 2 deletions
diff --git a/src/gallium/drivers/svga/svga_shader.h b/src/gallium/drivers/svga/svga_shader.h
index efcac408626..f49fdb46d0e 100644
--- a/src/gallium/drivers/svga/svga_shader.h
+++ b/src/gallium/drivers/svga/svga_shader.h
@@ -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;
diff --git a/src/gallium/drivers/svga/svga_tgsi.c b/src/gallium/drivers/svga/svga_tgsi.c
index 202eee276b7..4c16f4313a0 100644
--- a/src/gallium/drivers/svga/svga_tgsi.c
+++ b/src/gallium/drivers/svga/svga_tgsi.c
@@ -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) {
diff --git a/src/gallium/drivers/svga/svga_tgsi_emit.h b/src/gallium/drivers/svga/svga_tgsi_emit.h
index 0b82483ab2e..83f0c8bd4d0 100644
--- a/src/gallium/drivers/svga/svga_tgsi_emit.h
+++ b/src/gallium/drivers/svga/svga_tgsi_emit.h
@@ -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;
diff --git a/src/gallium/drivers/svga/svga_tgsi_insn.c b/src/gallium/drivers/svga/svga_tgsi_insn.c
index 00c91a4fa61..dbb90f7654e 100644
--- a/src/gallium/drivers/svga/svga_tgsi_insn.c
+++ b/src/gallium/drivers/svga/svga_tgsi_insn.c
@@ -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:
@@ -2103,6 +2104,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.
*/
static boolean
@@ -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);
diff --git a/src/gallium/drivers/svga/svga_tgsi_vgpu10.c b/src/gallium/drivers/svga/svga_tgsi_vgpu10.c
index 332904f88b4..e70ee689c59 100644
--- a/src/gallium/drivers/svga/svga_tgsi_vgpu10.c
+++ b/src/gallium/drivers/svga/svga_tgsi_vgpu10.c
@@ -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++;
}
}
}
@@ -5573,6 +5578,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.
*/