anv/image: Add 'offset' param to add_surface()

Will be used by VkImageDrmFormatModifierExplicitCreateInfoEXT.

Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/1466>
This commit is contained in:
Chad Versace
2021-02-22 16:41:02 -08:00
committed by Marge Bot
parent 13498cdd34
commit d526fcba0d

View File

@@ -36,6 +36,8 @@
#include "vk_format.h"
#define ANV_OFFSET_IMPLICIT UINT64_MAX
static const enum isl_surf_dim
vk_to_isl_surf_dim[] = {
[VK_IMAGE_TYPE_1D] = ISL_SURF_DIM_1D,
@@ -80,18 +82,26 @@ image_aspect_to_binding(struct anv_image *image, VkImageAspectFlags aspect)
}
/**
* Extend the memory binding's range by appending a new memory range with the
* given size and alignment. Return the appended range.
* Extend the memory binding's range by appending a new memory range with `size`
* and `alignment` at `offset`. Return the appended range.
*
* Offset is ignored if ANV_OFFSET_IMPLICIT.
*
* The given binding must not be ANV_IMAGE_MEMORY_BINDING_MAIN. The function
* converts to MAIN as needed.
*/
static struct anv_image_memory_range
image_binding_grow(struct anv_image *image,
static VkResult MUST_CHECK
image_binding_grow(const struct anv_device *device,
struct anv_image *image,
enum anv_image_memory_binding binding,
uint64_t offset,
uint64_t size,
uint32_t alignment)
uint32_t alignment,
struct anv_image_memory_range *out_range)
{
/* We overwrite 'offset' but need to remember if it was implicit. */
const bool has_implicit_offset = (offset == ANV_OFFSET_IMPLICIT);
assert(size > 0);
assert(util_is_power_of_two_or_zero(alignment));
@@ -106,6 +116,7 @@ image_binding_grow(struct anv_image *image,
binding = ANV_IMAGE_MEMORY_BINDING_MAIN;
break;
case ANV_IMAGE_MEMORY_BINDING_PRIVATE:
assert(offset == ANV_OFFSET_IMPLICIT);
break;
case ANV_IMAGE_MEMORY_BINDING_END:
unreachable("ANV_IMAGE_MEMORY_BINDING_END");
@@ -114,17 +125,55 @@ image_binding_grow(struct anv_image *image,
struct anv_image_memory_range *container =
&image->bindings[binding].memory_range;
struct anv_image_memory_range new = {
.binding = container->binding,
.offset = align_u64(container->offset + container->size, alignment),
if (has_implicit_offset) {
offset = align_u64(container->offset + container->size, alignment);
} else {
/* Offset must be validated because it comes from
* VkImageDrmFormatModifierExplicitCreateInfoEXT.
*/
if (unlikely(!anv_is_aligned(offset, alignment))) {
return vk_errorf(device, &device->vk.base,
VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
"VkImageDrmFormatModifierExplicitCreateInfoEXT::"
"pPlaneLayouts[]::offset is misaligned");
}
/* We require that surfaces be added in memory-order. This simplifies the
* layout validation required by
* VkImageDrmFormatModifierExplicitCreateInfoEXT,
*/
if (unlikely(offset < container->size)) {
return vk_errorf(device, &device->vk.base,
VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
"VkImageDrmFormatModifierExplicitCreateInfoEXT::"
"pPlaneLayouts[]::offset is too small");
}
}
if (__builtin_add_overflow(offset, size, &container->size)) {
if (has_implicit_offset) {
assert(!"overflow");
return vk_errorf(device, &device->vk.base,
VK_ERROR_UNKNOWN,
"internal error: overflow in %s", __func__);
} else {
return vk_errorf(device, &device->vk.base,
VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
"VkImageDrmFormatModifierExplicitCreateInfoEXT::"
"pPlaneLayouts[]::offset is too large");
}
}
container->alignment = MAX2(container->alignment, alignment);
*out_range = (struct anv_image_memory_range) {
.binding = binding,
.offset = offset,
.size = size,
.alignment = alignment,
};
container->size = new.offset + new.size;
container->alignment = MAX2(container->alignment, new.alignment);
return new;
return VK_SUCCESS;
}
/**
@@ -250,22 +299,24 @@ choose_isl_tiling_flags(const struct gen_device_info *devinfo,
}
/**
* Set the surface's anv_image_memory_range and add it to the given binding's
* memory range.
* Add the surface to the binding at the given offset.
*
* \see image_binding_grow()
*/
static void
add_surface(struct anv_image *image,
static VkResult MUST_CHECK
add_surface(struct anv_device *device,
struct anv_image *image,
struct anv_surface *surf,
enum anv_image_memory_binding binding,
struct anv_surface *surf)
uint64_t offset)
{
/* isl surface must be initialized */
assert(surf->isl.size_B > 0);
surf->memory_range = image_binding_grow(image, binding,
surf->isl.size_B,
surf->isl.alignment_B);
return image_binding_grow(device, image, binding, offset,
surf->isl.size_B,
surf->isl.alignment_B,
&surf->memory_range);
}
/**
@@ -401,7 +452,7 @@ anv_formats_ccs_e_compatible(const struct gen_device_info *devinfo,
* * For any blorp operations, we pass the address to the clear value into
* blorp and it knows to copy the clear color.
*/
static void
static VkResult MUST_CHECK
add_aux_state_tracking_buffer(struct anv_device *device,
struct anv_image *image,
uint32_t plane)
@@ -436,8 +487,9 @@ add_aux_state_tracking_buffer(struct anv_device *device,
/* We believe that 256B alignment may be sufficient, but we choose 4K due to
* lack of testing. And MI_LOAD/STORE operations require dword-alignment.
*/
image->planes[plane].fast_clear_memory_range =
image_binding_grow(image, binding, state_size, 4096);
return image_binding_grow(device, image, binding,
ANV_OFFSET_IMPLICIT, state_size, 4096,
&image->planes[plane].fast_clear_memory_range);
}
/**
@@ -456,6 +508,7 @@ add_aux_surface_if_supported(struct anv_device *device,
isl_surf_usage_flags_t isl_extra_usage_flags)
{
VkImageAspectFlags aspect = plane_format.aspect;
VkResult result;
bool ok;
/* The aux surface must not be already added. */
@@ -521,8 +574,9 @@ add_aux_surface_if_supported(struct anv_device *device,
image->planes[plane].aux_usage = ISL_AUX_USAGE_HIZ_CCS;
}
add_surface(image, ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
&image->planes[plane].aux_surface);
return add_surface(device, image, &image->planes[plane].aux_surface,
ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
ANV_OFFSET_IMPLICIT);
} else if (aspect == VK_IMAGE_ASPECT_STENCIL_BIT) {
if (INTEL_DEBUG & DEBUG_NO_RBC)
@@ -624,10 +678,13 @@ add_aux_surface_if_supported(struct anv_device *device,
!isl_drm_modifier_has_aux(image->drm_format_mod))
binding = ANV_IMAGE_MEMORY_BINDING_PRIVATE;
add_surface(image, binding, &image->planes[plane].aux_surface);
result = add_surface(device, image, &image->planes[plane].aux_surface,
binding, ANV_OFFSET_IMPLICIT);
if (result != VK_SUCCESS)
return result;
}
add_aux_state_tracking_buffer(device, image, plane);
return add_aux_state_tracking_buffer(device, image, plane);
} else if ((aspect & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) && image->samples > 1) {
assert(!(image->usage & VK_IMAGE_USAGE_STORAGE_BIT));
ok = isl_surf_get_mcs_surf(&device->isl_dev,
@@ -637,9 +694,14 @@ add_aux_surface_if_supported(struct anv_device *device,
return VK_SUCCESS;
image->planes[plane].aux_usage = ISL_AUX_USAGE_MCS;
add_surface(image, ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
&image->planes[plane].aux_surface);
add_aux_state_tracking_buffer(device, image, plane);
result = add_surface(device, image, &image->planes[plane].aux_surface,
ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
ANV_OFFSET_IMPLICIT);
if (result != VK_SUCCESS)
return result;
return add_aux_state_tracking_buffer(device, image, plane);
}
return VK_SUCCESS;
@@ -676,9 +738,9 @@ add_shadow_surface(struct anv_device *device,
*/
assert(ok);
add_surface(image, ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
&image->planes[plane].shadow_surface);
return VK_SUCCESS;
return add_surface(device, image, &image->planes[plane].shadow_surface,
ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
ANV_OFFSET_IMPLICIT);
}
/**
@@ -716,9 +778,9 @@ add_primary_surface(struct anv_device *device,
image->planes[plane].aux_usage = ISL_AUX_USAGE_NONE;
add_surface(image, ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane, anv_surf);
return VK_SUCCESS;
return add_surface(device, image, anv_surf,
ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
ANV_OFFSET_IMPLICIT);
}
#ifdef DEBUG