lima: implement dual source blend
It was a bit trickier to RE, since blob doesn't expose this functionality at all, however we had a clue from the very beginning: lima_blend_factor is 3 bits, i.e. 8 values, but only 5 of them were used, it just waited till someone tried what 3 unused values do. Interestingly enough, it turns out "5" works just as "0" (which is PIPE_BLENDFACTOR_*SRC_*), but only if output register for gl_FragColor is $0, So it looks suspiciously similar with PIPE_BLENDFACTOR_*SRC1_* behavior, and looks like secondary output is taken from $0. Since output regs for all other outputs are configured via RSW, there must be a field in RSW for output register for secondary color, it's likely 4 bits and it's currently set to 0 for reg $0. Then it was just a matter of brute-forcing various consecutive 4 bits in RSW - and indeed, setting top 4 bits of rsw->aux0 to the index of gl_FragColor output register fixes blending tests when we use "5" blend factor instead of "0". So it must be a register number for gl_SecondaryFragColor. Unlike gl_FragColor, the field is only repeated once in RSW. Wire it up in compiler, and piglit arb_blend_func_extended now passes. Reviewed-by: Andreas Baierl <ichgeh@imkreisrum.de> Reviewed-by: Erico Nunes <nunes.erico@gmail.com> Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13873>
This commit is contained in:

committed by
Marge Bot

