mirror of https://gitlab.freedesktop.org/mesa/mesa
117 lines
4.4 KiB
C
117 lines
4.4 KiB
C
/*
|
|
* Copyright (C) 2022 Collabora, Ltd.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the next
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
* Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
|
|
#include "pan_earlyzs.h"
|
|
#include "panfrost/util/pan_ir.h"
|
|
|
|
/*
|
|
* Return an "early" mode. If it is known that the depth/stencil tests always
|
|
* pass (so the shader is always executed), weak early is usually faster than
|
|
* force early.
|
|
*/
|
|
static enum pan_earlyzs
|
|
best_early_mode(bool zs_always_passes)
|
|
{
|
|
if (zs_always_passes)
|
|
return PAN_EARLYZS_WEAK_EARLY;
|
|
else
|
|
return PAN_EARLYZS_FORCE_EARLY;
|
|
}
|
|
|
|
/*
|
|
* Analyze a fragment shader and provided API state to determine the early-ZS
|
|
* configuration. The order of arguments must match the order of states in the
|
|
* lookup table, synchronized with pan_earlyzs_get.
|
|
*/
|
|
static struct pan_earlyzs_state
|
|
analyze(const struct pan_shader_info *s, bool writes_zs_or_oq,
|
|
bool alpha_to_coverage, bool zs_always_passes)
|
|
{
|
|
/* If the shader writes depth or stencil, all depth/stencil tests must
|
|
* be deferred until the value is known after the ZS_EMIT instruction,
|
|
* if present. ZS_EMIT must precede ATEST, so the value is known when
|
|
* ATEST executes, justifying the late test/update.
|
|
*/
|
|
bool shader_writes_zs = (s->fs.writes_depth || s->fs.writes_stencil);
|
|
bool late_update = shader_writes_zs;
|
|
bool late_kill = shader_writes_zs;
|
|
|
|
/* Late coverage updates are required if the coverage mask depends on
|
|
* the results of the shader. Discards are implemented as coverage mask
|
|
* updates and must be considered. Strictly, depth/stencil writes may
|
|
* also update the coverage mask, but these already force late updates.
|
|
*/
|
|
bool late_coverage =
|
|
s->fs.writes_coverage || s->fs.can_discard || alpha_to_coverage;
|
|
|
|
/* Late coverage mask updates may affect the value written to the
|
|
* depth/stencil buffer (if a pixel is discarded entirely). However,
|
|
* they do not affect depth/stencil testing. So they may only matter if
|
|
* depth or stencil is written.
|
|
*
|
|
* That dependency does mean late coverage mask updates require late
|
|
* depth/stencil updates.
|
|
*
|
|
* Similarly, occlusion queries count samples that pass the
|
|
* depth/stencil tests, so occlusion queries with late coverage also
|
|
* require a late update.
|
|
*/
|
|
late_update |= (late_coverage && writes_zs_or_oq);
|
|
|
|
/* Side effects require late depth/stencil tests to ensure the shader
|
|
* isn't killed before the side effects execute.
|
|
*/
|
|
late_kill |= s->writes_global;
|
|
|
|
/* Finally, the shader may override and force early fragment tests */
|
|
late_update &= !s->fs.early_fragment_tests;
|
|
late_kill &= !s->fs.early_fragment_tests;
|
|
|
|
/* Collect results */
|
|
enum pan_earlyzs early_mode = best_early_mode(zs_always_passes);
|
|
|
|
return (struct pan_earlyzs_state){
|
|
.update = late_update ? PAN_EARLYZS_FORCE_LATE : early_mode,
|
|
.kill = late_kill ? PAN_EARLYZS_FORCE_LATE : early_mode,
|
|
};
|
|
}
|
|
|
|
/*
|
|
* Analyze a fragment shader to determine all possible early-ZS configurations.
|
|
* Returns a lookup table of configurations indexed by the API state.
|
|
*/
|
|
struct pan_earlyzs_lut
|
|
pan_earlyzs_analyze(const struct pan_shader_info *s)
|
|
{
|
|
struct pan_earlyzs_lut lut;
|
|
|
|
for (unsigned v0 = 0; v0 < 2; ++v0) {
|
|
for (unsigned v1 = 0; v1 < 2; ++v1) {
|
|
for (unsigned v2 = 0; v2 < 2; ++v2)
|
|
lut.states[v0][v1][v2] = analyze(s, v0, v1, v2);
|
|
}
|
|
}
|
|
|
|
return lut;
|
|
}
|