Texture Cache: Implement Rating System.

This commit is contained in:
Fernando Sahmkow 2021-07-27 01:29:55 +02:00
parent cee7eba64e
commit 07c564f38b
5 changed files with 47 additions and 15 deletions

View File

@ -60,9 +60,9 @@ namespace {
ImageBase::ImageBase(const ImageInfo& info_, GPUVAddr gpu_addr_, VAddr cpu_addr_) ImageBase::ImageBase(const ImageInfo& info_, GPUVAddr gpu_addr_, VAddr cpu_addr_)
: info{info_}, guest_size_bytes{CalculateGuestSizeInBytes(info)}, : info{info_}, guest_size_bytes{CalculateGuestSizeInBytes(info)},
unswizzled_size_bytes{CalculateUnswizzledSizeBytes(info)}, unswizzled_size_bytes{CalculateUnswizzledSizeBytes(info)},
converted_size_bytes{CalculateConvertedSizeBytes(info)}, gpu_addr{gpu_addr_}, converted_size_bytes{CalculateConvertedSizeBytes(info)}, scale_rating{},
cpu_addr{cpu_addr_}, cpu_addr_end{cpu_addr + guest_size_bytes}, scale_tick{}, gpu_addr{gpu_addr_}, cpu_addr{cpu_addr_},
mip_level_offsets{CalculateMipLevelOffsets(info)} { cpu_addr_end{cpu_addr + guest_size_bytes}, mip_level_offsets{CalculateMipLevelOffsets(info)} {
if (info.type == ImageType::e3D) { if (info.type == ImageType::e3D) {
slice_offsets = CalculateSliceOffsets(info); slice_offsets = CalculateSliceOffsets(info);
slice_subresources = CalculateSliceSubresources(info); slice_subresources = CalculateSliceSubresources(info);

View File

@ -78,6 +78,8 @@ struct ImageBase {
u32 guest_size_bytes = 0; u32 guest_size_bytes = 0;
u32 unswizzled_size_bytes = 0; u32 unswizzled_size_bytes = 0;
u32 converted_size_bytes = 0; u32 converted_size_bytes = 0;
u32 scale_rating = 0;
u64 scale_tick = 0;
ImageFlagBits flags = ImageFlagBits::CpuModified; ImageFlagBits flags = ImageFlagBits::CpuModified;
GPUVAddr gpu_addr = 0; GPUVAddr gpu_addr = 0;

View File

@ -31,6 +31,7 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept {
.depth = config.block_depth, .depth = config.block_depth,
}; };
} }
rescaleable = false;
tile_width_spacing = config.tile_width_spacing; tile_width_spacing = config.tile_width_spacing;
if (config.texture_type != TextureType::Texture2D && if (config.texture_type != TextureType::Texture2D &&
config.texture_type != TextureType::Texture2DNoMipmap) { config.texture_type != TextureType::Texture2DNoMipmap) {
@ -53,12 +54,14 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept {
case TextureType::Texture2DNoMipmap: case TextureType::Texture2DNoMipmap:
ASSERT(config.Depth() == 1); ASSERT(config.Depth() == 1);
type = config.IsPitchLinear() ? ImageType::Linear : ImageType::e2D; type = config.IsPitchLinear() ? ImageType::Linear : ImageType::e2D;
rescaleable = !config.IsPitchLinear();
size.width = config.Width(); size.width = config.Width();
size.height = config.Height(); size.height = config.Height();
resources.layers = config.BaseLayer() + 1; resources.layers = config.BaseLayer() + 1;
break; break;
case TextureType::Texture2DArray: case TextureType::Texture2DArray:
type = ImageType::e2D; type = ImageType::e2D;
rescaleable = true;
size.width = config.Width(); size.width = config.Width();
size.height = config.Height(); size.height = config.Height();
resources.layers = config.BaseLayer() + config.Depth(); resources.layers = config.BaseLayer() + config.Depth();
@ -98,12 +101,14 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept {
// FIXME: Call this without passing *this // FIXME: Call this without passing *this
layer_stride = CalculateLayerStride(*this); layer_stride = CalculateLayerStride(*this);
maybe_unaligned_layer_stride = CalculateLayerSize(*this); maybe_unaligned_layer_stride = CalculateLayerSize(*this);
rescaleable &= (block.depth == 0) && resources.levels == 1;
} }
} }
ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index) noexcept { ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index) noexcept {
const auto& rt = regs.rt[index]; const auto& rt = regs.rt[index];
format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(rt.format); format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(rt.format);
rescaleable = false;
if (rt.tile_mode.is_pitch_linear) { if (rt.tile_mode.is_pitch_linear) {
ASSERT(rt.tile_mode.is_3d == 0); ASSERT(rt.tile_mode.is_3d == 0);
type = ImageType::Linear; type = ImageType::Linear;
@ -129,6 +134,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index)
type = ImageType::e3D; type = ImageType::e3D;
size.depth = rt.depth; size.depth = rt.depth;
} else { } else {
rescaleable = block.depth == 0 && size.height > 256;
type = ImageType::e2D; type = ImageType::e2D;
resources.layers = rt.depth; resources.layers = rt.depth;
} }
@ -138,6 +144,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept {
format = VideoCore::Surface::PixelFormatFromDepthFormat(regs.zeta.format); format = VideoCore::Surface::PixelFormatFromDepthFormat(regs.zeta.format);
size.width = regs.zeta_width; size.width = regs.zeta_width;
size.height = regs.zeta_height; size.height = regs.zeta_height;
rescaleable = false;
resources.levels = 1; resources.levels = 1;
layer_stride = regs.zeta.layer_stride * 4; layer_stride = regs.zeta.layer_stride * 4;
maybe_unaligned_layer_stride = layer_stride; maybe_unaligned_layer_stride = layer_stride;
@ -156,6 +163,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept {
type = ImageType::e3D; type = ImageType::e3D;
size.depth = regs.zeta_depth; size.depth = regs.zeta_depth;
} else { } else {
rescaleable = block.depth == 0 && size.height > 256;
type = ImageType::e2D; type = ImageType::e2D;
resources.layers = regs.zeta_depth; resources.layers = regs.zeta_depth;
} }
@ -164,6 +172,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept {
ImageInfo::ImageInfo(const Tegra::Engines::Fermi2D::Surface& config) noexcept { ImageInfo::ImageInfo(const Tegra::Engines::Fermi2D::Surface& config) noexcept {
UNIMPLEMENTED_IF_MSG(config.layer != 0, "Surface layer is not zero"); UNIMPLEMENTED_IF_MSG(config.layer != 0, "Surface layer is not zero");
format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(config.format); format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(config.format);
rescaleable = false;
if (config.linear == Tegra::Engines::Fermi2D::MemoryLayout::Pitch) { if (config.linear == Tegra::Engines::Fermi2D::MemoryLayout::Pitch) {
type = ImageType::Linear; type = ImageType::Linear;
size = Extent3D{ size = Extent3D{
@ -174,6 +183,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Fermi2D::Surface& config) noexcept {
pitch = config.pitch; pitch = config.pitch;
} else { } else {
type = config.block_depth > 0 ? ImageType::e3D : ImageType::e2D; type = config.block_depth > 0 ? ImageType::e3D : ImageType::e2D;
block = Extent3D{ block = Extent3D{
.width = config.block_width, .width = config.block_width,
.height = config.block_height, .height = config.block_height,
@ -186,6 +196,7 @@ ImageInfo::ImageInfo(const Tegra::Engines::Fermi2D::Surface& config) noexcept {
.height = config.height, .height = config.height,
.depth = 1, .depth = 1,
}; };
rescaleable = block.depth == 0 && size.height > 256;
} }
} }

View File

@ -33,6 +33,7 @@ struct ImageInfo {
u32 maybe_unaligned_layer_stride = 0; u32 maybe_unaligned_layer_stride = 0;
u32 num_samples = 1; u32 num_samples = 1;
u32 tile_width_spacing = 0; u32 tile_width_spacing = 0;
bool rescaleable = false;
}; };
} // namespace VideoCommon } // namespace VideoCommon

View File

@ -216,7 +216,10 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
return; return;
} }
u32 scale_rating;
bool rescaled; bool rescaled;
std::array<ImageId, NUM_RT> tmp_color_images{};
ImageId tmp_depth_image{};
do { do {
flags[Dirty::RenderTargets] = false; flags[Dirty::RenderTargets] = false;
@ -226,10 +229,10 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
const bool force = flags[Dirty::RenderTargetControl]; const bool force = flags[Dirty::RenderTargetControl];
flags[Dirty::RenderTargetControl] = false; flags[Dirty::RenderTargetControl] = false;
scale_rating = 0;
bool any_rescaled = false;
bool can_rescale = true; bool can_rescale = true;
bool any_blacklisted = false; bool any_blacklisted = false;
std::array<ImageId, NUM_RT> tmp_color_images{};
ImageId tmp_depth_image{};
const auto check_rescale = [&](ImageViewId view_id, ImageId& id_save) { const auto check_rescale = [&](ImageViewId view_id, ImageId& id_save) {
if (view_id) { if (view_id) {
const auto& view = slot_image_views[view_id]; const auto& view = slot_image_views[view_id];
@ -238,6 +241,10 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
auto& image = slot_images[image_id]; auto& image = slot_images[image_id];
can_rescale &= ImageCanRescale(image); can_rescale &= ImageCanRescale(image);
any_blacklisted |= True(image.flags & ImageFlagBits::Blacklisted); any_blacklisted |= True(image.flags & ImageFlagBits::Blacklisted);
any_rescaled |= True(image.flags & ImageFlagBits::Rescaled);
scale_rating = std::max<u32>(scale_rating, image.scale_tick <= frame_tick
? image.scale_rating + 1U
: image.scale_rating);
} else { } else {
id_save = CORRUPT_ID; id_save = CORRUPT_ID;
} }
@ -257,17 +264,19 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
check_rescale(render_targets.depth_buffer_id, tmp_depth_image); check_rescale(render_targets.depth_buffer_id, tmp_depth_image);
if (can_rescale) { if (can_rescale) {
rescaled = true; rescaled = any_rescaled || scale_rating >= 2;
const auto scale_up = [this](ImageId image_id) { const auto scale_up = [this](ImageId image_id) {
if (image_id != CORRUPT_ID) { if (image_id != CORRUPT_ID) {
Image& image = slot_images[image_id]; Image& image = slot_images[image_id];
ScaleUp(image); ScaleUp(image);
} }
}; };
if (rescaled) {
for (size_t index = 0; index < NUM_RT; ++index) { for (size_t index = 0; index < NUM_RT; ++index) {
scale_up(tmp_color_images[index]); scale_up(tmp_color_images[index]);
} }
scale_up(tmp_depth_image); scale_up(tmp_depth_image);
}
} else { } else {
rescaled = false; rescaled = false;
const auto scale_down = [this, any_blacklisted](ImageId image_id) { const auto scale_down = [this, any_blacklisted](ImageId image_id) {
@ -283,10 +292,23 @@ void TextureCache<P>::UpdateRenderTargets(bool is_clear) {
scale_down(tmp_color_images[index]); scale_down(tmp_color_images[index]);
} }
scale_down(tmp_depth_image); scale_down(tmp_depth_image);
scale_rating = 0;
} }
} while (has_deleted_images); } while (has_deleted_images);
// Rescale End // Rescale End
const auto set_rating = [this, scale_rating](ImageId image_id) {
if (image_id != CORRUPT_ID) {
Image& image = slot_images[image_id];
image.scale_rating = scale_rating;
image.scale_tick = frame_tick + 1;
}
};
for (size_t index = 0; index < NUM_RT; ++index) {
set_rating(tmp_color_images[index]);
}
set_rating(tmp_depth_image);
if (is_rescaling != rescaled) { if (is_rescaling != rescaled) {
flags[Dirty::RescaleViewports] = true; flags[Dirty::RescaleViewports] = true;
flags[Dirty::RescaleScissors] = true; flags[Dirty::RescaleScissors] = true;
@ -761,10 +783,7 @@ bool TextureCache<P>::ImageCanRescale(Image& image) {
True(image.flags & ImageFlagBits::RescaleChecked)) { True(image.flags & ImageFlagBits::RescaleChecked)) {
return true; return true;
} }
const auto& info = image.info; if (!image.info.rescaleable) {
const bool can_this_rescale =
(info.type == ImageType::e1D || info.type == ImageType::e2D) && info.block.depth == 0;
if (!can_this_rescale) {
image.flags &= ~ImageFlagBits::RescaleChecked; image.flags &= ~ImageFlagBits::RescaleChecked;
return false; return false;
} }
@ -928,8 +947,7 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA
}; };
ForEachSparseImageInRegion(gpu_addr, size_bytes, region_check_gpu); ForEachSparseImageInRegion(gpu_addr, size_bytes, region_check_gpu);
bool can_rescale = bool can_rescale = info.rescaleable;
(info.type == ImageType::e1D || info.type == ImageType::e2D) && info.block.depth == 0;
bool any_rescaled = false; bool any_rescaled = false;
bool any_blacklisted = false; bool any_blacklisted = false;
for (const ImageId sibling_id : all_siblings) { for (const ImageId sibling_id : all_siblings) {