This commit is contained in:
itsmattbytes 2026-06-26 19:03:29 +03:00 committed by GitHub
commit bdc7065fbe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 31 additions and 8 deletions

View File

@ -710,12 +710,19 @@ void Rasterizer::BindTextures(const Shader::Info& stage, Shader::Backend::Bindin
if (mip_fallback_mode == Shader::MipStorageFallbackMode::ConstantIndex) {
ASSERT(num_bindings == 1);
desc.view_info.range.base.level += image_desc.constant_mip_index;
// Cap to the last available mip so the view range stays within the image's
// actual subresources. Out-of-range constant LODs can occur when the shader's
// LOD immediate exceeds the TSHARP's last_level.
desc.view_info.range.base.level =
std::min(desc.view_info.range.base.level, desc.info.resources.levels - 1);
desc.view_info.range.extent.levels = 1;
} else if (mip_fallback_mode == Shader::MipStorageFallbackMode::DynamicIndex) {
desc.view_info.range.base.level += i;
desc.view_info.range.extent.levels = 1;
}
// Save range before FindImage can overwrite base.level/base.layer from a parent image.
desc.initial_range = desc.view_info.range;
image_id = texture_cache.FindImage(desc);
auto* image = &texture_cache.GetImage(image_id);
if (auto depth_image_id = texture_cache.GetAssociatedDepth(*image)) {
@ -747,10 +754,22 @@ void Rasterizer::BindTextures(const Shader::Info& stage, Shader::Backend::Bindin
vk::ImageLayout::eGeneral);
}
} else {
if (auto& old_image = texture_cache.GetImage(image_id);
old_image.binding.needs_rebind) {
old_image.binding = {};
image_id = texture_cache.FindImage(desc);
{
auto& old_image = texture_cache.GetImage(image_id);
// Re-find if (a) ExpandImage marked this image for rebind, or (b) the slot was
// silently reused between passes by another TSHARP's FindImage — detected by the
// stored range now being OOB for whatever image lives in that slot.
const bool range_oob =
desc.view_info.range.base.level >= old_image.info.resources.levels ||
desc.view_info.range.base.layer >= old_image.info.resources.layers;
const bool needs_rebind = old_image.binding.needs_rebind;
if (needs_rebind || range_oob) {
old_image.binding = {};
// Restore the pre-FindImage range so FindImage recomputes view_slice/view_mip
// against whatever image the cache currently holds.
desc.view_info.range = desc.initial_range;
image_id = texture_cache.FindImage(desc);
}
}
bound_images.emplace_back(image_id);

View File

@ -59,8 +59,8 @@ ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageReso
format = Vulkan::LiverpoolToVK::PromoteFormatToDepth(format);
}
range.base.level = image.base_level;
range.base.layer = image.base_array;
range.base.level = std::min<u32>(image.base_level, image.NumLevels() - 1);
range.base.layer = std::min<u32>(image.base_array, image.NumLayers() - 1);
range.extent.levels = image.NumViewLevels(desc.is_array);
range.extent.layers = image.NumViewLayers(desc.is_array);
type = image.GetViewType(desc.is_array);

View File

@ -581,8 +581,10 @@ ImageId TextureCache::FindImage(ImageDesc& desc, bool exact_fmt) {
if (exact_fmt && info.pixel_format != image_resolved.info.pixel_format) {
// Cannot reuse this image as we need the exact requested format.
image_id = {};
} else if (image_resolved.info.resources < info.resources) {
// The image was clearly picked up wrong.
} else if (image_resolved.info.resources.levels < info.resources.levels ||
image_resolved.info.resources.layers < info.resources.layers) {
// SubresourceExtent's default operator< is lexicographic: {3 levels, 1 layer} is not
// less than {1 level, 6 layers} because levels=3 > levels=1 stops the comparison.
FreeImage(image_id);
image_id = {};
LOG_WARNING(Render_Vulkan, "Image overlap resolve failed");

View File

@ -58,6 +58,8 @@ public:
struct ImageDesc {
ImageInfo info;
ImageViewInfo view_info;
// Saved before FindImage can overwrite base.level/base.layer; restored before rebind.
SubresourceRange initial_range{};
BindingType type{BindingType::Texture};
ImageDesc() = default;