Buffer_Cache: Fixes and optimizations.

This commit is contained in:
Fernando Sahmkow 2019-07-19 13:22:27 -04:00 committed by FernandoS27
parent 862bec001b
commit 86d8563314
2 changed files with 38 additions and 68 deletions

View file

@ -15,8 +15,8 @@
#include "common/alignment.h" #include "common/alignment.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "core/core.h" #include "core/core.h"
#include "video_core/buffer_cache/map_interval.h"
#include "video_core/buffer_cache/buffer_block.h" #include "video_core/buffer_cache/buffer_block.h"
#include "video_core/buffer_cache/map_interval.h"
#include "video_core/memory_manager.h" #include "video_core/memory_manager.h"
namespace VideoCore { namespace VideoCore {
@ -42,7 +42,7 @@ public:
const auto cache_addr = ToCacheAddr(host_ptr); const auto cache_addr = ToCacheAddr(host_ptr);
auto block = GetBlock(cache_addr, size); auto block = GetBlock(cache_addr, size);
MapAddress(block, gpu_addr, cache_addr, size, is_written); MapAddress(block, gpu_addr, cache_addr, size);
const u64 offset = static_cast<u64>(block->GetOffset(cache_addr)); const u64 offset = static_cast<u64>(block->GetOffset(cache_addr));
@ -149,86 +149,56 @@ protected:
private: private:
void MapAddress(const TBuffer& block, const GPUVAddr gpu_addr, const CacheAddr cache_addr, void MapAddress(const TBuffer& block, const GPUVAddr gpu_addr, const CacheAddr cache_addr,
const std::size_t size, bool is_written) { const std::size_t size) {
std::vector<MapInterval> overlaps = GetMapsInRange(cache_addr, size); std::vector<MapInterval> overlaps = GetMapsInRange(cache_addr, size);
if (overlaps.empty()) { if (overlaps.empty()) {
const CacheAddr cache_addr_end = cache_addr + size; const CacheAddr cache_addr_end = cache_addr + size;
MapInterval new_interval{cache_addr, cache_addr_end}; MapInterval new_interval{cache_addr, cache_addr_end};
if (!is_written) { u8* host_ptr = FromCacheAddr(cache_addr);
u8* host_ptr = FromCacheAddr(cache_addr); UploadBlockData(block, block->GetOffset(cache_addr), size, host_ptr);
UploadBlockData(block, block->GetOffset(cache_addr), size, host_ptr);
}
Register(new_interval, gpu_addr); Register(new_interval, gpu_addr);
return; return;
} }
const CacheAddr cache_addr_end = cache_addr + size;
if (overlaps.size() == 1) { if (overlaps.size() == 1) {
MapInterval current_map = overlaps[0]; const MapInterval& current_map = overlaps[0];
const CacheAddr cache_addr_end = cache_addr + size;
if (current_map.IsInside(cache_addr, cache_addr_end)) { if (current_map.IsInside(cache_addr, cache_addr_end)) {
return; return;
} }
const CacheAddr new_start = std::min(cache_addr, current_map.start); }
const CacheAddr new_end = std::max(cache_addr_end, current_map.end); CacheAddr new_start = cache_addr;
const GPUVAddr new_gpu_addr = gpu_addr + new_start - cache_addr; CacheAddr new_end = cache_addr_end;
const std::size_t new_size = static_cast<std::size_t>(new_end - new_start); // Calculate new buffer parameters
MapInterval new_interval{new_start, new_end}; for (auto& overlap : overlaps) {
const std::size_t offset = current_map.start - new_start; new_start = std::min(overlap.start, new_start);
const std::size_t size = current_map.end - current_map.start; new_end = std::max(overlap.end, new_end);
// Upload the remaining data }
if (!is_written) { GPUVAddr new_gpu_addr = gpu_addr + new_start - cache_addr;
u8* host_ptr = FromCacheAddr(new_start); for (auto& overlap : overlaps) {
if (new_start == cache_addr && new_end == cache_addr_end) { Unregister(overlap);
std::size_t first_size = current_map.start - new_start; }
if (first_size > 0) { UpdateBlock(block, new_start, new_end, overlaps);
UploadBlockData(block, block->GetOffset(new_start), first_size, host_ptr); MapInterval new_interval{new_start, new_end};
} Register(new_interval, new_gpu_addr);
}
std::size_t second_size = new_end - current_map.end; void UpdateBlock(const TBuffer& block, CacheAddr start, CacheAddr end,
if (second_size > 0) { std::vector<MapInterval>& overlaps) {
u8* host_ptr2 = FromCacheAddr(current_map.end); const IntervalType base_interval{start, end};
UploadBlockData(block, block->GetOffset(current_map.end), second_size, IntervalCache interval_set{};
host_ptr2); interval_set.add(base_interval);
} for (auto& overlap : overlaps) {
} else { const IntervalType subtract{overlap.start, overlap.end};
if (new_start == cache_addr) { interval_set.subtract(subtract);
std::size_t second_size = new_end - current_map.end; }
if (second_size > 0) { for (auto& interval : interval_set) {
u8* host_ptr2 = FromCacheAddr(current_map.end); std::size_t size = interval.upper() - interval.lower();
UploadBlockData(block, block->GetOffset(current_map.end), second_size, if (size > 0) {
host_ptr2); u8* host_ptr = FromCacheAddr(interval.lower());
} UploadBlockData(block, block->GetOffset(interval.lower()), size, host_ptr);
} else {
std::size_t first_size = current_map.start - new_start;
if (first_size > 0) {
UploadBlockData(block, block->GetOffset(new_start), first_size, host_ptr);
}
}
}
} }
Unregister(current_map);
Register(new_interval, new_gpu_addr);
} else {
// Calculate new buffer parameters
GPUVAddr new_gpu_addr = gpu_addr;
CacheAddr start = cache_addr;
CacheAddr end = cache_addr + size;
for (auto& overlap : overlaps) {
start = std::min(overlap.start, start);
end = std::max(overlap.end, end);
}
new_gpu_addr = gpu_addr + start - cache_addr;
MapInterval new_interval{start, end};
for (auto& overlap : overlaps) {
Unregister(overlap);
}
std::size_t new_size = end - start;
if (!is_written) {
u8* host_ptr = FromCacheAddr(start);
UploadBlockData(block, block->GetOffset(start), new_size, host_ptr);
}
Register(new_interval, new_gpu_addr);
} }
} }

View file

@ -14,7 +14,7 @@ struct MapInterval {
MapInterval(const CacheAddr start, const CacheAddr end) : start{start}, end{end} {} MapInterval(const CacheAddr start, const CacheAddr end) : start{start}, end{end} {}
CacheAddr start; CacheAddr start;
CacheAddr end; CacheAddr end;
bool IsInside(const CacheAddr other_start, const CacheAddr other_end) { bool IsInside(const CacheAddr other_start, const CacheAddr other_end) const {
return (start <= other_start && other_end <= end); return (start <= other_start && other_end <= end);
} }