From: Eric Anholt Date: Tue, 1 Sep 2020 19:09:40 +0000 (-0700) Subject: freedreno/a6xx: Add ARB_depth_clamp and separate clamp support. X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=commitdiff_plain;h=0369dd907778d8636e2b074717846bb658d76d90 freedreno/a6xx: Add ARB_depth_clamp and separate clamp support. Passes piglit depth_clamp, depth-clamp-range, amd_depth_clamp_separate_range. This is part of enabling GL 3.2 (the other is bumping PIPE_CAP_GLSL_FEATURE_LEVEL, which I'm hoping to do once we have the KHR-GL* testing in place). Part-of: --- diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c index fc1ea40e5c5..ff441126e19 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c @@ -34,6 +34,7 @@ #include "freedreno_log.h" #include "freedreno_resource.h" +#include "freedreno_state.h" #include "freedreno_query_hw.h" #include "common/freedreno_guardband.h" @@ -823,13 +824,13 @@ fd6_emit_state(struct fd_ringbuffer *ring, struct fd6_emit *emit) fd6_emit_take_group(emit, state, FD6_GROUP_VBO, ENABLE_ALL); } - if (dirty & FD_DIRTY_ZSA) { - struct fd6_zsa_stateobj *zsa = fd6_zsa_stateobj(ctx->zsa); + if (dirty & (FD_DIRTY_ZSA | FD_DIRTY_RASTERIZER)) { + struct fd_ringbuffer *state = + fd6_zsa_state(ctx, + util_format_is_pure_integer(pipe_surface_format(pfb->cbufs[0])), + fd_depth_clamp_enabled(ctx)); - if (util_format_is_pure_integer(pipe_surface_format(pfb->cbufs[0]))) - fd6_emit_add_group(emit, zsa->stateobj_no_alpha, FD6_GROUP_ZSA, ENABLE_ALL); - else - fd6_emit_add_group(emit, zsa->stateobj, FD6_GROUP_ZSA, ENABLE_ALL); + fd6_emit_add_group(emit, state, FD6_GROUP_ZSA, ENABLE_ALL); } if (dirty & (FD_DIRTY_ZSA | FD_DIRTY_BLEND | FD_DIRTY_PROG)) { @@ -919,6 +920,24 @@ fd6_emit_state(struct fd_ringbuffer *ring, struct fd6_emit *emit) ); } + /* The clamp ranges are only used when the rasterizer wants depth + * clamping. + */ + if ((dirty & (FD_DIRTY_VIEWPORT | FD_DIRTY_RASTERIZER)) && + fd_depth_clamp_enabled(ctx)) { + float zmin, zmax; + util_viewport_zmin_zmax(&ctx->viewport, ctx->rasterizer->clip_halfz, + &zmin, &zmax); + + OUT_REG(ring, + A6XX_GRAS_CL_Z_CLAMP_MIN(0, zmin), + A6XX_GRAS_CL_Z_CLAMP_MAX(0, zmax)); + + OUT_REG(ring, + A6XX_RB_Z_CLAMP_MIN(zmin), + A6XX_RB_Z_CLAMP_MAX(zmax)); + } + if (dirty & FD_DIRTY_PROG) { fd6_emit_add_group(emit, prog->config_stateobj, FD6_GROUP_PROG_CONFIG, ENABLE_ALL); fd6_emit_add_group(emit, prog->stateobj, FD6_GROUP_PROG, ENABLE_DRAW); diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_rasterizer.c b/src/gallium/drivers/freedreno/a6xx/fd6_rasterizer.c index 33c96377a0a..1f6bf70d904 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_rasterizer.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_rasterizer.c @@ -53,6 +53,9 @@ __fd6_setup_rasterizer_stateobj(struct fd_context *ctx, OUT_REG(ring, A6XX_GRAS_CL_CNTL( + .znear_clip_disable = !cso->depth_clip_near, + .zfar_clip_disable = !cso->depth_clip_far, + .unk5 = !cso->depth_clip_near || !cso->depth_clip_far, .vp_clip_code_ignore = 1, .zero_gb_scale_z = cso->clip_halfz ), diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_zsa.c b/src/gallium/drivers/freedreno/a6xx/fd6_zsa.c index dc7c1fbf087..06625617118 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_zsa.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_zsa.c @@ -200,37 +200,26 @@ fd6_zsa_state_create(struct pipe_context *pctx, A6XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC(cso->alpha.func); } - so->stateobj = fd_ringbuffer_new_object(ctx->pipe, 9 * 4); - struct fd_ringbuffer *ring = so->stateobj; + for (int i = 0; i < 4; i++) { + struct fd_ringbuffer *ring = fd_ringbuffer_new_object(ctx->pipe, 9 * 4); - OUT_PKT4(ring, REG_A6XX_RB_ALPHA_CONTROL, 1); - OUT_RING(ring, so->rb_alpha_control); + OUT_PKT4(ring, REG_A6XX_RB_ALPHA_CONTROL, 1); + OUT_RING(ring, (i & FD6_ZSA_NO_ALPHA) ? so->rb_alpha_control : + so->rb_alpha_control & ~A6XX_RB_ALPHA_CONTROL_ALPHA_TEST); - OUT_PKT4(ring, REG_A6XX_RB_STENCIL_CONTROL, 1); - OUT_RING(ring, so->rb_stencil_control); + OUT_PKT4(ring, REG_A6XX_RB_STENCIL_CONTROL, 1); + OUT_RING(ring, so->rb_stencil_control); - OUT_PKT4(ring, REG_A6XX_RB_DEPTH_CNTL, 1); - OUT_RING(ring, so->rb_depth_cntl); + OUT_PKT4(ring, REG_A6XX_RB_DEPTH_CNTL, 1); + OUT_RING(ring, so->rb_depth_cntl | + COND(i & FD6_ZSA_DEPTH_CLAMP, A6XX_RB_DEPTH_CNTL_Z_CLAMP_ENABLE)); - OUT_PKT4(ring, REG_A6XX_RB_STENCILMASK, 2); - OUT_RING(ring, so->rb_stencilmask); - OUT_RING(ring, so->rb_stencilwrmask); + OUT_PKT4(ring, REG_A6XX_RB_STENCILMASK, 2); + OUT_RING(ring, so->rb_stencilmask); + OUT_RING(ring, so->rb_stencilwrmask); - so->stateobj_no_alpha = fd_ringbuffer_new_object(ctx->pipe, 9 * 4); - ring = so->stateobj_no_alpha; - - OUT_PKT4(ring, REG_A6XX_RB_ALPHA_CONTROL, 1); - OUT_RING(ring, so->rb_alpha_control & ~A6XX_RB_ALPHA_CONTROL_ALPHA_TEST); - - OUT_PKT4(ring, REG_A6XX_RB_STENCIL_CONTROL, 1); - OUT_RING(ring, so->rb_stencil_control); - - OUT_PKT4(ring, REG_A6XX_RB_DEPTH_CNTL, 1); - OUT_RING(ring, so->rb_depth_cntl); - - OUT_PKT4(ring, REG_A6XX_RB_STENCILMASK, 2); - OUT_RING(ring, so->rb_stencilmask); - OUT_RING(ring, so->rb_stencilwrmask); + so->stateobj[i] = ring; + } return so; } @@ -240,7 +229,7 @@ fd6_depth_stencil_alpha_state_delete(struct pipe_context *pctx, void *hwcso) { struct fd6_zsa_stateobj *so = hwcso; - fd_ringbuffer_del(so->stateobj); - fd_ringbuffer_del(so->stateobj_no_alpha); + for (int i = 0; i < ARRAY_SIZE(so->stateobj); i++) + fd_ringbuffer_del(so->stateobj[i]); FREE(hwcso); } diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_zsa.h b/src/gallium/drivers/freedreno/a6xx/fd6_zsa.h index 2d39797116b..b1c087e82cb 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_zsa.h +++ b/src/gallium/drivers/freedreno/a6xx/fd6_zsa.h @@ -36,6 +36,9 @@ #include "fd6_context.h" +#define FD6_ZSA_NO_ALPHA (1 << 0) +#define FD6_ZSA_DEPTH_CLAMP (1 << 1) + struct fd6_zsa_stateobj { struct pipe_depth_stencil_alpha_state base; @@ -49,8 +52,7 @@ struct fd6_zsa_stateobj { bool invalidate_lrz; bool alpha_test; - struct fd_ringbuffer *stateobj; - struct fd_ringbuffer *stateobj_no_alpha; + struct fd_ringbuffer *stateobj[4]; }; static inline struct fd6_zsa_stateobj * @@ -59,6 +61,17 @@ fd6_zsa_stateobj(struct pipe_depth_stencil_alpha_state *zsa) return (struct fd6_zsa_stateobj *)zsa; } +static inline struct fd_ringbuffer * +fd6_zsa_state(struct fd_context *ctx, bool no_alpha, bool depth_clamp) +{ + int variant = 0; + if (no_alpha) + variant |= FD6_ZSA_NO_ALPHA; + if (depth_clamp) + variant |= FD6_ZSA_DEPTH_CLAMP; + return fd6_zsa_stateobj(ctx->zsa)->stateobj[variant]; +} + void * fd6_zsa_state_create(struct pipe_context *pctx, const struct pipe_depth_stencil_alpha_state *cso); diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index f2b8eee9531..bea23999026 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -232,7 +232,6 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_PCI_BUS: case PIPE_CAP_PCI_DEVICE: case PIPE_CAP_PCI_FUNCTION: - case PIPE_CAP_DEPTH_CLIP_DISABLE_SEPARATE: return 0; case PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD: @@ -262,7 +261,10 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return is_a6xx(screen); case PIPE_CAP_DEPTH_CLIP_DISABLE: - return is_a3xx(screen) || is_a4xx(screen); + return is_a3xx(screen) || is_a4xx(screen) || is_a6xx(screen); + + case PIPE_CAP_DEPTH_CLIP_DISABLE_SEPARATE: + return is_a6xx(screen); case PIPE_CAP_POLYGON_OFFSET_CLAMP: return is_a4xx(screen) || is_a5xx(screen) || is_a6xx(screen); diff --git a/src/gallium/drivers/freedreno/freedreno_state.h b/src/gallium/drivers/freedreno/freedreno_state.h index 0d8d3368ad4..ac65c44921d 100644 --- a/src/gallium/drivers/freedreno/freedreno_state.h +++ b/src/gallium/drivers/freedreno/freedreno_state.h @@ -55,6 +55,11 @@ static inline bool fd_blend_enabled(struct fd_context *ctx, unsigned n) return ctx->blend && ctx->blend->rt[n].blend_enable; } +static inline bool fd_depth_clamp_enabled(struct fd_context *ctx) +{ + return !(ctx->rasterizer->depth_clip_near && ctx->rasterizer->depth_clip_far); +} + void fd_set_shader_images(struct pipe_context *pctx, enum pipe_shader_type shader, unsigned start, unsigned count,