diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 9 | ||||
-rw-r--r-- | src/core/hle/kernel/vm_manager.cpp | 76 | ||||
-rw-r--r-- | src/core/hle/kernel/vm_manager.h | 55 | ||||
-rw-r--r-- | src/video_core/gpu.cpp | 9 | ||||
-rw-r--r-- | src/video_core/gpu.h | 6 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 4 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_resource_manager.cpp | 2 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_resource_manager.h | 2 |
8 files changed, 93 insertions, 70 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index e5e7f99e1..09d1eadb6 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -175,11 +175,8 @@ static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) { return ERR_INVALID_SIZE; } - auto& vm_manager = Core::CurrentProcess()->VMManager(); - const VAddr heap_base = vm_manager.GetHeapRegionBaseAddress(); - const auto alloc_result = - vm_manager.HeapAllocate(heap_base, heap_size, VMAPermission::ReadWrite); - + auto& vm_manager = Core::System::GetInstance().Kernel().CurrentProcess()->VMManager(); + const auto alloc_result = vm_manager.SetHeapSize(heap_size); if (alloc_result.Failed()) { return alloc_result.Code(); } @@ -809,7 +806,7 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) return RESULT_SUCCESS; case GetInfoType::TotalHeapUsage: - *result = process->VMManager().GetTotalHeapUsage(); + *result = process->VMManager().GetCurrentHeapSize(); return RESULT_SUCCESS; case GetInfoType::IsVirtualAddressMemoryEnabled: diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 22bf55ce7..ec0a480ce 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -256,57 +256,50 @@ ResultCode VMManager::ReprotectRange(VAddr target, u64 size, VMAPermission new_p return RESULT_SUCCESS; } -ResultVal<VAddr> VMManager::HeapAllocate(VAddr target, u64 size, VMAPermission perms) { - if (!IsWithinHeapRegion(target, size)) { - return ERR_INVALID_ADDRESS; +ResultVal<VAddr> VMManager::SetHeapSize(u64 size) { + if (size > GetHeapRegionSize()) { + return ERR_OUT_OF_MEMORY; + } + + // No need to do any additional work if the heap is already the given size. + if (size == GetCurrentHeapSize()) { + return MakeResult(heap_region_base); } if (heap_memory == nullptr) { // Initialize heap - heap_memory = std::make_shared<std::vector<u8>>(); - heap_start = heap_end = target; + heap_memory = std::make_shared<std::vector<u8>>(size); + heap_end = heap_region_base + size; } else { - UnmapRange(heap_start, heap_end - heap_start); - } - - // If necessary, expand backing vector to cover new heap extents. - if (target < heap_start) { - heap_memory->insert(begin(*heap_memory), heap_start - target, 0); - heap_start = target; - RefreshMemoryBlockMappings(heap_memory.get()); - } - if (target + size > heap_end) { - heap_memory->insert(end(*heap_memory), (target + size) - heap_end, 0); - heap_end = target + size; - RefreshMemoryBlockMappings(heap_memory.get()); + UnmapRange(heap_region_base, GetCurrentHeapSize()); } - ASSERT(heap_end - heap_start == heap_memory->size()); - CASCADE_RESULT(auto vma, MapMemoryBlock(target, heap_memory, target - heap_start, size, - MemoryState::Heap)); - Reprotect(vma, perms); + // If necessary, expand backing vector to cover new heap extents in + // the case of allocating. Otherwise, shrink the backing memory, + // if a smaller heap has been requested. + const u64 old_heap_size = GetCurrentHeapSize(); + if (size > old_heap_size) { + const u64 alloc_size = size - old_heap_size; - heap_used = size; - - return MakeResult<VAddr>(heap_end - size); -} + heap_memory->insert(heap_memory->end(), alloc_size, 0); + RefreshMemoryBlockMappings(heap_memory.get()); + } else if (size < old_heap_size) { + heap_memory->resize(size); + heap_memory->shrink_to_fit(); -ResultCode VMManager::HeapFree(VAddr target, u64 size) { - if (!IsWithinHeapRegion(target, size)) { - return ERR_INVALID_ADDRESS; + RefreshMemoryBlockMappings(heap_memory.get()); } - if (size == 0) { - return RESULT_SUCCESS; - } + heap_end = heap_region_base + size; + ASSERT(GetCurrentHeapSize() == heap_memory->size()); - const ResultCode result = UnmapRange(target, size); - if (result.IsError()) { - return result; + const auto mapping_result = + MapMemoryBlock(heap_region_base, heap_memory, 0, size, MemoryState::Heap); + if (mapping_result.Failed()) { + return mapping_result.Code(); } - heap_used -= size; - return RESULT_SUCCESS; + return MakeResult<VAddr>(heap_region_base); } MemoryInfo VMManager::QueryMemory(VAddr address) const { @@ -598,6 +591,7 @@ void VMManager::InitializeMemoryRegionRanges(FileSys::ProgramAddressSpaceType ty heap_region_base = map_region_end; heap_region_end = heap_region_base + heap_region_size; + heap_end = heap_region_base; new_map_region_base = heap_region_end; new_map_region_end = new_map_region_base + new_map_region_size; @@ -692,10 +686,6 @@ u64 VMManager::GetTotalMemoryUsage() const { return 0xF8000000; } -u64 VMManager::GetTotalHeapUsage() const { - return heap_used; -} - VAddr VMManager::GetAddressSpaceBaseAddress() const { return address_space_base; } @@ -778,6 +768,10 @@ u64 VMManager::GetHeapRegionSize() const { return heap_region_end - heap_region_base; } +u64 VMManager::GetCurrentHeapSize() const { + return heap_end - heap_region_base; +} + bool VMManager::IsWithinHeapRegion(VAddr address, u64 size) const { return IsInsideAddressRange(address, size, GetHeapRegionBaseAddress(), GetHeapRegionEndAddress()); diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 7cdff6094..6f484b7bf 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h @@ -380,11 +380,41 @@ public: /// Changes the permissions of a range of addresses, splitting VMAs as necessary. ResultCode ReprotectRange(VAddr target, u64 size, VMAPermission new_perms); - ResultVal<VAddr> HeapAllocate(VAddr target, u64 size, VMAPermission perms); - ResultCode HeapFree(VAddr target, u64 size); - ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size, MemoryState state); + /// Attempts to allocate a heap with the given size. + /// + /// @param size The size of the heap to allocate in bytes. + /// + /// @note If a heap is currently allocated, and this is called + /// with a size that is equal to the size of the current heap, + /// then this function will do nothing and return the current + /// heap's starting address, as there's no need to perform + /// any additional heap allocation work. + /// + /// @note If a heap is currently allocated, and this is called + /// with a size less than the current heap's size, then + /// this function will attempt to shrink the heap. + /// + /// @note If a heap is currently allocated, and this is called + /// with a size larger than the current heap's size, then + /// this function will attempt to extend the size of the heap. + /// + /// @returns A result indicating either success or failure. + /// <p> + /// If successful, this function will return a result + /// containing the starting address to the allocated heap. + /// <p> + /// If unsuccessful, this function will return a result + /// containing an error code. + /// + /// @pre The given size must lie within the allowable heap + /// memory region managed by this VMManager instance. + /// Failure to abide by this will result in ERR_OUT_OF_MEMORY + /// being returned as the result. + /// + ResultVal<VAddr> SetHeapSize(u64 size); + /// Queries the memory manager for information about the given address. /// /// @param address The address to query the memory manager about for information. @@ -418,9 +448,6 @@ public: /// Gets the total memory usage, used by svcGetInfo u64 GetTotalMemoryUsage() const; - /// Gets the total heap usage, used by svcGetInfo - u64 GetTotalHeapUsage() const; - /// Gets the address space base address VAddr GetAddressSpaceBaseAddress() const; @@ -469,6 +496,13 @@ public: /// Gets the total size of the heap region in bytes. u64 GetHeapRegionSize() const; + /// Gets the total size of the current heap in bytes. + /// + /// @note This is the current allocated heap size, not the size + /// of the region it's allowed to exist within. + /// + u64 GetCurrentHeapSize() const; + /// Determines whether or not the specified range is within the heap region. bool IsWithinHeapRegion(VAddr address, u64 size) const; @@ -617,9 +651,6 @@ private: VAddr new_map_region_base = 0; VAddr new_map_region_end = 0; - VAddr main_code_region_base = 0; - VAddr main_code_region_end = 0; - VAddr tls_io_region_base = 0; VAddr tls_io_region_end = 0; @@ -628,9 +659,9 @@ private: // This makes deallocation and reallocation of holes fast and keeps process memory contiguous // in the emulator address space, allowing Memory::GetPointer to be reasonably safe. std::shared_ptr<std::vector<u8>> heap_memory; - // The left/right bounds of the address space covered by heap_memory. - VAddr heap_start = 0; + + // The end of the currently allocated heap. This is not an inclusive + // end of the range. This is essentially 'base_address + current_size'. VAddr heap_end = 0; - u64 heap_used = 0; }; } // namespace Kernel diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 267a03f2d..30b29e14d 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -286,9 +286,10 @@ void GPU::ProcessSemaphoreTriggerMethod() { // TODO(Kmather73): Generate a real GPU timestamp and write it here instead of // CoreTiming block.timestamp = Core::System::GetInstance().CoreTiming().GetTicks(); - memory_manager->WriteBlock(regs.smaphore_address.SmaphoreAddress(), &block, sizeof(block)); + memory_manager->WriteBlock(regs.semaphore_address.SemaphoreAddress(), &block, + sizeof(block)); } else { - const u32 word{memory_manager->Read<u32>(regs.smaphore_address.SmaphoreAddress())}; + const u32 word{memory_manager->Read<u32>(regs.semaphore_address.SemaphoreAddress())}; if ((op == GpuSemaphoreOperation::AcquireEqual && word == regs.semaphore_sequence) || (op == GpuSemaphoreOperation::AcquireGequal && static_cast<s32>(word - regs.semaphore_sequence) > 0) || @@ -315,11 +316,11 @@ void GPU::ProcessSemaphoreTriggerMethod() { } void GPU::ProcessSemaphoreRelease() { - memory_manager->Write<u32>(regs.smaphore_address.SmaphoreAddress(), regs.semaphore_release); + memory_manager->Write<u32>(regs.semaphore_address.SemaphoreAddress(), regs.semaphore_release); } void GPU::ProcessSemaphoreAcquire() { - const u32 word = memory_manager->Read<u32>(regs.smaphore_address.SmaphoreAddress()); + const u32 word = memory_manager->Read<u32>(regs.semaphore_address.SemaphoreAddress()); const auto value = regs.semaphore_acquire; if (word != value) { regs.acquire_active = true; diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index c1830ac8d..de30ea354 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -177,11 +177,11 @@ public: u32 address_high; u32 address_low; - GPUVAddr SmaphoreAddress() const { + GPUVAddr SemaphoreAddress() const { return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low); } - } smaphore_address; + } semaphore_address; u32 semaphore_sequence; u32 semaphore_trigger; @@ -263,7 +263,7 @@ private: static_assert(offsetof(GPU::Regs, field_name) == position * 4, \ "Field " #field_name " has invalid position") -ASSERT_REG_POSITION(smaphore_address, 0x4); +ASSERT_REG_POSITION(semaphore_address, 0x4); ASSERT_REG_POSITION(semaphore_sequence, 0x6); ASSERT_REG_POSITION(semaphore_trigger, 0x7); ASSERT_REG_POSITION(reference_count, 0x14); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index c644271d0..e8073579f 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -538,12 +538,12 @@ private: return nullptr; } - void Register(const Surface& object) { + void Register(const Surface& object) override { RasterizerCache<Surface>::Register(object); } /// Unregisters an object from the cache - void Unregister(const Surface& object) { + void Unregister(const Surface& object) override { if (object->IsReinterpreted()) { auto interval = GetReinterpretInterval(object); reinterpreted_surfaces.erase(interval); diff --git a/src/video_core/renderer_vulkan/vk_resource_manager.cpp b/src/video_core/renderer_vulkan/vk_resource_manager.cpp index a1e117443..13c46e5b8 100644 --- a/src/video_core/renderer_vulkan/vk_resource_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_resource_manager.cpp @@ -21,7 +21,7 @@ public: CommandBufferPool(const VKDevice& device) : VKFencedPool(COMMAND_BUFFER_POOL_SIZE), device{device} {} - void Allocate(std::size_t begin, std::size_t end) { + void Allocate(std::size_t begin, std::size_t end) override { const auto dev = device.GetLogical(); const auto& dld = device.GetDispatchLoader(); const u32 graphics_family = device.GetGraphicsFamily(); diff --git a/src/video_core/renderer_vulkan/vk_resource_manager.h b/src/video_core/renderer_vulkan/vk_resource_manager.h index 5bfe4cead..08ee86fa6 100644 --- a/src/video_core/renderer_vulkan/vk_resource_manager.h +++ b/src/video_core/renderer_vulkan/vk_resource_manager.h @@ -97,7 +97,7 @@ private: class VKFenceWatch final : public VKResource { public: explicit VKFenceWatch(); - ~VKFenceWatch(); + ~VKFenceWatch() override; /// Waits for the fence to be released. void Wait(); |