mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-12 10:00:17 +01:00
draw,llvmpipe,util: add depth bias calculation for arb_depth_buffer_float
With this patch, the llvmpipe and draw modules will calculate the depth bias according to floating point depth buffer semantics described in the arb_depth_buffer_float specification, when the driver has a z buffer bound with a format type of UTIL_FORMAT_TYPE_FLOAT. By default, the driver will use the existing UNORM calculation for depth bias. A new function, draw_set_zs_format, was added to calculate the Minimum Resolvable Depth value and floating point depth sense for the draw module. Reviewed-by: Jose Fonseca <jfonseca@vmware.com> Reviewed-by: Roland Scheidegger <sroland@vmware.com>
This commit is contained in:
parent
185b5a54c9
commit
f9e2c24326
14 changed files with 182 additions and 56 deletions
|
|
@ -38,6 +38,7 @@
|
|||
#include "util/u_inlines.h"
|
||||
#include "util/u_helpers.h"
|
||||
#include "util/u_prim.h"
|
||||
#include "util/u_format.h"
|
||||
#include "draw_context.h"
|
||||
#include "draw_pipe.h"
|
||||
#include "draw_prim_assembler.h"
|
||||
|
|
@ -164,6 +165,8 @@ boolean draw_init(struct draw_context *draw)
|
|||
draw->quads_always_flatshade_last = !draw->pipe->screen->get_param(
|
||||
draw->pipe->screen, PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION);
|
||||
|
||||
draw->floating_point_depth = false;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -233,15 +236,20 @@ void draw_flush( struct draw_context *draw )
|
|||
|
||||
|
||||
/**
|
||||
* Specify the Minimum Resolvable Depth factor for polygon offset.
|
||||
* Specify the depth stencil format for the draw pipeline. This function
|
||||
* determines the Minimum Resolvable Depth factor for polygon offset.
|
||||
* This factor potentially depends on the number of Z buffer bits,
|
||||
* the rasterization algorithm and the arithmetic performed on Z
|
||||
* values between vertex shading and rasterization. It will vary
|
||||
* from one driver to another.
|
||||
* values between vertex shading and rasterization.
|
||||
*/
|
||||
void draw_set_mrd(struct draw_context *draw, double mrd)
|
||||
void draw_set_zs_format(struct draw_context *draw, enum pipe_format format)
|
||||
{
|
||||
draw->mrd = mrd;
|
||||
const struct util_format_description *desc = util_format_description(format);
|
||||
|
||||
draw->floating_point_depth =
|
||||
(util_get_depth_format_type(desc) == UTIL_FORMAT_TYPE_FLOAT);
|
||||
|
||||
draw->mrd = util_get_depth_format_mrd(desc);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ void draw_enable_line_stipple(struct draw_context *draw, boolean enable);
|
|||
|
||||
void draw_enable_point_sprites(struct draw_context *draw, boolean enable);
|
||||
|
||||
void draw_set_mrd(struct draw_context *draw, double mrd);
|
||||
void draw_set_zs_format(struct draw_context *draw, enum pipe_format format);
|
||||
|
||||
boolean
|
||||
draw_install_aaline_stage(struct draw_context *draw, struct pipe_context *pipe);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
* \author Brian Paul
|
||||
*/
|
||||
|
||||
#include "util/u_format.h"
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "draw_pipe.h"
|
||||
|
|
@ -89,7 +90,22 @@ static void do_offset_tri( struct draw_stage *stage,
|
|||
float dzdx = fabsf(a * inv_det);
|
||||
float dzdy = fabsf(b * inv_det);
|
||||
|
||||
float zoffset = offset->units + MAX2(dzdx, dzdy) * offset->scale;
|
||||
float zoffset, maxz, bias, mult;
|
||||
|
||||
mult = MAX2(dzdx, dzdy) * offset->scale;
|
||||
|
||||
if (stage->draw->floating_point_depth) {
|
||||
maxz = MAX3(v0[2], v1[2], v2[2]);
|
||||
|
||||
/**
|
||||
* XXX: TODO optimize this to quickly resolve a pow2 number through
|
||||
* an exponent only operation.
|
||||
*/
|
||||
bias = offset->units * util_fast_exp2(util_get_float32_exponent(maxz) - 23);
|
||||
zoffset = bias + mult;
|
||||
} else {
|
||||
zoffset = offset->units + mult;
|
||||
}
|
||||
|
||||
if (offset->clamp)
|
||||
zoffset = (offset->clamp < 0.0f) ? MAX2(zoffset, offset->clamp) :
|
||||
|
|
@ -157,7 +173,17 @@ static void offset_first_tri( struct draw_stage *stage,
|
|||
if (do_offset) {
|
||||
offset->scale = rast->offset_scale;
|
||||
offset->clamp = rast->offset_clamp;
|
||||
offset->units = (float) (rast->offset_units * stage->draw->mrd);
|
||||
|
||||
/*
|
||||
* If depth is floating point, depth bias is calculated with respect
|
||||
* to the primitive's maximum Z value. Retain the original depth bias
|
||||
* value until that stage.
|
||||
*/
|
||||
if (stage->draw->floating_point_depth) {
|
||||
offset->units = (float) rast->offset_units;
|
||||
} else {
|
||||
offset->units = (float) (rast->offset_units * stage->draw->mrd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
offset->scale = 0.0f;
|
||||
|
|
|
|||
|
|
@ -236,6 +236,8 @@ struct draw_context
|
|||
|
||||
boolean dump_vs;
|
||||
|
||||
/** Depth format and bias related settings. */
|
||||
boolean floating_point_depth;
|
||||
double mrd; /**< minimum resolvable depth value, for polygon offset */
|
||||
|
||||
/** Current rasterizer state given to us by the driver */
|
||||
|
|
|
|||
|
|
@ -215,9 +215,8 @@ util_format_is_supported(enum pipe_format format, unsigned bind)
|
|||
* default MRD will be 1.0 / ((1 << 24) - 1).
|
||||
*/
|
||||
double
|
||||
util_get_depth_format_mrd(enum pipe_format format)
|
||||
util_get_depth_format_mrd(const struct util_format_description *desc)
|
||||
{
|
||||
struct util_format_description *format_desc;
|
||||
/*
|
||||
* Depth buffer formats without a depth component OR scenarios
|
||||
* without a bound depth buffer default to D24.
|
||||
|
|
@ -225,23 +224,20 @@ util_get_depth_format_mrd(enum pipe_format format)
|
|||
double mrd = 1.0 / ((1 << 24) - 1);
|
||||
unsigned depth_channel;
|
||||
|
||||
format_desc = (struct util_format_description *)
|
||||
util_format_description(format);
|
||||
|
||||
assert(format_desc);
|
||||
assert(desc);
|
||||
|
||||
/*
|
||||
* Some depth formats do not store the depth component in the first
|
||||
* channel, detect the format and adjust the depth channel. Get the
|
||||
* swizzled depth component channel.
|
||||
*/
|
||||
depth_channel = format_desc->swizzle[0];
|
||||
depth_channel = desc->swizzle[0];
|
||||
|
||||
if (format_desc->channel[depth_channel].type == UTIL_FORMAT_TYPE_UNSIGNED &&
|
||||
format_desc->channel[depth_channel].normalized) {
|
||||
if (desc->channel[depth_channel].type == UTIL_FORMAT_TYPE_UNSIGNED &&
|
||||
desc->channel[depth_channel].normalized) {
|
||||
int depth_bits;
|
||||
|
||||
depth_bits = format_desc->channel[depth_channel].size;
|
||||
depth_bits = desc->channel[depth_channel].size;
|
||||
mrd = 1.0 / ((1ULL << depth_bits) - 1);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -545,6 +545,22 @@ util_format_is_depth_and_stencil(enum pipe_format format)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the depth format type based upon the incoming format description.
|
||||
*/
|
||||
static INLINE unsigned
|
||||
util_get_depth_format_type(const struct util_format_description *desc)
|
||||
{
|
||||
unsigned depth_channel = desc->swizzle[0];
|
||||
if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS &&
|
||||
depth_channel != UTIL_FORMAT_SWIZZLE_NONE) {
|
||||
return desc->channel[depth_channel].type;
|
||||
} else {
|
||||
return UTIL_FORMAT_TYPE_VOID;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the MRD for the depth format. MRD is used in depth bias
|
||||
* for UNORM and unbound depth buffers. When the depth buffer is floating
|
||||
|
|
@ -552,7 +568,7 @@ util_format_is_depth_and_stencil(enum pipe_format format)
|
|||
* default MRD will be 1.0 / ((1 << 24) - 1).
|
||||
*/
|
||||
double
|
||||
util_get_depth_format_mrd(enum pipe_format format);
|
||||
util_get_depth_format_mrd(const struct util_format_description *desc);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -245,6 +245,19 @@ union di {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Extract the IEEE float32 exponent.
|
||||
*/
|
||||
static INLINE signed
|
||||
util_get_float32_exponent(float x) {
|
||||
union fi f;
|
||||
|
||||
f.f = x;
|
||||
|
||||
return ((f.ui >> 23) & 0xff) - 127;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fast version of 2^x
|
||||
* Identity: exp2(a + b) = exp2(a) * exp2(b)
|
||||
|
|
|
|||
|
|
@ -124,9 +124,10 @@ struct llvmpipe_context {
|
|||
/** A fake frontface output for unfilled primitives */
|
||||
int face_slot;
|
||||
|
||||
/**< minimum resolvable depth value, for polygon offset */
|
||||
double mrd;
|
||||
|
||||
/** Depth format and bias settings. */
|
||||
boolean floating_point_depth;
|
||||
double mrd; /**< minimum resolvable depth value, for polygon offset */
|
||||
|
||||
/** The tiling engine */
|
||||
struct lp_setup_context *setup;
|
||||
struct lp_setup_variant setup_variant;
|
||||
|
|
|
|||
|
|
@ -186,7 +186,8 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
|
|||
llvmpipe_update_fs( llvmpipe );
|
||||
|
||||
if (llvmpipe->dirty & (LP_NEW_FS |
|
||||
LP_NEW_RASTERIZER))
|
||||
LP_NEW_FRAMEBUFFER |
|
||||
LP_NEW_RASTERIZER))
|
||||
llvmpipe_update_setup( llvmpipe );
|
||||
|
||||
if (llvmpipe->dirty & LP_NEW_BLEND_COLOR)
|
||||
|
|
|
|||
|
|
@ -256,6 +256,7 @@ lp_do_offset_tri(struct gallivm_state *gallivm,
|
|||
LLVMBuilderRef b = gallivm->builder;
|
||||
struct lp_build_context bld;
|
||||
struct lp_build_context flt_scalar_bld;
|
||||
struct lp_build_context int_scalar_bld;
|
||||
LLVMValueRef zoffset, mult;
|
||||
LLVMValueRef z0_new, z1_new, z2_new;
|
||||
LLVMValueRef dzdxdzdy, dzdx, dzdy, dzxyz20, dyzzx01, dyzzx01_dzxyz20, dzx01_dyz20;
|
||||
|
|
@ -267,6 +268,8 @@ lp_do_offset_tri(struct gallivm_state *gallivm,
|
|||
LLVMValueRef zeroi = lp_build_const_int32(gallivm, 0);
|
||||
LLVMValueRef twoi = lp_build_const_int32(gallivm, 2);
|
||||
LLVMValueRef threei = lp_build_const_int32(gallivm, 3);
|
||||
LLVMValueRef mantissa_bits, exp, bias;
|
||||
LLVMValueRef maxz_value, maxz0z1_value;
|
||||
|
||||
/* (res12) = cross(e,f).xy */
|
||||
shuffles[0] = twoi;
|
||||
|
|
@ -300,17 +303,56 @@ lp_do_offset_tri(struct gallivm_state *gallivm,
|
|||
dzdx = LLVMBuildExtractElement(b, dzdxdzdy, zeroi, "");
|
||||
dzdy = LLVMBuildExtractElement(b, dzdxdzdy, onei, "");
|
||||
|
||||
/* zoffset = pgon_offset_units + MAX2(dzdx, dzdy) * pgon_offset_scale */
|
||||
/* mult = MAX2(dzdx, dzdy) * pgon_offset_scale */
|
||||
max = LLVMBuildFCmp(b, LLVMRealUGT, dzdx, dzdy, "");
|
||||
max_value = LLVMBuildSelect(b, max, dzdx, dzdy, "max");
|
||||
|
||||
mult = LLVMBuildFMul(b, max_value,
|
||||
lp_build_const_float(gallivm, key->pgon_offset_scale), "");
|
||||
zoffset = LLVMBuildFAdd(b,
|
||||
lp_build_const_float(gallivm, key->pgon_offset_units),
|
||||
mult, "zoffset");
|
||||
|
||||
lp_build_context_init(&flt_scalar_bld, gallivm, lp_type_float_vec(32, 32));
|
||||
|
||||
if (key->floating_point_depth) {
|
||||
/*
|
||||
* bias = pgon_offset_units * 2^(exponent(max(z0, z1, z2)) - mantissa_bits) +
|
||||
* MAX2(dzdx, dzdy) * pgon_offset_scale
|
||||
*
|
||||
* NOTE: Assumes IEEE float32.
|
||||
*/
|
||||
lp_build_context_init(&int_scalar_bld, gallivm, lp_type_int_vec(32, 32));
|
||||
|
||||
mantissa_bits = lp_build_const_int32(gallivm, 23);
|
||||
|
||||
maxz0z1_value = lp_build_max(&flt_scalar_bld,
|
||||
LLVMBuildExtractElement(b, attribv[0], twoi, ""),
|
||||
LLVMBuildExtractElement(b, attribv[1], twoi, ""));
|
||||
|
||||
maxz_value = lp_build_max(&flt_scalar_bld,
|
||||
LLVMBuildExtractElement(b, attribv[2], twoi, ""),
|
||||
maxz0z1_value);
|
||||
|
||||
/**
|
||||
* XXX: TODO optimize this to quickly resolve a pow2 number through
|
||||
* an exponent only operation.
|
||||
*/
|
||||
exp = lp_build_extract_exponent(&flt_scalar_bld, maxz_value, 0);
|
||||
exp = lp_build_sub(&int_scalar_bld, exp, mantissa_bits);
|
||||
exp = lp_build_int_to_float(&flt_scalar_bld, exp);
|
||||
|
||||
bias = LLVMBuildFMul(b, lp_build_exp2(&flt_scalar_bld, exp),
|
||||
lp_build_const_float(gallivm, key->pgon_offset_units),
|
||||
"bias");
|
||||
|
||||
zoffset = LLVMBuildFAdd(b, bias, mult, "zoffset");
|
||||
} else {
|
||||
/*
|
||||
* bias = pgon_offset_units + MAX2(dzdx, dzdy) * pgon_offset_scale
|
||||
*/
|
||||
zoffset = LLVMBuildFAdd(b,
|
||||
lp_build_const_float(gallivm, key->pgon_offset_units),
|
||||
mult, "zoffset");
|
||||
}
|
||||
|
||||
if (key->pgon_offset_clamp > 0) {
|
||||
zoffset = lp_build_min(&flt_scalar_bld,
|
||||
lp_build_const_float(gallivm, key->pgon_offset_clamp),
|
||||
|
|
@ -849,7 +891,20 @@ lp_make_setup_variant_key(struct llvmpipe_context *lp,
|
|||
assert(key->spec_slot == lp->color_slot [1]);
|
||||
assert(key->bspec_slot == lp->bcolor_slot[1]);
|
||||
|
||||
key->pgon_offset_units = (float) (lp->rasterizer->offset_units * lp->mrd);
|
||||
/*
|
||||
* If depth is floating point, depth bias is calculated with respect
|
||||
* to the primitive's maximum Z value. Retain the original depth bias
|
||||
* value until that stage.
|
||||
*/
|
||||
key->floating_point_depth = lp->floating_point_depth;
|
||||
|
||||
if (key->floating_point_depth) {
|
||||
key->pgon_offset_units = (float) lp->rasterizer->offset_units;
|
||||
} else {
|
||||
key->pgon_offset_units =
|
||||
(float) (lp->rasterizer->offset_units * lp->mrd);
|
||||
}
|
||||
|
||||
key->pgon_offset_scale = lp->rasterizer->offset_scale;
|
||||
key->pgon_offset_clamp = lp->rasterizer->offset_clamp;
|
||||
key->pad = 0;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ struct lp_setup_variant_key {
|
|||
unsigned flatshade_first:1;
|
||||
unsigned pixel_center_half:1;
|
||||
unsigned twoside:1;
|
||||
unsigned pad:5;
|
||||
unsigned floating_point_depth:1;
|
||||
unsigned pad:4;
|
||||
|
||||
/* TODO: get those floats out of the key and use a jit_context for setup */
|
||||
float pgon_offset_units;
|
||||
|
|
|
|||
|
|
@ -57,24 +57,32 @@ llvmpipe_set_framebuffer_state(struct pipe_context *pipe,
|
|||
assert(fb->height <= LP_MAX_HEIGHT);
|
||||
|
||||
if (changed) {
|
||||
/*
|
||||
* If no depth buffer is bound, send the utility function the default
|
||||
* format for no bound depth (PIPE_FORMAT_NONE).
|
||||
*/
|
||||
enum pipe_format depth_format = fb->zsbuf ?
|
||||
fb->zsbuf->format : PIPE_FORMAT_NONE;
|
||||
const struct util_format_description *depth_desc =
|
||||
util_format_description(depth_format);
|
||||
|
||||
util_copy_framebuffer_state(&lp->framebuffer, fb);
|
||||
|
||||
if (LP_PERF & PERF_NO_DEPTH) {
|
||||
pipe_surface_reference(&lp->framebuffer.zsbuf, NULL);
|
||||
}
|
||||
|
||||
/* Tell draw module how deep the Z/depth buffer is.
|
||||
*
|
||||
* If no depth buffer is bound, send the utility function the default
|
||||
* format for no bound depth (PIPE_FORMAT_NONE).
|
||||
*
|
||||
* FIXME: mrd constant isn't right should use a value derived from
|
||||
* current primitive not a constant (for float depth buffers)
|
||||
/*
|
||||
* Calculate the floating point depth sense and Minimum Resolvable Depth
|
||||
* value for the llvmpipe module. This is separate from the draw module.
|
||||
*/
|
||||
lp->mrd = util_get_depth_format_mrd((lp->framebuffer.zsbuf) ?
|
||||
lp->framebuffer.zsbuf->format : PIPE_FORMAT_NONE);
|
||||
lp->floating_point_depth =
|
||||
(util_get_depth_format_type(depth_desc) == UTIL_FORMAT_TYPE_FLOAT);
|
||||
|
||||
lp->mrd = util_get_depth_format_mrd(depth_desc);
|
||||
|
||||
draw_set_mrd(lp->draw, lp->mrd);
|
||||
/* Tell the draw module how deep the Z/depth buffer is. */
|
||||
draw_set_zs_format(lp->draw, depth_format);
|
||||
|
||||
lp_setup_bind_framebuffer( lp->setup, &lp->framebuffer );
|
||||
|
||||
|
|
|
|||
|
|
@ -82,21 +82,14 @@ softpipe_set_framebuffer_state(struct pipe_context *pipe,
|
|||
/* update cache */
|
||||
sp_tile_cache_set_surface(sp->zsbuf_cache, fb->zsbuf);
|
||||
|
||||
/* Tell draw module how deep the Z/depth buffer is */
|
||||
if (sp->framebuffer.zsbuf) {
|
||||
int depth_bits;
|
||||
double mrd;
|
||||
depth_bits = util_format_get_component_bits(sp->framebuffer.zsbuf->format,
|
||||
UTIL_FORMAT_COLORSPACE_ZS,
|
||||
0);
|
||||
if (depth_bits > 16) {
|
||||
mrd = 0.0000001;
|
||||
}
|
||||
else {
|
||||
mrd = 0.00002;
|
||||
}
|
||||
draw_set_mrd(sp->draw, mrd);
|
||||
}
|
||||
/* Tell draw module how deep the Z/depth buffer is
|
||||
*
|
||||
* If no depth buffer is bound, send the utility function the
|
||||
* format for no bound depth (PIPE_FORMAT_NONE).
|
||||
*/
|
||||
draw_set_zs_format(sp->draw,
|
||||
(sp->framebuffer.zsbuf) ?
|
||||
sp->framebuffer.zsbuf->format : PIPE_FORMAT_NONE);
|
||||
}
|
||||
|
||||
sp->framebuffer.width = fb->width;
|
||||
|
|
|
|||
|
|
@ -121,9 +121,15 @@ update_swtnl_draw( struct svga_context *svga,
|
|||
&svga->curr.rast->templ,
|
||||
(void *) svga->curr.rast);
|
||||
|
||||
/* Tell the draw module how deep the Z/depth buffer is.
|
||||
*
|
||||
* If no depth buffer is bound, send the utility function the
|
||||
* format for no bound depth (PIPE_FORMAT_NONE).
|
||||
*/
|
||||
if (dirty & SVGA_NEW_FRAME_BUFFER)
|
||||
draw_set_mrd(svga->swtnl.draw,
|
||||
svga->curr.depthscale);
|
||||
draw_set_zs_format(svga->swtnl.draw,
|
||||
(svga->curr.framebuffer.zsbuf) ?
|
||||
svga->curr.framebuffer.zsbuf->format : PIPE_FORMAT_NONE);
|
||||
|
||||
return PIPE_OK;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue