llvmpipe: Implement TXQ.
authorOlivier Galibert <galibert@pobox.com>
Thu, 17 May 2012 14:48:54 +0000 (16:48 +0200)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Thu, 17 May 2012 23:27:28 +0000 (00:27 +0100)
Piglits test for fragment shaders pass, vertex shaders fail.  The
actual failure seems to be in the interpolators, and not the
textureSize query.

Signed-off-by: Olivier Galibert <galibert@pobox.com>
Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Reviewed-by: José Fonseca <jose.r.fonseca@gmail.com>
src/gallium/auxiliary/draw/draw_llvm_sample.c
src/gallium/auxiliary/gallivm/lp_bld_sample.c
src/gallium/auxiliary/gallivm/lp_bld_sample.h
src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
src/gallium/drivers/llvmpipe/lp_tex_sample.c

index 8af34617353dfe1ee69fe04da1ae620ec1a3374e..0a8b3bc535f64203fa5d2c334bcf485603710cd7 100644 (file)
@@ -195,6 +195,28 @@ draw_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base,
 }
 
 
+/**
+ * Fetch the texture size.
+ */
+static void
+draw_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,
+                                      struct gallivm_state *gallivm,
+                                      unsigned unit,
+                                      LLVMValueRef explicit_lod, /* optional */
+                                      LLVMValueRef *sizes_out)
+{
+   struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base;
+
+   assert(unit < PIPE_MAX_VERTEX_SAMPLERS);
+
+   lp_build_size_query_soa(gallivm,
+                           &sampler->dynamic_state.static_state[unit],
+                           &sampler->dynamic_state.base,
+                           unit,
+                           explicit_lod,
+                           sizes_out);
+}
+
 struct lp_build_sampler_soa *
 draw_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state,
                              LLVMValueRef context_ptr)
@@ -207,6 +229,7 @@ draw_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state,
 
    sampler->base.destroy = draw_llvm_sampler_soa_destroy;
    sampler->base.emit_fetch_texel = draw_llvm_sampler_soa_emit_fetch_texel;
+   sampler->base.emit_size_query = draw_llvm_sampler_soa_emit_size_query;
    sampler->dynamic_state.base.width = draw_llvm_texture_width;
    sampler->dynamic_state.base.height = draw_llvm_texture_height;
    sampler->dynamic_state.base.depth = draw_llvm_texture_depth;
index c6d4f1bcc28c8f91c5952818a12e3ff88105b600..2ffd9b8bfc361dfaa0785a6c8e1286d31b37d070 100644 (file)
  */
 #define BRILINEAR_FACTOR 2
 
-static LLVMValueRef
-lp_build_minify(struct lp_build_context *bld,
-                LLVMValueRef base_size,
-                LLVMValueRef level);
-
 /**
  * Does the given texture wrap mode allow sampling the texture border color?
  * XXX maybe move this into gallium util code.
@@ -670,7 +665,7 @@ lp_build_get_const_mipmap_level(struct lp_build_sample_context *bld,
  * Codegen equivalent for u_minify().
  * Return max(1, base_size >> level);
  */
-static LLVMValueRef
+LLVMValueRef
 lp_build_minify(struct lp_build_context *bld,
                 LLVMValueRef base_size,
                 LLVMValueRef level)
index a71e656fe0e95d3924f7de9d9b741af1717188b2..8ccba2ca09ebffdb23ae2c0d8ab6d8e56f93683b 100644 (file)
@@ -404,9 +404,23 @@ lp_build_sample_soa(struct gallivm_state *gallivm,
                     LLVMValueRef explicit_lod,
                     LLVMValueRef texel_out[4]);
 
+void
+lp_build_size_query_soa(struct gallivm_state *gallivm,
+                        const struct lp_sampler_static_state *static_state,
+                        struct lp_sampler_dynamic_state *dynamic_state,
+                        unsigned unit,
+                        LLVMValueRef explicit_lod,
+                        LLVMValueRef *sizes_out);
+
 void
 lp_build_sample_nop(struct gallivm_state *gallivm, struct lp_type type,
                     LLVMValueRef texel_out[4]);
 
 
+LLVMValueRef
+lp_build_minify(struct lp_build_context *bld,
+                LLVMValueRef base_size,
+                LLVMValueRef level);
+
+
 #endif /* LP_BLD_SAMPLE_H */
index 4ea7b4bd8a26e8ffc308fb5023ac0cc614aff800..73dc3e7708304de72efd32dc02944f830b16e7d5 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "pipe/p_defines.h"
 #include "pipe/p_state.h"
