texture_cache: Clamp buffer image height to microtile height (#3261)

Co-authored-by: georgemoralis <giorgosmrls@gmail.com>
This commit is contained in:
TheTurtle 2025-07-18 13:14:41 +03:00 committed by GitHub
parent af67473de3
commit 2ae7037c08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 12 additions and 13 deletions

View File

@ -961,15 +961,15 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr,
const u32 height = std::max(image.info.size.height >> m, 1u); const u32 height = std::max(image.info.size.height >> m, 1u);
const u32 depth = const u32 depth =
image.info.props.is_volume ? std::max(image.info.size.depth >> m, 1u) : 1u; image.info.props.is_volume ? std::max(image.info.size.depth >> m, 1u) : 1u;
const auto& [mip_size, mip_pitch, mip_height, mip_ofs] = image.info.mips_layout[m]; const auto [mip_size, mip_pitch, mip_height, mip_ofs] = image.info.mips_layout[m];
offset += mip_ofs; offset += mip_ofs;
if (offset + mip_size > max_offset) { if (offset + mip_size > max_offset) {
break; break;
} }
copies.push_back({ copies.push_back({
.bufferOffset = offset, .bufferOffset = offset,
.bufferRowLength = static_cast<u32>(mip_pitch), .bufferRowLength = mip_pitch,
.bufferImageHeight = static_cast<u32>(mip_height), .bufferImageHeight = mip_height,
.imageSubresource{ .imageSubresource{
.aspectMask = image.aspect_mask & ~vk::ImageAspectFlagBits::eStencil, .aspectMask = image.aspect_mask & ~vk::ImageAspectFlagBits::eStencil,
.mipLevel = m, .mipLevel = m,

View File

@ -605,28 +605,27 @@ void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_schedule
const u32 height = std::max(image.info.size.height >> m, 1u); const u32 height = std::max(image.info.size.height >> m, 1u);
const u32 depth = const u32 depth =
image.info.props.is_volume ? std::max(image.info.size.depth >> m, 1u) : 1u; image.info.props.is_volume ? std::max(image.info.size.depth >> m, 1u) : 1u;
const auto& mip = image.info.mips_layout[m]; const auto [mip_size, mip_pitch, mip_height, mip_offset] = image.info.mips_layout[m];
// Protect GPU modified resources from accidental CPU reuploads. // Protect GPU modified resources from accidental CPU reuploads.
if (is_gpu_modified && !is_gpu_dirty) { if (is_gpu_modified && !is_gpu_dirty) {
const u8* addr = std::bit_cast<u8*>(image.info.guest_address); const u8* addr = std::bit_cast<u8*>(image.info.guest_address);
const u64 hash = XXH3_64bits(addr + mip.offset, mip.size); const u64 hash = XXH3_64bits(addr + mip_offset, mip_size);
if (image.mip_hashes[m] == hash) { if (image.mip_hashes[m] == hash) {
continue; continue;
} }
image.mip_hashes[m] = hash; image.mip_hashes[m] = hash;
} }
auto mip_pitch = static_cast<u32>(mip.pitch); const u32 extent_width = mip_pitch ? std::min(mip_pitch, width) : width;
auto mip_height = static_cast<u32>(mip.height); const u32 extent_height = mip_height ? std::min(mip_height, height) : height;
const u32 height_aligned =
auto image_extent_width = mip_pitch ? std::min(mip_pitch, width) : width; mip_height && image.info.IsTiled() ? std::max(mip_height, 8U) : mip_height;
auto image_extent_height = mip_height ? std::min(mip_height, height) : height;
image_copy.push_back({ image_copy.push_back({
.bufferOffset = mip.offset, .bufferOffset = mip_offset,
.bufferRowLength = mip_pitch, .bufferRowLength = mip_pitch,
.bufferImageHeight = mip_height ? std::max(mip_height, 8U) : mip_height, .bufferImageHeight = height_aligned,
.imageSubresource{ .imageSubresource{
.aspectMask = image.aspect_mask & ~vk::ImageAspectFlagBits::eStencil, .aspectMask = image.aspect_mask & ~vk::ImageAspectFlagBits::eStencil,
.mipLevel = m, .mipLevel = m,
@ -634,7 +633,7 @@ void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_schedule
.layerCount = num_layers, .layerCount = num_layers,
}, },
.imageOffset = {0, 0, 0}, .imageOffset = {0, 0, 0},
.imageExtent = {image_extent_width, image_extent_height, depth}, .imageExtent = {extent_width, extent_height, depth},
}); });
} }