dev->ss.size = RENDER_SURFACE_STATE_length(info) * 4;
dev->ss.align = isl_align(dev->ss.size, 32);
+ dev->ss.clear_value_size =
+ isl_align(RENDER_SURFACE_STATE_RedClearColor_bits(info) +
+ RENDER_SURFACE_STATE_GreenClearColor_bits(info) +
+ RENDER_SURFACE_STATE_BlueClearColor_bits(info) +
+ RENDER_SURFACE_STATE_AlphaClearColor_bits(info), 32) / 8;
+
+ dev->ss.clear_value_offset =
+ RENDER_SURFACE_STATE_RedClearColor_start(info) / 32 * 4;
+
assert(RENDER_SURFACE_STATE_SurfaceBaseAddress_start(info) % 8 == 0);
dev->ss.addr_offset =
RENDER_SURFACE_STATE_SurfaceBaseAddress_start(info) / 8;
};
}
+bool
+isl_color_value_is_zero(union isl_color_value value,
+ enum isl_format format)
+{
+ const struct isl_format_layout *fmtl = isl_format_get_layout(format);
+
+#define RETURN_FALSE_IF_NOT_0(c, i) \
+ if (fmtl->channels.c.bits && value.u32[i] != 0) \
+ return false
+
+ RETURN_FALSE_IF_NOT_0(r, 0);
+ RETURN_FALSE_IF_NOT_0(g, 1);
+ RETURN_FALSE_IF_NOT_0(b, 2);
+ RETURN_FALSE_IF_NOT_0(a, 3);
+
+#undef RETURN_FALSE_IF_NOT_0
+
+ return true;
+}
+
+bool
+isl_color_value_is_zero_one(union isl_color_value value,
+ enum isl_format format)
+{
+ const struct isl_format_layout *fmtl = isl_format_get_layout(format);
+
+#define RETURN_FALSE_IF_NOT_0_1(c, i, field) \
+ if (fmtl->channels.c.bits && value.field[i] != 0 && value.field[i] != 1) \
+ return false
+
+ if (isl_format_has_int_channel(format)) {
+ RETURN_FALSE_IF_NOT_0_1(r, 0, u32);
+ RETURN_FALSE_IF_NOT_0_1(g, 1, u32);
+ RETURN_FALSE_IF_NOT_0_1(b, 2, u32);
+ RETURN_FALSE_IF_NOT_0_1(a, 3, u32);
+ } else {
+ RETURN_FALSE_IF_NOT_0_1(r, 0, f32);
+ RETURN_FALSE_IF_NOT_0_1(g, 1, f32);
+ RETURN_FALSE_IF_NOT_0_1(b, 2, f32);
+ RETURN_FALSE_IF_NOT_0_1(a, 3, f32);
+ }
+
+#undef RETURN_FALSE_IF_NOT_0_1
+
+ return true;
+}
+
/**
* @param[out] tiling is set only on success
*/
static enum isl_dim_layout
isl_surf_choose_dim_layout(const struct isl_device *dev,
enum isl_surf_dim logical_dim,
- enum isl_tiling tiling)
+ enum isl_tiling tiling,
+ isl_surf_usage_flags_t usage)
{
/* Sandy bridge needs a special layout for HiZ and stencil. */
if (ISL_DEV_GEN(dev) == 6 &&
switch (logical_dim) {
case ISL_SURF_DIM_1D:
case ISL_SURF_DIM_2D:
+ /* From the G45 PRM Vol. 1a, "6.17.4.1 Hardware Cube Map Layout":
+ *
+ * The cube face textures are stored in the same way as 3D surfaces
+ * are stored (see section 6.17.5 for details). For cube surfaces,
+ * however, the depth is equal to the number of faces (always 6) and
+ * is not reduced for each MIP.
+ */
+ if (ISL_DEV_GEN(dev) == 4 && (usage & ISL_SURF_USAGE_CUBE_BIT))
+ return ISL_DIM_LAYOUT_GEN4_3D;
+
return ISL_DIM_LAYOUT_GEN4_2D;
case ISL_SURF_DIM_3D:
return ISL_DIM_LAYOUT_GEN4_3D;
break;
case ISL_SURF_DIM_2D:
- assert(dim_layout == ISL_DIM_LAYOUT_GEN4_2D ||
- dim_layout == ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ);
+ if (ISL_DEV_GEN(dev) == 4 && (info->usage & ISL_SURF_USAGE_CUBE_BIT))
+ assert(dim_layout == ISL_DIM_LAYOUT_GEN4_3D);
+ else
+ assert(dim_layout == ISL_DIM_LAYOUT_GEN4_2D ||
+ dim_layout == ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ);
if (tiling == ISL_TILING_Ys && info->samples > 1)
isl_finishme("%s:%s: multisample TileYs layout", __FILE__, __func__);
&phys_slice0_sa);
*total_extent_el = (struct isl_extent2d) {
.w = isl_assert_div(phys_slice0_sa.w, fmtl->bw),
- .h = *array_pitch_el_rows * phys_level0_sa->array_len,
+ .h = *array_pitch_el_rows * (phys_level0_sa->array_len - 1) +
+ isl_assert_div(phys_slice0_sa.h, fmtl->bh),
};
}
const struct isl_format_layout *fmtl = isl_format_get_layout(info->format);
assert(info->samples == 1);
- assert(phys_level0_sa->array_len == 1);
+
+ if (info->dim != ISL_SURF_DIM_3D) {
+ /* From the G45 PRM Vol. 1a, "6.17.4.1 Hardware Cube Map Layout":
+ *
+ * The cube face textures are stored in the same way as 3D surfaces
+ * are stored (see section 6.17.5 for details). For cube surfaces,
+ * however, the depth is equal to the number of faces (always 6) and
+ * is not reduced for each MIP.
+ */
+ assert(ISL_DEV_GEN(dev) == 4);
+ assert(info->usage & ISL_SURF_USAGE_CUBE_BIT);
+ assert(phys_level0_sa->array_len == 6);
+ } else {
+ assert(phys_level0_sa->array_len == 1);
+ }
uint32_t total_w = 0;
uint32_t total_h = 0;
uint32_t W0 = phys_level0_sa->w;
uint32_t H0 = phys_level0_sa->h;
uint32_t D0 = phys_level0_sa->d;
+ uint32_t A0 = phys_level0_sa->a;
for (uint32_t l = 0; l < info->levels; ++l) {
uint32_t level_w = isl_align_npot(isl_minify(W0, l), image_align_sa->w);
uint32_t level_h = isl_align_npot(isl_minify(H0, l), image_align_sa->h);
- uint32_t level_d = isl_align_npot(isl_minify(D0, l), image_align_sa->d);
+ uint32_t level_d = info->dim == ISL_SURF_DIM_3D ? isl_minify(D0, l) : A0;
uint32_t max_layers_horiz = MIN(level_d, 1u << l);
uint32_t max_layers_vert = isl_align(level_d, 1u << l) / (1u << l);
{
MAYBE_UNUSED const struct isl_format_layout *fmtl = isl_format_get_layout(info->format);
- assert(phys_level0_sa->height == 1);
+ assert(phys_level0_sa->height / fmtl->bh == 1);
assert(phys_level0_sa->depth == 1);
assert(info->samples == 1);
assert(image_align_sa->w >= fmtl->bw);
const struct isl_extent2d *phys_total_el,
uint32_t *out_row_pitch)
{
- const uint32_t alignment =
+ uint32_t alignment =
isl_calc_row_pitch_alignment(surf_info, tile_info);
+ /* If pitch isn't given and it can be chosen freely, align it by cache line
+ * allowing one to use blit engine on the surface.
+ */
+ if (surf_info->row_pitch == 0 && tile_info->tiling == ISL_TILING_LINEAR) {
+ /* From the Broadwell PRM docs for XY_SRC_COPY_BLT::SourceBaseAddress:
+ *
+ * "Base address of the destination surface: X=0, Y=0. Lower 32bits
+ * of the 48bit addressing. When Src Tiling is enabled (Bit_15
+ * enabled), this address must be 4KB-aligned. When Tiling is not
+ * enabled, this address should be CL (64byte) aligned."
+ */
+ alignment = MAX2(alignment, 64);
+ }
+
const uint32_t min_row_pitch =
isl_calc_min_row_pitch(dev, surf_info, tile_info, phys_total_el,
alignment);
!pitch_in_range(row_pitch, _3DSTATE_HIER_DEPTH_BUFFER_SurfacePitch_bits(dev->info)))
return false;
- if (surf_info->usage & ISL_SURF_USAGE_STENCIL_BIT)
- isl_finishme("validate row pitch of stencil surfaces");
+ const uint32_t stencil_pitch_bits = dev->use_separate_stencil ?
+ _3DSTATE_STENCIL_BUFFER_SurfacePitch_bits(dev->info) :
+ _3DSTATE_DEPTH_BUFFER_SurfacePitch_bits(dev->info);
+
+ if ((surf_info->usage & ISL_SURF_USAGE_STENCIL_BIT) &&
+ !pitch_in_range(row_pitch, stencil_pitch_bits))
+ return false;
done:
*out_row_pitch = row_pitch;
return true;
}
-/**
- * Calculate and apply any padding required for the surface.
- *
- * @param[inout] total_h_el is updated with the new height
- * @param[out] pad_bytes is overwritten with additional padding requirements.
- */
-static void
-isl_apply_surface_padding(const struct isl_device *dev,
- const struct isl_surf_init_info *restrict info,
- const struct isl_tile_info *tile_info,
- uint32_t *total_h_el,
- uint32_t *pad_bytes)
-{
- const struct isl_format_layout *fmtl = isl_format_get_layout(info->format);
-
- *pad_bytes = 0;
-
- /* From the Broadwell PRM >> Volume 5: Memory Views >> Common Surface
- * Formats >> Surface Padding Requirements >> Render Target and Media
- * Surfaces:
- *
- * The data port accesses data (pixels) outside of the surface if they
- * are contained in the same cache request as pixels that are within the
- * surface. These pixels will not be returned by the requesting message,
- * however if these pixels lie outside of defined pages in the GTT,
- * a GTT error will result when the cache request is processed. In
- * order to avoid these GTT errors, “padding” at the bottom of the
- * surface is sometimes necessary.
- *
- * From the Broadwell PRM >> Volume 5: Memory Views >> Common Surface
- * Formats >> Surface Padding Requirements >> Sampling Engine Surfaces:
- *
- * ... Lots of padding requirements, all listed separately below.
- */
-
- /* We can safely ignore the first padding requirement, quoted below,
- * because isl doesn't do buffers.
- *
- * - [pre-BDW] For buffers, which have no inherent “height,” padding
- * requirements are different. A buffer must be padded to the next
- * multiple of 256 array elements, with an additional 16 bytes added
- * beyond that to account for the L1 cache line.
- */
-
- /*
- * - For compressed textures [...], padding at the bottom of the surface
- * is to an even compressed row.
- */
- if (isl_format_is_compressed(info->format))
- *total_h_el = isl_align(*total_h_el, 2);
-
- /*
- * - For cube surfaces, an additional two rows of padding are required
- * at the bottom of the surface.
- */
- if (info->usage & ISL_SURF_USAGE_CUBE_BIT)
- *total_h_el += 2;
-
- /*
- * - For packed YUV, 96 bpt, 48 bpt, and 24 bpt surface formats,
- * additional padding is required. These surfaces require an extra row
- * plus 16 bytes of padding at the bottom in addition to the general
- * padding requirements.
- */
- if (isl_format_is_yuv(info->format) &&
- (fmtl->bpb == 96 || fmtl->bpb == 48|| fmtl->bpb == 24)) {
- *total_h_el += 1;
- *pad_bytes += 16;
- }
-
- /*
- * - For linear surfaces, additional padding of 64 bytes is required at
- * the bottom of the surface. This is in addition to the padding
- * required above.
- */
- if (tile_info->tiling == ISL_TILING_LINEAR)
- *pad_bytes += 64;
-
- /* The below text weakens, not strengthens, the padding requirements for
- * linear surfaces. Therefore we can safely ignore it.
- *
- * - [BDW+] For SURFTYPE_BUFFER, SURFTYPE_1D, and SURFTYPE_2D non-array,
- * non-MSAA, non-mip-mapped surfaces in linear memory, the only
- * padding requirement is to the next aligned 64-byte boundary beyond
- * the end of the surface. The rest of the padding requirements
- * documented above do not apply to these surfaces.
- */
-
- /*
- * - [SKL+] For SURFTYPE_2D and SURFTYPE_3D with linear mode and
- * height % 4 != 0, the surface must be padded with
- * 4-(height % 4)*Surface Pitch # of bytes.
- */
- if (ISL_DEV_GEN(dev) >= 9 &&
- tile_info->tiling == ISL_TILING_LINEAR &&
- (info->dim == ISL_SURF_DIM_2D || info->dim == ISL_SURF_DIM_3D)) {
- *total_h_el = isl_align(*total_h_el, 4);
- }
-
- /*
- * - [SKL+] For SURFTYPE_1D with linear mode, the surface must be padded
- * to 4 times the Surface Pitch # of bytes
- */
- if (ISL_DEV_GEN(dev) >= 9 &&
- tile_info->tiling == ISL_TILING_LINEAR &&
- info->dim == ISL_SURF_DIM_1D) {
- *total_h_el += 4;
- }
-}
-
bool
isl_surf_init_s(const struct isl_device *dev,
struct isl_surf *surf,
isl_tiling_get_info(tiling, fmtl->bpb, &tile_info);
const enum isl_dim_layout dim_layout =
- isl_surf_choose_dim_layout(dev, info->dim, tiling);
+ isl_surf_choose_dim_layout(dev, info->dim, tiling, info->usage);
enum isl_msaa_layout msaa_layout;
if (!isl_choose_msaa_layout(dev, info, tiling, &msaa_layout))
array_pitch_span, &array_pitch_el_rows,
&phys_total_el);
- uint32_t padded_h_el = phys_total_el.h;
- uint32_t pad_bytes;
- isl_apply_surface_padding(dev, info, &tile_info, &padded_h_el, &pad_bytes);
-
uint32_t row_pitch;
if (!isl_calc_row_pitch(dev, info, &tile_info, dim_layout,
&phys_total_el, &row_pitch))
uint32_t base_alignment;
uint64_t size;
if (tiling == ISL_TILING_LINEAR) {
- size = (uint64_t) row_pitch * padded_h_el + pad_bytes;
+ size = (uint64_t) row_pitch * phys_total_el.h;
/* From the Broadwell PRM Vol 2d, RENDER_SURFACE_STATE::SurfaceBaseAddress:
*
}
base_alignment = isl_round_up_to_power_of_two(base_alignment);
} else {
- padded_h_el += isl_align_div_npot(pad_bytes, row_pitch);
const uint32_t total_h_tl =
- isl_align_div(padded_h_el, tile_info.logical_extent_el.height);
+ isl_align_div(phys_total_el.h, tile_info.logical_extent_el.height);
size = (uint64_t) total_h_tl * tile_info.phys_extent_B.height * row_pitch;
*/
if (size > (uint64_t) 1 << 31)
return false;
- } else {
+ } else if (ISL_DEV_GEN(dev) < 11) {
/* From the Skylake PRM Vol 5, Maximum Surface Size in Bytes:
* "In addition to restrictions on maximum height, width, and depth,
* surfaces are also restricted to a maximum size of 2^38 bytes.
*/
if (size > (uint64_t) 1 << 38)
return false;
+ } else {
+ /* gen11+ platforms raised this limit to 2^44 bytes. */
+ if (size > (uint64_t) 1 << 44)
+ return false;
}
*surf = (struct isl_surf) {
bool
isl_surf_get_ccs_surf(const struct isl_device *dev,
const struct isl_surf *surf,
- struct isl_surf *ccs_surf)
+ struct isl_surf *ccs_surf,
+ uint32_t row_pitch)
{
assert(surf->samples == 1 && surf->msaa_layout == ISL_MSAA_LAYOUT_NONE);
assert(ISL_DEV_GEN(dev) >= 7);
if (surf->usage & ISL_SURF_USAGE_DISABLE_AUX_BIT)
return false;
+ /* The PRM doesn't say this explicitly, but fast-clears don't appear to
+ * work for 3D textures until gen9 where the layout of 3D textures changes
+ * to match 2D array textures.
+ */
if (ISL_DEV_GEN(dev) <= 8 && surf->dim != ISL_SURF_DIM_2D)
return false;
+ /* From the HSW PRM Volume 7: 3D-Media-GPGPU, page 652 (Color Clear of
+ * Non-MultiSampler Render Target Restrictions):
+ *
+ * "Support is for non-mip-mapped and non-array surface types only."
+ *
+ * This restriction is lifted on gen8+. Technically, it may be possible to
+ * create a CCS for an arrayed or mipmapped image and only enable CCS_D
+ * when rendering to the base slice. However, there is no documentation
+ * tell us what the hardware would do in that case or what it does if you
+ * walk off the bases slice. (Does it ignore CCS or does it start
+ * scribbling over random memory?) We play it safe and just follow the
+ * docs and don't allow CCS_D for arrayed or mip-mapped surfaces.
+ */
+ if (ISL_DEV_GEN(dev) <= 7 &&
+ (surf->levels > 1 || surf->logical_level0_px.array_len > 1))
+ return false;
+
if (isl_format_is_compressed(surf->format))
return false;
return false;
}
- /* Multi-LOD and multi-layer CCS isn't supported on gen7. */
- const uint8_t levels = ISL_DEV_GEN(dev) <= 7 ? 1 : surf->levels;
- const uint32_t array_len = ISL_DEV_GEN(dev) <= 7 ?
- 1 : surf->logical_level0_px.array_len;
-
return isl_surf_init(dev, ccs_surf,
.dim = surf->dim,
.format = ccs_format,
.width = surf->logical_level0_px.width,
.height = surf->logical_level0_px.height,
.depth = surf->logical_level0_px.depth,
- .levels = levels,
- .array_len = array_len,
+ .levels = surf->levels,
+ .array_len = surf->logical_level0_px.array_len,
.samples = 1,
+ .row_pitch = row_pitch,
.usage = ISL_SURF_USAGE_CCS_BIT,
.tiling_flags = ISL_TILING_CCS_BIT);
}
+#define isl_genX_call(dev, func, ...) \
+ switch (ISL_DEV_GEN(dev)) { \
+ case 4: \
+ /* G45 surface state is the same as gen5 */ \
+ if (ISL_DEV_IS_G4X(dev)) { \
+ isl_gen5_##func(__VA_ARGS__); \
+ } else { \
+ isl_gen4_##func(__VA_ARGS__); \
+ } \
+ break; \
+ case 5: \
+ isl_gen5_##func(__VA_ARGS__); \
+ break; \
+ case 6: \
+ isl_gen6_##func(__VA_ARGS__); \
+ break; \
+ case 7: \
+ if (ISL_DEV_IS_HASWELL(dev)) { \
+ isl_gen75_##func(__VA_ARGS__); \
+ } else { \
+ isl_gen7_##func(__VA_ARGS__); \
+ } \
+ break; \
+ case 8: \
+ isl_gen8_##func(__VA_ARGS__); \
+ break; \
+ case 9: \
+ isl_gen9_##func(__VA_ARGS__); \
+ break; \
+ case 10: \
+ isl_gen10_##func(__VA_ARGS__); \
+ break; \
+ case 11: \
+ isl_gen11_##func(__VA_ARGS__); \
+ break; \
+ default: \
+ assert(!"Unknown hardware generation"); \
+ }
+
void
isl_surf_fill_state_s(const struct isl_device *dev, void *state,
const struct isl_surf_fill_state_info *restrict info)
info->surf->logical_level0_px.array_len);
}
- switch (ISL_DEV_GEN(dev)) {
- case 4:
- if (ISL_DEV_IS_G4X(dev)) {
- /* G45 surface state is the same as gen5 */
- isl_gen5_surf_fill_state_s(dev, state, info);
- } else {
- isl_gen4_surf_fill_state_s(dev, state, info);
- }
- break;
- case 5:
- isl_gen5_surf_fill_state_s(dev, state, info);
- break;
- case 6:
- isl_gen6_surf_fill_state_s(dev, state, info);
- break;
- case 7:
- if (ISL_DEV_IS_HASWELL(dev)) {
- isl_gen75_surf_fill_state_s(dev, state, info);
- } else {
- isl_gen7_surf_fill_state_s(dev, state, info);
- }
- break;
- case 8:
- isl_gen8_surf_fill_state_s(dev, state, info);
- break;
- case 9:
- isl_gen9_surf_fill_state_s(dev, state, info);
- break;
- case 10:
- isl_gen10_surf_fill_state_s(dev, state, info);
- break;
- default:
- assert(!"Cannot fill surface state for this gen");
- }
+ isl_genX_call(dev, surf_fill_state_s, dev, state, info);
}
void
isl_buffer_fill_state_s(const struct isl_device *dev, void *state,
const struct isl_buffer_fill_state_info *restrict info)
{
- switch (ISL_DEV_GEN(dev)) {
- case 4:
- case 5:
- /* Gen 4-5 are all the same when it comes to buffer surfaces */
- isl_gen5_buffer_fill_state_s(state, info);
- break;
- case 6:
- isl_gen6_buffer_fill_state_s(state, info);
- break;
- case 7:
- if (ISL_DEV_IS_HASWELL(dev)) {
- isl_gen75_buffer_fill_state_s(state, info);
- } else {
- isl_gen7_buffer_fill_state_s(state, info);
- }
- break;
- case 8:
- isl_gen8_buffer_fill_state_s(state, info);
- break;
- case 9:
- isl_gen9_buffer_fill_state_s(state, info);
- break;
- case 10:
- isl_gen10_buffer_fill_state_s(state, info);
- break;
- default:
- assert(!"Cannot fill surface state for this gen");
- }
+ isl_genX_call(dev, buffer_fill_state_s, state, info);
+}
+
+void
+isl_null_fill_state(const struct isl_device *dev, void *state,
+ struct isl_extent3d size)
+{
+ isl_genX_call(dev, null_fill_state, state, size);
}
void
}
}
- switch (ISL_DEV_GEN(dev)) {
- case 4:
- if (ISL_DEV_IS_G4X(dev)) {
- /* G45 surface state is the same as gen5 */
- isl_gen5_emit_depth_stencil_hiz_s(dev, batch, info);
- } else {
- isl_gen4_emit_depth_stencil_hiz_s(dev, batch, info);
- }
- break;
- case 5:
- isl_gen5_emit_depth_stencil_hiz_s(dev, batch, info);
- break;
- case 6:
- isl_gen6_emit_depth_stencil_hiz_s(dev, batch, info);
- break;
- case 7:
- if (ISL_DEV_IS_HASWELL(dev)) {
- isl_gen75_emit_depth_stencil_hiz_s(dev, batch, info);
- } else {
- isl_gen7_emit_depth_stencil_hiz_s(dev, batch, info);
- }
- break;
- case 8:
- isl_gen8_emit_depth_stencil_hiz_s(dev, batch, info);
- break;
- case 9:
- isl_gen9_emit_depth_stencil_hiz_s(dev, batch, info);
- break;
- case 10:
- isl_gen10_emit_depth_stencil_hiz_s(dev, batch, info);
- break;
- default:
- assert(!"Cannot fill surface state for this gen");
- }
+ isl_genX_call(dev, emit_depth_stencil_hiz_s, dev, batch, info);
}
/**
}
}
+void
+isl_surf_get_image_surf(const struct isl_device *dev,
+ const struct isl_surf *surf,
+ uint32_t level,
+ uint32_t logical_array_layer,
+ uint32_t logical_z_offset_px,
+ struct isl_surf *image_surf,
+ uint32_t *offset_B,
+ uint32_t *x_offset_sa,
+ uint32_t *y_offset_sa)
+{
+ isl_surf_get_image_offset_B_tile_sa(surf,
+ level,
+ logical_array_layer,
+ logical_z_offset_px,
+ offset_B,
+ x_offset_sa,
+ y_offset_sa);
+
+ /* Even for cube maps there will be only single face, therefore drop the
+ * corresponding flag if present.
+ */
+ const isl_surf_usage_flags_t usage =
+ surf->usage & (~ISL_SURF_USAGE_CUBE_BIT);
+
+ bool ok UNUSED;
+ ok = isl_surf_init(dev, image_surf,
+ .dim = ISL_SURF_DIM_2D,
+ .format = surf->format,
+ .width = isl_minify(surf->logical_level0_px.w, level),
+ .height = isl_minify(surf->logical_level0_px.h, level),
+ .depth = 1,
+ .levels = 1,
+ .array_len = 1,
+ .samples = surf->samples,
+ .row_pitch = surf->row_pitch,
+ .usage = usage,
+ .tiling_flags = (1 << surf->tiling));
+ assert(ok);
+}
+
void
isl_tiling_get_intratile_offset_el(enum isl_tiling tiling,
uint32_t bpb,