mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-14 20:58:06 +02:00
isl: Move some genxml surface state helpers into an include file
On XeHP, the XY_BLOCK_COPY_BLT command has a number of fields that describe the layout of the surface, much like SURFACE_STATE does. Several of them are encoded in such a similar manner that we really would like to reuse the isl helpers for emitting those. This commit moves them into a new isl_genX_helpers.h file which I can include from the BLORP code. (The alternative would be to add XY_BLOCK_COPY_BLT filling commands to isl, but that...seems more like a BLORP feature.) Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14094>
This commit is contained in:
parent
b3b63c795f
commit
2d7c25fb9d
3 changed files with 204 additions and 166 deletions
199
src/intel/isl/isl_genX_helpers.h
Normal file
199
src/intel/isl/isl_genX_helpers.h
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* Copyright 2016 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* 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, 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 above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*/
|
||||
|
||||
#ifndef ISL_SURFACE_STATE_H
|
||||
#define ISL_SURFACE_STATE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @file isl_surface_state.h
|
||||
*
|
||||
* ============================= GENXML CODE =============================
|
||||
* [This file is compiled once per generation.]
|
||||
* =======================================================================
|
||||
*
|
||||
* Helpers for encoding SURFACE_STATE and XY_BLOCK_COPY_BLT commands.
|
||||
*/
|
||||
|
||||
UNUSED static const uint8_t
|
||||
isl_encode_halign(uint8_t halign)
|
||||
{
|
||||
switch (halign) {
|
||||
#if GFX_VERx10 >= 125
|
||||
case 16: return HALIGN_16;
|
||||
case 32: return HALIGN_32;
|
||||
case 64: return HALIGN_64;
|
||||
case 128: return HALIGN_128;
|
||||
#elif GFX_VER >= 8
|
||||
case 4: return HALIGN_4;
|
||||
case 8: return HALIGN_8;
|
||||
case 16: return HALIGN_16;
|
||||
#elif GFX_VER >= 7
|
||||
case 4: return HALIGN_4;
|
||||
case 8: return HALIGN_8;
|
||||
#endif
|
||||
default: unreachable("Invalid halign");
|
||||
}
|
||||
}
|
||||
|
||||
UNUSED static const uint8_t
|
||||
isl_encode_valign(uint8_t valign)
|
||||
{
|
||||
switch (valign) {
|
||||
#if GFX_VER >= 8
|
||||
case 4: return VALIGN_4;
|
||||
case 8: return VALIGN_8;
|
||||
case 16: return VALIGN_16;
|
||||
#elif GFX_VER >= 6
|
||||
case 2: return VALIGN_2;
|
||||
case 4: return VALIGN_4;
|
||||
#endif
|
||||
default: unreachable("Invalid valign");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the horizontal and vertical alignment in the units expected by the
|
||||
* hardware. Note that this does NOT give you the actual hardware enum values
|
||||
* but an index into the isl_encode_[hv]align arrays above.
|
||||
*/
|
||||
UNUSED static struct isl_extent3d
|
||||
isl_get_image_alignment(const struct isl_surf *surf)
|
||||
{
|
||||
if (GFX_VERx10 >= 125) {
|
||||
if (surf->tiling == ISL_TILING_64) {
|
||||
/* The hardware ignores the alignment values. Anyway, the surface's
|
||||
* true alignment is likely outside the enum range of HALIGN* and
|
||||
* VALIGN*.
|
||||
*/
|
||||
return isl_extent3d(128, 4, 1);
|
||||
} else if (isl_format_get_layout(surf->format)->bpb % 3 == 0) {
|
||||
/* On XeHP, RENDER_SURFACE_STATE.SurfaceHorizontalAlignment is in
|
||||
* units of elements for 24, 48, and 96 bpb formats.
|
||||
*/
|
||||
return isl_surf_get_image_alignment_el(surf);
|
||||
} else {
|
||||
/* On XeHP, RENDER_SURFACE_STATE.SurfaceHorizontalAlignment is in
|
||||
* units of bytes for formats that are powers of two.
|
||||
*/
|
||||
const uint32_t bs = isl_format_get_layout(surf->format)->bpb / 8;
|
||||
return isl_extent3d(surf->image_alignment_el.w * bs,
|
||||
surf->image_alignment_el.h,
|
||||
surf->image_alignment_el.d);
|
||||
}
|
||||
} else if (GFX_VER >= 9) {
|
||||
if (isl_tiling_is_std_y(surf->tiling) ||
|
||||
surf->dim_layout == ISL_DIM_LAYOUT_GFX9_1D) {
|
||||
/* The hardware ignores the alignment values. Anyway, the surface's
|
||||
* true alignment is likely outside the enum range of HALIGN* and
|
||||
* VALIGN*.
|
||||
*/
|
||||
return isl_extent3d(4, 4, 1);
|
||||
} else {
|
||||
/* In Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in units
|
||||
* of surface elements (not pixels nor samples). For compressed formats,
|
||||
* a "surface element" is defined as a compression block. For example,
|
||||
* if SurfaceVerticalAlignment is VALIGN_4 and SurfaceFormat is an ETC2
|
||||
* format (ETC2 has a block height of 4), then the vertical alignment is
|
||||
* 4 compression blocks or, equivalently, 16 pixels.
|
||||
*/
|
||||
return isl_surf_get_image_alignment_el(surf);
|
||||
}
|
||||
} else {
|
||||
/* Pre-Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in
|
||||
* units of surface samples. For example, if SurfaceVerticalAlignment
|
||||
* is VALIGN_4 and the surface is singlesampled, then for any surface
|
||||
* format (compressed or not) the vertical alignment is
|
||||
* 4 pixels.
|
||||
*/
|
||||
return isl_surf_get_image_alignment_sa(surf);
|
||||
}
|
||||
}
|
||||
|
||||
UNUSED static uint32_t
|
||||
isl_get_qpitch(const struct isl_surf *surf)
|
||||
{
|
||||
switch (surf->dim_layout) {
|
||||
default:
|
||||
unreachable("Bad isl_surf_dim");
|
||||
case ISL_DIM_LAYOUT_GFX4_2D:
|
||||
if (GFX_VER >= 9) {
|
||||
if (surf->dim == ISL_SURF_DIM_3D && surf->tiling == ISL_TILING_W) {
|
||||
/* This is rather annoying and completely undocumented. It
|
||||
* appears that the hardware has a bug (or undocumented feature)
|
||||
* regarding stencil buffers most likely related to the way
|
||||
* W-tiling is handled as modified Y-tiling. If you bind a 3-D
|
||||
* stencil buffer normally, and use texelFetch on it, the z or
|
||||
* array index will get implicitly multiplied by 2 for no obvious
|
||||
* reason. The fix appears to be to divide qpitch by 2 for
|
||||
* W-tiled surfaces.
|
||||
*/
|
||||
return isl_surf_get_array_pitch_el_rows(surf) / 2;
|
||||
} else {
|
||||
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_GFX9_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);
|
||||
case ISL_DIM_LAYOUT_GFX4_3D:
|
||||
/* QPitch doesn't make sense for ISL_DIM_LAYOUT_GFX4_3D since it uses a
|
||||
* different pitch at each LOD. Also, the QPitch field is ignored for
|
||||
* these surfaces. From the Broadwell PRM documentation for QPitch:
|
||||
*
|
||||
* This field specifies the distance in rows between array slices. It
|
||||
* is used only in the following cases:
|
||||
* - Surface Array is enabled OR
|
||||
* - Number of Mulitsamples is not NUMSAMPLES_1 and Multisampled
|
||||
* Surface Storage Format set to MSFMT_MSS OR
|
||||
* - Surface Type is SURFTYPE_CUBE
|
||||
*
|
||||
* None of the three conditions above can possibly apply to a 3D surface
|
||||
* so it is safe to just set QPitch to 0.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -38,45 +38,7 @@ __gen_combine_address(__attribute__((unused)) void *data,
|
|||
#include "genxml/genX_pack.h"
|
||||
|
||||
#include "isl_priv.h"
|
||||
|
||||
#if GFX_VER >= 7
|
||||
static const uint8_t isl_encode_halign(uint8_t halign)
|
||||
{
|
||||
switch (halign) {
|
||||
#if GFX_VERx10 >= 125
|
||||
case 16: return HALIGN_16;
|
||||
case 32: return HALIGN_32;
|
||||
case 64: return HALIGN_64;
|
||||
case 128: return HALIGN_128;
|
||||
#elif GFX_VER >= 8
|
||||
case 4: return HALIGN_4;
|
||||
case 8: return HALIGN_8;
|
||||
case 16: return HALIGN_16;
|
||||
#else
|
||||
case 4: return HALIGN_4;
|
||||
case 8: return HALIGN_8;
|
||||
#endif
|
||||
default: unreachable("Invalid halign");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if GFX_VER >= 6
|
||||
static const uint8_t isl_encode_valign(uint8_t valign)
|
||||
{
|
||||
switch (valign) {
|
||||
#if GFX_VER >= 8
|
||||
case 4: return VALIGN_4;
|
||||
case 8: return VALIGN_8;
|
||||
case 16: return VALIGN_16;
|
||||
#else
|
||||
case 2: return VALIGN_2;
|
||||
case 4: return VALIGN_4;
|
||||
#endif
|
||||
default: unreachable("Invalid valign");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#include "isl_genX_helpers.h"
|
||||
|
||||
#if GFX_VER >= 8
|
||||
static const uint8_t isl_encode_tiling[] = {
|
||||
|
|
@ -158,131 +120,6 @@ get_surftype(enum isl_surf_dim dim, isl_surf_usage_flags_t usage)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the horizontal and vertical alignment in the units expected by the
|
||||
* hardware. Note that this does NOT give you the actual hardware enum values
|
||||
* but an index into the isl_encode_[hv]align arrays above.
|
||||
*/
|
||||
UNUSED static struct isl_extent3d
|
||||
get_image_alignment(const struct isl_surf *surf)
|
||||
{
|
||||
if (GFX_VERx10 >= 125) {
|
||||
if (surf->tiling == ISL_TILING_64) {
|
||||
/* The hardware ignores the alignment values. Anyway, the surface's
|
||||
* true alignment is likely outside the enum range of HALIGN* and
|
||||
* VALIGN*.
|
||||
*/
|
||||
return isl_extent3d(128, 4, 1);
|
||||
} else if (isl_format_get_layout(surf->format)->bpb % 3 == 0) {
|
||||
/* On XeHP, RENDER_SURFACE_STATE.SurfaceHorizontalAlignment is in
|
||||
* units of elements for 24, 48, and 96 bpb formats.
|
||||
*/
|
||||
return isl_surf_get_image_alignment_el(surf);
|
||||
} else {
|
||||
/* On XeHP, RENDER_SURFACE_STATE.SurfaceHorizontalAlignment is in
|
||||
* units of bytes for formats that are powers of two.
|
||||
*/
|
||||
const uint32_t bs = isl_format_get_layout(surf->format)->bpb / 8;
|
||||
return isl_extent3d(surf->image_alignment_el.w * bs,
|
||||
surf->image_alignment_el.h,
|
||||
surf->image_alignment_el.d);
|
||||
}
|
||||
} else if (GFX_VER >= 9) {
|
||||
if (isl_tiling_is_std_y(surf->tiling) ||
|
||||
surf->dim_layout == ISL_DIM_LAYOUT_GFX9_1D) {
|
||||
/* The hardware ignores the alignment values. Anyway, the surface's
|
||||
* true alignment is likely outside the enum range of HALIGN* and
|
||||
* VALIGN*.
|
||||
*/
|
||||
return isl_extent3d(4, 4, 1);
|
||||
} else {
|
||||
/* In Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in units
|
||||
* of surface elements (not pixels nor samples). For compressed formats,
|
||||
* a "surface element" is defined as a compression block. For example,
|
||||
* if SurfaceVerticalAlignment is VALIGN_4 and SurfaceFormat is an ETC2
|
||||
* format (ETC2 has a block height of 4), then the vertical alignment is
|
||||
* 4 compression blocks or, equivalently, 16 pixels.
|
||||
*/
|
||||
return isl_surf_get_image_alignment_el(surf);
|
||||
}
|
||||
} else {
|
||||
/* Pre-Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in
|
||||
* units of surface samples. For example, if SurfaceVerticalAlignment
|
||||
* is VALIGN_4 and the surface is singlesampled, then for any surface
|
||||
* format (compressed or not) the vertical alignment is
|
||||
* 4 pixels.
|
||||
*/
|
||||
return isl_surf_get_image_alignment_sa(surf);
|
||||
}
|
||||
}
|
||||
|
||||
#if GFX_VER >= 8
|
||||
static uint32_t
|
||||
get_qpitch(const struct isl_surf *surf)
|
||||
{
|
||||
switch (surf->dim_layout) {
|
||||
default:
|
||||
unreachable("Bad isl_surf_dim");
|
||||
case ISL_DIM_LAYOUT_GFX4_2D:
|
||||
if (GFX_VER >= 9) {
|
||||
if (surf->dim == ISL_SURF_DIM_3D && surf->tiling == ISL_TILING_W) {
|
||||
/* This is rather annoying and completely undocumented. It
|
||||
* appears that the hardware has a bug (or undocumented feature)
|
||||
* regarding stencil buffers most likely related to the way
|
||||
* W-tiling is handled as modified Y-tiling. If you bind a 3-D
|
||||
* stencil buffer normally, and use texelFetch on it, the z or
|
||||
* array index will get implicitly multiplied by 2 for no obvious
|
||||
* reason. The fix appears to be to divide qpitch by 2 for
|
||||
* W-tiled surfaces.
|
||||
*/
|
||||
return isl_surf_get_array_pitch_el_rows(surf) / 2;
|
||||
} else {
|
||||
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_GFX9_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);
|
||||
case ISL_DIM_LAYOUT_GFX4_3D:
|
||||
/* QPitch doesn't make sense for ISL_DIM_LAYOUT_GFX4_3D since it uses a
|
||||
* different pitch at each LOD. Also, the QPitch field is ignored for
|
||||
* these surfaces. From the Broadwell PRM documentation for QPitch:
|
||||
*
|
||||
* This field specifies the distance in rows between array slices. It
|
||||
* is used only in the following cases:
|
||||
* - Surface Array is enabled OR
|
||||
* - Number of Mulitsamples is not NUMSAMPLES_1 and Multisampled
|
||||
* Surface Storage Format set to MSFMT_MSS OR
|
||||
* - Surface Type is SURFTYPE_CUBE
|
||||
*
|
||||
* None of the three conditions above can possibly apply to a 3D surface
|
||||
* so it is safe to just set QPitch to 0.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif /* GFX_VER >= 8 */
|
||||
|
||||
void
|
||||
isl_genX(surf_fill_state_s)(const struct isl_device *dev, void *state,
|
||||
const struct isl_surf_fill_state_info *restrict info)
|
||||
|
|
@ -509,7 +346,8 @@ isl_genX(surf_fill_state_s)(const struct isl_device *dev, void *state,
|
|||
#endif
|
||||
|
||||
#if GFX_VER >= 6
|
||||
const struct isl_extent3d image_align = get_image_alignment(info->surf);
|
||||
const struct isl_extent3d image_align =
|
||||
isl_get_image_alignment(info->surf);
|
||||
s.SurfaceVerticalAlignment = isl_encode_valign(image_align.height);
|
||||
#if GFX_VER >= 7
|
||||
s.SurfaceHorizontalAlignment = isl_encode_halign(image_align.width);
|
||||
|
|
@ -524,7 +362,7 @@ isl_genX(surf_fill_state_s)(const struct isl_device *dev, void *state,
|
|||
}
|
||||
|
||||
#if GFX_VER >= 8
|
||||
s.SurfaceQPitch = get_qpitch(info->surf) >> 2;
|
||||
s.SurfaceQPitch = isl_get_qpitch(info->surf) >> 2;
|
||||
#elif GFX_VER == 7
|
||||
s.SurfaceArraySpacing = info->surf->array_pitch_span ==
|
||||
ISL_ARRAY_PITCH_SPAN_COMPACT;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
isl_per_hw_ver_files = files(
|
||||
'isl_emit_depth_stencil.c',
|
||||
'isl_surface_state.c',
|
||||
'isl_genX_helpers.h',
|
||||
)
|
||||
|
||||
isl_gfx4_files = files(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue