Mesa (master): freedreno/a6xx: add support for dual-source blending
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Thu Nov 26 17:36:48 UTC 2020
Module: Mesa
Branch: master
Commit: f7b2165b19c29f8494ac3eb5a40ff21c8d7e1fe8
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=f7b2165b19c29f8494ac3eb5a40ff21c8d7e1fe8
Author: Danylo Piliaiev <dpiliaiev at igalia.com>
Date: Thu Nov 19 11:27:33 2020 +0200
freedreno/a6xx: add support for dual-source blending
Signed-off-by: Danylo Piliaiev <dpiliaiev at igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7708>
---
src/gallium/drivers/freedreno/a6xx/fd6_blend.c | 8 ++++++-
src/gallium/drivers/freedreno/a6xx/fd6_blend.h | 2 ++
src/gallium/drivers/freedreno/a6xx/fd6_emit.c | 28 +++++++++++++++++++++---
src/gallium/drivers/freedreno/a6xx/fd6_gmem.c | 23 -------------------
src/gallium/drivers/freedreno/a6xx/fd6_program.c | 5 +++++
src/gallium/drivers/freedreno/freedreno_screen.c | 2 +-
6 files changed, 40 insertions(+), 28 deletions(-)
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_blend.c b/src/gallium/drivers/freedreno/a6xx/fd6_blend.c
index fe63be97fd5..b645b884ab6 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_blend.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_blend.c
@@ -27,6 +27,7 @@
#include "pipe/p_state.h"
#include "util/u_blend.h"
+#include "util/u_dual_blend.h"
#include "util/u_string.h"
#include "util/u_memory.h"
@@ -127,6 +128,7 @@ __fd6_setup_blend_variant(struct fd6_blend_stateobj *blend, unsigned sample_mask
.unk8 = true,
.alpha_to_coverage = cso->alpha_to_coverage,
.enabled = !!mrt_blend,
+ .dual_color_in_enable = blend->use_dual_src_blend,
));
OUT_REG(ring, A6XX_RB_BLEND_CNTL(
@@ -134,7 +136,8 @@ __fd6_setup_blend_variant(struct fd6_blend_stateobj *blend, unsigned sample_mask
.alpha_to_coverage = cso->alpha_to_coverage,
.alpha_to_one = cso->alpha_to_one,
.independent_blend = cso->independent_blend_enable,
- .sample_mask = sample_mask
+ .sample_mask = sample_mask,
+ .dual_color_in_enable = blend->use_dual_src_blend,
));
so->sample_mask = sample_mask;
@@ -161,6 +164,9 @@ fd6_blend_state_create(struct pipe_context *pctx,
so->reads_dest |= util_logicop_reads_dest(cso->logicop_func);
}
+ so->use_dual_src_blend =
+ cso->rt[0].blend_enable && util_blend_state_is_dual(cso, 0);
+
unsigned nr = cso->independent_blend_enable ? cso->max_rt : 0;
for (unsigned i = 0; i <= nr; i++) {
const struct pipe_rt_blend_state *rt = &cso->rt[i];
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_blend.h b/src/gallium/drivers/freedreno/a6xx/fd6_blend.h
index ef7dde8cf65..0878cf47c75 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_blend.h
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_blend.h
@@ -47,6 +47,8 @@ struct fd6_blend_variant {
struct fd6_blend_stateobj {
struct pipe_blend_state base;
+ bool use_dual_src_blend;
+
struct fd_context *ctx;
bool reads_dest;
struct util_dynarray variants;
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
index 83afd1c6575..ca21d292da2 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
@@ -955,24 +955,46 @@ fd6_emit_state(struct fd_ringbuffer *ring, struct fd6_emit *emit)
FD6_GROUP_RASTERIZER, ENABLE_ALL);
}
- if (dirty & (FD_DIRTY_FRAMEBUFFER | FD_DIRTY_RASTERIZER_DISCARD | FD_DIRTY_PROG)) {
+ if (dirty & (FD_DIRTY_FRAMEBUFFER | FD_DIRTY_RASTERIZER_DISCARD |
+ FD_DIRTY_PROG | FD_DIRTY_BLEND_DUAL)) {
struct fd_ringbuffer *ring = fd_submit_new_ringbuffer(
- emit->ctx->batch->submit, 5 * 4, FD_RINGBUFFER_STREAMING);
+ emit->ctx->batch->submit, 9 * 4, FD_RINGBUFFER_STREAMING);
unsigned nr = pfb->nr_cbufs;
if (ctx->rasterizer->rasterizer_discard)
nr = 0;
+ struct fd6_blend_stateobj *blend = fd6_blend_stateobj(ctx->blend);
+
+ if (blend->use_dual_src_blend)
+ nr++;
+
OUT_PKT4(ring, REG_A6XX_RB_FS_OUTPUT_CNTL0, 2);
OUT_RING(ring, COND(fs->writes_pos, A6XX_RB_FS_OUTPUT_CNTL0_FRAG_WRITES_Z) |
COND(fs->writes_smask && pfb->samples > 1,
- A6XX_RB_FS_OUTPUT_CNTL0_FRAG_WRITES_SAMPMASK));
+ A6XX_RB_FS_OUTPUT_CNTL0_FRAG_WRITES_SAMPMASK) |
+ COND(blend->use_dual_src_blend,
+ A6XX_RB_FS_OUTPUT_CNTL0_DUAL_COLOR_IN_ENABLE));
OUT_RING(ring, A6XX_RB_FS_OUTPUT_CNTL1_MRT(nr));
OUT_PKT4(ring, REG_A6XX_SP_FS_OUTPUT_CNTL1, 1);
OUT_RING(ring, A6XX_SP_FS_OUTPUT_CNTL1_MRT(nr));
+ unsigned mrt_components = 0;
+ for (unsigned i = 0; i < pfb->nr_cbufs; i++) {
+ if (!pfb->cbufs[i])
+ continue;
+ mrt_components |= 0xf << (i * 4);
+ }
+
+ /* dual source blending has an extra fs output in the 2nd slot */
+ if (blend->use_dual_src_blend)
+ mrt_components |= 0xf << 4;
+
+ OUT_REG(ring, A6XX_SP_FS_RENDER_COMPONENTS(.dword = mrt_components));
+ OUT_REG(ring, A6XX_RB_RENDER_COMPONENTS(.dword = mrt_components));
+
fd6_emit_take_group(emit, ring, FD6_GROUP_PROG_FB_RAST, ENABLE_DRAW);
}
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
index 5aac4d5438b..0c1348ca4b5 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
@@ -73,7 +73,6 @@ static void
emit_mrt(struct fd_ringbuffer *ring, struct pipe_framebuffer_state *pfb,
const struct fd_gmem_stateobj *gmem)
{
- unsigned char mrt_comp[A6XX_MAX_RENDER_TARGETS] = {0};
unsigned srgb_cntl = 0;
unsigned i;
@@ -92,8 +91,6 @@ emit_mrt(struct fd_ringbuffer *ring, struct pipe_framebuffer_state *pfb,
if (!pfb->cbufs[i])
continue;
- mrt_comp[i] = 0xf;
-
struct pipe_surface *psurf = pfb->cbufs[i];
enum pipe_format pformat = psurf->format;
rsc = fd_resource(psurf->texture);
@@ -142,26 +139,6 @@ emit_mrt(struct fd_ringbuffer *ring, struct pipe_framebuffer_state *pfb,
OUT_REG(ring, A6XX_RB_SRGB_CNTL(.dword = srgb_cntl));
OUT_REG(ring, A6XX_SP_SRGB_CNTL(.dword = srgb_cntl));
- OUT_REG(ring, A6XX_RB_RENDER_COMPONENTS(
- .rt0 = mrt_comp[0],
- .rt1 = mrt_comp[1],
- .rt2 = mrt_comp[2],
- .rt3 = mrt_comp[3],
- .rt4 = mrt_comp[4],
- .rt5 = mrt_comp[5],
- .rt6 = mrt_comp[6],
- .rt7 = mrt_comp[7]));
-
- OUT_REG(ring, A6XX_SP_FS_RENDER_COMPONENTS(
- .rt0 = mrt_comp[0],
- .rt1 = mrt_comp[1],
- .rt2 = mrt_comp[2],
- .rt3 = mrt_comp[3],
- .rt4 = mrt_comp[4],
- .rt5 = mrt_comp[5],
- .rt6 = mrt_comp[6],
- .rt7 = mrt_comp[7]));
-
OUT_REG(ring, A6XX_GRAS_MAX_LAYER_INDEX(max_layer_index));
}
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_program.c b/src/gallium/drivers/freedreno/a6xx/fd6_program.c
index 6d7f7e45232..512a016a98d 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_program.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_program.c
@@ -483,9 +483,14 @@ setup_stateobj(struct fd_ringbuffer *ring, struct fd_context *ctx,
OUT_PKT4(ring, REG_A6XX_SP_MODE_CONTROL, 1);
OUT_RING(ring, A6XX_SP_MODE_CONTROL_CONSTANT_DEMOTION_ENABLE | 4);
+ bool fs_has_dual_src_color = !binning_pass &&
+ fs->shader->nir->info.fs.color_is_dual_source;
+
OUT_PKT4(ring, REG_A6XX_SP_FS_OUTPUT_CNTL0, 1);
OUT_RING(ring, A6XX_SP_FS_OUTPUT_CNTL0_DEPTH_REGID(posz_regid) |
A6XX_SP_FS_OUTPUT_CNTL0_SAMPMASK_REGID(smask_regid) |
+ COND(fs_has_dual_src_color,
+ A6XX_SP_FS_OUTPUT_CNTL0_DUAL_COLOR_IN_ENABLE) |
0xfc000000);
enum a3xx_threadsize vssz;
diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c
index 705355fd373..b437f0fb853 100644
--- a/src/gallium/drivers/freedreno/freedreno_screen.c
+++ b/src/gallium/drivers/freedreno/freedreno_screen.c
@@ -437,7 +437,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_MAX_RENDER_TARGETS:
return screen->max_rts;
case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
- return is_a3xx(screen) ? 1 : 0;
+ return (is_a3xx(screen) || is_a6xx(screen)) ? 1 : 0;
/* Queries. */
case PIPE_CAP_OCCLUSION_QUERY:
More information about the mesa-commit
mailing list