From 7fe169dd4ab2f9e0f9fbe1dd3bd5193d170480a8 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Wed, 15 May 2024 15:45:21 +0200 Subject: [PATCH] ac,radv,radeonsi: introduce a helper to build a sampler descriptor This introduces ac_sampler_state which contains all information to build a sampler descriptor for AMD hardware instead of duplicating code between RADV and RadeonSI. Both drivers just need to fill this new struct to get a descriptor. This allows RADV to get GFX12 support for free. I think we should introduce helpers for other type of descriptors. Signed-off-by: Samuel Pitoiset Part-of: --- src/amd/common/ac_descriptors.c | 64 +++++++++++++++++++++++++ src/amd/common/ac_descriptors.h | 47 ++++++++++++++++++ src/amd/common/meson.build | 2 + src/amd/vulkan/radv_sampler.c | 54 +++++++++------------ src/gallium/drivers/radeonsi/si_state.c | 61 ++++++++--------------- 5 files changed, 156 insertions(+), 72 deletions(-) create mode 100644 src/amd/common/ac_descriptors.c create mode 100644 src/amd/common/ac_descriptors.h diff --git a/src/amd/common/ac_descriptors.c b/src/amd/common/ac_descriptors.c new file mode 100644 index 0000000000000..247e937c311b1 --- /dev/null +++ b/src/amd/common/ac_descriptors.c @@ -0,0 +1,64 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * Copyright 2024 Valve Corporation + * + * SPDX-License-Identifier: MIT + */ + +#include "ac_descriptors.h" + +#include "sid.h" + +#include "util/u_math.h" + +void +ac_build_sampler_descriptor(const enum amd_gfx_level gfx_level, const struct ac_sampler_state *state, uint32_t desc[4]) +{ + const unsigned perf_mip = state->max_aniso_ratio ? state->max_aniso_ratio + 6 : 0; + const bool compat_mode = gfx_level == GFX8 || gfx_level == GFX9; + + desc[0] = S_008F30_CLAMP_X(state->address_mode_u) | + S_008F30_CLAMP_Y(state->address_mode_v) | + S_008F30_CLAMP_Z(state->address_mode_w) | + S_008F30_MAX_ANISO_RATIO(state->max_aniso_ratio) | + S_008F30_DEPTH_COMPARE_FUNC(state->depth_compare_func) | + S_008F30_FORCE_UNNORMALIZED(state->unnormalized_coords) | + S_008F30_ANISO_THRESHOLD(state->max_aniso_ratio >> 1) | + S_008F30_ANISO_BIAS(state->max_aniso_ratio) | + S_008F30_DISABLE_CUBE_WRAP(!state->cube_wrap) | + S_008F30_COMPAT_MODE(compat_mode) | + S_008F30_TRUNC_COORD(state->trunc_coord) | + S_008F30_FILTER_MODE(state->filter_mode); + desc[1] = 0; + desc[2] = S_008F38_XY_MAG_FILTER(state->mag_filter) | + S_008F38_XY_MIN_FILTER(state->min_filter) | + S_008F38_MIP_FILTER(state->mip_filter); + desc[3] = S_008F3C_BORDER_COLOR_TYPE(state->border_color_type); + + if (gfx_level >= GFX12) { + desc[1] |= S_008F34_MIN_LOD_GFX12(util_unsigned_fixed(CLAMP(state->min_lod, 0, 17), 8)) | + S_008F34_MAX_LOD_GFX12(util_unsigned_fixed(CLAMP(state->max_lod, 0, 17), 8)); + desc[2] |= S_008F38_PERF_MIP_LO(perf_mip); + desc[3] |= S_008F3C_PERF_MIP_HI(perf_mip >> 2); + } else { + desc[1] |= S_008F34_MIN_LOD_GFX6(util_unsigned_fixed(CLAMP(state->min_lod, 0, 15), 8)) | + S_008F34_MAX_LOD_GFX6(util_unsigned_fixed(CLAMP(state->max_lod, 0, 15), 8)) | + S_008F34_PERF_MIP(perf_mip); + } + + if (gfx_level >= GFX10) { + desc[2] |= S_008F38_LOD_BIAS(util_signed_fixed(CLAMP(state->lod_bias, -32, 31), 8)) | + S_008F38_ANISO_OVERRIDE_GFX10(!state->aniso_single_level); + } else { + desc[2] |= S_008F38_LOD_BIAS(util_signed_fixed(CLAMP(state->lod_bias, -16, 16), 8)) | + S_008F38_DISABLE_LSB_CEIL(gfx_level <= GFX8) | + S_008F38_FILTER_PREC_FIX(1) | + S_008F38_ANISO_OVERRIDE_GFX8(gfx_level >= GFX8 && !state->aniso_single_level); + } + + if (gfx_level >= GFX11) { + desc[3] |= S_008F3C_BORDER_COLOR_PTR_GFX11(state->border_color_ptr); + } else { + desc[3] |= S_008F3C_BORDER_COLOR_PTR_GFX6(state->border_color_ptr); + } +} diff --git a/src/amd/common/ac_descriptors.h b/src/amd/common/ac_descriptors.h new file mode 100644 index 0000000000000..e3a88b920020a --- /dev/null +++ b/src/amd/common/ac_descriptors.h @@ -0,0 +1,47 @@ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * Copyright 2024 Valve Corporation + * + * SPDX-License-Identifier: MIT + */ + +#ifndef AC_DESCRIPTORS_H +#define AC_DESCRIPTORS_H + +#include "ac_gpu_info.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct ac_sampler_state { + unsigned address_mode_u : 3; + unsigned address_mode_v : 3; + unsigned address_mode_w : 3; + unsigned max_aniso_ratio : 3; + unsigned depth_compare_func : 3; + unsigned unnormalized_coords : 1; + unsigned cube_wrap : 1; + unsigned trunc_coord : 1; + unsigned filter_mode : 2; + unsigned mag_filter : 2; + unsigned min_filter : 2; + unsigned mip_filter : 2; + unsigned aniso_single_level : 1; + unsigned border_color_type : 2; + unsigned border_color_ptr : 12; + float min_lod; + float max_lod; + float lod_bias; +}; + +void +ac_build_sampler_descriptor(const enum amd_gfx_level gfx_level, + const struct ac_sampler_state *state, + uint32_t desc[4]); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/amd/common/meson.build b/src/amd/common/meson.build index 05e2b97a415d0..156499ca97e92 100644 --- a/src/amd/common/meson.build +++ b/src/amd/common/meson.build @@ -82,6 +82,8 @@ amd_common_files = files( 'ac_surface.h', 'ac_debug.c', 'ac_debug.h', + 'ac_descriptors.c', + 'ac_descriptors.h', 'ac_formats.c', 'ac_formats.h', 'ac_shadowed_regs.c', diff --git a/src/amd/vulkan/radv_sampler.c b/src/amd/vulkan/radv_sampler.c index c1f8f4a53ba9b..9702e0d1a3c7e 100644 --- a/src/amd/vulkan/radv_sampler.c +++ b/src/amd/vulkan/radv_sampler.c @@ -10,6 +10,8 @@ #include "vk_log.h" +#include "ac_descriptors.h" + #include "radv_sampler.h" #include "radv_device.h" #include "radv_entrypoints.h" @@ -186,7 +188,6 @@ radv_init_sampler(struct radv_device *device, struct radv_sampler *sampler, cons const struct radv_instance *instance = radv_physical_device_instance(pdev); uint32_t max_aniso = radv_get_max_anisotropy(device, pCreateInfo); uint32_t max_aniso_ratio = radv_tex_aniso_filter(max_aniso); - bool compat_mode = pdev->info.gfx_level == GFX8 || pdev->info.gfx_level == GFX9; unsigned filter_mode = radv_tex_filter_mode(sampler->vk.reduction_mode); unsigned depth_compare_func = V_008F30_SQ_TEX_DEPTH_COMPARE_NEVER; bool trunc_coord = ((pCreateInfo->minFilter == VK_FILTER_NEAREST && pCreateInfo->magFilter == VK_FILTER_NEAREST) || @@ -217,37 +218,28 @@ radv_init_sampler(struct radv_device *device, struct radv_sampler *sampler, cons /* If we don't have a custom color, set the ptr to 0 */ border_color_ptr = sampler->border_color_slot != RADV_BORDER_COLOR_COUNT ? sampler->border_color_slot : 0; - sampler->state[0] = (S_008F30_CLAMP_X(radv_tex_wrap(pCreateInfo->addressModeU)) | - S_008F30_CLAMP_Y(radv_tex_wrap(pCreateInfo->addressModeV)) | - S_008F30_CLAMP_Z(radv_tex_wrap(pCreateInfo->addressModeW)) | - S_008F30_MAX_ANISO_RATIO(max_aniso_ratio) | S_008F30_DEPTH_COMPARE_FUNC(depth_compare_func) | - S_008F30_FORCE_UNNORMALIZED(pCreateInfo->unnormalizedCoordinates ? 1 : 0) | - S_008F30_ANISO_THRESHOLD(max_aniso_ratio >> 1) | S_008F30_ANISO_BIAS(max_aniso_ratio) | - S_008F30_DISABLE_CUBE_WRAP(disable_cube_wrap) | S_008F30_COMPAT_MODE(compat_mode) | - S_008F30_FILTER_MODE(filter_mode) | S_008F30_TRUNC_COORD(trunc_coord)); - sampler->state[1] = (S_008F34_MIN_LOD_GFX6(util_unsigned_fixed(CLAMP(pCreateInfo->minLod, 0, 15), 8)) | - S_008F34_MAX_LOD_GFX6(util_unsigned_fixed(CLAMP(pCreateInfo->maxLod, 0, 15), 8)) | - S_008F34_PERF_MIP(max_aniso_ratio ? max_aniso_ratio + 6 : 0)); - sampler->state[2] = (S_008F38_XY_MAG_FILTER(radv_tex_filter(pCreateInfo->magFilter, max_aniso)) | - S_008F38_XY_MIN_FILTER(radv_tex_filter(pCreateInfo->minFilter, max_aniso)) | - S_008F38_MIP_FILTER(radv_tex_mipfilter(pCreateInfo->mipmapMode))); - sampler->state[3] = S_008F3C_BORDER_COLOR_TYPE(radv_tex_bordercolor(border_color)); + struct ac_sampler_state ac_state = { + .address_mode_u = radv_tex_wrap(pCreateInfo->addressModeU), + .address_mode_v = radv_tex_wrap(pCreateInfo->addressModeV), + .address_mode_w = radv_tex_wrap(pCreateInfo->addressModeW), + .max_aniso_ratio = max_aniso_ratio, + .depth_compare_func = depth_compare_func, + .unnormalized_coords = pCreateInfo->unnormalizedCoordinates ? 1 : 0, + .cube_wrap = !disable_cube_wrap, + .trunc_coord = trunc_coord, + .filter_mode = filter_mode, + .mag_filter = radv_tex_filter(pCreateInfo->magFilter, max_aniso), + .min_filter = radv_tex_filter(pCreateInfo->minFilter, max_aniso), + .mip_filter = radv_tex_mipfilter(pCreateInfo->mipmapMode), + .min_lod = pCreateInfo->minLod, + .max_lod = pCreateInfo->maxLod, + .lod_bias = pCreateInfo->mipLodBias, + .aniso_single_level = !instance->drirc.disable_aniso_single_level, + .border_color_type = radv_tex_bordercolor(border_color), + .border_color_ptr = border_color_ptr, + }; - if (pdev->info.gfx_level >= GFX10) { - sampler->state[2] |= S_008F38_LOD_BIAS(util_signed_fixed(CLAMP(pCreateInfo->mipLodBias, -32, 31), 8)) | - S_008F38_ANISO_OVERRIDE_GFX10(instance->drirc.disable_aniso_single_level); - } else { - sampler->state[2] |= - S_008F38_LOD_BIAS(util_signed_fixed(CLAMP(pCreateInfo->mipLodBias, -16, 16), 8)) | - S_008F38_DISABLE_LSB_CEIL(pdev->info.gfx_level <= GFX8) | S_008F38_FILTER_PREC_FIX(1) | - S_008F38_ANISO_OVERRIDE_GFX8(instance->drirc.disable_aniso_single_level && pdev->info.gfx_level >= GFX8); - } - - if (pdev->info.gfx_level >= GFX11) { - sampler->state[3] |= S_008F3C_BORDER_COLOR_PTR_GFX11(border_color_ptr); - } else { - sampler->state[3] |= S_008F3C_BORDER_COLOR_PTR_GFX6(border_color_ptr); - } + ac_build_sampler_descriptor(pdev->info.gfx_level, &ac_state, sampler->state); } VKAPI_ATTR VkResult VKAPI_CALL diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index ff58349cbbe51..8f53ca2f76a27 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -18,6 +18,7 @@ #include "util/u_upload_mgr.h" #include "util/u_blend.h" +#include "ac_descriptors.h" #include "ac_formats.h" #include "gfx10_format_table.h" @@ -5470,7 +5471,6 @@ static void *si_create_sampler_state(struct pipe_context *ctx, struct si_sampler_state *rstate = CALLOC_STRUCT(si_sampler_state); unsigned max_aniso = sscreen->force_aniso >= 0 ? sscreen->force_aniso : state->max_anisotropy; unsigned max_aniso_ratio = si_tex_aniso_filter(max_aniso); - unsigned perf_mip = max_aniso_ratio ? max_aniso_ratio + 6 : 0; bool trunc_coord = (state->min_img_filter == PIPE_TEX_FILTER_NEAREST && state->mag_img_filter == PIPE_TEX_FILTER_NEAREST && state->compare_mode == PIPE_TEX_COMPARE_NONE) || @@ -5502,47 +5502,26 @@ static void *si_create_sampler_state(struct pipe_context *ctx, state->border_color_is_integer, &border_color_ptr); - rstate->val[0] = - (S_008F30_CLAMP_X(si_tex_wrap(state->wrap_s)) | S_008F30_CLAMP_Y(si_tex_wrap(state->wrap_t)) | - S_008F30_CLAMP_Z(si_tex_wrap(state->wrap_r)) | S_008F30_MAX_ANISO_RATIO(max_aniso_ratio) | - S_008F30_DEPTH_COMPARE_FUNC(si_tex_compare(state->compare_mode, state->compare_func)) | - S_008F30_FORCE_UNNORMALIZED(state->unnormalized_coords) | - S_008F30_ANISO_THRESHOLD(max_aniso_ratio >> 1) | S_008F30_ANISO_BIAS(max_aniso_ratio) | - S_008F30_DISABLE_CUBE_WRAP(!state->seamless_cube_map) | - S_008F30_TRUNC_COORD(trunc_coord)); - rstate->val[1] = 0; - rstate->val[2] = (S_008F38_XY_MAG_FILTER(si_tex_filter(state->mag_img_filter, max_aniso)) | - S_008F38_XY_MIN_FILTER(si_tex_filter(state->min_img_filter, max_aniso)) | - S_008F38_MIP_FILTER(si_tex_mipfilter(state->min_mip_filter))); - rstate->val[3] = S_008F3C_BORDER_COLOR_TYPE(border_color_type); + struct ac_sampler_state ac_state = { + .address_mode_u = si_tex_wrap(state->wrap_s), + .address_mode_v = si_tex_wrap(state->wrap_t), + .address_mode_w = si_tex_wrap(state->wrap_r), + .max_aniso_ratio = max_aniso_ratio, + .depth_compare_func = si_tex_compare(state->compare_mode, state->compare_func), + .unnormalized_coords = state->unnormalized_coords, + .cube_wrap = state->seamless_cube_map, + .trunc_coord = trunc_coord, + .mag_filter = si_tex_filter(state->mag_img_filter, max_aniso), + .min_filter = si_tex_filter(state->min_img_filter, max_aniso), + .mip_filter = si_tex_mipfilter(state->min_mip_filter), + .min_lod = state->min_lod, + .max_lod = state->max_lod, + .lod_bias = state->lod_bias, + .border_color_type = border_color_type, + .border_color_ptr = border_color_ptr, + }; - if (sscreen->info.gfx_level >= GFX12) { - rstate->val[1] |= S_008F34_MIN_LOD_GFX12(S_FIXED(CLAMP(state->min_lod, 0, 17), 8)) | - S_008F34_MAX_LOD_GFX12(S_FIXED(CLAMP(state->max_lod, 0, 17), 8)); - rstate->val[2] |= S_008F38_PERF_MIP_LO(perf_mip); - rstate->val[3] |= S_008F3C_PERF_MIP_HI(perf_mip >> 2); - } else { - rstate->val[1] |= S_008F34_MIN_LOD_GFX6(S_FIXED(CLAMP(state->min_lod, 0, 15), 8)) | - S_008F34_MAX_LOD_GFX6(S_FIXED(CLAMP(state->max_lod, 0, 15), 8)) | - S_008F34_PERF_MIP(perf_mip); - } - - if (sscreen->info.gfx_level >= GFX10) { - rstate->val[2] |= S_008F38_LOD_BIAS(S_FIXED(CLAMP(state->lod_bias, -32, 31), 8)) | - S_008F38_ANISO_OVERRIDE_GFX10(1); - } else { - rstate->val[0] |= S_008F30_COMPAT_MODE(sctx->gfx_level >= GFX8); - rstate->val[2] |= S_008F38_LOD_BIAS(S_FIXED(CLAMP(state->lod_bias, -16, 16), 8)) | - S_008F38_DISABLE_LSB_CEIL(sctx->gfx_level <= GFX8) | - S_008F38_FILTER_PREC_FIX(1) | - S_008F38_ANISO_OVERRIDE_GFX8(sctx->gfx_level >= GFX8); - } - - if (sscreen->info.gfx_level >= GFX11) { - rstate->val[3] |= S_008F3C_BORDER_COLOR_PTR_GFX11(border_color_ptr); - } else { - rstate->val[3] |= S_008F3C_BORDER_COLOR_PTR_GFX6(border_color_ptr); - } + ac_build_sampler_descriptor(sscreen->info.gfx_level, &ac_state, rstate->val); /* Create sampler resource for upgraded depth textures. */ memcpy(rstate->upgraded_depth_val, rstate->val, sizeof(rstate->val));