};
#endif
+#if GEN_GEN >= 7
static const uint32_t isl_to_gen_multisample_layout[] = {
[ISL_MSAA_LAYOUT_NONE] = MSFMT_MSS,
[ISL_MSAA_LAYOUT_INTERLEAVED] = MSFMT_DEPTH_STENCIL,
[ISL_MSAA_LAYOUT_ARRAY] = MSFMT_MSS,
};
+#endif
+
+#if GEN_GEN >= 9
+static const uint32_t isl_to_gen_aux_mode[] = {
+ [ISL_AUX_USAGE_NONE] = AUX_NONE,
+ [ISL_AUX_USAGE_HIZ] = AUX_HIZ,
+ [ISL_AUX_USAGE_MCS] = AUX_CCS_D,
+ [ISL_AUX_USAGE_CCS_D] = AUX_CCS_D,
+ [ISL_AUX_USAGE_CCS_E] = AUX_CCS_E,
+};
+#elif GEN_GEN >= 8
+static const uint32_t isl_to_gen_aux_mode[] = {
+ [ISL_AUX_USAGE_NONE] = AUX_NONE,
+ [ISL_AUX_USAGE_HIZ] = AUX_HIZ,
+ [ISL_AUX_USAGE_MCS] = AUX_MCS,
+ [ISL_AUX_USAGE_CCS_D] = AUX_MCS,
+};
+#endif
static uint8_t
get_surftype(enum isl_surf_dim dim, isl_surf_usage_flags_t usage)
* hardware. Note that this does NOT give you the actual hardware enum values
* but an index into the isl_to_gen_[hv]align arrays above.
*/
-static struct isl_extent3d
+static inline struct isl_extent3d
get_image_alignment(const struct isl_surf *surf)
{
if (GEN_GEN >= 9) {
* true alignment is likely outside the enum range of HALIGN* and
* VALIGN*.
*/
- return isl_extent3d(0, 0, 0);
+ 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,
s.Width = info->surf->logical_level0_px.width - 1;
s.Height = info->surf->logical_level0_px.height - 1;
+ /* In the gen6 PRM Volume 1 Part 1: Graphics Core, Section 7.18.3.7.1
+ * (Surface Arrays For all surfaces other than separate stencil buffer):
+ *
+ * "[DevSNB] Errata: Sampler MSAA Qpitch will be 4 greater than the value
+ * calculated in the equation above , for every other odd Surface Height
+ * starting from 1 i.e. 1,5,9,13"
+ *
+ * Since this Qpitch errata only impacts the sampler, we have to adjust the
+ * input for the rendering surface to achieve the same qpitch. For the
+ * affected heights, we increment the height by 1 for the rendering
+ * surface.
+ */
+ if (GEN_GEN == 6 && (info->view->usage & ISL_SURF_USAGE_RENDER_TARGET_BIT) &&
+ info->surf->samples > 1 &&
+ (info->surf->logical_level0_px.height % 4) == 1)
+ s.Height++;
+
switch (s.SurfaceType) {
case SURFTYPE_1D:
case SURFTYPE_2D:
unreachable("bad SurfaceType");
}
+#if GEN_GEN >= 7
s.SurfaceArray = info->surf->dim != ISL_SURF_DIM_3D;
+#endif
if (info->view->usage & ISL_SURF_USAGE_RENDER_TARGET_BIT) {
/* For render target surfaces, the hardware interprets field
s.MipTailStartLOD = 15;
#endif
+#if GEN_GEN >= 6
const struct isl_extent3d image_align = get_image_alignment(info->surf);
s.SurfaceVerticalAlignment = isl_to_gen_valign[image_align.height];
+#if GEN_GEN >= 7
s.SurfaceHorizontalAlignment = isl_to_gen_halign[image_align.width];
+#endif
+#endif
if (info->surf->dim_layout == ISL_DIM_LAYOUT_GEN9_1D) {
/* For gen9 1-D textures, surface pitch is ignored */
#endif
}
+#if GEN_GEN >= 6
+ s.NumberofMultisamples = ffs(info->surf->samples) - 1;
+#if GEN_GEN >= 7
s.MultisampledSurfaceStorageFormat =
isl_to_gen_multisample_layout[info->surf->msaa_layout];
- s.NumberofMultisamples = ffs(info->surf->samples) - 1;
+#endif
+#endif
#if (GEN_GEN >= 8 || GEN_IS_HASWELL)
s.ShaderChannelSelectRed = info->view->channel_select[0];
#endif
s.SurfaceBaseAddress = info->address;
+
+#if GEN_GEN >= 6
s.MOCS = info->mocs;
+#endif
+
+#if GEN_GEN > 4 || GEN_IS_G4X
+ if (info->x_offset_sa != 0 || info->y_offset_sa != 0) {
+ /* There are fairly strict rules about when the offsets can be used.
+ * These are mostly taken from the Sky Lake PRM documentation for
+ * RENDER_SURFACE_STATE.
+ */
+ assert(info->surf->tiling != ISL_TILING_LINEAR);
+ assert(info->surf->dim == ISL_SURF_DIM_2D);
+ assert(isl_is_pow2(isl_format_get_layout(info->view->format)->bpb));
+ assert(info->surf->levels == 1);
+ assert(info->surf->logical_level0_px.array_len == 1);
+ assert(info->aux_usage == ISL_AUX_USAGE_NONE);
+#if GEN_GEN >= 7
+ s.SurfaceArray = false;
+#endif
+ }
+
+ const unsigned x_div = 4;
+ const unsigned y_div = GEN_GEN >= 8 ? 4 : 2;
+ assert(info->x_offset_sa % x_div == 0);
+ assert(info->y_offset_sa % y_div == 0);
+ s.XOffset = info->x_offset_sa / x_div;
+ s.YOffset = info->y_offset_sa / y_div;
+#else
+ assert(info->x_offset_sa == 0);
+ assert(info->y_offset_sa == 0);
+#endif
+
+#if GEN_GEN >= 7
+ if (info->aux_surf && info->aux_usage != ISL_AUX_USAGE_NONE) {
+ struct isl_tile_info tile_info;
+ isl_surf_get_tile_info(dev, info->aux_surf, &tile_info);
+ uint32_t pitch_in_tiles =
+ info->aux_surf->row_pitch / tile_info.phys_extent_B.width;
#if GEN_GEN >= 8
- s.AuxiliarySurfaceMode = AUX_NONE;
+ assert(GEN_GEN >= 9 || info->aux_usage != ISL_AUX_USAGE_CCS_E);
+ s.AuxiliarySurfacePitch = pitch_in_tiles - 1;
+ /* Auxiliary surfaces in ISL have compressed formats but the hardware
+ * doesn't expect our definition of the compression, it expects qpitch
+ * in units of samples on the main surface.
+ */
+ s.AuxiliarySurfaceQPitch =
+ isl_surf_get_array_pitch_sa_rows(info->aux_surf) >> 2;
+ s.AuxiliarySurfaceBaseAddress = info->aux_address;
+ s.AuxiliarySurfaceMode = isl_to_gen_aux_mode[info->aux_usage];
#else
- s.MCSEnable = false;
+ assert(info->aux_usage == ISL_AUX_USAGE_MCS ||
+ info->aux_usage == ISL_AUX_USAGE_CCS_D);
+ s.MCSBaseAddress = info->aux_address,
+ s.MCSSurfacePitch = pitch_in_tiles - 1;
+ s.MCSEnable = true;
+#endif
+ }
#endif
#if GEN_GEN >= 8
uint32_t num_elements = info->size / info->stride;
if (GEN_GEN >= 7) {
+ /* From the IVB PRM, SURFACE_STATE::Height,
+ *
+ * For typed buffer and structured buffer surfaces, the number
+ * of entries in the buffer ranges from 1 to 2^27. For raw buffer
+ * surfaces, the number of entries in the buffer is the number of bytes
+ * which can range from 1 to 2^30.
+ */
if (info->format == ISL_FORMAT_RAW) {
- assert(num_elements <= (1ull << 31));
+ assert(num_elements <= (1ull << 30));
assert((num_elements & 3) == 0);
} else {
assert(num_elements <= (1ull << 27));
struct GENX(RENDER_SURFACE_STATE) s = { 0, };
s.SurfaceType = SURFTYPE_BUFFER;
- s.SurfaceArray = false;
s.SurfaceFormat = info->format;
+
+#if GEN_GEN >= 6
s.SurfaceVerticalAlignment = isl_to_gen_valign[4];
+#if GEN_GEN >= 7
s.SurfaceHorizontalAlignment = isl_to_gen_halign[4];
+ s.SurfaceArray = false;
+#endif
+#endif
+
+#if GEN_GEN >= 7
s.Height = ((num_elements - 1) >> 7) & 0x3fff;
s.Width = (num_elements - 1) & 0x7f;
s.Depth = ((num_elements - 1) >> 21) & 0x3ff;
+#else
+ s.Height = ((num_elements - 1) >> 7) & 0x1fff;
+ s.Width = (num_elements - 1) & 0x7f;
+ s.Depth = ((num_elements - 1) >> 20) & 0x7f;
+#endif
+
s.SurfacePitch = info->stride - 1;
+
+#if GEN_GEN >= 6
s.NumberofMultisamples = MULTISAMPLECOUNT_1;
+#endif
#if (GEN_GEN >= 8)
s.TileMode = LINEAR;
#endif
s.SurfaceBaseAddress = info->address;
+#if GEN_GEN >= 6
s.MOCS = info->mocs;
+#endif
#if (GEN_GEN >= 8 || GEN_IS_HASWELL)
s.ShaderChannelSelectRed = SCS_RED;