i965: Lower textureGrad() for samplerCubeShadow.
authorKenneth Graunke <kenneth@whitecape.org>
Wed, 13 Feb 2013 05:51:16 +0000 (21:51 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Wed, 1 May 2013 17:42:51 +0000 (10:42 -0700)
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 <kenneth@whitecape.org>
src/mesa/drivers/dri/i965/brw_context.h
src/mesa/drivers/dri/i965/brw_lower_texture_gradients.cpp
src/mesa/drivers/dri/i965/brw_shader.cpp

index 7ef3186ab1ca4636e7e163f1edbe0619feb204ac..c6825018ddcf18061f9ffd295fc475469cf98053 100644 (file)
@@ -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;
index d0c1ea48dc240db1653c1e5fedfa74187483bfb9..c5294bcf0cbc26fda6ecfd4792da522946070005 100644 (file)
 #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);
 
index a8209527d53e26fc9b93b822e61442f66a23c5fb..75468b1d194a117d20d923ed48ee18f933de244c 100644 (file)
@@ -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);