diff options
author | Matthew McClure <[email protected]> | 2013-10-29 13:36:41 -0700 |
---|---|---|
committer | José Fonseca <[email protected]> | 2013-11-07 18:32:54 +0000 |
commit | f9e2c24326869542c9b43220f63dd9841c6de38f (patch) | |
tree | bd208be0c8a880c0665c6672138083e00eeef680 /src/gallium/drivers/llvmpipe | |
parent | 185b5a54c94ce11487146042c8eec24909187ed6 (diff) |
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 <[email protected]>
Reviewed-by: Roland Scheidegger <[email protected]>
Diffstat (limited to 'src/gallium/drivers/llvmpipe')
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_context.h | 7 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_derived.c | 3 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_setup.c | 65 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_setup.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_surface.c | 28 |
5 files changed, 86 insertions, 20 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h index 106288a6ad3..9ec18e8429e 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.h +++ b/src/gallium/drivers/llvmpipe/lp_context.h @@ -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; diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c index 8aee92b1b96..47e413b776c 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_derived.c +++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c @@ -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) diff --git a/src/gallium/drivers/llvmpipe/lp_state_setup.c b/src/gallium/drivers/llvmpipe/lp_state_setup.c index dab5096c61d..ccc9fb902f3 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_state_setup.c @@ -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; diff --git a/src/gallium/drivers/llvmpipe/lp_state_setup.h b/src/gallium/drivers/llvmpipe/lp_state_setup.h index f49e575aa1f..82af8350fb7 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_setup.h +++ b/src/gallium/drivers/llvmpipe/lp_state_setup.h @@ -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; diff --git a/src/gallium/drivers/llvmpipe/lp_state_surface.c b/src/gallium/drivers/llvmpipe/lp_state_surface.c index 89098410280..c228c63d139 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_surface.c +++ b/src/gallium/drivers/llvmpipe/lp_state_surface.c @@ -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 ); |