Ejemplo n.º 1
0
VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout(
    VkDevice                                    device,
    VkImage                                     image,
    const VkImageSubresource*                   pSubresource,
    VkSubresourceLayout*                        pLayout)
{
    const struct intel_img *img = intel_img(image);
    unsigned x, y;

    intel_layout_get_slice_pos(&img->layout, pSubresource->mipLevel,
                               pSubresource->arrayLayer, &x, &y);
    intel_layout_pos_to_mem(&img->layout, x, y, &x, &y);

    pLayout->offset = intel_layout_mem_to_linear(&img->layout, x, y);
    pLayout->size = intel_layout_get_slice_size(&img->layout,
                                               pSubresource->mipLevel);
    pLayout->rowPitch = img->layout.bo_stride;
    pLayout->depthPitch = intel_layout_get_slice_stride(&img->layout,
                                                       pSubresource->mipLevel);
    pLayout->arrayPitch = intel_layout_get_slice_stride(&img->layout,
                                                       pSubresource->arrayLayer);
}
Ejemplo n.º 2
0
/**
 * Return the offset (in bytes) to a slice within the bo.
 *
 * The returned offset is aligned to tile size.  Since slices are not
 * guaranteed to start at tile boundaries, the X and Y offsets (in pixels)
 * from the tile origin to the slice are also returned.  X offset is always a
 * multiple of 4 and Y offset is always a multiple of 2.
 */
unsigned
intel_layout_get_slice_tile_offset(const struct intel_layout *layout,
                                   unsigned level, unsigned slice,
                                   unsigned *x_offset, unsigned *y_offset)
{
   unsigned tile_w, tile_h, tile_size, row_size;
   unsigned tile_offset, x, y;

   /* see the Sandy Bridge PRM, volume 1 part 2, page 24 */

   switch (layout->tiling) {
   case GEN6_TILING_NONE:
       tile_w = 1;
       tile_h = 1;
      break;
   case GEN6_TILING_X:
      tile_w = 512;
      tile_h = 8;
      break;
   case GEN6_TILING_Y:
      tile_w = 128;
      tile_h = 32;
      break;
   case GEN8_TILING_W:
      tile_w = 64;
      tile_h = 64;
      break;
   default:
      assert(!"unknown tiling");
      tile_w = 1;
      tile_h = 1;
      break;
   }

   tile_size = tile_w * tile_h;
   row_size = layout->bo_stride * tile_h;

   intel_layout_get_slice_pos(layout, level, slice, &x, &y);
   /* in bytes */
   intel_layout_pos_to_mem(layout, x, y, &x, &y);
   tile_offset = row_size * (y / tile_h) + tile_size * (x / tile_w);

   /*
    * Since tex->bo_stride is a multiple of tile_w, slice_offset should be
    * aligned at this point.
    */
   assert(tile_offset % tile_size == 0);

   /*
    * because of the possible values of align_i and align_j in
    * tex_layout_init_alignments(), x_offset is guaranteed to be a multiple of
    * 4 and y_offset is guaranteed to be a multiple of 2.
    */
   if (x_offset) {
      /* in pixels */
      x = (x % tile_w) / layout->block_size * layout->block_width;
      assert(x % 4 == 0);

      *x_offset = x;
   }

   if (y_offset) {
      /* in pixels */
      y = (y % tile_h) * layout->block_height;
      assert(y % 2 == 0);

      *y_offset = y;
   }

   return tile_offset;
}
Ejemplo n.º 3
0
static void
ds_init_info(const struct intel_gpu *gpu,
             const struct intel_img *img,
             VkImageViewType view_type,
             VkFormat format, unsigned level,
             unsigned first_layer, unsigned num_layers,
             struct ds_surface_info *info)
{
   bool separate_stencil;

   INTEL_GPU_ASSERT(gpu, 6, 7.5);

   memset(info, 0, sizeof(*info));

   info->surface_type = view_type_to_surface_type(view_type);

   if (info->surface_type == GEN6_SURFTYPE_CUBE) {
      /*
       * From the Sandy Bridge PRM, volume 2 part 1, page 325-326:
       *
       *     "For Other Surfaces (Cube Surfaces):
       *      This field (Minimum Array Element) is ignored."
       *
       *     "For Other Surfaces (Cube Surfaces):
       *      This field (Render Target View Extent) is ignored."
       *
       * As such, we cannot set first_layer and num_layers on cube surfaces.
       * To work around that, treat it as a 2D surface.
       */
      info->surface_type = GEN6_SURFTYPE_2D;
   }

