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:
@@ -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
|
||||
|
Reference in New Issue
Block a user