Example #1
0
static uint32_t
get_qpitch(const struct isl_surf *surf)
{
   switch (surf->dim_layout) {
   default:
      unreachable("Bad isl_surf_dim");
   case ISL_DIM_LAYOUT_GEN4_2D:
   case ISL_DIM_LAYOUT_GEN4_3D:
      if (GEN_GEN >= 9) {
         return isl_surf_get_array_pitch_el_rows(surf);
      } else {
         /* From the Broadwell PRM for RENDER_SURFACE_STATE.QPitch
          *
          *    "This field must be set to an integer multiple of the Surface
          *    Vertical Alignment. For compressed textures (BC*, FXT1,
          *    ETC*, and EAC* Surface Formats), this field is in units of
          *    rows in the uncompressed surface, and must be set to an
          *    integer multiple of the vertical alignment parameter "j"
          *    defined in the Common Surface Formats section."
          */
         return isl_surf_get_array_pitch_sa_rows(surf);
      }
   case ISL_DIM_LAYOUT_GEN9_1D:
      /* QPitch is usually expressed as rows of surface elements (where
       * a surface element is an compression block or a single surface
       * sample). Skylake 1D is an outlier.
       *
       * From the Skylake BSpec >> Memory Views >> Common Surface
       * Formats >> Surface Layout and Tiling >> 1D Surfaces:
       *
       *    Surface QPitch specifies the distance in pixels between array
       *    slices.
       */
      return isl_surf_get_array_pitch_el(surf);
   }
}
void
isl_surf_fill_image_param(const struct isl_device *dev,
                          struct brw_image_param *param,
                          const struct isl_surf *surf,
                          const struct isl_view *view)
{
   *param = image_param_defaults;

   param->size[0] = isl_minify(surf->logical_level0_px.w, view->base_level);
   param->size[1] = isl_minify(surf->logical_level0_px.h, view->base_level);
   if (surf->dim == ISL_SURF_DIM_3D) {
      param->size[2] = isl_minify(surf->logical_level0_px.d, view->base_level);
   } else {
      param->size[2] = surf->logical_level0_px.array_len -
                       view->base_array_layer;
   }

   isl_surf_get_image_offset_el(surf, view->base_level,
                                surf->dim == ISL_SURF_DIM_3D ?
                                   0 : view->base_array_layer,
                                surf->dim == ISL_SURF_DIM_3D ?
                                   view->base_array_layer : 0,
                                &param->offset[0],  &param->offset[1]);

   const int cpp = isl_format_get_layout(surf->format)->bpb / 8;
   param->stride[0] = cpp;
   param->stride[1] = surf->row_pitch / cpp;

   const struct isl_extent3d image_align_sa =
      isl_surf_get_image_alignment_sa(surf);
   if (ISL_DEV_GEN(dev) < 9 && surf->dim == ISL_SURF_DIM_3D) {
      param->stride[2] = isl_align_npot(param->size[0], image_align_sa.w);
      param->stride[3] = isl_align_npot(param->size[1], image_align_sa.h);
   } else {
      param->stride[2] = 0;
      param->stride[3] = isl_surf_get_array_pitch_el_rows(surf);
   }

   switch (surf->tiling) {
   case ISL_TILING_LINEAR:
      /* image_param_defaults is good enough */
      break;

   case ISL_TILING_X:
      /* An X tile is a rectangular block of 512x8 bytes. */
      param->tiling[0] = isl_log2u(512 / cpp);
      param->tiling[1] = isl_log2u(8);

      if (dev->has_bit6_swizzling) {
         /* Right shifts required to swizzle bits 9 and 10 of the memory
          * address with bit 6.
          */
         param->swizzling[0] = 3;
         param->swizzling[1] = 4;
      }
      break;

   case ISL_TILING_Y0:
      /* The layout of a Y-tiled surface in memory isn't really fundamentally
       * different to the layout of an X-tiled surface, we simply pretend that
       * the surface is broken up in a number of smaller 16Bx32 tiles, each
       * one arranged in X-major order just like is the case for X-tiling.
       */
      param->tiling[0] = isl_log2u(16 / cpp);
      param->tiling[1] = isl_log2u(32);

      if (dev->has_bit6_swizzling) {
         /* Right shift required to swizzle bit 9 of the memory address with
          * bit 6.
          */
         param->swizzling[0] = 3;
         param->swizzling[1] = 0xff;
      }
      break;

   default:
      assert(!"Unhandled storage image tiling");
   }

   /* 3D textures are arranged in 2D in memory with 2^lod slices per row.  The
    * address calculation algorithm (emit_address_calculation() in
    * brw_fs_surface_builder.cpp) handles this as a sort of tiling with
    * modulus equal to the LOD.
    */
   param->tiling[2] = (ISL_DEV_GEN(dev) < 9 && surf->dim == ISL_SURF_DIM_3D ?
                       view->base_level : 0);
}