r300_hyperz.c revision f9e8cdc145fc0ba1f6c47e20860add6528387c7c
1/*
2 * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
3 * Copyright 2009 Marek Olšák <maraeo@gmail.com>
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
23
24#include "r300_context.h"
25#include "r300_hyperz.h"
26#include "r300_reg.h"
27#include "r300_fs.h"
28
29/*****************************************************************************/
30/* The ZTOP state                                                            */
31/*****************************************************************************/
32
33static boolean r300_dsa_writes_stencil(
34        struct pipe_stencil_state *s)
35{
36    return s->enabled && s->writemask &&
37           (s->fail_op  != PIPE_STENCIL_OP_KEEP ||
38            s->zfail_op != PIPE_STENCIL_OP_KEEP ||
39            s->zpass_op != PIPE_STENCIL_OP_KEEP);
40}
41
42static boolean r300_dsa_writes_depth_stencil(
43        struct pipe_depth_stencil_alpha_state *dsa)
44{
45    /* We are interested only in the cases when a depth or stencil value
46     * can be changed. */
47
48    if (dsa->depth.enabled && dsa->depth.writemask &&
49        dsa->depth.func != PIPE_FUNC_NEVER)
50        return TRUE;
51
52    if (r300_dsa_writes_stencil(&dsa->stencil[0]) ||
53        r300_dsa_writes_stencil(&dsa->stencil[1]))
54        return TRUE;
55
56    return FALSE;
57}
58
59static boolean r300_dsa_alpha_test_enabled(
60        struct pipe_depth_stencil_alpha_state *dsa)
61{
62    /* We are interested only in the cases when alpha testing can kill
63     * a fragment. */
64
65    return dsa->alpha.enabled && dsa->alpha.func != PIPE_FUNC_ALWAYS;
66}
67
68static void r300_update_ztop(struct r300_context* r300)
69{
70    struct r300_ztop_state* ztop_state =
71        (struct r300_ztop_state*)r300->ztop_state.state;
72    uint32_t old_ztop = ztop_state->z_buffer_top;
73
74    /* This is important enough that I felt it warranted a comment.
75     *
76     * According to the docs, these are the conditions where ZTOP must be
77     * disabled:
78     * 1) Alpha testing enabled
79     * 2) Texture kill instructions in fragment shader
80     * 3) Chroma key culling enabled
81     * 4) W-buffering enabled
82     *
83     * The docs claim that for the first three cases, if no ZS writes happen,
84     * then ZTOP can be used.
85     *
86     * (3) will never apply since we do not support chroma-keyed operations.
87     * (4) will need to be re-examined (and this comment updated) if/when
88     * Hyper-Z becomes supported.
89     *
90     * Additionally, the following conditions require disabled ZTOP:
91     * 5) Depth writes in fragment shader
92     * 6) Outstanding occlusion queries
93     *
94     * This register causes stalls all the way from SC to CB when changed,
95     * but it is buffered on-chip so it does not hurt to write it if it has
96     * not changed.
97     *
98     * ~C.
99     */
100
101    /* ZS writes */
102    if (r300_dsa_writes_depth_stencil(r300->dsa_state.state) &&
103           (r300_dsa_alpha_test_enabled(r300->dsa_state.state) ||  /* (1) */
104            r300_fs(r300)->shader->info.uses_kill)) {              /* (2) */
105        ztop_state->z_buffer_top = R300_ZTOP_DISABLE;
106    } else if (r300_fragment_shader_writes_depth(r300_fs(r300))) { /* (5) */
107        ztop_state->z_buffer_top = R300_ZTOP_DISABLE;
108    } else if (r300->query_current) {                              /* (6) */
109        ztop_state->z_buffer_top = R300_ZTOP_DISABLE;
110    } else {
111        ztop_state->z_buffer_top = R300_ZTOP_ENABLE;
112    }
113
114    if (ztop_state->z_buffer_top != old_ztop)
115        r300->ztop_state.dirty = TRUE;
116}
117
118void r300_update_hyperz_state(struct r300_context* r300)
119{
120    r300_update_ztop(r300);
121}
122