From: Rob Clark Date: Fri, 12 Sep 2014 13:01:25 +0000 (-0400) Subject: freedreno/a3xx: alpha render-target shenanigans X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=80058c0f08ea94d3de96909027a792e397fa9262;p=mesa.git freedreno/a3xx: alpha render-target shenanigans We need the .w component to end up in .x, since the hw appears to fetch gl_FragColor starting with the .x coordinate regardless of MRT format. As long as we are doing this, we might as well throw out the remaining unneeded components. Signed-off-by: Rob Clark --- diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_draw.c b/src/gallium/drivers/freedreno/a3xx/fd3_draw.c index 394277cf6b9..15d2ce4a943 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_draw.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_draw.c @@ -30,6 +30,7 @@ #include "util/u_string.h" #include "util/u_memory.h" #include "util/u_prim.h" +#include "util/u_format.h" #include "freedreno_state.h" #include "freedreno_resource.h" @@ -103,6 +104,7 @@ fd3_draw(struct fd_context *ctx, const struct pipe_draw_info *info) /* do binning pass first: */ .binning_pass = true, .color_two_side = ctx->rasterizer ? ctx->rasterizer->light_twoside : false, + .alpha = util_format_is_alpha(pipe_surface_format(ctx->framebuffer.cbufs[0])), // TODO set .half_precision based on render target format, // ie. float16 and smaller use half, float32 use full.. .half_precision = !!(fd_mesa_debug & FD_DBG_FRAGHALF), diff --git a/src/gallium/drivers/freedreno/ir3/ir3_compiler.c b/src/gallium/drivers/freedreno/ir3/ir3_compiler.c index affb775f75b..25211feb024 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_compiler.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_compiler.c @@ -2607,6 +2607,23 @@ ir3_compile_shader(struct ir3_shader_variant *so, block->noutputs = j * 4; } + /* for rendering to alpha format, we only need the .w component, + * and we need it to be in the .x position: + */ + if (key.alpha) { + for (i = 0, j = 0; i < so->outputs_count; i++) { + unsigned name = sem2name(so->outputs[i].semantic); + + /* move .w component to .x and discard others: */ + if (name == TGSI_SEMANTIC_COLOR) { + block->outputs[(i*4)+0] = block->outputs[(i*4)+3]; + block->outputs[(i*4)+1] = NULL; + block->outputs[(i*4)+2] = NULL; + block->outputs[(i*4)+3] = NULL; + } + } + } + /* at this point, we want the kill's in the outputs array too, * so that they get scheduled (since they have no dst).. we've * already ensured that the array is big enough in push_block(): diff --git a/src/gallium/drivers/freedreno/ir3/ir3_shader.c b/src/gallium/drivers/freedreno/ir3/ir3_shader.c index a170469b573..6d45597886b 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_shader.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_shader.c @@ -189,6 +189,7 @@ ir3_shader_variant(struct ir3_shader *shader, struct ir3_shader_key key) if (shader->type == SHADER_VERTEX) { key.color_two_side = false; key.half_precision = false; + key.alpha = false; } for (v = shader->variants; v; v = v->next) diff --git a/src/gallium/drivers/freedreno/ir3/ir3_shader.h b/src/gallium/drivers/freedreno/ir3/ir3_shader.h index 1a91fcbcb13..882893fdde5 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_shader.h +++ b/src/gallium/drivers/freedreno/ir3/ir3_shader.h @@ -54,12 +54,24 @@ static inline uint16_t sem2idx(ir3_semantic sem) * in hw (two sided color), binning-pass vertex shader, etc. */ struct ir3_shader_key { - /* vertex shader variant parameters: */ + /* + * Vertex shader variant parameters: + */ unsigned binning_pass : 1; - /* fragment shader variant parameters: */ + /* + * Fragment shader variant parameters: + */ unsigned color_two_side : 1; unsigned half_precision : 1; + /* For rendering to alpha, we need a bit of special handling + * since the hw always takes gl_FragColor starting from x + * component, rather than figuring out to take the w component. + * We could be more clever and generate variants for other + * render target formats (ie. luminance formats are xxx1), but + * let's start with this and see how it goes: + */ + unsigned alpha : 1; }; struct ir3_shader_variant {