-/**************************************************************************
- *
+/*
* Copyright 2006 VMware, Inc.
* All Rights Reserved.
*
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
+ * distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
+ */
#include <GL/gl.h>
#include <GL/internal/dri_interface.h>
#include "brw_blorp.h"
#include "brw_context.h"
+#include "brw_state.h"
#include "main/enums.h"
#include "main/fbobject.h"
#define FILE_DEBUG_FLAG DEBUG_MIPTREE
+static void *intel_miptree_map_raw(struct brw_context *brw,
+ struct intel_mipmap_tree *mt);
+
+static void intel_miptree_unmap_raw(struct intel_mipmap_tree *mt);
+
static bool
intel_miptree_alloc_mcs(struct brw_context *brw,
struct intel_mipmap_tree *mt,
* created, based on the chip generation and the surface type.
*/
static enum intel_msaa_layout
-compute_msaa_layout(struct brw_context *brw, mesa_format format, GLenum target,
+compute_msaa_layout(struct brw_context *brw, mesa_format format,
bool disable_aux_buffers)
{
/* Prior to Gen7, all MSAA surfaces used IMS layout. */
* by half the block width, and Y coordinates by half the block height.
*/
void
-intel_get_non_msrt_mcs_alignment(struct brw_context *brw,
- struct intel_mipmap_tree *mt,
+intel_get_non_msrt_mcs_alignment(const struct intel_mipmap_tree *mt,
unsigned *width_px, unsigned *height)
{
switch (mt->tiling) {
}
bool
-intel_tiling_supports_non_msrt_mcs(struct brw_context *brw, unsigned tiling)
+intel_tiling_supports_non_msrt_mcs(const struct brw_context *brw,
+ unsigned tiling)
{
/* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render
* Target(s)", beneath the "Fast Color Clear" bullet (p326):
*
* - MCS buffer for non-MSRT is supported only for RT formats 32bpp,
* 64bpp, and 128bpp.
+ *
+ * From the Skylake documentation, it is made clear that X-tiling is no longer
+ * supported:
+ *
+ * - MCS and Lossless compression is supported for TiledY/TileYs/TileYf
+ * non-MSRTs only.
*/
bool
-intel_miptree_is_fast_clear_capable(struct brw_context *brw,
- struct intel_mipmap_tree *mt)
+intel_miptree_supports_non_msrt_fast_clear(struct brw_context *brw,
+ const struct intel_mipmap_tree *mt)
{
/* MCS support does not exist prior to Gen7 */
if (brw->gen < 7)
if (mt->disable_aux_buffers)
return false;
+ /* This function applies only to non-multisampled render targets. */
+ if (mt->num_samples > 1)
+ return false;
+
/* MCS is only supported for color buffers */
switch (_mesa_get_format_base_format(mt->format)) {
case GL_DEPTH_COMPONENT:
return false;
}
+
+ /* Check for layered surfaces. */
if (mt->physical_depth0 != 1) {
+ /* Multisample surfaces with the CMS layout are not layered surfaces,
+ * yet still have physical_depth0 > 1. Assert that we don't
+ * accidentally reject a multisampled surface here. We should have
+ * rejected it earlier by explicitly checking the sample count.
+ */
+ assert(mt->num_samples <= 1);
+
if (brw->gen >= 8) {
perf_debug("Layered fast clear - giving up. (%dx%d%d)\n",
mt->logical_width0, mt->logical_height0,
if (!brw->format_supported_as_render_target[mt->format])
return false;
- return true;
+ if (brw->gen >= 9) {
+ mesa_format linear_format = _mesa_get_srgb_format_linear(mt->format);
+ const uint32_t brw_format = brw_format_for_mesa_format(linear_format);
+ return isl_format_supports_lossless_compression(brw->intelScreen->devinfo,
+ brw_format);
+ } else
+ return true;
}
+/* On Gen9 support for color buffer compression was extended to single
+ * sampled surfaces. This is a helper considering both auxiliary buffer
+ * type and number of samples telling if the given miptree represents
+ * the new single sampled case - also called lossless compression.
+ */
+bool
+intel_miptree_is_lossless_compressed(const struct brw_context *brw,
+ const struct intel_mipmap_tree *mt)
+{
+ /* Only available from Gen9 onwards. */
+ if (brw->gen < 9)
+ return false;
+
+ /* Compression always requires auxiliary buffer. */
+ if (!mt->mcs_mt)
+ return false;
+
+ /* Single sample compression is represented re-using msaa compression
+ * layout type: "Compressed Multisampled Surfaces".
+ */
+ if (mt->msaa_layout != INTEL_MSAA_LAYOUT_CMS)
+ return false;
+
+ /* And finally distinguish between msaa and single sample case. */
+ return mt->num_samples <= 1;
+}
+
+bool
+intel_miptree_supports_lossless_compressed(struct brw_context *brw,
+ const struct intel_mipmap_tree *mt)
+{
+ /* For now compression is only enabled for integer formats even though
+ * there exist supported floating point formats also. This is a heuristic
+ * decision based on current public benchmarks. In none of the cases these
+ * formats provided any improvement but a few cases were seen to regress.
+ * Hence these are left to to be enabled in the future when they are known
+ * to improve things.
+ */
+ if (_mesa_get_format_datatype(mt->format) == GL_FLOAT)
+ return false;
+
+ /* Fast clear mechanism and lossless compression go hand in hand. */
+ if (!intel_miptree_supports_non_msrt_fast_clear(brw, mt))
+ return false;
+
+ /* Fast clear can be also used to clear srgb surfaces by using equivalent
+ * linear format. This trick, however, can't be extended to be used with
+ * lossless compression and therefore a check is needed to see if the format
+ * really is linear.
+ */
+ return _mesa_get_srgb_format_linear(mt->format) == mt->format;
+}
/**
* Determine depth format corresponding to a depth+stencil format,
mt->logical_depth0 = depth0;
mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_NO_MCS;
mt->disable_aux_buffers = (layout_flags & MIPTREE_LAYOUT_DISABLE_AUX) != 0;
+ mt->is_scanout = (layout_flags & MIPTREE_LAYOUT_FOR_SCANOUT) != 0;
exec_list_make_empty(&mt->hiz_map);
mt->cpp = _mesa_get_format_bytes(format);
mt->num_samples = num_samples;
if (num_samples > 1) {
/* Adjust width/height/depth for MSAA */
mt->msaa_layout = compute_msaa_layout(brw, format,
- mt->target, mt->disable_aux_buffers);
+ mt->disable_aux_buffers);
if (mt->msaa_layout == INTEL_MSAA_LAYOUT_IMS) {
/* From the Ivybridge PRM, Volume 1, Part 1, page 108:
* "If the surface is multisampled and it is a depth or stencil
width0 = ALIGN(width0, 2) * 4;
height0 = ALIGN(height0, 2) * 2;
break;
+ case 16:
+ width0 = ALIGN(width0, 2) * 4;
+ height0 = ALIGN(height0, 2) * 4;
+ break;
default:
- /* num_samples should already have been quantized to 0, 1, 2, 4, or
- * 8.
+ /* num_samples should already have been quantized to 0, 1, 2, 4, 8
+ * or 16.
*/
unreachable("not reached");
}
* 7 | ? | ?
* 6 | ? | ?
*/
- if (intel_miptree_is_fast_clear_capable(brw, mt)) {
+ if (intel_miptree_supports_non_msrt_fast_clear(brw, mt)) {
if (brw->gen >= 9 || (brw->gen == 8 && num_samples <= 1))
layout_flags |= MIPTREE_LAYOUT_FORCE_HALIGN16;
} else if (brw->gen >= 9 && num_samples > 1) {
layout_flags |= MIPTREE_LAYOUT_FORCE_HALIGN16;
} else {
+ const UNUSED bool is_lossless_compressed_aux =
+ brw->gen >= 9 && num_samples == 1 &&
+ mt->format == MESA_FORMAT_R_UINT32;
+
/* For now, nothing else has this requirement */
- assert((layout_flags & MIPTREE_LAYOUT_FORCE_HALIGN16) == 0);
+ assert(is_lossless_compressed_aux ||
+ (layout_flags & MIPTREE_LAYOUT_FORCE_HALIGN16) == 0);
}
brw_miptree_layout(brw, mt, layout_flags);
intel_get_yf_ys_bo_size(struct intel_mipmap_tree *mt, unsigned *alignment,
unsigned long *pitch)
{
- const uint32_t bpp = mt->cpp * 8;
- const uint32_t aspect_ratio = (bpp == 16 || bpp == 64) ? 2 : 1;
uint32_t tile_width, tile_height;
unsigned long stride, size, aligned_y;
assert(mt->tr_mode != INTEL_MIPTREE_TRMODE_NONE);
-
- switch (bpp) {
- case 8:
- tile_height = 64;
- break;
- case 16:
- case 32:
- tile_height = 32;
- break;
- case 64:
- case 128:
- tile_height = 16;
- break;
- default:
- unreachable("not reached");
- }
-
- if (mt->tr_mode == INTEL_MIPTREE_TRMODE_YS)
- tile_height *= 4;
+ intel_get_tile_dims(mt->tiling, mt->tr_mode, mt->cpp,
+ &tile_width, &tile_height);
aligned_y = ALIGN(mt->total_height, tile_height);
stride = mt->total_width * mt->cpp;
- tile_width = tile_height * mt->cpp * aspect_ratio;
stride = ALIGN(stride, tile_width);
size = stride * aligned_y;
return size;
}
-struct intel_mipmap_tree *
-intel_miptree_create(struct brw_context *brw,
- GLenum target,
- mesa_format format,
- GLuint first_level,
- GLuint last_level,
- GLuint width0,
- GLuint height0,
- GLuint depth0,
- GLuint num_samples,
- uint32_t layout_flags)
+static struct intel_mipmap_tree *
+miptree_create(struct brw_context *brw,
+ GLenum target,
+ mesa_format format,
+ GLuint first_level,
+ GLuint last_level,
+ GLuint width0,
+ GLuint height0,
+ GLuint depth0,
+ GLuint num_samples,
+ uint32_t layout_flags)
{
struct intel_mipmap_tree *mt;
mesa_format tex_format = format;
mesa_format etc_format = MESA_FORMAT_NONE;
- GLuint total_width, total_height;
uint32_t alloc_flags = 0;
format = intel_lower_compressed_format(brw, format);
return NULL;
}
- total_width = mt->total_width;
- total_height = mt->total_height;
-
- if (format == MESA_FORMAT_S_UINT8) {
- /* Align to size of W tile, 64x64. */
- total_width = ALIGN(total_width, 64);
- total_height = ALIGN(total_height, 64);
- }
-
- bool y_or_x = false;
-
- if (mt->tiling == (I915_TILING_Y | I915_TILING_X)) {
- y_or_x = true;
+ if (mt->tiling == (I915_TILING_Y | I915_TILING_X))
mt->tiling = I915_TILING_Y;
- }
if (layout_flags & MIPTREE_LAYOUT_ACCELERATED_UPLOAD)
alloc_flags |= BO_ALLOC_FOR_RENDER;
mt->bo = drm_intel_bo_alloc_for_render(brw->bufmgr, "miptree",
size, alignment);
} else {
- mt->bo = drm_intel_bo_alloc_tiled(brw->bufmgr, "miptree",
- total_width, total_height, mt->cpp,
- &mt->tiling, &pitch,
- alloc_flags);
+ if (format == MESA_FORMAT_S_UINT8) {
+ /* Align to size of W tile, 64x64. */
+ mt->bo = drm_intel_bo_alloc_tiled(brw->bufmgr, "miptree",
+ ALIGN(mt->total_width, 64),
+ ALIGN(mt->total_height, 64),
+ mt->cpp, &mt->tiling, &pitch,
+ alloc_flags);
+ } else {
+ mt->bo = drm_intel_bo_alloc_tiled(brw->bufmgr, "miptree",
+ mt->total_width, mt->total_height,
+ mt->cpp, &mt->tiling, &pitch,
+ alloc_flags);
+ }
}
mt->pitch = pitch;
+ return mt;
+}
+
+struct intel_mipmap_tree *
+intel_miptree_create(struct brw_context *brw,
+ GLenum target,
+ mesa_format format,
+ GLuint first_level,
+ GLuint last_level,
+ GLuint width0,
+ GLuint height0,
+ GLuint depth0,
+ GLuint num_samples,
+ uint32_t layout_flags)
+{
+ struct intel_mipmap_tree *mt = miptree_create(
+ brw, target, format,
+ first_level, last_level,
+ width0, height0, depth0, num_samples,
+ layout_flags);
+
/* If the BO is too large to fit in the aperture, we need to use the
* BLT engine to support it. Prior to Sandybridge, the BLT paths can't
* handle Y-tiling, so we need to fall back to X.
*/
- if (brw->gen < 6 && y_or_x && mt->bo->size >= brw->max_gtt_map_object_size) {
+ if (brw->gen < 6 && mt->bo->size >= brw->max_gtt_map_object_size &&
+ mt->tiling == I915_TILING_Y) {
+ unsigned long pitch = mt->pitch;
+ const uint32_t alloc_flags =
+ (layout_flags & MIPTREE_LAYOUT_ACCELERATED_UPLOAD) ?
+ BO_ALLOC_FOR_RENDER : 0;
perf_debug("%dx%d miptree larger than aperture; falling back to X-tiled\n",
mt->total_width, mt->total_height);
mt->tiling = I915_TILING_X;
drm_intel_bo_unreference(mt->bo);
mt->bo = drm_intel_bo_alloc_tiled(brw->bufmgr, "miptree",
- total_width, total_height, mt->cpp,
+ mt->total_width, mt->total_height, mt->cpp,
&mt->tiling, &pitch, alloc_flags);
mt->pitch = pitch;
}
/* If this miptree is capable of supporting fast color clears, set
* fast_clear_state appropriately to ensure that fast clears will occur.
* Allocation of the MCS miptree will be deferred until the first fast
- * clear actually occurs.
+ * clear actually occurs or when compressed single sampled buffer is
+ * written by the GPU for the first time.
*/
if (intel_tiling_supports_non_msrt_mcs(brw, mt->tiling) &&
- intel_miptree_is_fast_clear_capable(brw, mt)) {
+ intel_miptree_supports_non_msrt_fast_clear(brw, mt)) {
mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_RESOLVED;
- assert(brw->gen < 8 || mt->align_w == 16 || num_samples <= 1);
+ assert(brw->gen < 8 || mt->halign == 16 || num_samples <= 1);
}
return mt;
height,
1,
pitch,
- 0);
+ MIPTREE_LAYOUT_FOR_SCANOUT);
if (!singlesample_mt)
goto fail;
* clear actually occurs.
*/
if (intel_tiling_supports_non_msrt_mcs(intel, singlesample_mt->tiling) &&
- intel_miptree_is_fast_clear_capable(intel, singlesample_mt))
+ intel_miptree_supports_non_msrt_fast_clear(intel, singlesample_mt)) {
singlesample_mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_RESOLVED;
+ }
if (num_samples == 0) {
intel_miptree_release(&irb->mt);
bool ok;
GLenum target = num_samples > 1 ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
const uint32_t layout_flags = MIPTREE_LAYOUT_ACCELERATED_UPLOAD |
- MIPTREE_LAYOUT_TILING_ANY;
-
+ MIPTREE_LAYOUT_TILING_ANY |
+ MIPTREE_LAYOUT_FOR_SCANOUT;
mt = intel_miptree_create(brw, target, format, 0, 0,
width, height, depth, num_samples,
intel_miptree_release(&(*mt)->mcs_mt);
intel_resolve_map_clear(&(*mt)->hiz_map);
+ intel_miptree_release(&(*mt)->plane[0]);
+ intel_miptree_release(&(*mt)->plane[1]);
+
for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
free((*mt)->level[i].slice);
}
*mt = NULL;
}
+
void
-intel_miptree_get_dimensions_for_image(struct gl_texture_image *image,
- int *width, int *height, int *depth)
+intel_get_image_dims(struct gl_texture_image *image,
+ int *width, int *height, int *depth)
{
switch (image->TexObject->Target) {
case GL_TEXTURE_1D_ARRAY:
+ /* For a 1D Array texture the OpenGL API will treat the image height as
+ * the number of array slices. For Intel hardware, we treat the 1D array
+ * as a 2D Array with a height of 1. So, here we want to swap image
+ * height and depth.
+ */
*width = image->Width;
*height = 1;
*depth = image->Height;
if (image->TexFormat != mt_format)
return false;
- intel_miptree_get_dimensions_for_image(image, &width, &height, &depth);
+ intel_get_image_dims(image, &width, &height, &depth);
if (mt->target == GL_TEXTURE_CUBE_MAP)
depth = 6;
*y = mt->level[level].slice[slice].y_offset;
}
+
+/**
+ * This function computes the tile_w (in bytes) and tile_h (in rows) of
+ * different tiling patterns. If the BO is untiled, tile_w is set to cpp
+ * and tile_h is set to 1.
+ */
+void
+intel_get_tile_dims(uint32_t tiling, uint32_t tr_mode, uint32_t cpp,
+ uint32_t *tile_w, uint32_t *tile_h)
+{
+ if (tr_mode == INTEL_MIPTREE_TRMODE_NONE) {
+ switch (tiling) {
+ case I915_TILING_X:
+ *tile_w = 512;
+ *tile_h = 8;
+ break;
+ case I915_TILING_Y:
+ *tile_w = 128;
+ *tile_h = 32;
+ break;
+ case I915_TILING_NONE:
+ *tile_w = cpp;
+ *tile_h = 1;
+ break;
+ default:
+ unreachable("not reached");
+ }
+ } else {
+ uint32_t aspect_ratio = 1;
+ assert(_mesa_is_pow_two(cpp));
+
+ switch (cpp) {
+ case 1:
+ *tile_h = 64;
+ break;
+ case 2:
+ case 4:
+ *tile_h = 32;
+ break;
+ case 8:
+ case 16:
+ *tile_h = 16;
+ break;
+ default:
+ unreachable("not reached");
+ }
+
+ if (cpp == 2 || cpp == 8)
+ aspect_ratio = 2;
+
+ if (tr_mode == INTEL_MIPTREE_TRMODE_YS)
+ *tile_h *= 4;
+
+ *tile_w = *tile_h * aspect_ratio * cpp;
+ }
+}
+
+
/**
* This function computes masks that may be used to select the bits of the X
* and Y coordinates that indicate the offset within a tile. If the BO is
* untiled, the masks are set to 0.
*/
void
-intel_miptree_get_tile_masks(const struct intel_mipmap_tree *mt,
- uint32_t *mask_x, uint32_t *mask_y,
- bool map_stencil_as_y_tiled)
+intel_get_tile_masks(uint32_t tiling, uint32_t tr_mode, uint32_t cpp,
+ bool map_stencil_as_y_tiled,
+ uint32_t *mask_x, uint32_t *mask_y)
{
- int cpp = mt->cpp;
- uint32_t tiling = mt->tiling;
-
+ uint32_t tile_w_bytes, tile_h;
if (map_stencil_as_y_tiled)
tiling = I915_TILING_Y;
- switch (tiling) {
- default:
- unreachable("not reached");
- case I915_TILING_NONE:
- *mask_x = *mask_y = 0;
- break;
- case I915_TILING_X:
- *mask_x = 512 / cpp - 1;
- *mask_y = 7;
- break;
- case I915_TILING_Y:
- *mask_x = 128 / cpp - 1;
- *mask_y = 31;
- break;
- }
+ intel_get_tile_dims(tiling, tr_mode, cpp, &tile_w_bytes, &tile_h);
+
+ *mask_x = tile_w_bytes / cpp - 1;
+ *mask_y = tile_h - 1;
}
/**
uint32_t x, y;
uint32_t mask_x, mask_y;
- intel_miptree_get_tile_masks(mt, &mask_x, &mask_y, false);
+ intel_get_tile_masks(mt->tiling, mt->tr_mode, mt->cpp, false, &mask_x, &mask_y);
intel_miptree_get_image_offset(mt, level, slice, &x, &y);
*tile_x = x & mask_x;
intel_obj->needs_validate = true;
}
+static void
+intel_miptree_init_mcs(struct brw_context *brw,
+ struct intel_mipmap_tree *mt,
+ int init_value)
+{
+ /* From the Ivy Bridge PRM, Vol 2 Part 1 p326:
+ *
+ * When MCS buffer is enabled and bound to MSRT, it is required that it
+ * is cleared prior to any rendering.
+ *
+ * Since we don't use the MCS buffer for any purpose other than rendering,
+ * it makes sense to just clear it immediately upon allocation.
+ *
+ * Note: the clear value for MCS buffers is all 1's, so we memset to 0xff.
+ */
+ void *data = intel_miptree_map_raw(brw, mt->mcs_mt);
+ memset(data, init_value, mt->mcs_mt->total_height * mt->mcs_mt->pitch);
+ intel_miptree_unmap_raw(mt->mcs_mt);
+ mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_CLEAR;
+}
+
static bool
intel_miptree_alloc_mcs(struct brw_context *brw,
struct intel_mipmap_tree *mt,
*/
format = MESA_FORMAT_R_UINT32;
break;
+ case 16:
+ /* 64 bits/pixel are required for MCS data when using 16x MSAA (4 bits
+ * for each sample).
+ */
+ format = MESA_FORMAT_RG_UINT32;
+ break;
default:
unreachable("Unrecognized sample count in intel_miptree_alloc_mcs");
};
*/
const uint32_t mcs_flags = MIPTREE_LAYOUT_ACCELERATED_UPLOAD |
MIPTREE_LAYOUT_TILING_Y;
- mt->mcs_mt = intel_miptree_create(brw,
- mt->target,
- format,
- mt->first_level,
- mt->last_level,
- mt->logical_width0,
- mt->logical_height0,
- mt->logical_depth0,
- 0 /* num_samples */,
- mcs_flags);
-
- /* From the Ivy Bridge PRM, Vol 2 Part 1 p326:
- *
- * When MCS buffer is enabled and bound to MSRT, it is required that it
- * is cleared prior to any rendering.
- *
- * Since we don't use the MCS buffer for any purpose other than rendering,
- * it makes sense to just clear it immediately upon allocation.
- *
- * Note: the clear value for MCS buffers is all 1's, so we memset to 0xff.
- */
- void *data = intel_miptree_map_raw(brw, mt->mcs_mt);
- memset(data, 0xff, mt->mcs_mt->total_height * mt->mcs_mt->pitch);
- intel_miptree_unmap_raw(brw, mt->mcs_mt);
- mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_CLEAR;
+ mt->mcs_mt = miptree_create(brw,
+ mt->target,
+ format,
+ mt->first_level,
+ mt->last_level,
+ mt->logical_width0,
+ mt->logical_height0,
+ mt->logical_depth0,
+ 0 /* num_samples */,
+ mcs_flags);
+
+ intel_miptree_init_mcs(brw, mt, 0xFF);
return mt->mcs_mt;
}
const mesa_format format = MESA_FORMAT_R_UINT32;
unsigned block_width_px;
unsigned block_height;
- intel_get_non_msrt_mcs_alignment(brw, mt, &block_width_px, &block_height);
+ intel_get_non_msrt_mcs_alignment(mt, &block_width_px, &block_height);
unsigned width_divisor = block_width_px * 4;
unsigned height_divisor = block_height * 8;
+
+ /* The Skylake MCS is twice as tall as the Broadwell MCS.
+ *
+ * In pre-Skylake, each bit in the MCS contained the state of 2 cachelines
+ * in the main surface. In Skylake, it's two bits. The extra bit
+ * doubles the MCS height, not width, because in Skylake the MCS is always
+ * Y-tiled.
+ */
+ if (brw->gen >= 9)
+ height_divisor /= 2;
+
unsigned mcs_width =
ALIGN(mt->logical_width0, width_divisor) / width_divisor;
unsigned mcs_height =
ALIGN(mt->logical_height0, height_divisor) / height_divisor;
assert(mt->logical_depth0 == 1);
- uint32_t layout_flags = MIPTREE_LAYOUT_ACCELERATED_UPLOAD |
- MIPTREE_LAYOUT_TILING_Y;
+ uint32_t layout_flags = MIPTREE_LAYOUT_TILING_Y;
+
if (brw->gen >= 8) {
layout_flags |= MIPTREE_LAYOUT_FORCE_HALIGN16;
}
- mt->mcs_mt = intel_miptree_create(brw,
- mt->target,
- format,
- mt->first_level,
- mt->last_level,
- mcs_width,
- mcs_height,
- mt->logical_depth0,
- 0 /* num_samples */,
- layout_flags);
+
+ /* On Gen9+ clients are not currently capable of consuming compressed
+ * single-sampled buffers. Disabling compression allows us to skip
+ * resolves.
+ */
+ const bool lossless_compression_disabled = INTEL_DEBUG & DEBUG_NO_RBC;
+ const bool is_lossless_compressed =
+ unlikely(!lossless_compression_disabled) &&
+ brw->gen >= 9 && !mt->is_scanout &&
+ intel_miptree_supports_lossless_compressed(brw, mt);
+
+ /* In case of compression mcs buffer needs to be initialised requiring the
+ * buffer to be immediately mapped to cpu space for writing. Therefore do
+ * not use the gpu access flag which can cause an unnecessary delay if the
+ * backing pages happened to be just used by the GPU.
+ */
+ if (!is_lossless_compressed)
+ layout_flags |= MIPTREE_LAYOUT_ACCELERATED_UPLOAD;
+
+ mt->mcs_mt = miptree_create(brw,
+ mt->target,
+ format,
+ mt->first_level,
+ mt->last_level,
+ mcs_width,
+ mcs_height,
+ mt->logical_depth0,
+ 0 /* num_samples */,
+ layout_flags);
+
+ /* From Gen9 onwards single-sampled (non-msrt) auxiliary buffers are
+ * used for lossless compression which requires similar initialisation
+ * as multi-sample compression.
+ */
+ if (is_lossless_compressed) {
+ /* Hardware sets the auxiliary buffer to all zeroes when it does full
+ * resolve. Initialize it accordingly in case the first renderer is
+ * cpu (or other none compression aware party).
+ *
+ * This is also explicitly stated in the spec (MCS Buffer for Render
+ * Target(s)):
+ * "If Software wants to enable Color Compression without Fast clear,
+ * Software needs to initialize MCS with zeros."
+ */
+ intel_miptree_init_mcs(brw, mt, 0);
+ mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_RESOLVED;
+ mt->msaa_layout = INTEL_MSAA_LAYOUT_CMS;
+ }
return mt->mcs_mt;
}
+void
+intel_miptree_prepare_mcs(struct brw_context *brw,
+ struct intel_mipmap_tree *mt)
+{
+ if (mt->mcs_mt)
+ return;
+
+ if (brw->gen < 9)
+ return;
+
+ /* Single sample compression is represented re-using msaa compression
+ * layout type: "Compressed Multisampled Surfaces".
+ */
+ if (mt->msaa_layout != INTEL_MSAA_LAYOUT_CMS || mt->num_samples > 1)
+ return;
+
+ /* Clients are not currently capable of consuming compressed
+ * single-sampled buffers.
+ */
+ if (mt->is_scanout)
+ return;
+
+ assert(intel_tiling_supports_non_msrt_mcs(brw, mt->tiling) ||
+ intel_miptree_supports_lossless_compressed(brw, mt));
+
+ /* Consider if lossless compression is supported but the needed
+ * auxiliary buffer doesn't exist yet.
+ *
+ * Failing to allocate the auxiliary buffer means running out of
+ * memory. The pointer to the aux miptree is left NULL which should
+ * signal non-compressed behavior.
+ */
+ if (!intel_miptree_alloc_non_msrt_mcs(brw, mt)) {
+ _mesa_warning(NULL,
+ "Failed to allocated aux buffer for lossless"
+ " compressed %p %u:%u %s\n",
+ mt, mt->logical_width0, mt->logical_height0,
+ _mesa_get_format_name(mt->format));
+ }
+}
/**
* Helper for intel_miptree_alloc_hiz() that sets
/* Gen7 PRM Volume 2, Part 1, 11.5.3 "Hierarchical Depth Buffer" documents
* adjustments required for Z_Height and Z_Width based on multisampling.
*/
- if (brw->gen < 9) {
- switch (mt->num_samples) {
- case 0:
- case 1:
- break;
- case 2:
- case 4:
- z_width *= 2;
- z_height *= 2;
- break;
- case 8:
- z_width *= 4;
- z_height *= 2;
- break;
- default:
- unreachable("unsupported sample count");
- }
+ switch (mt->num_samples) {
+ case 0:
+ case 1:
+ break;
+ case 2:
+ case 4:
+ z_width *= 2;
+ z_height *= 2;
+ break;
+ case 8:
+ z_width *= 4;
+ z_height *= 2;
+ break;
+ default:
+ unreachable("unsupported sample count");
}
const unsigned vertical_align = 8; /* 'j' in the docs */
unsigned H_i = H0;
unsigned Z_i = Z0;
hz_height = 0;
- for (int level = mt->first_level; level <= mt->last_level; ++level) {
+ for (unsigned level = mt->first_level; level <= mt->last_level; ++level) {
unsigned h_i = ALIGN(H_i, vertical_align);
/* sum(i=0 to m; h_i * max(1, floor(Z_Depth/2**i))) */
hz_height += h_i * Z_i;
/* Gen7 PRM Volume 2, Part 1, 11.5.3 "Hierarchical Depth Buffer" documents
* adjustments required for Z_Height and Z_Width based on multisampling.
*/
- switch (mt->num_samples) {
- case 0:
- case 1:
- break;
- case 2:
- case 4:
- z_width *= 2;
- z_height *= 2;
- break;
- case 8:
- z_width *= 4;
- z_height *= 2;
- break;
- default:
- unreachable("unsupported sample count");
+ if (brw->gen < 9) {
+ switch (mt->num_samples) {
+ case 0:
+ case 1:
+ break;
+ case 2:
+ case 4:
+ z_width *= 2;
+ z_height *= 2;
+ break;
+ case 8:
+ z_width *= 4;
+ z_height *= 2;
+ break;
+ default:
+ unreachable("unsupported sample count");
+ }
}
const unsigned vertical_align = 8; /* 'j' in the docs */
unsigned Z_i = Z0;
unsigned sum_h_i = 0;
unsigned hz_height_3d_sum = 0;
- for (int level = mt->first_level; level <= mt->last_level; ++level) {
+ for (unsigned level = mt->first_level; level <= mt->last_level; ++level) {
unsigned i = level - mt->first_level;
unsigned h_i = ALIGN(H_i, vertical_align);
/* sum(i=2 to m; h_i) */
return false;
/* Mark that all slices need a HiZ resolve. */
- for (int level = mt->first_level; level <= mt->last_level; ++level) {
+ for (unsigned level = mt->first_level; level <= mt->last_level; ++level) {
if (!intel_miptree_level_enable_hiz(brw, mt, level))
continue;
- for (int layer = 0; layer < mt->level[level].depth; ++layer) {
+ for (unsigned layer = 0; layer < mt->level[level].depth; ++layer) {
struct intel_resolve_map *m = malloc(sizeof(struct intel_resolve_map));
exec_node_init(&m->link);
m->level = level;
void
intel_miptree_resolve_color(struct brw_context *brw,
- struct intel_mipmap_tree *mt)
+ struct intel_mipmap_tree *mt,
+ int flags)
{
+ /* From gen9 onwards there is new compression scheme for single sampled
+ * surfaces called "lossless compressed". These don't need to be always
+ * resolved.
+ */
+ if ((flags & INTEL_MIPTREE_IGNORE_CCS_E) &&
+ intel_miptree_is_lossless_compressed(brw, mt))
+ return;
+
switch (mt->fast_clear_state) {
case INTEL_FAST_CLEAR_STATE_NO_MCS:
case INTEL_FAST_CLEAR_STATE_RESOLVED:
case INTEL_FAST_CLEAR_STATE_UNRESOLVED:
case INTEL_FAST_CLEAR_STATE_CLEAR:
/* Fast color clear resolves only make sense for non-MSAA buffers. */
- if (mt->msaa_layout == INTEL_MSAA_LAYOUT_NONE)
- brw_meta_resolve_color(brw, mt);
+ if (mt->msaa_layout == INTEL_MSAA_LAYOUT_NONE ||
+ intel_miptree_is_lossless_compressed(brw, mt)) {
+ brw_blorp_resolve_color(brw, mt);
+ }
break;
}
}
assert(mt->msaa_layout == INTEL_MSAA_LAYOUT_NONE);
if (mt->mcs_mt) {
- intel_miptree_resolve_color(brw, mt);
+ intel_miptree_resolve_color(brw, mt, 0);
intel_miptree_release(&mt->mcs_mt);
mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_NO_MCS;
}
struct intel_mipmap_tree *src,
struct intel_mipmap_tree *dst)
{
- if (brw->gen < 8) {
- brw_blorp_blit_miptrees(brw,
- src, 0 /* level */, 0 /* layer */, src->format,
- dst, 0 /* level */, 0 /* layer */, dst->format,
- 0, 0,
- src->logical_width0, src->logical_height0,
- 0, 0,
- dst->logical_width0, dst->logical_height0,
- GL_NEAREST, false, false /*mirror x, y*/);
- } else if (src->format == MESA_FORMAT_S_UINT8) {
- brw_meta_stencil_updownsample(brw, src, dst);
- } else {
- brw_meta_updownsample(brw, src, dst);
- }
+ brw_blorp_blit_miptrees(brw,
+ src, 0 /* level */, 0 /* layer */,
+ src->format, SWIZZLE_XYZW,
+ dst, 0 /* level */, 0 /* layer */, dst->format,
+ 0, 0,
+ src->logical_width0, src->logical_height0,
+ 0, 0,
+ dst->logical_width0, dst->logical_height0,
+ GL_NEAREST, false, false /*mirror x, y*/,
+ false, false);
if (src->stencil_mt) {
- if (brw->gen >= 8) {
- brw_meta_stencil_updownsample(brw, src->stencil_mt, dst);
- return;
- }
-
brw_blorp_blit_miptrees(brw,
src->stencil_mt, 0 /* level */, 0 /* layer */,
- src->stencil_mt->format,
+ src->stencil_mt->format, SWIZZLE_XYZW,
dst->stencil_mt, 0 /* level */, 0 /* layer */,
dst->stencil_mt->format,
0, 0,
src->logical_width0, src->logical_height0,
0, 0,
dst->logical_width0, dst->logical_height0,
- GL_NEAREST, false, false /*mirror x, y*/);
+ GL_NEAREST, false, false /*mirror x, y*/,
+ false, false /* decode/encode srgb */);
}
}
-void *
+static void *
intel_miptree_map_raw(struct brw_context *brw, struct intel_mipmap_tree *mt)
{
/* CPU accesses to color buffers don't understand fast color clears, so
* resolve any pending fast color clears before we map.
*/
- intel_miptree_resolve_color(brw, mt);
+ intel_miptree_resolve_color(brw, mt, 0);
drm_intel_bo *bo = mt->bo;
return bo->virtual;
}
-void
-intel_miptree_unmap_raw(struct brw_context *brw,
- struct intel_mipmap_tree *mt)
+static void
+intel_miptree_unmap_raw(struct intel_mipmap_tree *mt)
{
drm_intel_bo_unmap(mt->bo);
}
}
static void
-intel_miptree_unmap_gtt(struct brw_context *brw,
- struct intel_mipmap_tree *mt,
- struct intel_miptree_map *map,
- unsigned int level,
- unsigned int slice)
+intel_miptree_unmap_gtt(struct intel_mipmap_tree *mt)
{
- intel_miptree_unmap_raw(brw, mt);
+ intel_miptree_unmap_raw(mt);
}
static void
struct intel_miptree_map *map,
unsigned int level, unsigned int slice)
{
- map->mt = intel_miptree_create(brw, GL_TEXTURE_2D, mt->format,
- 0, 0,
- map->w, map->h, 1,
- 0, MIPTREE_LAYOUT_TILING_NONE);
+ map->linear_mt = intel_miptree_create(brw, GL_TEXTURE_2D, mt->format,
+ /* first_level */ 0,
+ /* last_level */ 0,
+ map->w, map->h, 1,
+ /* samples */ 0,
+ MIPTREE_LAYOUT_TILING_NONE);
- if (!map->mt) {
+ if (!map->linear_mt) {
fprintf(stderr, "Failed to allocate blit temporary\n");
goto fail;
}
- map->stride = map->mt->pitch;
+ map->stride = map->linear_mt->pitch;
/* One of either READ_BIT or WRITE_BIT or both is set. READ_BIT implies no
* INVALIDATE_RANGE_BIT. WRITE_BIT needs the original values read in unless
if (!intel_miptree_blit(brw,
mt, level, slice,
map->x, map->y, false,
- map->mt, 0, 0,
+ map->linear_mt, 0, 0,
0, 0, false,
map->w, map->h, GL_COPY)) {
fprintf(stderr, "Failed to blit\n");
}
}
- map->ptr = intel_miptree_map_raw(brw, map->mt);
+ map->ptr = intel_miptree_map_raw(brw, map->linear_mt);
DBG("%s: %d,%d %dx%d from mt %p (%s) %d,%d = %p/%d\n", __func__,
map->x, map->y, map->w, map->h,
return;
fail:
- intel_miptree_release(&map->mt);
+ intel_miptree_release(&map->linear_mt);
map->ptr = NULL;
map->stride = 0;
}
{
struct gl_context *ctx = &brw->ctx;
- intel_miptree_unmap_raw(brw, map->mt);
+ intel_miptree_unmap_raw(map->linear_mt);
if (map->mode & GL_MAP_WRITE_BIT) {
bool ok = intel_miptree_blit(brw,
- map->mt, 0, 0,
+ map->linear_mt, 0, 0,
0, 0, false,
mt, level, slice,
map->x, map->y, false,
WARN_ONCE(!ok, "Failed to blit from linear temporary mapping");
}
- intel_miptree_release(&map->mt);
+ intel_miptree_release(&map->linear_mt);
}
/**
_mesa_streaming_load_memcpy(dst_ptr, src_ptr, width_bytes);
}
- intel_miptree_unmap_raw(brw, mt);
+ intel_miptree_unmap_raw(mt);
}
static void
}
}
- intel_miptree_unmap_raw(brw, mt);
+ intel_miptree_unmap_raw(mt);
DBG("%s: %d,%d %dx%d from mt %p %d,%d = %p/%d\n", __func__,
map->x, map->y, map->w, map->h,
for (uint32_t y = 0; y < map->h; y++) {
for (uint32_t x = 0; x < map->w; x++) {
ptrdiff_t offset = intel_offset_S8(mt->pitch,
- x + map->x,
- y + map->y,
+ image_x + x + map->x,
+ image_y + y + map->y,
brw->has_swizzling);
tiled_s8_map[offset] = untiled_s8_map[y * map->w + x];
}
}
- intel_miptree_unmap_raw(brw, mt);
+ intel_miptree_unmap_raw(mt);
}
free(map->buffer);
map->ptr, map->stride,
map->w, map->h, mt->etc_format);
- intel_miptree_unmap_raw(brw, mt);
+ intel_miptree_unmap_raw(mt);
free(map->buffer);
}
}
}
- intel_miptree_unmap_raw(brw, s_mt);
- intel_miptree_unmap_raw(brw, z_mt);
+ intel_miptree_unmap_raw(s_mt);
+ intel_miptree_unmap_raw(z_mt);
DBG("%s: %d,%d %dx%d from z mt %p %d,%d, s mt %p %d,%d = %p/%d\n",
__func__,
}
}
- intel_miptree_unmap_raw(brw, s_mt);
- intel_miptree_unmap_raw(brw, z_mt);
+ intel_miptree_unmap_raw(s_mt);
+ intel_miptree_unmap_raw(z_mt);
DBG("%s: %d,%d %dx%d from z mt %p (%s) %d,%d, s mt %p %d,%d = %p/%d\n",
__func__,
{
if (brw->has_llc &&
/* It's probably not worth swapping to the blit ring because of
- * all the overhead involved.
+ * all the overhead involved. But, we must use blitter for the
+ * surfaces with INTEL_MIPTREE_TRMODE_{YF,YS}.
*/
- !(mode & GL_MAP_WRITE_BIT) &&
+ (!(mode & GL_MAP_WRITE_BIT) ||
+ mt->tr_mode != INTEL_MIPTREE_TRMODE_NONE) &&
!mt->compressed &&
(mt->tiling == I915_TILING_X ||
/* Prior to Sandybridge, the blitter can't handle Y tiling */
- (brw->gen >= 6 && mt->tiling == I915_TILING_Y)) &&
+ (brw->gen >= 6 && mt->tiling == I915_TILING_Y) ||
+ /* Fast copy blit on skl+ supports all tiling formats. */
+ brw->gen >= 9) &&
can_blit_slice(mt, level, slice))
return true;
intel_miptree_map_movntdqa(brw, mt, map, level, slice);
#endif
} else {
+ /* intel_miptree_map_gtt() doesn't support surfaces with Yf/Ys tiling. */
+ assert(mt->tr_mode == INTEL_MIPTREE_TRMODE_NONE);
intel_miptree_map_gtt(brw, mt, map, level, slice);
}
intel_miptree_unmap_etc(brw, mt, map, level, slice);
} else if (mt->stencil_mt && !(map->mode & BRW_MAP_DIRECT_BIT)) {
intel_miptree_unmap_depthstencil(brw, mt, map, level, slice);
- } else if (map->mt) {
+ } else if (map->linear_mt) {
intel_miptree_unmap_blit(brw, mt, map, level, slice);
#if defined(USE_SSE41)
} else if (map->buffer && cpu_has_sse4_1) {
intel_miptree_unmap_movntdqa(brw, mt, map, level, slice);
#endif
} else {
- intel_miptree_unmap_gtt(brw, mt, map, level, slice);
+ intel_miptree_unmap_gtt(mt);
}
intel_miptree_release_map(mt, level, slice);
}
+
+void
+intel_miptree_get_isl_surf(struct brw_context *brw,
+ const struct intel_mipmap_tree *mt,
+ struct isl_surf *surf)
+{
+ switch (mt->target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_1D_ARRAY: {
+ surf->dim = ISL_SURF_DIM_1D;
+ if (brw->gen >= 9 && mt->tiling == I915_TILING_NONE)
+ surf->dim_layout = ISL_DIM_LAYOUT_GEN9_1D;
+ else
+ surf->dim_layout = ISL_DIM_LAYOUT_GEN4_2D;
+ break;
+ }
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_RECTANGLE:
+ case GL_TEXTURE_CUBE_MAP:
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+ case GL_TEXTURE_EXTERNAL_OES:
+ surf->dim = ISL_SURF_DIM_2D;
+ surf->dim_layout = ISL_DIM_LAYOUT_GEN4_2D;
+ break;
+ case GL_TEXTURE_3D:
+ surf->dim = ISL_SURF_DIM_3D;
+ if (brw->gen >= 9)
+ surf->dim_layout = ISL_DIM_LAYOUT_GEN4_2D;
+ else
+ surf->dim_layout = ISL_DIM_LAYOUT_GEN4_3D;
+ break;
+ default:
+ unreachable("Invalid texture target");
+ }
+
+ if (mt->num_samples > 1) {
+ switch (mt->msaa_layout) {
+ case INTEL_MSAA_LAYOUT_IMS:
+ surf->msaa_layout = ISL_MSAA_LAYOUT_INTERLEAVED;
+ break;
+ case INTEL_MSAA_LAYOUT_UMS:
+ case INTEL_MSAA_LAYOUT_CMS:
+ surf->msaa_layout = ISL_MSAA_LAYOUT_ARRAY;
+ break;
+ default:
+ unreachable("Invalid MSAA layout");
+ }
+ } else {
+ surf->msaa_layout = ISL_MSAA_LAYOUT_NONE;
+ }
+
+ if (mt->format == MESA_FORMAT_S_UINT8) {
+ surf->tiling = ISL_TILING_W;
+ /* The ISL definition of row_pitch matches the surface state pitch field
+ * a bit better than intel_mipmap_tree. In particular, ISL incorporates
+ * the factor of 2 for W-tiling in row_pitch.
+ */
+ surf->row_pitch = 2 * mt->pitch;
+ } else {
+ switch (mt->tiling) {
+ case I915_TILING_NONE:
+ surf->tiling = ISL_TILING_LINEAR;
+ break;
+ case I915_TILING_X:
+ surf->tiling = ISL_TILING_X;
+ break;
+ case I915_TILING_Y:
+ switch (mt->tr_mode) {
+ case INTEL_MIPTREE_TRMODE_NONE:
+ surf->tiling = ISL_TILING_Y0;
+ break;
+ case INTEL_MIPTREE_TRMODE_YF:
+ surf->tiling = ISL_TILING_Yf;
+ break;
+ case INTEL_MIPTREE_TRMODE_YS:
+ surf->tiling = ISL_TILING_Ys;
+ break;
+ }
+ break;
+ default:
+ unreachable("Invalid tiling mode");
+ }
+
+ surf->row_pitch = mt->pitch;
+ }
+
+ surf->format = translate_tex_format(brw, mt->format, false);
+
+ if (brw->gen >= 9) {
+ if (surf->dim == ISL_SURF_DIM_1D && surf->tiling == ISL_TILING_LINEAR) {
+ /* For gen9 1-D surfaces, intel_mipmap_tree has a bogus alignment. */
+ surf->image_alignment_el = isl_extent3d(64, 1, 1);
+ } else {
+ /* On gen9+, intel_mipmap_tree stores the horizontal and vertical
+ * alignment in terms of surface elements like we want.
+ */
+ surf->image_alignment_el = isl_extent3d(mt->halign, mt->valign, 1);
+ }
+ } else {
+ /* On earlier gens it's stored in pixels. */
+ unsigned bw, bh;
+ _mesa_get_format_block_size(mt->format, &bw, &bh);
+ surf->image_alignment_el =
+ isl_extent3d(mt->halign / bw, mt->valign / bh, 1);
+ }
+
+ surf->logical_level0_px.width = mt->logical_width0;
+ surf->logical_level0_px.height = mt->logical_height0;
+ if (surf->dim == ISL_SURF_DIM_3D) {
+ surf->logical_level0_px.depth = mt->logical_depth0;
+ surf->logical_level0_px.array_len = 1;
+ } else if (mt->target == GL_TEXTURE_CUBE_MAP ||
+ mt->target == GL_TEXTURE_CUBE_MAP_ARRAY) {
+ /* For cube maps, mt->logical_depth0 is in number of cubes */
+ surf->logical_level0_px.depth = 1;
+ surf->logical_level0_px.array_len = mt->logical_depth0 * 6;
+ } else {
+ surf->logical_level0_px.depth = 1;
+ surf->logical_level0_px.array_len = mt->logical_depth0;
+ }
+
+ surf->phys_level0_sa.width = mt->physical_width0;
+ surf->phys_level0_sa.height = mt->physical_height0;
+ if (surf->dim == ISL_SURF_DIM_3D) {
+ surf->phys_level0_sa.depth = mt->physical_depth0;
+ surf->phys_level0_sa.array_len = 1;
+ } else {
+ surf->phys_level0_sa.depth = 1;
+ surf->phys_level0_sa.array_len = mt->physical_depth0;
+ }
+
+ surf->levels = mt->last_level + 1;
+ surf->samples = MAX2(mt->num_samples, 1);
+
+ surf->size = 0; /* TODO */
+ surf->alignment = 0; /* TODO */
+
+ switch (surf->dim_layout) {
+ case ISL_DIM_LAYOUT_GEN4_2D:
+ case ISL_DIM_LAYOUT_GEN4_3D:
+ if (brw->gen >= 9) {
+ surf->array_pitch_el_rows = mt->qpitch;
+ } else {
+ unsigned bw, bh;
+ _mesa_get_format_block_size(mt->format, &bw, &bh);
+ assert(mt->qpitch % bh == 0);
+ surf->array_pitch_el_rows = mt->qpitch / bh;
+ }
+ break;
+ case ISL_DIM_LAYOUT_GEN9_1D:
+ surf->array_pitch_el_rows = 1;
+ break;
+ }
+
+ switch (mt->array_layout) {
+ case ALL_LOD_IN_EACH_SLICE:
+ surf->array_pitch_span = ISL_ARRAY_PITCH_SPAN_FULL;
+ break;
+ case ALL_SLICES_AT_EACH_LOD:
+ surf->array_pitch_span = ISL_ARRAY_PITCH_SPAN_COMPACT;
+ break;
+ default:
+ unreachable("Invalid array layout");
+ }
+
+ surf->usage = 0; /* TODO */
+}