mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-30 17:18:14 +00:00
texture_cache: apply DCC fast clears of mipmapped color targets
Co-authored-by: Artyom Zabroda <artyomzabroda@gmail.com>
This commit is contained in:
1 parent
ae67e2db51
commit
a5cfdcfd32
7 files changed
+189
-79
No files matched your search
+38
-17
@@ -1043,34 +1043,51 @@ void TextureCache::MaterializeColorClear(ImageId id, const ImageDesc& desc,
|
||||
desc.info.metadata.kind != ImageMetadataKind::Cmask) {
|
||||
return;
|
||||
}
|
||||
const auto range = desc.info.metadata.range;
|
||||
const auto range = desc.info.metadata.range;
|
||||
const auto& view = desc.view_info;
|
||||
{
|
||||
std::scoped_lock lock {m_lock};
|
||||
auto& image = m_slot_images[id];
|
||||
image.info.metadata = desc.info.metadata;
|
||||
// Native color metadata must not retain a reused HTile clear flag.
|
||||
m_surface_metas.erase(range.address);
|
||||
if (range.size == 0 || desc.info.resources.levels != 1) {
|
||||
if (range.size == 0 || view.level_count != 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const auto layers = desc.info.TransferLayers();
|
||||
// These one-mip surfaces use complete 4 KiB color metadata blocks.
|
||||
// Color metadata slices consist of complete 4 KiB blocks.
|
||||
constexpr uint64_t MetadataBlockSize = 0x1000;
|
||||
if (!range.Valid() || range.address % MetadataBlockSize != 0 || layers == 0 ||
|
||||
range.size % layers != 0 || (range.size / layers) % MetadataBlockSize != 0) {
|
||||
EXIT("TextureCache: color metadata slices must contain aligned 4 KiB blocks\n");
|
||||
}
|
||||
const auto& view = desc.view_info;
|
||||
const bool volume_texture = desc.info.IsVolume() && view.type == vk::ImageViewType::e3D;
|
||||
const auto first = volume_texture ? 0u : metadata_base_layer;
|
||||
const auto image_first = volume_texture ? 0u : view.base_layer;
|
||||
const auto count = volume_texture ? desc.info.extent.depth : view.layer_count;
|
||||
const bool volume_texture = desc.info.IsVolume() && view.type == vk::ImageViewType::e3D;
|
||||
const auto first = volume_texture ? 0u : metadata_base_layer;
|
||||
const auto image_first = volume_texture ? 0u : view.base_layer;
|
||||
const auto count =
|
||||
volume_texture ? std::max(desc.info.extent.depth >> view.base_level, 1u) : view.layer_count;
|
||||
if (first >= layers || count > layers - first) {
|
||||
EXIT("TextureCache: color view exceeds its native metadata slices\n");
|
||||
}
|
||||
const auto slice_size = range.size / layers;
|
||||
const GuestRange viewed {range.address + slice_size * first, slice_size * count};
|
||||
const auto slice_size = range.size / layers;
|
||||
// Each slice holds the viewed mip's metadata in one run; DCC mips past the first tail mip
|
||||
// have none. FindImage moves base_level only for one-mip descriptors, which keep the slice.
|
||||
TileSizeOffset mip {.size = static_cast<uint32_t>(slice_size)};
|
||||
if (desc.info.metadata.kind == ImageMetadataKind::Dcc && desc.info.resources.levels > 1) {
|
||||
std::array<TileSizeOffset, 16> mips {};
|
||||
TileSizeAlign total {};
|
||||
(void)TileGetDccSize(desc.info.extent.width, desc.info.extent.height, layers,
|
||||
desc.info.bytes_per_block, desc.info.resources.levels,
|
||||
desc.info.tile_mode, total, 0, mips.data());
|
||||
mip = mips[view.base_level];
|
||||
}
|
||||
if (mip.size == 0) {
|
||||
return;
|
||||
}
|
||||
const GuestRange viewed {range.address + slice_size * first + mip.offset,
|
||||
slice_size * (count - 1) + mip.size};
|
||||
const auto run = [&](uint32_t slice) { return viewed.address + slice_size * slice; };
|
||||
if (m_buffer_cache.IsRegionGpuModified(viewed.address, viewed.size)) {
|
||||
std::array<vk::ClearAttachment, TileManager::ColorClearSlots> clears {};
|
||||
uint32_t keys = 0;
|
||||
@@ -1082,7 +1099,11 @@ void TextureCache::MaterializeColorClear(ImageId id, const ImageDesc& desc,
|
||||
}
|
||||
}
|
||||
// No selected key to clear, or none left since the last check.
|
||||
if (m_buffer_cache.IsColorMetadataChecked(viewed.address, viewed.size, keys)) {
|
||||
bool checked = true;
|
||||
for (uint32_t slice = 0; slice < count && checked; slice++) {
|
||||
checked = m_buffer_cache.IsColorMetadataChecked(run(slice), mip.size, keys);
|
||||
}
|
||||
if (checked) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
@@ -1107,9 +1128,9 @@ void TextureCache::MaterializeColorClear(ImageId id, const ImageDesc& desc,
|
||||
const auto [buffer, offset] =
|
||||
m_buffer_cache.ObtainBuffer(viewed.address, viewed.size, expand);
|
||||
const auto predicates = m_tiler.CheckColorClear(
|
||||
{buffer->Handle(), offset, viewed.size}, count, keys, expand);
|
||||
if (expand) {
|
||||
m_buffer_cache.MarkColorMetadataChecked(viewed.address, viewed.size, keys);
|
||||
{buffer->Handle(), offset, viewed.size}, slice_size, count, keys, expand);
|
||||
for (uint32_t slice = 0; slice < count && expand; slice++) {
|
||||
m_buffer_cache.MarkColorMetadataChecked(run(slice), mip.size, keys);
|
||||
}
|
||||
const auto command = m_scheduler.Current().Handle();
|
||||
const auto area = BeginColorRendering(image, view.format, view.base_level,
|
||||
@@ -1142,7 +1163,7 @@ void TextureCache::MaterializeColorClear(ImageId id, const ImageDesc& desc,
|
||||
m_buffer_cache.ReadMemory(viewed.address, viewed.size, false);
|
||||
}
|
||||
for (uint32_t slice = 0; slice < count; slice++) {
|
||||
const auto address = range.address + slice_size * (first + slice);
|
||||
const auto address = run(slice);
|
||||
uint8_t code = 0;
|
||||
if (!LibKernel::Memory::TryReadBacking(address, &code, sizeof(code))) {
|
||||
EXIT("TextureCache: failed to read color metadata backing\n");
|
||||
@@ -1151,7 +1172,7 @@ void TextureCache::MaterializeColorClear(ImageId id, const ImageDesc& desc,
|
||||
if (!DecodeColorClear(desc, code, clear.color)) {
|
||||
continue;
|
||||
}
|
||||
std::vector<uint8_t> bytes(slice_size);
|
||||
std::vector<uint8_t> bytes(mip.size);
|
||||
if (!LibKernel::Memory::TryReadBacking(address, bytes.data(), bytes.size())) {
|
||||
EXIT("TextureCache: failed to read color metadata slice\n");
|
||||
}
|
||||
@@ -1175,7 +1196,7 @@ void TextureCache::MaterializeColorClear(ImageId id, const ImageDesc& desc,
|
||||
// to overlapping image data. Invalidate the buffer before updating its backing.
|
||||
if (desc.type != BindingType::VideoOut) {
|
||||
std::fill(bytes.begin(), bytes.end(), uint8_t {0xff});
|
||||
m_buffer_cache.InvalidateMemory(address, slice_size);
|
||||
m_buffer_cache.InvalidateMemory(address, bytes.size());
|
||||
LibKernel::Memory::WriteBacking(address, bytes.data(), bytes.size());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user