+#include "pipe/p_shader_tokens.h"
 #include "util/u_debug.h"
 #include "util/u_dump.h"
 #include "util/u_memory.h"
@@ -1277,3 +1278,75 @@ lp_build_sample_soa(struct gallivm_state *gallivm,
 
    apply_sampler_swizzle(&bld, texel_out);
 }
+
+void
+lp_build_size_query_soa(struct gallivm_state *gallivm,
+                        const struct lp_sampler_static_state *static_state,
+                        struct lp_sampler_dynamic_state *dynamic_state,
+                        unsigned unit,
+                        LLVMValueRef explicit_lod,
+                        LLVMValueRef *sizes_out)
+{
+   LLVMValueRef lod;
+   LLVMValueRef size;
+   int dims, i;
+   struct lp_build_context bld_int_vec;
+
+   switch (static_state->target) {
+   case PIPE_TEXTURE_1D:
+   case PIPE_BUFFER:
+      dims = 1;
+      break;
+   case PIPE_TEXTURE_2D:
+   case PIPE_TEXTURE_CUBE:
+   case PIPE_TEXTURE_RECT:
+      dims = 2;
+      break;
+   case PIPE_TEXTURE_3D:
+      dims = 3;
+      break;
+
+   default:
+      assert(0);
+      return;
+   }
+
+   lp_build_context_init(&bld_int_vec, gallivm, lp_type_int_vec(32));
+
+   if (explicit_lod) {
+      LLVMValueRef first_level;
+      lod = LLVMBuildExtractElement(gallivm->builder, explicit_lod, lp_build_const_int32(gallivm, 0), "");
+      first_level = dynamic_state->first_level(dynamic_state, gallivm, unit);
+      lod = lp_build_broadcast_scalar(&bld_int_vec,
+                                      LLVMBuildAdd(gallivm->builder, lod, first_level, "lod"));
+
+   } else {
+      lod = bld_int_vec.zero;
+   }
+
+   size = bld_int_vec.undef;
+
+   size = LLVMBuildInsertElement(gallivm->builder, size,
+                                 dynamic_state->width(dynamic_state, gallivm, unit),
+                                 lp_build_const_int32(gallivm, 0), "");
+
+   if (dims >= 2) {
+      size = LLVMBuildInsertElement(gallivm->builder, size,
+                                    dynamic_state->height(dynamic_state, gallivm, unit),
+                                    lp_build_const_int32(gallivm, 1), "");
+   }
+
+   if (dims >= 3) {
+      size = LLVMBuildInsertElement(gallivm->builder, size,
+                                    dynamic_state->depth(dynamic_state, gallivm, unit),
+                                    lp_build_const_int32(gallivm, 2), "");
+   }
+
+   size = lp_build_minify(&bld_int_vec, size, lod);
+
+   for (i=0; i < dims; i++) {
+      sizes_out[i] = lp_build_extract_broadcast(gallivm, bld_int_vec.type, bld_int_vec.type,
+                                                size,
+                                                lp_build_const_int32(gallivm, i));
+   }
+}
index 773c679a4d838d94848a70395e89fa20bd87ac77..141e799c4e4b1900005ad18a294ba80f5197a9d8 100644 (file)
@@ -170,6 +170,13 @@ struct lp_build_sampler_soa
                         LLVMValueRef lod_bias, /* optional */
                         LLVMValueRef explicit_lod, /* optional */
                         LLVMValueRef *texel);
+
+   void
+   (*emit_size_query)( const struct lp_build_sampler_soa *sampler,
+                       struct gallivm_state *gallivm,
+                       unsigned unit,
+                       LLVMValueRef explicit_lod, /* optional */
+                       LLVMValueRef *sizes_out);
 };
 
 
index cca7ef5f89a027b631e97e2db3b8db924ca44667..a9d69a3259e59e99a4338f9616c8d7e3c3c4178e 100644 (file)
@@ -1209,6 +1209,80 @@ emit_tex( struct lp_build_tgsi_soa_context *bld,
                                   texel);
 }
 
