diff options
author | Brian Paul <[email protected]> | 2017-07-21 10:37:36 -0600 |
---|---|---|
committer | Brian Paul <[email protected]> | 2017-07-25 15:40:24 -0600 |
commit | 91735e2d4a25df0685e5f4c8f0a064f9d58c6b8e (patch) | |
tree | fe7bc1ef952fbc3067faa836287c27da54e7697d /src | |
parent | 71d3b69b239c2e2eb8b154229c5defc013b7c7b5 (diff) |
svga: implement MSAA alpha_to_one feature
The device doesn't directly support this feature so we implement it with
additional shader code which sets the color output(s) w component to
1.0 (or max_int or max_uint).
Fixes 16 Piglit ext_framebuffer_multisample/*alpha-to-one* tests.
v2: only support unorm/float buffers, not int/uint, per Roland.
Reviewed-by: Roland Scheidegger <[email protected]>
Reviewed-by: Charmaine Lee <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/drivers/svga/svga_context.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_pipe_blend.c | 1 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_shader.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_state_fs.c | 3 | ||||
-rw-r--r-- | src/gallium/drivers/svga/svga_tgsi_vgpu10.c | 52 |
5 files changed, 57 insertions, 1 deletions
diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h index d0306c036f3..0d695a64927 100644 --- a/src/gallium/drivers/svga/svga_context.h +++ b/src/gallium/drivers/svga/svga_context.h @@ -106,6 +106,7 @@ struct svga_blend_state { unsigned need_white_fragments:1; unsigned independent_blend_enable:1; unsigned alpha_to_coverage:1; + unsigned alpha_to_one:1; unsigned blend_color_alpha:1; /**< set blend color to alpha value */ /** Per-render target state */ diff --git a/src/gallium/drivers/svga/svga_pipe_blend.c b/src/gallium/drivers/svga/svga_pipe_blend.c index 408e175fea7..a29fbd3ac28 100644 --- a/src/gallium/drivers/svga/svga_pipe_blend.c +++ b/src/gallium/drivers/svga/svga_pipe_blend.c @@ -331,6 +331,7 @@ svga_create_blend_state(struct pipe_context *pipe, blend->independent_blend_enable = templ->independent_blend_enable; blend->alpha_to_coverage = templ->alpha_to_coverage; + blend->alpha_to_one = templ->alpha_to_one; if (svga_have_vgpu10(svga)) { define_blend_state_object(svga, blend); diff --git a/src/gallium/drivers/svga/svga_shader.h b/src/gallium/drivers/svga/svga_shader.h index a594d120f84..dc462c94af6 100644 --- a/src/gallium/drivers/svga/svga_shader.h +++ b/src/gallium/drivers/svga/svga_shader.h @@ -77,6 +77,7 @@ struct svga_compile_key unsigned light_twoside:1; unsigned front_ccw:1; unsigned white_fragments:1; + unsigned alpha_to_one:1; unsigned flatshade:1; unsigned pstipple:1; unsigned alpha_func:4; /**< SVGA3D_CMP_x */ diff --git a/src/gallium/drivers/svga/svga_state_fs.c b/src/gallium/drivers/svga/svga_state_fs.c index bf452163049..5e568993fed 100644 --- a/src/gallium/drivers/svga/svga_state_fs.c +++ b/src/gallium/drivers/svga/svga_state_fs.c @@ -25,6 +25,7 @@ #include "util/u_inlines.h" #include "pipe/p_defines.h" +#include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" #include "util/u_bitmask.h" @@ -234,6 +235,8 @@ make_fs_key(const struct svga_context *svga, */ key->fs.white_fragments = svga->curr.blend->need_white_fragments; + key->fs.alpha_to_one = svga->curr.blend->alpha_to_one; + #ifdef DEBUG /* * We expect a consistent set of samplers and sampler views. diff --git a/src/gallium/drivers/svga/svga_tgsi_vgpu10.c b/src/gallium/drivers/svga/svga_tgsi_vgpu10.c index 9f5cd4b285b..d7ec48eb8ac 100644 --- a/src/gallium/drivers/svga/svga_tgsi_vgpu10.c +++ b/src/gallium/drivers/svga/svga_tgsi_vgpu10.c @@ -167,8 +167,8 @@ struct svga_shader_emitter_v10 /* For fragment shaders only */ struct { - /* apha test */ unsigned color_out_index[PIPE_MAX_COLOR_BUFS]; /**< the real color output regs */ + unsigned num_color_outputs; unsigned color_tmp_index; /**< fake/temp color output reg */ unsigned alpha_ref_index; /**< immediate constant for alpha ref */ @@ -2499,6 +2499,9 @@ emit_output_declarations(struct svga_shader_emitter_v10 *emit) emit->fs.color_out_index[semantic_index] = index; + emit->fs.num_color_outputs = MAX2(emit->fs.num_color_outputs, + index + 1); + /* The semantic index is the shader's color output/buffer index */ emit_output_declaration(emit, VGPU10_OPCODE_DCL_OUTPUT, semantic_index, @@ -2521,6 +2524,9 @@ emit_output_declarations(struct svga_shader_emitter_v10 *emit) VGPU10_OPERAND_4_COMPONENT_MASK_ALL); emit->info.output_semantic_index[idx] = j; } + + emit->fs.num_color_outputs = + emit->key.fs.write_color0_to_n_cbufs; } } else { @@ -6378,6 +6384,47 @@ emit_pre_helpers(struct svga_shader_emitter_v10 *emit) /** + * The device has no direct support for the pipe_blend_state::alpha_to_one + * option so we implement it here with shader code. + * + * Note that this is kind of pointless, actually. Here we're clobbering + * the alpha value with 1.0. So if alpha-to-coverage is enabled, we'll wind + * up with 100% coverage. That's almost certainly not what the user wants. + * The work-around is to add extra shader code to compute coverage from alpha + * and write it to the coverage output register (if the user's shader doesn't + * do so already). We'll probably do that in the future. + */ +static void +emit_alpha_to_one_instructions(struct svga_shader_emitter_v10 *emit, + unsigned fs_color_tmp_index) +{ + struct tgsi_full_src_register one = make_immediate_reg_float(emit, 1.0f); + unsigned i; + + /* Note: it's not 100% clear from the spec if we're supposed to clobber + * the alpha for all render targets. But that's what NVIDIA does and + * that's what Piglit tests. + */ + for (i = 0; i < emit->fs.num_color_outputs; i++) { + struct tgsi_full_dst_register color_dst; + + if (fs_color_tmp_index != INVALID_INDEX && i == 0) { + /* write to the temp color register */ + color_dst = make_dst_temp_reg(fs_color_tmp_index); + } + else { + /* write directly to the color[i] output */ + color_dst = make_dst_output_reg(emit->fs.color_out_index[i]); + } + + color_dst = writemask_dst(&color_dst, TGSI_WRITEMASK_W); + + emit_instruction_op1(emit, VGPU10_OPCODE_MOV, &color_dst, &one, FALSE); + } +} + + +/** * Emit alpha test code. This compares TEMP[fs_color_tmp_index].w * against the alpha reference value and discards the fragment if the * comparison fails. @@ -6494,6 +6541,9 @@ emit_post_helpers(struct svga_shader_emitter_v10 *emit) */ emit->fs.color_tmp_index = INVALID_INDEX; + if (emit->key.fs.alpha_to_one) { + emit_alpha_to_one_instructions(emit, fs_color_tmp_index); + } if (emit->key.fs.alpha_func != SVGA3D_CMP_ALWAYS) { emit_alpha_test_instructions(emit, fs_color_tmp_index); } |