From 47dc2ae6e283423bad6286287b870dff63c7954c Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Sun, 25 Jan 2015 18:20:43 +0800 Subject: [PATCH] ilo: update ilo_blend_state and related functions for Gen8 --- .../drivers/ilo/ilo_builder_3d_bottom.h | 105 ++++++++- src/gallium/drivers/ilo/ilo_builder_decode.c | 5 + src/gallium/drivers/ilo/ilo_render_gen6.c | 2 +- src/gallium/drivers/ilo/ilo_render_gen7.c | 2 +- src/gallium/drivers/ilo/ilo_state.h | 7 +- src/gallium/drivers/ilo/ilo_state_3d_bottom.c | 220 ++++++++++++++++-- 6 files changed, 319 insertions(+), 22 deletions(-) diff --git a/src/gallium/drivers/ilo/ilo_builder_3d_bottom.h b/src/gallium/drivers/ilo/ilo_builder_3d_bottom.h index fd82d045683..14360af681a 100644 --- a/src/gallium/drivers/ilo/ilo_builder_3d_bottom.h +++ b/src/gallium/drivers/ilo/ilo_builder_3d_bottom.h @@ -705,6 +705,44 @@ gen8_3DSTATE_PS_EXTRA(struct ilo_builder *builder, dw[1] = dw1; } +static inline void +gen8_3DSTATE_PS_BLEND(struct ilo_builder *builder, + const struct ilo_blend_state *blend, + const struct ilo_fb_state *fb, + const struct ilo_dsa_state *dsa) +{ + const uint8_t cmd_len = 2; + uint32_t dw1, *dw; + + ILO_DEV_ASSERT(builder->dev, 8, 8); + + dw1 = 0; + if (blend->alpha_to_coverage && fb->num_samples > 1) + dw1 |= GEN8_PS_BLEND_DW1_ALPHA_TO_COVERAGE; + + if (fb->state.nr_cbufs && fb->state.cbufs[0]) { + const struct ilo_fb_blend_caps *caps = &fb->blend_caps[0]; + + dw1 |= GEN8_PS_BLEND_DW1_WRITABLE_RT; + if (caps->can_blend) { + if (caps->dst_alpha_forced_one) + dw1 |= blend->dw_ps_blend_dst_alpha_forced_one; + else + dw1 |= blend->dw_ps_blend; + } + + if (caps->can_alpha_test) + dw1 |= dsa->dw_ps_blend_alpha; + } else { + dw1 |= dsa->dw_ps_blend_alpha; + } + + ilo_builder_batch_pointer(builder, cmd_len, &dw); + + dw[0] = GEN8_RENDER_CMD(3D, 3DSTATE_PS_BLEND) | (cmd_len - 2); + dw[1] = dw1; +} + static inline void gen6_3DSTATE_CONSTANT_PS(struct ilo_builder *builder, const uint32_t *bufs, const int *sizes, @@ -1517,7 +1555,7 @@ gen6_BLEND_STATE(struct ilo_builder *builder, assert(num_targets <= 8); if (!num_targets) { - if (!dsa->dw_alpha) + if (!dsa->dw_blend_alpha) return 0; /* to be able to reference alpha func */ num_targets = 1; @@ -1548,13 +1586,13 @@ gen6_BLEND_STATE(struct ilo_builder *builder, dw[1] |= blend->dw_logicop; if (caps->can_alpha_test) - dw[1] |= dsa->dw_alpha; + dw[1] |= dsa->dw_blend_alpha; } else { dw[1] |= GEN6_RT_DW1_WRITE_DISABLE_A | GEN6_RT_DW1_WRITE_DISABLE_R | GEN6_RT_DW1_WRITE_DISABLE_G | GEN6_RT_DW1_WRITE_DISABLE_B | - dsa->dw_alpha; + dsa->dw_blend_alpha; } /* @@ -1575,4 +1613,65 @@ gen6_BLEND_STATE(struct ilo_builder *builder, return state_offset; } +static inline uint32_t +gen8_BLEND_STATE(struct ilo_builder *builder, + const struct ilo_blend_state *blend, + const struct ilo_fb_state *fb, + const struct ilo_dsa_state *dsa) +{ + const int state_align = 64; + int state_len; + uint32_t state_offset, *dw; + unsigned i; + + ILO_DEV_ASSERT(builder->dev, 8, 8); + + assert(fb->state.nr_cbufs <= 8); + + /* may need to reference alpha func even when there is no color buffer */ + if (!fb->state.nr_cbufs && !dsa->dw_blend_alpha) + return 0; + + state_len = 1 + 2 * fb->state.nr_cbufs; + + state_offset = ilo_builder_dynamic_pointer(builder, + ILO_BUILDER_ITEM_BLEND, state_align, state_len, &dw); + + dw[0] = blend->dw_shared; + if (fb->num_samples > 1) + dw[0] |= blend->dw_alpha_mod; + if (!fb->state.nr_cbufs || fb->blend_caps[0].can_alpha_test) + dw[0] |= dsa->dw_blend_alpha; + dw++; + + for (i = 0; i < fb->state.nr_cbufs; i++) { + const struct ilo_fb_blend_caps *caps = &fb->blend_caps[i]; + const struct ilo_blend_cso *cso = &blend->cso[i]; + + dw[0] = cso->payload[0]; + dw[1] = cso->payload[1]; + + if (fb->state.cbufs[i]) { + if (caps->can_blend) { + if (caps->dst_alpha_forced_one) + dw[0] |= cso->dw_blend_dst_alpha_forced_one; + else + dw[0] |= cso->dw_blend; + } + + if (caps->can_logicop) + dw[1] |= blend->dw_logicop; + } else { + dw[0] |= GEN8_RT_DW0_WRITE_DISABLE_A | + GEN8_RT_DW0_WRITE_DISABLE_R | + GEN8_RT_DW0_WRITE_DISABLE_G | + GEN8_RT_DW0_WRITE_DISABLE_B; + } + + dw += 2; + } + + return state_offset; +} + #endif /* ILO_BUILDER_3D_BOTTOM_H */ diff --git a/src/gallium/drivers/ilo/ilo_builder_decode.c b/src/gallium/drivers/ilo/ilo_builder_decode.c index d645f389fad..f518b49292b 100644 --- a/src/gallium/drivers/ilo/ilo_builder_decode.c +++ b/src/gallium/drivers/ilo/ilo_builder_decode.c @@ -371,6 +371,11 @@ writer_decode_blend(const struct ilo_builder *builder, unsigned offset = item->offset; unsigned i; + if (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) { + writer_dw(builder, which, offset, 0, "BLEND\n"); + offset += 4; + } + for (i = 0; i < count; i++) { writer_dw(builder, which, offset, 0, "BLEND%d\n", i); writer_dw(builder, which, offset, 1, "BLEND%d\n", i); diff --git a/src/gallium/drivers/ilo/ilo_render_gen6.c b/src/gallium/drivers/ilo/ilo_render_gen6.c index 3f0aa7cf23c..5e8cb33e0d2 100644 --- a/src/gallium/drivers/ilo/ilo_render_gen6.c +++ b/src/gallium/drivers/ilo/ilo_render_gen6.c @@ -702,7 +702,7 @@ gen6_draw_wm(struct ilo_render *r, if (DIRTY(FS) || DIRTY(BLEND) || DIRTY(DSA) || DIRTY(RASTERIZER) || r->instruction_bo_changed) { const bool dual_blend = vec->blend->dual_blend; - const bool cc_may_kill = (vec->dsa->dw_alpha || + const bool cc_may_kill = (vec->dsa->dw_blend_alpha || vec->blend->alpha_to_coverage); if (ilo_dev_gen(r->dev) == ILO_GEN(6) && r->hw_ctx_changed) diff --git a/src/gallium/drivers/ilo/ilo_render_gen7.c b/src/gallium/drivers/ilo/ilo_render_gen7.c index 5fe6995ef8c..1de6e2b2202 100644 --- a/src/gallium/drivers/ilo/ilo_render_gen7.c +++ b/src/gallium/drivers/ilo/ilo_render_gen7.c @@ -516,7 +516,7 @@ gen7_draw_wm(struct ilo_render *r, { /* 3DSTATE_WM */ if (DIRTY(FS) || DIRTY(BLEND) || DIRTY(DSA) || DIRTY(RASTERIZER)) { - const bool cc_may_kill = (vec->dsa->dw_alpha || + const bool cc_may_kill = (vec->dsa->dw_blend_alpha || vec->blend->alpha_to_coverage); gen7_3DSTATE_WM(r->builder, vec->fs, vec->rasterizer, cc_may_kill); diff --git a/src/gallium/drivers/ilo/ilo_state.h b/src/gallium/drivers/ilo/ilo_state.h index e935e5d5b78..737f50e31a4 100644 --- a/src/gallium/drivers/ilo/ilo_state.h +++ b/src/gallium/drivers/ilo/ilo_state.h @@ -250,7 +250,8 @@ struct ilo_dsa_state { /* DEPTH_STENCIL_STATE or Gen8+ 3DSTATE_WM_DEPTH_STENCIL */ uint32_t payload[3]; - uint32_t dw_alpha; + uint32_t dw_blend_alpha; + uint32_t dw_ps_blend_alpha; ubyte alpha_ref; }; @@ -271,6 +272,10 @@ struct ilo_blend_state { uint32_t dw_shared; uint32_t dw_alpha_mod; uint32_t dw_logicop; + + /* a part of 3DSTATE_PS_BLEND */ + uint32_t dw_ps_blend; + uint32_t dw_ps_blend_dst_alpha_forced_one; }; struct ilo_sampler_cso { diff --git a/src/gallium/drivers/ilo/ilo_state_3d_bottom.c b/src/gallium/drivers/ilo/ilo_state_3d_bottom.c index b309c947770..5ad88de2b75 100644 --- a/src/gallium/drivers/ilo/ilo_state_3d_bottom.c +++ b/src/gallium/drivers/ilo/ilo_state_3d_bottom.c @@ -1529,6 +1529,49 @@ blend_get_rt_blend_enable_gen6(const struct ilo_dev_info *dev, return dw; } +static uint32_t +blend_get_rt_blend_enable_gen8(const struct ilo_dev_info *dev, + const struct pipe_rt_blend_state *rt, + bool dst_alpha_forced_one, + bool *independent_alpha) +{ + int rgb_src, rgb_dst, a_src, a_dst; + uint32_t dw; + + ILO_DEV_ASSERT(dev, 8, 8); + + if (!rt->blend_enable) { + *independent_alpha = false; + return 0; + } + + rgb_src = gen6_translate_pipe_blendfactor(rt->rgb_src_factor); + rgb_dst = gen6_translate_pipe_blendfactor(rt->rgb_dst_factor); + a_src = gen6_translate_pipe_blendfactor(rt->alpha_src_factor); + a_dst = gen6_translate_pipe_blendfactor(rt->alpha_dst_factor); + + if (dst_alpha_forced_one) { + rgb_src = gen6_blend_factor_dst_alpha_forced_one(rgb_src); + rgb_dst = gen6_blend_factor_dst_alpha_forced_one(rgb_dst); + a_src = gen6_blend_factor_dst_alpha_forced_one(a_src); + a_dst = gen6_blend_factor_dst_alpha_forced_one(a_dst); + } + + dw = GEN8_RT_DW0_BLEND_ENABLE | + rgb_src << 26 | + rgb_dst << 21 | + gen6_translate_pipe_blend(rt->rgb_func) << 18 | + a_src << 13 | + a_dst << 8 | + gen6_translate_pipe_blend(rt->alpha_func) << 5; + + *independent_alpha = (rt->rgb_func != rt->alpha_func || + rgb_src != a_src || + rgb_dst != a_dst); + + return dw; +} + static void blend_init_cso_gen6(const struct ilo_dev_info *dev, const struct pipe_blend_state *state, @@ -1573,6 +1616,49 @@ blend_init_cso_gen6(const struct ilo_dev_info *dev, } } +static bool +blend_init_cso_gen8(const struct ilo_dev_info *dev, + const struct pipe_blend_state *state, + struct ilo_blend_state *blend, + unsigned index) +{ + const struct pipe_rt_blend_state *rt = &state->rt[index]; + struct ilo_blend_cso *cso = &blend->cso[index]; + bool independent_alpha = false; + + ILO_DEV_ASSERT(dev, 8, 8); + + cso->payload[0] = 0; + cso->payload[1] = GEN8_RT_DW1_COLORCLAMP_RTFORMAT | + GEN8_RT_DW1_PRE_BLEND_CLAMP | + GEN8_RT_DW1_POST_BLEND_CLAMP; + + if (!(rt->colormask & PIPE_MASK_A)) + cso->payload[0] |= GEN8_RT_DW0_WRITE_DISABLE_A; + if (!(rt->colormask & PIPE_MASK_R)) + cso->payload[0] |= GEN8_RT_DW0_WRITE_DISABLE_R; + if (!(rt->colormask & PIPE_MASK_G)) + cso->payload[0] |= GEN8_RT_DW0_WRITE_DISABLE_G; + if (!(rt->colormask & PIPE_MASK_B)) + cso->payload[0] |= GEN8_RT_DW0_WRITE_DISABLE_B; + + if (state->logicop_enable) { + cso->dw_blend = 0; + cso->dw_blend_dst_alpha_forced_one = 0; + } else { + bool tmp[2]; + + cso->dw_blend = blend_get_rt_blend_enable_gen8(dev, rt, false, &tmp[0]); + cso->dw_blend_dst_alpha_forced_one = + blend_get_rt_blend_enable_gen8(dev, rt, true, &tmp[1]); + + if (tmp[0] || tmp[1]) + independent_alpha = true; + } + + return independent_alpha; +} + static uint32_t blend_get_logicop_enable_gen6(const struct ilo_dev_info *dev, const struct pipe_blend_state *state) @@ -1586,6 +1672,19 @@ blend_get_logicop_enable_gen6(const struct ilo_dev_info *dev, gen6_translate_pipe_logicop(state->logicop_func) << 18; } +static uint32_t +blend_get_logicop_enable_gen8(const struct ilo_dev_info *dev, + const struct pipe_blend_state *state) +{ + ILO_DEV_ASSERT(dev, 8, 8); + + if (!state->logicop_enable) + return 0; + + return GEN8_RT_DW1_LOGICOP_ENABLE | + gen6_translate_pipe_logicop(state->logicop_func) << 27; +} + static uint32_t blend_get_alpha_mod_gen6(const struct ilo_dev_info *dev, const struct pipe_blend_state *state, @@ -1612,6 +1711,54 @@ blend_get_alpha_mod_gen6(const struct ilo_dev_info *dev, return dw; } +static uint32_t +blend_get_alpha_mod_gen8(const struct ilo_dev_info *dev, + const struct pipe_blend_state *state, + bool dual_blend) +{ + uint32_t dw = 0; + + ILO_DEV_ASSERT(dev, 8, 8); + + if (state->alpha_to_coverage) { + dw |= GEN8_BLEND_DW0_ALPHA_TO_COVERAGE | + GEN8_BLEND_DW0_ALPHA_TO_COVERAGE_DITHER; + } + + if (state->alpha_to_one && !dual_blend) + dw |= GEN8_BLEND_DW0_ALPHA_TO_ONE; + + return dw; +} + +static uint32_t +blend_get_ps_blend_gen8(const struct ilo_dev_info *dev, uint32_t rt_dw0) +{ + int rgb_src, rgb_dst, a_src, a_dst; + uint32_t dw; + + ILO_DEV_ASSERT(dev, 8, 8); + + if (!(rt_dw0 & GEN8_RT_DW0_BLEND_ENABLE)) + return 0; + + a_src = GEN_EXTRACT(rt_dw0, GEN8_RT_DW0_SRC_ALPHA_FACTOR); + a_dst = GEN_EXTRACT(rt_dw0, GEN8_RT_DW0_DST_ALPHA_FACTOR); + rgb_src = GEN_EXTRACT(rt_dw0, GEN8_RT_DW0_SRC_COLOR_FACTOR); + rgb_dst = GEN_EXTRACT(rt_dw0, GEN8_RT_DW0_DST_COLOR_FACTOR); + + dw = GEN8_PS_BLEND_DW1_BLEND_ENABLE; + dw |= GEN_SHIFT32(a_src, GEN8_PS_BLEND_DW1_SRC_ALPHA_FACTOR); + dw |= GEN_SHIFT32(a_dst, GEN8_PS_BLEND_DW1_DST_ALPHA_FACTOR); + dw |= GEN_SHIFT32(rgb_src, GEN8_PS_BLEND_DW1_SRC_COLOR_FACTOR); + dw |= GEN_SHIFT32(rgb_dst, GEN8_PS_BLEND_DW1_DST_COLOR_FACTOR); + + if (a_src != rgb_src || a_dst != rgb_dst) + dw |= GEN8_PS_BLEND_DW1_INDEPENDENT_ALPHA_ENABLE; + + return dw; +} + void ilo_gpe_init_blend(const struct ilo_dev_info *dev, const struct pipe_blend_state *state, @@ -1619,25 +1766,57 @@ ilo_gpe_init_blend(const struct ilo_dev_info *dev, { unsigned i; - ILO_DEV_ASSERT(dev, 6, 7.5); + ILO_DEV_ASSERT(dev, 6, 8); blend->dual_blend = (util_blend_state_is_dual(state, 0) && state->rt[0].blend_enable && !state->logicop_enable); blend->alpha_to_coverage = state->alpha_to_coverage; - blend->dw_alpha_mod = - blend_get_alpha_mod_gen6(dev, state, blend->dual_blend); - blend->dw_logicop = blend_get_logicop_enable_gen6(dev, state); - blend->dw_shared = (state->dither) ? GEN6_RT_DW1_DITHER_ENABLE : 0; - - blend_init_cso_gen6(dev, state, blend, 0); - if (state->independent_blend_enable) { - for (i = 1; i < Elements(blend->cso); i++) - blend_init_cso_gen6(dev, state, blend, i); + if (ilo_dev_gen(dev) >= ILO_GEN(8)) { + bool independent_alpha; + + blend->dw_alpha_mod = + blend_get_alpha_mod_gen8(dev, state, blend->dual_blend); + blend->dw_logicop = blend_get_logicop_enable_gen8(dev, state); + blend->dw_shared = (state->dither) ? GEN8_BLEND_DW0_DITHER_ENABLE : 0; + + independent_alpha = blend_init_cso_gen8(dev, state, blend, 0); + if (independent_alpha) + blend->dw_shared |= GEN8_BLEND_DW0_INDEPENDENT_ALPHA_ENABLE; + + blend->dw_ps_blend = blend_get_ps_blend_gen8(dev, + blend->cso[0].dw_blend); + blend->dw_ps_blend_dst_alpha_forced_one = blend_get_ps_blend_gen8(dev, + blend->cso[0].dw_blend_dst_alpha_forced_one); + + if (state->independent_blend_enable) { + for (i = 1; i < Elements(blend->cso); i++) { + independent_alpha = blend_init_cso_gen8(dev, state, blend, i); + if (independent_alpha) + blend->dw_shared |= GEN8_BLEND_DW0_INDEPENDENT_ALPHA_ENABLE; + } + } else { + for (i = 1; i < Elements(blend->cso); i++) + blend->cso[i] = blend->cso[0]; + } } else { - for (i = 1; i < Elements(blend->cso); i++) - blend->cso[i] = blend->cso[0]; + blend->dw_alpha_mod = + blend_get_alpha_mod_gen6(dev, state, blend->dual_blend); + blend->dw_logicop = blend_get_logicop_enable_gen6(dev, state); + blend->dw_shared = (state->dither) ? GEN6_RT_DW1_DITHER_ENABLE : 0; + + blend->dw_ps_blend = 0; + blend->dw_ps_blend_dst_alpha_forced_one = 0; + + blend_init_cso_gen6(dev, state, blend, 0); + if (state->independent_blend_enable) { + for (i = 1; i < Elements(blend->cso); i++) + blend_init_cso_gen6(dev, state, blend, i); + } else { + for (i = 1; i < Elements(blend->cso); i++) + blend->cso[i] = blend->cso[0]; + } } } @@ -1843,7 +2022,10 @@ ilo_gpe_init_dsa(const struct ilo_dev_info *dev, state->stencil[1].valuemask << 8 | state->stencil[1].writemask; - dsa->dw_alpha = dsa_get_alpha_enable_gen6(dev, &state->alpha); + dsa->dw_blend_alpha = dsa_get_alpha_enable_gen6(dev, &state->alpha); + dsa->dw_ps_blend_alpha = (state->alpha.enabled) ? + GEN8_PS_BLEND_DW1_ALPHA_TEST_ENABLE : 0; + dsa->alpha_ref = float_to_ubyte(state->alpha.ref_value); } @@ -1916,10 +2098,16 @@ fb_set_blend_caps(const struct ilo_dev_info *dev, * * "Logic Ops are only supported on *_UNORM surfaces (excluding _SRGB * variants), otherwise Logic Ops must be DISABLED." + * + * According to the classic driver, this is lifted on Gen8+. */ - caps->can_logicop = (ch >= 0 && desc->channel[ch].normalized && - desc->channel[ch].type == UTIL_FORMAT_TYPE_UNSIGNED && - desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB); + if (ilo_dev_gen(dev) >= ILO_GEN(8)) { + caps->can_logicop = true; + } else { + caps->can_logicop = (ch >= 0 && desc->channel[ch].normalized && + desc->channel[ch].type == UTIL_FORMAT_TYPE_UNSIGNED && + desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB); + } /* no blending for pure integer formats */ caps->can_blend = !util_format_is_pure_integer(format); -- 2.30.2