#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"
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;
}
/**
- * 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);
}
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);
* \author Brian Paul
*/
+#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "draw_pipe.h"
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) :
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;
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 */
* 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.
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);
}
}
+/**
+ * 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
* 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);
/**
};
+/**
+ * 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)
/** 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;
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)
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;
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;
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),
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;
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;
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 );
/* 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;
&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;
}