From 2215455617bd6290eb85ce143c0c27fd39921edd Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Sun, 2 Aug 2026 03:44:54 -0400 Subject: [PATCH] Another pair of fixes on nvgpu --- .../service/nvdrv/devices/nvhost_as_gpu.cpp | 55 ++++++++++--------- .../hle/service/nvdrv/devices/nvhost_as_gpu.h | 3 - .../hle/service/nvdrv/devices/nvhost_gpu.cpp | 24 ++++---- .../impl/internal_stage_buffer_entry_read.cpp | 39 +------------ 4 files changed, 44 insertions(+), 77 deletions(-) diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index dad3ab048c..38667e7777 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -375,39 +375,42 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) { mapping_map.insert_or_assign(params.offset, Mapping(params.handle, device_address, params.offset, size, false, big_page, false)); } - map_buffer_offsets.insert(params.offset); - return NvResult::Success; } NvResult nvhost_as_gpu::UnmapBuffer(IoctlUnmapBuffer& params) { + LOG_DEBUG(Service_NVDRV, "called, offset={:#X}", params.offset); + std::scoped_lock lock(mutex); - if (auto const offset_it = map_buffer_offsets.find(params.offset); offset_it != map_buffer_offsets.end()) { - LOG_DEBUG(Service_NVDRV, "called, offset={:#X}", params.offset); - if (!vm.initialised) { - return NvResult::BadValue; - } - auto const it = mapping_map.find(params.offset); - auto const mapping = it->second; - if (!mapping.fixed) { - auto& allocator{mapping.big_page ? *vm.big_page_allocator : *vm.small_page_allocator}; - u32 page_size_bits{mapping.big_page ? vm.big_page_size_bits : VM::PAGE_SIZE_BITS}; - allocator.Free(u32(mapping.offset >> page_size_bits), u32(mapping.size >> page_size_bits)); - } - - // Sparse mappings shouldn't be fully unmapped, just returned to their sparse state - // Only FreeSpace can unmap them fully - if (mapping.sparse_alloc) { - gmmu->MapSparse(params.offset, mapping.size, mapping.big_page); - } else { - gmmu->Unmap(params.offset, mapping.size); - } - - nvmap.UnpinHandle(mapping.handle); - mapping_map.erase(params.offset); - map_buffer_offsets.erase(params.offset); + if (!vm.initialised) { + return NvResult::BadValue; } + + auto const it = mapping_map.find(params.offset); + if (it == mapping_map.end()) { + LOG_WARNING(Service_NVDRV, "Couldn't find region to unmap at {:#X}", params.offset); + return NvResult::Success; + } + + auto const mapping = it->second; + if (!mapping.fixed) { + auto& allocator{mapping.big_page ? *vm.big_page_allocator : *vm.small_page_allocator}; + u32 page_size_bits{mapping.big_page ? vm.big_page_size_bits : VM::PAGE_SIZE_BITS}; + allocator.Free(u32(mapping.offset >> page_size_bits), u32(mapping.size >> page_size_bits)); + } + + // Sparse mappings shouldn't be fully unmapped, just returned to their sparse state + // Only FreeSpace can unmap them fully + if (mapping.sparse_alloc) { + gmmu->MapSparse(params.offset, mapping.size, mapping.big_page); + } else { + gmmu->Unmap(params.offset, mapping.size); + } + + nvmap.UnpinHandle(mapping.handle); + mapping_map.erase(it); + return NvResult::Success; } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index b8ae57e1b4..46bda127d0 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h @@ -13,7 +13,6 @@ #include #include #include -#include #include #include "common/address_space.h" @@ -113,8 +112,6 @@ private: }; static_assert(sizeof(IoctlRemapEntry) == 20, "IoctlRemapEntry is incorrect size"); - ankerl::unordered_dense::set map_buffer_offsets{}; - struct IoctlMapBufferEx { MappingFlags flags{}; // bit0: fixed_offset, bit2: cacheable u32_le kind{}; // -1 is default diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 5869bec903..46a6198839 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -174,7 +174,9 @@ NvResult nvhost_gpu::SetChannelPriority(IoctlChannelSetPriority& params) { case ChannelPriority::Low: channel_timeslice = 1300; break; case ChannelPriority::Medium: channel_timeslice = 2600; break; case ChannelPriority::High: channel_timeslice = 5200; break; - default : return NvResult::BadParameter; + default: + LOG_WARNING(Service_NVDRV, "unknown channel priority {:#X}", channel_priority); + break; } return NvResult::Success; @@ -278,18 +280,20 @@ NvResult nvhost_gpu::AllocateObjectContext(IoctlAllocObjCtx& params) { params.flags = allowed_mask; } - s32_le ctx_class_number_index = + params.obj_id = 0; + + s32_le ctx_class_number_index = GetObjectContextClassNumberIndex(static_cast(params.class_num)); if (ctx_class_number_index < 0) { - LOG_ERROR(Service_NVDRV, "Invalid class number for object context: {:#X}", - params.class_num); - return NvResult::BadParameter; + LOG_WARNING(Service_NVDRV, "Untracked class number for object context: {:#X}", + params.class_num); + return NvResult::Success; } if (ctxObjs[ctx_class_number_index].has_value()) { - LOG_WARNING(Service_NVDRV, "Object context for class {:#X} already allocated on this channel", - params.class_num); - return NvResult::AlreadyAllocated; + LOG_DEBUG(Service_NVDRV, "Object context for class {:#X} already allocated on this channel", + params.class_num); + return NvResult::Success; } // Defer actual hardware context binding until channel is initialized. @@ -435,10 +439,6 @@ NvResult nvhost_gpu::ChannelSetTimeout(IoctlChannelSetTimeout& params) { NvResult nvhost_gpu::ChannelSetTimeslice(IoctlSetTimeslice& params) { LOG_INFO(Service_NVDRV, "called, timeslice={:#X}", params.timeslice); - if (params.timeslice < 1000 || params.timeslice > 5000) { - return NvResult::BadParameter; - } - channel_timeslice = params.timeslice; return NvResult::Success; diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp index 38cdc1a2d1..e4c39d7974 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp @@ -17,28 +17,12 @@ enum class Mode : u64 { Attr, }; -enum class SZ : u64 { - U8, - U16, - U32, - F32 -}; - enum class Shift : u64 { Default, U16, B32, }; -IR::U32 scaleIndex(IR::IREmitter& ir, IR::U32 index, Shift shift) { - switch (shift) { - case Shift::Default: return index; - case Shift::U16: return ir.ShiftLeftLogical(index, ir.Imm32(1)); - case Shift::B32: return ir.ShiftLeftLogical(index, ir.Imm32(2)); - default: UNREACHABLE(); - } -} - } // Anonymous namespace void TranslatorVisitor::ISBERD(u64 insn) { @@ -53,7 +37,6 @@ void TranslatorVisitor::ISBERD(u64 insn) { BitField<31, 1, u64> skew; BitField<32, 1, u64> o; BitField<33, 2, Mode> mode; - BitField<36, 4, SZ> sz; BitField<47, 2, Shift> shift; } const isberd{insn}; @@ -63,31 +46,15 @@ void TranslatorVisitor::ISBERD(u64 insn) { if (isberd.o != 0) { throw NotImplementedException("ISBERD O"); } - if (isberd.sz.Value() > SZ::F32) { - throw NotImplementedException("ISBERD SZ {}", - static_cast(isberd.sz.Value())); - } - if (isberd.shift.Value() > Shift::B32) { - throw NotImplementedException("ISBERD Shift {}", - static_cast(isberd.shift.Value())); - } switch (isberd.mode.Value()) { case Mode::Default: X(isberd.dest_reg.Value(), X(isberd.src_reg.Value())); return; - case Mode::Attr: { - IR::U32 offset{}; - if (isberd.src_reg_num.Value() == 0xFF) { - offset = ir.Imm32(isberd.imm.Value()); - } else { - const IR::U32 index{ - scaleIndex(ir, X(isberd.src_reg.Value()), isberd.shift.Value())}; - offset = ir.IAdd(index, ir.Imm32(isberd.imm.Value())); - } - X(isberd.dest_reg.Value(), ir.BitCast(ir.GetAttributeIndexed(offset))); + case Mode::Attr: + LOG_DEBUG(Shader, "(STUBBED) ISBERD Mode Attr"); + X(isberd.dest_reg.Value(), X(isberd.src_reg.Value())); return; - } default: throw NotImplementedException("ISBERD Mode {}", static_cast(isberd.mode.Value()));