virtual_buffer.h 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. // Copyright 2020 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <type_traits>
  6. #include <utility>
  7. namespace Common {
  8. void* AllocateMemoryPages(std::size_t size) noexcept;
  9. void FreeMemoryPages(void* base, std::size_t size) noexcept;
  10. template <typename T>
  11. class VirtualBuffer final {
  12. public:
  13. // TODO: Uncomment this and change Common::PageTable::PageInfo to be trivially constructible
  14. // using std::atomic_ref once libc++ has support for it
  15. // static_assert(
  16. // std::is_trivially_constructible_v<T>,
  17. // "T must be trivially constructible, as non-trivial constructors will not be executed "
  18. // "with the current allocator");
  19. constexpr VirtualBuffer() = default;
  20. explicit VirtualBuffer(std::size_t count) : alloc_size{count * sizeof(T)} {
  21. base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size));
  22. }
  23. ~VirtualBuffer() noexcept {
  24. FreeMemoryPages(base_ptr, alloc_size);
  25. }
  26. VirtualBuffer(const VirtualBuffer&) = delete;
  27. VirtualBuffer& operator=(const VirtualBuffer&) = delete;
  28. VirtualBuffer(VirtualBuffer&& other) noexcept
  29. : alloc_size{std::exchange(other.alloc_size, 0)}, base_ptr{std::exchange(other.base_ptr),
  30. nullptr} {}
  31. VirtualBuffer& operator=(VirtualBuffer&& other) noexcept {
  32. alloc_size = std::exchange(other.alloc_size, 0);
  33. base_ptr = std::exchange(other.base_ptr, nullptr);
  34. return *this;
  35. }
  36. void resize(std::size_t count) {
  37. const auto new_size = count * sizeof(T);
  38. if (new_size == alloc_size) {
  39. return;
  40. }
  41. FreeMemoryPages(base_ptr, alloc_size);
  42. alloc_size = new_size;
  43. base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size));
  44. }
  45. [[nodiscard]] constexpr const T& operator[](std::size_t index) const {
  46. return base_ptr[index];
  47. }
  48. [[nodiscard]] constexpr T& operator[](std::size_t index) {
  49. return base_ptr[index];
  50. }
  51. [[nodiscard]] constexpr T* data() {
  52. return base_ptr;
  53. }
  54. [[nodiscard]] constexpr const T* data() const {
  55. return base_ptr;
  56. }
  57. [[nodiscard]] constexpr std::size_t size() const {
  58. return alloc_size / sizeof(T);
  59. }
  60. private:
  61. std::size_t alloc_size{};
  62. T* base_ptr{};
  63. };
  64. } // namespace Common