Commit 7f7da82d authored by Bas Nieuwenhuizen's avatar Bas Nieuwenhuizen Committed by Marge Bot
Browse files

radv: Add image layout with drm format modifiers.



Half of it is passing the right modifier to ac_surface, the other half
is applying the offset/strides.
Reviewed-By: chadversary's avatarChad Versace <chad@kiwitree.net>
Part-of: <mesa/mesa!7667>
parent 1fbb6ff5
......@@ -5323,7 +5323,8 @@ static VkResult radv_alloc_memory(struct radv_device *device,
/* This gives a basic ability to import radeonsi images
* that don't have DCC. This is not guaranteed by any
* spec and can be removed after we support modifiers. */
result = radv_image_create_layout(device, create_info, mem->image);
result = radv_image_create_layout(device, create_info, NULL,
mem->image);
if (result != VK_SUCCESS) {
device->ws->buffer_destroy(mem->bo);
goto fail;
......
......@@ -1349,6 +1349,7 @@ radv_image_reset_layout(struct radv_image *image)
VkResult
radv_image_create_layout(struct radv_device *device,
struct radv_image_create_info create_info,
const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *mod_info,
struct radv_image *image)
{
/* Clear the pCreateInfo pointer so we catch issues in the delayed case when we test in the
......@@ -1360,11 +1361,14 @@ radv_image_create_layout(struct radv_device *device,
if (result != VK_SUCCESS)
return result;
assert(!mod_info || mod_info->drmFormatModifierPlaneCount == image->plane_count);
radv_image_reset_layout(image);
for (unsigned plane = 0; plane < image->plane_count; ++plane) {
struct ac_surf_info info = image_info;
uint64_t offset;
unsigned stride;
if (plane) {
const struct vk_format_description *desc = vk_format_description(image->vk_format);
......@@ -1383,15 +1387,42 @@ radv_image_create_layout(struct radv_device *device,
device->ws->surface_init(device->ws, &info, &image->planes[plane].surface);
if (!create_info.no_metadata_planes && image->plane_count == 1)
if (!create_info.no_metadata_planes && image->plane_count == 1 &&
!mod_info)
radv_image_alloc_single_sample_cmask(device, image, &image->planes[plane].surface);
offset = align(image->size, image->planes[plane].surface.alignment);
ac_surface_override_offset_stride(&device->physical_device->rad_info,
&image->planes[plane].surface,
image->info.levels,
offset,
0);
if (mod_info) {
if (mod_info->pPlaneLayouts[plane].rowPitch % image->planes[plane].surface.bpe ||
!mod_info->pPlaneLayouts[plane].rowPitch)
return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT;
offset = mod_info->pPlaneLayouts[plane].offset;
stride = mod_info->pPlaneLayouts[plane].rowPitch / image->planes[plane].surface.bpe;
} else {
offset = align(image->size, image->planes[plane].surface.alignment);
stride = 0; /* 0 means no override */
}
if (!ac_surface_override_offset_stride(&device->physical_device->rad_info,
&image->planes[plane].surface,
image->info.levels,
offset,
stride))
return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT;
/* Validate DCC offsets in modifier layout. */
if (image->plane_count == 1 && mod_info) {
unsigned mem_planes = ac_surface_get_nplanes(&image->planes[plane].surface);
if (mod_info->drmFormatModifierPlaneCount != mem_planes)
return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT;
for (unsigned i = 1; i < mem_planes; ++i) {
if (ac_surface_get_plane_offset(device->physical_device->rad_info.chip_class,
&image->planes[plane].surface, i, 0) !=
mod_info->pPlaneLayouts[i].offset)
return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT;
}
}
image->size = MAX2(image->size, offset + image->planes[plane].surface.total_size);
image->alignment = MAX2(image->alignment, image->planes[plane].surface.alignment);
......@@ -1405,6 +1436,8 @@ radv_image_create_layout(struct radv_device *device,
radv_image_alloc_values(device, image);
assert(image->planes[0].surface.surf_size);
assert(ac_modifier_has_dcc(image->planes[0].surface.modifier) ==
radv_image_has_dcc(image));
return VK_SUCCESS;
}
......@@ -1482,6 +1515,46 @@ radv_image_can_fast_clear(const struct radv_device *device,
return true;
}
static uint64_t
radv_select_modifier(const struct radv_device *dev,
VkFormat format,
const struct VkImageDrmFormatModifierListCreateInfoEXT *mod_list)
{
const struct radv_physical_device *pdev = dev->physical_device;
unsigned mod_count;
assert(mod_list->drmFormatModifierCount);
/* We can allow everything here as it does not affect order and the application
* is only allowed to specify modifiers that we support. */
const struct ac_modifier_options modifier_options = {
.dcc = true,
.dcc_retile = true,
};
ac_get_supported_modifiers(&pdev->rad_info, &modifier_options,
vk_format_to_pipe_format(format), &mod_count, NULL);
uint64_t *mods = calloc(mod_count, sizeof(*mods));
/* If allocations fail, fall back to a dumber solution. */
if (!mods)
return mod_list->pDrmFormatModifiers[0];
ac_get_supported_modifiers(&pdev->rad_info, &modifier_options,
vk_format_to_pipe_format(format), &mod_count, mods);
for (unsigned i = 0; i < mod_count; ++i) {
for (uint32_t j = 0; j < mod_list->drmFormatModifierCount; ++j) {
if (mods[i] == mod_list->pDrmFormatModifiers[j]) {
free(mods);
return mod_list->pDrmFormatModifiers[j];
}
}
}
unreachable("App specified an invalid modifier");
}
VkResult
radv_image_create(VkDevice _device,
const struct radv_image_create_info *create_info,
......@@ -1490,9 +1563,14 @@ radv_image_create(VkDevice _device,
{
RADV_FROM_HANDLE(radv_device, device, _device);
const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
uint64_t modifier = DRM_FORMAT_MOD_INVALID;
struct radv_image *image = NULL;
VkFormat format = radv_select_android_external_format(pCreateInfo->pNext,
pCreateInfo->format);
const struct VkImageDrmFormatModifierListCreateInfoEXT *mod_list =
vk_find_struct_const(pCreateInfo->pNext, IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *explicit_mod =
vk_find_struct_const(pCreateInfo->pNext, IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
const unsigned plane_count = vk_format_get_plane_count(format);
......@@ -1544,14 +1622,20 @@ radv_image_create(VkDevice _device,
image->shareable = external_info;
if (!vk_format_is_depth_or_stencil(format) && !image->shareable &&
!(image->flags & VK_IMAGE_CREATE_SPARSE_ALIASED_BIT)) {
!(image->flags & VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) &&
pCreateInfo->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
image->info.surf_index = &device->image_mrt_offset_counter;
}
if (mod_list)
modifier = radv_select_modifier(device, format, mod_list);
else if (explicit_mod)
modifier = explicit_mod->drmFormatModifier;
for (unsigned plane = 0; plane < image->plane_count; ++plane) {
image->planes[plane].surface.flags =
radv_get_surface_flags(device, image, plane, pCreateInfo, format);
image->planes[plane].surface.modifier = DRM_FORMAT_MOD_INVALID;
image->planes[plane].surface.modifier = modifier;
}
bool delay_layout = external_info &&
......@@ -1563,7 +1647,7 @@ radv_image_create(VkDevice _device,
return VK_SUCCESS;
}
ASSERTED VkResult result = radv_image_create_layout(device, *create_info, image);
ASSERTED VkResult result = radv_image_create_layout(device, *create_info, explicit_mod, image);
assert(result == VK_SUCCESS);
if (image->flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) {
......
......@@ -2175,6 +2175,7 @@ struct radv_image_create_info {
VkResult
radv_image_create_layout(struct radv_device *device,
struct radv_image_create_info create_info,
const struct VkImageDrmFormatModifierExplicitCreateInfoEXT *mod_info,
struct radv_image *image);
VkResult radv_image_create(VkDevice _device,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment