mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-12-18 19:41:01 +01:00
SMMU: Fix software rendering and cleanup
This commit is contained in:
parent
d8f1ce2f76
commit
b0bca0f8b0
7 changed files with 24 additions and 30 deletions
|
@ -22,7 +22,7 @@ NvMap::Handle::Handle(u64 size_, Id id_)
|
||||||
flags.raw = 0;
|
flags.raw = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult NvMap::Handle::Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress) {
|
NvResult NvMap::Handle::Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress, size_t pSessionId) {
|
||||||
std::scoped_lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
// Handles cannot be allocated twice
|
// Handles cannot be allocated twice
|
||||||
if (allocated) {
|
if (allocated) {
|
||||||
|
@ -32,6 +32,7 @@ NvResult NvMap::Handle::Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress)
|
||||||
flags = pFlags;
|
flags = pFlags;
|
||||||
kind = pKind;
|
kind = pKind;
|
||||||
align = pAlign < YUZU_PAGESIZE ? YUZU_PAGESIZE : pAlign;
|
align = pAlign < YUZU_PAGESIZE ? YUZU_PAGESIZE : pAlign;
|
||||||
|
session_id = pSessionId;
|
||||||
|
|
||||||
// This flag is only applicable for handles with an address passed
|
// This flag is only applicable for handles with an address passed
|
||||||
if (pAddress) {
|
if (pAddress) {
|
||||||
|
@ -154,7 +155,7 @@ DAddr NvMap::GetHandleAddress(Handle::Id handle) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DAddr NvMap::PinHandle(NvMap::Handle::Id handle, size_t session_id, bool low_area_pin) {
|
DAddr NvMap::PinHandle(NvMap::Handle::Id handle, bool low_area_pin) {
|
||||||
auto handle_description{GetHandle(handle)};
|
auto handle_description{GetHandle(handle)};
|
||||||
if (!handle_description) [[unlikely]] {
|
if (!handle_description) [[unlikely]] {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -198,10 +199,9 @@ DAddr NvMap::PinHandle(NvMap::Handle::Id handle, size_t session_id, bool low_are
|
||||||
// If not then allocate some space and map it
|
// If not then allocate some space and map it
|
||||||
DAddr address{};
|
DAddr address{};
|
||||||
auto& smmu = host1x.MemoryManager();
|
auto& smmu = host1x.MemoryManager();
|
||||||
auto* session = core.GetSession(session_id);
|
auto* session = core.GetSession(handle_description->session_id);
|
||||||
const VAddr vaddress = handle_description->address;
|
const VAddr vaddress = handle_description->address;
|
||||||
const size_t map_size = handle_description->aligned_size;
|
const size_t map_size = handle_description->aligned_size;
|
||||||
handle_description->session_id = session_id;
|
|
||||||
if (session->has_preallocated_area && session->mapper->IsInBounds(vaddress, map_size)) {
|
if (session->has_preallocated_area && session->mapper->IsInBounds(vaddress, map_size)) {
|
||||||
handle_description->d_address = session->mapper->Map(vaddress, map_size);
|
handle_description->d_address = session->mapper->Map(vaddress, map_size);
|
||||||
handle_description->in_heap = true;
|
handle_description->in_heap = true;
|
||||||
|
|
|
@ -82,7 +82,7 @@ public:
|
||||||
* @brief Sets up the handle with the given memory config, can allocate memory from the tmem
|
* @brief Sets up the handle with the given memory config, can allocate memory from the tmem
|
||||||
* if a 0 address is passed
|
* if a 0 address is passed
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] NvResult Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress);
|
[[nodiscard]] NvResult Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress, size_t pSessionId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Increases the dupe counter of the handle for the given session
|
* @brief Increases the dupe counter of the handle for the given session
|
||||||
|
@ -130,7 +130,7 @@ public:
|
||||||
* number of calls to `UnpinHandle`
|
* number of calls to `UnpinHandle`
|
||||||
* @return The SMMU virtual address that the handle has been mapped to
|
* @return The SMMU virtual address that the handle has been mapped to
|
||||||
*/
|
*/
|
||||||
DAddr PinHandle(Handle::Id handle, size_t session_id, bool low_area_pin);
|
DAddr PinHandle(Handle::Id handle, bool low_area_pin);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief When this has been called an equal number of times to `PinHandle` for the supplied
|
* @brief When this has been called an equal number of times to `PinHandle` for the supplied
|
||||||
|
|
|
@ -40,15 +40,15 @@ NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> i
|
||||||
case 0x3:
|
case 0x3:
|
||||||
return WrapFixed(this, &nvhost_as_gpu::FreeSpace, input, output);
|
return WrapFixed(this, &nvhost_as_gpu::FreeSpace, input, output);
|
||||||
case 0x5:
|
case 0x5:
|
||||||
return WrapFixed(this, &nvhost_as_gpu::UnmapBuffer, input, output, fd);
|
return WrapFixed(this, &nvhost_as_gpu::UnmapBuffer, input, output);
|
||||||
case 0x6:
|
case 0x6:
|
||||||
return WrapFixed(this, &nvhost_as_gpu::MapBufferEx, input, output, fd);
|
return WrapFixed(this, &nvhost_as_gpu::MapBufferEx, input, output);
|
||||||
case 0x8:
|
case 0x8:
|
||||||
return WrapFixed(this, &nvhost_as_gpu::GetVARegions1, input, output);
|
return WrapFixed(this, &nvhost_as_gpu::GetVARegions1, input, output);
|
||||||
case 0x9:
|
case 0x9:
|
||||||
return WrapFixed(this, &nvhost_as_gpu::AllocAsEx, input, output);
|
return WrapFixed(this, &nvhost_as_gpu::AllocAsEx, input, output);
|
||||||
case 0x14:
|
case 0x14:
|
||||||
return WrapVariable(this, &nvhost_as_gpu::Remap, input, output, fd);
|
return WrapVariable(this, &nvhost_as_gpu::Remap, input, output);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -86,15 +86,8 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> i
|
||||||
return NvResult::NotImplemented;
|
return NvResult::NotImplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvhost_as_gpu::OnOpen(size_t session_id, DeviceFD fd) {
|
void nvhost_as_gpu::OnOpen(size_t session_id, DeviceFD fd) {}
|
||||||
sessions[fd] = session_id;
|
void nvhost_as_gpu::OnClose(DeviceFD fd) {}
|
||||||
}
|
|
||||||
void nvhost_as_gpu::OnClose(DeviceFD fd) {
|
|
||||||
auto it = sessions.find(fd);
|
|
||||||
if (it != sessions.end()) {
|
|
||||||
sessions.erase(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) {
|
NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) {
|
||||||
LOG_DEBUG(Service_NVDRV, "called, big_page_size=0x{:X}", params.big_page_size);
|
LOG_DEBUG(Service_NVDRV, "called, big_page_size=0x{:X}", params.big_page_size);
|
||||||
|
@ -268,7 +261,7 @@ NvResult nvhost_as_gpu::FreeSpace(IoctlFreeSpace& params) {
|
||||||
return NvResult::Success;
|
return NvResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_as_gpu::Remap(std::span<IoctlRemapEntry> entries, DeviceFD fd) {
|
NvResult nvhost_as_gpu::Remap(std::span<IoctlRemapEntry> entries) {
|
||||||
LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", entries.size());
|
LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", entries.size());
|
||||||
|
|
||||||
if (!vm.initialised) {
|
if (!vm.initialised) {
|
||||||
|
@ -302,7 +295,7 @@ NvResult nvhost_as_gpu::Remap(std::span<IoctlRemapEntry> entries, DeviceFD fd) {
|
||||||
return NvResult::BadValue;
|
return NvResult::BadValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
DAddr base = nvmap.PinHandle(entry.handle, sessions[fd], false);
|
DAddr base = nvmap.PinHandle(entry.handle, false);
|
||||||
DAddr device_address{static_cast<DAddr>(
|
DAddr device_address{static_cast<DAddr>(
|
||||||
base + (static_cast<u64>(entry.handle_offset_big_pages) << vm.big_page_size_bits))};
|
base + (static_cast<u64>(entry.handle_offset_big_pages) << vm.big_page_size_bits))};
|
||||||
|
|
||||||
|
@ -314,7 +307,7 @@ NvResult nvhost_as_gpu::Remap(std::span<IoctlRemapEntry> entries, DeviceFD fd) {
|
||||||
return NvResult::Success;
|
return NvResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params, DeviceFD fd) {
|
NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) {
|
||||||
LOG_DEBUG(Service_NVDRV,
|
LOG_DEBUG(Service_NVDRV,
|
||||||
"called, flags={:X}, nvmap_handle={:X}, buffer_offset={}, mapping_size={}"
|
"called, flags={:X}, nvmap_handle={:X}, buffer_offset={}, mapping_size={}"
|
||||||
", offset={}",
|
", offset={}",
|
||||||
|
@ -358,8 +351,8 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params, DeviceFD fd) {
|
||||||
return NvResult::BadValue;
|
return NvResult::BadValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
DAddr device_address{static_cast<DAddr>(nvmap.PinHandle(params.handle, sessions[fd], false) +
|
DAddr device_address{
|
||||||
params.buffer_offset)};
|
static_cast<DAddr>(nvmap.PinHandle(params.handle, false) + params.buffer_offset)};
|
||||||
u64 size{params.mapping_size ? params.mapping_size : handle->orig_size};
|
u64 size{params.mapping_size ? params.mapping_size : handle->orig_size};
|
||||||
|
|
||||||
bool big_page{[&]() {
|
bool big_page{[&]() {
|
||||||
|
@ -414,7 +407,7 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params, DeviceFD fd) {
|
||||||
return NvResult::Success;
|
return NvResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_as_gpu::UnmapBuffer(IoctlUnmapBuffer& params, DeviceFD fd) {
|
NvResult nvhost_as_gpu::UnmapBuffer(IoctlUnmapBuffer& params) {
|
||||||
LOG_DEBUG(Service_NVDRV, "called, offset=0x{:X}", params.offset);
|
LOG_DEBUG(Service_NVDRV, "called, offset=0x{:X}", params.offset);
|
||||||
|
|
||||||
std::scoped_lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
|
@ -141,9 +141,9 @@ private:
|
||||||
|
|
||||||
NvResult AllocAsEx(IoctlAllocAsEx& params);
|
NvResult AllocAsEx(IoctlAllocAsEx& params);
|
||||||
NvResult AllocateSpace(IoctlAllocSpace& params);
|
NvResult AllocateSpace(IoctlAllocSpace& params);
|
||||||
NvResult Remap(std::span<IoctlRemapEntry> params, DeviceFD fd);
|
NvResult Remap(std::span<IoctlRemapEntry> params);
|
||||||
NvResult MapBufferEx(IoctlMapBufferEx& params, DeviceFD fd);
|
NvResult MapBufferEx(IoctlMapBufferEx& params);
|
||||||
NvResult UnmapBuffer(IoctlUnmapBuffer& params, DeviceFD fd);
|
NvResult UnmapBuffer(IoctlUnmapBuffer& params);
|
||||||
NvResult FreeSpace(IoctlFreeSpace& params);
|
NvResult FreeSpace(IoctlFreeSpace& params);
|
||||||
NvResult BindChannel(IoctlBindChannel& params);
|
NvResult BindChannel(IoctlBindChannel& params);
|
||||||
|
|
||||||
|
@ -214,7 +214,6 @@ private:
|
||||||
bool initialised{};
|
bool initialised{};
|
||||||
} vm;
|
} vm;
|
||||||
std::shared_ptr<Tegra::MemoryManager> gmmu;
|
std::shared_ptr<Tegra::MemoryManager> gmmu;
|
||||||
std::unordered_map<DeviceFD, size_t> sessions;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::Nvidia::Devices
|
} // namespace Service::Nvidia::Devices
|
||||||
|
|
|
@ -140,7 +140,7 @@ NvResult nvhost_nvdec_common::MapBuffer(IoctlMapBuffer& params, std::span<MapBuf
|
||||||
DeviceFD fd) {
|
DeviceFD fd) {
|
||||||
const size_t num_entries = std::min(params.num_entries, static_cast<u32>(entries.size()));
|
const size_t num_entries = std::min(params.num_entries, static_cast<u32>(entries.size()));
|
||||||
for (size_t i = 0; i < num_entries; i++) {
|
for (size_t i = 0; i < num_entries; i++) {
|
||||||
DAddr pin_address = nvmap.PinHandle(entries[i].map_handle, sessions[fd], true);
|
DAddr pin_address = nvmap.PinHandle(entries[i].map_handle, true);
|
||||||
entries[i].map_address = static_cast<u32>(pin_address);
|
entries[i].map_address = static_cast<u32>(pin_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ NvResult nvmap::IocAlloc(IocAllocParams& params, DeviceFD fd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto result =
|
const auto result =
|
||||||
handle_description->Alloc(params.flags, params.align, params.kind, params.address);
|
handle_description->Alloc(params.flags, params.align, params.kind, params.address, sessions[fd]);
|
||||||
if (result != NvResult::Success) {
|
if (result != NvResult::Success) {
|
||||||
LOG_CRITICAL(Service_NVDRV, "Object failed to allocate, handle={:08X}", params.handle);
|
LOG_CRITICAL(Service_NVDRV, "Object failed to allocate, handle={:08X}", params.handle);
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -22,11 +22,13 @@ GraphicBuffer::GraphicBuffer(Service::Nvidia::NvCore::NvMap& nvmap,
|
||||||
: NvGraphicBuffer(GetBuffer(buffer)), m_nvmap(std::addressof(nvmap)) {
|
: NvGraphicBuffer(GetBuffer(buffer)), m_nvmap(std::addressof(nvmap)) {
|
||||||
if (this->BufferId() > 0) {
|
if (this->BufferId() > 0) {
|
||||||
m_nvmap->DuplicateHandle(this->BufferId(), true);
|
m_nvmap->DuplicateHandle(this->BufferId(), true);
|
||||||
|
m_nvmap->PinHandle(this->BufferId(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphicBuffer::~GraphicBuffer() {
|
GraphicBuffer::~GraphicBuffer() {
|
||||||
if (m_nvmap != nullptr && this->BufferId() > 0) {
|
if (m_nvmap != nullptr && this->BufferId() > 0) {
|
||||||
|
m_nvmap->UnpinHandle(this->BufferId());
|
||||||
m_nvmap->FreeHandle(this->BufferId(), true);
|
m_nvmap->FreeHandle(this->BufferId(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue