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"
|
#include "vk_format.h"
|
||||||
|
|
||||||
|
#define ANV_OFFSET_IMPLICIT UINT64_MAX
|
||||||
|
|
||||||
static const enum isl_surf_dim
|
static const enum isl_surf_dim
|
||||||
vk_to_isl_surf_dim[] = {
|
vk_to_isl_surf_dim[] = {
|
||||||
[VK_IMAGE_TYPE_1D] = ISL_SURF_DIM_1D,
|
[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
|
* Extend the memory binding's range by appending a new memory range with `size`
|
||||||
* given size and alignment. Return the appended range.
|
* 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
|
* The given binding must not be ANV_IMAGE_MEMORY_BINDING_MAIN. The function
|
||||||
* converts to MAIN as needed.
|
* converts to MAIN as needed.
|
||||||
*/
|
*/
|
||||||
static struct anv_image_memory_range
|
static VkResult MUST_CHECK
|
||||||
image_binding_grow(struct anv_image *image,
|
image_binding_grow(const struct anv_device *device,
|
||||||
|
struct anv_image *image,
|
||||||
enum anv_image_memory_binding binding,
|
enum anv_image_memory_binding binding,
|
||||||
|
uint64_t offset,
|
||||||
uint64_t size,
|
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(size > 0);
|
||||||
assert(util_is_power_of_two_or_zero(alignment));
|
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;
|
binding = ANV_IMAGE_MEMORY_BINDING_MAIN;
|
||||||
break;
|
break;
|
||||||
case ANV_IMAGE_MEMORY_BINDING_PRIVATE:
|
case ANV_IMAGE_MEMORY_BINDING_PRIVATE:
|
||||||
|
assert(offset == ANV_OFFSET_IMPLICIT);
|
||||||
break;
|
break;
|
||||||
case ANV_IMAGE_MEMORY_BINDING_END:
|
case ANV_IMAGE_MEMORY_BINDING_END:
|
||||||
unreachable("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 =
|
struct anv_image_memory_range *container =
|
||||||
&image->bindings[binding].memory_range;
|
&image->bindings[binding].memory_range;
|
||||||
|
|
||||||
struct anv_image_memory_range new = {
|
if (has_implicit_offset) {
|
||||||
.binding = container->binding,
|
offset = align_u64(container->offset + container->size, alignment);
|
||||||
.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,
|
.size = size,
|
||||||
.alignment = alignment,
|
.alignment = alignment,
|
||||||
};
|
};
|
||||||
|
|
||||||
container->size = new.offset + new.size;
|
return VK_SUCCESS;
|
||||||
container->alignment = MAX2(container->alignment, new.alignment);
|
|
||||||
|
|
||||||
return new;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -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
|
* Add the surface to the binding at the given offset.
|
||||||
* memory range.
|
|
||||||
*
|
*
|
||||||
* \see image_binding_grow()
|
* \see image_binding_grow()
|
||||||
*/
|
*/
|
||||||
static void
|
static VkResult MUST_CHECK
|
||||||
add_surface(struct anv_image *image,
|
add_surface(struct anv_device *device,
|
||||||
|
struct anv_image *image,
|
||||||
|
struct anv_surface *surf,
|
||||||
enum anv_image_memory_binding binding,
|
enum anv_image_memory_binding binding,
|
||||||
struct anv_surface *surf)
|
uint64_t offset)
|
||||||
{
|
{
|
||||||
/* isl surface must be initialized */
|
/* isl surface must be initialized */
|
||||||
assert(surf->isl.size_B > 0);
|
assert(surf->isl.size_B > 0);
|
||||||
|
|
||||||
surf->memory_range = image_binding_grow(image, binding,
|
return image_binding_grow(device, image, binding, offset,
|
||||||
surf->isl.size_B,
|
surf->isl.size_B,
|
||||||
surf->isl.alignment_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
|
* * For any blorp operations, we pass the address to the clear value into
|
||||||
* blorp and it knows to copy the clear color.
|
* blorp and it knows to copy the clear color.
|
||||||
*/
|
*/
|
||||||
static void
|
static VkResult MUST_CHECK
|
||||||
add_aux_state_tracking_buffer(struct anv_device *device,
|
add_aux_state_tracking_buffer(struct anv_device *device,
|
||||||
struct anv_image *image,
|
struct anv_image *image,
|
||||||
uint32_t plane)
|
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
|
/* 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.
|
* lack of testing. And MI_LOAD/STORE operations require dword-alignment.
|
||||||
*/
|
*/
|
||||||
image->planes[plane].fast_clear_memory_range =
|
return image_binding_grow(device, image, binding,
|
||||||
image_binding_grow(image, binding, state_size, 4096);
|
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)
|
isl_surf_usage_flags_t isl_extra_usage_flags)
|
||||||
{
|
{
|
||||||
VkImageAspectFlags aspect = plane_format.aspect;
|
VkImageAspectFlags aspect = plane_format.aspect;
|
||||||
|
VkResult result;
|
||||||
bool ok;
|
bool ok;
|
||||||
|
|
||||||
/* The aux surface must not be already added. */
|
/* 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;
|
image->planes[plane].aux_usage = ISL_AUX_USAGE_HIZ_CCS;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_surface(image, ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
|
return add_surface(device, image, &image->planes[plane].aux_surface,
|
||||||
&image->planes[plane].aux_surface);
|
ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
|
||||||
|
ANV_OFFSET_IMPLICIT);
|
||||||
} else if (aspect == VK_IMAGE_ASPECT_STENCIL_BIT) {
|
} else if (aspect == VK_IMAGE_ASPECT_STENCIL_BIT) {
|
||||||
|
|
||||||
if (INTEL_DEBUG & DEBUG_NO_RBC)
|
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))
|
!isl_drm_modifier_has_aux(image->drm_format_mod))
|
||||||
binding = ANV_IMAGE_MEMORY_BINDING_PRIVATE;
|
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) {
|
} else if ((aspect & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) && image->samples > 1) {
|
||||||
assert(!(image->usage & VK_IMAGE_USAGE_STORAGE_BIT));
|
assert(!(image->usage & VK_IMAGE_USAGE_STORAGE_BIT));
|
||||||
ok = isl_surf_get_mcs_surf(&device->isl_dev,
|
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;
|
return VK_SUCCESS;
|
||||||
|
|
||||||
image->planes[plane].aux_usage = ISL_AUX_USAGE_MCS;
|
image->planes[plane].aux_usage = ISL_AUX_USAGE_MCS;
|
||||||
add_surface(image, ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
|
|
||||||
&image->planes[plane].aux_surface);
|
result = add_surface(device, image, &image->planes[plane].aux_surface,
|
||||||
add_aux_state_tracking_buffer(device, image, plane);
|
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;
|
return VK_SUCCESS;
|
||||||
@@ -676,9 +738,9 @@ add_shadow_surface(struct anv_device *device,
|
|||||||
*/
|
*/
|
||||||
assert(ok);
|
assert(ok);
|
||||||
|
|
||||||
add_surface(image, ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
|
return add_surface(device, image, &image->planes[plane].shadow_surface,
|
||||||
&image->planes[plane].shadow_surface);
|
ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
|
||||||
return VK_SUCCESS;
|
ANV_OFFSET_IMPLICIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -716,9 +778,9 @@ add_primary_surface(struct anv_device *device,
|
|||||||
|
|
||||||
image->planes[plane].aux_usage = ISL_AUX_USAGE_NONE;
|
image->planes[plane].aux_usage = ISL_AUX_USAGE_NONE;
|
||||||
|
|
||||||
add_surface(image, ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane, anv_surf);
|
return add_surface(device, image, anv_surf,
|
||||||
|
ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
|
||||||
return VK_SUCCESS;
|
ANV_OFFSET_IMPLICIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
Reference in New Issue
Block a user