summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/svga
diff options
context:
space:
mode:
authorBrian Paul <[email protected]>2017-07-21 10:37:36 -0600
committerBrian Paul <[email protected]>2017-07-25 15:40:24 -0600
commit91735e2d4a25df0685e5f4c8f0a064f9d58c6b8e (patch)
treefe7bc1ef952fbc3067faa836287c27da54e7697d /src/gallium/drivers/svga
parent71d3b69b239c2e2eb8b154229c5defc013b7c7b5 (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/gallium/drivers/svga')
-rw-r--r--src/gallium/drivers/svga/svga_context.h1
-rw-r--r--src/gallium/drivers/svga/svga_pipe_blend.c1
-rw-r--r--src/gallium/drivers/svga/svga_shader.h1
-rw-r--r--src/gallium/drivers/svga/svga_state_fs.c3
-rw-r--r--src/gallium/drivers/svga/svga_tgsi_vgpu10.c52
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);
}