svga: implement 'white_fragments' option for VGPU10 fragment shaders

When we emulate XOR logicop mode with blend-subtract, we need to ensure
that the fragment shader always emits white.  We had this implemented
for VGPU9, but not VGPU10.

VMware bug 1545492.

Reviewed-by: Charmaine Lee <charmainel@vmware.com>
This commit is contained in:
Brian Paul
2015-11-03 14:34:15 -07:00
parent 149ac1fe43
commit d31481e70a
+30 -5
View File
@@ -2672,6 +2672,7 @@ emit_temporaries_declaration(struct svga_shader_emitter_v10 *emit)
}
else if (emit->unit == PIPE_SHADER_FRAGMENT) {
if (emit->key.fs.alpha_func != SVGA3D_CMP_ALWAYS ||
emit->key.fs.white_fragments ||
emit->key.fs.write_color0_to_n_cbufs > 1) {
/* Allocate a temp to hold the output color */
emit->fs.color_tmp_index = total_temps;
@@ -6369,8 +6370,11 @@ emit_alpha_test_instructions(struct svga_shader_emitter_v10 *emit,
emit_src_register(emit, &tmp_src_x);
end_emit_instruction(emit);
/* If we don't need to broadcast the color below, emit final color here */
if (emit->key.fs.write_color0_to_n_cbufs <= 1) {
/* If we don't need to broadcast the color below or set fragments to
* white, emit final color here.
*/
if (emit->key.fs.write_color0_to_n_cbufs <= 1 &&
!emit->key.fs.white_fragments) {
/* MOV output.color, tempcolor */
emit_instruction_op1(emit, VGPU10_OPCODE_MOV, &color_dst,
&color_src, FALSE); /* XXX saturate? */
@@ -6380,10 +6384,28 @@ emit_alpha_test_instructions(struct svga_shader_emitter_v10 *emit,
}
/**
* When we need to emit white for all fragments (for emulating XOR logicop
* mode), this function copies white into the temporary color output register.
*/
static void
emit_set_color_white(struct svga_shader_emitter_v10 *emit,
unsigned fs_color_tmp_index)
{
struct tgsi_full_dst_register color_dst =
make_dst_temp_reg(fs_color_tmp_index);
struct tgsi_full_src_register white =
make_immediate_reg_float(emit, 1.0f);
emit_instruction_op1(emit, VGPU10_OPCODE_MOV, &color_dst, &white, FALSE);
}
/**
* Emit instructions for writing a single color output to multiple
* color buffers.
* This is used when the TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS
* This is used when the TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS (or
* when key.fs.white_fragments is true).
* property is set and the number of render targets is greater than one.
* \param fs_color_tmp_index index of the temp register that holds the
* color to broadcast.
@@ -6398,7 +6420,6 @@ emit_broadcast_color_instructions(struct svga_shader_emitter_v10 *emit,
make_src_temp_reg(fs_color_tmp_index);
assert(emit->unit == PIPE_SHADER_FRAGMENT);
assert(n > 1);
for (i = 0; i < n; i++) {
unsigned output_reg = emit->fs.color_out_index[i];
@@ -6440,7 +6461,11 @@ emit_post_helpers(struct svga_shader_emitter_v10 *emit)
if (emit->key.fs.alpha_func != SVGA3D_CMP_ALWAYS) {
emit_alpha_test_instructions(emit, fs_color_tmp_index);
}
if (emit->key.fs.write_color0_to_n_cbufs > 1) {
if (emit->key.fs.white_fragments) {
emit_set_color_white(emit, fs_color_tmp_index);
}
if (emit->key.fs.write_color0_to_n_cbufs > 1 ||
emit->key.fs.white_fragments) {
emit_broadcast_color_instructions(emit, fs_color_tmp_index);
}
}