anv: implement storage image depth query using descriptor buffer read
The HW not returning the depth value we would like for VK_EXT_sliced_view_of_3d, we can pull that value by reading the RENDER_SURFACE_STATE struct directly. Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Reviewed-by: José Roberto de Souza <jose.souza@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/23868>
This commit is contained in:

committed by
Marge Bot

parent
a7ccba2dfd
commit
2e8c0a33e7
@@ -78,6 +78,7 @@ genX_bits_included_symbols = [
|
|||||||
'RENDER_SURFACE_STATE::Height',
|
'RENDER_SURFACE_STATE::Height',
|
||||||
'RENDER_SURFACE_STATE::Depth',
|
'RENDER_SURFACE_STATE::Depth',
|
||||||
'RENDER_SURFACE_STATE::Surface Type',
|
'RENDER_SURFACE_STATE::Surface Type',
|
||||||
|
'RENDER_SURFACE_STATE::Render Target View Extent',
|
||||||
'CLEAR_COLOR',
|
'CLEAR_COLOR',
|
||||||
'VERTEX_BUFFER_STATE::Buffer Starting Address',
|
'VERTEX_BUFFER_STATE::Buffer Starting Address',
|
||||||
'CPS_STATE',
|
'CPS_STATE',
|
||||||
|
@@ -1676,6 +1676,7 @@ anv_descriptor_set_write_image_view(struct anv_device *device,
|
|||||||
.vanilla = anv_surface_state_to_handle(
|
.vanilla = anv_surface_state_to_handle(
|
||||||
device->physical,
|
device->physical,
|
||||||
image_view->planes[0].storage.state),
|
image_view->planes[0].storage.state),
|
||||||
|
.image_depth = image_view->vk.storage.z_slice_count,
|
||||||
};
|
};
|
||||||
memcpy(desc_map, &desc_data, sizeof(desc_data));
|
memcpy(desc_map, &desc_data, sizeof(desc_data));
|
||||||
} else {
|
} else {
|
||||||
|
@@ -436,6 +436,51 @@ build_load_render_surface_state_address(nir_builder *b,
|
|||||||
return nir_vec4(b, addr_ldw, addr_udw, length, nir_imm_int(b, 0));
|
return nir_vec4(b, addr_ldw, addr_udw, length, nir_imm_int(b, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Load the depth of a 3D storage image.
|
||||||
|
*
|
||||||
|
* Either by reading the indirect descriptor value, or reading the value from
|
||||||
|
* RENDER_SURFACE_STATE.
|
||||||
|
*
|
||||||
|
* This is necessary for VK_EXT_image_sliced_view_of_3d.
|
||||||
|
*/
|
||||||
|
static nir_ssa_def *
|
||||||
|
build_load_storage_3d_image_depth(nir_builder *b,
|
||||||
|
nir_ssa_def *desc_addr,
|
||||||
|
nir_ssa_def *resinfo_depth,
|
||||||
|
struct apply_pipeline_layout_state *state)
|
||||||
|
|
||||||
|
{
|
||||||
|
const struct intel_device_info *devinfo = &state->pdevice->info;
|
||||||
|
|
||||||
|
if (state->layout->type == ANV_PIPELINE_DESCRIPTOR_SET_LAYOUT_TYPE_INDIRECT) {
|
||||||
|
return build_load_descriptor_mem(
|
||||||
|
b, desc_addr,
|
||||||
|
offsetof(struct anv_storage_image_descriptor, image_depth),
|
||||||
|
1, 32, state);
|
||||||
|
} else {
|
||||||
|
nir_ssa_def *data = build_load_descriptor_mem(
|
||||||
|
b, desc_addr,
|
||||||
|
RENDER_SURFACE_STATE_RenderTargetViewExtent_start(devinfo) / 8,
|
||||||
|
1, 32, state);
|
||||||
|
nir_ssa_def *depth =
|
||||||
|
nir_ushr_imm(
|
||||||
|
b, data,
|
||||||
|
RENDER_SURFACE_STATE_RenderTargetViewExtent_start(devinfo) % 32);
|
||||||
|
depth = nir_iand_imm(
|
||||||
|
b, depth,
|
||||||
|
(1u << RENDER_SURFACE_STATE_RenderTargetViewExtent_bits(devinfo)) - 1);
|
||||||
|
depth = nir_iadd_imm(b, depth, 1);
|
||||||
|
|
||||||
|
/* Return the minimum between the RESINFO value and the
|
||||||
|
* RENDER_SURFACE_STATE::RenderTargetViewExtent value.
|
||||||
|
*
|
||||||
|
* Both are expressed for the current view LOD, but in the case of a
|
||||||
|
* SURFTYPE_NULL, RESINFO will return the right value, while the -1
|
||||||
|
* value in RENDER_SURFACE_STATE should be ignored.
|
||||||
|
*/
|
||||||
|
return nir_umin(b, resinfo_depth, depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
/** Build a Vulkan resource index
|
/** Build a Vulkan resource index
|
||||||
*
|
*
|
||||||
* A "resource index" is the term used by our SPIR-V parser and the relevant
|
* A "resource index" is the term used by our SPIR-V parser and the relevant
|
||||||
@@ -1479,6 +1524,58 @@ lower_image_intrinsic(nir_builder *b, nir_intrinsic_instr *intrin,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
lower_image_size_intrinsic(nir_builder *b, nir_intrinsic_instr *intrin,
|
||||||
|
struct apply_pipeline_layout_state *state)
|
||||||
|
{
|
||||||
|
if (nir_intrinsic_image_dim(intrin) != GLSL_SAMPLER_DIM_3D)
|
||||||
|
return lower_image_intrinsic(b, intrin, state);
|
||||||
|
|
||||||
|
nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
|
||||||
|
|
||||||
|
b->cursor = nir_before_instr(&intrin->instr);
|
||||||
|
|
||||||
|
bool non_uniform = nir_intrinsic_access(intrin) & ACCESS_NON_UNIFORM;
|
||||||
|
bool is_bindless;
|
||||||
|
nir_ssa_def *handle =
|
||||||
|
build_load_var_deref_surface_handle(b, deref, non_uniform,
|
||||||
|
&is_bindless, state);
|
||||||
|
nir_rewrite_image_intrinsic(intrin, handle, is_bindless);
|
||||||
|
|
||||||
|
nir_variable *var = nir_deref_instr_get_variable(deref);
|
||||||
|
const uint32_t set = var->data.descriptor_set;
|
||||||
|
const uint32_t binding = var->data.binding;
|
||||||
|
|
||||||
|
nir_ssa_def *array_index;
|
||||||
|
if (deref->deref_type != nir_deref_type_var) {
|
||||||
|
assert(deref->deref_type == nir_deref_type_array);
|
||||||
|
assert(nir_deref_instr_parent(deref)->deref_type == nir_deref_type_var);
|
||||||
|
assert(deref->arr.index.is_ssa);
|
||||||
|
array_index = deref->arr.index.ssa;
|
||||||
|
} else {
|
||||||
|
array_index = nir_imm_int(b, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
nir_ssa_def *desc_addr = build_desc_addr_for_binding(
|
||||||
|
b, set, binding, array_index, state);
|
||||||
|
|
||||||
|
b->cursor = nir_after_instr(&intrin->instr);
|
||||||
|
|
||||||
|
nir_ssa_def *image_depth =
|
||||||
|
build_load_storage_3d_image_depth(b, desc_addr,
|
||||||
|
nir_channel(b, &intrin->dest.ssa, 2),
|
||||||
|
state);
|
||||||
|
|
||||||
|
nir_ssa_def *comps[4] = {};
|
||||||
|
for (unsigned c = 0; c < intrin->dest.ssa.num_components; c++)
|
||||||
|
comps[c] = c == 2 ? image_depth : nir_channel(b, &intrin->dest.ssa, c);
|
||||||
|
|
||||||
|
nir_ssa_def *vec = nir_vec(b, comps, intrin->dest.ssa.num_components);
|
||||||
|
nir_ssa_def_rewrite_uses_after(&intrin->dest.ssa, vec, vec->parent_instr);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
lower_load_constant(nir_builder *b, nir_intrinsic_instr *intrin,
|
lower_load_constant(nir_builder *b, nir_intrinsic_instr *intrin,
|
||||||
struct apply_pipeline_layout_state *state)
|
struct apply_pipeline_layout_state *state)
|
||||||
@@ -1675,12 +1772,13 @@ apply_pipeline_layout(nir_builder *b, nir_instr *instr, void *_state)
|
|||||||
case nir_intrinsic_image_deref_store:
|
case nir_intrinsic_image_deref_store:
|
||||||
case nir_intrinsic_image_deref_atomic:
|
case nir_intrinsic_image_deref_atomic:
|
||||||
case nir_intrinsic_image_deref_atomic_swap:
|
case nir_intrinsic_image_deref_atomic_swap:
|
||||||
case nir_intrinsic_image_deref_size:
|
|
||||||
case nir_intrinsic_image_deref_samples:
|
case nir_intrinsic_image_deref_samples:
|
||||||
case nir_intrinsic_image_deref_load_param_intel:
|
case nir_intrinsic_image_deref_load_param_intel:
|
||||||
case nir_intrinsic_image_deref_load_raw_intel:
|
case nir_intrinsic_image_deref_load_raw_intel:
|
||||||
case nir_intrinsic_image_deref_store_raw_intel:
|
case nir_intrinsic_image_deref_store_raw_intel:
|
||||||
return lower_image_intrinsic(b, intrin, state);
|
return lower_image_intrinsic(b, intrin, state);
|
||||||
|
case nir_intrinsic_image_deref_size:
|
||||||
|
return lower_image_size_intrinsic(b, intrin, state);
|
||||||
case nir_intrinsic_load_constant:
|
case nir_intrinsic_load_constant:
|
||||||
return lower_load_constant(b, intrin, state);
|
return lower_load_constant(b, intrin, state);
|
||||||
case nir_intrinsic_load_base_workgroup_id:
|
case nir_intrinsic_load_base_workgroup_id:
|
||||||
|
@@ -1671,7 +1671,27 @@ struct anv_storage_image_descriptor {
|
|||||||
*/
|
*/
|
||||||
uint32_t vanilla;
|
uint32_t vanilla;
|
||||||
|
|
||||||
uint32_t pad;
|
/** Image depth
|
||||||
|
*
|
||||||
|
* By default the HW RESINFO message allows us to query the depth of an image :
|
||||||
|
*
|
||||||
|
* From the Kaby Lake docs for the RESINFO message:
|
||||||
|
*
|
||||||
|
* "Surface Type | ... | Blue
|
||||||
|
* --------------+-----+----------------
|
||||||
|
* SURFTYPE_3D | ... | (Depth+1)»LOD"
|
||||||
|
*
|
||||||
|
* With VK_EXT_sliced_view_of_3d, we have to support a slice of a 3D image,
|
||||||
|
* meaning at a depth offset with a new depth value potentially reduced
|
||||||
|
* from the original image. Unfortunately if we change the Depth value of
|
||||||
|
* the image, we then run into issues with Yf/Ys tilings where the HW fetch
|
||||||
|
* data at incorrect locations.
|
||||||
|
*
|
||||||
|
* To solve this, we put the slice depth in the descriptor and recompose
|
||||||
|
* the vec3 (width, height, depth) using this field for z and xy using the
|
||||||
|
* RESINFO result.
|
||||||
|
*/
|
||||||
|
uint32_t image_depth;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Struct representing a address/range descriptor
|
/** Struct representing a address/range descriptor
|
||||||
|
Reference in New Issue
Block a user