Path: blob/21.2-virgl/src/gallium/drivers/freedreno/a6xx/fd6_zsa.c
4574 views
/*1* Copyright (C) 2016 Rob Clark <[email protected]>2* Copyright © 2018 Google, Inc.3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the "Software"),6* to deal in the Software without restriction, including without limitation7* the rights to use, copy, modify, merge, publish, distribute, sublicense,8* and/or sell copies of the Software, and to permit persons to whom the9* Software is furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice (including the next12* paragraph) shall be included in all copies or substantial portions of the13* Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL18* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,20* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*23* Authors:24* Rob Clark <[email protected]>25*/2627#include "pipe/p_state.h"28#include "util/u_memory.h"29#include "util/u_string.h"3031#include "fd6_context.h"32#include "fd6_format.h"33#include "fd6_zsa.h"3435/* update lza state based on stencil-test func:36*37* Conceptually the order of the pipeline is:38*39*40* FS -> Alpha-Test -> Stencil-Test -> Depth-Test41* | |42* if wrmask != 0 if wrmask != 043* | |44* v v45* Stencil-Write Depth-Write46*47* Because Stencil-Test can have side effects (Stencil-Write) prior48* to depth test, in this case we potentially need to disable early49* lrz-test. See:50*51* https://www.khronos.org/opengl/wiki/Per-Sample_Processing52*/53static void54update_lrz_stencil(struct fd6_zsa_stateobj *so, enum pipe_compare_func func,55bool stencil_write)56{57switch (func) {58case PIPE_FUNC_ALWAYS:59/* nothing to do for LRZ, but for stencil test when stencil-60* write is enabled, we need to disable lrz-test, since61* conceptually stencil test and write happens before depth-62* test:63*/64if (stencil_write) {65so->lrz.enable = false;66so->lrz.test = false;67}68break;69case PIPE_FUNC_NEVER:70/* fragment never passes, disable lrz_write for this draw: */71so->lrz.write = false;72break;73default:74/* whether the fragment passes or not depends on result75* of stencil test, which we cannot know when doing binning76* pass:77*/78so->lrz.write = false;79/* similarly to the PIPE_FUNC_ALWAY case, if there are side-80* effects from stencil test we need to disable lrz-test.81*/82if (stencil_write) {83so->lrz.enable = false;84so->lrz.test = false;85}86break;87}88}8990void *91fd6_zsa_state_create(struct pipe_context *pctx,92const struct pipe_depth_stencil_alpha_state *cso)93{94struct fd_context *ctx = fd_context(pctx);95struct fd6_zsa_stateobj *so;9697so = CALLOC_STRUCT(fd6_zsa_stateobj);98if (!so)99return NULL;100101so->base = *cso;102103so->writes_zs = util_writes_depth_stencil(cso);104105so->rb_depth_cntl |=106A6XX_RB_DEPTH_CNTL_ZFUNC(cso->depth_func); /* maps 1:1 */107108if (cso->depth_enabled) {109so->rb_depth_cntl |=110A6XX_RB_DEPTH_CNTL_Z_ENABLE | A6XX_RB_DEPTH_CNTL_Z_TEST_ENABLE;111112so->lrz.test = true;113114if (cso->depth_writemask) {115so->lrz.write = true;116}117118switch (cso->depth_func) {119case PIPE_FUNC_LESS:120case PIPE_FUNC_LEQUAL:121so->lrz.enable = true;122so->lrz.direction = FD_LRZ_LESS;123break;124125case PIPE_FUNC_GREATER:126case PIPE_FUNC_GEQUAL:127so->lrz.enable = true;128so->lrz.direction = FD_LRZ_GREATER;129break;130131case PIPE_FUNC_NEVER:132so->lrz.enable = true;133so->lrz.write = false;134so->lrz.direction = FD_LRZ_LESS;135break;136137/* TODO revisit these: */138case PIPE_FUNC_EQUAL:139case PIPE_FUNC_NOTEQUAL:140case PIPE_FUNC_ALWAYS:141so->lrz.write = false;142so->invalidate_lrz = true;143break;144}145}146147if (cso->depth_writemask)148so->rb_depth_cntl |= A6XX_RB_DEPTH_CNTL_Z_WRITE_ENABLE;149150if (cso->stencil[0].enabled) {151const struct pipe_stencil_state *s = &cso->stencil[0];152153/* stencil test happens before depth test, so without performing154* stencil test we don't really know what the updates to the155* depth buffer will be.156*/157update_lrz_stencil(so, s->func, !!s->writemask);158159so->rb_stencil_control |=160A6XX_RB_STENCIL_CONTROL_STENCIL_READ |161A6XX_RB_STENCIL_CONTROL_STENCIL_ENABLE |162A6XX_RB_STENCIL_CONTROL_FUNC(s->func) | /* maps 1:1 */163A6XX_RB_STENCIL_CONTROL_FAIL(fd_stencil_op(s->fail_op)) |164A6XX_RB_STENCIL_CONTROL_ZPASS(fd_stencil_op(s->zpass_op)) |165A6XX_RB_STENCIL_CONTROL_ZFAIL(fd_stencil_op(s->zfail_op));166167so->rb_stencilmask = A6XX_RB_STENCILMASK_MASK(s->valuemask);168so->rb_stencilwrmask = A6XX_RB_STENCILWRMASK_WRMASK(s->writemask);169170if (cso->stencil[1].enabled) {171const struct pipe_stencil_state *bs = &cso->stencil[1];172173update_lrz_stencil(so, bs->func, !!bs->writemask);174175so->rb_stencil_control |=176A6XX_RB_STENCIL_CONTROL_STENCIL_ENABLE_BF |177A6XX_RB_STENCIL_CONTROL_FUNC_BF(bs->func) | /* maps 1:1 */178A6XX_RB_STENCIL_CONTROL_FAIL_BF(fd_stencil_op(bs->fail_op)) |179A6XX_RB_STENCIL_CONTROL_ZPASS_BF(fd_stencil_op(bs->zpass_op)) |180A6XX_RB_STENCIL_CONTROL_ZFAIL_BF(fd_stencil_op(bs->zfail_op));181182so->rb_stencilmask |= A6XX_RB_STENCILMASK_BFMASK(bs->valuemask);183so->rb_stencilwrmask |= A6XX_RB_STENCILWRMASK_BFWRMASK(bs->writemask);184}185}186187if (cso->alpha_enabled) {188/* Alpha test is functionally a conditional discard, so we can't189* write LRZ before seeing if we end up discarding or not190*/191if (cso->alpha_func != PIPE_FUNC_ALWAYS) {192so->lrz.write = false;193so->alpha_test = true;194}195196uint32_t ref = cso->alpha_ref_value * 255.0;197so->rb_alpha_control =198A6XX_RB_ALPHA_CONTROL_ALPHA_TEST |199A6XX_RB_ALPHA_CONTROL_ALPHA_REF(ref) |200A6XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC(cso->alpha_func);201}202203for (int i = 0; i < 4; i++) {204struct fd_ringbuffer *ring = fd_ringbuffer_new_object(ctx->pipe, 9 * 4);205206OUT_PKT4(ring, REG_A6XX_RB_ALPHA_CONTROL, 1);207OUT_RING(ring,208(i & FD6_ZSA_NO_ALPHA)209? so->rb_alpha_control & ~A6XX_RB_ALPHA_CONTROL_ALPHA_TEST210: so->rb_alpha_control);211212OUT_PKT4(ring, REG_A6XX_RB_STENCIL_CONTROL, 1);213OUT_RING(ring, so->rb_stencil_control);214215OUT_PKT4(ring, REG_A6XX_RB_DEPTH_CNTL, 1);216OUT_RING(ring,217so->rb_depth_cntl | COND(i & FD6_ZSA_DEPTH_CLAMP,218A6XX_RB_DEPTH_CNTL_Z_CLAMP_ENABLE));219220OUT_PKT4(ring, REG_A6XX_RB_STENCILMASK, 2);221OUT_RING(ring, so->rb_stencilmask);222OUT_RING(ring, so->rb_stencilwrmask);223224so->stateobj[i] = ring;225}226227return so;228}229230void231fd6_zsa_state_delete(struct pipe_context *pctx, void *hwcso)232{233struct fd6_zsa_stateobj *so = hwcso;234235for (int i = 0; i < ARRAY_SIZE(so->stateobj); i++)236fd_ringbuffer_del(so->stateobj[i]);237FREE(hwcso);238}239240241