diff options
author | Fernando Sahmkow <fsahmkow27@gmail.com> | 2023-01-05 04:05:20 +0100 |
---|---|---|
committer | Fernando Sahmkow <fsahmkow27@gmail.com> | 2023-01-05 11:23:39 +0100 |
commit | 6c7eb81f7d871f5c08a4844471633a67725aae73 (patch) | |
tree | d642b93700ff8527a7750d20551e96c58a36e90f /src/video_core/invalidation_accumulator.h | |
parent | Merge pull request #9501 from FernandoS27/yfc-rel-2 (diff) | |
download | yuzu-6c7eb81f7d871f5c08a4844471633a67725aae73.tar yuzu-6c7eb81f7d871f5c08a4844471633a67725aae73.tar.gz yuzu-6c7eb81f7d871f5c08a4844471633a67725aae73.tar.bz2 yuzu-6c7eb81f7d871f5c08a4844471633a67725aae73.tar.lz yuzu-6c7eb81f7d871f5c08a4844471633a67725aae73.tar.xz yuzu-6c7eb81f7d871f5c08a4844471633a67725aae73.tar.zst yuzu-6c7eb81f7d871f5c08a4844471633a67725aae73.zip |
Diffstat (limited to 'src/video_core/invalidation_accumulator.h')
-rw-r--r-- | src/video_core/invalidation_accumulator.h | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/video_core/invalidation_accumulator.h b/src/video_core/invalidation_accumulator.h new file mode 100644 index 000000000..42420e31c --- /dev/null +++ b/src/video_core/invalidation_accumulator.h @@ -0,0 +1,78 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <vector> + +#include "common/common_types.h" + +namespace VideoCommon { + +class InvalidationAccumulator { +public: + InvalidationAccumulator() = default; + ~InvalidationAccumulator() = default; + + void Add(GPUVAddr address, size_t size) { + const auto reset_values = [&]() { + if (has_collected) { + buffer.emplace_back(start_address, accumulated_size); + } + start_address = address; + accumulated_size = size; + last_collection = start_address + size; + }; + if (address >= start_address && address + size <= last_collection) [[likely]] { + return; + } + size = (address + size + atomicy_side_mask) & atomicy_mask - address; + address = address & atomicy_mask; + if (!has_collected) [[unlikely]] { + reset_values(); + has_collected = true; + return; + } + if (address != last_collection) [[unlikely]] { + reset_values(); + return; + } + accumulated_size += size; + last_collection += size; + } + + void Clear() { + buffer.clear(); + start_address = 0; + last_collection = 0; + has_collected = false; + } + + bool AnyAccumulated() const { + return has_collected; + } + + template <typename Func> + void Callback(Func&& func) { + if (!has_collected) { + return; + } + buffer.emplace_back(start_address, accumulated_size); + for (auto& [address, size] : buffer) { + func(address, size); + } + } + +private: + static constexpr size_t atomicy_bits = 5; + static constexpr size_t atomicy_size = 1ULL << atomicy_bits; + static constexpr size_t atomicy_side_mask = atomicy_size - 1; + static constexpr size_t atomicy_mask = ~atomicy_side_mask; + GPUVAddr start_address{}; + GPUVAddr last_collection{}; + size_t accumulated_size{}; + bool has_collected{}; + std::vector<std::pair<VAddr, size_t>> buffer; +}; + +} // namespace VideoCommon |