mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-09 02:28:10 +02:00
v3d: Implement dual source blending
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33942>
This commit is contained in:
parent
42154029fc
commit
a72be0f720
8 changed files with 84 additions and 7 deletions
|
|
@ -99,7 +99,7 @@ GL 3.2, GLSL 1.50 --- all DONE: freedreno, nv50, nvc0, r600, radeonsi, llvmpipe,
|
|||
|
||||
GL 3.3, GLSL 3.30 --- all DONE: freedreno, nv50, nvc0, r600, radeonsi, llvmpipe, softpipe, virgl, zink, d3d12, iris, crocus/gen6+, asahi
|
||||
|
||||
GL_ARB_blend_func_extended DONE (freedreno/a3xx, freedreno/a6xx, panfrost, lima)
|
||||
GL_ARB_blend_func_extended DONE (freedreno/a3xx, freedreno/a6xx, v3d, panfrost, lima)
|
||||
GL_ARB_explicit_attrib_location DONE (all drivers that support GLSL)
|
||||
GL_ARB_occlusion_query2 DONE (v3d, panfrost)
|
||||
GL_ARB_sampler_objects DONE (all drivers)
|
||||
|
|
|
|||
|
|
@ -4,3 +4,4 @@ pushDescriptor on panvk
|
|||
VK_EXT_vertex_input_dynamic_state on panvk
|
||||
VK_EXT_vertex_attribute_divisor on panvk
|
||||
supportsNonZeroFirstInstance on panvk
|
||||
GL_ARB_blend_func_extended on v3d
|
||||
|
|
|
|||
|
|
@ -712,6 +712,8 @@ struct v3d_depth_stencil_alpha_state {
|
|||
struct v3d_blend_state {
|
||||
struct pipe_blend_state base;
|
||||
|
||||
bool use_software;
|
||||
|
||||
/* Per-RT mask of whether blending is enabled. */
|
||||
uint8_t blend_enables;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -367,6 +367,16 @@ v3d_uncompiled_shader_create(struct pipe_context *pctx,
|
|||
if (s->info.stage == MESA_SHADER_KERNEL)
|
||||
s->info.stage = MESA_SHADER_COMPUTE;
|
||||
|
||||
if (s->info.stage == MESA_SHADER_FRAGMENT &&
|
||||
s->info.outputs_written & BITFIELD_BIT(FRAG_RESULT_COLOR)) {
|
||||
/* We only support one attachment when doing dual source blending. */
|
||||
if (s->info.fs.color_is_dual_source)
|
||||
NIR_PASS(_, s, nir_lower_fragcolor, 1);
|
||||
else if (V3D_DBG(SOFT_BLEND))
|
||||
NIR_PASS(_, s, nir_lower_fragcolor,
|
||||
V3D_MAX_DRAW_BUFFERS);
|
||||
}
|
||||
|
||||
if (s->info.stage != MESA_SHADER_VERTEX &&
|
||||
s->info.stage != MESA_SHADER_GEOMETRY) {
|
||||
NIR_PASS(_, s, nir_lower_io,
|
||||
|
|
@ -680,6 +690,8 @@ v3d_update_compiled_fs(struct v3d_context *v3d, uint8_t prim_mode)
|
|||
!v3d->zsa->base.depth_writemask) &&
|
||||
!(v3d->active_queries && v3d->current_oq);
|
||||
|
||||
key->software_blend = v3d->blend->use_software;
|
||||
|
||||
for (int i = 0; i < v3d->framebuffer.nr_cbufs; i++) {
|
||||
struct pipe_surface *cbuf = v3d->framebuffer.cbufs[i];
|
||||
if (!cbuf)
|
||||
|
|
@ -696,7 +708,8 @@ v3d_update_compiled_fs(struct v3d_context *v3d, uint8_t prim_mode)
|
|||
* swizzle.
|
||||
*/
|
||||
if (key->logicop_func != PIPE_LOGICOP_COPY ||
|
||||
s->info.fs.uses_fbfetch_output) {
|
||||
s->info.fs.uses_fbfetch_output ||
|
||||
key->software_blend) {
|
||||
|
||||
key->color_fmt[i].format = cbuf->format;
|
||||
memcpy(key->color_fmt[i].swizzle,
|
||||
|
|
@ -705,6 +718,26 @@ v3d_update_compiled_fs(struct v3d_context *v3d, uint8_t prim_mode)
|
|||
sizeof(key->color_fmt[i].swizzle));
|
||||
}
|
||||
|
||||
if (key->software_blend) {
|
||||
struct pipe_rt_blend_state *blend = &v3d->blend->base.rt[i];
|
||||
|
||||
if (blend->blend_enable) {
|
||||
key->blend[i].rgb_func = blend->rgb_func;
|
||||
key->blend[i].rgb_src_factor = blend->rgb_src_factor;
|
||||
key->blend[i].rgb_dst_factor = blend->rgb_dst_factor;
|
||||
key->blend[i].alpha_func = blend->alpha_func;
|
||||
key->blend[i].alpha_src_factor = blend->alpha_src_factor;
|
||||
key->blend[i].alpha_dst_factor = blend->alpha_dst_factor;
|
||||
} else {
|
||||
key->blend[i].rgb_func = PIPE_BLEND_ADD;
|
||||
key->blend[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
|
||||
key->blend[i].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
|
||||
key->blend[i].alpha_func = PIPE_BLEND_ADD;
|
||||
key->blend[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
|
||||
key->blend[i].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
const struct util_format_description *desc =
|
||||
util_format_description(cbuf->format);
|
||||
|
||||
|
|
|
|||
|
|
@ -338,6 +338,7 @@ v3d_init_screen_caps(struct v3d_screen *screen)
|
|||
caps->max_render_targets = V3D_MAX_RENDER_TARGETS(screen->devinfo.ver);
|
||||
caps->fbfetch = caps->max_render_targets;
|
||||
caps->fbfetch_coherent = true;
|
||||
caps->max_dual_source_render_targets = 1;
|
||||
|
||||
caps->vendor_id = 0x14E4;
|
||||
|
||||
|
|
|
|||
|
|
@ -393,6 +393,19 @@ v3d_write_uniforms(struct v3d_context *v3d, struct v3d_job *job,
|
|||
cl_aligned_u32(&uniforms, job->num_layers);
|
||||
break;
|
||||
|
||||
case QUNIFORM_BLEND_CONSTANT_R:
|
||||
cl_aligned_f(&uniforms, v3d->blend_color.f.color[0]);
|
||||
break;
|
||||
case QUNIFORM_BLEND_CONSTANT_G:
|
||||
cl_aligned_f(&uniforms, v3d->blend_color.f.color[1]);
|
||||
break;
|
||||
case QUNIFORM_BLEND_CONSTANT_B:
|
||||
cl_aligned_f(&uniforms, v3d->blend_color.f.color[2]);
|
||||
break;
|
||||
case QUNIFORM_BLEND_CONSTANT_A:
|
||||
cl_aligned_f(&uniforms, v3d->blend_color.f.color[3]);
|
||||
break;
|
||||
|
||||
default:
|
||||
unreachable("Unknown QUNIFORM");
|
||||
|
||||
|
|
@ -486,6 +499,13 @@ v3d_set_shader_uniform_dirty_flags(struct v3d_compiled_shader *shader)
|
|||
dirty |= V3D_DIRTY_FRAMEBUFFER;
|
||||
break;
|
||||
|
||||
case QUNIFORM_BLEND_CONSTANT_R:
|
||||
case QUNIFORM_BLEND_CONSTANT_G:
|
||||
case QUNIFORM_BLEND_CONSTANT_B:
|
||||
case QUNIFORM_BLEND_CONSTANT_A:
|
||||
dirty |= V3D_DIRTY_BLEND_COLOR;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(quniform_contents_is_texture_p0(shader->prog_data.base->uniforms.contents[i]));
|
||||
dirty |= V3D_DIRTY_FRAGTEX | V3D_DIRTY_VERTTEX |
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ v3dX(emit_state)(struct pipe_context *pctx)
|
|||
config.direct3d_provoking_vertex =
|
||||
v3d->rasterizer->base.flatshade_first;
|
||||
|
||||
config.blend_enable = v3d->blend->blend_enables;
|
||||
config.blend_enable = v3d->blend->blend_enables && !v3d->blend->use_software;
|
||||
|
||||
/* Note: EZ state may update based on the compiled FS,
|
||||
* along with ZSA
|
||||
|
|
@ -480,7 +480,7 @@ v3dX(emit_state)(struct pipe_context *pctx)
|
|||
if (v3d->dirty & V3D_DIRTY_BLEND) {
|
||||
struct v3d_blend_state *blend = v3d->blend;
|
||||
|
||||
if (blend->blend_enables) {
|
||||
if (blend->blend_enables && !blend->use_software) {
|
||||
cl_emit(&job->bcl, BLEND_ENABLES, enables) {
|
||||
enables.mask = blend->blend_enables;
|
||||
}
|
||||
|
|
@ -516,6 +516,10 @@ v3dX(emit_state)(struct pipe_context *pctx)
|
|||
(1 << max_rts) - 1,
|
||||
v3d->blend_dst_alpha_one);
|
||||
}
|
||||
} else {
|
||||
cl_emit(&job->bcl, BLEND_ENABLES, enables) {
|
||||
enables.mask = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -535,9 +539,6 @@ v3dX(emit_state)(struct pipe_context *pctx)
|
|||
}
|
||||
}
|
||||
|
||||
/* GFXH-1431: On V3D 3.x, writing BLEND_CONFIG resets the constant
|
||||
* color.
|
||||
*/
|
||||
if (v3d->dirty & V3D_DIRTY_BLEND_COLOR) {
|
||||
cl_emit(&job->bcl, BLEND_CONSTANT_COLOR, color) {
|
||||
color.red_f16 = (v3d->swap_color_rb ?
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "pipe/p_state.h"
|
||||
#include "util/format/u_format.h"
|
||||
#include "util/u_dual_blend.h"
|
||||
#include "util/u_framebuffer.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_math.h"
|
||||
|
|
@ -123,6 +124,22 @@ v3d_create_rasterizer_state(struct pipe_context *pctx,
|
|||
return so;
|
||||
}
|
||||
|
||||
/* If the pipe_blend_state contains dual source factors then we need to fall
|
||||
* back to software blend.
|
||||
*/
|
||||
static bool
|
||||
v3d_needs_software_blend(const struct pipe_blend_state *blend)
|
||||
{
|
||||
if (V3D_DBG(SOFT_BLEND))
|
||||
return true;
|
||||
|
||||
/* We only support 1 attachment with dual source blend. */
|
||||
if (util_blend_state_is_dual(blend, 0))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Blend state is baked into shaders. */
|
||||
static void *
|
||||
v3d_create_blend_state(struct pipe_context *pctx,
|
||||
|
|
@ -136,6 +153,8 @@ v3d_create_blend_state(struct pipe_context *pctx,
|
|||
|
||||
so->base = *cso;
|
||||
|
||||
so->use_software = v3d_needs_software_blend(cso);
|
||||
|
||||
uint32_t max_rts = V3D_MAX_RENDER_TARGETS(V3D_VERSION);
|
||||
if (cso->independent_blend_enable) {
|
||||
for (int i = 0; i < max_rts; i++) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue