freedreno/a6xx: add support for dual-source blending

Signed-off-by: Danylo Piliaiev <dpiliaiev@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7708>
This commit is contained in:
Danylo Piliaiev
2020-11-19 11:27:33 +02:00
committed by Marge Bot
parent efba865c4c
commit f7b2165b19
6 changed files with 40 additions and 28 deletions
@@ -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];
@@ -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;
+25 -3
View File
@@ -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);
}
@@ -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));
}
@@ -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;
@@ -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: