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:
committed by
Marge Bot
parent
efba865c4c
commit
f7b2165b19
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user