iris: Export and import surfaces with modifiers that have aux data
The DRI interface for modifiers with aux data treats the aux data as a separate plane of the main surface. When the dri layer requests the plane associated with the aux data, we save the required information into the dri aux plane image. Later when the image is used, the dri plane image will be available in the pipe_resource structure's `next` field. Therefore in iris, we reconstruct the aux setup from this separate dri plane image when the image is used. Signed-off-by: Jordan Justen <jordan.l.justen@intel.com> Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
parent
99c8eb997d
commit
246eebba4a
|
@ -238,6 +238,8 @@ iris_blorp_surf_for_resource(struct iris_vtable *vtbl,
|
|||
{
|
||||
struct iris_resource *res = (void *) p_res;
|
||||
|
||||
assert(!iris_resource_unfinished_aux_import(res));
|
||||
|
||||
if (aux_usage == ISL_AUX_USAGE_HIZ &&
|
||||
!iris_resource_level_has_hiz(res, level))
|
||||
aux_usage = ISL_AUX_USAGE_NONE;
|
||||
|
|
|
@ -364,7 +364,8 @@ iris_get_aux_clear_color_state_size(struct iris_screen *screen)
|
|||
*/
|
||||
static bool
|
||||
iris_resource_configure_aux(struct iris_screen *screen,
|
||||
struct iris_resource *res, uint64_t *aux_size_B,
|
||||
struct iris_resource *res, bool imported,
|
||||
uint64_t *aux_size_B,
|
||||
uint32_t *alloc_flags)
|
||||
{
|
||||
struct isl_device *isl_dev = &screen->isl_dev;
|
||||
|
@ -412,7 +413,11 @@ iris_resource_configure_aux(struct iris_screen *screen,
|
|||
* For CCS_D, do the same thing. On Gen9+, this avoids having any
|
||||
* undefined bits in the aux buffer.
|
||||
*/
|
||||
initial_state = ISL_AUX_STATE_PASS_THROUGH;
|
||||
if (imported)
|
||||
initial_state =
|
||||
isl_drm_modifier_get_default_aux_state(res->mod_info->modifier);
|
||||
else
|
||||
initial_state = ISL_AUX_STATE_PASS_THROUGH;
|
||||
*alloc_flags |= BO_ALLOC_ZEROED;
|
||||
ok = isl_surf_get_ccs_surf(isl_dev, &res->surf, &res->aux.surf, 0);
|
||||
break;
|
||||
|
@ -506,7 +511,7 @@ iris_resource_alloc_separate_aux(struct iris_screen *screen,
|
|||
{
|
||||
uint32_t alloc_flags;
|
||||
uint64_t size;
|
||||
if (!iris_resource_configure_aux(screen, res, &size, &alloc_flags))
|
||||
if (!iris_resource_configure_aux(screen, res, false, &size, &alloc_flags))
|
||||
return false;
|
||||
|
||||
if (size == 0)
|
||||
|
@ -531,6 +536,44 @@ iris_resource_alloc_separate_aux(struct iris_screen *screen,
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
iris_resource_finish_aux_import(struct pipe_screen *pscreen,
|
||||
struct iris_resource *res)
|
||||
{
|
||||
struct iris_screen *screen = (struct iris_screen *)pscreen;
|
||||
assert(iris_resource_unfinished_aux_import(res));
|
||||
assert(!res->mod_info->supports_clear_color);
|
||||
|
||||
struct iris_resource *aux_res = (void *) res->base.next;
|
||||
assert(aux_res->aux.surf.row_pitch_B && aux_res->aux.offset &&
|
||||
aux_res->aux.bo);
|
||||
|
||||
assert(res->bo == aux_res->aux.bo);
|
||||
iris_bo_reference(aux_res->aux.bo);
|
||||
res->aux.bo = aux_res->aux.bo;
|
||||
|
||||
res->aux.offset = aux_res->aux.offset;
|
||||
|
||||
assert(res->bo->size >= (res->aux.offset + res->aux.surf.size_B));
|
||||
assert(res->aux.clear_color_bo == NULL);
|
||||
res->aux.clear_color_offset = 0;
|
||||
|
||||
assert(aux_res->aux.surf.row_pitch_B == res->aux.surf.row_pitch_B);
|
||||
|
||||
unsigned clear_color_state_size =
|
||||
iris_get_aux_clear_color_state_size(screen);
|
||||
|
||||
if (clear_color_state_size > 0) {
|
||||
res->aux.clear_color_bo =
|
||||
iris_bo_alloc(screen->bufmgr, "clear color buffer",
|
||||
clear_color_state_size, IRIS_MEMZONE_OTHER);
|
||||
res->aux.clear_color_offset = 0;
|
||||
}
|
||||
|
||||
iris_resource_destroy(&screen->base, res->base.next);
|
||||
res->base.next = NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
supports_mcs(const struct isl_surf *surf)
|
||||
{
|
||||
|
@ -728,7 +771,7 @@ iris_resource_create_with_modifiers(struct pipe_screen *pscreen,
|
|||
uint32_t aux_preferred_alloc_flags;
|
||||
uint64_t aux_size = 0;
|
||||
bool aux_enabled =
|
||||
iris_resource_configure_aux(screen, res, &aux_size,
|
||||
iris_resource_configure_aux(screen, res, false, &aux_size,
|
||||
&aux_preferred_alloc_flags);
|
||||
aux_enabled = aux_enabled && res->aux.surf.size_B > 0;
|
||||
const bool separate_aux = aux_enabled && !res->mod_info;
|
||||
|
@ -878,27 +921,57 @@ iris_resource_from_handle(struct pipe_screen *pscreen,
|
|||
if (templ->target == PIPE_BUFFER) {
|
||||
res->surf.tiling = ISL_TILING_LINEAR;
|
||||
} else {
|
||||
UNUSED const bool isl_surf_created_successfully =
|
||||
isl_surf_init(&screen->isl_dev, &res->surf,
|
||||
.dim = target_to_isl_surf_dim(templ->target),
|
||||
.format = fmt.fmt,
|
||||
.width = templ->width0,
|
||||
.height = templ->height0,
|
||||
.depth = templ->depth0,
|
||||
.levels = templ->last_level + 1,
|
||||
.array_len = templ->array_size,
|
||||
.samples = MAX2(templ->nr_samples, 1),
|
||||
.min_alignment_B = 0,
|
||||
.row_pitch_B = whandle->stride,
|
||||
.usage = isl_usage,
|
||||
.tiling_flags = 1 << res->mod_info->tiling);
|
||||
assert(isl_surf_created_successfully);
|
||||
assert(res->bo->tiling_mode ==
|
||||
isl_tiling_to_i915_tiling(res->surf.tiling));
|
||||
if (whandle->modifier == DRM_FORMAT_MOD_INVALID || whandle->plane == 0) {
|
||||
UNUSED const bool isl_surf_created_successfully =
|
||||
isl_surf_init(&screen->isl_dev, &res->surf,
|
||||
.dim = target_to_isl_surf_dim(templ->target),
|
||||
.format = fmt.fmt,
|
||||
.width = templ->width0,
|
||||
.height = templ->height0,
|
||||
.depth = templ->depth0,
|
||||
.levels = templ->last_level + 1,
|
||||
.array_len = templ->array_size,
|
||||
.samples = MAX2(templ->nr_samples, 1),
|
||||
.min_alignment_B = 0,
|
||||
.row_pitch_B = whandle->stride,
|
||||
.usage = isl_usage,
|
||||
.tiling_flags = 1 << res->mod_info->tiling);
|
||||
assert(isl_surf_created_successfully);
|
||||
assert(res->bo->tiling_mode ==
|
||||
isl_tiling_to_i915_tiling(res->surf.tiling));
|
||||
|
||||
// XXX: create_ccs_buf_for_image?
|
||||
if (!iris_resource_alloc_separate_aux(screen, res))
|
||||
goto fail;
|
||||
// XXX: create_ccs_buf_for_image?
|
||||
if (whandle->modifier == DRM_FORMAT_MOD_INVALID) {
|
||||
if (!iris_resource_alloc_separate_aux(screen, res))
|
||||
goto fail;
|
||||
} else {
|
||||
if (res->mod_info->aux_usage != ISL_AUX_USAGE_NONE) {
|
||||
uint32_t alloc_flags;
|
||||
uint64_t size;
|
||||
res->aux.usage = res->mod_info->aux_usage;
|
||||
res->aux.possible_usages = 1 << res->mod_info->aux_usage;
|
||||
res->aux.sampler_usages = res->aux.possible_usages;
|
||||
bool ok = iris_resource_configure_aux(screen, res, true, &size,
|
||||
&alloc_flags);
|
||||
assert(ok);
|
||||
/* The gallium dri layer will create a separate plane resource
|
||||
* for the aux image. iris_resource_finish_aux_import will
|
||||
* merge the separate aux parameters back into a single
|
||||
* iris_resource.
|
||||
*/
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Save modifier import information to reconstruct later. After
|
||||
* import, this will be available under a second image accessible
|
||||
* from the main image with res->base.next. See
|
||||
* iris_resource_finish_aux_import.
|
||||
*/
|
||||
res->aux.surf.row_pitch_B = whandle->stride;
|
||||
res->aux.offset = whandle->offset;
|
||||
res->aux.bo = res->bo;
|
||||
res->bo = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return &res->base;
|
||||
|
|
|
@ -407,6 +407,16 @@ void iris_resource_prepare_image(struct iris_context *ice,
|
|||
struct iris_batch *batch,
|
||||
struct iris_resource *res);
|
||||
|
||||
static inline bool
|
||||
iris_resource_unfinished_aux_import(struct iris_resource *res)
|
||||
{
|
||||
return res->base.next != NULL && res->mod_info &&
|
||||
res->mod_info->aux_usage != ISL_AUX_USAGE_NONE;
|
||||
}
|
||||
|
||||
void iris_resource_finish_aux_import(struct pipe_screen *pscreen,
|
||||
struct iris_resource *res);
|
||||
|
||||
bool iris_has_color_unresolved(const struct iris_resource *res,
|
||||
unsigned start_level, unsigned num_levels,
|
||||
unsigned start_layer, unsigned num_layers);
|
||||
|
|
|
@ -1749,6 +1749,8 @@ fill_surface_state(struct isl_device *isl_dev,
|
|||
.address = res->bo->gtt_offset + res->offset,
|
||||
};
|
||||
|
||||
assert(!iris_resource_unfinished_aux_import(res));
|
||||
|
||||
if (aux_usage != ISL_AUX_USAGE_NONE) {
|
||||
f.aux_surf = &res->aux.surf;
|
||||
f.aux_usage = aux_usage;
|
||||
|
@ -1839,6 +1841,9 @@ iris_create_sampler_view(struct pipe_context *ctx,
|
|||
isv->view.array_len =
|
||||
tmpl->u.tex.last_layer - tmpl->u.tex.first_layer + 1;
|
||||
|
||||
if (iris_resource_unfinished_aux_import(isv->res))
|
||||
iris_resource_finish_aux_import(&screen->base, isv->res);
|
||||
|
||||
unsigned aux_modes = isv->res->aux.sampler_usages;
|
||||
while (aux_modes) {
|
||||
enum isl_aux_usage aux_usage = u_bit_scan(&aux_modes);
|
||||
|
@ -1949,6 +1954,9 @@ iris_create_surface(struct pipe_context *ctx,
|
|||
return NULL;
|
||||
|
||||
if (!isl_format_is_compressed(res->surf.format)) {
|
||||
if (iris_resource_unfinished_aux_import(res))
|
||||
iris_resource_finish_aux_import(&screen->base, res);
|
||||
|
||||
/* This is a normal surface. Fill out a SURFACE_STATE for each possible
|
||||
* auxiliary surface mode and return the pipe_surface.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue