diff options
author | Fernando S <fsahmkow27@gmail.com> | 2023-01-06 13:31:39 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-06 13:31:39 +0100 |
commit | 5bcbb8de45540bee7a64b7b1867f61c57f51ab88 (patch) | |
tree | 49fd1c79dfefba1139ad1577a414ed07293ecf81 /src/video_core/invalidation_accumulator.h | |
parent | Merge pull request #9564 from FernandoS27/oops-i-did-it-again (diff) | |
parent | BufferBase: Don't ignore GPU pages. (diff) | |
download | yuzu-5bcbb8de45540bee7a64b7b1867f61c57f51ab88.tar yuzu-5bcbb8de45540bee7a64b7b1867f61c57f51ab88.tar.gz yuzu-5bcbb8de45540bee7a64b7b1867f61c57f51ab88.tar.bz2 yuzu-5bcbb8de45540bee7a64b7b1867f61c57f51ab88.tar.lz yuzu-5bcbb8de45540bee7a64b7b1867f61c57f51ab88.tar.xz yuzu-5bcbb8de45540bee7a64b7b1867f61c57f51ab88.tar.zst yuzu-5bcbb8de45540bee7a64b7b1867f61c57f51ab88.zip |
Diffstat (limited to 'src/video_core/invalidation_accumulator.h')
-rw-r--r-- | src/video_core/invalidation_accumulator.h | 79 |
1 files changed, 79 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..2c2aaf7bb --- /dev/null +++ b/src/video_core/invalidation_accumulator.h @@ -0,0 +1,79 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <utility> +#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 + atomicity_size_mask) & atomicity_mask) - address; + address = address & atomicity_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 atomicity_bits = 5; + static constexpr size_t atomicity_size = 1ULL << atomicity_bits; + static constexpr size_t atomicity_size_mask = atomicity_size - 1; + static constexpr size_t atomicity_mask = ~atomicity_size_mask; + GPUVAddr start_address{}; + GPUVAddr last_collection{}; + size_t accumulated_size{}; + bool has_collected{}; + std::vector<std::pair<VAddr, size_t>> buffer; +}; + +} // namespace VideoCommon |