13464ebd5Sriastradh/* 23464ebd5Sriastradh * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com> 33464ebd5Sriastradh * Copyright 2009 Marek Olšák <maraeo@gmail.com> 43464ebd5Sriastradh * 53464ebd5Sriastradh * Permission is hereby granted, free of charge, to any person obtaining a 63464ebd5Sriastradh * copy of this software and associated documentation files (the "Software"), 73464ebd5Sriastradh * to deal in the Software without restriction, including without limitation 83464ebd5Sriastradh * on the rights to use, copy, modify, merge, publish, distribute, sub 93464ebd5Sriastradh * license, and/or sell copies of the Software, and to permit persons to whom 103464ebd5Sriastradh * the Software is furnished to do so, subject to the following conditions: 113464ebd5Sriastradh * 123464ebd5Sriastradh * The above copyright notice and this permission notice (including the next 133464ebd5Sriastradh * paragraph) shall be included in all copies or substantial portions of the 143464ebd5Sriastradh * Software. 153464ebd5Sriastradh * 163464ebd5Sriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 173464ebd5Sriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 183464ebd5Sriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 193464ebd5Sriastradh * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 203464ebd5Sriastradh * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 213464ebd5Sriastradh * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 223464ebd5Sriastradh * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 233464ebd5Sriastradh 243464ebd5Sriastradh#include "r300_context.h" 253464ebd5Sriastradh#include "r300_reg.h" 263464ebd5Sriastradh#include "r300_fs.h" 273464ebd5Sriastradh 287ec681f3Smrg#include "util/format/u_format.h" 293464ebd5Sriastradh 303464ebd5Sriastradh/* 313464ebd5Sriastradh HiZ rules - taken from various docs 323464ebd5Sriastradh 1. HiZ only works on depth values 333464ebd5Sriastradh 2. Cannot HiZ if stencil fail or zfail is !KEEP 343464ebd5Sriastradh 3. on R300/400, HiZ is disabled if depth test is EQUAL 353464ebd5Sriastradh 4. comparison changes without clears usually mean disabling HiZ 363464ebd5Sriastradh*/ 373464ebd5Sriastradh/*****************************************************************************/ 383464ebd5Sriastradh/* The HyperZ setup */ 393464ebd5Sriastradh/*****************************************************************************/ 403464ebd5Sriastradh 413464ebd5Sriastradhstatic enum r300_hiz_func r300_get_hiz_func(struct r300_context *r300) 423464ebd5Sriastradh{ 433464ebd5Sriastradh struct r300_dsa_state *dsa = r300->dsa_state.state; 443464ebd5Sriastradh 457ec681f3Smrg switch (dsa->dsa.depth_func) { 463464ebd5Sriastradh case PIPE_FUNC_NEVER: 473464ebd5Sriastradh case PIPE_FUNC_EQUAL: 483464ebd5Sriastradh case PIPE_FUNC_NOTEQUAL: 493464ebd5Sriastradh case PIPE_FUNC_ALWAYS: 503464ebd5Sriastradh default: 513464ebd5Sriastradh /* Guess MAX for uncertain cases. */ 523464ebd5Sriastradh case PIPE_FUNC_LESS: 533464ebd5Sriastradh case PIPE_FUNC_LEQUAL: 543464ebd5Sriastradh return HIZ_FUNC_MAX; 553464ebd5Sriastradh 563464ebd5Sriastradh case PIPE_FUNC_GREATER: 573464ebd5Sriastradh case PIPE_FUNC_GEQUAL: 583464ebd5Sriastradh return HIZ_FUNC_MIN; 593464ebd5Sriastradh } 603464ebd5Sriastradh} 613464ebd5Sriastradh 623464ebd5Sriastradh/* Return what's used for the depth test (either minimum or maximum). */ 633464ebd5Sriastradhstatic unsigned r300_get_sc_hz_max(struct r300_context *r300) 643464ebd5Sriastradh{ 653464ebd5Sriastradh struct r300_dsa_state *dsa = r300->dsa_state.state; 667ec681f3Smrg unsigned func = dsa->dsa.depth_func; 673464ebd5Sriastradh 683464ebd5Sriastradh return func >= PIPE_FUNC_GREATER ? R300_SC_HYPERZ_MAX : R300_SC_HYPERZ_MIN; 693464ebd5Sriastradh} 703464ebd5Sriastradh 713464ebd5Sriastradhstatic boolean r300_is_hiz_func_valid(struct r300_context *r300) 723464ebd5Sriastradh{ 733464ebd5Sriastradh struct r300_dsa_state *dsa = r300->dsa_state.state; 747ec681f3Smrg unsigned func = dsa->dsa.depth_func; 753464ebd5Sriastradh 763464ebd5Sriastradh if (r300->hiz_func == HIZ_FUNC_NONE) 773464ebd5Sriastradh return TRUE; 783464ebd5Sriastradh 793464ebd5Sriastradh /* func1 is less/lessthan */ 803464ebd5Sriastradh if (r300->hiz_func == HIZ_FUNC_MAX && 813464ebd5Sriastradh (func == PIPE_FUNC_GEQUAL || func == PIPE_FUNC_GREATER)) 823464ebd5Sriastradh return FALSE; 833464ebd5Sriastradh 843464ebd5Sriastradh /* func1 is greater/greaterthan */ 853464ebd5Sriastradh if (r300->hiz_func == HIZ_FUNC_MIN && 863464ebd5Sriastradh (func == PIPE_FUNC_LESS || func == PIPE_FUNC_LEQUAL)) 873464ebd5Sriastradh return FALSE; 883464ebd5Sriastradh 893464ebd5Sriastradh return TRUE; 903464ebd5Sriastradh} 913464ebd5Sriastradh 923464ebd5Sriastradhstatic boolean r300_dsa_stencil_op_not_keep(struct pipe_stencil_state *s) 933464ebd5Sriastradh{ 943464ebd5Sriastradh return s->enabled && (s->fail_op != PIPE_STENCIL_OP_KEEP || 953464ebd5Sriastradh s->zfail_op != PIPE_STENCIL_OP_KEEP); 963464ebd5Sriastradh} 973464ebd5Sriastradh 983464ebd5Sriastradhstatic boolean r300_hiz_allowed(struct r300_context *r300) 993464ebd5Sriastradh{ 1003464ebd5Sriastradh struct r300_dsa_state *dsa = r300->dsa_state.state; 1013464ebd5Sriastradh struct r300_screen *r300screen = r300->screen; 1023464ebd5Sriastradh 1033464ebd5Sriastradh if (r300_fragment_shader_writes_depth(r300_fs(r300))) 1043464ebd5Sriastradh return FALSE; 1053464ebd5Sriastradh 1063464ebd5Sriastradh if (r300->query_current) 1073464ebd5Sriastradh return FALSE; 1083464ebd5Sriastradh 1093464ebd5Sriastradh /* If the depth function is inverted, HiZ must be disabled. */ 1103464ebd5Sriastradh if (!r300_is_hiz_func_valid(r300)) 1113464ebd5Sriastradh return FALSE; 1123464ebd5Sriastradh 1133464ebd5Sriastradh /* if stencil fail/zfail op is not KEEP */ 1143464ebd5Sriastradh if (r300_dsa_stencil_op_not_keep(&dsa->dsa.stencil[0]) || 1153464ebd5Sriastradh r300_dsa_stencil_op_not_keep(&dsa->dsa.stencil[1])) 1163464ebd5Sriastradh return FALSE; 1173464ebd5Sriastradh 1187ec681f3Smrg if (dsa->dsa.depth_enabled) { 1193464ebd5Sriastradh /* if depth func is EQUAL pre-r500 */ 1207ec681f3Smrg if (dsa->dsa.depth_func == PIPE_FUNC_EQUAL && !r300screen->caps.is_r500) 1213464ebd5Sriastradh return FALSE; 1223464ebd5Sriastradh 1233464ebd5Sriastradh /* if depth func is NOTEQUAL */ 1247ec681f3Smrg if (dsa->dsa.depth_func == PIPE_FUNC_NOTEQUAL) 1253464ebd5Sriastradh return FALSE; 1263464ebd5Sriastradh } 1273464ebd5Sriastradh return TRUE; 1283464ebd5Sriastradh} 1293464ebd5Sriastradh 1303464ebd5Sriastradhstatic void r300_update_hyperz(struct r300_context* r300) 1313464ebd5Sriastradh{ 1323464ebd5Sriastradh struct r300_hyperz_state *z = 1333464ebd5Sriastradh (struct r300_hyperz_state*)r300->hyperz_state.state; 1343464ebd5Sriastradh struct pipe_framebuffer_state *fb = 1353464ebd5Sriastradh (struct pipe_framebuffer_state*)r300->fb_state.state; 1363464ebd5Sriastradh struct r300_dsa_state *dsa = r300->dsa_state.state; 1373464ebd5Sriastradh struct r300_resource *zstex = 1383464ebd5Sriastradh fb->zsbuf ? r300_resource(fb->zsbuf->texture) : NULL; 1393464ebd5Sriastradh 1403464ebd5Sriastradh z->gb_z_peq_config = 0; 1413464ebd5Sriastradh z->zb_bw_cntl = 0; 1423464ebd5Sriastradh z->sc_hyperz = R300_SC_HYPERZ_ADJ_2; 1433464ebd5Sriastradh z->flush = 0; 1443464ebd5Sriastradh 1453464ebd5Sriastradh if (r300->cbzb_clear) { 1463464ebd5Sriastradh z->zb_bw_cntl |= R300_ZB_CB_CLEAR_CACHE_LINE_WRITE_ONLY; 1473464ebd5Sriastradh return; 1483464ebd5Sriastradh } 1493464ebd5Sriastradh 1503464ebd5Sriastradh if (!zstex || !r300->hyperz_enabled) 1513464ebd5Sriastradh return; 1523464ebd5Sriastradh 1533464ebd5Sriastradh /* Set the size of ZMASK tiles. */ 1543464ebd5Sriastradh if (zstex->tex.zcomp8x8[fb->zsbuf->u.tex.level]) { 1553464ebd5Sriastradh z->gb_z_peq_config |= R300_GB_Z_PEQ_CONFIG_Z_PEQ_SIZE_8_8; 1563464ebd5Sriastradh } 1573464ebd5Sriastradh 1583464ebd5Sriastradh /* R500-specific features and optimizations. */ 1593464ebd5Sriastradh if (r300->screen->caps.is_r500) { 1603464ebd5Sriastradh z->zb_bw_cntl |= R500_PEQ_PACKING_ENABLE | 1613464ebd5Sriastradh R500_COVERED_PTR_MASKING_ENABLE; 1623464ebd5Sriastradh } 1633464ebd5Sriastradh 1643464ebd5Sriastradh /* Setup decompression if needed. No other HyperZ setting is required. */ 1653464ebd5Sriastradh if (r300->zmask_decompress) { 1663464ebd5Sriastradh z->zb_bw_cntl |= R300_FAST_FILL_ENABLE | 1673464ebd5Sriastradh R300_RD_COMP_ENABLE; 1683464ebd5Sriastradh return; 1693464ebd5Sriastradh } 1703464ebd5Sriastradh 1713464ebd5Sriastradh /* Do not set anything if depth and stencil tests are off. */ 1727ec681f3Smrg if (!dsa->dsa.depth_enabled && 1733464ebd5Sriastradh !dsa->dsa.stencil[0].enabled && 1743464ebd5Sriastradh !dsa->dsa.stencil[1].enabled) { 1757ec681f3Smrg assert(!dsa->dsa.depth_writemask); 1763464ebd5Sriastradh return; 1773464ebd5Sriastradh } 1783464ebd5Sriastradh 1793464ebd5Sriastradh /* Zbuffer compression. */ 1803464ebd5Sriastradh if (r300->zmask_in_use && !r300->locked_zbuffer) { 1813464ebd5Sriastradh z->zb_bw_cntl |= R300_FAST_FILL_ENABLE | 1823464ebd5Sriastradh R300_RD_COMP_ENABLE | 1833464ebd5Sriastradh R300_WR_COMP_ENABLE; 1843464ebd5Sriastradh } 1853464ebd5Sriastradh 1863464ebd5Sriastradh /* HiZ. */ 1873464ebd5Sriastradh if (r300->hiz_in_use && !r300->locked_zbuffer) { 1883464ebd5Sriastradh /* HiZ cannot be used under some circumstances. */ 1893464ebd5Sriastradh if (!r300_hiz_allowed(r300)) { 1903464ebd5Sriastradh /* If writemask is disabled, the HiZ memory will not be changed, 1913464ebd5Sriastradh * so we can keep its content for later. */ 1927ec681f3Smrg if (dsa->dsa.depth_writemask) { 1933464ebd5Sriastradh r300->hiz_in_use = FALSE; 1943464ebd5Sriastradh } 1953464ebd5Sriastradh return; 1963464ebd5Sriastradh } 1977ec681f3Smrg DBG(r300, DBG_HYPERZ, "r300: Z-func: %i\n", dsa->dsa.depth_func); 1983464ebd5Sriastradh 1993464ebd5Sriastradh /* Set the HiZ function if needed. */ 2003464ebd5Sriastradh if (r300->hiz_func == HIZ_FUNC_NONE) { 2013464ebd5Sriastradh r300->hiz_func = r300_get_hiz_func(r300); 2023464ebd5Sriastradh } 2033464ebd5Sriastradh 2043464ebd5Sriastradh /* Setup the HiZ bits. */ 2053464ebd5Sriastradh z->zb_bw_cntl |= R300_HIZ_ENABLE | 2063464ebd5Sriastradh (r300->hiz_func == HIZ_FUNC_MIN ? R300_HIZ_MIN : R300_HIZ_MAX); 2073464ebd5Sriastradh 2083464ebd5Sriastradh z->sc_hyperz |= R300_SC_HYPERZ_ENABLE | 2093464ebd5Sriastradh r300_get_sc_hz_max(r300); 2103464ebd5Sriastradh 2113464ebd5Sriastradh if (r300->screen->caps.is_r500) { 2123464ebd5Sriastradh z->zb_bw_cntl |= R500_HIZ_EQUAL_REJECT_ENABLE; 2133464ebd5Sriastradh } 2143464ebd5Sriastradh } 2153464ebd5Sriastradh} 2163464ebd5Sriastradh 2173464ebd5Sriastradh/*****************************************************************************/ 2183464ebd5Sriastradh/* The ZTOP state */ 2193464ebd5Sriastradh/*****************************************************************************/ 2203464ebd5Sriastradh 2213464ebd5Sriastradhstatic boolean r300_dsa_alpha_test_enabled( 2223464ebd5Sriastradh struct pipe_depth_stencil_alpha_state *dsa) 2233464ebd5Sriastradh{ 2243464ebd5Sriastradh /* We are interested only in the cases when alpha testing can kill 2253464ebd5Sriastradh * a fragment. */ 2263464ebd5Sriastradh 2277ec681f3Smrg return dsa->alpha_enabled && dsa->alpha_func != PIPE_FUNC_ALWAYS; 2283464ebd5Sriastradh} 2293464ebd5Sriastradh 2303464ebd5Sriastradhstatic void r300_update_ztop(struct r300_context* r300) 2313464ebd5Sriastradh{ 2323464ebd5Sriastradh struct r300_ztop_state* ztop_state = 2333464ebd5Sriastradh (struct r300_ztop_state*)r300->ztop_state.state; 2343464ebd5Sriastradh uint32_t old_ztop = ztop_state->z_buffer_top; 2353464ebd5Sriastradh 2363464ebd5Sriastradh /* This is important enough that I felt it warranted a comment. 2373464ebd5Sriastradh * 2383464ebd5Sriastradh * According to the docs, these are the conditions where ZTOP must be 2393464ebd5Sriastradh * disabled: 2403464ebd5Sriastradh * 1) Alpha testing enabled 2413464ebd5Sriastradh * 2) Texture kill instructions in fragment shader 2423464ebd5Sriastradh * 3) Chroma key culling enabled 2433464ebd5Sriastradh * 4) W-buffering enabled 2443464ebd5Sriastradh * 2453464ebd5Sriastradh * The docs claim that for the first three cases, if no ZS writes happen, 2463464ebd5Sriastradh * then ZTOP can be used. 2473464ebd5Sriastradh * 2483464ebd5Sriastradh * (3) will never apply since we do not support chroma-keyed operations. 2493464ebd5Sriastradh * (4) will need to be re-examined (and this comment updated) if/when 2503464ebd5Sriastradh * Hyper-Z becomes supported. 2513464ebd5Sriastradh * 2523464ebd5Sriastradh * Additionally, the following conditions require disabled ZTOP: 2533464ebd5Sriastradh * 5) Depth writes in fragment shader 2543464ebd5Sriastradh * 6) Outstanding occlusion queries 2553464ebd5Sriastradh * 2563464ebd5Sriastradh * This register causes stalls all the way from SC to CB when changed, 2573464ebd5Sriastradh * but it is buffered on-chip so it does not hurt to write it if it has 2583464ebd5Sriastradh * not changed. 2593464ebd5Sriastradh * 2603464ebd5Sriastradh * ~C. 2613464ebd5Sriastradh */ 2623464ebd5Sriastradh 2633464ebd5Sriastradh /* ZS writes */ 2647ec681f3Smrg if (util_writes_depth_stencil(r300->dsa_state.state) && 2653464ebd5Sriastradh (r300_dsa_alpha_test_enabled(r300->dsa_state.state) || /* (1) */ 2663464ebd5Sriastradh r300_fs(r300)->shader->info.uses_kill)) { /* (2) */ 2673464ebd5Sriastradh ztop_state->z_buffer_top = R300_ZTOP_DISABLE; 2683464ebd5Sriastradh } else if (r300_fragment_shader_writes_depth(r300_fs(r300))) { /* (5) */ 2693464ebd5Sriastradh ztop_state->z_buffer_top = R300_ZTOP_DISABLE; 2703464ebd5Sriastradh } else if (r300->query_current) { /* (6) */ 2713464ebd5Sriastradh ztop_state->z_buffer_top = R300_ZTOP_DISABLE; 2723464ebd5Sriastradh } else { 2733464ebd5Sriastradh ztop_state->z_buffer_top = R300_ZTOP_ENABLE; 2743464ebd5Sriastradh } 2753464ebd5Sriastradh if (ztop_state->z_buffer_top != old_ztop) 2763464ebd5Sriastradh r300_mark_atom_dirty(r300, &r300->ztop_state); 2773464ebd5Sriastradh} 2783464ebd5Sriastradh 2793464ebd5Sriastradhvoid r300_update_hyperz_state(struct r300_context* r300) 2803464ebd5Sriastradh{ 2813464ebd5Sriastradh r300_update_ztop(r300); 2823464ebd5Sriastradh 2833464ebd5Sriastradh if (r300->hyperz_state.dirty) { 2843464ebd5Sriastradh r300_update_hyperz(r300); 2853464ebd5Sriastradh } 2863464ebd5Sriastradh} 287