From d31481e70ab0da293d4c3010815f643f161b7168 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Tue, 3 Nov 2015 14:34:15 -0700 Subject: [PATCH] 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 --- src/gallium/drivers/svga/svga_tgsi_vgpu10.c | 35 ++++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/gallium/drivers/svga/svga_tgsi_vgpu10.c b/src/gallium/drivers/svga/svga_tgsi_vgpu10.c index e70ee689c59..9b7ab16103f 100644 --- a/src/gallium/drivers/svga/svga_tgsi_vgpu10.c +++ b/src/gallium/drivers/svga/svga_tgsi_vgpu10.c @@ -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); } } -- 2.30.2