clover: Define helper classes for the new object model.
[mesa.git] / src / gallium / drivers / ilo / ilo_shader.c
index c2d5623fc2622c40456c6c587ee8928f1ab9265a..480b477181696456c434cd0e101833a68a5da72d 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "tgsi/tgsi_parse.h"
 #include "intel_winsys.h"
+#include "brw_defines.h" /* for SBE setup */
 
 #include "shader/ilo_shader_internal.h"
 #include "ilo_state.h"
@@ -272,6 +273,13 @@ ilo_shader_variant_init(struct ilo_shader_variant *variant,
       break;
    }
 
+   /* use PCB unless constant buffer 0 is not in user buffer  */
+   if ((ilo->cbuf[info->type].enabled_mask & 0x1) &&
+       !ilo->cbuf[info->type].cso[0].user_buffer)
+      variant->use_pcb = false;
+   else
+      variant->use_pcb = true;
+
    num_views = ilo->view[info->type].count;
    assert(info->num_samplers <= num_views);
 
@@ -340,6 +348,8 @@ ilo_shader_variant_guess(struct ilo_shader_variant *variant,
       break;
    }
 
+   variant->use_pcb = true;
+
    variant->num_sampler_views = info->num_samplers;
    for (i = 0; i < info->num_samplers; i++) {
       if (info->shadow_samplers & (1 << i)) {
@@ -610,6 +620,42 @@ ilo_shader_state_search_variant(struct ilo_shader_state *state,
    return sh;
 }
 
+static void
+copy_so_info(struct ilo_shader *sh,
+             const struct pipe_stream_output_info *so_info)
+{
+   unsigned i, attr;
+
+   if (!so_info->num_outputs)
+      return;
+
+   sh->so_info = *so_info;
+
+   for (i = 0; i < so_info->num_outputs; i++) {
+      /* figure out which attribute is sourced */
+      for (attr = 0; attr < sh->out.count; attr++) {
+         const int reg_idx = sh->out.register_indices[attr];
+         if (reg_idx == so_info->output[i].register_index)
+            break;
+      }
+
+      if (attr < sh->out.count) {
+         sh->so_info.output[i].register_index = attr;
+      }
+      else {
+         assert(!"stream output an undefined register");
+         sh->so_info.output[i].register_index = 0;
+      }
+
+      /* PSIZE is at W channel */
+      if (sh->out.semantic_names[attr] == TGSI_SEMANTIC_PSIZE) {
+         assert(so_info->output[i].start_component == 0);
+         assert(so_info->output[i].num_components == 1);
+         sh->so_info.output[i].start_component = 3;
+      }
+   }
+}
+
 /**
  * Add a shader variant to the shader state.
  */
@@ -643,6 +689,8 @@ ilo_shader_state_add_variant(struct ilo_shader_state *state,
 
    sh->variant = *variant;
 
+   copy_so_info(sh, &state->info.stream_output);
+
    ilo_shader_state_add_shader(state, sh);
 
    return sh;
@@ -707,8 +755,9 @@ ilo_shader_create_vs(const struct ilo_dev_info *dev,
    shader = ilo_shader_state_create(precompile, PIPE_SHADER_VERTEX, state);
 
    /* states used in ilo_shader_variant_init() */
-   shader->info.non_orthogonal_states = ILO_DIRTY_VERTEX_SAMPLER_VIEWS |
-                                        ILO_DIRTY_RASTERIZER;
+   shader->info.non_orthogonal_states = ILO_DIRTY_VIEW_VS |
+                                        ILO_DIRTY_RASTERIZER |
+                                        ILO_DIRTY_CBUF;
 
    return shader;
 }
@@ -723,9 +772,10 @@ ilo_shader_create_gs(const struct ilo_dev_info *dev,
    shader = ilo_shader_state_create(precompile, PIPE_SHADER_GEOMETRY, state);
 
    /* states used in ilo_shader_variant_init() */
-   shader->info.non_orthogonal_states = ILO_DIRTY_GEOMETRY_SAMPLER_VIEWS |
+   shader->info.non_orthogonal_states = ILO_DIRTY_VIEW_GS |
                                         ILO_DIRTY_VS |
-                                        ILO_DIRTY_RASTERIZER;
+                                        ILO_DIRTY_RASTERIZER |
+                                        ILO_DIRTY_CBUF;
 
    return shader;
 }
@@ -740,9 +790,10 @@ ilo_shader_create_fs(const struct ilo_dev_info *dev,
    shader = ilo_shader_state_create(precompile, PIPE_SHADER_FRAGMENT, state);
 
    /* states used in ilo_shader_variant_init() */
-   shader->info.non_orthogonal_states = ILO_DIRTY_FRAGMENT_SAMPLER_VIEWS |
+   shader->info.non_orthogonal_states = ILO_DIRTY_VIEW_FS |
                                         ILO_DIRTY_RASTERIZER |
-                                        ILO_DIRTY_FRAMEBUFFER;
+                                        ILO_DIRTY_FB |
+                                        ILO_DIRTY_CBUF;
 
    return shader;
 }
@@ -810,6 +861,181 @@ ilo_shader_select_kernel(struct ilo_shader_state *shader,
    return (shader->shader != cur);
 }
 
+static int
+route_attr(const int *semantics, const int *indices, int len,
+           int semantic, int index)
+{
+   int i;
+
+   for (i = 0; i < len; i++) {
+      if (semantics[i] == semantic && indices[i] == index)
+         return i;
+   }
+
+   /* failed to match for COLOR, try BCOLOR */
+   if (semantic == TGSI_SEMANTIC_COLOR) {
+      for (i = 0; i < len; i++) {
+         if (semantics[i] == TGSI_SEMANTIC_BCOLOR && indices[i] == index)
+            return i;
+      }
+   }
+
+   return -1;
+}
+
+/**
+ * Select a routing for the given source shader and rasterizer state.
+ *
+ * \return true if a different routing is selected
+ */
+bool
+ilo_shader_select_kernel_routing(struct ilo_shader_state *shader,
+                                 const struct ilo_shader_state *source,
+                                 const struct ilo_rasterizer_state *rasterizer)
+{
+   const uint32_t sprite_coord_enable = rasterizer->state.sprite_coord_enable;
+   const bool light_twoside = rasterizer->state.light_twoside;
+   struct ilo_shader *kernel = shader->shader;
+   struct ilo_kernel_routing *routing = &kernel->routing;
+   const int *src_semantics, *src_indices;
+   int src_len, max_src_slot;
+   int dst_len, dst_slot;
+
+   /* we are constructing 3DSTATE_SBE here */
+   assert(shader->info.dev->gen >= ILO_GEN(6) &&
+          shader->info.dev->gen <= ILO_GEN(7.5));
+
+   assert(kernel);
+
+   if (source) {
+      assert(source->shader);
+      src_semantics = source->shader->out.semantic_names;
+      src_indices = source->shader->out.semantic_indices;
+      src_len = source->shader->out.count;
+   }
+   else {
+      src_semantics = kernel->in.semantic_names;
+      src_indices = kernel->in.semantic_indices;
+      src_len = kernel->in.count;
+   }
+
+   /* no change */
+   if (kernel->routing_initialized &&
+       routing->source_skip + routing->source_len <= src_len &&
+       kernel->routing_sprite_coord_enable == sprite_coord_enable &&
+       !memcmp(kernel->routing_src_semantics,
+          &src_semantics[routing->source_skip],
+          sizeof(kernel->routing_src_semantics[0]) * routing->source_len) &&
+       !memcmp(kernel->routing_src_indices,
+          &src_indices[routing->source_skip],
+          sizeof(kernel->routing_src_indices[0]) * routing->source_len))
+      return false;
+
+   if (source) {
+      /* skip PSIZE and POSITION (how about the optional CLIPDISTs?) */
+      assert(src_semantics[0] == TGSI_SEMANTIC_PSIZE);
+      assert(src_semantics[1] == TGSI_SEMANTIC_POSITION);
+      routing->source_skip = 2;
+
+      routing->source_len = src_len - routing->source_skip;
+      src_semantics += routing->source_skip;
+      src_indices += routing->source_skip;
+   }
+   else {
+      routing->source_skip = 0;
+      routing->source_len = src_len;
+   }
+
+   routing->const_interp_enable = kernel->in.const_interp_enable;
+   routing->point_sprite_enable = 0;
+   routing->swizzle_enable = false;
+
+   assert(kernel->in.count <= Elements(routing->swizzles));
+   dst_len = MIN2(kernel->in.count, Elements(routing->swizzles));
+   max_src_slot = -1;
+
+   for (dst_slot = 0; dst_slot < dst_len; dst_slot++) {
+      const int semantic = kernel->in.semantic_names[dst_slot];
+      const int index = kernel->in.semantic_indices[dst_slot];
+      int src_slot;
+
+      if (semantic == TGSI_SEMANTIC_GENERIC &&
+          (sprite_coord_enable & (1 << index)))
+         routing->point_sprite_enable |= 1 << dst_slot;
+
+      if (source) {
+         src_slot = route_attr(src_semantics, src_indices,
+               routing->source_len, semantic, index);
+
+         /*
+          * The source shader stage does not output this attribute.  The value
+          * is supposed to be undefined, unless the attribute goes through
+          * point sprite replacement or the attribute is
+          * TGSI_SEMANTIC_POSITION.  In all cases, we do not care which source
+          * attribute is picked.
+          *
+          * We should update the kernel code and omit the output of
+          * TGSI_SEMANTIC_POSITION here.
+          */
+         if (src_slot < 0)
+            src_slot = 0;
+      }
+      else {
+         src_slot = dst_slot;
+      }
+
+      routing->swizzles[dst_slot] = src_slot;
+
+      /* use the following slot for two-sided lighting */
+      if (semantic == TGSI_SEMANTIC_COLOR && light_twoside &&
+          src_slot + 1 < routing->source_len &&
+          src_semantics[src_slot + 1] == TGSI_SEMANTIC_BCOLOR &&
+          src_indices[src_slot + 1] == index) {
+         routing->swizzles[dst_slot] |= ATTRIBUTE_SWIZZLE_INPUTATTR_FACING <<
+            ATTRIBUTE_SWIZZLE_SHIFT;
+         src_slot++;
+      }
+
+      if (routing->swizzles[dst_slot] != dst_slot)
+         routing->swizzle_enable = true;
+
+      if (max_src_slot < src_slot)
+         max_src_slot = src_slot;
+   }
+
+   memset(&routing->swizzles[dst_slot], 0, sizeof(routing->swizzles) -
+         sizeof(routing->swizzles[0]) * dst_slot);
+
+   /*
+    * From the Sandy Bridge PRM, volume 2 part 1, page 248:
+    *
+    *     "It is UNDEFINED to set this field (Vertex URB Entry Read Length) to
+    *      0 indicating no Vertex URB data to be read.
+    *
+    *      This field should be set to the minimum length required to read the
+    *      maximum source attribute. The maximum source attribute is indicated
+    *      by the maximum value of the enabled Attribute # Source Attribute if
+    *      Attribute Swizzle Enable is set, Number of Output Attributes-1 if
+    *      enable is not set.
+    *
+    *        read_length = ceiling((max_source_attr+1)/2)
+    *
+    *      [errata] Corruption/Hang possible if length programmed larger than
+    *      recommended"
+    */
+   routing->source_len = max_src_slot + 1;
+
+   /* remember the states of the source */
+   kernel->routing_initialized = true;
+   kernel->routing_sprite_coord_enable = sprite_coord_enable;
+   memcpy(kernel->routing_src_semantics, src_semantics,
+         sizeof(kernel->routing_src_semantics[0]) * routing->source_len);
+   memcpy(kernel->routing_src_indices, src_indices,
+         sizeof(kernel->routing_src_indices[0]) * routing->source_len);
+
+   return true;
+}
+
 /**
  * Return the cache offset of the selected kernel.  This must be called after
  * ilo_shader_select_kernel() and ilo_shader_cache_upload().
@@ -846,6 +1072,12 @@ ilo_shader_get_kernel_param(const struct ilo_shader_state *shader,
    case ILO_KERNEL_URB_DATA_START_REG:
       val = kernel->in.start_grf;
       break;
+   case ILO_KERNEL_SKIP_CBUF0_UPLOAD:
+      val = kernel->skip_cbuf0_upload;
+      break;
+   case ILO_KERNEL_PCB_CBUF0_SIZE:
+      val = kernel->pcb.cbuf0_size;
+      break;
 
    case ILO_KERNEL_VS_INPUT_INSTANCEID:
       val = shader->info.has_instanceid;
@@ -927,3 +1159,29 @@ ilo_shader_get_kernel_cso(const struct ilo_shader_state *shader)
 
    return &kernel->cso;
 }
+
+/**
+ * Return the SO info of the selected kernel.
+ */
+const struct pipe_stream_output_info *
+ilo_shader_get_kernel_so_info(const struct ilo_shader_state *shader)
+{
+   const struct ilo_shader *kernel = shader->shader;
+
+   assert(kernel);
+
+   return &kernel->so_info;
+}
+
+/**
+ * Return the routing info of the selected kernel.
+ */
+const struct ilo_kernel_routing *
+ilo_shader_get_kernel_routing(const struct ilo_shader_state *shader)
+{
+   const struct ilo_shader *kernel = shader->shader;
+
+   assert(kernel);
+
+   return &kernel->routing;
+}