draw: hack around weird primitive id input in gs
authorRoland Scheidegger <sroland@vmware.com>
Thu, 7 Aug 2014 18:34:17 +0000 (20:34 +0200)
committerRoland Scheidegger <sroland@vmware.com>
Fri, 8 Aug 2014 16:54:08 +0000 (18:54 +0200)
The distinction between system values and ordinary inputs is not very
obvious in gallium - further fueled by the fact that they use the same
semantic names.
Still, if there's any value which imho really is a system value, it's the
primitive id input into the gs (while earlier (tessleation) stages could read
it, it is _always_ generated by the system). For some odd reason though (which
I'd classify as a bug but seems too complicated to fix) the glsl compiler in
mesa treats this as an ordinary varying, and everything else after that
(including the state tracker and other drivers) just go along with that.
But input fetching in gs for llvm based draw was definitely limited to the
ordinary (2-dimensional) inputs so only worked with other state trackers,
the code was also additionally relying on tgsi_scan_shader filling
uses_primid correctly which did not happen neither (would set it only for
all stages if it was a system value, but only set it for the fragment shader
if it was an input value).
This fixes piglit glsl-1.50-geometry-primitive-id-restart and primitive-id-in
in llvmpipe.

Reviewed-by: Brian Paul <brianp@vmware.com>
src/gallium/auxiliary/draw/draw_gs.c
src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
src/gallium/auxiliary/tgsi/tgsi_scan.c

index 2b6d2a02821995ed052296920446afd516995fc1..bbf515a9525ff751e00b954195362be69182a71f 100644 (file)
@@ -228,8 +228,7 @@ llvm_fetch_gs_input(struct draw_geometry_shader *shader,
    const float (*input_ptr)[4];
    float (*input_data)[6][PIPE_MAX_SHADER_INPUTS][TGSI_NUM_CHANNELS][TGSI_NUM_CHANNELS] = &shader->gs_input->data;
 
-   shader->llvm_prim_ids[shader->fetched_prim_count] =
-      shader->in_prim_idx;
+   shader->llvm_prim_ids[shader->fetched_prim_count] = shader->in_prim_idx;
 
    input_ptr = shader->input;
 
@@ -244,6 +243,11 @@ llvm_fetch_gs_input(struct draw_geometry_shader *shader,
       for (slot = 0, vs_slot = 0; slot < shader->info.num_inputs; ++slot) {
          if (shader->info.input_semantic_name[slot] == TGSI_SEMANTIC_PRIMID) {
             /* skip. we handle system values through gallivm */
+            /* NOTE: If we hit this case here it's an ordinary input not a sv,
+             * even though it probably should be a sv.
+             * Not sure how to set it up as regular input however if that even,
+             * would make sense so hack around this later in gallivm.
+             */
          } else {
             vs_slot = draw_gs_get_input_index(
                shader->info.input_semantic_name[slot],
index 02a4a526bb21131c0ec5e60458c8578fd249056f..f54e85649c610a1859793b26bacd2a0a7542ebc2 100644 (file)
@@ -1408,12 +1408,24 @@ emit_fetch_gs_input(
 {
    struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
    struct gallivm_state *gallivm = bld->bld_base.base.gallivm;
+   const struct tgsi_shader_info *info = bld->bld_base.info;
    LLVMBuilderRef builder = gallivm->builder;
    LLVMValueRef attrib_index = NULL;
    LLVMValueRef vertex_index = NULL;
    LLVMValueRef swizzle_index = lp_build_const_int32(gallivm, swizzle);
    LLVMValueRef res;
 
+   if (info->input_semantic_name[reg->Register.Index] == TGSI_SEMANTIC_PRIMID) {
+      /* This is really a system value not a regular input */
+      assert(!reg->Register.Indirect);
+      assert(!reg->Dimension.Indirect);
+      res = bld->system_values.prim_id;
+      if (stype != TGSI_TYPE_UNSIGNED && stype != TGSI_TYPE_SIGNED) {
+         res = LLVMBuildBitCast(builder, res, bld_base->base.vec_type, "");
+      }
+      return res;
+   }
+
    if (reg->Register.Indirect) {
       attrib_index = get_indirect_index(bld,
                                         reg->Register.File,
index 563d2c55f60fd3347599040ce03b7f8380fa4d7c..c71bb360bb3f5e371ce975e830256d163b93efeb 100644 (file)
@@ -191,11 +191,11 @@ tgsi_scan_shader(const struct tgsi_token *tokens,
                   info->input_cylindrical_wrap[reg] = (ubyte)fulldecl->Interp.CylindricalWrap;
                   info->num_inputs++;
 
-                  if (procType == TGSI_PROCESSOR_FRAGMENT) {
+                  if (semName == TGSI_SEMANTIC_PRIMID)
+                     info->uses_primid = TRUE;
+                  else if (procType == TGSI_PROCESSOR_FRAGMENT) {
                      if (semName == TGSI_SEMANTIC_POSITION)
                         info->reads_position = TRUE;
-                     else if (semName == TGSI_SEMANTIC_PRIMID)
-                        info->uses_primid = TRUE;
                      else if (semName == TGSI_SEMANTIC_FACE)
                         info->uses_frontface = TRUE;
                   }