lavapipe: Implement VK_EXT_image_2d_view_of_3d with sparse textures

The following things needed to be fixed:
- lp_build_tiled_sample_offset has to use the block size of the
  underlying 3D texture. Remaining calculations use the dimensions of
  the view since the z-coordinate is undefined and has to be ignored.
- The layer offset must be calculated using llvmpipe_get_texel_offset.

Fixes: d747c4a ("lavapipe: Implement sparse buffers and images")
Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31038>
(cherry picked from commit 1ad1b356fc)
This commit is contained in:
Konstantin Seurer 2024-09-05 11:46:21 +02:00 committed by Eric Engestrom
parent 97570a038d
commit 412fbc16ed
5 changed files with 48 additions and 9 deletions

View file

@ -3234,7 +3234,7 @@
"description": "lavapipe: Implement VK_EXT_image_2d_view_of_3d with sparse textures",
"nominated": true,
"nomination_type": 1,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": "d747c4a8746834d3c9a6fbd7b455b7ce9441fb38",
"notes": null

View file

@ -123,6 +123,8 @@ lp_sampler_static_texture_state(struct lp_static_texture_state *state,
else
state->target = view->target;
state->res_target = texture->target;
state->pot_width = util_is_power_of_two_or_zero(texture->width0);
state->pot_height = util_is_power_of_two_or_zero(texture->height0);
state->pot_depth = util_is_power_of_two_or_zero(texture->depth0);
@ -166,13 +168,17 @@ lp_sampler_static_texture_state_image(struct lp_static_texture_state *state,
assert(state->swizzle_a < PIPE_SWIZZLE_NONE);
state->target = resource->target;
state->res_target = resource->target;
state->pot_width = util_is_power_of_two_or_zero(resource->width0);
state->pot_height = util_is_power_of_two_or_zero(resource->height0);
state->pot_depth = util_is_power_of_two_or_zero(resource->depth0);
state->level_zero_only = view->u.tex.level == 0;
state->tiled = !!(resource->flags & PIPE_RESOURCE_FLAG_SPARSE);
if (state->tiled)
if (state->tiled) {
state->tiled_samples = resource->nr_samples;
if (view->u.tex.is_2d_view_of_3d)
state->target = PIPE_TEXTURE_2D;
}
/*
* the layer / element / level parameters are all either dynamic
@ -2222,6 +2228,21 @@ lp_build_tiled_sample_offset(struct lp_build_context *bld,
assert(static_texture_state->tiled);
uint32_t res_dimensions = 1;
switch (static_texture_state->res_target) {
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_CUBE:
case PIPE_TEXTURE_RECT:
case PIPE_TEXTURE_2D_ARRAY:
res_dimensions = 2;
break;
case PIPE_TEXTURE_3D:
res_dimensions = 3;
break;
default:
break;
}
uint32_t dimensions = 1;
switch (static_texture_state->target) {
case PIPE_TEXTURE_2D:
@ -2244,9 +2265,9 @@ lp_build_tiled_sample_offset(struct lp_build_context *bld,
};
uint32_t sparse_tile_size[3] = {
util_format_get_tilesize(format, dimensions, static_texture_state->tiled_samples, 0) * block_size[0],
util_format_get_tilesize(format, dimensions, static_texture_state->tiled_samples, 1) * block_size[1],
util_format_get_tilesize(format, dimensions, static_texture_state->tiled_samples, 2) * block_size[2],
util_format_get_tilesize(format, res_dimensions, static_texture_state->tiled_samples, 0) * block_size[0],
util_format_get_tilesize(format, res_dimensions, static_texture_state->tiled_samples, 1) * block_size[1],
util_format_get_tilesize(format, res_dimensions, static_texture_state->tiled_samples, 2) * block_size[2],
};
LLVMValueRef sparse_tile_size_log2[3] = {

View file

@ -197,6 +197,7 @@ struct lp_static_texture_state
/* pipe_texture's state */
enum pipe_texture_target target:5; /**< PIPE_TEXTURE_* */
enum pipe_texture_target res_target:5;
unsigned pot_width:1; /**< is the width a power of two? */
unsigned pot_height:1;
unsigned pot_depth:1;

View file

@ -418,11 +418,13 @@ lp_jit_texture_from_pipe(struct lp_jit_texture *jit, const struct pipe_sampler_v
}
}
bool is_2d_view_of_3d = res->target == PIPE_TEXTURE_3D && view->target == PIPE_TEXTURE_2D;
if (res->target == PIPE_TEXTURE_1D_ARRAY ||
res->target == PIPE_TEXTURE_2D_ARRAY ||
res->target == PIPE_TEXTURE_CUBE ||
res->target == PIPE_TEXTURE_CUBE_ARRAY ||
(res->target == PIPE_TEXTURE_3D && view->target == PIPE_TEXTURE_2D)) {
is_2d_view_of_3d) {
/*
* For array textures, we don't have first_layer, instead
* adjust last_layer (stored as depth) plus the mip level
@ -432,8 +434,13 @@ lp_jit_texture_from_pipe(struct lp_jit_texture *jit, const struct pipe_sampler_v
*/
jit->depth = view->u.tex.last_layer - view->u.tex.first_layer + 1;
for (unsigned j = first_level; j <= last_level; j++) {
jit->mip_offsets[j] += view->u.tex.first_layer *
lp_tex->img_stride[j];
if (is_2d_view_of_3d && (res->flags & PIPE_RESOURCE_FLAG_SPARSE)) {
jit->mip_offsets[j] = llvmpipe_get_texel_offset(
view->texture, j, 0, 0, view->u.tex.first_layer);
} else {
jit->mip_offsets[j] += view->u.tex.first_layer *
lp_tex->img_stride[j];
}
}
if (view->target == PIPE_TEXTURE_CUBE ||
view->target == PIPE_TEXTURE_CUBE_ARRAY) {
@ -580,7 +587,14 @@ lp_jit_image_from_pipe(struct lp_jit_image *jit, const struct pipe_image_view *v
* XXX For mip levels, could do something similar.
*/
jit->depth = view->u.tex.last_layer - view->u.tex.first_layer + 1;
mip_offset += view->u.tex.first_layer * lp_res->img_stride[view->u.tex.level];
if (res->target == PIPE_TEXTURE_3D && view->u.tex.first_layer != 0 &&
(res->flags & PIPE_RESOURCE_FLAG_SPARSE)) {
mip_offset = llvmpipe_get_texel_offset(
res, view->u.tex.level, 0, 0, view->u.tex.first_layer);
} else {
mip_offset += view->u.tex.first_layer * lp_res->img_stride[view->u.tex.level];
}
} else
jit->depth = u_minify(jit->depth, view->u.tex.level);

View file

@ -327,6 +327,9 @@ lvp_create_imageview(const struct lvp_image_view *iv, VkFormat plane_format, uns
} else {
view.u.tex.first_layer = iv->vk.base_array_layer,
view.u.tex.last_layer = iv->vk.base_array_layer + iv->vk.layer_count - 1;
if (view.resource->target == PIPE_TEXTURE_3D)
view.u.tex.is_2d_view_of_3d = true;
}
view.u.tex.level = iv->vk.base_mip_level;
return view;