ilo: update ilo_blend_state and related functions for Gen8

This commit is contained in:
Chia-I Wu
2015-01-25 18:20:43 +08:00
parent e8455128aa
commit 47dc2ae6e2
6 changed files with 318 additions and 21 deletions
+102 -3
View File
@@ -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 */
@@ -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);
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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);
+6 -1
View File
@@ -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 {
+203 -15
View File
@@ -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;
if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
bool independent_alpha;
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);
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);