mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-01 01:00:10 +01:00
etnaviv: Extend etna_set_framebuffer_state(..) for MRTs
The GPU needs all the active (non-null) render targets in a contiguous representation. For instance, if fb->nr_cbufs is 4 but fb->cbufs[0] and fb->cbufs[1] are null we need to program the GPU that fb->cbufs[2] is configured via PE_COLOR_FORMAT and friends and fb->cbufs[3] via PE_RT_CONFIG[0] and friends. We need to keep track which render target is used as we need to update the fragment shader output mapping. Signed-off-by: Christian Gmeiner <cgmeiner@igalia.com> Reviewed-by: Lucas Stach <l.stach@pengutronix.de> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26565>
This commit is contained in:
parent
546c4b992c
commit
2436babbd2
2 changed files with 154 additions and 65 deletions
|
|
@ -170,6 +170,8 @@ struct compiled_viewport_state {
|
|||
|
||||
/* Compiled pipe_framebuffer_state */
|
||||
struct compiled_framebuffer_state {
|
||||
unsigned ps_output_remap[8];
|
||||
uint8_t num_rt;
|
||||
uint32_t GL_MULTI_SAMPLE_CONFIG;
|
||||
uint32_t PE_COLOR_FORMAT;
|
||||
uint32_t PE_DEPTH_CONFIG;
|
||||
|
|
@ -196,6 +198,15 @@ struct compiled_framebuffer_state {
|
|||
uint32_t PE_LOGIC_OP;
|
||||
uint32_t PS_CONTROL;
|
||||
uint32_t PS_CONTROL_EXT;
|
||||
uint32_t PS_OUTPUT_REG2;
|
||||
struct etna_reloc PE_RT_COLOR_ADDR[7];
|
||||
struct etna_reloc PE_RT_PIPE_COLOR_ADDR[7][ETNA_MAX_PIXELPIPES];
|
||||
uint32_t PE_RT_CONFIG[7];
|
||||
uint32_t RT_TS_MEM_CONFIG[7];
|
||||
uint32_t RT_TS_COLOR_CLEAR_VALUE[7];
|
||||
uint32_t RT_TS_COLOR_CLEAR_VALUE_EXT[7];
|
||||
struct etna_reloc RT_TS_COLOR_STATUS_BASE[7];
|
||||
struct etna_reloc RT_TS_COLOR_SURFACE_BASE[7];
|
||||
bool msaa_mode; /* adds input (and possible temp) to PS */
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -139,13 +139,20 @@ etna_set_framebuffer_state(struct pipe_context *pctx,
|
|||
bool target_16bpp = false;
|
||||
bool target_linear = false;
|
||||
|
||||
memset(cs, 0, sizeof(struct compiled_framebuffer_state));
|
||||
|
||||
/* Set up TS as well. Warning: this state is used by both the RS and PE */
|
||||
uint32_t ts_mem_config = 0;
|
||||
uint32_t pe_mem_config = 0;
|
||||
uint32_t pe_logic_op = 0;
|
||||
|
||||
if (fb->nr_cbufs > 0) { /* at least one color buffer? */
|
||||
struct etna_surface *cbuf = etna_surface(fb->cbufs[0]);
|
||||
unsigned rt = 0;
|
||||
|
||||
for (unsigned i = 0; i < fb->nr_cbufs; i++) {
|
||||
if (!fb->cbufs[i])
|
||||
continue;
|
||||
|
||||
struct etna_surface *cbuf = etna_surface(fb->cbufs[i]);
|
||||
struct etna_resource *res = etna_resource(cbuf->base.texture);
|
||||
bool color_supertiled = (res->layout & ETNA_LAYOUT_BIT_SUPER) != 0;
|
||||
uint32_t fmt = translate_pe_format(cbuf->base.format);
|
||||
|
|
@ -157,86 +164,157 @@ etna_set_framebuffer_state(struct pipe_context *pctx,
|
|||
if (res->layout == ETNA_LAYOUT_LINEAR)
|
||||
target_linear = true;
|
||||
|
||||
if (fmt >= PE_FORMAT_R16F)
|
||||
cs->PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_FORMAT_EXT(fmt) |
|
||||
VIVS_PE_COLOR_FORMAT_FORMAT_MASK;
|
||||
else
|
||||
cs->PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_FORMAT(fmt);
|
||||
|
||||
if (util_format_get_blocksize(cbuf->base.format) <= 2)
|
||||
target_16bpp = true;
|
||||
|
||||
cs->PE_COLOR_FORMAT |=
|
||||
VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK |
|
||||
COND(color_supertiled, VIVS_PE_COLOR_FORMAT_SUPER_TILED);
|
||||
if (rt == 0) {
|
||||
if (fmt >= PE_FORMAT_R16F)
|
||||
cs->PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_FORMAT_EXT(fmt) |
|
||||
VIVS_PE_COLOR_FORMAT_FORMAT_MASK;
|
||||
else
|
||||
cs->PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_FORMAT(fmt);
|
||||
|
||||
nr_samples_color = cbuf->base.texture->nr_samples;
|
||||
if (nr_samples_color <= 1)
|
||||
cs->PE_COLOR_FORMAT |= VIVS_PE_COLOR_FORMAT_OVERWRITE;
|
||||
cs->PE_COLOR_FORMAT |=
|
||||
VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK |
|
||||
COND(color_supertiled, VIVS_PE_COLOR_FORMAT_SUPER_TILED);
|
||||
|
||||
if (VIV_FEATURE(screen, ETNA_FEATURE_CACHE128B256BPERLINE))
|
||||
cs->PE_COLOR_FORMAT |= COND(color_supertiled, VIVS_PE_COLOR_FORMAT_SUPER_TILED_NEW);
|
||||
/* VIVS_PE_COLOR_FORMAT_COMPONENTS() and
|
||||
* VIVS_PE_COLOR_FORMAT_OVERWRITE comes from blend_state
|
||||
* but only if we set the bits above. */
|
||||
/* merged with depth_stencil_alpha */
|
||||
if ((cbuf->offset & 63) ||
|
||||
(((cbuf->level->stride * 4) & 63) && cbuf->level->height > 4)) {
|
||||
/* XXX Must make temporary surface here.
|
||||
* Need the same mechanism on gc2000 when we want to do mipmap
|
||||
* generation by
|
||||
* rendering to levels > 1 due to multitiled / tiled conversion. */
|
||||
BUG("Alignment error, trying to render to offset %08x with tile "
|
||||
"stride %i",
|
||||
cbuf->offset, cbuf->level->stride * 4);
|
||||
}
|
||||
nr_samples_color = cbuf->base.texture->nr_samples;
|
||||
if (nr_samples_color <= 1)
|
||||
cs->PE_COLOR_FORMAT |= VIVS_PE_COLOR_FORMAT_OVERWRITE;
|
||||
|
||||
if (screen->info->halti >= 0 && screen->info->model != 0x880) {
|
||||
/* Rendertargets on GPUs with more than a single pixel pipe must always
|
||||
* be multi-tiled, or single-buffer mode must be supported */
|
||||
assert(screen->specs.pixel_pipes == 1 ||
|
||||
(res->layout & ETNA_LAYOUT_BIT_MULTI) || screen->specs.single_buffer);
|
||||
for (int i = 0; i < screen->specs.pixel_pipes; i++) {
|
||||
cs->PE_PIPE_COLOR_ADDR[i] = cbuf->reloc[i];
|
||||
cs->PE_PIPE_COLOR_ADDR[i].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
|
||||
if (VIV_FEATURE(screen, ETNA_FEATURE_CACHE128B256BPERLINE))
|
||||
cs->PE_COLOR_FORMAT |= COND(color_supertiled, VIVS_PE_COLOR_FORMAT_SUPER_TILED_NEW);
|
||||
/* VIVS_PE_COLOR_FORMAT_COMPONENTS() and
|
||||
* VIVS_PE_COLOR_FORMAT_OVERWRITE comes from blend_state
|
||||
* but only if we set the bits above. */
|
||||
/* merged with depth_stencil_alpha */
|
||||
if ((cbuf->offset & 63) ||
|
||||
(((cbuf->level->stride * 4) & 63) && cbuf->level->height > 4)) {
|
||||
/* XXX Must make temporary surface here.
|
||||
* Need the same mechanism on gc2000 when we want to do mipmap
|
||||
* generation by
|
||||
* rendering to levels > 1 due to multitiled / tiled conversion. */
|
||||
BUG("Alignment error, trying to render to offset %08x with tile "
|
||||
"stride %i",
|
||||
cbuf->offset, cbuf->level->stride * 4);
|
||||
}
|
||||
|
||||
if (screen->info->halti >= 0 && screen->info->model != 0x880) {
|
||||
/* Rendertargets on GPUs with more than a single pixel pipe must always
|
||||
* be multi-tiled, or single-buffer mode must be supported */
|
||||
assert(screen->specs.pixel_pipes == 1 ||
|
||||
(res->layout & ETNA_LAYOUT_BIT_MULTI) || screen->specs.single_buffer);
|
||||
for (int i = 0; i < screen->specs.pixel_pipes; i++) {
|
||||
cs->PE_PIPE_COLOR_ADDR[i] = cbuf->reloc[i];
|
||||
cs->PE_PIPE_COLOR_ADDR[i].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
|
||||
}
|
||||
} else {
|
||||
cs->PE_COLOR_ADDR = cbuf->reloc[0];
|
||||
cs->PE_COLOR_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
|
||||
}
|
||||
|
||||
cs->PE_COLOR_STRIDE = cbuf->level->stride;
|
||||
|
||||
if (cbuf->level->ts_size) {
|
||||
cs->TS_COLOR_CLEAR_VALUE = cbuf->level->clear_value;
|
||||
cs->TS_COLOR_CLEAR_VALUE_EXT = cbuf->level->clear_value >> 32;
|
||||
|
||||
cs->TS_COLOR_STATUS_BASE = cbuf->ts_reloc;
|
||||
cs->TS_COLOR_STATUS_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
|
||||
|
||||
cs->TS_COLOR_SURFACE_BASE = cbuf->reloc[0];
|
||||
cs->TS_COLOR_SURFACE_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
|
||||
|
||||
pe_mem_config |= VIVS_PE_MEM_CONFIG_COLOR_TS_MODE(cbuf->level->ts_mode);
|
||||
|
||||
if (cbuf->level->ts_compress_fmt >= 0) {
|
||||
/* overwrite bit breaks v1/v2 compression */
|
||||
if (!screen->specs.v4_compression)
|
||||
cs->PE_COLOR_FORMAT &= ~VIVS_PE_COLOR_FORMAT_OVERWRITE;
|
||||
|
||||
ts_mem_config |=
|
||||
VIVS_TS_MEM_CONFIG_COLOR_COMPRESSION |
|
||||
VIVS_TS_MEM_CONFIG_COLOR_COMPRESSION_FORMAT(cbuf->level->ts_compress_fmt);
|
||||
}
|
||||
}
|
||||
|
||||
if (util_format_is_srgb(cbuf->base.format))
|
||||
pe_logic_op |= VIVS_PE_LOGIC_OP_SRGB;
|
||||
} else {
|
||||
cs->PE_COLOR_ADDR = cbuf->reloc[0];
|
||||
cs->PE_COLOR_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
|
||||
}
|
||||
cs->PE_RT_PIPE_COLOR_ADDR[rt - 1][0] = cbuf->reloc[0];
|
||||
cs->PE_RT_PIPE_COLOR_ADDR[rt - 1][1] = cbuf->reloc[1];
|
||||
cs->PE_RT_CONFIG[rt - 1] =
|
||||
RT_CONFIG_STRIDE(cbuf->level->stride) |
|
||||
RT_CONFIG_FORMAT(fmt) |
|
||||
COND(color_supertiled, RT_CONFIG_SUPER_TILED);
|
||||
|
||||
cs->PE_COLOR_STRIDE = cbuf->level->stride;
|
||||
if (VIV_FEATURE(screen, ETNA_FEATURE_CACHE128B256BPERLINE))
|
||||
cs->PE_RT_CONFIG[rt - 1] |= COND(color_supertiled, RT_CONFIG_SUPER_TILED_NEW);
|
||||
|
||||
if (cbuf->level->ts_size) {
|
||||
cs->TS_COLOR_CLEAR_VALUE = cbuf->level->clear_value;
|
||||
cs->TS_COLOR_CLEAR_VALUE_EXT = cbuf->level->clear_value >> 32;
|
||||
if (cbuf->level->ts_size) {
|
||||
cs->RT_TS_MEM_CONFIG[rt - 1] =
|
||||
COND(cbuf->level->ts_compress_fmt >= 0, VIVS_TS_RT_CONFIG_COMPRESSION) |
|
||||
COND(cbuf->level->ts_compress_fmt >= 0, VIVS_TS_RT_CONFIG_COMPRESSION_FORMAT(cbuf->level->ts_compress_fmt));
|
||||
|
||||
cs->TS_COLOR_STATUS_BASE = cbuf->ts_reloc;
|
||||
cs->TS_COLOR_STATUS_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
|
||||
cs->RT_TS_COLOR_CLEAR_VALUE[rt - 1] = cbuf->level->clear_value;
|
||||
cs->RT_TS_COLOR_CLEAR_VALUE_EXT[rt - 1] = cbuf->level->clear_value >> 32;
|
||||
|
||||
cs->TS_COLOR_SURFACE_BASE = cbuf->reloc[0];
|
||||
cs->TS_COLOR_SURFACE_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
|
||||
cs->RT_TS_COLOR_STATUS_BASE[rt - 1] = cbuf->ts_reloc;
|
||||
cs->RT_TS_COLOR_STATUS_BASE[rt - 1].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
|
||||
|
||||
pe_mem_config |= VIVS_PE_MEM_CONFIG_COLOR_TS_MODE(cbuf->level->ts_mode);
|
||||
|
||||
if (cbuf->level->ts_compress_fmt >= 0) {
|
||||
/* overwrite bit breaks v1/v2 compression */
|
||||
if (!screen->specs.v4_compression)
|
||||
cs->PE_COLOR_FORMAT &= ~VIVS_PE_COLOR_FORMAT_OVERWRITE;
|
||||
|
||||
ts_mem_config |=
|
||||
VIVS_TS_MEM_CONFIG_COLOR_COMPRESSION |
|
||||
VIVS_TS_MEM_CONFIG_COLOR_COMPRESSION_FORMAT(cbuf->level->ts_compress_fmt);
|
||||
cs->RT_TS_COLOR_SURFACE_BASE[rt - 1] = cbuf->reloc[0];
|
||||
cs->RT_TS_COLOR_SURFACE_BASE[rt - 1].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
|
||||
} else {
|
||||
if (VIV_FEATURE(screen, ETNA_FEATURE_CACHE128B256BPERLINE))
|
||||
cs->PE_RT_CONFIG[rt - 1] |= RT_CONFIG_UNK27;
|
||||
}
|
||||
}
|
||||
|
||||
if (util_format_is_srgb(cbuf->base.format))
|
||||
pe_logic_op |= VIVS_PE_LOGIC_OP_SRGB;
|
||||
static_assert((VIVS_PS_CONTROL_SATURATE_RT0 << 0) == VIVS_PS_CONTROL_SATURATE_RT0, "VIVS_PS_CONTROL_SATURATE_RT0");
|
||||
static_assert((VIVS_PS_CONTROL_SATURATE_RT0 << 1) == VIVS_PS_CONTROL_SATURATE_RT1, "VIVS_PS_CONTROL_SATURATE_RT1");
|
||||
static_assert((VIVS_PS_CONTROL_SATURATE_RT0 << 2) == VIVS_PS_CONTROL_SATURATE_RT2, "VIVS_PS_CONTROL_SATURATE_RT2");
|
||||
static_assert((VIVS_PS_CONTROL_SATURATE_RT0 << 3) == VIVS_PS_CONTROL_SATURATE_RT3, "VIVS_PS_CONTROL_SATURATE_RT3");
|
||||
|
||||
cs->PS_CONTROL = COND(util_format_is_unorm(cbuf->base.format), VIVS_PS_CONTROL_SATURATE_RT0);
|
||||
cs->PS_CONTROL_EXT =
|
||||
VIVS_PS_CONTROL_EXT_OUTPUT_MODE0(translate_output_mode(cbuf->base.format, screen->info->halti >= 5));
|
||||
} else {
|
||||
static_assert((VIVS_PS_OUTPUT_REG2_SATURATE_RT4 << 0) == VIVS_PS_OUTPUT_REG2_SATURATE_RT4, "VIVS_PS_OUTPUT_REG2_SATURATE_RT4");
|
||||
static_assert((VIVS_PS_OUTPUT_REG2_SATURATE_RT4 << 8) == VIVS_PS_OUTPUT_REG2_SATURATE_RT5, "VIVS_PS_OUTPUT_REG2_SATURATE_RT5");
|
||||
static_assert((VIVS_PS_OUTPUT_REG2_SATURATE_RT4 << 16) == VIVS_PS_OUTPUT_REG2_SATURATE_RT6, "VIVS_PS_OUTPUT_REG2_SATURATE_RT6");
|
||||
static_assert((VIVS_PS_OUTPUT_REG2_SATURATE_RT4 << 24) == VIVS_PS_OUTPUT_REG2_SATURATE_RT7, "VIVS_PS_OUTPUT_REG2_SATURATE_RT7");
|
||||
|
||||
if (rt < 4)
|
||||
cs->PS_CONTROL |= COND(util_format_is_unorm(cbuf->base.format), VIVS_PS_CONTROL_SATURATE_RT0 << rt);
|
||||
else
|
||||
cs->PS_OUTPUT_REG2 |= COND(util_format_is_unorm(cbuf->base.format), VIVS_PS_OUTPUT_REG2_SATURATE_RT4 << (8 * (rt - 4)));
|
||||
|
||||
static_assert((VIVS_PS_CONTROL_EXT_OUTPUT_MODE0__MASK << 4) == VIVS_PS_CONTROL_EXT_OUTPUT_MODE1__MASK, "VIVS_PS_CONTROL_EXT_OUTPUT_MODE1__MASK");
|
||||
static_assert((VIVS_PS_CONTROL_EXT_OUTPUT_MODE0__MASK << 8) == VIVS_PS_CONTROL_EXT_OUTPUT_MODE2__MASK, "VIVS_PS_CONTROL_EXT_OUTPUT_MODE2__MASK");
|
||||
static_assert((VIVS_PS_CONTROL_EXT_OUTPUT_MODE0__MASK << 12) == VIVS_PS_CONTROL_EXT_OUTPUT_MODE3__MASK, "VIVS_PS_CONTROL_EXT_OUTPUT_MODE3__MASK");
|
||||
static_assert((VIVS_PS_CONTROL_EXT_OUTPUT_MODE0__MASK << 16) == VIVS_PS_CONTROL_EXT_OUTPUT_MODE4__MASK, "VIVS_PS_CONTROL_EXT_OUTPUT_MODE4__MASK");
|
||||
static_assert((VIVS_PS_CONTROL_EXT_OUTPUT_MODE0__MASK << 20) == VIVS_PS_CONTROL_EXT_OUTPUT_MODE5__MASK, "VIVS_PS_CONTROL_EXT_OUTPUT_MODE5__MASK");
|
||||
static_assert((VIVS_PS_CONTROL_EXT_OUTPUT_MODE0__MASK << 24) == VIVS_PS_CONTROL_EXT_OUTPUT_MODE6__MASK, "VIVS_PS_CONTROL_EXT_OUTPUT_MODE6__MASK");
|
||||
static_assert((VIVS_PS_CONTROL_EXT_OUTPUT_MODE0__MASK << 28) == VIVS_PS_CONTROL_EXT_OUTPUT_MODE7__MASK, "VIVS_PS_CONTROL_EXT_OUTPUT_MODE7__MASK");
|
||||
|
||||
cs->PS_CONTROL_EXT |=
|
||||
translate_output_mode(cbuf->base.format, screen->info->halti >= 5) << (4 * rt);
|
||||
|
||||
/* When there are null render targets we need to modify the fragment
|
||||
* shader output mapping.
|
||||
*/
|
||||
assert(rt < ARRAY_SIZE(cs->ps_output_remap));
|
||||
cs->ps_output_remap[rt] = i;
|
||||
|
||||
rt++;
|
||||
}
|
||||
|
||||
cs->num_rt = rt;
|
||||
|
||||
if (rt)
|
||||
cs->PS_CONTROL |= VIVS_PS_CONTROL_RT_COUNT(rt - 1);
|
||||
|
||||
/*
|
||||
* Disable the main render target if needed. The extra render targets are implicitly
|
||||
* disabled by using VIVS_PS_CONTROL_RT_COUNT(0).
|
||||
*/
|
||||
if (fb->nr_cbufs == 0) {
|
||||
/* Clearing VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK and
|
||||
* VIVS_PE_COLOR_FORMAT_OVERWRITE prevents us from overwriting the
|
||||
* color target */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue