diff --git a/src/nouveau/compiler/meson.build b/src/nouveau/compiler/meson.build index 8634810ac6a..627eee66309 100644 --- a/src/nouveau/compiler/meson.build +++ b/src/nouveau/compiler/meson.build @@ -51,6 +51,10 @@ _libbitview_rs = static_library( rust_args : nak_rust_args, ) +idep_bitview_rs = declare_dependency( + link_with : _libbitview_rs, +) + libnak_deps = [ idep_mesautil, idep_nir_headers, diff --git a/src/nouveau/nil/format.rs b/src/nouveau/nil/format.rs index a208ac2dd04..0cbe38480e5 100644 --- a/src/nouveau/nil/format.rs +++ b/src/nouveau/nil/format.rs @@ -55,14 +55,18 @@ impl Format { } } - fn info(&self) -> &nil_format_info { + pub(crate) fn info(&self) -> &nil_format_info { unsafe { &nil_format_table[self.p_format as usize] } } - pub fn is_integer(&self) -> bool { + pub(crate) fn is_integer(&self) -> bool { unsafe { util_format_is_pure_integer((*self).into()) } } + pub(crate) fn is_srgb(&self) -> bool { + self.description().colorspace == UTIL_FORMAT_COLORSPACE_SRGB + } + pub fn supports_texturing(&self, dev: &nv_device_info) -> bool { if self.info().support() & NIL_FORMAT_SUPPORTS_TEXTURE_BIT == 0 { return false; @@ -83,7 +87,7 @@ impl Format { self.supports_texturing(dev) && !self.is_integer() } - pub fn supports_buffer(&self, _dev: &nv_device_info) -> bool { + pub fn supports_buffer(&self) -> bool { self.info().support() & NIL_FORMAT_SUPPORTS_BUFFER_BIT != 0 } @@ -128,10 +132,10 @@ pub extern "C" fn nil_format_supports_filtering( #[no_mangle] pub extern "C" fn nil_format_supports_buffer( - dev: &nv_device_info, + _dev: &nv_device_info, p_format: pipe_format, ) -> bool { - Format::try_from(p_format).is_ok_and(|f| f.supports_buffer(dev)) + Format::try_from(p_format).is_ok_and(|f| f.supports_buffer()) } #[no_mangle] diff --git a/src/nouveau/nil/lib.rs b/src/nouveau/nil/lib.rs index 8c41f7de7b3..a94465d8805 100644 --- a/src/nouveau/nil/lib.rs +++ b/src/nouveau/nil/lib.rs @@ -7,6 +7,7 @@ extern crate nvidia_headers; mod extent; mod format; mod image; +mod tic; mod tiling; pub trait ILog2Ceil { diff --git a/src/nouveau/nil/meson.build b/src/nouveau/nil/meson.build index 0f20d6400bb..ddd980c31ee 100644 --- a/src/nouveau/nil/meson.build +++ b/src/nouveau/nil/meson.build @@ -14,9 +14,14 @@ endif prog_cbindgen = find_program('cbindgen', required : false, native : true) +dep_paste = dependency('paste', + version : '>= 1.0.14', + fallback : ['paste', 'dep_paste'], + required : true, +) + libnil_files = files( 'nil.h', - 'nil_image_tic.c', ) nil_format_table = custom_target( @@ -40,10 +45,13 @@ _libnil_rs_files = files( 'extent.rs', 'format.rs', 'image.rs', + 'tic.rs', 'tiling.rs', ) _libnil_rs_deps = [ + dep_paste, + idep_bitview_rs, idep_nvidia_headers_rs, ] diff --git a/src/nouveau/nil/nil.h b/src/nouveau/nil/nil.h index 71a376a92d7..c304d28db6f 100644 --- a/src/nouveau/nil/nil.h +++ b/src/nouveau/nil/nil.h @@ -14,64 +14,4 @@ #include "nil_rs.h" -struct nv_device_info; - -enum ENUM_PACKED nil_view_type { - NIL_VIEW_TYPE_1D, - NIL_VIEW_TYPE_2D, - NIL_VIEW_TYPE_3D, - NIL_VIEW_TYPE_3D_SLICED, - NIL_VIEW_TYPE_CUBE, - NIL_VIEW_TYPE_1D_ARRAY, - NIL_VIEW_TYPE_2D_ARRAY, - NIL_VIEW_TYPE_CUBE_ARRAY, -}; - -struct nil_view { - enum nil_view_type type; - - /** - * The format to use in the view - * - * This may differ from the format of the actual isl_surf but must have - * the same block size. - */ - enum pipe_format format; - - uint32_t base_level; - uint32_t num_levels; - - /** - * Base array layer - * - * For cube maps, both base_array_layer and array_len should be - * specified in terms of 2-D layers and must be a multiple of 6. - */ - uint32_t base_array_layer; - - /** - * Array Length - * - * Indicates the number of array elements starting at Base Array Layer. - */ - uint32_t array_len; - - enum pipe_swizzle swizzle[4]; - - /* VK_EXT_image_view_min_lod */ - float min_lod_clamp; -}; - -void nil_image_fill_tic(struct nv_device_info *dev, - const struct nil_image *image, - const struct nil_view *view, - uint64_t base_address, - void *desc_out); - -void nil_buffer_fill_tic(struct nv_device_info *dev, - uint64_t base_address, - enum pipe_format format, - uint32_t num_elements, - void *desc_out); - #endif /* NIL_H */ diff --git a/src/nouveau/nil/nil_image_tic.c b/src/nouveau/nil/nil_image_tic.c deleted file mode 100644 index af52dbd5f84..00000000000 --- a/src/nouveau/nil/nil_image_tic.c +++ /dev/null @@ -1,620 +0,0 @@ -/* - * Copyright © 2022 Collabora Ltd. - * SPDX-License-Identifier: MIT - */ -#include "nil.h" - -#include "nil_format_table.h" -#include "util/bitpack_helpers.h" - -#include "nouveau_device.h" - -#include "cl9097.h" -#include "cl9097tex.h" -#include "clb097.h" -#include "clb097tex.h" -#include "clc097.h" -#include "clc097tex.h" -#include "drf.h" - -ALWAYS_INLINE static void -__set_u32(uint32_t *o, uint32_t v, unsigned lo, unsigned hi) -{ - assert(lo <= hi && (lo / 32) == (hi / 32)); - o[lo / 32] |= util_bitpack_uint(v, lo % 32, hi % 32); -} - -#define FIXED_FRAC_BITS 8 - -ALWAYS_INLINE static void -__set_ufixed(uint32_t *o, float v, unsigned lo, unsigned hi) -{ - assert(lo <= hi && (lo / 32) == (hi / 32)); - o[lo / 32] |= util_bitpack_ufixed_clamp(v, lo % 32, hi % 32, - FIXED_FRAC_BITS); -} - -ALWAYS_INLINE static void -__set_i32(uint32_t *o, int32_t v, unsigned lo, unsigned hi) -{ - assert(lo <= hi && (lo / 32) == (hi / 32)); - o[lo / 32] |= util_bitpack_sint(v, lo % 32, hi % 32); -} - -ALWAYS_INLINE static void -__set_bool(uint32_t *o, bool b, unsigned lo, unsigned hi) -{ - assert(lo == hi); - o[lo / 32] |= util_bitpack_uint(b, lo % 32, hi % 32); -} - -#define MW(x) x - -#define TH_SET_U(o, NV, VER, FIELD, val) \ - __set_u32((o), (val), DRF_LO(NV##_TEXHEAD##VER##_##FIELD),\ - DRF_HI(NV##_TEXHEAD##VER##_##FIELD)) - -#define TH_SET_UF(o, NV, VER, FIELD, val) \ - __set_ufixed((o), (val), DRF_LO(NV##_TEXHEAD##VER##_##FIELD),\ - DRF_HI(NV##_TEXHEAD##VER##_##FIELD)) - -#define TH_SET_I(o, NV, VER, FIELD, val) \ - __set_i32((o), (val), DRF_LO(NV##_TEXHEAD##VER##_##FIELD),\ - DRF_HI(NV##_TEXHEAD##VER##_##FIELD)) - -#define TH_SET_B(o, NV, VER, FIELD, b) \ - __set_bool((o), (b), DRF_LO(NV##_TEXHEAD##VER##_##FIELD),\ - DRF_HI(NV##_TEXHEAD##VER##_##FIELD)) - -#define TH_SET_E(o, NV, VER, FIELD, E) \ - TH_SET_U((o), NV, VER, FIELD, NV##_TEXHEAD##VER##_##FIELD##_##E) - -#define TH_NV9097_SET_U(o, IDX, FIELD, val) \ - TH_SET_U(&(o)[IDX], NV9097, V2_##IDX, FIELD, (val)); -#define TH_NV9097_SET_UF(o, IDX, FIELD, val) \ - TH_SET_UF(&(o)[IDX], NV9097, V2_##IDX, FIELD, (val)); -#define TH_NV9097_SET_I(o, IDX, FIELD, val) \ - TH_SET_I(&(o)[IDX], NV9097, V2_##IDX, FIELD, (val)); -#define TH_NV9097_SET_B(o, IDX, FIELD, b) \ - TH_SET_B(&(o)[IDX], NV9097, V2_##IDX, FIELD, (b)); -#define TH_NV9097_SET_E(o, IDX, FIELD, E) \ - TH_SET_E(&(o)[IDX], NV9097, V2_##IDX, FIELD, E); - -#define TH_NVB097_SET_U(o, VER, FIELD, val) \ - TH_SET_U((o), NVB097, _##VER, FIELD, (val)); -#define TH_NVB097_SET_UF(o, VER, FIELD, val) \ - TH_SET_UF((o), NVB097, _##VER, FIELD, (val)); -#define TH_NVB097_SET_I(o, VER, FIELD, val) \ - TH_SET_I((o), NVB097, _##VER, FIELD, (val)); -#define TH_NVB097_SET_B(o, VER, FIELD, b) \ - TH_SET_B((o), NVB097, _##VER, FIELD, (b)); -#define TH_NVB097_SET_E(o, VER, FIELD, E) \ - TH_SET_E((o), NVB097, _##VER, FIELD, E); - -#define TH_NVC097_SET_U(o, VER, FIELD, val) \ - TH_SET_U((o), NVC097, _##VER, FIELD, (val)); - -static const struct nil_tic_format * -nil_tic_format_for_pipe(enum pipe_format format) -{ - assert(format < PIPE_FORMAT_COUNT); - const struct nil_format_info *fmt = &nil_format_table[format]; - return fmt->tic.comp_sizes == 0 ? NULL : &fmt->tic; -} - -static inline uint32_t -nv9097_th_bl_source(const struct nil_tic_format *fmt, - enum pipe_swizzle swz, bool is_int) -{ - switch (swz) { - case PIPE_SWIZZLE_X: return fmt->src_x; - case PIPE_SWIZZLE_Y: return fmt->src_y; - case PIPE_SWIZZLE_Z: return fmt->src_z; - case PIPE_SWIZZLE_W: return fmt->src_w; - case PIPE_SWIZZLE_0: - return NV9097_TEXHEADV2_0_X_SOURCE_IN_ZERO; - case PIPE_SWIZZLE_1: - return is_int ? NV9097_TEXHEADV2_0_X_SOURCE_IN_ONE_INT : - NV9097_TEXHEADV2_0_X_SOURCE_IN_ONE_FLOAT; - default: - unreachable("Invalid component swizzle"); - } -} - -static inline uint32_t -nvb097_th_bl_source(const struct nil_tic_format *fmt, - enum pipe_swizzle swz, bool is_int) -{ - switch (swz) { - case PIPE_SWIZZLE_X: return fmt->src_x; - case PIPE_SWIZZLE_Y: return fmt->src_y; - case PIPE_SWIZZLE_Z: return fmt->src_z; - case PIPE_SWIZZLE_W: return fmt->src_w; - case PIPE_SWIZZLE_0: - return NVB097_TEXHEAD_BL_X_SOURCE_IN_ZERO; - case PIPE_SWIZZLE_1: - return is_int ? NVB097_TEXHEAD_BL_X_SOURCE_IN_ONE_INT : - NVB097_TEXHEAD_BL_X_SOURCE_IN_ONE_FLOAT; - default: - unreachable("Invalid component swizzle"); - } -} - -static uint32_t -nv9097_th_bl_0(enum pipe_format format, const enum pipe_swizzle swizzle[4]) -{ - const struct nil_tic_format *fmt = nil_tic_format_for_pipe(format); - const bool is_int = util_format_is_pure_integer(format); - - uint32_t source[4]; - for (unsigned i = 0; i < 4; i++) - source[i] = nvb097_th_bl_source(fmt, swizzle[i], is_int); - - uint32_t th_0 = 0; - TH_NV9097_SET_U(&th_0, 0, COMPONENT_SIZES, fmt->comp_sizes); - TH_NV9097_SET_U(&th_0, 0, R_DATA_TYPE, fmt->type_r); - TH_NV9097_SET_U(&th_0, 0, G_DATA_TYPE, fmt->type_g); - TH_NV9097_SET_U(&th_0, 0, B_DATA_TYPE, fmt->type_b); - TH_NV9097_SET_U(&th_0, 0, A_DATA_TYPE, fmt->type_a); - TH_NV9097_SET_U(&th_0, 0, X_SOURCE, source[0]); - TH_NV9097_SET_U(&th_0, 0, Y_SOURCE, source[1]); - TH_NV9097_SET_U(&th_0, 0, Z_SOURCE, source[2]); - TH_NV9097_SET_U(&th_0, 0, W_SOURCE, source[3]); - - return th_0; -} - -static uint32_t -nvb097_th_bl_0(enum pipe_format format, const enum pipe_swizzle swizzle[4]) -{ - const struct nil_tic_format *fmt = nil_tic_format_for_pipe(format); - const bool is_int = util_format_is_pure_integer(format); - - uint32_t source[4]; - for (unsigned i = 0; i < 4; i++) - source[i] = nvb097_th_bl_source(fmt, swizzle[i], is_int); - - uint32_t th_0 = 0; - TH_NVB097_SET_U(&th_0, BL, COMPONENTS, fmt->comp_sizes); - TH_NVB097_SET_U(&th_0, BL, R_DATA_TYPE, fmt->type_r); - TH_NVB097_SET_U(&th_0, BL, G_DATA_TYPE, fmt->type_g); - TH_NVB097_SET_U(&th_0, BL, B_DATA_TYPE, fmt->type_b); - TH_NVB097_SET_U(&th_0, BL, A_DATA_TYPE, fmt->type_a); - TH_NVB097_SET_U(&th_0, BL, X_SOURCE, source[0]); - TH_NVB097_SET_U(&th_0, BL, Y_SOURCE, source[1]); - TH_NVB097_SET_U(&th_0, BL, Z_SOURCE, source[2]); - TH_NVB097_SET_U(&th_0, BL, W_SOURCE, source[3]); - - return th_0; -} - -static uint32_t -pipe_to_nv_texture_type(enum nil_view_type type) -{ -#define CASE(NIL, NV) \ - case NIL_VIEW_TYPE_##NIL: return NVB097_TEXHEAD_BL_TEXTURE_TYPE_##NV; \ - STATIC_ASSERT(NVB097_TEXHEAD_BL_TEXTURE_TYPE_##NV == NV9097_TEXHEADV2_2_TEXTURE_TYPE_##NV); - - switch (type) { - CASE(1D, ONE_D); - CASE(2D, TWO_D); - CASE(3D, THREE_D); - CASE(3D_SLICED, THREE_D); - CASE(CUBE, CUBEMAP); - CASE(1D_ARRAY, ONE_D_ARRAY); - CASE(2D_ARRAY, TWO_D_ARRAY); - CASE(CUBE_ARRAY, CUBEMAP_ARRAY); - default: unreachable("Invalid image view type"); - } - -#undef CASE -} - -static uint32_t -nil_to_nv9097_multi_sample_count(enum nil_sample_layout sample_layout) -{ -#define CASE(SIZE) \ - case NIL_SAMPLE_LAYOUT_##SIZE: \ - return NV9097_TEXHEADV2_7_MULTI_SAMPLE_COUNT_MODE_##SIZE - - switch (sample_layout) { - CASE(1X1); - CASE(2X1); - CASE(2X2); - CASE(4X2); - CASE(4X4); - default: - unreachable("Invalid sample layout"); - } - -#undef CASE -} - -static uint32_t -nil_to_nvb097_multi_sample_count(enum nil_sample_layout sample_layout) -{ -#define CASE(SIZE) \ - case NIL_SAMPLE_LAYOUT_##SIZE: \ - return NVB097_TEXHEAD_BL_MULTI_SAMPLE_COUNT_MODE_##SIZE - - switch (sample_layout) { - CASE(1X1); - CASE(2X1); - CASE(2X2); - CASE(4X2); - CASE(4X4); - default: - unreachable("Invalid sample layout"); - } - -#undef CASE -} - -static inline uint32_t -nil_max_mip_level(const struct nil_image *image, - const struct nil_view *view) -{ - if (view->type != NIL_VIEW_TYPE_3D && view->array_len == 1 && - view->base_level == 0 && view->num_levels == 1) { - /* The Unnormalized coordinates bit in the sampler gets ignored if the - * referenced image has more than one miplevel. Fortunately, Vulkan has - * restrictions requiring the view to be a single-layer single-LOD view - * in order to use nonnormalizedCoordinates = VK_TRUE in the sampler. - * From the Vulkan 1.3.255 spec: - * - * "When unnormalizedCoordinates is VK_TRUE, images the sampler is - * used with in the shader have the following requirements: - * - * - The viewType must be either VK_IMAGE_VIEW_TYPE_1D or - * VK_IMAGE_VIEW_TYPE_2D. - * - The image view must have a single layer and a single mip - * level." - * - * Under these conditions, the view is simply LOD 0 of a single array - * slice so we don't need to care about aray stride between slices so - * it's safe to set the number of miplevels to 0 regardless of how many - * the image actually has. - */ - return 0; - } else { - return image->num_levels - 1; - } -} - -static struct nil_extent4d -nil_normalize_extent(const struct nil_image *image, - const struct nil_view *view) -{ - struct nil_extent4d extent; - - extent.width = image->extent_px.width; - extent.height = image->extent_px.height; - extent.array_len = 0; - - switch (view->type) { - case NIL_VIEW_TYPE_1D: - case NIL_VIEW_TYPE_1D_ARRAY: - case NIL_VIEW_TYPE_2D: - case NIL_VIEW_TYPE_2D_ARRAY: - assert(image->extent_px.depth == 1); - extent.depth = view->array_len; - break; - case NIL_VIEW_TYPE_CUBE: - case NIL_VIEW_TYPE_CUBE_ARRAY: - assert(image->dim == NIL_IMAGE_DIM_2D); - assert(view->array_len % 6 == 0); - extent.depth = view->array_len / 6; - break; - case NIL_VIEW_TYPE_3D: - assert(image->dim == NIL_IMAGE_DIM_3D); - extent.depth = image->extent_px.depth; - break; - case NIL_VIEW_TYPE_3D_SLICED: - assert(image->dim == NIL_IMAGE_DIM_3D); - extent.depth = view->array_len; - break; - default: - unreachable("Unsupported image view target"); - }; - - return extent; -} - -static void -nv9097_nil_image_fill_tic(const struct nil_image *image, - const struct nil_view *view, - uint64_t base_address, - void *desc_out) -{ - assert(util_format_get_blocksize(image->format.p_format) == - util_format_get_blocksize(view->format)); - assert(view->base_level + view->num_levels <= image->num_levels); - assert(view->base_array_layer + view->array_len <= - image->extent_px.array_len); - - uint32_t th[8] = { }; - - TH_NV9097_SET_B(th, 4, USE_TEXTURE_HEADER_VERSION2, true); - - th[0] = nv9097_th_bl_0(view->format, view->swizzle); - - /* There's no base layer field in the texture header */ - const uint64_t layer_address = - base_address + view->base_array_layer * image->array_stride_B; - TH_NV9097_SET_U(th, 1, OFFSET_LOWER, layer_address & 0xffffffff); - TH_NV9097_SET_U(th, 2, OFFSET_UPPER, layer_address >> 32); - - const struct nil_tiling *tiling = &image->levels[0].tiling; - if (tiling->is_tiled) { - TH_NV9097_SET_E(th, 2, MEMORY_LAYOUT, BLOCKLINEAR); - - assert(tiling->gob_height_is_8); - assert(tiling->x_log2 == 0); - TH_NV9097_SET_E(th, 2, GOBS_PER_BLOCK_WIDTH, ONE_GOB); - TH_NV9097_SET_U(th, 2, GOBS_PER_BLOCK_HEIGHT, tiling->y_log2); - TH_NV9097_SET_U(th, 2, GOBS_PER_BLOCK_DEPTH, tiling->z_log2); - - TH_NV9097_SET_U(th, 2, TEXTURE_TYPE, pipe_to_nv_texture_type(view->type)); - } else { - TH_NV9097_SET_E(th, 2, MEMORY_LAYOUT, PITCH); - - uint32_t pitch = image->levels[0].row_stride_B; - TH_NV9097_SET_U(th, 3, PITCH, pitch); - - assert(view->type == NIL_VIEW_TYPE_2D || - view->type == NIL_VIEW_TYPE_2D_ARRAY); - assert(image->sample_layout == NIL_SAMPLE_LAYOUT_1X1); - assert(view->num_levels == 1); - TH_NV9097_SET_E(th, 2, TEXTURE_TYPE, TWO_D_NO_MIPMAP); - } - - TH_NV9097_SET_E(th, 3, LOD_ANISO_QUALITY, LOD_QUALITY_HIGH); - TH_NV9097_SET_E(th, 3, LOD_ISO_QUALITY, LOD_QUALITY_HIGH); - TH_NV9097_SET_E(th, 3, ANISO_COARSE_SPREAD_MODIFIER, SPREAD_MODIFIER_NONE); - - const struct nil_extent4d extent = nil_normalize_extent(image, view); - TH_NV9097_SET_U(th, 4, WIDTH, extent.width); - TH_NV9097_SET_U(th, 5, HEIGHT, extent.height); - TH_NV9097_SET_U(th, 5, DEPTH, extent.depth); - - TH_NV9097_SET_U(th, 5, MAX_MIP_LEVEL, nil_max_mip_level(image, view)); - - TH_NV9097_SET_B(th, 2, S_R_G_B_CONVERSION, - util_format_is_srgb(view->format)); - - TH_NV9097_SET_E(th, 2, BORDER_SOURCE, BORDER_COLOR); - - /* In the sampler, the two options for FLOAT_COORD_NORMALIZATION are: - * - * - FORCE_UNNORMALIZED_COORDS - * - USE_HEADER_SETTING - * - * So we set it to normalized in the header and let the sampler select - * that or force non-normalized. - */ - TH_NV9097_SET_B(th, 2, NORMALIZED_COORDS, true); - - TH_NV9097_SET_E(th, 6, ANISO_FINE_SPREAD_FUNC, SPREAD_FUNC_TWO); - TH_NV9097_SET_E(th, 6, ANISO_COARSE_SPREAD_FUNC, SPREAD_FUNC_ONE); - - TH_NV9097_SET_U(th, 7, RES_VIEW_MIN_MIP_LEVEL, view->base_level); - TH_NV9097_SET_U(th, 7, RES_VIEW_MAX_MIP_LEVEL, - view->num_levels + view->base_level - 1); - - TH_NV9097_SET_U(th, 7, MULTI_SAMPLE_COUNT, - nil_to_nv9097_multi_sample_count(image->sample_layout)); - - TH_NV9097_SET_UF(th, 7, MIN_LOD_CLAMP, - view->min_lod_clamp - view->base_level); - - memcpy(desc_out, th, sizeof(th)); -} - -static void -nvb097_nil_image_fill_tic(struct nv_device_info *dev, - const struct nil_image *image, - const struct nil_view *view, - uint64_t base_address, - void *desc_out) -{ - assert(util_format_get_blocksize(image->format.p_format) == - util_format_get_blocksize(view->format)); - assert(view->base_level + view->num_levels <= image->num_levels); - - uint32_t th[8] = { }; - - th[0] = nvb097_th_bl_0(view->format, view->swizzle); - - const struct nil_tiling *tiling = &image->levels[0].tiling; - - /* There's no base layer field in the texture header */ - uint64_t layer_address = base_address; - if (view->type == NIL_VIEW_TYPE_3D_SLICED) { - assert(image->num_levels == 1); - assert(view->base_array_layer + view->array_len <= - image->extent_px.depth); - layer_address += nil_image_level_z_offset_B(image, view->base_level, - view->base_array_layer); - } else { - assert(view->base_array_layer + view->array_len <= - image->extent_px.array_len); - layer_address += view->base_array_layer * image->array_stride_B; - } - - if (tiling->is_tiled) { - TH_NVB097_SET_E(th, BL, HEADER_VERSION, SELECT_BLOCKLINEAR); - - assert((layer_address & BITFIELD_MASK(9)) == 0); - TH_NVB097_SET_U(th, BL, ADDRESS_BITS31TO9, (uint32_t)layer_address >> 9); - TH_NVB097_SET_U(th, BL, ADDRESS_BITS47TO32, layer_address >> 32); - - assert(tiling->gob_height_is_8); - TH_NVB097_SET_E(th, BL, GOBS_PER_BLOCK_WIDTH, ONE_GOB); - TH_NVB097_SET_U(th, BL, GOBS_PER_BLOCK_HEIGHT, tiling->y_log2); - TH_NVB097_SET_U(th, BL, GOBS_PER_BLOCK_DEPTH, tiling->z_log2); - TH_NVB097_SET_U(th, BL, TILE_WIDTH_IN_GOBS, tiling->x_log2); - - TH_NVB097_SET_U(th, BL, TEXTURE_TYPE, pipe_to_nv_texture_type(view->type)); - } else { - TH_NVB097_SET_E(th, PITCH, HEADER_VERSION, SELECT_PITCH); - - assert((layer_address & BITFIELD_MASK(5)) == 0); - TH_NVB097_SET_U(th, PITCH, ADDRESS_BITS31TO5, - (uint32_t)layer_address >> 5); - TH_NVB097_SET_U(th, PITCH, ADDRESS_BITS47TO32, - layer_address >> 32); - - uint32_t pitch = image->levels[0].row_stride_B; - assert((pitch & BITFIELD_MASK(5)) == 0); - TH_NVB097_SET_U(th, PITCH, PITCH_BITS20TO5, pitch >> 5); - - assert(view->type == NIL_VIEW_TYPE_2D || - view->type == NIL_VIEW_TYPE_2D_ARRAY); - assert(image->sample_layout == NIL_SAMPLE_LAYOUT_1X1); - assert(view->num_levels == 1); - TH_NVB097_SET_E(th, PITCH, TEXTURE_TYPE, TWO_D_NO_MIPMAP); - } - - TH_NVB097_SET_B(th, BL, LOD_ANISO_QUALITY2, true); - TH_NVB097_SET_E(th, BL, LOD_ANISO_QUALITY, LOD_QUALITY_HIGH); - TH_NVB097_SET_E(th, BL, LOD_ISO_QUALITY, LOD_QUALITY_HIGH); - TH_NVB097_SET_E(th, BL, ANISO_COARSE_SPREAD_MODIFIER, SPREAD_MODIFIER_NONE); - - const struct nil_extent4d extent = nil_normalize_extent(image, view); - TH_NVB097_SET_U(th, BL, WIDTH_MINUS_ONE, extent.width - 1); - if (dev->cls_eng3d >= PASCAL_A) { - const uint32_t height_1 = extent.height - 1; - const uint32_t depth_1 = extent.depth - 1; - TH_NVC097_SET_U(th, BL, HEIGHT_MINUS_ONE, height_1 & BITFIELD_MASK(16)); - TH_NVC097_SET_U(th, BL, HEIGHT_MINUS_ONE_BIT16, height_1 >> 16); - TH_NVC097_SET_U(th, BL, DEPTH_MINUS_ONE, depth_1 & BITFIELD_MASK(14)); - TH_NVC097_SET_U(th, BL, DEPTH_MINUS_ONE_BIT14, depth_1 >> 14); - } else { - TH_NVB097_SET_U(th, BL, HEIGHT_MINUS_ONE, extent.height - 1); - TH_NVB097_SET_U(th, BL, DEPTH_MINUS_ONE, extent.depth - 1); - } - - TH_NVB097_SET_U(th, BL, MAX_MIP_LEVEL, nil_max_mip_level(image, view)); - - TH_NVB097_SET_B(th, BL, S_R_G_B_CONVERSION, - util_format_is_srgb(view->format)); - - TH_NVB097_SET_E(th, BL, SECTOR_PROMOTION, PROMOTE_TO_2_V); - TH_NVB097_SET_E(th, BL, BORDER_SIZE, BORDER_SAMPLER_COLOR); - - /* In the sampler, the two options for FLOAT_COORD_NORMALIZATION are: - * - * - FORCE_UNNORMALIZED_COORDS - * - USE_HEADER_SETTING - * - * So we set it to normalized in the header and let the sampler select - * that or force non-normalized. - */ - TH_NVB097_SET_B(th, BL, NORMALIZED_COORDS, true); - - TH_NVB097_SET_E(th, BL, ANISO_FINE_SPREAD_FUNC, SPREAD_FUNC_TWO); - TH_NVB097_SET_E(th, BL, ANISO_COARSE_SPREAD_FUNC, SPREAD_FUNC_ONE); - - TH_NVB097_SET_U(th, BL, RES_VIEW_MIN_MIP_LEVEL, view->base_level); - TH_NVB097_SET_U(th, BL, RES_VIEW_MAX_MIP_LEVEL, - view->num_levels + view->base_level - 1); - - TH_NVB097_SET_U(th, BL, MULTI_SAMPLE_COUNT, - nil_to_nvb097_multi_sample_count(image->sample_layout)); - - TH_NVB097_SET_UF(th, BL, MIN_LOD_CLAMP, - view->min_lod_clamp - view->base_level); - - memcpy(desc_out, th, sizeof(th)); -} - -static const enum pipe_swizzle IDENTITY_SWIZZLE[4] = { - PIPE_SWIZZLE_X, - PIPE_SWIZZLE_Y, - PIPE_SWIZZLE_Z, - PIPE_SWIZZLE_W, -}; - -static void -nv9097_nil_buffer_fill_tic(uint64_t base_address, - enum pipe_format format, - uint32_t num_elements, - void *desc_out) -{ - uint32_t th[8] = { }; - - TH_NV9097_SET_B(th, 4, USE_TEXTURE_HEADER_VERSION2, true); - - assert(!util_format_is_compressed(format)); - th[0] = nv9097_th_bl_0(format, IDENTITY_SWIZZLE); - - TH_NV9097_SET_U(th, 1, OFFSET_LOWER, base_address); - TH_NV9097_SET_U(th, 2, OFFSET_UPPER, base_address >> 32); - TH_NV9097_SET_E(th, 2, MEMORY_LAYOUT, PITCH); - - TH_NV9097_SET_U(th, 4, WIDTH, num_elements); - TH_NV9097_SET_E(th, 2, TEXTURE_TYPE, ONE_D_BUFFER); - - - memcpy(desc_out, th, sizeof(th)); -} - -static void -nvb097_nil_buffer_fill_tic(uint64_t base_address, - enum pipe_format format, - uint32_t num_elements, - void *desc_out) -{ - uint32_t th[8] = { }; - - assert(!util_format_is_compressed(format)); - th[0] = nvb097_th_bl_0(format, IDENTITY_SWIZZLE); - - TH_NVB097_SET_U(th, 1D, ADDRESS_BITS31TO0, base_address); - TH_NVB097_SET_U(th, 1D, ADDRESS_BITS47TO32, base_address >> 32); - TH_NVB097_SET_E(th, 1D, HEADER_VERSION, SELECT_ONE_D_BUFFER); - - TH_NVB097_SET_U(th, 1D, WIDTH_MINUS_ONE_BITS15TO0, - (num_elements - 1) & 0xffff); - TH_NVB097_SET_U(th, 1D, WIDTH_MINUS_ONE_BITS31TO16, - (num_elements - 1) >> 16); - - TH_NVB097_SET_E(th, 1D, TEXTURE_TYPE, ONE_D_BUFFER); - - /* TODO: Do we need this? */ - TH_NVB097_SET_E(th, 1D, SECTOR_PROMOTION, PROMOTE_TO_2_V); - - memcpy(desc_out, th, sizeof(th)); -} - -void -nil_image_fill_tic(struct nv_device_info *dev, - const struct nil_image *image, - const struct nil_view *view, - uint64_t base_address, - void *desc_out) -{ - if (dev->cls_eng3d >= MAXWELL_A) { - nvb097_nil_image_fill_tic(dev, image, view, base_address, desc_out); - } else if (dev->cls_eng3d >= FERMI_A) { - nv9097_nil_image_fill_tic(image, view, base_address, desc_out); - } else { - unreachable("Tesla and older not supported"); - } -} - -void -nil_buffer_fill_tic(struct nv_device_info *dev, - uint64_t base_address, - enum pipe_format format, - uint32_t num_elements, - void *desc_out) -{ - if (dev->cls_eng3d >= MAXWELL_A) { - nvb097_nil_buffer_fill_tic(base_address, format, num_elements, desc_out); - } else if (dev->cls_eng3d >= FERMI_A) { - nv9097_nil_buffer_fill_tic(base_address, format, num_elements, desc_out); - } else { - unreachable("Tesla and older not supported"); - } -} diff --git a/src/nouveau/nil/tic.rs b/src/nouveau/nil/tic.rs new file mode 100644 index 00000000000..f7400ddc16b --- /dev/null +++ b/src/nouveau/nil/tic.rs @@ -0,0 +1,633 @@ +// Copyright © 2024 Collabora, Ltd. +// SPDX-License-Identifier: MIT + +#![allow(unused_macros)] + +extern crate bitview; +extern crate nvidia_headers; + +use bitview::*; +use nil_rs_bindings::*; +use nvidia_headers::cl9097::tex as cl9097; +use nvidia_headers::cl9097::FERMI_A; +use nvidia_headers::clb097::tex as clb097; +use nvidia_headers::clb097::MAXWELL_A; +use nvidia_headers::clc097::tex as clc097; +use nvidia_headers::clc097::PASCAL_A; +use paste::paste; +use std::ops::Range; + +use crate::extent::Extent4D; +use crate::format::Format; +use crate::image::Image; +use crate::image::ImageDim; +use crate::image::SampleLayout; +use crate::image::View; +use crate::image::ViewType; + +macro_rules! set_enum { + ($th:expr, $cls:ident, $field:ident, $enum:ident) => { + paste! { + $th.set_field($cls::$field, $cls::[<$field _ $enum>]) + } + }; +} + +trait SetUFixed { + fn set_ufixed(&mut self, range: Range, val: f32); +} + +const FIXED_FRAC_BITS: u32 = 8; + +impl SetUFixed for T { + fn set_ufixed(&mut self, range: Range, val: f32) { + assert!(range.len() >= FIXED_FRAC_BITS as usize); + let scaled = val * ((1 << FIXED_FRAC_BITS) as f32); + let scaled_max = ((1 << range.len()) - 1) as f32; + let u_val = scaled.clamp(0.0, scaled_max).round() as u32; + self.set_field(range, u_val); + } +} + +fn nv9097_th_v2_source( + fmt: &nil_tic_format, + swizzle: pipe_swizzle, + is_int: bool, +) -> u32 { + match swizzle { + PIPE_SWIZZLE_X => fmt.src_x(), + PIPE_SWIZZLE_Y => fmt.src_y(), + PIPE_SWIZZLE_Z => fmt.src_z(), + PIPE_SWIZZLE_W => fmt.src_w(), + PIPE_SWIZZLE_0 => cl9097::TEXHEADV2_X_SOURCE_IN_ZERO, + PIPE_SWIZZLE_1 => { + if is_int { + cl9097::TEXHEADV2_X_SOURCE_IN_ONE_INT + } else { + cl9097::TEXHEADV2_X_SOURCE_IN_ONE_FLOAT + } + } + other => panic!("Invalid component swizzle {}", other), + } +} + +fn nvb097_th_bl_source( + fmt: &nil_tic_format, + swizzle: pipe_swizzle, + is_int: bool, +) -> u32 { + match swizzle { + PIPE_SWIZZLE_X => fmt.src_x(), + PIPE_SWIZZLE_Y => fmt.src_y(), + PIPE_SWIZZLE_Z => fmt.src_z(), + PIPE_SWIZZLE_W => fmt.src_w(), + PIPE_SWIZZLE_0 => clb097::TEXHEADV2_X_SOURCE_IN_ZERO, + PIPE_SWIZZLE_1 => { + if is_int { + clb097::TEXHEADV2_X_SOURCE_IN_ONE_INT + } else { + clb097::TEXHEADV2_X_SOURCE_IN_ONE_FLOAT + } + } + other => panic!("Invalid component swizzle {}", other), + } +} + +type THBitView<'a> = BitMutView<'a, [u32; 8]>; + +fn nv9097_set_th_v2_0<'a>( + th: &mut THBitView<'a>, + format: &Format, + swizzle: [nil_rs_bindings::pipe_swizzle; 4], +) { + let fmt = &format.info().tic; + let is_int = format.is_integer(); + let source = [ + nv9097_th_v2_source(fmt, swizzle[0], is_int), + nv9097_th_v2_source(fmt, swizzle[1], is_int), + nv9097_th_v2_source(fmt, swizzle[2], is_int), + nv9097_th_v2_source(fmt, swizzle[3], is_int), + ]; + + th.set_field(cl9097::TEXHEADV2_COMPONENT_SIZES, fmt.comp_sizes()); + th.set_field(cl9097::TEXHEADV2_R_DATA_TYPE, fmt.type_r()); + th.set_field(cl9097::TEXHEADV2_G_DATA_TYPE, fmt.type_g()); + th.set_field(cl9097::TEXHEADV2_B_DATA_TYPE, fmt.type_b()); + th.set_field(cl9097::TEXHEADV2_A_DATA_TYPE, fmt.type_a()); + th.set_field(cl9097::TEXHEADV2_X_SOURCE, source[0]); + th.set_field(cl9097::TEXHEADV2_Y_SOURCE, source[1]); + th.set_field(cl9097::TEXHEADV2_Z_SOURCE, source[2]); + th.set_field(cl9097::TEXHEADV2_W_SOURCE, source[3]); +} + +fn nvb097_set_th_bl_0<'a>( + th: &mut THBitView<'a>, + format: &Format, + swizzle: [nil_rs_bindings::pipe_swizzle; 4], +) { + let fmt = &format.info().tic; + let is_int = format.is_integer(); + let source = [ + nvb097_th_bl_source(fmt, swizzle[0], is_int), + nvb097_th_bl_source(fmt, swizzle[1], is_int), + nvb097_th_bl_source(fmt, swizzle[2], is_int), + nvb097_th_bl_source(fmt, swizzle[3], is_int), + ]; + + th.set_field(clb097::TEXHEAD_BL_COMPONENTS, fmt.comp_sizes()); + th.set_field(clb097::TEXHEAD_BL_R_DATA_TYPE, fmt.type_r()); + th.set_field(clb097::TEXHEAD_BL_G_DATA_TYPE, fmt.type_g()); + th.set_field(clb097::TEXHEAD_BL_B_DATA_TYPE, fmt.type_b()); + th.set_field(clb097::TEXHEAD_BL_A_DATA_TYPE, fmt.type_a()); + th.set_field(clb097::TEXHEAD_BL_X_SOURCE, source[0]); + th.set_field(clb097::TEXHEAD_BL_Y_SOURCE, source[1]); + th.set_field(clb097::TEXHEAD_BL_Z_SOURCE, source[2]); + th.set_field(clb097::TEXHEAD_BL_W_SOURCE, source[3]); +} + +fn pipe_to_nv_texture_type(ty: ViewType) -> u32 { + match ty { + ViewType::_1D => clb097::TEXHEAD_BL_TEXTURE_TYPE_ONE_D, + ViewType::_2D => clb097::TEXHEAD_BL_TEXTURE_TYPE_TWO_D, + ViewType::_3D | ViewType::_3DSliced => { + clb097::TEXHEAD_BL_TEXTURE_TYPE_THREE_D + } + ViewType::Cube => clb097::TEXHEAD_BL_TEXTURE_TYPE_CUBEMAP, + ViewType::_1DArray => clb097::TEXHEAD_BL_TEXTURE_TYPE_ONE_D_ARRAY, + ViewType::_2DArray => clb097::TEXHEAD_BL_TEXTURE_TYPE_TWO_D_ARRAY, + ViewType::CubeArray => clb097::TEXHEAD_BL_TEXTURE_TYPE_CUBEMAP_ARRAY, + } +} + +fn nil_rs_to_nv9097_multi_sample_count(sample_layout: SampleLayout) -> u32 { + match sample_layout { + SampleLayout::_1x1 => cl9097::TEXHEADV2_MULTI_SAMPLE_COUNT_MODE_1X1, + SampleLayout::_2x1 => cl9097::TEXHEADV2_MULTI_SAMPLE_COUNT_MODE_2X1, + SampleLayout::_2x2 => cl9097::TEXHEADV2_MULTI_SAMPLE_COUNT_MODE_2X2, + SampleLayout::_4x2 => cl9097::TEXHEADV2_MULTI_SAMPLE_COUNT_MODE_4X2, + SampleLayout::_4x4 => cl9097::TEXHEADV2_MULTI_SAMPLE_COUNT_MODE_4X4, + SampleLayout::Invalid => panic!("Invalid sample layout"), + } +} + +fn nil_rs_to_nvb097_multi_sample_count(sample_layout: SampleLayout) -> u32 { + match sample_layout { + SampleLayout::_1x1 => clb097::TEXHEAD_BL_MULTI_SAMPLE_COUNT_MODE_1X1, + SampleLayout::_2x1 => clb097::TEXHEAD_BL_MULTI_SAMPLE_COUNT_MODE_2X1, + SampleLayout::_2x2 => clb097::TEXHEAD_BL_MULTI_SAMPLE_COUNT_MODE_2X2, + SampleLayout::_4x2 => clb097::TEXHEAD_BL_MULTI_SAMPLE_COUNT_MODE_4X2, + SampleLayout::_4x4 => clb097::TEXHEAD_BL_MULTI_SAMPLE_COUNT_MODE_4X4, + SampleLayout::Invalid => panic!("Invalid sample layout"), + } +} + +fn nil_rs_max_mip_level(image: &Image, view: &View) -> u32 { + if view.view_type != ViewType::_3D + && view.array_len == 1 + && view.base_level == 0 + && view.num_levels == 1 + { + // The Unnormalized coordinates bit in the sampler gets ignored if the + // referenced image has more than one miplevel. Fortunately, Vulkan has + // restrictions requiring the view to be a single-layer single-LOD view + // in order to use nonnormalizedCoordinates = VK_TRUE in the sampler. + // From the Vulkan 1.3.255 spec: + // + // "When unnormalizedCoordinates is VK_TRUE, images the sampler is + // used with in the shader have the following requirements: + // + // - The viewType must be either VK_IMAGE_VIEW_TYPE_1D or + // VK_IMAGE_VIEW_TYPE_2D. + // - The image view must have a single layer and a single mip + // level." + // + // Under these conditions, the view is simply LOD 0 of a single array + // slice so we don't need to care about aray stride between slices so + // it's safe to set the number of miplevels to 0 regardless of how many + // the image actually has. + 0 + } else { + image.num_levels - 1 + } +} + +fn normalize_extent(image: &Image, view: &View) -> Extent4D { + let mut extent = Extent4D { + width: image.extent_px.width, + height: image.extent_px.height, + depth: 0, + array_len: 0, + }; + + match view.view_type { + ViewType::_1D + | ViewType::_2D + | ViewType::_1DArray + | ViewType::_2DArray => { + assert!(image.extent_px.depth == 1); + extent.depth = view.array_len; + } + ViewType::_3D => { + assert!(image.dim == ImageDim::_3D); + extent.depth = image.extent_px.depth; + } + ViewType::Cube | ViewType::CubeArray => { + assert!(image.dim == ImageDim::_2D); + assert!(view.array_len % 6 == 0); + extent.depth = view.array_len / 6; + } + ViewType::_3DSliced => { + assert!(image.dim == ImageDim::_3D); + extent.depth = view.array_len; + } + } + + extent +} + +fn nv9097_fill_tic( + image: &Image, + view: &View, + base_address: u64, + desc_out: &mut [u32; 8], +) { + assert!(image.format.el_size_B() == view.format.el_size_B()); + assert!(view.base_level + view.num_levels <= image.num_levels); + assert!( + view.base_array_layer + view.array_len <= image.extent_px.array_len + ); + + *desc_out = [0u32; 8]; + let mut th = BitMutView::new(desc_out); + + th.set_field(cl9097::TEXHEADV2_USE_TEXTURE_HEADER_VERSION2, true); + nv9097_set_th_v2_0(&mut th, &view.format, view.swizzle); + + // There's no base layer field in the texture header + let layer_address = base_address + + u64::from(view.base_array_layer) + + u64::from(image.array_stride_B); + + th.set_field(cl9097::TEXHEADV2_OFFSET_LOWER, layer_address as u32); + th.set_field(cl9097::TEXHEADV2_OFFSET_UPPER, (layer_address >> 32) as u32); + + let tiling = &image.levels[0].tiling; + + if tiling.is_tiled { + set_enum!(th, cl9097, TEXHEADV2_MEMORY_LAYOUT, BLOCKLINEAR); + + assert!(tiling.gob_height_is_8); + assert!(tiling.x_log2 == 0); + set_enum!(th, cl9097, TEXHEADV2_GOBS_PER_BLOCK_WIDTH, ONE_GOB); + th.set_field(cl9097::TEXHEADV2_GOBS_PER_BLOCK_HEIGHT, tiling.y_log2); + th.set_field(cl9097::TEXHEADV2_GOBS_PER_BLOCK_DEPTH, tiling.z_log2); + + let nv_tex_type = pipe_to_nv_texture_type(view.view_type); + th.set_field(cl9097::TEXHEADV2_TEXTURE_TYPE, nv_tex_type); + } else { + set_enum!(th, cl9097, TEXHEADV2_MEMORY_LAYOUT, PITCH); + + let pitch = image.levels[0].row_stride_B; + th.set_field(cl9097::TEXHEADV2_PITCH, pitch); + + assert!( + view.view_type == ViewType::_2D + || view.view_type == ViewType::_2DArray + ); + assert!(image.sample_layout == SampleLayout::_1x1); + assert!(view.num_levels == 1); + set_enum!(th, cl9097, TEXHEADV2_TEXTURE_TYPE, TWO_D_NO_MIPMAP); + } + + set_enum!(th, cl9097, TEXHEADV2_LOD_ANISO_QUALITY, LOD_QUALITY_HIGH); + set_enum!(th, cl9097, TEXHEADV2_LOD_ISO_QUALITY, LOD_QUALITY_HIGH); + set_enum!( + th, + cl9097, + TEXHEADV2_ANISO_COARSE_SPREAD_MODIFIER, + SPREAD_MODIFIER_NONE + ); + + let extent = normalize_extent(image, view); + th.set_field(cl9097::TEXHEADV2_WIDTH, extent.width); + th.set_field(cl9097::TEXHEADV2_HEIGHT, extent.height); + th.set_field(cl9097::TEXHEADV2_DEPTH, extent.depth); + + let max_mip_level = nil_rs_max_mip_level(image, view); + th.set_field(cl9097::TEXHEADV2_MAX_MIP_LEVEL, max_mip_level); + + th.set_field(cl9097::TEXHEADV2_S_R_G_B_CONVERSION, view.format.is_srgb()); + + set_enum!(th, cl9097, TEXHEADV2_BORDER_SOURCE, BORDER_COLOR); + + // In the sampler, the two options for FLOAT_COORD_NORMALIZATION are: + // + // - FORCE_UNNORMALIZED_COORDS + // - USE_HEADER_SETTING + // + // So we set it to normalized in the header and let the sampler select that + // or force non-normalized. + th.set_field(cl9097::TEXHEADV2_NORMALIZED_COORDS, true); + + set_enum!( + th, + cl9097, + TEXHEADV2_ANISO_FINE_SPREAD_FUNC, + SPREAD_FUNC_TWO + ); + set_enum!( + th, + cl9097, + TEXHEADV2_ANISO_COARSE_SPREAD_FUNC, + SPREAD_FUNC_ONE + ); + + th.set_field(cl9097::TEXHEADV2_RES_VIEW_MIN_MIP_LEVEL, view.base_level); + th.set_field( + cl9097::TEXHEADV2_RES_VIEW_MAX_MIP_LEVEL, + view.num_levels + view.base_level - 1, + ); + + let msc = nil_rs_to_nv9097_multi_sample_count(image.sample_layout); + th.set_field(cl9097::TEXHEADV2_MULTI_SAMPLE_COUNT, msc); + + let min_lod_clamp = view.min_lod_clamp - (view.base_level as f32); + th.set_ufixed(cl9097::TEXHEADV2_MIN_LOD_CLAMP, min_lod_clamp); +} + +fn nvb097_fill_tic( + dev: &nil_rs_bindings::nv_device_info, + image: &Image, + view: &View, + base_address: u64, + desc_out: &mut [u32; 8], +) { + assert!(image.format.el_size_B() == view.format.el_size_B()); + assert!(view.base_level + view.num_levels <= image.num_levels); + + *desc_out = [0u32; 8]; + let mut th = BitMutView::new(desc_out); + + nvb097_set_th_bl_0(&mut th, &view.format, view.swizzle); + + let tiling = &image.levels[0].tiling; + + // There's no base layer field in the texture header + let mut layer_address = base_address; + if view.view_type == ViewType::_3DSliced { + assert!(view.num_levels == 1); + assert!( + view.base_array_layer + view.array_len <= image.extent_px.depth + ); + + layer_address += + image.level_z_offset_B(view.base_level, view.base_array_layer); + } else { + assert!( + view.base_array_layer + view.array_len <= image.extent_px.array_len + ); + layer_address += + u64::from(view.base_array_layer) * u64::from(image.array_stride_B); + } + + if tiling.is_tiled { + set_enum!(th, clb097, TEXHEAD_BL_HEADER_VERSION, SELECT_BLOCKLINEAR); + + let addr = BitView::new(&layer_address); + assert!(addr.get_bit_range_u64(0..9) == 0); + th.set_field( + clb097::TEXHEAD_BL_ADDRESS_BITS31TO9, + addr.get_bit_range_u64(9..32), + ); + th.set_field( + clb097::TEXHEAD_BL_ADDRESS_BITS47TO32, + addr.get_bit_range_u64(32..48), + ); + assert!(addr.get_bit_range_u64(48..64) == 0); + + assert!(tiling.gob_height_is_8); + + set_enum!(th, clb097, TEXHEAD_BL_GOBS_PER_BLOCK_WIDTH, ONE_GOB); + th.set_field(clb097::TEXHEAD_BL_GOBS_PER_BLOCK_HEIGHT, tiling.y_log2); + th.set_field(clb097::TEXHEAD_BL_GOBS_PER_BLOCK_DEPTH, tiling.z_log2); + th.set_field(clb097::TEXHEAD_BL_TILE_WIDTH_IN_GOBS, tiling.x_log2); + + let nv_text_type = pipe_to_nv_texture_type(view.view_type); + th.set_field(clb097::TEXHEAD_BL_TEXTURE_TYPE, nv_text_type); + } else { + set_enum!(th, clb097, TEXHEAD_BL_HEADER_VERSION, SELECT_PITCH); + + let addr = BitView::new(&layer_address); + assert!(addr.get_bit_range_u64(0..5) == 0); + th.set_field( + clb097::TEXHEAD_PITCH_ADDRESS_BITS31TO5, + addr.get_bit_range_u64(5..32), + ); + th.set_field( + clb097::TEXHEAD_PITCH_ADDRESS_BITS47TO32, + addr.get_bit_range_u64(32..48), + ); + assert!(addr.get_bit_range_u64(48..64) == 0); + + let pitch = image.levels[0].row_stride_B; + let pitch = BitView::new(&pitch); + assert!(pitch.get_bit_range_u64(0..5) == 0); + assert!(pitch.get_bit_range_u64(21..32) == 0); + th.set_field( + clb097::TEXHEAD_PITCH_PITCH_BITS20TO5, + pitch.get_bit_range_u64(5..21), + ); + + assert!( + view.view_type == ViewType::_2D + || view.view_type == ViewType::_2DArray + ); + assert!(image.sample_layout == SampleLayout::_1x1); + assert!(view.num_levels == 1); + set_enum!(th, clb097, TEXHEAD_PITCH_TEXTURE_TYPE, TWO_D_NO_MIPMAP); + } + + th.set_field(clb097::TEXHEAD_BL_LOD_ANISO_QUALITY2, true); + set_enum!(th, clb097, TEXHEAD_BL_LOD_ANISO_QUALITY, LOD_QUALITY_HIGH); + set_enum!(th, clb097, TEXHEAD_BL_LOD_ISO_QUALITY, LOD_QUALITY_HIGH); + set_enum!( + th, + clb097, + TEXHEAD_BL_ANISO_COARSE_SPREAD_MODIFIER, + SPREAD_MODIFIER_NONE + ); + + let extent = normalize_extent(image, view); + th.set_field(clb097::TEXHEAD_BL_WIDTH_MINUS_ONE, extent.width - 1); + + if dev.cls_eng3d >= PASCAL_A { + let height_1 = extent.height - 1; + let depth_1 = extent.depth - 1; + th.set_field(clc097::TEXHEAD_BL_HEIGHT_MINUS_ONE, height_1 & 0xffff); + th.set_field(clc097::TEXHEAD_BL_HEIGHT_MINUS_ONE_BIT16, height_1 >> 16); + th.set_field(clc097::TEXHEAD_BL_DEPTH_MINUS_ONE, depth_1 & 0x3fff); + th.set_field(clc097::TEXHEAD_BL_DEPTH_MINUS_ONE_BIT14, depth_1 >> 14); + } else { + th.set_field(clb097::TEXHEAD_BL_HEIGHT_MINUS_ONE, extent.height - 1); + th.set_field(clb097::TEXHEAD_BL_DEPTH_MINUS_ONE, extent.depth - 1); + } + + let max_mip_level = nil_rs_max_mip_level(image, view); + th.set_field(clb097::TEXHEAD_BL_MAX_MIP_LEVEL, max_mip_level); + + th.set_field(clb097::TEXHEAD_BL_S_R_G_B_CONVERSION, view.format.is_srgb()); + + set_enum!(th, clb097, TEXHEAD_BL_SECTOR_PROMOTION, PROMOTE_TO_2_V); + set_enum!(th, clb097, TEXHEAD_BL_BORDER_SIZE, BORDER_SAMPLER_COLOR); + + // In the sampler, the two options for FLOAT_COORD_NORMALIZATION are: + // + // - FORCE_UNNORMALIZED_COORDS + // - USE_HEADER_SETTING + // + // So we set it to normalized in the header and let the sampler select that + // or force non-normalized. + + th.set_field(clb097::TEXHEAD_BL_NORMALIZED_COORDS, true); + set_enum!( + th, + clb097, + TEXHEAD_BL_ANISO_FINE_SPREAD_FUNC, + SPREAD_FUNC_TWO + ); + set_enum!( + th, + clb097, + TEXHEAD_BL_ANISO_COARSE_SPREAD_FUNC, + SPREAD_FUNC_ONE + ); + + th.set_field(clb097::TEXHEAD_BL_RES_VIEW_MIN_MIP_LEVEL, view.base_level); + + let max_mip_level = view.num_levels + view.base_level - 1; + th.set_field(clb097::TEXHEAD_BL_RES_VIEW_MAX_MIP_LEVEL, max_mip_level); + + let msc = nil_rs_to_nvb097_multi_sample_count(image.sample_layout); + th.set_field(clb097::TEXHEAD_BL_MULTI_SAMPLE_COUNT, msc); + + let min_lod_clamp = view.min_lod_clamp - (view.base_level as f32); + th.set_ufixed(clb097::TEXHEAD_BL_MIN_LOD_CLAMP, min_lod_clamp); +} + +pub const IDENTITY_SWIZZLE: [nil_rs_bindings::pipe_swizzle; 4] = [ + nil_rs_bindings::PIPE_SWIZZLE_X, + nil_rs_bindings::PIPE_SWIZZLE_Y, + nil_rs_bindings::PIPE_SWIZZLE_Z, + nil_rs_bindings::PIPE_SWIZZLE_W, +]; + +fn nv9097_nil_fill_buffer_tic( + base_address: u64, + format: Format, + num_elements: u32, + desc_out: &mut [u32; 8], +) { + *desc_out = [0u32; 8]; + let mut th = BitMutView::new(desc_out); + th.set_field(cl9097::TEXHEADV2_USE_TEXTURE_HEADER_VERSION2, true); + + assert!(format.supports_buffer()); + nv9097_set_th_v2_0(&mut th, &format, IDENTITY_SWIZZLE); + + th.set_field(cl9097::TEXHEADV2_OFFSET_LOWER, base_address as u32); + th.set_field(cl9097::TEXHEADV2_OFFSET_UPPER, (base_address >> 32) as u32); + + set_enum!(th, cl9097, TEXHEADV2_MEMORY_LAYOUT, PITCH); + + th.set_field(cl9097::TEXHEADV2_WIDTH, num_elements); + + set_enum!(th, cl9097, TEXHEADV2_TEXTURE_TYPE, ONE_D_BUFFER); +} + +fn nvb097_nil_fill_buffer_tic( + base_address: u64, + format: Format, + num_elements: u32, + desc_out: &mut [u32; 8], +) { + *desc_out = [0u32; 8]; + let mut th = BitMutView::new(desc_out); + + assert!(format.supports_buffer()); + nvb097_set_th_bl_0(&mut th, &format, IDENTITY_SWIZZLE); + + th.set_field(clb097::TEXHEAD_1D_ADDRESS_BITS31TO0, base_address as u32); + th.set_field(clb097::TEXHEAD_1D_ADDRESS_BITS47TO32, base_address >> 32); + + set_enum!(th, clb097, TEXHEAD_1D_HEADER_VERSION, SELECT_ONE_D_BUFFER); + + th.set_field( + clb097::TEXHEAD_1D_WIDTH_MINUS_ONE_BITS15TO0, + (num_elements - 1) & 0xffff, + ); + th.set_field( + clb097::TEXHEAD_1D_WIDTH_MINUS_ONE_BITS31TO16, + (num_elements - 1) >> 16, + ); + + set_enum!(th, clb097, TEXHEAD_1D_TEXTURE_TYPE, ONE_D_BUFFER); + + // TODO: Do we need this? + set_enum!(th, clb097, TEXHEAD_1D_SECTOR_PROMOTION, PROMOTE_TO_2_V); +} + +impl Image { + #[no_mangle] + pub extern "C" fn nil_image_fill_tic( + &self, + dev: &nil_rs_bindings::nv_device_info, + view: &View, + base_address: u64, + desc_out: &mut [u32; 8], + ) { + self.fill_tic(dev, view, base_address, desc_out); + } + + pub fn fill_tic( + &self, + dev: &nil_rs_bindings::nv_device_info, + view: &View, + base_address: u64, + desc_out: &mut [u32; 8], + ) { + if dev.cls_eng3d >= MAXWELL_A { + nvb097_fill_tic(dev, self, view, base_address, desc_out); + } else if dev.cls_eng3d >= FERMI_A { + nv9097_fill_tic(self, view, base_address, desc_out); + } else { + panic!("Tesla and older not supported"); + } + } +} + +#[no_mangle] +pub extern "C" fn nil_buffer_fill_tic( + dev: &nil_rs_bindings::nv_device_info, + base_address: u64, + format: Format, + num_elements: u32, + desc_out: &mut [u32; 8], +) { + fill_buffer_tic(dev, base_address, format, num_elements, desc_out); +} + +pub fn fill_buffer_tic( + dev: &nil_rs_bindings::nv_device_info, + base_address: u64, + format: Format, + num_elements: u32, + desc_out: &mut [u32; 8], +) { + if dev.cls_eng3d >= MAXWELL_A { + nvb097_nil_fill_buffer_tic(base_address, format, num_elements, desc_out) + } else if dev.cls_eng3d >= FERMI_A { + nv9097_nil_fill_buffer_tic(base_address, format, num_elements, desc_out) + } else { + panic!("Tesla and older not supported"); + } +} diff --git a/src/nouveau/vulkan/nvk_buffer_view.c b/src/nouveau/vulkan/nvk_buffer_view.c index 3a7349cfc93..428ea78ef1b 100644 --- a/src/nouveau/vulkan/nvk_buffer_view.c +++ b/src/nouveau/vulkan/nvk_buffer_view.c @@ -57,8 +57,8 @@ nvk_CreateBufferView(VkDevice _device, uint32_t desc[8]; nil_buffer_fill_tic(&nvk_device_physical(device)->info, nvk_buffer_address(buffer, view->vk.offset), - vk_format_to_pipe_format(view->vk.format), - view->vk.elements, desc); + nil_format(vk_format_to_pipe_format(view->vk.format)), + view->vk.elements, &desc); result = nvk_descriptor_table_add(device, &device->images, desc, sizeof(desc), &view->desc_index); diff --git a/src/nouveau/vulkan/nvk_image_view.c b/src/nouveau/vulkan/nvk_image_view.c index a470fe96b01..1b6e98f1c78 100644 --- a/src/nouveau/vulkan/nvk_image_view.c +++ b/src/nouveau/vulkan/nvk_image_view.c @@ -74,8 +74,8 @@ image_3d_view_as_2d_array(struct nil_image *image, struct nil_view *view, uint64_t *base_addr) { - assert(view->type == NIL_VIEW_TYPE_2D || - view->type == NIL_VIEW_TYPE_2D_ARRAY); + assert(view->view_type == NIL_VIEW_TYPE_2D || + view->view_type == NIL_VIEW_TYPE_2D_ARRAY); assert(view->num_levels == 1); uint64_t offset_B; @@ -102,6 +102,7 @@ nvk_image_view_init(struct nvk_device *dev, bool driver_internal, const VkImageViewCreateInfo *pCreateInfo) { + struct nvk_physical_device *pdev = nvk_device_physical(dev); VK_FROM_HANDLE(nvk_image, image, pCreateInfo->image); VkResult result; @@ -149,8 +150,8 @@ nvk_image_view_init(struct nvk_device *dev, p_format = get_stencil_format(p_format); struct nil_view nil_view = { - .type = vk_image_view_type_to_nil_view_type(view->vk.view_type), - .format = p_format, + .view_type = vk_image_view_type_to_nil_view_type(view->vk.view_type), + .format = nil_format(p_format), .base_level = view->vk.base_mip_level, .num_levels = view->vk.level_count, .base_array_layer = view->vk.base_array_layer, @@ -165,11 +166,11 @@ nvk_image_view_init(struct nvk_device *dev, }; if (util_format_is_compressed(nil_image.format.p_format) && - !util_format_is_compressed(nil_view.format)) + !util_format_is_compressed(nil_view.format.p_format)) image_uncompressed_view(&nil_image, &nil_view, &base_addr); if (nil_image.dim == NIL_IMAGE_DIM_3D && - nil_view.type != NIL_VIEW_TYPE_3D) + nil_view.view_type != NIL_VIEW_TYPE_3D) image_3d_view_as_2d_array(&nil_image, &nil_view, &base_addr); view->planes[view_plane].sample_layout = nil_image.sample_layout; @@ -177,8 +178,8 @@ nvk_image_view_init(struct nvk_device *dev, if (view->vk.usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) { uint32_t tic[8]; - nil_image_fill_tic(&nvk_device_physical(dev)->info, - &nil_image, &nil_view, base_addr, tic); + nil_image_fill_tic(&nil_image, &pdev->info, + &nil_view, base_addr, &tic); result = nvk_descriptor_table_add(dev, &dev->images, tic, sizeof(tic), &view->planes[view_plane].sampled_desc_index); @@ -192,7 +193,7 @@ nvk_image_view_init(struct nvk_device *dev, /* For storage images, we can't have any cubes */ if (view->vk.view_type == VK_IMAGE_VIEW_TYPE_CUBE || view->vk.view_type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) - nil_view.type = NIL_VIEW_TYPE_2D_ARRAY; + nil_view.view_type = NIL_VIEW_TYPE_2D_ARRAY; if (view->vk.view_type == VK_IMAGE_VIEW_TYPE_3D) { /* Without VK_AMD_shader_image_load_store_lod, the client can only @@ -205,7 +206,7 @@ nvk_image_view_init(struct nvk_device *dev, if (view->vk.storage.z_slice_offset > 0 || view->vk.storage.z_slice_count < nil_image.extent_px.depth) { - nil_view.type = NIL_VIEW_TYPE_3D_SLICED; + nil_view.view_type = NIL_VIEW_TYPE_3D_SLICED; nil_view.base_array_layer = view->vk.storage.z_slice_offset; nil_view.array_len = view->vk.storage.z_slice_count; } @@ -215,8 +216,8 @@ nvk_image_view_init(struct nvk_device *dev, nil_image = nil_msaa_image_as_sa(&nil_image); uint32_t tic[8]; - nil_image_fill_tic(&nvk_device_physical(dev)->info, - &nil_image, &nil_view, base_addr, tic); + nil_image_fill_tic(&nil_image, &pdev->info, &nil_view, + base_addr, &tic); result = nvk_descriptor_table_add(dev, &dev->images, tic, sizeof(tic), &view->planes[view_plane].storage_desc_index);