From 8d27be2633f2fc543a6d00d66dcb033798d44749 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 14 Jan 2014 13:03:20 -0500 Subject: [PATCH] freedreno/a3xx: handle frag z write Signed-off-by: Rob Clark --- .../drivers/freedreno/a3xx/fd3_compiler.c | 9 ++++- src/gallium/drivers/freedreno/a3xx/fd3_draw.c | 15 +++----- src/gallium/drivers/freedreno/a3xx/fd3_emit.c | 38 +++++++++++++------ src/gallium/drivers/freedreno/a3xx/fd3_emit.h | 2 +- .../drivers/freedreno/a3xx/fd3_program.c | 11 +++++- .../drivers/freedreno/a3xx/fd3_program.h | 1 + .../drivers/freedreno/freedreno_screen.c | 2 +- 7 files changed, 53 insertions(+), 25 deletions(-) diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_compiler.c b/src/gallium/drivers/freedreno/a3xx/fd3_compiler.c index c8e66fc76dd..2c32c0fa2a7 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_compiler.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_compiler.c @@ -1341,6 +1341,7 @@ decl_out(struct fd3_compile_context *ctx, struct tgsi_full_declaration *decl) { struct fd3_shader_stateobj *so = ctx->so; unsigned base = ctx->base_reg[TGSI_FILE_OUTPUT]; + unsigned comp = 0; unsigned name = decl->Semantic.Name; unsigned i; @@ -1351,6 +1352,8 @@ decl_out(struct fd3_compile_context *ctx, struct tgsi_full_declaration *decl) if (ctx->type == TGSI_PROCESSOR_VERTEX) { switch (name) { case TGSI_SEMANTIC_POSITION: + so->writes_pos = true; + /* fallthrough */ case TGSI_SEMANTIC_PSIZE: case TGSI_SEMANTIC_COLOR: case TGSI_SEMANTIC_GENERIC: @@ -1363,6 +1366,10 @@ decl_out(struct fd3_compile_context *ctx, struct tgsi_full_declaration *decl) } } else { switch (name) { + case TGSI_SEMANTIC_POSITION: + comp = 2; /* tgsi will write to .z component */ + so->writes_pos = true; + /* fallthrough */ case TGSI_SEMANTIC_COLOR: break; default: @@ -1374,7 +1381,7 @@ decl_out(struct fd3_compile_context *ctx, struct tgsi_full_declaration *decl) for (i = decl->Range.First; i <= decl->Range.Last; i++) { unsigned n = so->outputs_count++; so->outputs[n].semantic = decl_semantic(&decl->Semantic); - so->outputs[n].regid = regid(i + base, 0); + so->outputs[n].regid = regid(i + base, comp); } } diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_draw.c b/src/gallium/drivers/freedreno/a3xx/fd3_draw.c index 4f28b0e0608..a482aec3dec 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_draw.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_draw.c @@ -70,7 +70,7 @@ static void draw_impl(struct fd_context *ctx, const struct pipe_draw_info *info, struct fd_ringbuffer *ring, unsigned dirty, bool binning) { - fd3_emit_state(ctx, ring, dirty, binning); + fd3_emit_state(ctx, ring, &ctx->prog, dirty, binning); if (dirty & FD_DIRTY_VTXBUF) emit_vertexbufs(ctx, ring); @@ -114,10 +114,7 @@ fd3_clear_binning(struct fd_context *ctx, unsigned dirty) struct fd3_context *fd3_ctx = fd3_context(ctx); struct fd_ringbuffer *ring = ctx->binning_ring; - fd3_emit_state(ctx, ring, dirty & (FD_DIRTY_VIEWPORT | - FD_DIRTY_FRAMEBUFFER | FD_DIRTY_SCISSOR), true); - - fd3_program_emit(ring, &ctx->solid_prog, true); + fd3_emit_state(ctx, ring, &ctx->solid_prog, dirty, true); fd3_emit_vertex_bufs(ring, &ctx->solid_prog, (struct fd3_vertex_buf[]) { { .prsc = fd3_ctx->solid_vbuf, .stride = 12, .format = PIPE_FORMAT_R32G32B32_FLOAT }, @@ -152,11 +149,13 @@ fd3_clear(struct fd_context *ctx, unsigned buffers, unsigned dirty = ctx->dirty; unsigned ce, i; + dirty &= FD_DIRTY_VIEWPORT | FD_DIRTY_FRAMEBUFFER | FD_DIRTY_SCISSOR; + dirty |= FD_DIRTY_PROG; + fd3_clear_binning(ctx, dirty); /* emit generic state now: */ - fd3_emit_state(ctx, ring, dirty & (FD_DIRTY_VIEWPORT | - FD_DIRTY_FRAMEBUFFER | FD_DIRTY_SCISSOR), false); + fd3_emit_state(ctx, ring, &ctx->solid_prog, dirty, false); OUT_PKT0(ring, REG_A3XX_RB_BLEND_ALPHA, 1); OUT_RING(ring, A3XX_RB_BLEND_ALPHA_UINT(0xff) | @@ -246,8 +245,6 @@ fd3_clear(struct fd_context *ctx, unsigned buffers, OUT_PKT0(ring, REG_A3XX_GRAS_SU_MODE_CONTROL, 1); OUT_RING(ring, A3XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(0)); - fd3_program_emit(ring, &ctx->solid_prog, false); - fd3_emit_vertex_bufs(ring, &ctx->solid_prog, (struct fd3_vertex_buf[]) { { .prsc = fd3_ctx->solid_vbuf, .stride = 12, .format = PIPE_FORMAT_R32G32B32_FLOAT }, }, 1); diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c index 543c116ce2f..3ca49ff949b 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c @@ -338,7 +338,7 @@ fd3_emit_vertex_bufs(struct fd_ringbuffer *ring, void fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, - uint32_t dirty, bool binning) + struct fd_program_stateobj *prog, uint32_t dirty, bool binning) { emit_marker(ring, 5); @@ -370,9 +370,6 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, OUT_PKT0(ring, REG_A3XX_RB_ALPHA_REF, 1); OUT_RING(ring, zsa->rb_alpha_ref); - OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1); - OUT_RING(ring, zsa->rb_depth_control); - OUT_PKT0(ring, REG_A3XX_RB_STENCIL_CONTROL, 1); OUT_RING(ring, zsa->rb_stencil_control); @@ -383,6 +380,17 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, A3XX_RB_STENCILREFMASK_BF_STENCILREF(sr->ref_value[1])); } + if (dirty & (FD_DIRTY_ZSA | FD_DIRTY_PROG)) { + struct fd3_shader_stateobj *fp = prog->fp; + uint32_t val = fd3_zsa_stateobj(ctx->zsa)->rb_depth_control; + if (fp->writes_pos) { + val |= A3XX_RB_DEPTH_CONTROL_FRAG_WRITES_Z; + val |= A3XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE; + } + OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1); + OUT_RING(ring, val); + } + if (dirty & FD_DIRTY_RASTERIZER) { struct fd3_rasterizer_stateobj *rasterizer = fd3_rasterizer_stateobj(ctx->rasterizer); @@ -397,15 +405,23 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, OUT_PKT0(ring, REG_A3XX_GRAS_SU_POLY_OFFSET_SCALE, 2); OUT_RING(ring, rasterizer->gras_su_poly_offset_scale); OUT_RING(ring, rasterizer->gras_su_poly_offset_offset); + } + if (dirty & (FD_DIRTY_RASTERIZER | FD_DIRTY_PROG)) { + struct fd3_shader_stateobj *fp = prog->fp; + uint32_t val = fd3_rasterizer_stateobj(ctx->rasterizer) + ->gras_cl_clip_cntl; + if (fp->writes_pos) { + val |= A3XX_GRAS_CL_CLIP_CNTL_ZCLIP_DISABLE; + } OUT_PKT0(ring, REG_A3XX_GRAS_CL_CLIP_CNTL, 1); - OUT_RING(ring, rasterizer->gras_cl_clip_cntl); + OUT_RING(ring, val); } if (dirty & (FD_DIRTY_RASTERIZER | FD_DIRTY_PROG)) { struct fd3_rasterizer_stateobj *rasterizer = fd3_rasterizer_stateobj(ctx->rasterizer); - struct fd3_shader_stateobj *fp = ctx->prog.fp; + struct fd3_shader_stateobj *fp = prog->fp; uint32_t stride_in_vpc; stride_in_vpc = align(fp->total_in, 4) / 4; @@ -443,14 +459,14 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, } if (dirty & FD_DIRTY_PROG) - fd3_program_emit(ring, &ctx->prog, binning); + fd3_program_emit(ring, prog, binning); OUT_PKT3(ring, CP_EVENT_WRITE, 1); OUT_RING(ring, HLSQ_FLUSH); - if (dirty & (FD_DIRTY_PROG | FD_DIRTY_CONSTBUF)) { - struct fd_program_stateobj *prog = &ctx->prog; - + if ((dirty & (FD_DIRTY_PROG | FD_DIRTY_CONSTBUF)) && + /* evil hack to deal sanely with clear path: */ + (prog == &ctx->prog)) { emit_constants(ring, SB_VERT_SHADER, &ctx->constbuf[PIPE_SHADER_VERTEX], (prog->dirty & FD_SHADER_DIRTY_VP) ? prog->vp : NULL); @@ -459,7 +475,7 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, (prog->dirty & FD_SHADER_DIRTY_FP) ? prog->fp : NULL); } - if (dirty & FD_DIRTY_BLEND) { + if ((dirty & FD_DIRTY_BLEND) && ctx->blend) { struct fd3_blend_stateobj *blend = fd3_blend_stateobj(ctx->blend); uint32_t i; diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_emit.h b/src/gallium/drivers/freedreno/a3xx/fd3_emit.h index 1b4774d83f9..8584eb5b59b 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_emit.h +++ b/src/gallium/drivers/freedreno/a3xx/fd3_emit.h @@ -59,7 +59,7 @@ void fd3_emit_vertex_bufs(struct fd_ringbuffer *ring, struct fd_program_stateobj *prog, struct fd3_vertex_buf *vbufs, uint32_t n); void fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, - uint32_t dirty, bool binning); + struct fd_program_stateobj *prog, uint32_t dirty, bool binning); void fd3_emit_restore(struct fd_context *ctx); #endif /* FD3_EMIT_H */ diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_program.c b/src/gallium/drivers/freedreno/a3xx/fd3_program.c index 2d95583666d..3df29ecc911 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_program.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_program.c @@ -247,7 +247,7 @@ fd3_program_emit(struct fd_ringbuffer *ring, const struct fd3_shader_stateobj *fp = prog->fp; const struct ir3_shader_info *vsi = &vp->info; const struct ir3_shader_info *fsi = &fp->info; - uint32_t pos_regid, psize_regid, color_regid; + uint32_t pos_regid, posz_regid, psize_regid, color_regid; int i; if (binning) { @@ -259,6 +259,8 @@ fd3_program_emit(struct fd_ringbuffer *ring, pos_regid = find_regid(vp, fd3_semantic_name(TGSI_SEMANTIC_POSITION, 0)); + posz_regid = find_regid(fp, + fd3_semantic_name(TGSI_SEMANTIC_POSITION, 0)); psize_regid = find_regid(vp, fd3_semantic_name(TGSI_SEMANTIC_PSIZE, 0)); color_regid = find_regid(fp, @@ -389,7 +391,12 @@ fd3_program_emit(struct fd_ringbuffer *ring, OUT_RING(ring, 0x00000000); /* SP_FS_FLAT_SHAD_MODE_REG_1 */ OUT_PKT0(ring, REG_A3XX_SP_FS_OUTPUT_REG, 1); - OUT_RING(ring, 0x00000000); /* SP_FS_OUTPUT_REG */ + if (fp->writes_pos) { + OUT_RING(ring, A3XX_SP_FS_OUTPUT_REG_DEPTH_ENABLE | + A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID(posz_regid)); + } else { + OUT_RING(ring, 0x00000000); + } OUT_PKT0(ring, REG_A3XX_SP_FS_MRT_REG(0), 4); OUT_RING(ring, A3XX_SP_FS_MRT_REG_REGID(color_regid) | diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_program.h b/src/gallium/drivers/freedreno/a3xx/fd3_program.h index e7aaa476316..4aeeb2e3006 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_program.h +++ b/src/gallium/drivers/freedreno/a3xx/fd3_program.h @@ -81,6 +81,7 @@ struct fd3_shader_stateobj { fd3_semantic semantic; uint8_t regid; } outputs[16]; + bool writes_pos; /* vertices/inputs: */ unsigned inputs_count; diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index f36bd8be0cd..d6d3c6c3fd9 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -153,7 +153,6 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_TEXTURE_MIRROR_CLAMP: case PIPE_CAP_BLEND_EQUATION_SEPARATE: case PIPE_CAP_TEXTURE_SWIZZLE: - case PIPE_CAP_SHADER_STENCIL_EXPORT: case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: case PIPE_CAP_MIXED_COLORBUFFER_FORMATS: case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: @@ -176,6 +175,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_USER_CONSTANT_BUFFERS: return 1; + case PIPE_CAP_SHADER_STENCIL_EXPORT: case PIPE_CAP_TGSI_TEXCOORD: case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: return 0; -- 2.30.2