i965/vec4: Add support for nonconst sampler indexing in VS visitor
[mesa.git] / src / mesa / drivers / dri / i965 / brw_wm_surface_state.c
index dd96c9bfd3c39e6362c41df822949738ff9e36b1..4a3111ac69cb72e3874a32b4454801f51bc96618 100644 (file)
@@ -73,8 +73,7 @@ translate_tex_target(GLenum target)
       return BRW_SURFACE_CUBE;
 
    default:
-      assert(0);
-      return 0;
+      unreachable("not reached");
    }
 }
 
@@ -101,6 +100,30 @@ brw_get_surface_num_multisamples(unsigned num_samples)
       return BRW_SURFACE_MULTISAMPLECOUNT_1;
 }
 
+void
+brw_configure_w_tiled(const struct intel_mipmap_tree *mt,
+                      bool is_render_target,
+                      unsigned *width, unsigned *height,
+                      unsigned *pitch, uint32_t *tiling, unsigned *format)
+{
+   static const unsigned halign_stencil = 8;
+
+   /* In Y-tiling row is twice as wide as in W-tiling, and subsequently
+    * there are half as many rows.
+    * In addition, mip-levels are accessed manually by the program and
+    * therefore the surface is setup to cover all the mip-levels for one slice.
+    * (Hardware is still used to access individual slices).
+    */
+   *tiling = I915_TILING_Y;
+   *pitch = mt->pitch * 2;
+   *width = ALIGN(mt->total_width, halign_stencil) * 2;
+   *height = (mt->total_height / mt->physical_depth0) / 2;
+
+   if (is_render_target) {
+      *format = BRW_SURFACEFORMAT_R8_UINT;
+   }
+}
+
 
 /**
  * Compute the combination of DEPTH_TEXTURE_MODE and EXT_texture_swizzle
@@ -282,38 +305,64 @@ brw_update_texture_surface(struct gl_context *ctx,
    surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE,
                          6 * 4, 32, surf_offset);
 
-   (void) for_gather;   /* no w/a to apply for this gen */
+   uint32_t tex_format = translate_tex_format(brw, mt->format,
+                                              sampler->sRGBDecode);
+
+   if (for_gather) {
+      /* Sandybridge's gather4 message is broken for integer formats.
+       * To work around this, we pretend the surface is UNORM for
+       * 8 or 16-bit formats, and emit shader instructions to recover
+       * the real INT/UINT value.  For 32-bit formats, we pretend
+       * the surface is FLOAT, and simply reinterpret the resulting
+       * bits.
+       */
+      switch (tex_format) {
+      case BRW_SURFACEFORMAT_R8_SINT:
+      case BRW_SURFACEFORMAT_R8_UINT:
+         tex_format = BRW_SURFACEFORMAT_R8_UNORM;
+         break;
+
+      case BRW_SURFACEFORMAT_R16_SINT:
+      case BRW_SURFACEFORMAT_R16_UINT:
+         tex_format = BRW_SURFACEFORMAT_R16_UNORM;
+         break;
+
+      case BRW_SURFACEFORMAT_R32_SINT:
+      case BRW_SURFACEFORMAT_R32_UINT:
+         tex_format = BRW_SURFACEFORMAT_R32_FLOAT;
+         break;
+
+      default:
+         break;
+      }
+   }
 
    surf[0] = (translate_tex_target(tObj->Target) << BRW_SURFACE_TYPE_SHIFT |
              BRW_SURFACE_MIPMAPLAYOUT_BELOW << BRW_SURFACE_MIPLAYOUT_SHIFT |
              BRW_SURFACE_CUBEFACE_ENABLES |
-             (translate_tex_format(brw,
-                                    mt->format,
-                                   sampler->sRGBDecode) <<
-              BRW_SURFACE_FORMAT_SHIFT));
+             tex_format << BRW_SURFACE_FORMAT_SHIFT);
 
-   surf[1] = intelObj->mt->region->bo->offset64 + intelObj->mt->offset; /* reloc */
+   surf[1] = mt->bo->offset64 + mt->offset; /* reloc */
 
    surf[2] = ((intelObj->_MaxLevel - tObj->BaseLevel) << BRW_SURFACE_LOD_SHIFT |
              (mt->logical_width0 - 1) << BRW_SURFACE_WIDTH_SHIFT |
              (mt->logical_height0 - 1) << BRW_SURFACE_HEIGHT_SHIFT);
 
