break;
}
- if ((attrib == 0) && (chan == 2)){
+ if ((attrib == 0) && (chan == 2) && !bld->depth_clamp){
/* FIXME: Depth values can exceed 1.0, due to the fact that
* setup interpolation coefficients refer to (0,0) which causes
- * precision loss. So we must clamp to 1.0 here to avoid artifacts
+ * precision loss. So we must clamp to 1.0 here to avoid artifacts.
+ * Note though values outside [0,1] are perfectly valid with
+ * depth clip disabled.
+ * XXX: If depth clip is disabled but we force depth clamp
+ * we may get values larger than 1.0 in the fs (but not in
+ * depth test). Not sure if that's an issue...
+ * Also, on a similar note, it is not obvious if the depth values
+ * appearing in fs (with depth clip disabled) should be clamped
+ * to [0,1], clamped to near/far or not be clamped at all...
*/
a = lp_build_min(coeff_bld, a, coeff_bld->one);
}
}
#endif
- if (attrib == 0 && chan == 2) {
+ if (attrib == 0 && chan == 2 && !bld->depth_clamp) {
/* FIXME: Depth values can exceed 1.0, due to the fact that
* setup interpolation coefficients refer to (0,0) which causes
- * precision loss. So we must clamp to 1.0 here to avoid artifacts
+ * precision loss. So we must clamp to 1.0 here to avoid artifacts.
+ * Note though values outside [0,1] are perfectly valid with
+ * depth clip disabled..
+ * XXX: If depth clip is disabled but we force depth clamp
+ * we may get values larger than 1.0 in the fs (but not in
+ * depth test). Not sure if that's an issue...
+ * Also, on a similar note, it is not obvious if the depth values
+ * appearing in fs (with depth clip disabled) should be clamped
+ * to [0,1], clamped to near/far or not be clamped at all...
*/
a = lp_build_min(coeff_bld, a, coeff_bld->one);
}
unsigned num_inputs,
const struct lp_shader_input *inputs,
boolean pixel_center_integer,
+ boolean depth_clamp,
LLVMBuilderRef builder,
struct lp_type type,
LLVMValueRef a0_ptr,
} else {
bld->pos_offset = 0.5;
}
+ bld->depth_clamp = depth_clamp;
pos_init(bld, x0, y0);
}
+static LLVMValueRef
+lp_build_depth_clamp(struct gallivm_state *gallivm,
+ LLVMBuilderRef builder,
+ struct lp_type type,
+ LLVMValueRef context_ptr,
+ LLVMValueRef thread_data_ptr,
+ LLVMValueRef z)
+{
+ LLVMValueRef viewport, min_depth, max_depth;
+ LLVMValueRef viewport_index;
+ struct lp_build_context f32_bld;
+
+ assert(type.floating);
+ lp_build_context_init(&f32_bld, gallivm, type);
+
+ /*
+ * Assumes clamping of the viewport index will occur in setup/gs. Value
+ * is passed through the rasterization stage via lp_rast_shader_inputs.
+ *
+ * See: draw_clamp_viewport_idx and lp_clamp_viewport_idx for clamping
+ * semantics.
+ */
+ viewport_index = lp_jit_thread_data_raster_state_viewport_index(gallivm,
+ thread_data_ptr);
+
+ /*
+ * Load the min and max depth from the lp_jit_context.viewports
+ * array of lp_jit_viewport structures.
+ */
+ viewport = lp_llvm_viewport(context_ptr, gallivm, viewport_index);
+
+ /* viewports[viewport_index].min_depth */
+ min_depth = LLVMBuildExtractElement(builder, viewport,
+ lp_build_const_int32(gallivm, LP_JIT_VIEWPORT_MIN_DEPTH), "");
+ min_depth = lp_build_broadcast_scalar(&f32_bld, min_depth);
+
+ /* viewports[viewport_index].max_depth */
+ max_depth = LLVMBuildExtractElement(builder, viewport,
+ lp_build_const_int32(gallivm, LP_JIT_VIEWPORT_MAX_DEPTH), "");
+ max_depth = lp_build_broadcast_scalar(&f32_bld, max_depth);
+
+ /*
+ * Clamp to the min and max depth values for the given viewport.
+ */
+ return lp_build_clamp(&f32_bld, z, min_depth, max_depth);
+}
+
+
/**
* Generate the fragment shader, depth/stencil test, and alpha tests.
*/
z = interp->pos[2];
if (depth_mode & EARLY_DEPTH_TEST) {
+ /*
+ * Clamp according to ARB_depth_clamp semantics.
+ */
+ if (key->depth_clamp) {
+ z = lp_build_depth_clamp(gallivm, builder, type, context_ptr,
+ thread_data_ptr, z);
+ }
lp_build_depth_stencil_load_swizzled(gallivm, type,
zs_format_desc, key->resource_1d,
depth_ptr, depth_stride,
0);
if (pos0 != -1 && outputs[pos0][2]) {
z = LLVMBuildLoad(builder, outputs[pos0][2], "output.z");
-
- /*
- * Clamp according to ARB_depth_clamp semantics.
- */
- if (key->depth_clamp) {
- LLVMValueRef viewport, min_depth, max_depth;
- LLVMValueRef viewport_index;
- struct lp_build_context f32_bld;
-
- assert(type.floating);
- lp_build_context_init(&f32_bld, gallivm, type);
-
- /*
- * Assumes clamping of the viewport index will occur in setup/gs. Value
- * is passed through the rasterization stage via lp_rast_shader_inputs.
- *
- * See: draw_clamp_viewport_idx and lp_clamp_viewport_idx for clamping
- * semantics.
- */
- viewport_index = lp_jit_thread_data_raster_state_viewport_index(gallivm,
- thread_data_ptr);
-
- /*
- * Load the min and max depth from the lp_jit_context.viewports
- * array of lp_jit_viewport structures.
- */
- viewport = lp_llvm_viewport(context_ptr, gallivm, viewport_index);
-
- /* viewports[viewport_index].min_depth */
- min_depth = LLVMBuildExtractElement(builder, viewport,
- lp_build_const_int32(gallivm, LP_JIT_VIEWPORT_MIN_DEPTH),
- "");
- min_depth = lp_build_broadcast_scalar(&f32_bld, min_depth);
-
- /* viewports[viewport_index].max_depth */
- max_depth = LLVMBuildExtractElement(builder, viewport,
- lp_build_const_int32(gallivm, LP_JIT_VIEWPORT_MAX_DEPTH),
- "");
- max_depth = lp_build_broadcast_scalar(&f32_bld, max_depth);
-
- /*
- * Clamp to the min and max depth values for the given viewport.
- */
- z = lp_build_clamp(&f32_bld, z, min_depth, max_depth);
- }
+ }
+ /*
+ * Clamp according to ARB_depth_clamp semantics.
+ */
+ if (key->depth_clamp) {
+ z = lp_build_depth_clamp(gallivm, builder, type, context_ptr,
+ thread_data_ptr, z);
}
if (s_out != -1 && outputs[s_out][1]) {
shader->info.base.num_inputs,
inputs,
pixel_center_integer,
+ key->depth_clamp,
builder, fs_type,
a0_ptr, dadx_ptr, dady_ptr,
x, y);
* depth_clip == 0 implies depth clamping is enabled.
*
* When clip_halfz is enabled, then always clamp the depth values.
+ *
+ * XXX: This is incorrect for GL, but correct for d3d10 (depth
+ * clamp is always active in d3d10, regardless if depth clip is
+ * enabled or not).
+ * (GL has an always-on [0,1] clamp on fs depth output instead
+ * to ensure the depth values stay in range. Doesn't look like
+ * we do that, though...)
*/
if (lp->rasterizer->clip_halfz) {
key->depth_clamp = 1;