From: Kenneth Graunke Date: Wed, 13 Feb 2013 05:51:16 +0000 (-0800) Subject: i965: Lower textureGrad() for samplerCubeShadow. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e2f887b243fd34ef82e4782a968baca485b07b15;p=mesa.git i965: Lower textureGrad() for samplerCubeShadow. According to the Ivybridge PRM, Volume 4 Part 1, page 130, in the section for the sample_d message: "The r coordinate contains the faceid, and the r gradients are ignored by hardware." This doesn't match GLSL, which provides gradients for all of the coordinates. So we would need to do some math to compute the face ID before using sample_d. We currently don't have any code to do that. However, we do have a lowering pass that converts textureGrad to textureLod, which solves this problem. Since textureGrad on three components is sufficiently obscure, it's not a performance path. For now, only handle samplerCubeShadow; we need tests for samplerCube and samplerCubeArray. Fixes es3conform's shadow_comparison_frag test on Haswell. NOTE: This is a candidate for stable branches. Signed-off-by: Kenneth Graunke --- diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index 7ef3186ab1c..c6825018ddc 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -1337,7 +1337,8 @@ brw_program_reloc(struct brw_context *brw, uint32_t state_offset, } bool brw_do_cubemap_normalize(struct exec_list *instructions); -bool brw_lower_texture_gradients(struct exec_list *instructions); +bool brw_lower_texture_gradients(struct intel_context *intel, + struct exec_list *instructions); struct opcode_desc { char *name; diff --git a/src/mesa/drivers/dri/i965/brw_lower_texture_gradients.cpp b/src/mesa/drivers/dri/i965/brw_lower_texture_gradients.cpp index d0c1ea48dc2..c5294bcf0cb 100644 --- a/src/mesa/drivers/dri/i965/brw_lower_texture_gradients.cpp +++ b/src/mesa/drivers/dri/i965/brw_lower_texture_gradients.cpp @@ -28,12 +28,14 @@ #include "glsl/ir.h" #include "glsl/ir_builder.h" #include "program/prog_instruction.h" +#include "brw_context.h" using namespace ir_builder; class lower_texture_grad_visitor : public ir_hierarchical_visitor { public: - lower_texture_grad_visitor() + lower_texture_grad_visitor(bool has_sample_d_c) + : has_sample_d_c(has_sample_d_c) { progress = false; } @@ -42,6 +44,7 @@ public: bool progress; + bool has_sample_d_c; private: void emit(ir_variable *, ir_rvalue *); @@ -91,6 +94,22 @@ lower_texture_grad_visitor::visit_leave(ir_texture *ir) if (ir->op != ir_txd || !ir->shadow_comparitor) return visit_continue; + /* Lower textureGrad() with samplerCubeShadow even if we have the sample_d_c + * message. GLSL provides gradients for the 'r' coordinate. Unfortunately: + * + * From the Ivybridge PRM, Volume 4, Part 1, sample_d message description: + * "The r coordinate contains the faceid, and the r gradients are ignored + * by hardware." + * + * We likely need to do a similar treatment for samplerCube and + * samplerCubeArray, but we have insufficient testing for that at the moment. + */ + bool need_lowering = !has_sample_d_c || + ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE; + + if (!need_lowering) + return visit_continue; + void *mem_ctx = ralloc_parent(ir); const glsl_type *grad_type = ir->lod_info.grad.dPdx->type; @@ -146,9 +165,11 @@ lower_texture_grad_visitor::visit_leave(ir_texture *ir) extern "C" { bool -brw_lower_texture_gradients(struct exec_list *instructions) +brw_lower_texture_gradients(struct intel_context *intel, + struct exec_list *instructions) { - lower_texture_grad_visitor v; + bool has_sample_d_c = intel->gen >= 8 || intel->is_haswell; + lower_texture_grad_visitor v(has_sample_d_c); visit_list_elements(&v, instructions); diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp index a8209527d53..75468b1d194 100644 --- a/src/mesa/drivers/dri/i965/brw_shader.cpp +++ b/src/mesa/drivers/dri/i965/brw_shader.cpp @@ -168,8 +168,7 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *shProg) lower_if_to_cond_assign(shader->ir, 16); do_lower_texture_projection(shader->ir); - if (intel->gen < 8 && !intel->is_haswell) - brw_lower_texture_gradients(shader->ir); + brw_lower_texture_gradients(intel, shader->ir); do_vec_index_to_cond_assign(shader->ir); brw_do_cubemap_normalize(shader->ir); lower_noise(shader->ir);