virtual_buffer.h 2.3 KB

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