parent
65a78b2252
commit
d1d3ebb48c
@@ -99,7 +99,7 @@ GL 3.2, GLSL 1.50 --- all DONE: freedreno, i965, nv50, nvc0, r600, radeonsi, llv
|
||||
|
||||
GL 3.3, GLSL 3.30 --- all DONE: freedreno, i965, nv50, nvc0, r600, radeonsi, llvmpipe, softpipe, virgl, zink, d3d12
|
||||
|
||||
GL_ARB_blend_func_extended DONE (freedreno/a3xx, freedreno/a6xx, swr, panfrost)
|
||||
GL_ARB_blend_func_extended DONE (freedreno/a3xx, freedreno/a6xx, swr, panfrost, lima)
|
||||
GL_ARB_explicit_attrib_location DONE (all drivers that support GLSL)
|
||||
GL_ARB_occlusion_query2 DONE (swr, v3d, vc4, panfrost, lima)
|
||||
GL_ARB_sampler_objects DONE (all drivers)
|
||||
|
@@ -351,7 +351,8 @@ static bool ppir_emit_intrinsic(ppir_block *block, nir_instr *ni)
|
||||
nir_io_semantics io = nir_intrinsic_io_semantics(instr);
|
||||
unsigned offset = nir_src_as_uint(instr->src[1]);
|
||||
unsigned slot = io.location + offset;
|
||||
ppir_output_type out_type = ppir_nir_output_to_ppir(slot);
|
||||
ppir_output_type out_type = ppir_nir_output_to_ppir(slot,
|
||||
block->comp->dual_source_blend ? io.dual_source_blend_index : 0);
|
||||
if (out_type == ppir_output_invalid) {
|
||||
ppir_debug("Unsupported output type: %d\n", slot);
|
||||
return false;
|
||||
@@ -916,6 +917,7 @@ bool ppir_compile_nir(struct lima_fs_compiled_shader *prog, struct nir_shader *n
|
||||
|
||||
comp->ra = ra;
|
||||
comp->uses_discard = nir->info.fs.uses_discard;
|
||||
comp->dual_source_blend = nir->info.fs.color_is_dual_source;
|
||||
|
||||
/* 1st pass: create ppir blocks */
|
||||
nir_foreach_function(function, nir) {
|
||||
|
@@ -180,7 +180,8 @@ typedef enum {
|
||||
} ppir_pipeline;
|
||||
|
||||
typedef enum {
|
||||
ppir_output_color,
|
||||
ppir_output_color0,
|
||||
ppir_output_color1,
|
||||
ppir_output_depth,
|
||||
ppir_output_num,
|
||||
ppir_output_invalid = -1,
|
||||
@@ -189,8 +190,10 @@ typedef enum {
|
||||
static inline const char *ppir_output_type_to_str(ppir_output_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case ppir_output_color:
|
||||
return "OUTPUT_COLOR";
|
||||
case ppir_output_color0:
|
||||
return "OUTPUT_COLOR0";
|
||||
case ppir_output_color1:
|
||||
return "OUTPUT_COLOR1";
|
||||
case ppir_output_depth:
|
||||
return "OUTPUT_DEPTH";
|
||||
default:
|
||||
@@ -198,12 +201,12 @@ static inline const char *ppir_output_type_to_str(ppir_output_type type)
|
||||
}
|
||||
}
|
||||
|
||||
static inline ppir_output_type ppir_nir_output_to_ppir(gl_frag_result res)
|
||||
static inline ppir_output_type ppir_nir_output_to_ppir(gl_frag_result res, int dual_src_index)
|
||||
{
|
||||
switch (res) {
|
||||
case FRAG_RESULT_COLOR:
|
||||
case FRAG_RESULT_DATA0:
|
||||
return ppir_output_color;
|
||||
return ppir_output_color0 + dual_src_index;
|
||||
case FRAG_RESULT_DEPTH:
|
||||
return ppir_output_depth;
|
||||
default:
|
||||
@@ -417,6 +420,7 @@ typedef struct ppir_compiler {
|
||||
struct ra_regs *ra;
|
||||
struct lima_fs_compiled_shader *prog;
|
||||
bool uses_discard;
|
||||
bool dual_source_blend;
|
||||
|
||||
/* for scheduler */
|
||||
int sched_instr_base;
|
||||
|
@@ -617,7 +617,8 @@ bool ppir_regalloc_prog(ppir_compiler *comp)
|
||||
|
||||
/* No registers? Probably shader consists of discard instruction */
|
||||
if (list_is_empty(&comp->reg_list)) {
|
||||
comp->prog->state.frag_color_reg = 0;
|
||||
comp->prog->state.frag_color0_reg = 0;
|
||||
comp->prog->state.frag_color1_reg = -1;
|
||||
comp->prog->state.frag_depth_reg = -1;
|
||||
return true;
|
||||
}
|
||||
@@ -628,8 +629,10 @@ bool ppir_regalloc_prog(ppir_compiler *comp)
|
||||
if (!spilled)
|
||||
return false;
|
||||
|
||||
comp->prog->state.frag_color_reg =
|
||||
comp->out_type_to_reg[ppir_output_color];
|
||||
comp->prog->state.frag_color0_reg =
|
||||
comp->out_type_to_reg[ppir_output_color0];
|
||||
comp->prog->state.frag_color1_reg =
|
||||
comp->out_type_to_reg[ppir_output_color1];
|
||||
comp->prog->state.frag_depth_reg =
|
||||
comp->out_type_to_reg[ppir_output_depth];
|
||||
|
||||
|
@@ -49,7 +49,8 @@ struct lima_fs_compiled_shader {
|
||||
struct {
|
||||
int shader_size;
|
||||
int stack_size;
|
||||
int frag_color_reg;
|
||||
int frag_color0_reg;
|
||||
int frag_color1_reg;
|
||||
int frag_depth_reg;
|
||||
bool uses_discard;
|
||||
} state;
|
||||
|
@@ -449,107 +449,56 @@ lima_blend_func(enum pipe_blend_func pipe)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
lima_blend_factor_has_alpha(enum pipe_blendfactor pipe)
|
||||
{
|
||||
/* Bit 4 is set if the blendfactor uses alpha */
|
||||
switch (pipe) {
|
||||
case PIPE_BLENDFACTOR_SRC_ALPHA:
|
||||
case PIPE_BLENDFACTOR_DST_ALPHA:
|
||||
case PIPE_BLENDFACTOR_CONST_ALPHA:
|
||||
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
|
||||
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
|
||||
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
|
||||
return 1;
|
||||
|
||||
case PIPE_BLENDFACTOR_SRC_COLOR:
|
||||
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
|
||||
case PIPE_BLENDFACTOR_DST_COLOR:
|
||||
case PIPE_BLENDFACTOR_INV_DST_COLOR:
|
||||
case PIPE_BLENDFACTOR_CONST_COLOR:
|
||||
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
|
||||
case PIPE_BLENDFACTOR_ZERO:
|
||||
case PIPE_BLENDFACTOR_ONE:
|
||||
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
|
||||
return 0;
|
||||
|
||||
case PIPE_BLENDFACTOR_SRC1_COLOR:
|
||||
case PIPE_BLENDFACTOR_SRC1_ALPHA:
|
||||
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
|
||||
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
|
||||
return -1; /* not supported */
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
lima_blend_factor_is_inv(enum pipe_blendfactor pipe)
|
||||
{
|
||||
/* Bit 3 is set if the blendfactor type is inverted */
|
||||
switch (pipe) {
|
||||
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
|
||||
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
|
||||
case PIPE_BLENDFACTOR_INV_DST_COLOR:
|
||||
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
|
||||
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
|
||||
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
|
||||
case PIPE_BLENDFACTOR_ONE:
|
||||
return 1;
|
||||
|
||||
case PIPE_BLENDFACTOR_SRC_COLOR:
|
||||
case PIPE_BLENDFACTOR_SRC_ALPHA:
|
||||
case PIPE_BLENDFACTOR_DST_COLOR:
|
||||
case PIPE_BLENDFACTOR_DST_ALPHA:
|
||||
case PIPE_BLENDFACTOR_CONST_COLOR:
|
||||
case PIPE_BLENDFACTOR_CONST_ALPHA:
|
||||
case PIPE_BLENDFACTOR_ZERO:
|
||||
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
|
||||
return 0;
|
||||
|
||||
case PIPE_BLENDFACTOR_SRC1_COLOR:
|
||||
case PIPE_BLENDFACTOR_SRC1_ALPHA:
|
||||
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
|
||||
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
|
||||
return -1; /* not supported */
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
lima_blend_factor(enum pipe_blendfactor pipe)
|
||||
{
|
||||
/* Bits 0-2 indicate the blendfactor type */
|
||||
/* Bits 0-2 indicate the blendfactor type,
|
||||
* Bit 3 is set if blendfactor is inverted
|
||||
* Bit 4 is set if blendfactor has alpha */
|
||||
switch (pipe) {
|
||||
case PIPE_BLENDFACTOR_SRC_COLOR:
|
||||
return 0 << 4 | 0 << 3 | 0;
|
||||
case PIPE_BLENDFACTOR_SRC_ALPHA:
|
||||
return 1 << 4 | 0 << 3 | 0;
|
||||
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
|
||||
return 0 << 4 | 1 << 3 | 0;
|
||||
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
|
||||
return 0;
|
||||
return 1 << 4 | 1 << 3 | 0;
|
||||
|
||||
case PIPE_BLENDFACTOR_DST_COLOR:
|
||||
return 0 << 4 | 0 << 3 | 1;
|
||||
case PIPE_BLENDFACTOR_DST_ALPHA:
|
||||
return 1 << 4 | 0 << 3 | 1;
|
||||
case PIPE_BLENDFACTOR_INV_DST_COLOR:
|
||||
return 0 << 4 | 1 << 3 | 1;
|
||||
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
|
||||
return 1;
|
||||
return 1 << 4 | 1 << 3 | 1;
|
||||
|
||||
case PIPE_BLENDFACTOR_CONST_COLOR:
|
||||
return 0 << 4 | 0 << 3 | 2;
|
||||
case PIPE_BLENDFACTOR_CONST_ALPHA:
|
||||
return 1 << 4 | 0 << 3 | 2;
|
||||
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
|
||||
return 0 << 4 | 1 << 3 | 2;
|
||||
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
|
||||
return 2;
|
||||
return 1 << 4 | 1 << 3 | 2;
|
||||
|
||||
case PIPE_BLENDFACTOR_ZERO:
|
||||
return 0 << 4 | 0 << 3 | 3;
|
||||
case PIPE_BLENDFACTOR_ONE:
|
||||
return 3;
|
||||
return 0 << 4 | 1 << 3 | 3;
|
||||
|
||||
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
|
||||
return 4;
|
||||
return 0 << 4 | 0 << 3 | 4;
|
||||
|
||||
case PIPE_BLENDFACTOR_SRC1_COLOR:
|
||||
return 0 << 4 | 0 << 3 | 5;
|
||||
case PIPE_BLENDFACTOR_SRC1_ALPHA:
|
||||
return 1 << 4 | 0 << 3 | 5;
|
||||
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
|
||||
return 0 << 4 | 1 << 3 | 5;
|
||||
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
|
||||
return -1; /* not supported */
|
||||
return 1 << 4 | 1 << 3 | 5;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -567,20 +516,11 @@ lima_calculate_alpha_blend(enum pipe_blend_func rgb_func, enum pipe_blend_func a
|
||||
|
||||
return lima_blend_func(rgb_func) |
|
||||
(lima_blend_func(alpha_func) << 3) |
|
||||
|
||||
(lima_blend_factor(rgb_src_factor) << 6) |
|
||||
(lima_blend_factor_is_inv(rgb_src_factor) << 9) |
|
||||
(lima_blend_factor_has_alpha(rgb_src_factor) << 10) |
|
||||
|
||||
(lima_blend_factor(rgb_dst_factor) << 11) |
|
||||
(lima_blend_factor_is_inv(rgb_dst_factor) << 14) |
|
||||
(lima_blend_factor_has_alpha(rgb_dst_factor) << 15) |
|
||||
|
||||
(lima_blend_factor(alpha_src_factor) << 16) |
|
||||
(lima_blend_factor_is_inv(alpha_src_factor) << 19) |
|
||||
|
||||
(lima_blend_factor(alpha_dst_factor) << 20) |
|
||||
(lima_blend_factor_is_inv(alpha_dst_factor) << 23) |
|
||||
/* alpha_src and alpha_dst are 4 bit, so need to mask 5th bit */
|
||||
((lima_blend_factor(alpha_src_factor) & 0xf) << 16) |
|
||||
((lima_blend_factor(alpha_dst_factor) & 0xf) << 20) |
|
||||
0x0C000000; /* need to check if this is GLESv1 glAlphaFunc */
|
||||
}
|
||||
|
||||
@@ -736,10 +676,10 @@ lima_pack_render_state(struct lima_context *ctx, const struct pipe_draw_info *in
|
||||
render->multi_sample |= 0x68;
|
||||
|
||||
/* Set gl_FragColor register, need to specify it 4 times */
|
||||
render->multi_sample |= (fs->state.frag_color_reg << 28) |
|
||||
(fs->state.frag_color_reg << 24) |
|
||||
(fs->state.frag_color_reg << 20) |
|
||||
(fs->state.frag_color_reg << 16);
|
||||
render->multi_sample |= (fs->state.frag_color0_reg << 28) |
|
||||
(fs->state.frag_color0_reg << 24) |
|
||||
(fs->state.frag_color0_reg << 20) |
|
||||
(fs->state.frag_color0_reg << 16);
|
||||
|
||||
/* alpha test */
|
||||
if (ctx->zsa->base.alpha_enabled) {
|
||||
@@ -807,6 +747,10 @@ lima_pack_render_state(struct lima_context *ctx, const struct pipe_draw_info *in
|
||||
render->aux1 |= 0x10000;
|
||||
}
|
||||
|
||||
/* Set secondary output color */
|
||||
if (fs->state.frag_color1_reg != -1)
|
||||
render->aux0 |= (fs->state.frag_color1_reg << 28);
|
||||
|
||||
if (ctx->vs->state.num_varyings) {
|
||||
render->varying_types = 0x00000000;
|
||||
render->varyings_address = ctx->gp_output->va +
|
||||
|
@@ -674,6 +674,11 @@ parse_rsw(FILE *fp, uint32_t *value, int i, uint32_t *helper)
|
||||
|
||||
if ((*value & 0x00002000) == 0x00002000) /* bit 13 unknown */
|
||||
fprintf(fp, ", bit 13 set");
|
||||
|
||||
fprintf(fp, " */\n");
|
||||
fprintf(fp, "\n\t\t\t\t\t\t/* %s(3):", render_state_infos[i].info);
|
||||
fprintf(fp, " register for gl_SecondaryFragColor: $%d",
|
||||
(*value & 0xf0000000) >> 28);
|
||||
fprintf(fp, " */\n");
|
||||
break;
|
||||
case 14: /* AUX1 */
|
||||
|
@@ -61,7 +61,7 @@ static const char *PIPE_BLENDFACTOR_STRING[] = {
|
||||
"CONST_COLOR", /* 2 */
|
||||
"ZERO", /* 3 */
|
||||
"UNKNOWN_4", /* 4 */
|
||||
"UNKNOWN_5", /* 5 */
|
||||
"SRC2_COLOR", /* 5 */
|
||||
"UNKNOWN_6", /* 6 */
|
||||
"SRC_ALPHA_SAT", /* 7 */
|
||||
"INV_SRC_COLOR", /* 8 */
|
||||
@@ -69,7 +69,7 @@ static const char *PIPE_BLENDFACTOR_STRING[] = {
|
||||
"INV_CONST_COLOR", /* 10 */
|
||||
"ONE", /* 11 */
|
||||
"UNKNOWN_12", /* 12 */
|
||||
"UNKNOWN_13", /* 13 */
|
||||
"INV_SRC2_COLOR", /* 13 */
|
||||
"UNKNOWN_14", /* 14 */
|
||||
"UNKNOWN_15", /* 15 */
|
||||
"SRC_ALPHA", /* 16 */
|
||||
@@ -77,13 +77,15 @@ static const char *PIPE_BLENDFACTOR_STRING[] = {
|
||||
"CONST_ALPHA", /* 18 */
|
||||
"UNKNOWN_19", /* 19 */
|
||||
"UNKNOWN_20", /* 20 */
|
||||
"UNKNOWN_21", /* 21 */
|
||||
"SRC2_ALPHA", /* 21 */
|
||||
"UNKNOWN_22", /* 22 */
|
||||
"UNKNOWN_23", /* 23 */
|
||||
"INV_SRC_ALPHA", /* 24 */
|
||||
"INV_DST_ALPHA", /* 25 */
|
||||
"INV_CONST_ALPHA", /* 26 */
|
||||
|
||||
"UNKNOWN_27", /* 27 */
|
||||
"UNKNOWN_28", /* 28 */
|
||||
"INV_SRC2_ALPHA", /* 29 */
|
||||
};
|
||||
|
||||
static const char *LIMA_WRAP_MODE_STRING[] = {
|
||||
|
@@ -168,6 +168,9 @@ lima_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
|
||||
case PIPE_CAP_PREFER_POT_ALIGNED_VARYINGS:
|
||||
return 1;
|
||||
|
||||
case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return u_pipe_screen_get_param_defaults(pscreen, param);
|
||||
}
|
||||
|
Reference in New Issue
Block a user