mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-06-21 03:48:22 +02:00
lavapipe: implement VK_EXT_image_view_min_lod with fractional minLod
Plumb VkImageViewMinLodCreateInfoEXT::minLod into the texture descriptor and clamp lambda in the JITted sampling path. The view's minLod lives on the texture side of lp_descriptor (so it is reachable in both combined-image-sampler and separate sampler / sampled image setups). A new lp_static_texture_state::apply_view_min_lod bit is set when the view has a non-zero clamp; this gates the load+max in the shader so unaffected views and non-bindless gallivm consumers pay zero cost. lp_jit_bindless_texture_from_pipe converts to view-relative space (min_lod_clamp - first_level, clamped to >= 0) so the value composes directly with the view-relative lambda lp_build_lod_selector computes. The clamp is applied in both the normal lod path and the min_max_lod_equal fast path, before lod_positive is recomputed, so magnification, lodq and trilinear all behave correctly. For integer texel fetches the Vulkan spec defines an OpImageFetch whose LOD is below the view's minLodInteger as reading zero, so lp_build_fetch_texel applies the same floor(view_min_lod) clamp. Drops test_view_min_lod from the vkd3d fails list. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/42188>
This commit is contained in:
parent
4339200e76
commit
d58aba6c83
9 changed files with 100 additions and 1 deletions
|
|
@ -421,6 +421,29 @@ lp_build_llvm_texture_member(struct gallivm_state *gallivm,
|
|||
return res;
|
||||
}
|
||||
|
||||
static LLVMValueRef
|
||||
lp_build_llvm_texture_view_min_lod(struct gallivm_state *gallivm,
|
||||
LLVMTypeRef resources_type,
|
||||
LLVMValueRef resources_ptr,
|
||||
unsigned texture_unit,
|
||||
LLVMValueRef texture_unit_offset)
|
||||
{
|
||||
/* Only reached in bindless mode, where apply_view_min_lod gates the call. */
|
||||
assert(gallivm->texture_descriptor);
|
||||
|
||||
LLVMBuilderRef builder = gallivm->builder;
|
||||
LLVMTypeRef float_type = LLVMFloatTypeInContext(gallivm->context);
|
||||
|
||||
LLVMValueRef ptr = LLVMBuildAdd(builder, gallivm->texture_descriptor,
|
||||
lp_build_const_int64(gallivm,
|
||||
offsetof(struct lp_image_descriptor, texture.view_min_lod)),
|
||||
"");
|
||||
ptr = LLVMBuildIntToPtr(builder, ptr, LLVMPointerType(float_type, 0), "");
|
||||
|
||||
return LLVMBuildLoad2(builder, float_type, ptr, "view_min_lod");
|
||||
}
|
||||
|
||||
|
||||
static LLVMValueRef
|
||||
lp_build_llvm_texture_residency(struct gallivm_state *gallivm,
|
||||
LLVMTypeRef resources_type,
|
||||
|
|
@ -725,6 +748,8 @@ lp_build_jit_fill_sampler_dynamic_state(struct lp_sampler_dynamic_state *state)
|
|||
state->max_lod = lp_build_llvm_sampler_max_lod;
|
||||
state->lod_bias = lp_build_llvm_sampler_lod_bias;
|
||||
state->border_color = lp_build_llvm_sampler_border_color;
|
||||
|
||||
state->view_min_lod = lp_build_llvm_texture_view_min_lod;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -238,6 +238,7 @@ struct lp_jit_bindless_texture
|
|||
const void *base;
|
||||
const void *residency;
|
||||
uint32_t base_offset;
|
||||
float view_min_lod; /* VK_EXT_image_view_min_lod, relative to first_level */
|
||||
};
|
||||
|
||||
struct lp_image_descriptor {
|
||||
|
|
|
|||
|
|
@ -133,6 +133,13 @@ lp_sampler_static_texture_state(struct lp_static_texture_state *state,
|
|||
if (state->tiled)
|
||||
state->tiled_samples = texture->nr_samples;
|
||||
|
||||
/* VK_EXT_image_view_min_lod: bake "apply view min-lod" into the static state
|
||||
* so views without a clamp don't pay any shader cost. The actual clamp value
|
||||
* lives in the texture descriptor (dynamic state).
|
||||
*/
|
||||
state->apply_view_min_lod = texture->target != PIPE_BUFFER &&
|
||||
view->u.tex.min_lod_clamp > 0.0f;
|
||||
|
||||
/*
|
||||
* the layer / element / level parameters are all either dynamic
|
||||
* state or handled transparently wrt execution.
|
||||
|
|
@ -1158,6 +1165,16 @@ lp_build_lod_selector(struct lp_build_sample_context *bld,
|
|||
bld->resources_ptr, sampler_unit);
|
||||
|
||||
lod = lp_build_broadcast_scalar(lodf_bld, min_lod);
|
||||
|
||||
/* VK_EXT_image_view_min_lod applies even when min == max lod. */
|
||||
if (bld->static_texture_state->apply_view_min_lod &&
|
||||
dynamic_state->view_min_lod) {
|
||||
LLVMValueRef view_min_lod =
|
||||
dynamic_state->view_min_lod(bld->gallivm, bld->resources_type,
|
||||
bld->resources_ptr, sampler_unit, NULL);
|
||||
view_min_lod = lp_build_broadcast_scalar(lodf_bld, view_min_lod);
|
||||
lod = lp_build_max(lodf_bld, lod, view_min_lod);
|
||||
}
|
||||
} else {
|
||||
if (explicit_lod) {
|
||||
if (bld->num_lods != bld->coord_type.length) {
|
||||
|
|
@ -1274,6 +1291,17 @@ lp_build_lod_selector(struct lp_build_sample_context *bld,
|
|||
lod = lp_build_max(lodf_bld, lod, desc_min_lod);
|
||||
}
|
||||
|
||||
/* VK_EXT_image_view_min_lod: clamp lod to the per-view minimum. */
|
||||
if (bld->static_texture_state->apply_view_min_lod &&
|
||||
dynamic_state->view_min_lod) {
|
||||
LLVMValueRef view_min_lod =
|
||||
dynamic_state->view_min_lod(bld->gallivm, bld->resources_type,
|
||||
bld->resources_ptr, sampler_unit, NULL);
|
||||
view_min_lod = lp_build_broadcast_scalar(lodf_bld, view_min_lod);
|
||||
|
||||
lod = lp_build_max(lodf_bld, lod, view_min_lod);
|
||||
}
|
||||
|
||||
if (min_lod) {
|
||||
if (bld->num_lods != bld->coord_type.length) {
|
||||
min_lod = lp_build_pack_aos_scalars(bld->gallivm, bld->coord_bld.type,
|
||||
|
|
|
|||
|
|
@ -221,6 +221,8 @@ struct lp_static_texture_state
|
|||
unsigned level_zero_only:1;
|
||||
unsigned tiled:1;
|
||||
unsigned tiled_samples:5;
|
||||
/**< view min lod clamp (VK_EXT_image_view_min_lod): apply lod = max(lod, view_min_lod) */
|
||||
unsigned apply_view_min_lod:1;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -377,6 +379,13 @@ struct lp_sampler_dynamic_state
|
|||
LLVMValueRef resources_ptr,
|
||||
unsigned sampler_unit);
|
||||
|
||||
/* Obtain the per-view min-lod clamp (returns float, relative to first_level) */
|
||||
LLVMValueRef
|
||||
(*view_min_lod)(struct gallivm_state *gallivm,
|
||||
LLVMTypeRef resources_type,
|
||||
LLVMValueRef resources_ptr,
|
||||
unsigned texture_unit, LLVMValueRef texture_unit_offset);
|
||||
|
||||
/**
|
||||
* Obtain texture cache (returns ptr to lp_build_format_cache).
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2969,10 +2969,35 @@ lp_build_fetch_texel(struct lp_build_sample_context *bld,
|
|||
|
||||
first_level = lp_build_broadcast_scalar(&bld->leveli_bld, first_level);
|
||||
last_level = lp_build_broadcast_scalar(&bld->leveli_bld, last_level);
|
||||
|
||||
LLVMValueRef requested_level = ilevel;
|
||||
lp_build_nearest_mip_level(bld,
|
||||
first_level, last_level,
|
||||
ilevel, &ilevel,
|
||||
out_of_bound_ret_zero ? &out_of_bounds : NULL);
|
||||
|
||||
/* The Vulkan spec defines an OpImageFetch with LOD below the view's
|
||||
* minLodInteger as reading zero.
|
||||
* Since view_min_lod is view-relative, clamp against its floor.
|
||||
*/
|
||||
if (out_of_bound_ret_zero &&
|
||||
bld->static_texture_state->apply_view_min_lod &&
|
||||
bld->dynamic_state->view_min_lod) {
|
||||
LLVMValueRef vml =
|
||||
bld->dynamic_state->view_min_lod(bld->gallivm, bld->resources_type,
|
||||
bld->resources_ptr, texture_unit, NULL);
|
||||
LLVMValueRef min_level =
|
||||
lp_build_broadcast_scalar(&bld->leveli_bld,
|
||||
lp_build_ifloor(&bld->float_bld, vml));
|
||||
LLVMValueRef below = lp_build_cmp(&bld->leveli_bld, PIPE_FUNC_LESS,
|
||||
requested_level, min_level);
|
||||
if (bld->num_mips == 1)
|
||||
below = lp_build_broadcast_scalar(&bld->int_coord_bld, below);
|
||||
else if (bld->num_mips != bld->coord_bld.type.length)
|
||||
below = lp_build_unpack_broadcast_aos_scalars(bld->gallivm,
|
||||
bld->leveli_bld.type, bld->int_coord_bld.type, below);
|
||||
out_of_bounds = lp_build_or(int_coord_bld, out_of_bounds, below);
|
||||
}
|
||||
} else {
|
||||
assert(bld->num_mips == 1);
|
||||
if (bld->static_texture_state->target != PIPE_BUFFER) {
|
||||
|
|
|
|||
|
|
@ -515,8 +515,14 @@ lp_jit_bindless_texture_from_pipe(struct lp_jit_bindless_texture *jit, const str
|
|||
assert(!lp_tex->dt);
|
||||
|
||||
if (llvmpipe_resource_is_texture(res)) {
|
||||
/* Convert the view's min_lod_clamp to view-relative space for the shader. */
|
||||
float view_relative_min_lod =
|
||||
view->u.tex.min_lod_clamp - (float)view->u.tex.first_level;
|
||||
jit->view_min_lod = view_relative_min_lod > 0.0f ? view_relative_min_lod : 0.0f;
|
||||
|
||||
jit->base = lp_tex->tex_data;
|
||||
} else {
|
||||
jit->view_min_lod = 0.0f;
|
||||
jit->base = lp_tex->data;
|
||||
}
|
||||
const void *base = jit->base;
|
||||
|
|
@ -586,6 +592,7 @@ void
|
|||
lp_jit_bindless_texture_buffer_from_bda(struct lp_jit_bindless_texture *jit, void *mem)
|
||||
{
|
||||
jit->base = mem;
|
||||
jit->view_min_lod = 0.0f;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ test_planar_video_formats,Fail
|
|||
test_sample_instructions,Fail
|
||||
|
||||
test_sampler_rounding,Fail
|
||||
test_view_min_lod,Fail
|
||||
|
||||
test_null_descriptor_resinfo_dxbc,Fail
|
||||
test_null_descriptor_resinfo_dxil,Fail
|
||||
|
|
|
|||
|
|
@ -255,6 +255,7 @@ static const struct vk_device_extension_table lvp_device_extensions_supported =
|
|||
.EXT_image_2d_view_of_3d = true,
|
||||
.EXT_image_sliced_view_of_3d = true,
|
||||
.EXT_image_robustness = true,
|
||||
.EXT_image_view_min_lod = true,
|
||||
.EXT_index_type_uint8 = true,
|
||||
.EXT_inline_uniform_block = true,
|
||||
.EXT_load_store_op_none = true,
|
||||
|
|
@ -635,6 +636,9 @@ lvp_get_features(const struct lvp_physical_device *pdevice,
|
|||
/* VK_EXT_image_sliced_view_of_3d */
|
||||
.imageSlicedViewOf3D = true,
|
||||
|
||||
/* VK_EXT_image_view_min_lod */
|
||||
.minLod = true,
|
||||
|
||||
/* VK_EXT_depth_bias_control */
|
||||
.depthBiasControl = true,
|
||||
.leastRepresentableValueForceUnormRepresentation = true,
|
||||
|
|
|
|||
|
|
@ -311,6 +311,7 @@ lvp_create_samplerview(struct pipe_context *pctx, struct lvp_image_view *iv, VkF
|
|||
templ.u.tex.last_layer = iv->vk.base_array_layer + iv->vk.layer_count - 1;
|
||||
templ.u.tex.first_level = iv->vk.base_mip_level;
|
||||
templ.u.tex.last_level = iv->vk.base_mip_level + iv->vk.level_count - 1;
|
||||
templ.u.tex.min_lod_clamp = iv->vk.min_lod;
|
||||
templ.swizzle_r = vk_conv_swizzle(iv->vk.swizzle.r, PIPE_SWIZZLE_X);
|
||||
templ.swizzle_g = vk_conv_swizzle(iv->vk.swizzle.g, PIPE_SWIZZLE_Y);
|
||||
templ.swizzle_b = vk_conv_swizzle(iv->vk.swizzle.b, PIPE_SWIZZLE_Z);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue