anv: split sampler state packing from API object creation

We'll reuse the state packing somewhere else later.

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Acked-by: Alyssa Rosenzweig <alyssa.rosenzweig@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39478>
This commit is contained in:
Lionel Landwerlin 2025-08-12 17:51:14 +03:00 committed by Marge Bot
parent 5ec7d31e20
commit 7b95d82240
7 changed files with 181 additions and 159 deletions

View file

@ -88,6 +88,7 @@ genX_bits_included_symbols = [
'RT_DISPATCH_GLOBALS::Launch Width',
'RT_DISPATCH_GLOBALS::Launch Height',
'RT_DISPATCH_GLOBALS::Launch Depth',
'SAMPLER_STATE',
]
genX_bits_h = custom_target(

View file

@ -577,7 +577,7 @@ void anv_GetDescriptorSetLayoutSupport(
ANV_FROM_HANDLE(anv_sampler, sampler,
binding->pImmutableSamplers[i]);
anv_foreach_stage(s, binding->stageFlags)
surface_count[s] += sampler->n_planes;
surface_count[s] += sampler->state.n_planes;
}
} else {
anv_foreach_stage(s, binding->stageFlags)
@ -866,7 +866,7 @@ VkResult anv_CreateDescriptorSetLayout(
};
if (has_embedded_samplers) {
set_layout->binding[b].samplers[i].embedded_key =
sampler->embedded_key;
sampler->state.embedded_key;
}
if (sampler->vk.ycbcr_conversion) {
set_layout->binding[b].samplers[i].has_ycbcr_conversion = true;
@ -874,8 +874,8 @@ VkResult anv_CreateDescriptorSetLayout(
sampler->vk.ycbcr_conversion->state;
}
if (set_layout->binding[b].max_plane_count < sampler->n_planes)
set_layout->binding[b].max_plane_count = sampler->n_planes;
if (set_layout->binding[b].max_plane_count < sampler->state.n_planes)
set_layout->binding[b].max_plane_count = sampler->state.n_planes;
}
}
break;
@ -1972,7 +1972,7 @@ anv_sampler_state_for_descriptor_set(const struct anv_sampler *sampler,
const struct anv_descriptor_set *set,
uint32_t plane)
{
return sampler->state[plane];
return sampler->state.state[plane];
}
void
@ -2053,7 +2053,7 @@ anv_descriptor_set_write_image_view(struct anv_device *device,
}
if (sampler) {
for (unsigned p = 0; p < sampler->n_planes; p++)
for (unsigned p = 0; p < sampler->state.n_planes; p++)
desc_data[p].sampler = sampler->bindless_state.offset + p * 32;
}
@ -2094,7 +2094,7 @@ anv_descriptor_set_write_image_view(struct anv_device *device,
bind_layout->descriptor_sampler_offset +
element * bind_layout->descriptor_sampler_stride) : desc_surface_map;
if (sampler) {
for (unsigned p = 0; p < sampler->n_planes; p++) {
for (unsigned p = 0; p < sampler->state.n_planes; p++) {
memcpy(sampler_map + p * ANV_SAMPLER_STATE_SIZE,
anv_sampler_state_for_descriptor_set(sampler, set, p),
ANV_SAMPLER_STATE_SIZE);
@ -2124,7 +2124,7 @@ anv_descriptor_set_write_image_view(struct anv_device *device,
if (data & ANV_DESCRIPTOR_SURFACE_SAMPLER) {
unsigned max_plane_count =
MAX2(image_view ? image_view->n_planes : 1,
sampler ? sampler->n_planes : 1);
sampler ? sampler->state.n_planes : 1);
for (unsigned p = 0; p < max_plane_count; p++) {
void *plane_map = desc_surface_map + p * 2 * ANV_SURFACE_STATE_SIZE;
@ -2758,7 +2758,7 @@ void anv_GetDescriptorEXT(
case VK_DESCRIPTOR_TYPE_SAMPLER:
if (pDescriptorInfo->data.pSampler &&
(sampler = anv_sampler_from_handle(*pDescriptorInfo->data.pSampler))) {
memcpy(pDescriptor, sampler->state[0], ANV_SAMPLER_STATE_SIZE);
memcpy(pDescriptor, sampler->state.state[0], ANV_SAMPLER_STATE_SIZE);
} else {
memset(pDescriptor, 0, ANV_SAMPLER_STATE_SIZE);
}
@ -2789,7 +2789,7 @@ void anv_GetDescriptorEXT(
(sampler = anv_sampler_from_handle(
pDescriptorInfo->data.pCombinedImageSampler->sampler))) {
memcpy(pDescriptor + desc_offset + ANV_SURFACE_STATE_SIZE,
sampler->state[i], ANV_SAMPLER_STATE_SIZE);
sampler->state.state[i], ANV_SAMPLER_STATE_SIZE);
} else {
memset(pDescriptor + desc_offset + ANV_SURFACE_STATE_SIZE,
0, ANV_SAMPLER_STATE_SIZE);

View file

@ -508,6 +508,11 @@ genX(cmd_buffer_flush_push_descriptors)(struct anv_cmd_buffer *cmd_buffer,
return push_buffer_dirty | push_descriptor_dirty;
}
void genX(emit_sampler_state)(const struct anv_device *device,
const struct vk_sampler_state *vk_state,
uint32_t border_color_offset,
struct anv_sampler_state *state);
void genX(emit_embedded_sampler)(struct anv_device *device,
struct anv_embedded_sampler *sampler,
struct anv_pipeline_embedded_sampler_binding *binding);

View file

@ -6660,9 +6660,7 @@ struct gfx8_border_color {
extern const struct gfx8_border_color anv_default_border_colors[];
struct anv_sampler {
struct vk_sampler vk;
struct anv_sampler_state {
/* Hashing key for embedded samplers */
struct anv_embedded_sampler_key embedded_key;
@ -6670,6 +6668,12 @@ struct anv_sampler {
/* Packed SAMPLER_STATE without the border color pointer. */
uint32_t state_no_bc[3][4];
uint32_t n_planes;
};
struct anv_sampler {
struct vk_sampler vk;
struct anv_sampler_state state;
/* Blob of sampler state data which is guaranteed to be 32-byte aligned
* and with a 32-byte stride for use as bindless samplers.

View file

@ -4,6 +4,8 @@
#include "anv_private.h"
#include "genxml/genX_bits.h"
VkResult anv_GetSamplerOpaqueCaptureDescriptorDataEXT(
VkDevice _device,
const VkSamplerCaptureDescriptorDataInfoEXT* pInfo,
@ -24,6 +26,115 @@ VkResult anv_GetSamplerOpaqueCaptureDescriptorDataEXT(
return VK_SUCCESS;
}
static VkResult
border_color_load(struct anv_device *device,
struct anv_sampler *sampler,
const VkSamplerCreateInfo* pCreateInfo,
uint32_t *ret_border_color_offset)
{
uint32_t border_color_stride = 64;
uint32_t border_color_offset;
void *border_color_ptr;
if (sampler->vk.border_color <= VK_BORDER_COLOR_INT_OPAQUE_WHITE) {
border_color_offset = device->border_colors.offset +
pCreateInfo->borderColor *
border_color_stride;
border_color_ptr = device->border_colors.map +
pCreateInfo->borderColor * border_color_stride;
} else {
assert(vk_border_color_is_custom(sampler->vk.border_color));
if (pCreateInfo->flags & VK_SAMPLER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT) {
const VkOpaqueCaptureDescriptorDataCreateInfoEXT *opaque_info =
vk_find_struct_const(pCreateInfo->pNext,
OPAQUE_CAPTURE_DESCRIPTOR_DATA_CREATE_INFO_EXT);
if (opaque_info) {
uint32_t alloc_idx = *((const uint32_t *)opaque_info->opaqueCaptureDescriptorData);
sampler->custom_border_color_state =
anv_state_reserved_array_pool_alloc_index(&device->custom_border_colors, alloc_idx);
} else {
sampler->custom_border_color_state =
anv_state_reserved_array_pool_alloc(&device->custom_border_colors, true);
}
} else {
sampler->custom_border_color_state =
anv_state_reserved_array_pool_alloc(&device->custom_border_colors, false);
}
if (sampler->custom_border_color_state.alloc_size == 0)
return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
border_color_offset = sampler->custom_border_color_state.offset;
border_color_ptr = sampler->custom_border_color_state.map;
union isl_color_value color = { .u32 = {
sampler->vk.border_color_value.uint32[0],
sampler->vk.border_color_value.uint32[1],
sampler->vk.border_color_value.uint32[2],
sampler->vk.border_color_value.uint32[3],
} };
const struct anv_format *format_desc =
sampler->vk.format != VK_FORMAT_UNDEFINED ?
anv_get_format(device->physical, sampler->vk.format) : NULL;
if (format_desc && format_desc->n_planes == 1 &&
!isl_swizzle_is_identity(format_desc->planes[0].swizzle)) {
const struct anv_format_plane *fmt_plane = &format_desc->planes[0];
assert(!isl_format_has_int_channel(fmt_plane->isl_format));
color = isl_color_value_swizzle(color, fmt_plane->swizzle, true);
}
memcpy(border_color_ptr, color.u32, sizeof(color));
}
*ret_border_color_offset = border_color_offset;
return VK_SUCCESS;
}
VkResult anv_CreateSampler(
VkDevice _device,
const VkSamplerCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSampler* pSampler)
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_sampler *sampler;
sampler = vk_sampler_create(&device->vk, pCreateInfo,
pAllocator, sizeof(*sampler));
if (!sampler)
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
uint32_t border_color_offset = 0;
VkResult result = border_color_load(device, sampler, pCreateInfo, &border_color_offset);
if (result != VK_SUCCESS)
return result;
struct vk_sampler_state vk_state;
vk_sampler_state_init(&vk_state, pCreateInfo);
anv_genX(device->info, emit_sampler_state)(device, &vk_state,
border_color_offset,
&sampler->state);
/* If we have bindless, allocate enough samplers. We allocate 32 bytes
* for each sampler instead of 16 bytes because we want all bindless
* samplers to be 32-byte aligned so we don't have to use indirect
* sampler messages on them.
*/
sampler->bindless_state =
anv_state_pool_alloc(&device->dynamic_state_pool,
sampler->state.n_planes * 32, 32);
if (sampler->bindless_state.map) {
memcpy(sampler->bindless_state.map, sampler->state.state,
sampler->state.n_planes * SAMPLER_STATE_length(device->info) * 4);
}
*pSampler = anv_sampler_to_handle(sampler);
return VK_SUCCESS;
}
void anv_DestroySampler(
VkDevice _device,
VkSampler _sampler,

View file

@ -2863,8 +2863,9 @@ emit_samplers(struct anv_cmd_buffer *cmd_buffer,
if (sampler == NULL)
continue;
memcpy(state->map + (s * 16), sampler->state[binding->plane],
sizeof(sampler->state[0]));
memcpy(state->map + (s * 16),
sampler->state.state[binding->plane],
sizeof(sampler->state.state[0]));
}
return VK_SUCCESS;

View file

@ -1327,121 +1327,39 @@ static const uint32_t vk_to_intel_sampler_reduction_mode[] = {
[VK_SAMPLER_REDUCTION_MODE_MAX] = MAXIMUM,
};
static VkResult
border_color_load(struct anv_device *device,
struct anv_sampler *sampler,
const VkSamplerCreateInfo* pCreateInfo,
uint32_t *ret_border_color_offset)
void
genX(emit_sampler_state)(const struct anv_device *device,
const struct vk_sampler_state *vk_state,
uint32_t border_color_offset,
struct anv_sampler_state *state)
{
uint32_t border_color_stride = 64;
uint32_t border_color_offset;
void *border_color_ptr;
if (sampler->vk.border_color <= VK_BORDER_COLOR_INT_OPAQUE_WHITE) {
border_color_offset = device->border_colors.offset +
pCreateInfo->borderColor *
border_color_stride;
border_color_ptr = device->border_colors.map +
pCreateInfo->borderColor * border_color_stride;
} else {
assert(vk_border_color_is_custom(sampler->vk.border_color));
if (pCreateInfo->flags & VK_SAMPLER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT) {
const VkOpaqueCaptureDescriptorDataCreateInfoEXT *opaque_info =
vk_find_struct_const(pCreateInfo->pNext,
OPAQUE_CAPTURE_DESCRIPTOR_DATA_CREATE_INFO_EXT);
if (opaque_info) {
uint32_t alloc_idx = *((const uint32_t *)opaque_info->opaqueCaptureDescriptorData);
sampler->custom_border_color_state =
anv_state_reserved_array_pool_alloc_index(&device->custom_border_colors, alloc_idx);
} else {
sampler->custom_border_color_state =
anv_state_reserved_array_pool_alloc(&device->custom_border_colors, true);
}
} else {
sampler->custom_border_color_state =
anv_state_reserved_array_pool_alloc(&device->custom_border_colors, false);
}
if (sampler->custom_border_color_state.alloc_size == 0)
return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
border_color_offset = sampler->custom_border_color_state.offset;
border_color_ptr = sampler->custom_border_color_state.map;
union isl_color_value color = { .u32 = {
sampler->vk.border_color_value.uint32[0],
sampler->vk.border_color_value.uint32[1],
sampler->vk.border_color_value.uint32[2],
sampler->vk.border_color_value.uint32[3],
} };
const struct anv_format *format_desc =
sampler->vk.format != VK_FORMAT_UNDEFINED ?
anv_get_format(device->physical, sampler->vk.format) : NULL;
if (format_desc && format_desc->n_planes == 1 &&
!isl_swizzle_is_identity(format_desc->planes[0].swizzle)) {
const struct anv_format_plane *fmt_plane = &format_desc->planes[0];
assert(!isl_format_has_int_channel(fmt_plane->isl_format));
color = isl_color_value_swizzle(color, fmt_plane->swizzle, true);
}
memcpy(border_color_ptr, color.u32, sizeof(color));
}
*ret_border_color_offset = border_color_offset;
return VK_SUCCESS;
}
VkResult genX(CreateSampler)(
VkDevice _device,
const VkSamplerCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSampler* pSampler)
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_sampler *sampler;
sampler = vk_sampler_create(&device->vk, pCreateInfo,
pAllocator, sizeof(*sampler));
if (!sampler)
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
const bool seamless_cube =
!(vk_state->flags & VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT);
const struct vk_format_ycbcr_info *ycbcr_info =
sampler->vk.format != VK_FORMAT_UNDEFINED ?
vk_format_get_ycbcr_info(sampler->vk.format) : NULL;
assert((ycbcr_info == NULL) == (sampler->vk.ycbcr_conversion == NULL));
vk_state->has_ycbcr_conversion ?
vk_format_get_ycbcr_info(vk_state->format) : NULL;
sampler->n_planes = ycbcr_info ? ycbcr_info->n_planes : 1;
state->n_planes = ycbcr_info ? ycbcr_info->n_planes : 1;
uint32_t border_color_offset = 0;
VkResult result = border_color_load(device, sampler, pCreateInfo, &border_color_offset);
if (result != VK_SUCCESS)
return result;
const bool seamless_cube =
!(pCreateInfo->flags & VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT);
for (unsigned p = 0; p < sampler->n_planes; p++) {
for (unsigned p = 0; p < state->n_planes; p++) {
const bool plane_has_chroma =
ycbcr_info && ycbcr_info->planes[p].has_chroma;
const VkFilter min_filter =
plane_has_chroma ? sampler->vk.ycbcr_conversion->state.chroma_filter :
pCreateInfo->minFilter;
const VkFilter mag_filter =
plane_has_chroma ? sampler->vk.ycbcr_conversion->state.chroma_filter :
pCreateInfo->magFilter;
const VkFilter min_filter = plane_has_chroma ?
vk_state->ycbcr_conversion.chroma_filter : vk_state->min_filter;
const VkFilter mag_filter = plane_has_chroma ?
vk_state->ycbcr_conversion.chroma_filter : vk_state->mag_filter;
const bool force_addr_rounding =
device->physical->instance->force_filter_addr_rounding;
device->physical->instance->force_filter_addr_rounding;
const bool enable_min_filter_addr_rounding =
force_addr_rounding || min_filter != VK_FILTER_NEAREST;
force_addr_rounding || min_filter != VK_FILTER_NEAREST;
const bool enable_mag_filter_addr_rounding =
force_addr_rounding || mag_filter != VK_FILTER_NEAREST;
force_addr_rounding || mag_filter != VK_FILTER_NEAREST;
/* From Broadwell PRM, SAMPLER_STATE:
* "Mip Mode Filter must be set to MIPFILTER_NONE for Planar YUV surfaces."
*/
enum isl_format plane0_isl_format = sampler->vk.ycbcr_conversion ?
anv_get_format(device->physical, sampler->vk.format)->planes[0].isl_format :
enum isl_format plane0_isl_format = ycbcr_info ?
anv_get_format(device->physical, vk_state->format)->planes[0].isl_format :
ISL_FORMAT_UNSUPPORTED;
const bool isl_format_is_planar_yuv =
plane0_isl_format != ISL_FORMAT_UNSUPPORTED &&
@ -1450,7 +1368,7 @@ VkResult genX(CreateSampler)(
const uint32_t mip_filter_mode =
isl_format_is_planar_yuv ?
MIPFILTER_NONE : vk_to_intel_mipmap_mode[pCreateInfo->mipmapMode];
MIPFILTER_NONE : vk_to_intel_mipmap_mode[vk_state->mipmap_mode];
struct GENX(SAMPLER_STATE) sampler_state = {
.SamplerDisable = false,
@ -1464,24 +1382,23 @@ VkResult genX(CreateSampler)(
.LODPreClampMode = CLAMP_MODE_OGL,
.MipModeFilter = mip_filter_mode,
.MagModeFilter = vk_to_intel_tex_filter(mag_filter, pCreateInfo->anisotropyEnable),
.MinModeFilter = vk_to_intel_tex_filter(min_filter, pCreateInfo->anisotropyEnable),
.TextureLODBias = CLAMP(pCreateInfo->mipLodBias, -16, 15.996),
.AnisotropicAlgorithm =
pCreateInfo->anisotropyEnable ? EWAApproximation : LEGACY,
.MinLOD = CLAMP(pCreateInfo->minLod, 0, 14),
.MaxLOD = CLAMP(pCreateInfo->maxLod, 0, 14),
.MagModeFilter = vk_to_intel_tex_filter(mag_filter, vk_state->anisotropy_enable),
.MinModeFilter = vk_to_intel_tex_filter(min_filter, vk_state->anisotropy_enable),
.TextureLODBias = CLAMP(vk_state->mip_lod_bias, -16, 15.996),
.AnisotropicAlgorithm = vk_state->anisotropy_enable ? EWAApproximation : LEGACY,
.MinLOD = CLAMP(vk_state->min_lod, 0, 14),
.MaxLOD = CLAMP(vk_state->max_lod, 0, 14),
.ChromaKeyEnable = 0,
.ChromaKeyIndex = 0,
.ChromaKeyMode = 0,
.ShadowFunction =
vk_to_intel_shadow_compare_op[pCreateInfo->compareEnable ?
pCreateInfo->compareOp : VK_COMPARE_OP_NEVER],
vk_to_intel_shadow_compare_op[vk_state->compare_enable ?
vk_state->compare_op : VK_COMPARE_OP_NEVER],
.CubeSurfaceControlMode = seamless_cube ? OVERRIDE : PROGRAMMED,
.LODClampMagnificationMode = MIPNONE,
.MaximumAnisotropy = vk_to_intel_max_anisotropy(pCreateInfo->maxAnisotropy),
.MaximumAnisotropy = vk_to_intel_max_anisotropy(vk_state->max_anisotropy),
.RAddressMinFilterRoundingEnable = enable_min_filter_addr_rounding,
.RAddressMagFilterRoundingEnable = enable_mag_filter_addr_rounding,
.VAddressMinFilterRoundingEnable = enable_min_filter_addr_rounding,
@ -1489,53 +1406,36 @@ VkResult genX(CreateSampler)(
.UAddressMinFilterRoundingEnable = enable_min_filter_addr_rounding,
.UAddressMagFilterRoundingEnable = enable_mag_filter_addr_rounding,
.TrilinearFilterQuality = 0,
.NonnormalizedCoordinateEnable = pCreateInfo->unnormalizedCoordinates,
.TCXAddressControlMode = vk_to_intel_tex_address[pCreateInfo->addressModeU],
.TCYAddressControlMode = vk_to_intel_tex_address[pCreateInfo->addressModeV],
.TCZAddressControlMode = vk_to_intel_tex_address[pCreateInfo->addressModeW],
.NonnormalizedCoordinateEnable = vk_state->unnormalized_coordinates,
.TCXAddressControlMode = vk_to_intel_tex_address[vk_state->address_mode_u],
.TCYAddressControlMode = vk_to_intel_tex_address[vk_state->address_mode_v],
.TCZAddressControlMode = vk_to_intel_tex_address[vk_state->address_mode_w],
.ReductionType =
vk_to_intel_sampler_reduction_mode[sampler->vk.reduction_mode],
vk_to_intel_sampler_reduction_mode[vk_state->reduction_mode],
.ReductionTypeEnable =
sampler->vk.reduction_mode != VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE,
vk_state->reduction_mode != VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE,
};
/* Pack a version of the SAMPLER_STATE without the border color. We'll
* use it to store into the shader cache and also for hashing.
*/
GENX(SAMPLER_STATE_pack)(NULL, sampler->state_no_bc[p], &sampler_state);
GENX(SAMPLER_STATE_pack)(NULL, state->state_no_bc[p], &sampler_state);
/* Put border color after the hashing, we don't want the allocation
* order of border colors to influence the hash. We just need th
* parameters to be hashed.
*/
sampler_state.BorderColorPointer = border_color_offset;
GENX(SAMPLER_STATE_pack)(NULL, sampler->state[p], &sampler_state);
GENX(SAMPLER_STATE_pack)(NULL, state->state[p], &sampler_state);
}
memcpy(sampler->embedded_key.sampler,
sampler->state_no_bc[0],
sizeof(sampler->embedded_key.sampler));
memcpy(sampler->embedded_key.color,
sampler->vk.border_color_value.uint32,
sizeof(sampler->embedded_key.color));
/* If we have bindless, allocate enough samplers. We allocate 32 bytes
* for each sampler instead of 16 bytes because we want all bindless
* samplers to be 32-byte aligned so we don't have to use indirect
* sampler messages on them.
*/
sampler->bindless_state =
anv_state_pool_alloc(&device->dynamic_state_pool,
sampler->n_planes * 32, 32);
if (sampler->bindless_state.map) {
memcpy(sampler->bindless_state.map, sampler->state,
sampler->n_planes * GENX(SAMPLER_STATE_length) * 4);
}
*pSampler = anv_sampler_to_handle(sampler);
return VK_SUCCESS;
memcpy(state->embedded_key.sampler,
state->state_no_bc[0],
sizeof(state->embedded_key.sampler));
memcpy(state->embedded_key.color,
vk_state->border_color_value.uint32,
sizeof(state->embedded_key.color));
}
void