Browse Source
Merge pull request #2256 from bunnei/gpu-vmm
Merge pull request #2256 from bunnei/gpu-vmm
gpu: Rewrite MemoryManager based on the VMManager implementation.pull/15/merge
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 550 additions and 257 deletions
-
7src/common/common_types.h
-
2src/common/page_table.cpp
-
6src/common/page_table.h
-
16src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
-
2src/core/memory.cpp
-
1src/video_core/dma_pusher.h
-
2src/video_core/engines/kepler_memory.cpp
-
8src/video_core/engines/maxwell_3d.cpp
-
10src/video_core/engines/maxwell_dma.cpp
-
7src/video_core/gpu.cpp
-
6src/video_core/gpu.h
-
482src/video_core/memory_manager.cpp
-
170src/video_core/memory_manager.h
-
1src/video_core/rasterizer_interface.h
-
4src/video_core/renderer_opengl/gl_buffer_cache.cpp
-
2src/video_core/renderer_opengl/gl_buffer_cache.h
-
6src/video_core/renderer_opengl/gl_global_cache.cpp
-
2src/video_core/renderer_opengl/gl_global_cache.h
-
3src/video_core/renderer_opengl/gl_primitive_assembler.cpp
-
2src/video_core/renderer_opengl/gl_primitive_assembler.h
-
8src/video_core/renderer_opengl/gl_rasterizer.cpp
-
35src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
-
11src/video_core/renderer_opengl/gl_rasterizer_cache.h
-
4src/video_core/renderer_opengl/gl_shader_cache.cpp
-
3src/video_core/renderer_vulkan/vk_buffer_cache.cpp
-
3src/video_core/renderer_vulkan/vk_buffer_cache.h
-
2src/yuzu/debugger/graphics/graphics_surface.cpp
-
2src/yuzu/debugger/graphics/graphics_surface.h
@ -1,82 +1,148 @@ |
|||||
// Copyright 2018 yuzu emulator team |
|
||||
|
// Copyright 2018 yuzu emulator team |
||||
// Licensed under GPLv2 or any later version |
// Licensed under GPLv2 or any later version |
||||
// Refer to the license.txt file included. |
// Refer to the license.txt file included. |
||||
|
|
||||
#pragma once |
#pragma once |
||||
|
|
||||
#include <array> |
|
||||
#include <memory> |
|
||||
|
#include <map> |
||||
#include <optional> |
#include <optional> |
||||
#include <vector> |
|
||||
|
|
||||
#include "common/common_types.h" |
#include "common/common_types.h" |
||||
|
#include "common/page_table.h" |
||||
|
|
||||
namespace Tegra { |
namespace Tegra { |
||||
|
|
||||
/// Virtual addresses in the GPU's memory map are 64 bit. |
|
||||
using GPUVAddr = u64; |
|
||||
|
/** |
||||
|
* Represents a VMA in an address space. A VMA is a contiguous region of virtual addressing space |
||||
|
* with homogeneous attributes across its extents. In this particular implementation each VMA is |
||||
|
* also backed by a single host memory allocation. |
||||
|
*/ |
||||
|
struct VirtualMemoryArea { |
||||
|
enum class Type : u8 { |
||||
|
Unmapped, |
||||
|
Allocated, |
||||
|
Mapped, |
||||
|
}; |
||||
|
|
||||
|
/// Virtual base address of the region. |
||||
|
GPUVAddr base{}; |
||||
|
/// Size of the region. |
||||
|
u64 size{}; |
||||
|
/// Memory area mapping type. |
||||
|
Type type{Type::Unmapped}; |
||||
|
/// CPU memory mapped address corresponding to this memory area. |
||||
|
VAddr backing_addr{}; |
||||
|
/// Offset into the backing_memory the mapping starts from. |
||||
|
std::size_t offset{}; |
||||
|
/// Pointer backing this VMA. |
||||
|
u8* backing_memory{}; |
||||
|
|
||||
|
/// Tests if this area can be merged to the right with `next`. |
||||
|
bool CanBeMergedWith(const VirtualMemoryArea& next) const; |
||||
|
}; |
||||
|
|
||||
class MemoryManager final { |
class MemoryManager final { |
||||
public: |
public: |
||||
MemoryManager(); |
MemoryManager(); |
||||
|
|
||||
GPUVAddr AllocateSpace(u64 size, u64 align); |
GPUVAddr AllocateSpace(u64 size, u64 align); |
||||
GPUVAddr AllocateSpace(GPUVAddr gpu_addr, u64 size, u64 align); |
|
||||
|
GPUVAddr AllocateSpace(GPUVAddr addr, u64 size, u64 align); |
||||
GPUVAddr MapBufferEx(VAddr cpu_addr, u64 size); |
GPUVAddr MapBufferEx(VAddr cpu_addr, u64 size); |
||||
GPUVAddr MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size); |
|
||||
GPUVAddr UnmapBuffer(GPUVAddr gpu_addr, u64 size); |
|
||||
GPUVAddr GetRegionEnd(GPUVAddr region_start) const; |
|
||||
std::optional<VAddr> GpuToCpuAddress(GPUVAddr gpu_addr); |
|
||||
|
|
||||
static constexpr u64 PAGE_BITS = 16; |
|
||||
static constexpr u64 PAGE_SIZE = 1 << PAGE_BITS; |
|
||||
static constexpr u64 PAGE_MASK = PAGE_SIZE - 1; |
|
||||
|
GPUVAddr MapBufferEx(VAddr cpu_addr, GPUVAddr addr, u64 size); |
||||
|
GPUVAddr UnmapBuffer(GPUVAddr addr, u64 size); |
||||
|
std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr); |
||||
|
|
||||
u8 Read8(GPUVAddr addr); |
|
||||
u16 Read16(GPUVAddr addr); |
|
||||
u32 Read32(GPUVAddr addr); |
|
||||
u64 Read64(GPUVAddr addr); |
|
||||
|
template <typename T> |
||||
|
T Read(GPUVAddr addr); |
||||
|
|
||||
void Write8(GPUVAddr addr, u8 data); |
|
||||
void Write16(GPUVAddr addr, u16 data); |
|
||||
void Write32(GPUVAddr addr, u32 data); |
|
||||
void Write64(GPUVAddr addr, u64 data); |
|
||||
|
template <typename T> |
||||
|
void Write(GPUVAddr addr, T data); |
||||
|
|
||||
u8* GetPointer(GPUVAddr vaddr); |
|
||||
|
u8* GetPointer(GPUVAddr addr); |
||||
|
|
||||
void ReadBlock(GPUVAddr src_addr, void* dest_buffer, std::size_t size); |
void ReadBlock(GPUVAddr src_addr, void* dest_buffer, std::size_t size); |
||||
void WriteBlock(GPUVAddr dest_addr, const void* src_buffer, std::size_t size); |
void WriteBlock(GPUVAddr dest_addr, const void* src_buffer, std::size_t size); |
||||
void CopyBlock(VAddr dest_addr, VAddr src_addr, std::size_t size); |
|
||||
|
void CopyBlock(GPUVAddr dest_addr, GPUVAddr src_addr, std::size_t size); |
||||
|
|
||||
private: |
private: |
||||
enum class PageStatus : u64 { |
|
||||
Unmapped = 0xFFFFFFFFFFFFFFFFULL, |
|
||||
Allocated = 0xFFFFFFFFFFFFFFFEULL, |
|
||||
Reserved = 0xFFFFFFFFFFFFFFFDULL, |
|
||||
}; |
|
||||
|
|
||||
std::optional<GPUVAddr> FindFreeBlock(GPUVAddr region_start, u64 size, u64 align, |
|
||||
PageStatus status); |
|
||||
VAddr& PageSlot(GPUVAddr gpu_addr); |
|
||||
|
|
||||
static constexpr u64 MAX_ADDRESS{0x10000000000ULL}; |
|
||||
static constexpr u64 PAGE_TABLE_BITS{10}; |
|
||||
static constexpr u64 PAGE_TABLE_SIZE{1 << PAGE_TABLE_BITS}; |
|
||||
static constexpr u64 PAGE_TABLE_MASK{PAGE_TABLE_SIZE - 1}; |
|
||||
static constexpr u64 PAGE_BLOCK_BITS{14}; |
|
||||
static constexpr u64 PAGE_BLOCK_SIZE{1 << PAGE_BLOCK_BITS}; |
|
||||
static constexpr u64 PAGE_BLOCK_MASK{PAGE_BLOCK_SIZE - 1}; |
|
||||
|
|
||||
using PageBlock = std::array<VAddr, PAGE_BLOCK_SIZE>; |
|
||||
std::array<std::unique_ptr<PageBlock>, PAGE_TABLE_SIZE> page_table{}; |
|
||||
|
|
||||
struct MappedRegion { |
|
||||
VAddr cpu_addr; |
|
||||
GPUVAddr gpu_addr; |
|
||||
u64 size; |
|
||||
}; |
|
||||
|
using VMAMap = std::map<GPUVAddr, VirtualMemoryArea>; |
||||
|
using VMAHandle = VMAMap::const_iterator; |
||||
|
using VMAIter = VMAMap::iterator; |
||||
|
|
||||
|
bool IsAddressValid(GPUVAddr addr) const; |
||||
|
void MapPages(GPUVAddr base, u64 size, u8* memory, Common::PageType type, |
||||
|
VAddr backing_addr = 0); |
||||
|
void MapMemoryRegion(GPUVAddr base, u64 size, u8* target, VAddr backing_addr); |
||||
|
void UnmapRegion(GPUVAddr base, u64 size); |
||||
|
|
||||
|
/// Finds the VMA in which the given address is included in, or `vma_map.end()`. |
||||
|
VMAHandle FindVMA(GPUVAddr target) const; |
||||
|
|
||||
|
VMAHandle AllocateMemory(GPUVAddr target, std::size_t offset, u64 size); |
||||
|
|
||||
|
/** |
||||
|
* Maps an unmanaged host memory pointer at a given address. |
||||
|
* |
||||
|
* @param target The guest address to start the mapping at. |
||||
|
* @param memory The memory to be mapped. |
||||
|
* @param size Size of the mapping. |
||||
|
* @param state MemoryState tag to attach to the VMA. |
||||
|
*/ |
||||
|
VMAHandle MapBackingMemory(GPUVAddr target, u8* memory, u64 size, VAddr backing_addr); |
||||
|
|
||||
|
/// Unmaps a range of addresses, splitting VMAs as necessary. |
||||
|
void UnmapRange(GPUVAddr target, u64 size); |
||||
|
|
||||
|
/// Converts a VMAHandle to a mutable VMAIter. |
||||
|
VMAIter StripIterConstness(const VMAHandle& iter); |
||||
|
|
||||
|
/// Marks as the specfied VMA as allocated. |
||||
|
VMAIter Allocate(VMAIter vma); |
||||
|
|
||||
|
/** |
||||
|
* Carves a VMA of a specific size at the specified address by splitting Free VMAs while doing |
||||
|
* the appropriate error checking. |
||||
|
*/ |
||||
|
VMAIter CarveVMA(GPUVAddr base, u64 size); |
||||
|
|
||||
|
/** |
||||
|
* Splits the edges of the given range of non-Free VMAs so that there is a VMA split at each |
||||
|
* end of the range. |
||||
|
*/ |
||||
|
VMAIter CarveVMARange(GPUVAddr base, u64 size); |
||||
|
|
||||
|
/** |
||||
|
* Splits a VMA in two, at the specified offset. |
||||
|
* @returns the right side of the split, with the original iterator becoming the left side. |
||||
|
*/ |
||||
|
VMAIter SplitVMA(VMAIter vma, u64 offset_in_vma); |
||||
|
|
||||
|
/** |
||||
|
* Checks for and merges the specified VMA with adjacent ones if possible. |
||||
|
* @returns the merged VMA or the original if no merging was possible. |
||||
|
*/ |
||||
|
VMAIter MergeAdjacent(VMAIter vma); |
||||
|
|
||||
|
/// Updates the pages corresponding to this VMA so they match the VMA's attributes. |
||||
|
void UpdatePageTableForVMA(const VirtualMemoryArea& vma); |
||||
|
|
||||
|
/// Finds a free (unmapped region) of the specified size starting at the specified address. |
||||
|
GPUVAddr FindFreeRegion(GPUVAddr region_start, u64 size); |
||||
|
|
||||
std::vector<MappedRegion> mapped_regions; |
|
||||
|
private: |
||||
|
static constexpr u64 page_bits{16}; |
||||
|
static constexpr u64 page_size{1 << page_bits}; |
||||
|
static constexpr u64 page_mask{page_size - 1}; |
||||
|
|
||||
|
/// Address space in bits, this is fairly arbitrary but sufficiently large. |
||||
|
static constexpr u32 address_space_width{39}; |
||||
|
/// Start address for mapping, this is fairly arbitrary but must be non-zero. |
||||
|
static constexpr GPUVAddr address_space_base{0x100000}; |
||||
|
/// End of address space, based on address space in bits. |
||||
|
static constexpr GPUVAddr address_space_end{1ULL << address_space_width}; |
||||
|
|
||||
|
Common::PageTable page_table{page_bits}; |
||||
|
VMAMap vma_map; |
||||
}; |
}; |
||||
|
|
||||
} // namespace Tegra |
} // namespace Tegra |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue