Texture Cache: make sparse texture table per channel

This commit is contained in:
Fernando Sahmkow 2024-01-30 11:52:41 +01:00
parent ffe3984353
commit a7c1306e2d
2 changed files with 51 additions and 40 deletions

View file

@ -1431,7 +1431,8 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, DA
} }
} }
}; };
ForEachSparseImageInRegion(gpu_addr, size_bytes, region_check_gpu); ForEachSparseImageInRegion(channel_state->gpu_memory.GetID(), gpu_addr, size_bytes,
region_check_gpu);
bool can_rescale = info.rescaleable; bool can_rescale = info.rescaleable;
bool any_rescaled = false; bool any_rescaled = false;
@ -1842,7 +1843,7 @@ void TextureCache<P>::ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, s
if (!storage_id) { if (!storage_id) {
return; return;
} }
auto& gpu_page_table = gpu_page_table_storage[*storage_id]; auto& gpu_page_table = gpu_page_table_storage[*storage_id * 2];
ForEachGPUPage(gpu_addr, size, ForEachGPUPage(gpu_addr, size,
[this, &gpu_page_table, &images, gpu_addr, size, func](u64 page) { [this, &gpu_page_table, &images, gpu_addr, size, func](u64 page) {
const auto it = gpu_page_table.find(page); const auto it = gpu_page_table.find(page);
@ -1882,41 +1883,48 @@ void TextureCache<P>::ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, s
template <class P> template <class P>
template <typename Func> template <typename Func>
void TextureCache<P>::ForEachSparseImageInRegion(GPUVAddr gpu_addr, size_t size, Func&& func) { void TextureCache<P>::ForEachSparseImageInRegion(size_t as_id, GPUVAddr gpu_addr, size_t size,
Func&& func) {
using FuncReturn = typename std::invoke_result<Func, ImageId, Image&>::type; using FuncReturn = typename std::invoke_result<Func, ImageId, Image&>::type;
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>; static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
boost::container::small_vector<ImageId, 8> images; boost::container::small_vector<ImageId, 8> images;
ForEachGPUPage(gpu_addr, size, [this, &images, gpu_addr, size, func](u64 page) { auto storage_id = getStorageID(as_id);
const auto it = sparse_page_table.find(page); if (!storage_id) {
if (it == sparse_page_table.end()) { return;
if constexpr (BOOL_BREAK) { }
return false; auto& sparse_page_table = gpu_page_table_storage[*storage_id * 2 + 1];
} else { ForEachGPUPage(gpu_addr, size,
return; [this, &sparse_page_table, &images, gpu_addr, size, func](u64 page) {
} const auto it = sparse_page_table.find(page);
} if (it == sparse_page_table.end()) {
for (const ImageId image_id : it->second) { if constexpr (BOOL_BREAK) {
Image& image = slot_images[image_id]; return false;
if (True(image.flags & ImageFlagBits::Picked)) { } else {
continue; return;
} }
if (!image.OverlapsGPU(gpu_addr, size)) { }
continue; for (const ImageId image_id : it->second) {
} Image& image = slot_images[image_id];
image.flags |= ImageFlagBits::Picked; if (True(image.flags & ImageFlagBits::Picked)) {
images.push_back(image_id); continue;
if constexpr (BOOL_BREAK) { }
if (func(image_id, image)) { if (!image.OverlapsGPU(gpu_addr, size)) {
return true; continue;
} }
} else { image.flags |= ImageFlagBits::Picked;
func(image_id, image); images.push_back(image_id);
} if constexpr (BOOL_BREAK) {
} if (func(image_id, image)) {
if constexpr (BOOL_BREAK) { return true;
return false; }
} } else {
}); func(image_id, image);
}
}
if constexpr (BOOL_BREAK) {
return false;
}
});
for (const ImageId image_id : images) { for (const ImageId image_id : images) {
slot_images[image_id].flags &= ~ImageFlagBits::Picked; slot_images[image_id].flags &= ~ImageFlagBits::Picked;
} }
@ -1988,8 +1996,9 @@ void TextureCache<P>::RegisterImage(ImageId image_id) {
sparse_maps.push_back(map_id); sparse_maps.push_back(map_id);
}); });
sparse_views.emplace(image_id, std::move(sparse_maps)); sparse_views.emplace(image_id, std::move(sparse_maps));
ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, image_id](u64 page) {
[this, image_id](u64 page) { sparse_page_table[page].push_back(image_id); }); (*channel_state->sparse_page_table)[page].push_back(image_id);
});
} }
template <class P> template <class P>
@ -2042,7 +2051,7 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) {
return; return;
} }
ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, &clear_page_table](u64 page) { ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, &clear_page_table](u64 page) {
clear_page_table(page, sparse_page_table); clear_page_table(page, (*channel_state->sparse_page_table));
}); });
auto it = sparse_views.find(image_id); auto it = sparse_views.find(image_id);
ASSERT(it != sparse_views.end()); ASSERT(it != sparse_views.end());
@ -2496,13 +2505,15 @@ void TextureCache<P>::CreateChannel(struct Tegra::Control::ChannelState& channel
const auto it = channel_map.find(channel.bind_id); const auto it = channel_map.find(channel.bind_id);
auto* this_state = &channel_storage[it->second]; auto* this_state = &channel_storage[it->second];
const auto& this_as_ref = address_spaces[channel.memory_manager->GetID()]; const auto& this_as_ref = address_spaces[channel.memory_manager->GetID()];
this_state->gpu_page_table = &gpu_page_table_storage[this_as_ref.storage_id]; this_state->gpu_page_table = &gpu_page_table_storage[this_as_ref.storage_id * 2];
this_state->sparse_page_table = &gpu_page_table_storage[this_as_ref.storage_id * 2 + 1];
} }
/// Bind a channel for execution. /// Bind a channel for execution.
template <class P> template <class P>
void TextureCache<P>::OnGPUASRegister([[maybe_unused]] size_t map_id) { void TextureCache<P>::OnGPUASRegister([[maybe_unused]] size_t map_id) {
gpu_page_table_storage.emplace_back(); gpu_page_table_storage.emplace_back();
gpu_page_table_storage.emplace_back();
} }
} // namespace VideoCommon } // namespace VideoCommon

View file

@ -86,6 +86,7 @@ public:
std::unordered_map<TSCEntry, SamplerId> samplers; std::unordered_map<TSCEntry, SamplerId> samplers;
TextureCacheGPUMap* gpu_page_table; TextureCacheGPUMap* gpu_page_table;
TextureCacheGPUMap* sparse_page_table;
}; };
template <class P> template <class P>
@ -357,7 +358,7 @@ private:
void ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func); void ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func);
template <typename Func> template <typename Func>
void ForEachSparseImageInRegion(GPUVAddr gpu_addr, size_t size, Func&& func); void ForEachSparseImageInRegion(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func);
/// Iterates over all the images in a region calling func /// Iterates over all the images in a region calling func
template <typename Func> template <typename Func>
@ -431,7 +432,6 @@ private:
std::unordered_map<RenderTargets, FramebufferId> framebuffers; std::unordered_map<RenderTargets, FramebufferId> framebuffers;
std::unordered_map<u64, std::vector<ImageMapId>, Common::IdentityHash<u64>> page_table; std::unordered_map<u64, std::vector<ImageMapId>, Common::IdentityHash<u64>> page_table;
std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>> sparse_page_table;
std::unordered_map<ImageId, boost::container::small_vector<ImageViewId, 16>> sparse_views; std::unordered_map<ImageId, boost::container::small_vector<ImageViewId, 16>> sparse_views;
DAddr virtual_invalid_space{}; DAddr virtual_invalid_space{};