Mesa (master): gallium: implement modern sampling scheme

Zack Rusin zack at kemper.freedesktop.org
Mon Jan 24 22:45:10 UTC 2011


Module: Mesa
Branch: master
Commit: bdbe77f9c6f06cfaa155f27c2ade3c523d7fbea7
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=bdbe77f9c6f06cfaa155f27c2ade3c523d7fbea7

Author: Zack Rusin <zackr at vmware.com>
Date:   Mon Jan 24 17:47:10 2011 -0500

gallium: implement modern sampling scheme

largely a merge of the previously discussed origin/gallium-resource-sampling
but updated.
the idea is to allow arbitrary binding of resources, the way opencl, new gl
versions and dx10+ require, i.e.
    DCL RES[0], 2D, FLOAT

    LOAD DST[0], SRC[0], RES[0]
    SAMPLE DST[0], SRC[0], RES[0], SAMP[0]

---

 src/gallium/auxiliary/tgsi/tgsi_build.c      |   59 +++++++
 src/gallium/auxiliary/tgsi/tgsi_dump.c       |   32 ++++-
 src/gallium/auxiliary/tgsi/tgsi_exec.c       |  211 ++++++++++++++++++++++++++
 src/gallium/auxiliary/tgsi/tgsi_exec.h       |    1 +
 src/gallium/auxiliary/tgsi/tgsi_info.c       |   15 ++-
 src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h |   17 ++
 src/gallium/auxiliary/tgsi/tgsi_parse.c      |    4 +
 src/gallium/auxiliary/tgsi/tgsi_parse.h      |    3 +-
 src/gallium/auxiliary/tgsi/tgsi_sanity.c     |    3 +-
 src/gallium/auxiliary/tgsi/tgsi_text.c       |  135 +++++++++++++----
 src/gallium/auxiliary/tgsi/tgsi_ureg.c       |   91 +++++++++++-
 src/gallium/auxiliary/tgsi/tgsi_ureg.h       |   69 +++++++++
 src/gallium/docs/source/tgsi.rst             |  123 +++++++++++++++
 src/gallium/include/pipe/p_format.h          |   10 ++
 src/gallium/include/pipe/p_shader_tokens.h   |   26 +++-
 src/gallium/include/pipe/p_state.h           |    1 +
 src/gallium/tests/graw/SConscript            |    1 +
 17 files changed, 767 insertions(+), 34 deletions(-)

diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.c b/src/gallium/auxiliary/tgsi/tgsi_build.c
index 16a205f..d2cb98e 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_build.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_build.c
@@ -26,6 +26,7 @@
  **************************************************************************/
 
 #include "util/u_debug.h"
+#include "pipe/p_format.h"
 #include "pipe/p_shader_tokens.h"
 #include "tgsi_build.h"
 #include "tgsi_parse.h"
@@ -226,6 +227,45 @@ tgsi_build_declaration_semantic(
    return ds;
 }
 
+
+static struct tgsi_declaration_resource
+tgsi_default_declaration_resource(void)
+{
+   struct tgsi_declaration_resource declaration_resource;
+
+   declaration_resource.Resource = TGSI_TEXTURE_UNKNOWN;
+   declaration_resource.ReturnTypeX = PIPE_TYPE_UNORM;
+   declaration_resource.ReturnTypeY = PIPE_TYPE_UNORM;
+   declaration_resource.ReturnTypeZ = PIPE_TYPE_UNORM;
+   declaration_resource.ReturnTypeW = PIPE_TYPE_UNORM;
+
+   return declaration_resource;
+}
+
+static struct tgsi_declaration_resource
+tgsi_build_declaration_resource(unsigned texture,
+                                unsigned return_type_x,
+                                unsigned return_type_y,
+                                unsigned return_type_z,
+                                unsigned return_type_w,
+                                struct tgsi_declaration *declaration,
+                                struct tgsi_header *header)
+{
+   struct tgsi_declaration_resource declaration_resource;
+
+   declaration_resource = tgsi_default_declaration_resource();
+   declaration_resource.Resource = texture;
+   declaration_resource.ReturnTypeX = return_type_x;
+   declaration_resource.ReturnTypeY = return_type_y;
+   declaration_resource.ReturnTypeZ = return_type_z;
+   declaration_resource.ReturnTypeW = return_type_w;
+
+   declaration_grow(declaration, header);
+
+   return declaration_resource;
+}
+
+
 struct tgsi_full_declaration
 tgsi_default_full_declaration( void )
 {
@@ -235,6 +275,7 @@ tgsi_default_full_declaration( void )
    full_declaration.Range = tgsi_default_declaration_range();
    full_declaration.Semantic = tgsi_default_declaration_semantic();
    full_declaration.ImmediateData.u = NULL;
+   full_declaration.Resource = tgsi_default_declaration_resource();
 
    return full_declaration;
 }
@@ -324,6 +365,24 @@ tgsi_build_full_declaration(
       }
    }
 
+   if (full_decl->Declaration.File == TGSI_FILE_RESOURCE) {
+      struct tgsi_declaration_resource *dr;
+
+      if (maxsize <= size) {
+         return  0;
+      }
+      dr = (struct tgsi_declaration_resource *)&tokens[size];
+      size++;
+
+      *dr = tgsi_build_declaration_resource(full_decl->Resource.Resource,
+                                            full_decl->Resource.ReturnTypeX,
+                                            full_decl->Resource.ReturnTypeY,
+                                            full_decl->Resource.ReturnTypeZ,
+                                            full_decl->Resource.ReturnTypeW,
+                                            declaration,
+                                            header);
+   }
+
    return size;
 }
 
diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.c b/src/gallium/auxiliary/tgsi/tgsi_dump.c
index 82cd8ea..e97698d 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_dump.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_dump.c
@@ -104,7 +104,8 @@ tgsi_file_names[TGSI_FILE_COUNT] =
    "PRED",
    "SV",
    "IMMX",
-   "TEMPX"
+   "TEMPX",
+   "RES"
 };
 
 static const char *interpolate_names[] =
@@ -170,6 +171,15 @@ const char *tgsi_property_names[TGSI_PROPERTY_COUNT] =
    "FS_COLOR0_WRITES_ALL_CBUFS",
 };
 
+static const char *tgsi_type_names[] =
+{
+   "UNORM",
+   "SNORM",
+   "SINT",
+   "UINT",
+   "FLOAT"
+};
+
 const char *tgsi_primitive_names[PIPE_PRIM_MAX] =
 {
    "POINTS",
@@ -393,6 +403,26 @@ iter_declaration(
       }
    }
 
+   if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
+      TXT(", ");
+      ENM(decl->Resource.Resource, tgsi_texture_names);
+      TXT(", ");
+      if ((decl->Resource.ReturnTypeX == decl->Resource.ReturnTypeY) &&
+          (decl->Resource.ReturnTypeX == decl->Resource.ReturnTypeZ) &&
+          (decl->Resource.ReturnTypeX == decl->Resource.ReturnTypeW)) {
+         ENM(decl->Resource.ReturnTypeX, tgsi_type_names);
+      } else {
+         ENM(decl->Resource.ReturnTypeX, tgsi_type_names);
+         TXT(", ");
+         ENM(decl->Resource.ReturnTypeY, tgsi_type_names);
+         TXT(", ");
+         ENM(decl->Resource.ReturnTypeZ, tgsi_type_names);
+         TXT(", ");
+         ENM(decl->Resource.ReturnTypeW, tgsi_type_names);
+      }
+
+   }
+
    if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT &&
        decl->Declaration.File == TGSI_FILE_INPUT)
    {
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c
index 35b2742..959d978 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c
@@ -1843,6 +1843,164 @@ exec_txd(struct tgsi_exec_machine *mach,
 }
 
 
+
+static void
+exec_sample(struct tgsi_exec_machine *mach,
+            const struct tgsi_full_instruction *inst,
+            uint modifier)
+{
+   const uint resource_unit = inst->Src[1].Register.Index;
+   const uint sampler_unit = inst->Src[2].Register.Index;
+   union tgsi_exec_channel r[4];
+   const union tgsi_exec_channel *lod = &ZeroVec;
+   enum tgsi_sampler_control control;
+   uint chan;
+
+   if (modifier != TEX_MODIFIER_NONE) {
+      if (modifier == TEX_MODIFIER_LOD_BIAS)
+         FETCH(&r[3], 3, CHAN_X);
+      else /*TEX_MODIFIER_LOD*/
+         FETCH(&r[3], 0, CHAN_W);
+
+      if (modifier != TEX_MODIFIER_PROJECTED) {
+         lod = &r[3];
+      }
+   }
+
+   if (modifier == TEX_MODIFIER_EXPLICIT_LOD) {
+      control = tgsi_sampler_lod_explicit;
+   } else {
+      control = tgsi_sampler_lod_bias;
+   }
+
+   switch (mach->Resources[resource_unit].Resource) {
+   case TGSI_TEXTURE_1D:
+   case TGSI_TEXTURE_SHADOW1D:
+      FETCH(&r[0], 0, CHAN_X);
+
+      if (modifier == TEX_MODIFIER_PROJECTED) {
+         micro_div(&r[0], &r[0], &r[3]);
+      }
+
+      fetch_texel(mach->Samplers[sampler_unit],
+                  &r[0], &ZeroVec, &ZeroVec, lod,  /* S, T, P, LOD */
+                  control,
+                  &r[0], &r[1], &r[2], &r[3]);     /* R, G, B, A */
+      break;
+
+   case TGSI_TEXTURE_2D:
+   case TGSI_TEXTURE_RECT:
+   case TGSI_TEXTURE_SHADOW2D:
+   case TGSI_TEXTURE_SHADOWRECT:
+      FETCH(&r[0], 0, CHAN_X);
+      FETCH(&r[1], 0, CHAN_Y);
+      FETCH(&r[2], 0, CHAN_Z);
+
+      if (modifier == TEX_MODIFIER_PROJECTED) {
+         micro_div(&r[0], &r[0], &r[3]);
+         micro_div(&r[1], &r[1], &r[3]);
+         micro_div(&r[2], &r[2], &r[3]);
+      }
+
+      fetch_texel(mach->Samplers[sampler_unit],
+                  &r[0], &r[1], &r[2], lod,     /* S, T, P, LOD */
+                  control,
+                  &r[0], &r[1], &r[2], &r[3]);  /* outputs */
+      break;
+
+   case TGSI_TEXTURE_3D:
+   case TGSI_TEXTURE_CUBE:
+      FETCH(&r[0], 0, CHAN_X);
+      FETCH(&r[1], 0, CHAN_Y);
+      FETCH(&r[2], 0, CHAN_Z);
+
+      if (modifier == TEX_MODIFIER_PROJECTED) {
+         micro_div(&r[0], &r[0], &r[3]);
+         micro_div(&r[1], &r[1], &r[3]);
+         micro_div(&r[2], &r[2], &r[3]);
+      }
+
+      fetch_texel(mach->Samplers[sampler_unit],
+                  &r[0], &r[1], &r[2], lod,
+                  control,
+                  &r[0], &r[1], &r[2], &r[3]);
+      break;
+
+   default:
+      assert(0);
+   }
+
+   for (chan = 0; chan < NUM_CHANNELS; chan++) {
+      if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
+         store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
+      }
+   }
+}
+
+static void
+exec_sample_d(struct tgsi_exec_machine *mach,
+              const struct tgsi_full_instruction *inst)
+{
+   const uint resource_unit = inst->Src[1].Register.Index;
+   const uint sampler_unit = inst->Src[2].Register.Index;
+   union tgsi_exec_channel r[4];
+   uint chan;
+   /*
+    * XXX: This is fake SAMPLE_D -- the derivatives are not taken into account, yet.
+    */
+
+   switch (mach->Resources[resource_unit].Resource) {
+   case TGSI_TEXTURE_1D:
+   case TGSI_TEXTURE_SHADOW1D:
+
+      FETCH(&r[0], 0, CHAN_X);
+
+      fetch_texel(mach->Samplers[sampler_unit],
+                  &r[0], &ZeroVec, &ZeroVec, &ZeroVec,   /* S, T, P, BIAS */
+                  tgsi_sampler_lod_bias,
+                  &r[0], &r[1], &r[2], &r[3]);           /* R, G, B, A */
+      break;
+
+   case TGSI_TEXTURE_2D:
+   case TGSI_TEXTURE_RECT:
+   case TGSI_TEXTURE_SHADOW2D:
+   case TGSI_TEXTURE_SHADOWRECT:
+
+      FETCH(&r[0], 0, CHAN_X);
+      FETCH(&r[1], 0, CHAN_Y);
+      FETCH(&r[2], 0, CHAN_Z);
+
+      fetch_texel(mach->Samplers[sampler_unit],
+                  &r[0], &r[1], &r[2], &ZeroVec,   /* inputs */
+                  tgsi_sampler_lod_bias,
+                  &r[0], &r[1], &r[2], &r[3]);     /* outputs */
+      break;
+
+   case TGSI_TEXTURE_3D:
+   case TGSI_TEXTURE_CUBE:
+
+      FETCH(&r[0], 0, CHAN_X);
+      FETCH(&r[1], 0, CHAN_Y);
+      FETCH(&r[2], 0, CHAN_Z);
+
+      fetch_texel(mach->Samplers[sampler_unit],
+                  &r[0], &r[1], &r[2], &ZeroVec,
+                  tgsi_sampler_lod_bias,
+                  &r[0], &r[1], &r[2], &r[3]);
+      break;
+
+   default:
+      assert(0);
+   }
+
+   for (chan = 0; chan < NUM_CHANNELS; chan++) {
+      if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
+         store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
+      }
+   }
+}
+
+
 /**
  * Evaluate a constant-valued coefficient at the position of the
  * current quad.
@@ -1914,6 +2072,11 @@ static void
 exec_declaration(struct tgsi_exec_machine *mach,
                  const struct tgsi_full_declaration *decl)
 {
+   if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
+      mach->Resources[decl->Range.First] = decl->Resource;
+      return;
+   }
+
    if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) {
       if (decl->Declaration.File == TGSI_FILE_INPUT) {
          uint first, last, mask;
@@ -3688,6 +3851,54 @@ exec_instruction(
       exec_endswitch(mach);
       break;
 
+   case TGSI_OPCODE_LOAD:
+      assert(0);
+      break;
+
+   case TGSI_OPCODE_LOAD_MS:
+      assert(0);
+      break;
+
+   case TGSI_OPCODE_SAMPLE:
+      exec_sample(mach, inst, TEX_MODIFIER_NONE);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_B:
+      exec_sample(mach, inst, TEX_MODIFIER_LOD_BIAS);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_C:
+      exec_sample(mach, inst, TEX_MODIFIER_NONE);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_C_LZ:
+      exec_sample(mach, inst, TEX_MODIFIER_LOD_BIAS);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_D:
+      exec_sample_d(mach, inst);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_L:
+      exec_sample(mach, inst, TEX_MODIFIER_EXPLICIT_LOD);
+      break;
+
+   case TGSI_OPCODE_GATHER4:
+      assert(0);
+      break;
+
+   case TGSI_OPCODE_RESINFO:
+      assert(0);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_POS:
+      assert(0);
+      break;
+
+   case TGSI_OPCODE_SAMPLE_INFO:
+      assert(0);
+      break;
+
    default:
       assert( 0 );
    }
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h
index 6c204c7..4a423b5 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h
@@ -308,6 +308,7 @@ struct tgsi_exec_machine
    struct tgsi_full_declaration *Declarations;
    uint NumDeclarations;
 
+   struct tgsi_declaration_resource Resources[PIPE_MAX_SHADER_RESOURCES];
 };
 
 struct tgsi_exec_machine *
diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.c b/src/gallium/auxiliary/tgsi/tgsi_info.c
index e59e964..14ed56a 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_info.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_info.c
@@ -175,7 +175,20 @@ static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] =
    { 0, 1, 0, 0, 0, 0, "SWITCH", TGSI_OPCODE_SWITCH },
    { 0, 1, 0, 0, 0, 0, "CASE", TGSI_OPCODE_CASE },
    { 0, 0, 0, 0, 0, 0, "DEFAULT", TGSI_OPCODE_DEFAULT },
-   { 0, 0, 0, 0, 0, 0, "ENDSWITCH", TGSI_OPCODE_ENDSWITCH }
+   { 0, 0, 0, 0, 0, 0, "ENDSWITCH", TGSI_OPCODE_ENDSWITCH },
+
+   { 1, 2, 0, 0, 0, 0, "LOAD",        TGSI_OPCODE_LOAD },
+   { 1, 2, 0, 0, 0, 0, "LOAD_MS",     TGSI_OPCODE_LOAD_MS },
+   { 1, 3, 0, 0, 0, 0, "SAMPLE",      TGSI_OPCODE_SAMPLE },
+   { 1, 4, 0, 0, 0, 0, "SAMPLE_B",    TGSI_OPCODE_SAMPLE_B },
+   { 1, 4, 0, 0, 0, 0, "SAMPLE_C",    TGSI_OPCODE_SAMPLE_C },
+   { 1, 4, 0, 0, 0, 0, "SAMPLE_C_LZ", TGSI_OPCODE_SAMPLE_C_LZ },
+   { 1, 5, 0, 0, 0, 0, "SAMPLE_D",    TGSI_OPCODE_SAMPLE_D },
+   { 1, 3, 0, 0, 0, 0, "SAMPLE_L",    TGSI_OPCODE_SAMPLE_L },
+   { 1, 3, 0, 0, 0, 0, "GATHER4",     TGSI_OPCODE_GATHER4 },
+   { 1, 2, 0, 0, 0, 0, "RESINFO",     TGSI_OPCODE_RESINFO },
+   { 1, 2, 0, 0, 0, 0, "SAMPLE_POS",  TGSI_OPCODE_SAMPLE_POS },
+   { 1, 2, 0, 0, 0, 0, "SAMPLE_INFO", TGSI_OPCODE_SAMPLE_INFO },
 };
 
 const struct tgsi_opcode_info *
diff --git a/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
index b3123ed..b5d4504 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
@@ -168,6 +168,19 @@ OP01(CASE)
 OP00(DEFAULT)
 OP00(ENDSWITCH)
 
+OP12(LOAD)
+OP12(LOAD_MS)
+OP13(SAMPLE)
+OP14(SAMPLE_B)
+OP14(SAMPLE_C)
+OP14(SAMPLE_C_LZ)
+OP15(SAMPLE_D)
+OP13(SAMPLE_L)
+OP13(GATHER4)
+OP12(RESINFO)
+OP13(SAMPLE_POS)
+OP12(SAMPLE_INFO)
+
 
 #undef OP00
 #undef OP01
@@ -180,6 +193,10 @@ OP00(ENDSWITCH)
 #undef OP14
 #endif
 
+#ifdef OP15
+#undef OP15
+#endif
+
 #undef OP00_LBL
 #undef OP01_LBL
 
diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.c b/src/gallium/auxiliary/tgsi/tgsi_parse.c
index 1891203..fb36f9d 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_parse.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_parse.c
@@ -128,6 +128,10 @@ tgsi_parse_token(
          }
       }
 
+      if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
+         next_token(ctx, &decl->Resource);
+      }
+
       break;
    }
 
diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.h b/src/gallium/auxiliary/tgsi/tgsi_parse.h
index 2aafa2a..b7a3c9b 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_parse.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_parse.h
@@ -69,6 +69,7 @@ struct tgsi_full_declaration
    struct tgsi_declaration_dimension Dim;
    struct tgsi_declaration_semantic Semantic;
    struct tgsi_immediate_array_data ImmediateData;
+   struct tgsi_declaration_resource Resource;
 };
 
 struct tgsi_full_immediate
@@ -84,7 +85,7 @@ struct tgsi_full_property
 };
 
 #define TGSI_FULL_MAX_DST_REGISTERS 2
-#define TGSI_FULL_MAX_SRC_REGISTERS 4 /* TXD has 4 */
+#define TGSI_FULL_MAX_SRC_REGISTERS 5 /* SAMPLE_D has 5 */
 
 struct tgsi_full_instruction
 {
diff --git a/src/gallium/auxiliary/tgsi/tgsi_sanity.c b/src/gallium/auxiliary/tgsi/tgsi_sanity.c
index acbff10..509c534 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_sanity.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_sanity.c
@@ -258,7 +258,8 @@ static const char *file_names[TGSI_FILE_COUNT] =
    "PRED",
    "SV",
    "IMMX",
-   "TEMPX"
+   "TEMPX",
+   "RES"
 };
 
 static boolean
