intel/blorp: Stop using the X/YOffset field of RENDER_SURFACE_STATE
authorJason Ekstrand <jason.ekstrand@intel.com>
Tue, 30 Aug 2016 18:18:39 +0000 (11:18 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Tue, 13 Sep 2016 02:42:57 +0000 (19:42 -0700)
While it can be useful, the field has substantial limtations.  In
particular, the bittom 2 or 3 bits is missing so your offset always has to
be a multiple of 4 or 8.  While surface alignments usually work out to make
this ok, when you start trying to fake compressed surfaces as uncompressed
(which we will want to do) this falls apart.  The easiest solution is to
simply align all offsets to a tile boundary and munge the regions we're
copying to account for the intratile offset.

Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
Reviewed-by: Topi Pohjolainen <topi.pohjolainen@intel.com>
src/intel/blorp/blorp_blit.c
src/intel/blorp/blorp_genX_exec.h
src/intel/blorp/blorp_priv.h

index fdcd29d68c7dac5e112624b6b0b1dfccd6ad4200..dba49b9c207e009e680ba3778593b49635782bbe 100644 (file)
@@ -49,6 +49,8 @@ struct brw_blorp_blit_vars {
    nir_variable *v_rect_grid;
    nir_variable *v_coord_transform;
    nir_variable *v_src_z;
+   nir_variable *v_src_offset;
+   nir_variable *v_dst_offset;
 
    /* gl_FragCoord */
    nir_variable *frag_coord;
@@ -69,12 +71,16 @@ brw_blorp_blit_vars_init(nir_builder *b, struct brw_blorp_blit_vars *v,
                                      type, #name); \
    v->v_##name->data.interpolation = INTERP_MODE_FLAT; \
    v->v_##name->data.location = VARYING_SLOT_VAR0 + \
-      offsetof(struct brw_blorp_wm_inputs, name) / (4 * sizeof(float));
+      offsetof(struct brw_blorp_wm_inputs, name) / (4 * sizeof(float)); \
+   v->v_##name->data.location_frac = \
+      (offsetof(struct brw_blorp_wm_inputs, name) / sizeof(float)) % 4;
 
    LOAD_INPUT(discard_rect, glsl_vec4_type())
    LOAD_INPUT(rect_grid, glsl_vec4_type())
    LOAD_INPUT(coord_transform, glsl_vec4_type())
    LOAD_INPUT(src_z, glsl_uint_type())
+   LOAD_INPUT(src_offset, glsl_vector_type(GLSL_TYPE_UINT, 2))
+   LOAD_INPUT(dst_offset, glsl_vector_type(GLSL_TYPE_UINT, 2))
 
 #undef LOAD_INPUT
 
@@ -95,6 +101,17 @@ blorp_blit_get_frag_coords(nir_builder *b,
 {
    nir_ssa_def *coord = nir_f2i(b, nir_load_var(b, v->frag_coord));
 
+   /* Account for destination surface intratile offset
+    *
+    * Transformation parameters giving translation from destination to source
+    * coordinates don't take into account possible intra-tile destination
+    * offset.  Therefore it has to be first subtracted from the incoming
+    * coordinates.  Vertices are set up based on coordinates containing the
+    * intra-tile offset.
+    */
+   if (key->need_dst_offset)
+      coord = nir_isub(b, coord, nir_load_var(b, v->v_dst_offset));
+
    if (key->persample_msaa_dispatch) {
       return nir_vec3(b, nir_channel(b, coord, 0), nir_channel(b, coord, 1),
                       nir_load_sample_id(b));
@@ -1160,6 +1177,9 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp,
                                             key->tex_layout);
          }
 
+         if (key->need_src_offset)
+            src_pos = nir_iadd(&b, src_pos, nir_load_var(&b, v.v_src_offset));
+
          /* Now (X, Y, S) = decode_msaa(tex_samples, detile(tex_tiling, offset)).
           *
           * In other words: X, Y, and S now contain values which, when passed to
@@ -1247,6 +1267,23 @@ brw_blorp_setup_coord_transform(struct brw_blorp_coord_transform *xform,
    }
 }
 
+static inline void
+surf_get_intratile_offset_px(struct brw_blorp_surface_info *info,
+                             uint32_t *tile_x_px, uint32_t *tile_y_px)
+{
+   if (info->surf.msaa_layout == ISL_MSAA_LAYOUT_INTERLEAVED) {
+      struct isl_extent2d px_size_sa =
+         isl_get_interleaved_msaa_px_size_sa(info->surf.samples);
+      assert(info->tile_x_sa % px_size_sa.width == 0);
+      assert(info->tile_y_sa % px_size_sa.height == 0);
+      *tile_x_px = info->tile_x_sa / px_size_sa.width;
+      *tile_y_px = info->tile_y_sa / px_size_sa.height;
+   } else {
+      *tile_x_px = info->tile_x_sa;
+      *tile_y_px = info->tile_y_sa;
+   }
+}
+
 static void
 surf_convert_to_single_slice(const struct isl_device *isl_dev,
                              struct brw_blorp_surface_info *info)
@@ -1280,6 +1317,14 @@ surf_convert_to_single_slice(const struct isl_device *isl_dev,
                                       &info->tile_x_sa, &info->tile_y_sa);
    info->addr.offset += byte_offset;
 
+   const uint32_t slice_width_px =
+      minify(info->surf.logical_level0_px.width, info->view.base_level);
+   const uint32_t slice_height_px =
+      minify(info->surf.logical_level0_px.height, info->view.base_level);
+
+   uint32_t tile_x_px, tile_y_px;
+   surf_get_intratile_offset_px(info, &tile_x_px, &tile_y_px);
+
    /* TODO: Once this file gets converted to C, we shouls just use designated
     * initializers.
     */
@@ -1287,10 +1332,8 @@ surf_convert_to_single_slice(const struct isl_device *isl_dev,
 
    init_info.dim = ISL_SURF_DIM_2D;
    init_info.format = info->surf.format;
-   init_info.width =
-      minify(info->surf.logical_level0_px.width, info->view.base_level);
-   init_info.height =
-      minify(info->surf.logical_level0_px.height, info->view.base_level);
+   init_info.width = slice_width_px + tile_x_px;
+   init_info.height = slice_height_px + tile_y_px;
    init_info.depth = 1;
    init_info.levels = 1;
    init_info.array_len = 1;
@@ -1492,6 +1535,7 @@ blorp_blit(struct blorp_batch *batch,
       surf_fake_interleaved_msaa(batch->blorp->isl_dev, &params.dst);
 
       wm_prog_key.use_kill = true;
+      wm_prog_key.need_dst_offset = true;
    }
 
    if (params.dst.surf.tiling == ISL_TILING_W) {
@@ -1552,6 +1596,7 @@ blorp_blit(struct blorp_batch *batch,
 
       wm_prog_key.dst_tiled_w = true;
       wm_prog_key.use_kill = true;
+      wm_prog_key.need_dst_offset = true;
 
       if (params.dst.surf.samples > 1) {
          /* If the destination surface is a W-tiled multisampled stencil
@@ -1576,6 +1621,7 @@ blorp_blit(struct blorp_batch *batch,
       surf_retile_w_to_y(batch->blorp->isl_dev, &params.src);
 
       wm_prog_key.src_tiled_w = true;
+      wm_prog_key.need_src_offset = true;
    }
 
    /* tex_samples and rt_samples are the sample counts that are set up in
@@ -1599,6 +1645,24 @@ blorp_blit(struct blorp_batch *batch,
       wm_prog_key.persample_msaa_dispatch = true;
    }
 
+   if (params.src.tile_x_sa || params.src.tile_y_sa) {
+      assert(wm_prog_key.need_src_offset);
+      surf_get_intratile_offset_px(&params.src,
+                                   &params.wm_inputs.src_offset.x,
+                                   &params.wm_inputs.src_offset.y);
+   }
+
+   if (params.dst.tile_x_sa || params.dst.tile_y_sa) {
+      assert(wm_prog_key.need_dst_offset);
+      surf_get_intratile_offset_px(&params.dst,
+                                   &params.wm_inputs.dst_offset.x,
+                                   &params.wm_inputs.dst_offset.y);
+      params.x0 += params.wm_inputs.dst_offset.x;
+      params.y0 += params.wm_inputs.dst_offset.y;
+      params.x1 += params.wm_inputs.dst_offset.x;
+      params.y1 += params.wm_inputs.dst_offset.y;
+   }
+
    /* For some texture types, we need to pass the layer through the sampler. */
    params.wm_inputs.src_z = params.src.z_offset;
 
index 65a981d4ce2b8d5cd549f26553869f99bc299e40..8f26925e6cbd4ccb6a2a3fffa099718cd9316382 100644 (file)
@@ -926,9 +926,7 @@ blorp_emit_surface_state(struct blorp_batch *batch,
    isl_surf_fill_state(batch->blorp->isl_dev, state,
                        .surf = &surf, .view = &surface->view,
                        .aux_surf = &surface->aux_surf, .aux_usage = aux_usage,
-                       .mocs = mocs, .clear_color = surface->clear_color,
-                       .x_offset_sa = surface->tile_x_sa,
-                       .y_offset_sa = surface->tile_y_sa);
+                       .mocs = mocs, .clear_color = surface->clear_color);
 
    blorp_surface_reloc(batch, state_offset + ss_info.reloc_dw * 4,
                        surface->addr, 0);
index 33f197b523da4975dbcded4770c1da90701f6ec7..46ff272630af937e9a899d6a6206d958a545a2e1 100644 (file)
@@ -112,19 +112,27 @@ struct brw_blorp_rect_grid
    float pad[2];
 };
 
+struct blorp_surf_offset {
+   uint32_t x;
+   uint32_t y;
+};
+
 struct brw_blorp_wm_inputs
 {
    struct brw_blorp_discard_rect discard_rect;
    struct brw_blorp_rect_grid rect_grid;
    struct brw_blorp_coord_transform coord_transform[2];
 
+   struct blorp_surf_offset src_offset;
+   struct blorp_surf_offset dst_offset;
+
    /* Minimum layer setting works for all the textures types but texture_3d
     * for which the setting has no effect. Use the z-coordinate instead.
     */
    uint32_t src_z;
 
    /* Pad out to an integral number of registers */
-   uint32_t pad[3];
+   uint32_t pad[1];
 };
 
 struct brw_blorp_prog_data
@@ -258,6 +266,16 @@ struct brw_blorp_blit_prog_key
    /* True for scaled blitting. */
    bool blit_scaled;
 
+   /* True if this blit operation may involve intratile offsets on the source.
+    * In this case, we need to add the offset before texturing.
+    */
+   bool need_src_offset;
+
+   /* True if this blit operation may involve intratile offsets on the
+    * destination.  In this case, we need to add the offset to gl_FragCoord.
+    */
+   bool need_dst_offset;
+
    /* Scale factors between the pixel grid and the grid of samples. We're
     * using grid of samples for bilinear filetring in multisample scaled blits.
     */