From 9231204026210e84ddb03ee4056c8c643a7ae287 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Tue, 12 Aug 2025 15:49:48 +0300 Subject: [PATCH] anv: implement EXT_descriptor_heap entry points Signed-off-by: Lionel Landwerlin Acked-by: Alyssa Rosenzweig Part-of: --- src/intel/vulkan/anv_allocator.c | 11 +- src/intel/vulkan/anv_descriptor_set.c | 247 +++++++++++++++++++++++++ src/intel/vulkan/anv_image.c | 41 ++++ src/intel/vulkan/anv_physical_device.c | 31 ++++ src/intel/vulkan/anv_private.h | 2 + src/intel/vulkan/anv_sampler.c | 55 ++++++ 6 files changed, 386 insertions(+), 1 deletion(-) diff --git a/src/intel/vulkan/anv_allocator.c b/src/intel/vulkan/anv_allocator.c index 6aeb1fc835a..fd33eaf88a7 100644 --- a/src/intel/vulkan/anv_allocator.c +++ b/src/intel/vulkan/anv_allocator.c @@ -1234,7 +1234,16 @@ anv_state_reserved_array_pool_free(struct anv_state_reserved_array_pool *pool, simple_mtx_lock(&pool->mutex); BITSET_SET(pool->states, idx); simple_mtx_unlock(&pool->mutex); - } +} + +void +anv_state_reserved_array_pool_index_free(struct anv_state_reserved_array_pool *pool, + uint32_t index) +{ + simple_mtx_lock(&pool->mutex); + BITSET_SET(pool->states, index); + simple_mtx_unlock(&pool->mutex); +} void anv_bo_pool_init(struct anv_bo_pool *pool, struct anv_device *device, diff --git a/src/intel/vulkan/anv_descriptor_set.c b/src/intel/vulkan/anv_descriptor_set.c index 0367f1bdb80..4118647a95f 100644 --- a/src/intel/vulkan/anv_descriptor_set.c +++ b/src/intel/vulkan/anv_descriptor_set.c @@ -2919,3 +2919,250 @@ void anv_GetDescriptorEXT( UNREACHABLE("Invalid descriptor type"); } } + +VkResult anv_WriteSamplerDescriptorsEXT( + VkDevice _device, + uint32_t samplerCount, + const VkSamplerCreateInfo* pSamplers, + const VkHostAddressRangeEXT* pDescriptors) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + + const uint32_t border_color_stride = 64; + for (uint32_t i = 0; i < samplerCount; i++) { + struct vk_sampler_state vk_state; + vk_sampler_state_init(&vk_state, &pSamplers[i]); + + const VkSamplerCustomBorderColorIndexCreateInfoEXT *color_info = + vk_find_struct_const(pSamplers[i].pNext, + SAMPLER_CUSTOM_BORDER_COLOR_INDEX_CREATE_INFO_EXT); + const uint32_t border_color_offset = + vk_state.border_color <= VK_BORDER_COLOR_INT_OPAQUE_WHITE ? + (device->border_colors.offset + vk_state.border_color * border_color_stride) : + (device->custom_border_colors.state.offset + color_info->index * border_color_stride); + + struct anv_sampler_state state; + anv_genX(device->info, emit_sampler_state)(device, &vk_state, + border_color_offset, + &state); + + memcpy(pDescriptors[i].address, state.state[0], ANV_SAMPLER_STATE_SIZE); + } + + return VK_SUCCESS; +} + +static bool +texel_info_is_null(const VkTexelBufferDescriptorInfoEXT *texel_info) +{ + return texel_info == NULL || + texel_info->addressRange.size == 0 || + texel_info->addressRange.address == 0; +} + +static bool +address_range_is_null(const VkDeviceAddressRangeEXT *addr) +{ + return addr == NULL || addr->size == 0 || addr->address == 0; +} + +static enum isl_channel_select +remap_swizzle(VkComponentSwizzle swizzle, + struct isl_swizzle format_swizzle) +{ + switch (swizzle) { + case VK_COMPONENT_SWIZZLE_ZERO: return ISL_CHANNEL_SELECT_ZERO; + case VK_COMPONENT_SWIZZLE_ONE: return ISL_CHANNEL_SELECT_ONE; + case VK_COMPONENT_SWIZZLE_R: return format_swizzle.r; + case VK_COMPONENT_SWIZZLE_G: return format_swizzle.g; + case VK_COMPONENT_SWIZZLE_B: return format_swizzle.b; + case VK_COMPONENT_SWIZZLE_A: return format_swizzle.a; + default: + UNREACHABLE("Invalid swizzle"); + } +} + +VkResult anv_WriteResourceDescriptorsEXT( + VkDevice _device, + uint32_t resourceCount, + const VkResourceDescriptorInfoEXT* pResources, + const VkHostAddressRangeEXT* pDescriptors) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + + for (uint32_t i = 0; i < resourceCount; i++) { + const VkResourceDescriptorInfoEXT *res = &pResources[i]; + const VkHostAddressRangeEXT *out = &pDescriptors[i]; + + switch (res->type) { + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: { + const VkImageDescriptorInfoEXT *img_info = + res->data.pImage; + if (img_info) { + ANV_FROM_HANDLE(anv_image, image, img_info->pView->image); + + struct vk_image_view vk_view; + vk_image_view_init(&device->vk, &vk_view, img_info->pView); + + VkFormat view_format = vk_view.view_format; + if (anv_is_compressed_format_emulated(device->physical, + view_format)) { + assert(image->emu_plane_format != VK_FORMAT_UNDEFINED); + view_format = anv_get_compressed_format_emulation( + device->physical, view_format); + } + + anv_foreach_image_aspect_bit(iaspect_bit, image, vk_view.aspects) { + VkImageAspectFlags aspect = 1u << iaspect_bit; + + const uint32_t vplane = anv_aspect_to_plane(vk_view.aspects, aspect); + + const struct anv_format_plane format = anv_get_format_plane( + device->physical, view_format, vplane, image->vk.tiling); + + struct isl_view isl_view = { + .format = format.isl_format, + .base_level = vk_view.base_mip_level, + .levels = vk_view.level_count, + .base_array_layer = vk_view.base_array_layer, + .array_len = vk_view.layer_count, + .min_lod_clamp = vk_view.min_lod, + .swizzle = { + .r = remap_swizzle(vk_view.swizzle.r, format.swizzle), + .g = remap_swizzle(vk_view.swizzle.g, format.swizzle), + .b = remap_swizzle(vk_view.swizzle.b, format.swizzle), + .a = remap_swizzle(vk_view.swizzle.a, format.swizzle), + }, + }; + + if (vk_view.view_type == VK_IMAGE_VIEW_TYPE_3D) { + isl_view.base_array_layer = 0; + isl_view.array_len = vk_view.extent.depth; + } + + if (vk_view.view_type == VK_IMAGE_VIEW_TYPE_CUBE || + vk_view.view_type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) { + isl_view.usage = ISL_SURF_USAGE_CUBE_BIT; + } else { + isl_view.usage = 0; + } + + const bool is_storage = + res->type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + const bool read_only_layout = + img_info->layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL || + img_info->layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL || + img_info->layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL || + img_info->layout == VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL; + + enum isl_aux_usage aux_usage = + anv_layout_to_aux_usage(device->info, image, aspect, + is_storage ? + VK_IMAGE_USAGE_STORAGE_BIT : + VK_IMAGE_USAGE_SAMPLED_BIT, + img_info->layout, + VK_QUEUE_GRAPHICS_BIT | + VK_QUEUE_COMPUTE_BIT); + + struct anv_surface_state state = {}; + anv_image_fill_surface_state(device, image, aspect, + &isl_view, + is_storage ? + ISL_SURF_USAGE_STORAGE_BIT : + ISL_SURF_USAGE_TEXTURE_BIT, + aux_usage, NULL, + read_only_layout ? + ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL : 0, + &state); + + memcpy(out->address + vplane * ANV_SURFACE_STATE_SIZE, + state.state_data.data, ANV_SURFACE_STATE_SIZE); + } + } else { + memcpy(out->address, device->host_null_surface_state, + ANV_SURFACE_STATE_SIZE); + } + break; + } + + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: { + const VkTexelBufferDescriptorInfoEXT *texel_info = + res->data.pTexelBuffer; + + if (!texel_info_is_null(texel_info)) { + struct anv_format_plane format = + anv_get_format_plane(device->physical, + texel_info->format, + 0, VK_IMAGE_TILING_LINEAR); + const uint32_t format_bs = + isl_format_get_layout(format.isl_format)->bpb / 8; + + anv_fill_buffer_surface_state( + device, out->address, + format.isl_format, format.swizzle, + res->type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER ? + ISL_SURF_USAGE_STORAGE_BIT : ISL_SURF_USAGE_TEXTURE_BIT, + anv_address_from_u64(texel_info->addressRange.address), + align_down_npot_u64(texel_info->addressRange.size, format_bs), + format_bs); + } else { + memcpy(out->address, device->host_null_surface_state, + ANV_SURFACE_STATE_SIZE); + } + break; + } + + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: { + const VkDeviceAddressRangeEXT *addr_info = res->data.pAddressRange; + + if (!address_range_is_null(addr_info)) { + VkDeviceSize range = addr_info->size; + + /* We report a bounds checking alignment of 32B for the sake of + * block messages which read an entire register worth at a time. + */ + if (res->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) + range = align64(range, ANV_UBO_ALIGNMENT); + + isl_surf_usage_flags_t usage = + res->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ? + ISL_SURF_USAGE_CONSTANT_BUFFER_BIT : + ISL_SURF_USAGE_STORAGE_BIT; + + enum isl_format format = + anv_isl_format_for_descriptor_type(device, res->type); + + isl_buffer_fill_state(&device->isl_dev, out->address, + .address = addr_info->address, + .mocs = isl_mocs(&device->isl_dev, usage, false), + .size_B = range, + .format = format, + .swizzle = ISL_SWIZZLE_IDENTITY, + .stride_B = 1, + .usage = usage); + } else { + memcpy(out->address, device->host_null_surface_state, + ANV_SURFACE_STATE_SIZE); + } + break; + } + + case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: { + const VkDeviceAddressRangeEXT *addr_info = res->data.pAddressRange; + uint64_t desc_data = addr_info ? addr_info->address : 0; + + memcpy(out->address, &desc_data, sizeof(desc_data)); + break; + } + + default: + UNREACHABLE("Invalid descriptor type"); + } + } + + return VK_SUCCESS; +} diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c index 07aa1c2d600..45e16754d62 100644 --- a/src/intel/vulkan/anv_image.c +++ b/src/intel/vulkan/anv_image.c @@ -1738,6 +1738,20 @@ anv_image_init_sparse_bindings(struct anv_image *image, explicit_addresses = opaque_info->opaqueCaptureDescriptorData; } + if (image->vk.create_flags & VK_IMAGE_CREATE_DESCRIPTOR_HEAP_CAPTURE_REPLAY_BIT_EXT) { + alloc_flags |= ANV_BO_ALLOC_FIXED_ADDRESS; + + const VkOpaqueCaptureDataCreateInfoEXT *opaque_info = + vk_find_struct_const(create_info->vk_info->pNext, + OPAQUE_CAPTURE_DATA_CREATE_INFO_EXT); + if (opaque_info) { + assert(opaque_info->pData[0].size == + sizeof(struct anv_image_opaque_capture_data)); + explicit_addresses = + (const struct anv_image_opaque_capture_data *)opaque_info->pData; + } + } + uint64_t total_size = 0; for (int i = 0; i < ANV_IMAGE_MEMORY_BINDING_END; i++) { struct anv_image_binding *b = &image->bindings[i]; @@ -4294,3 +4308,30 @@ anv_layout_has_untracked_aux_writes(const struct intel_device_info * const devin return true; } + +VkResult anv_GetImageOpaqueCaptureDataEXT( + VkDevice _device, + uint32_t imageCount, + const VkImage* pImages, + VkHostAddressRangeEXT* pDatas) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + + for (uint32_t i = 0; i < imageCount; i++) { + ANV_FROM_HANDLE(anv_image, image, pImages[i]); + + if (pDatas[i].size < sizeof(uint64_t)) + return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); + + if (anv_image_is_sparse(image) && + (image->vk.create_flags & VK_IMAGE_CREATE_DESCRIPTOR_HEAP_CAPTURE_REPLAY_BIT_EXT)) { + *((uint64_t *)pDatas[i].address) = anv_address_physical( + image->bindings[ANV_IMAGE_MEMORY_BINDING_MAIN].address); + } else { + *((uint64_t *)pDatas[i].address) = 0; + } + pDatas[i].size = sizeof(uint64_t); + } + + return VK_SUCCESS; +} diff --git a/src/intel/vulkan/anv_physical_device.c b/src/intel/vulkan/anv_physical_device.c index 5c0bafffe65..2e6d68e9661 100644 --- a/src/intel/vulkan/anv_physical_device.c +++ b/src/intel/vulkan/anv_physical_device.c @@ -3420,3 +3420,34 @@ VkResult anv_GetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV( /* TODO: When we enable flexible dimensions, fill this properly. */ return vk_outarray_status(&out); } + +VkDeviceSize anv_GetPhysicalDeviceDescriptorSizeEXT( + VkPhysicalDevice physicalDevice, + VkDescriptorType descriptorType) +{ + switch (descriptorType) { + case VK_DESCRIPTOR_TYPE_SAMPLER: + return ANV_SAMPLER_STATE_SIZE; + + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + return ANV_SURFACE_STATE_SIZE + + align(ANV_SAMPLER_STATE_SIZE, ANV_SURFACE_STATE_SIZE); + + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + return ANV_SURFACE_STATE_SIZE; + + case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: + return sizeof(uint64_t); + + default: + UNREACHABLE("invalid descriptor type"); + } +} diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index f7d7d89f3ba..421fb889623 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -945,6 +945,8 @@ uint32_t anv_state_reserved_array_pool_state_index(struct anv_state_reserved_arr struct anv_state state); void anv_state_reserved_array_pool_free(struct anv_state_reserved_array_pool *pool, struct anv_state state); +void anv_state_reserved_array_pool_index_free(struct anv_state_reserved_array_pool *pool, + uint32_t index); VkResult anv_state_table_init(struct anv_state_table *table, struct anv_device *device, diff --git a/src/intel/vulkan/anv_sampler.c b/src/intel/vulkan/anv_sampler.c index 46db9b42b9e..4e98c98283f 100644 --- a/src/intel/vulkan/anv_sampler.c +++ b/src/intel/vulkan/anv_sampler.c @@ -159,3 +159,58 @@ void anv_DestroySampler( vk_sampler_destroy(&device->vk, pAllocator, &sampler->vk); } + +VkResult anv_RegisterCustomBorderColorEXT( + VkDevice _device, + const VkSamplerCustomBorderColorCreateInfoEXT* pBorderColor, + VkBool32 requestIndex, + uint32_t* pIndex) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + + struct anv_state color_state = requestIndex ? + anv_state_reserved_array_pool_alloc_index( + &device->custom_border_colors, *pIndex) : + anv_state_reserved_array_pool_alloc( + &device->custom_border_colors, true); + + if (color_state.alloc_size == 0) + return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY); + + *pIndex = anv_state_reserved_array_pool_state_index( + &device->custom_border_colors, color_state); + + union isl_color_value color = { .u32 = { + pBorderColor->customBorderColor.uint32[0], + pBorderColor->customBorderColor.uint32[1], + pBorderColor->customBorderColor.uint32[2], + pBorderColor->customBorderColor.uint32[3], + } + }; + + const struct anv_format *format_desc = + pBorderColor->format != VK_FORMAT_UNDEFINED ? + anv_get_format(device->physical, pBorderColor->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(color_state.map, color.u32, sizeof(color)); + + return VK_SUCCESS; +} + +void anv_UnregisterCustomBorderColorEXT( + VkDevice _device, + uint32_t index) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + + anv_state_reserved_array_pool_index_free( + &device->custom_border_colors, index); +}