diff --git a/src/gallium/auxiliary/tgsi/tgsi_text.c b/src/gallium/auxiliary/tgsi/tgsi_text.c
index 819b072..1eac762 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_text.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_text.c
@@ -283,7 +283,8 @@ static const char *file_names[TGSI_FILE_COUNT] =
    "PRED",
    "SV",
    "IMMX",
-   "TEMPX"
+   "TEMPX",
+   "RES"
 };
 
 static boolean
@@ -828,6 +829,15 @@ static const char *texture_names[TGSI_TEXTURE_COUNT] =
    "SHADOWRECT"
 };
 
+static const char *type_names[] =
+{
+   "UNORM",
+   "SNORM",
+   "SINT",
+   "UINT",
+   "FLOAT"
+};
+
 static boolean
 match_inst_mnemonic(const char **pcur,
                     const struct tgsi_opcode_info *info)
@@ -1104,42 +1114,113 @@ static boolean parse_declaration( struct translate_ctx *ctx )
    cur = ctx->cur;
    eat_opt_white( &cur );
    if (*cur == ',' && !is_vs_input) {
-      uint i;
+      uint i, j;
 
       cur++;
       eat_opt_white( &cur );
-      for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
-         if (str_match_no_case( &cur, semantic_names[i] )) {
-            const char *cur2 = cur;
-            uint index;
-
-            if (is_digit_alpha_underscore( cur ))
-               continue;
-            eat_opt_white( &cur2 );
-            if (*cur2 == '[') {
-               cur2++;
-               eat_opt_white( &cur2 );
-               if (!parse_uint( &cur2, &index )) {
-                  report_error( ctx, "Expected literal integer" );
+      if (file == TGSI_FILE_RESOURCE) {
+         for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
+            if (str_match_no_case(&cur, texture_names[i])) {
+               if (!is_digit_alpha_underscore(cur)) {
+                  decl.Resource.Resource = i;
+                  break;
+               }
+            }
+         }
+         if (i == TGSI_TEXTURE_COUNT) {
+            report_error(ctx, "Expected texture target");
+            return FALSE;
+         }
+         eat_opt_white( &cur );
+         if (*cur != ',') {
+            report_error( ctx, "Expected `,'" );
+            return FALSE;
+         }
+         ++cur;
+         eat_opt_white( &cur );
+         for (j = 0; j < 4; ++j) {
+            for (i = 0; i < PIPE_TYPE_COUNT; ++i) {
+               if (str_match_no_case(&cur, type_names[i])) {
+                  if (!is_digit_alpha_underscore(cur)) {
+                     switch (j) {
+                     case 0:
+                        decl.Resource.ReturnTypeX = i;
+                        break;
+                     case 1:
+                        decl.Resource.ReturnTypeY = i;
+                        break;
+                     case 2:
+                        decl.Resource.ReturnTypeZ = i;
+                        break;
+                     case 3:
+                        decl.Resource.ReturnTypeW = i;
+                        break;
+                     default:
+                        assert(0);
+                     }
+                     break;
+                  }
+               }
+            }
+            if (i == PIPE_TYPE_COUNT) {
+               if (j == 0 || j >  2) {
+                  report_error(ctx, "Expected type name");
                   return FALSE;
                }
+               break;
+            } else {
+               const char *cur2 = cur;
                eat_opt_white( &cur2 );
-               if (*cur2 != ']') {
-                  report_error( ctx, "Expected `]'" );
-                  return FALSE;
+               if (*cur2 == ',') {
+                  cur2++;
+                  eat_opt_white( &cur2 );
+                  cur = cur2;
+                  continue;
+               } else
+                  break;
+            }
+         }
+         if (j < 4) {
+            decl.Resource.ReturnTypeY =
+               decl.Resource.ReturnTypeZ =
+               decl.Resource.ReturnTypeW =
+               decl.Resource.ReturnTypeX;
+         }
+         ctx->cur = cur;
+      } else {
+         for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
+            if (str_match_no_case( &cur, semantic_names[i] )) {
+               const char *cur2 = cur;
+               uint index;
+
+               if (is_digit_alpha_underscore( cur ))
+                  continue;
+               eat_opt_white( &cur2 );
+               if (*cur2 == '[') {
+                  cur2++;
+                  eat_opt_white( &cur2 );
+                  if (!parse_uint( &cur2, &index )) {
+                     report_error( ctx, "Expected literal integer" );
+                     return FALSE;
+                  }
+                  eat_opt_white( &cur2 );
+                  if (*cur2 != ']') {
+                     report_error( ctx, "Expected `]'" );
+                     return FALSE;
+                  }
+                  cur2++;
+
+                  decl.Semantic.Index = index;
+
+                  cur = cur2;
                }
-               cur2++;
 
-               decl.Semantic.Index = index;
+               decl.Declaration.Semantic = 1;
+               decl.Semantic.Name = i;
 
-               cur = cur2;
+               ctx->cur = cur;
+               break;
             }
-
-            decl.Declaration.Semantic = 1;
-            decl.Semantic.Name = i;
-
-            ctx->cur = cur;
-            break;
          }
       }
    } else if (is_imm_array) {
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
index 02de12d..4564ab8 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
@@ -1,6 +1,6 @@
 /**************************************************************************
  * 
- * Copyright 2009 VMware, Inc.
+ * Copyright 2009-2010 VMware, Inc.
  * All Rights Reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -47,6 +47,7 @@ union tgsi_any_token {
    struct tgsi_declaration_range decl_range;
    struct tgsi_declaration_dimension decl_dim;
    struct tgsi_declaration_semantic decl_semantic;
+   struct tgsi_declaration_resource decl_resource;
    struct tgsi_immediate imm;
    union  tgsi_immediate_data imm_data;
    struct tgsi_instruction insn;
@@ -137,6 +138,16 @@ struct ureg_program
    struct ureg_src sampler[PIPE_MAX_SAMPLERS];
    unsigned nr_samplers;
 
+   struct {
+      unsigned index;
+      unsigned target;
+      unsigned return_type_x;
+      unsigned return_type_y;
+      unsigned return_type_z;
+      unsigned return_type_w;
+   } resource[PIPE_MAX_SHADER_RESOURCES];
+   unsigned nr_resources;
+
    unsigned temps_active[UREG_MAX_TEMP / 32];
    unsigned nr_temps;
 
@@ -578,6 +589,41 @@ struct ureg_src ureg_DECL_sampler( struct ureg_program *ureg,
    return ureg->sampler[0];
 }
 
+/*
+ * Allocate a new shader resource.
+ */
+struct ureg_src
+ureg_DECL_resource(struct ureg_program *ureg,
+                   unsigned index,
+                   unsigned target,
+                   unsigned return_type_x,
+                   unsigned return_type_y,
+                   unsigned return_type_z,
+                   unsigned return_type_w)
+{
+   struct ureg_src reg = ureg_src_register(TGSI_FILE_RESOURCE, index);
+   uint i;
+
+   for (i = 0; i < ureg->nr_resources; i++) {
+      if (ureg->resource[i].index == index) {
+         return reg;
+      }
+   }
+
+   if (i < PIPE_MAX_SHADER_RESOURCES) {
+      ureg->resource[i].index = index;
+      ureg->resource[i].target = target;
+      ureg->resource[i].return_type_x = return_type_x;
+      ureg->resource[i].return_type_y = return_type_y;
+      ureg->resource[i].return_type_z = return_type_z;
+      ureg->resource[i].return_type_w = return_type_w;
+      ureg->nr_resources++;
+      return reg;
+   }
+
+   assert(0);
+   return reg;
+}
 
 static int
 match_or_expand_immediate( const unsigned *v,
@@ -821,9 +867,10 @@ ureg_emit_dst( struct ureg_program *ureg,
    assert(dst.File != TGSI_FILE_CONSTANT);
    assert(dst.File != TGSI_FILE_INPUT);
    assert(dst.File != TGSI_FILE_SAMPLER);
+   assert(dst.File != TGSI_FILE_RESOURCE);
    assert(dst.File != TGSI_FILE_IMMEDIATE);
    assert(dst.File < TGSI_FILE_COUNT);
-   
+
    out[n].value = 0;
    out[n].dst.File = dst.File;
    out[n].dst.WriteMask = dst.WriteMask;
@@ -1206,6 +1253,36 @@ emit_decl_range2D(struct ureg_program *ureg,
 }
 
 static void
+emit_decl_resource(struct ureg_program *ureg,
+                   unsigned index,
+                   unsigned target,
+                   unsigned return_type_x,
+                   unsigned return_type_y,
+                   unsigned return_type_z,
+                   unsigned return_type_w )
+{
+   union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3);
+
+   out[0].value = 0;
+   out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
+   out[0].decl.NrTokens = 3;
+   out[0].decl.File = TGSI_FILE_RESOURCE;
+   out[0].decl.UsageMask = 0xf;
+   out[0].decl.Interpolate = TGSI_INTERPOLATE_CONSTANT;
+
+   out[1].value = 0;
+   out[1].decl_range.First = index;
+   out[1].decl_range.Last = index;
+
+   out[2].value = 0;
+   out[2].decl_resource.Resource    = target;
+   out[2].decl_resource.ReturnTypeX = return_type_x;
+   out[2].decl_resource.ReturnTypeY = return_type_y;
+   out[2].decl_resource.ReturnTypeZ = return_type_z;
+   out[2].decl_resource.ReturnTypeW = return_type_w;
+}
+
+static void
 emit_immediate( struct ureg_program *ureg,
                 const unsigned *v,
                 unsigned type )
@@ -1341,6 +1418,16 @@ static void emit_decls( struct ureg_program *ureg )
                        ureg->sampler[i].Index, 1 );
    }
 
+   for (i = 0; i < ureg->nr_resources; i++) {
+      emit_decl_resource(ureg,
+                         ureg->resource[i].index,
+                         ureg->resource[i].target,
+                         ureg->resource[i].return_type_x,
+                         ureg->resource[i].return_type_y,
+                         ureg->resource[i].return_type_z,
+                         ureg->resource[i].return_type_w);
+   }
+
    if (ureg->const_decls.nr_constant_ranges) {
       for (i = 0; i < ureg->const_decls.nr_constant_ranges; i++) {
          emit_decl_range(ureg,
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h
index 807128a..b8d193f 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_ureg.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h
@@ -270,6 +270,15 @@ struct ureg_src
 ureg_DECL_sampler( struct ureg_program *,
                    unsigned index );
 
+struct ureg_src
+ureg_DECL_resource(struct ureg_program *,
+                   unsigned index,
+                   unsigned target,
+                   unsigned return_type_x,
+                   unsigned return_type_y,
+                   unsigned return_type_z,
+                   unsigned return_type_w );
+
 
 static INLINE struct ureg_src
 ureg_imm4f( struct ureg_program *ureg,
@@ -733,6 +742,66 @@ static INLINE void ureg_##op( struct ureg_program *ureg,                \
 }
 
 
+#define OP14( op )                                                      \
+static INLINE void ureg_##op( struct ureg_program *ureg,                \
+                              struct ureg_dst dst,                      \
+                              struct ureg_src src0,                     \
+                              struct ureg_src src1,                     \
+                              struct ureg_src src2,                     \
+                              struct ureg_src src3 )                    \
+{                                                                       \
+   unsigned opcode = TGSI_OPCODE_##op;                                  \
+   unsigned insn = ureg_emit_insn(ureg,                                 \
+                                  opcode,                               \
+                                  dst.Saturate,                         \
+                                  dst.Predicate,                        \
+                                  dst.PredNegate,                       \
+                                  dst.PredSwizzleX,                     \
+                                  dst.PredSwizzleY,                     \
+                                  dst.PredSwizzleZ,                     \
+                                  dst.PredSwizzleW,                     \
+                                  1,                                    \
+                                  4).insn_token;                        \
+   ureg_emit_dst( ureg, dst );                                          \
+   ureg_emit_src( ureg, src0 );                                         \
+   ureg_emit_src( ureg, src1 );                                         \
+   ureg_emit_src( ureg, src2 );                                         \
+   ureg_emit_src( ureg, src3 );                                         \
+   ureg_fixup_insn_size( ureg, insn );                                  \
+}
+
+
+#define OP15( op )                                                      \
+static INLINE void ureg_##op( struct ureg_program *ureg,                \
+                              struct ureg_dst dst,                      \
+                              struct ureg_src src0,                     \
+                              struct ureg_src src1,                     \
+                              struct ureg_src src2,                     \
+                              struct ureg_src src3,                     \
+                              struct ureg_src src4 )                    \
+{                                                                       \
+   unsigned opcode = TGSI_OPCODE_##op;                                  \
+   unsigned insn = ureg_emit_insn(ureg,                                 \
+                                  opcode,                               \
+                                  dst.Saturate,                         \
+                                  dst.Predicate,                        \
+                                  dst.PredNegate,                       \
+                                  dst.PredSwizzleX,                     \
+                                  dst.PredSwizzleY,                     \
+                                  dst.PredSwizzleZ,                     \
+                                  dst.PredSwizzleW,                     \
+                                  1,                                    \
+                                  5).insn_token;                        \
+   ureg_emit_dst( ureg, dst );                                          \
+   ureg_emit_src( ureg, src0 );                                         \
+   ureg_emit_src( ureg, src1 );                                         \
+   ureg_emit_src( ureg, src2 );                                         \
+   ureg_emit_src( ureg, src3 );                                         \
+   ureg_emit_src( ureg, src4 );                                         \
+   ureg_fixup_insn_size( ureg, insn );                                  \
+}
+
+
 /* Use a template include to generate a correctly-typed ureg_OP()
  * function for each TGSI opcode:
  */
diff --git a/src/gallium/docs/source/tgsi.rst b/src/gallium/docs/source/tgsi.rst
index d986e66..4987720 100644
--- a/src/gallium/docs/source/tgsi.rst
+++ b/src/gallium/docs/source/tgsi.rst
@@ -1250,6 +1250,110 @@ This opcode is the inverse of :opcode:`DFRACEXP`.
    dst.zw = \sqrt{src.zw}
 
 
+.. _resourceopcodes:
+
+Resource Access Opcodes
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Those opcodes follow very closely semantics of the respective Direct3D
+instructions. If in doubt double check Direct3D documentation.
+
+.. opcode:: LOAD - Simplified alternative to the "SAMPLE" instruction.
+               Using the provided integer address, LOAD fetches data
+               from the specified buffer/texture without any filtering.
+               The source data may come from any resource type other
+               than CUBE.
+               LOAD dst, address, resource
+               e.g.
+               LOAD TEMP[0], TEMP[1], RES[0]
+
+.. opcode:: LOAD_MS - Just like LOAD but allows fetch data from
+               multi-sampled surfaces.
+
+.. opcode:: SAMPLE - Using provided address, sample data from the
+               specified texture using the filtering mode identified
+               by the gven sampler. The source data may come from
+               any resource type other than buffers.
+               SAMPLE dst, address, resource, sampler
+               e.g.
+               SAMPLE TEMP[0], TEMP[1], RES[0], SAMP[0]
+
+.. opcode:: SAMPLE_B - Just like the SAMPLE instruction with the
+               exception that an additiona bias is applied to the
+               level of detail computed as part of the instruction
+               execution.
+               SAMPLE_B dst, address, resource, sampler, lod_bias
+               e.g.
+               SAMPLE_B TEMP[0], TEMP[1], RES[0], SAMP[0], TEMP[2].x
+
+.. opcode:: SAMPLE_C - Similar to the SAMPLE instruction but it 
+               performs a comparison filter. The operands to SAMPLE_C
+               are identical to SAMPLE, except that tere is an additional
+               float32 operand, reference value, which must be a register
+               with single-component, or a scalar literal.
+               SAMPLE_C makes the hardware use the current samplers
+               compare_func (in pipe_sampler_state) to compare
+               reference value against the red component value for the
+               surce resource at each texel that the currently configured
+               texture filter covers based on the provided coordinates.
+               SAMPLE_C dst, address, resource.r, sampler, ref_value
+               e.g.
+               SAMPLE_C TEMP[0], TEMP[1], RES[0].r, SAMP[0], TEMP[2].x
+
+.. opcode:: SAMPLE_C_LZ - Same as SAMPLE_C, but LOD is 0 and derivatives
+               are ignored. The LZ stands for level-zero.
+               SAMPLE_C_LZ dst, address, resource.r, sampler, ref_value
+               e.g.
+               SAMPLE_C_LZ TEMP[0], TEMP[1], RES[0].r, SAMP[0], TEMP[2].x
+
+
+.. opcode:: SAMPLE_D - SAMPLE_D is identical to the SAMPLE opcode except
+               that the derivatives for the source address in the x
+               direction and the y direction are provided by extra
+               parameters.
+               SAMPLE_D dst, address, resource, sampler, der_x, der_y
+               e.g.
+               SAMPLE_D TEMP[0], TEMP[1], RES[0], SAMP[0], TEMP[2], TEMP[3]
+
+.. opcode:: SAMPLE_L - SAMPLE_L is identical to the SAMPLE opcode except
+               that the LOD is provided directly as a scalar value,
+               representing no anisotropy. Source addresses A channel
+               is used as the LOD.
+               SAMPLE_L dst, address, resource, sampler
+               e.g.
+               SAMPLE_L TEMP[0], TEMP[1], RES[0], SAMP[0]
+
+
+.. opcode:: GATHER4 - Gathers the four texels to be used in a bi-linear
+               filtering operation and packs them into a single register.
+               Only woth with 2D, 2D array, cubemaps, and cubemaps arrays.
+               For 2D textures, only the addressing modes of the sampler and
+               the top level of any mip pyramid are used. Set W to zero.
+               It behaves like the SAMPLE instruction, but a filtered
+               sample is not generated. The four samples that contribute
+               to filtering are places into xyzw in cunter-clockwise order,
+               starting with the (u,v) texture coordinate delta at the
+               following locations (-, +), (+, +), (+, -), (-, -), where
+               the magnitude of the deltas are half a texel.
+
+
+.. opcode:: RESINFO - query the dimentions of a given input buffer.
+               dst receives width, height, depth or array size and
+               total mip count (also can be slected by writemask).
+               RESINFO dst, src_mip_level, resource
+               e.g.
+               RESINFO TEMP[0], TEMP[1].x, RES[0]
+
+.. opcode:: SAMPLE_POS - query the position of a given sample.
+               dst receives float4 (x, y, 0, 0) indicated where the
+               sample is located. If the resource is not a multi-sample
+               resource and not a render target, the result is 0.
+
+.. opcode:: SAMPLE_INFO - dst receives number of components in x.
+               If the resource is not a multi-sample resource and 
+               not a render target, the result is 0.
+
+
 Explanation of symbols used
 ------------------------------
 
@@ -1332,6 +1436,8 @@ wrapping when interpolating by the rasteriser. If TGSI_CYLINDRICAL_WRAP_X
 is set to 1, the X component should be interpolated according to cylindrical
 wrapping rules.
 
+If file is TGSI_FILE_RESOURCE, a Declaration Resource token follows.
+
 
 Declaration Semantic
 ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1475,6 +1581,23 @@ is a writable stencil reference value. Only the Y component is writable.
 This allows the fragment shader to change the fragments stencilref value.
 
 
+Declaration Resource
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+   Follows Declaration token if file is TGSI_FILE_RESOURCE.
+
+   DCL RES[#], resource, type(s)
+
+   Declares a shader input resource and assigns it to a RES[#]
+   register.
+
+   resource can be one of BUFFER, 1D, 2D, 3D, CUBE, 1DArray and
+   2DArray.
+
+   type must be 1 or 4 entries (if specifying on a per-component
+   level) out of UNORM, SNORM, SINT, UINT and FLOAT.
+
+
 Properties
 ^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/src/gallium/include/pipe/p_format.h b/src/gallium/include/pipe/p_format.h
index 74a9939..c8904d4 100644
--- a/src/gallium/include/pipe/p_format.h
+++ b/src/gallium/include/pipe/p_format.h
@@ -33,6 +33,16 @@
 extern "C" {
 #endif
 
+
+enum pipe_type {
+   PIPE_TYPE_UNORM = 0,
+   PIPE_TYPE_SNORM,
+   PIPE_TYPE_SINT,
+   PIPE_TYPE_UINT,
+   PIPE_TYPE_FLOAT,
+   PIPE_TYPE_COUNT
+};
+
 /**
  * Texture/surface image formats (preliminary)
  */
diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h
index 0a9e141..6e5a48b 100644
--- a/src/gallium/include/pipe/p_shader_tokens.h
+++ b/src/gallium/include/pipe/p_shader_tokens.h
@@ -75,6 +75,7 @@ enum tgsi_file_type {
    TGSI_FILE_SYSTEM_VALUE        =9,
    TGSI_FILE_IMMEDIATE_ARRAY     =10,
    TGSI_FILE_TEMPORARY_ARRAY     =11,
+   TGSI_FILE_RESOURCE            =12,
    TGSI_FILE_COUNT      /**< how many TGSI_FILE_ types */
 };
 
@@ -153,6 +154,14 @@ struct tgsi_declaration_semantic
    unsigned Padding        : 8;
 };
 
+struct tgsi_declaration_resource {
+   unsigned Resource    : 8; /**< one of TGSI_TEXTURE_ */
+   unsigned ReturnTypeX : 6; /**< one of enum pipe_type */
+   unsigned ReturnTypeY : 6; /**< one of enum pipe_type */
+   unsigned ReturnTypeZ : 6; /**< one of enum pipe_type */
+   unsigned ReturnTypeW : 6; /**< one of enum pipe_type */
+};
+
 #define TGSI_IMM_FLOAT32   0
 #define TGSI_IMM_UINT32    1
 #define TGSI_IMM_INT32     2
@@ -339,7 +348,22 @@ struct tgsi_property_data {
 #define TGSI_OPCODE_CASE                142
 #define TGSI_OPCODE_DEFAULT             143
 #define TGSI_OPCODE_ENDSWITCH           144
-#define TGSI_OPCODE_LAST                145
+
+/* resource related opcodes */
+#define TGSI_OPCODE_LOAD                145
+#define TGSI_OPCODE_LOAD_MS             146
+#define TGSI_OPCODE_SAMPLE              147
+#define TGSI_OPCODE_SAMPLE_B            148
+#define TGSI_OPCODE_SAMPLE_C            149
+#define TGSI_OPCODE_SAMPLE_C_LZ         150
+#define TGSI_OPCODE_SAMPLE_D            151
+#define TGSI_OPCODE_SAMPLE_L            152
+#define TGSI_OPCODE_GATHER4             153
+#define TGSI_OPCODE_RESINFO             154
+#define TGSI_OPCODE_SAMPLE_POS          155
+#define TGSI_OPCODE_SAMPLE_INFO         156
+
+#define TGSI_OPCODE_LAST                157
 
 #define TGSI_SAT_NONE            0  /* do not saturate */
 #define TGSI_SAT_ZERO_ONE        1  /* clamp to [0,1] */
diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
index 226ae86..d5c767a 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -62,6 +62,7 @@ extern "C" {
 #define PIPE_MAX_GEOMETRY_SAMPLERS  16
 #define PIPE_MAX_SHADER_INPUTS    32
 #define PIPE_MAX_SHADER_OUTPUTS   32
+#define PIPE_MAX_SHADER_RESOURCES 32
 #define PIPE_MAX_TEXTURE_LEVELS   16
 #define PIPE_MAX_SO_BUFFERS        4
 
diff --git a/src/gallium/tests/graw/SConscript b/src/gallium/tests/graw/SConscript
index 3341b88..565fa52 100644
--- a/src/gallium/tests/graw/SConscript
+++ b/src/gallium/tests/graw/SConscript
@@ -24,6 +24,7 @@ progs = [
     'gs-test',
     'shader-leak',
     'tri-gs',
+    'quad-sample',
 ]
 
 for name in progs:




More information about the mesa-commit mailing list