X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fintel%2Fisl%2Fisl.c;h=f0e948a1c9648eeef88aed1f26f528225c82f211;hb=c1a70165be1e81204033c46dac1d8361366be236;hp=81f40b6a6fb427bcb54609b69c44f14d7d2e1048;hpb=44ac618a4169c3ca35ec70dddac07d3e5346685a;p=mesa.git diff --git a/src/intel/isl/isl.c b/src/intel/isl/isl.c index 81f40b6a6fb..f0e948a1c96 100644 --- a/src/intel/isl/isl.c +++ b/src/intel/isl/isl.c @@ -25,6 +25,8 @@ #include #include +#include "genxml/genX_bits.h" + #include "isl.h" #include "isl_gen4.h" #include "isl_gen6.h" @@ -46,20 +48,6 @@ __isl_finishme(const char *file, int line, const char *fmt, ...) fprintf(stderr, "%s:%d: FINISHME: %s\n", file, line, buf); } -static const struct { - uint8_t size; - uint8_t align; - uint8_t addr_offset; - uint8_t aux_addr_offset; -} ss_infos[] = { - [4] = {24, 32, 4}, - [5] = {24, 32, 4}, - [6] = {24, 32, 4}, - [7] = {32, 32, 4, 24}, - [8] = {64, 64, 32, 40}, - [9] = {64, 64, 32, 40}, -}; - void isl_device_init(struct isl_device *dev, const struct gen_device_info *info, @@ -82,10 +70,44 @@ isl_device_init(struct isl_device *dev, if (info->must_use_separate_stencil) assert(ISL_DEV_USE_SEPARATE_STENCIL(dev)); - dev->ss.size = ss_infos[ISL_DEV_GEN(dev)].size; - dev->ss.align = ss_infos[ISL_DEV_GEN(dev)].align; - dev->ss.addr_offset = ss_infos[ISL_DEV_GEN(dev)].addr_offset; - dev->ss.aux_addr_offset = ss_infos[ISL_DEV_GEN(dev)].aux_addr_offset; + dev->ss.size = RENDER_SURFACE_STATE_length(info) * 4; + dev->ss.align = isl_align(dev->ss.size, 32); + + assert(RENDER_SURFACE_STATE_SurfaceBaseAddress_start(info) % 8 == 0); + dev->ss.addr_offset = + RENDER_SURFACE_STATE_SurfaceBaseAddress_start(info) / 8; + + /* The "Auxiliary Surface Base Address" field starts a bit higher up + * because the bottom 12 bits are used for other things. Round down to + * the nearest dword before. + */ + dev->ss.aux_addr_offset = + (RENDER_SURFACE_STATE_AuxiliarySurfaceBaseAddress_start(info) & ~31) / 8; + + dev->ds.size = _3DSTATE_DEPTH_BUFFER_length(info) * 4; + assert(_3DSTATE_DEPTH_BUFFER_SurfaceBaseAddress_start(info) % 8 == 0); + dev->ds.depth_offset = + _3DSTATE_DEPTH_BUFFER_SurfaceBaseAddress_start(info) / 8; + + if (dev->use_separate_stencil) { + dev->ds.size += _3DSTATE_STENCIL_BUFFER_length(info) * 4 + + _3DSTATE_HIER_DEPTH_BUFFER_length(info) * 4 + + _3DSTATE_CLEAR_PARAMS_length(info) * 4; + + assert(_3DSTATE_STENCIL_BUFFER_SurfaceBaseAddress_start(info) % 8 == 0); + dev->ds.stencil_offset = + _3DSTATE_DEPTH_BUFFER_length(info) * 4 + + _3DSTATE_STENCIL_BUFFER_SurfaceBaseAddress_start(info) / 8; + + assert(_3DSTATE_HIER_DEPTH_BUFFER_SurfaceBaseAddress_start(info) % 8 == 0); + dev->ds.hiz_offset = + _3DSTATE_DEPTH_BUFFER_length(info) * 4 + + _3DSTATE_STENCIL_BUFFER_length(info) * 4 + + _3DSTATE_HIER_DEPTH_BUFFER_SurfaceBaseAddress_start(info) / 8; + } else { + dev->ds.stencil_offset = 0; + dev->ds.hiz_offset = 0; + } } /** @@ -123,9 +145,8 @@ isl_device_get_sample_counts(struct isl_device *dev) /** * @param[out] info is written only on success */ -static bool -isl_tiling_get_info(const struct isl_device *dev, - enum isl_tiling tiling, +static void +isl_tiling_get_info(enum isl_tiling tiling, uint32_t format_bpb, struct isl_tile_info *tile_info) { @@ -140,7 +161,8 @@ isl_tiling_get_info(const struct isl_device *dev, */ assert(tiling == ISL_TILING_X || tiling == ISL_TILING_Y0); assert(bs % 3 == 0 && isl_is_pow2(format_bpb / 3)); - return isl_tiling_get_info(dev, tiling, format_bpb / 3, tile_info); + isl_tiling_get_info(tiling, format_bpb / 3, tile_info); + return; } switch (tiling) { @@ -181,12 +203,6 @@ isl_tiling_get_info(const struct isl_device *dev, case ISL_TILING_Yf: case ISL_TILING_Ys: { - if (ISL_DEV_GEN(dev) < 9) - return false; - - if (!isl_is_pow2(bs)) - return false; - bool is_Ys = tiling == ISL_TILING_Ys; assert(bs > 0); @@ -241,8 +257,6 @@ isl_tiling_get_info(const struct isl_device *dev, .logical_extent_el = logical_el, .phys_extent_B = phys_B, }; - - return true; } /** @@ -274,8 +288,7 @@ isl_surf_choose_tiling(const struct isl_device *dev, if (ISL_DEV_GEN(dev) >= 6) { isl_gen6_filter_tiling(dev, info, &tiling_flags); } else { - isl_finishme("%s: gen%u", __func__, ISL_DEV_GEN(dev)); - isl_gen6_filter_tiling(dev, info, &tiling_flags); + isl_gen4_filter_tiling(dev, info, &tiling_flags); } #define CHOOSE(__tiling) \ @@ -1041,11 +1054,7 @@ isl_calc_linear_min_row_pitch(const struct isl_device *dev, assert(phys_slice0_sa->w % fmtl->bw == 0); - uint32_t min_row_pitch = bs * (phys_slice0_sa->w / fmtl->bw); - min_row_pitch = MAX2(min_row_pitch, info->min_pitch); - min_row_pitch = isl_align_npot(min_row_pitch, alignment); - - return min_row_pitch; + return isl_align_npot(bs * (phys_slice0_sa->w / fmtl->bw), alignment); } static uint32_t @@ -1066,11 +1075,8 @@ isl_calc_tiled_min_row_pitch(const struct isl_device *dev, isl_align_div(total_w_el * tile_el_scale, tile_info->logical_extent_el.width); - uint32_t min_row_pitch = total_w_tl * tile_info->phys_extent_B.width; - min_row_pitch = MAX2(min_row_pitch, surf_info->min_pitch); - min_row_pitch = isl_align_npot(min_row_pitch, alignment); - - return min_row_pitch; + assert(alignment == tile_info->phys_extent_B.width); + return total_w_tl * tile_info->phys_extent_B.width; } static uint32_t @@ -1089,18 +1095,84 @@ isl_calc_min_row_pitch(const struct isl_device *dev, } } -static uint32_t +/** + * Is `pitch` in the valid range for a hardware bitfield, if the bitfield's + * size is `bits` bits? + * + * Hardware pitch fields are offset by 1. For example, if the size of + * RENDER_SURFACE_STATE::SurfacePitch is B bits, then the range of valid + * pitches is [1, 2^b] inclusive. If the surface pitch is N, then + * RENDER_SURFACE_STATE::SurfacePitch must be set to N-1. + */ +static bool +pitch_in_range(uint32_t n, uint32_t bits) +{ + assert(n != 0); + return likely(bits != 0 && 1 <= n && n <= (1 << bits)); +} + +static bool isl_calc_row_pitch(const struct isl_device *dev, const struct isl_surf_init_info *surf_info, const struct isl_tile_info *tile_info, enum isl_dim_layout dim_layout, - const struct isl_extent2d *phys_slice0_sa) + const struct isl_extent2d *phys_slice0_sa, + uint32_t *out_row_pitch) { const uint32_t alignment = isl_calc_row_pitch_alignment(surf_info, tile_info); - return isl_calc_min_row_pitch(dev, surf_info, tile_info, phys_slice0_sa, - alignment); + const uint32_t min_row_pitch = + isl_calc_min_row_pitch(dev, surf_info, tile_info, phys_slice0_sa, + alignment); + + uint32_t row_pitch = min_row_pitch; + + if (surf_info->row_pitch != 0) { + row_pitch = surf_info->row_pitch; + + if (row_pitch < min_row_pitch) + return false; + + if (row_pitch % alignment != 0) + return false; + } + + const uint32_t row_pitch_tiles = row_pitch / tile_info->phys_extent_B.width; + + if (row_pitch == 0) + return false; + + if (dim_layout == ISL_DIM_LAYOUT_GEN9_1D) { + /* SurfacePitch is ignored for this layout. */ + goto done; + } + + if ((surf_info->usage & (ISL_SURF_USAGE_RENDER_TARGET_BIT | + ISL_SURF_USAGE_TEXTURE_BIT | + ISL_SURF_USAGE_STORAGE_BIT)) && + !pitch_in_range(row_pitch, RENDER_SURFACE_STATE_SurfacePitch_bits(dev->info))) + return false; + + if ((surf_info->usage & (ISL_SURF_USAGE_CCS_BIT | + ISL_SURF_USAGE_MCS_BIT)) && + !pitch_in_range(row_pitch_tiles, RENDER_SURFACE_STATE_AuxiliarySurfacePitch_bits(dev->info))) + return false; + + if ((surf_info->usage & ISL_SURF_USAGE_DEPTH_BIT) && + !pitch_in_range(row_pitch, _3DSTATE_DEPTH_BUFFER_SurfacePitch_bits(dev->info))) + return false; + + if ((surf_info->usage & ISL_SURF_USAGE_HIZ_BIT) && + !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"); + + done: + *out_row_pitch = row_pitch; + return true; } /** @@ -1232,8 +1304,7 @@ isl_surf_init_s(const struct isl_device *dev, return false; struct isl_tile_info tile_info; - if (!isl_tiling_get_info(dev, tiling, fmtl->bpb, &tile_info)) - return false; + 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); @@ -1275,8 +1346,10 @@ isl_surf_init_s(const struct isl_device *dev, uint32_t pad_bytes; isl_apply_surface_padding(dev, info, &tile_info, &total_h_el, &pad_bytes); - const uint32_t row_pitch = isl_calc_row_pitch(dev, info, &tile_info, - dim_layout, &phys_slice0_sa); + uint32_t row_pitch; + if (!isl_calc_row_pitch(dev, info, &tile_info, dim_layout, + &phys_slice0_sa, &row_pitch)) + return false; uint32_t size, base_alignment; if (tiling == ISL_TILING_LINEAR) { @@ -1340,12 +1413,11 @@ isl_surf_init_s(const struct isl_device *dev, } void -isl_surf_get_tile_info(const struct isl_device *dev, - const struct isl_surf *surf, +isl_surf_get_tile_info(const struct isl_surf *surf, struct isl_tile_info *tile_info) { const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format); - isl_tiling_get_info(dev, surf->tiling, fmtl->bpb, tile_info); + isl_tiling_get_info(surf->tiling, fmtl->bpb, tile_info); } bool @@ -1626,6 +1698,73 @@ isl_buffer_fill_state_s(const struct isl_device *dev, void *state, } } +void +isl_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch, + const struct isl_depth_stencil_hiz_emit_info *restrict info) +{ + if (info->depth_surf && info->stencil_surf) { + if (!dev->info->has_hiz_and_separate_stencil) { + assert(info->depth_surf == info->stencil_surf); + assert(info->depth_address == info->stencil_address); + } + assert(info->depth_surf->dim == info->stencil_surf->dim); + } + + if (info->depth_surf) { + assert((info->depth_surf->usage & ISL_SURF_USAGE_DEPTH_BIT)); + if (info->depth_surf->dim == ISL_SURF_DIM_3D) { + assert(info->view->base_array_layer + info->view->array_len <= + info->depth_surf->logical_level0_px.depth); + } else { + assert(info->view->base_array_layer + info->view->array_len <= + info->depth_surf->logical_level0_px.array_len); + } + } + + if (info->stencil_surf) { + assert((info->stencil_surf->usage & ISL_SURF_USAGE_STENCIL_BIT)); + if (info->stencil_surf->dim == ISL_SURF_DIM_3D) { + assert(info->view->base_array_layer + info->view->array_len <= + info->stencil_surf->logical_level0_px.depth); + } else { + assert(info->view->base_array_layer + info->view->array_len <= + info->stencil_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_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; + default: + assert(!"Cannot fill surface state for this gen"); + } +} + /** * A variant of isl_surf_get_image_offset_sa() specific to * ISL_DIM_LAYOUT_GEN4_2D. @@ -1679,8 +1818,15 @@ get_image_offset_sa_gen4_3d(const struct isl_surf *surf, uint32_t *y_offset_sa) { assert(level < surf->levels); - assert(logical_z_offset_px < isl_minify(surf->phys_level0_sa.depth, level)); - assert(surf->phys_level0_sa.array_len == 1); + if (surf->dim == ISL_SURF_DIM_3D) { + assert(surf->phys_level0_sa.array_len == 1); + assert(logical_z_offset_px < isl_minify(surf->phys_level0_sa.depth, level)); + } else { + assert(surf->dim == ISL_SURF_DIM_2D); + assert(surf->usage & ISL_SURF_USAGE_CUBE_BIT); + assert(surf->phys_level0_sa.array_len == 6); + assert(logical_z_offset_px < surf->phys_level0_sa.array_len); + } const struct isl_extent3d image_align_sa = isl_surf_get_image_alignment_sa(surf); @@ -1688,13 +1834,16 @@ get_image_offset_sa_gen4_3d(const struct isl_surf *surf, const uint32_t W0 = surf->phys_level0_sa.width; const uint32_t H0 = surf->phys_level0_sa.height; const uint32_t D0 = surf->phys_level0_sa.depth; + const uint32_t AL = surf->phys_level0_sa.array_len; uint32_t x = 0; uint32_t y = 0; for (uint32_t l = 0; l < level; ++l) { const uint32_t level_h = isl_align_npot(isl_minify(H0, l), image_align_sa.h); - const uint32_t level_d = isl_align_npot(isl_minify(D0, l), image_align_sa.d); + const uint32_t level_d = + isl_align_npot(surf->dim == ISL_SURF_DIM_3D ? isl_minify(D0, l) : AL, + image_align_sa.d); const uint32_t max_layers_vert = isl_align(level_d, 1u << l) / (1u << l); y += level_h * max_layers_vert; @@ -1702,7 +1851,9 @@ get_image_offset_sa_gen4_3d(const struct isl_surf *surf, const uint32_t level_w = isl_align_npot(isl_minify(W0, level), image_align_sa.w); const uint32_t level_h = isl_align_npot(isl_minify(H0, level), image_align_sa.h); - const uint32_t level_d = isl_align_npot(isl_minify(D0, level), image_align_sa.d); + const uint32_t level_d = + isl_align_npot(surf->dim == ISL_SURF_DIM_3D ? isl_minify(D0, level) : AL, + image_align_sa.d); const uint32_t max_layers_horiz = MIN(level_d, 1u << level); @@ -1778,7 +1929,8 @@ isl_surf_get_image_offset_sa(const struct isl_surf *surf, x_offset_sa, y_offset_sa); break; case ISL_DIM_LAYOUT_GEN4_3D: - get_image_offset_sa_gen4_3d(surf, level, logical_z_offset_px, + get_image_offset_sa_gen4_3d(surf, level, logical_array_layer + + logical_z_offset_px, x_offset_sa, y_offset_sa); break; @@ -1814,8 +1966,7 @@ isl_surf_get_image_offset_el(const struct isl_surf *surf, } void -isl_tiling_get_intratile_offset_el(const struct isl_device *dev, - enum isl_tiling tiling, +isl_tiling_get_intratile_offset_el(enum isl_tiling tiling, uint8_t bs, uint32_t row_pitch, uint32_t total_x_offset_el, @@ -1835,7 +1986,7 @@ isl_tiling_get_intratile_offset_el(const struct isl_device *dev, const uint32_t bpb = bs * 8; struct isl_tile_info tile_info; - isl_tiling_get_info(dev, tiling, bpb, &tile_info); + isl_tiling_get_info(tiling, bpb, &tile_info); assert(row_pitch % tile_info.phys_extent_B.width == 0);