+static void
+emit_txq( struct lp_build_tgsi_soa_context *bld,
+          const struct tgsi_full_instruction *inst,
+          LLVMValueRef *sizes_out)
+{
+   LLVMValueRef explicit_lod;
+   unsigned num_coords, has_lod;
+   unsigned i;
+
+   switch (inst->Texture.Texture) {
+   case TGSI_TEXTURE_1D:
+   case TGSI_TEXTURE_SHADOW1D:
+   case TGSI_TEXTURE_SHADOW2D:
+   case TGSI_TEXTURE_SHADOWCUBE:
+      num_coords = 1;
+      has_lod = 1;
+      break;
+   case TGSI_TEXTURE_2D:
+   case TGSI_TEXTURE_CUBE:
+   case TGSI_TEXTURE_1D_ARRAY:
+   case TGSI_TEXTURE_SHADOW1D_ARRAY:
+      num_coords = 2;
+      has_lod = 1;
+      break;
+   case TGSI_TEXTURE_3D:
+// case TGSI_TEXTURE_CUBE_ARRAY:
+// case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
+   case TGSI_TEXTURE_2D_ARRAY:
+   case TGSI_TEXTURE_SHADOW2D_ARRAY:
+      num_coords = 3;
+      has_lod = 1;
+      break;
+
+   case TGSI_TEXTURE_BUFFER:
+      num_coords = 1;
+      has_lod = 0;
+      break;
+
+   case TGSI_TEXTURE_RECT:
+   case TGSI_TEXTURE_SHADOWRECT:
+// case TGSI_TEXTURE_2D_MS:
+      num_coords = 2;
+      has_lod = 0;
+      break;
+
+// case TGSI_TEXTURE_2D_MS_ARRAY:
+//    num_coords = 3;
+//    has_lod = 0;
+//    break;
+
+   default:
+      assert(0);
+      return;
+   }
+
+   if (!bld->sampler) {
+      _debug_printf("warning: found texture query instruction but no sampler generator supplied\n");
+      for (i = 0; i < num_coords; i++)
+         sizes_out[i] = bld->bld_base.base.undef;
+      return;
+   }
+
+   if (has_lod)
+      explicit_lod = lp_build_emit_fetch( &bld->bld_base, inst, 0, 2 );
+   else
+      explicit_lod = NULL;
+
+   bld->sampler->emit_size_query(bld->sampler,
+                                 bld->bld_base.base.gallivm,
+                                 inst->Src[1].Register.Index,
+                                 explicit_lod,
+                                 sizes_out);
+}
+
 static boolean
 near_end_of_shader(struct lp_build_tgsi_soa_context *bld,
                   int pc)
@@ -1584,6 +1658,17 @@ txp_emit(
             emit_data->output);
 }
 
+static void
+txq_emit(
+   const struct lp_build_tgsi_action * action,
+   struct lp_build_tgsi_context * bld_base,
+   struct lp_build_emit_data * emit_data)
+{
+   struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
+
+   emit_txq(bld, emit_data->inst, emit_data->output);
+}
+
 static void
 cal_emit(
    const struct lp_build_tgsi_action * action,
@@ -1954,6 +2039,7 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
    bld.bld_base.op_actions[TGSI_OPCODE_TXD].emit = txd_emit;
    bld.bld_base.op_actions[TGSI_OPCODE_TXL].emit = txl_emit;
    bld.bld_base.op_actions[TGSI_OPCODE_TXP].emit = txp_emit;
+   bld.bld_base.op_actions[TGSI_OPCODE_TXQ].emit = txq_emit;
 
    lp_exec_mask_init(&bld.exec_mask, &bld.bld_base.base);
 
index ccc139603ee043e14b0d22e878924b0cac0db4cd..daa96f20c7e5d167be7394e582c211d3b257c25a 100644 (file)
@@ -204,6 +204,28 @@ lp_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base,
                        texel);
 }
 
+/**
+ * Fetch the texture size.
+ */
+static void
+lp_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,
+                                    struct gallivm_state *gallivm,
+                                    unsigned unit,
+                                    LLVMValueRef explicit_lod, /* optional */
+                                    LLVMValueRef *sizes_out)
+{
+   struct lp_llvm_sampler_soa *sampler = (struct lp_llvm_sampler_soa *)base;
+
+   assert(unit < PIPE_MAX_SAMPLERS);
+   
+   lp_build_size_query_soa(gallivm,
+                          &sampler->dynamic_state.static_state[unit],
+                          &sampler->dynamic_state.base,
+                          unit,
+                          explicit_lod,
+                          sizes_out);
+}
+
 
 struct lp_build_sampler_soa *
 lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state,
@@ -217,6 +239,7 @@ lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state,
 
    sampler->base.destroy = lp_llvm_sampler_soa_destroy;
    sampler->base.emit_fetch_texel = lp_llvm_sampler_soa_emit_fetch_texel;
+   sampler->base.emit_size_query = lp_llvm_sampler_soa_emit_size_query;
    sampler->dynamic_state.base.width = lp_llvm_texture_width;
    sampler->dynamic_state.base.height = lp_llvm_texture_height;
    sampler->dynamic_state.base.depth = lp_llvm_texture_depth;