   if (intel_gpu_gen(gpu) >= INTEL_GEN(7)) {
      separate_stencil = true;
   }
   else {
      /*
       * From the Sandy Bridge PRM, volume 2 part 1, page 317:
       *
       *     "This field (Separate Stencil Buffer Enable) must be set to the
       *      same value (enabled or disabled) as Hierarchical Depth Buffer
       *      Enable."
       */
      separate_stencil = intel_img_can_enable_hiz(img, level);
   }

   /*
    * From the Sandy Bridge PRM, volume 2 part 1, page 317:
    *
    *     "If this field (Hierarchical Depth Buffer Enable) is enabled, the
    *      Surface Format of the depth buffer cannot be
    *      D32_FLOAT_S8X24_UINT or D24_UNORM_S8_UINT. Use of stencil
    *      requires the separate stencil buffer."
    *
    * From the Ironlake PRM, volume 2 part 1, page 330:
    *
    *     "If this field (Separate Stencil Buffer Enable) is disabled, the
    *      Surface Format of the depth buffer cannot be D24_UNORM_X8_UINT."
    *
    * There is no similar restriction for GEN6.  But when D24_UNORM_X8_UINT
    * is indeed used, the depth values output by the fragment shaders will
    * be different when read back.
    *
    * As for GEN7+, separate_stencil is always true.
    */
   switch (format) {
   case VK_FORMAT_D16_UNORM:
      info->format = GEN6_ZFORMAT_D16_UNORM;
      break;
   case VK_FORMAT_D32_SFLOAT:
      info->format = GEN6_ZFORMAT_D32_FLOAT;
      break;
   case VK_FORMAT_D32_SFLOAT_S8_UINT:
      info->format = (separate_stencil) ?
         GEN6_ZFORMAT_D32_FLOAT :
         GEN6_ZFORMAT_D32_FLOAT_S8X24_UINT;
      break;
   case VK_FORMAT_S8_UINT:
      if (separate_stencil) {
         info->format = GEN6_ZFORMAT_D32_FLOAT;
         break;
      }
      /* fall through */
   default:
      assert(!"unsupported depth/stencil format");
      ds_init_info_null(gpu, info);
      return;
      break;
   }

   if (format != VK_FORMAT_S8_UINT)
      info->zs.stride = img->layout.bo_stride;

   if (img->s8_layout) {
      /*
       * From the Sandy Bridge PRM, volume 2 part 1, page 329:
       *
       *     "The pitch must be set to 2x the value computed based on width,
       *       as the stencil buffer is stored with two rows interleaved."
       *
       * According to the classic driver, we need to do the same for GEN7+
       * even though the Ivy Bridge PRM does not say anything about it.
       */
      info->stencil.stride = img->s8_layout->bo_stride * 2;

      if (intel_gpu_gen(gpu) == INTEL_GEN(6)) {
         unsigned x, y;

         assert(img->s8_layout->walk == INTEL_LAYOUT_WALK_LOD);

         /* offset to the level */
         intel_layout_get_slice_pos(img->s8_layout, level, 0, &x, &y);
         intel_layout_pos_to_mem(img->s8_layout, x, y, &x, &y);
         info->stencil.offset = intel_layout_mem_to_raw(img->s8_layout, x, y);
      }
   } else if (format == VK_FORMAT_S8_UINT) {
      info->stencil.stride = img->layout.bo_stride * 2;
   }

   if (intel_img_can_enable_hiz(img, level)) {
      info->hiz.stride = img->layout.aux_stride;

      /* offset to the level */
      if (intel_gpu_gen(gpu) == INTEL_GEN(6))
          info->hiz.offset = img->layout.aux_offsets[level];
   }

   info->width = img->layout.width0;
   info->height = img->layout.height0;
   info->depth = (img->type == VK_IMAGE_TYPE_3D) ?
      img->depth : num_layers;

   info->lod = level;
   info->first_layer = first_layer;
   info->num_layers = num_layers;
}