-   surf[3] = (brw_get_surface_tiling_bits(intelObj->mt->region->tiling) |
+   surf[3] = (brw_get_surface_tiling_bits(mt->tiling) |
              (mt->logical_depth0 - 1) << BRW_SURFACE_DEPTH_SHIFT |
-             (intelObj->mt->region->pitch - 1) <<
-             BRW_SURFACE_PITCH_SHIFT);
+             (mt->pitch - 1) << BRW_SURFACE_PITCH_SHIFT);
 
-   surf[4] = (brw_get_surface_num_multisamples(intelObj->mt->num_samples) |
+   surf[4] = (brw_get_surface_num_multisamples(mt->num_samples) |
               SET_FIELD(tObj->BaseLevel - mt->first_level, BRW_SURFACE_MIN_LOD));
 
    surf[5] = mt->align_h == 4 ? BRW_SURFACE_VERTICAL_ALIGN_ENABLE : 0;
 
    /* Emit relocation to surface contents */
    drm_intel_bo_emit_reloc(brw->batch.bo,
-                          *surf_offset + 4,
-                          intelObj->mt->region->bo,
-                           surf[1] - intelObj->mt->region->bo->offset64,
-                          I915_GEM_DOMAIN_SAMPLER, 0);
+                           *surf_offset + 4,
+                           mt->bo,
+                           surf[1] - mt->bo->offset64,
+                           I915_GEM_DOMAIN_SAMPLER, 0);
 }
 
 /**
@@ -399,9 +448,7 @@ brw_update_sol_surface(struct brw_context *brw,
       surface_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT;
       break;
    default:
-      assert(!"Invalid vector size for transform feedback output");
-      surface_format = BRW_SURFACEFORMAT_R32_FLOAT;
-      break;
+      unreachable("Invalid vector size for transform feedback output");
    }
 
    surf[0] = BRW_SURFACE_BUFFER << BRW_SURFACE_TYPE_SHIFT |
@@ -432,47 +479,16 @@ brw_update_sol_surface(struct brw_context *brw,
 static void
 brw_upload_wm_pull_constants(struct brw_context *brw)
 {
-   struct gl_context *ctx = &brw->ctx;
+   struct brw_stage_state *stage_state = &brw->wm.base;
    /* BRW_NEW_FRAGMENT_PROGRAM */
    struct brw_fragment_program *fp =
       (struct brw_fragment_program *) brw->fragment_program;
-   struct gl_program_parameter_list *params = fp->program.Base.Parameters;
-   const int size = brw->wm.prog_data->nr_pull_params * sizeof(float);
-   const int surf_index =
-      brw->wm.prog_data->base.binding_table.pull_constants_start;
-   float *constants;
-   unsigned int i;
-
-   _mesa_load_state_parameters(ctx, params);
-
    /* CACHE_NEW_WM_PROG */
-   if (brw->wm.prog_data->nr_pull_params == 0) {
-      if (brw->wm.base.const_bo) {
-        drm_intel_bo_unreference(brw->wm.base.const_bo);
-        brw->wm.base.const_bo = NULL;
-        brw->wm.base.surf_offset[surf_index] = 0;
-        brw->state.dirty.brw |= BRW_NEW_SURFACES;
-      }
-      return;
-   }
-
-   drm_intel_bo_unreference(brw->wm.base.const_bo);
-   brw->wm.base.const_bo = drm_intel_bo_alloc(brw->bufmgr, "WM const bo",
-                                        size, 64);
+   struct brw_stage_prog_data *prog_data = &brw->wm.prog_data->base;
 
    /* _NEW_PROGRAM_CONSTANTS */
-   drm_intel_gem_bo_map_gtt(brw->wm.base.const_bo);
-   constants = brw->wm.base.const_bo->virtual;
-   for (i = 0; i < brw->wm.prog_data->nr_pull_params; i++) {
-      constants[i] = *brw->wm.prog_data->pull_param[i];
-   }
-   drm_intel_gem_bo_unmap_gtt(brw->wm.base.const_bo);
-
-   brw_create_constant_surface(brw, brw->wm.base.const_bo, 0, size,
-                               &brw->wm.base.surf_offset[surf_index],
-                               true);
-
-   brw->state.dirty.brw |= BRW_NEW_SURFACES;
+   brw_upload_pull_constants(brw, BRW_NEW_SURFACES, &fp->program.Base,
+                             stage_state, prog_data, true);
 }
 
 const struct brw_tracked_state brw_wm_pull_constants = {
@@ -484,6 +500,14 @@ const struct brw_tracked_state brw_wm_pull_constants = {
    .emit = brw_upload_wm_pull_constants,
 };
 
+/**
+ * Creates a null renderbuffer surface.
+ *
+ * This is used when the shader doesn't write to any color output.  An FB
+ * write to target 0 will still be emitted, because that's how the thread is
+ * terminated (and computed depth is returned), so we need to have the
+ * hardware discard the target 0 color output..
+ */
 static void
 brw_update_null_renderbuffer_surface(struct brw_context *brw, unsigned int unit)
 {
@@ -591,7 +615,6 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
    struct gl_context *ctx = &brw->ctx;
    struct intel_renderbuffer *irb = intel_renderbuffer(rb);
    struct intel_mipmap_tree *mt = irb->mt;
-   struct intel_region *region;
    uint32_t *surf;
    uint32_t tile_x, tile_y;
    uint32_t format = 0;
@@ -619,8 +642,6 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
 
    intel_miptree_used_for_rendering(irb->mt);
 
-   region = irb->mt->region;
-
    surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, 6 * 4, 32,
                           &brw->wm.base.surf_offset[surf_index]);
 
@@ -635,13 +656,13 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
 
    /* reloc */
    surf[1] = (intel_renderbuffer_get_tile_offsets(irb, &tile_x, &tile_y) +
-             region->bo->offset64);
+             mt->bo->offset64);
 
    surf[2] = ((rb->Width - 1) << BRW_SURFACE_WIDTH_SHIFT |
              (rb->Height - 1) << BRW_SURFACE_HEIGHT_SHIFT);
 
-   surf[3] = (brw_get_surface_tiling_bits(region->tiling) |
-             (region->pitch - 1) << BRW_SURFACE_PITCH_SHIFT);
+   surf[3] = (brw_get_surface_tiling_bits(mt->tiling) |
+             (mt->pitch - 1) << BRW_SURFACE_PITCH_SHIFT);
 
    surf[4] = brw_get_surface_num_multisamples(mt->num_samples);
 
@@ -679,8 +700,8 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
 
    drm_intel_bo_emit_reloc(brw->batch.bo,
                           brw->wm.base.surf_offset[surf_index] + 4,
-                          region->bo,
-                          surf[1] - region->bo->offset64,
+                          mt->bo,
+                          surf[1] - mt->bo->offset64,
                           I915_GEM_DOMAIN_RENDER,
                           I915_GEM_DOMAIN_RENDER);
 }
@@ -756,7 +777,7 @@ update_stage_texture_surfaces(struct brw_context *brw,
          const unsigned unit = prog->SamplerUnits[s];
 
          /* _NEW_TEXTURE */
-         if (ctx->Texture.Unit[unit]._ReallyEnabled) {
+         if (ctx->Texture.Unit[unit]._Current) {
             brw->vtbl.update_texture_surface(ctx, unit, surf_offset + s, for_gather);
          }
       }
@@ -787,12 +808,14 @@ brw_update_texture_surfaces(struct brw_context *brw)
    /* emit alternate set of surface state for gather. this
     * allows the surface format to be overriden for only the
     * gather4 messages. */
-   if (vs && vs->UsesGather)
-      update_stage_texture_surfaces(brw, vs, &brw->vs.base, true);
-   if (gs && gs->UsesGather)
-      update_stage_texture_surfaces(brw, gs, &brw->gs.base, true);
-   if (fs && fs->UsesGather)
-      update_stage_texture_surfaces(brw, fs, &brw->wm.base, true);
+   if (brw->gen < 8) {
+      if (vs && vs->UsesGather)
+         update_stage_texture_surfaces(brw, vs, &brw->vs.base, true);
+      if (gs && gs->UsesGather)
+         update_stage_texture_surfaces(brw, gs, &brw->gs.base, true);
+      if (fs && fs->UsesGather)
+         update_stage_texture_surfaces(brw, fs, &brw->wm.base, true);
+   }
 
    brw->state.dirty.brw |= BRW_NEW_SURFACES;
 }
@@ -854,7 +877,7 @@ brw_upload_wm_ubo_surfaces(struct brw_context *brw)
 {
    struct gl_context *ctx = &brw->ctx;
    /* _NEW_PROGRAM */
-   struct gl_shader_program *prog = ctx->Shader._CurrentFragmentProgram;
+   struct gl_shader_program *prog = ctx->_Shader->_CurrentFragmentProgram;
 
    if (!prog)
       return;