summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/nvdrv/devices
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service/nvdrv/devices')
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdevice.h13
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp11
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.h5
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp15
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h5
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp152
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.h15
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp7
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h5
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp44
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.h41
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp5
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.h5
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp5
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h5
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_vic.cpp5
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_vic.h5
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp5
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.h5
19 files changed, 267 insertions, 86 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h
index 4f6042b00..5b8248433 100644
--- a/src/core/hle/service/nvdrv/devices/nvdevice.h
+++ b/src/core/hle/service/nvdrv/devices/nvdevice.h
@@ -8,6 +8,11 @@
#include "common/bit_field.h"
#include "common/common_types.h"
#include "common/swap.h"
+#include "core/hle/service/nvdrv/nvdata.h"
+
+namespace Core {
+class System;
+}
namespace Service::Nvidia::Devices {
@@ -15,7 +20,7 @@ namespace Service::Nvidia::Devices {
/// implement the ioctl interface.
class nvdevice {
public:
- nvdevice() = default;
+ explicit nvdevice(Core::System& system) : system{system} {};
virtual ~nvdevice() = default;
union Ioctl {
u32_le raw;
@@ -33,7 +38,11 @@ public:
* @param output A buffer where the output data will be written to.
* @returns The result code of the ioctl.
*/
- virtual u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) = 0;
+ virtual u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) = 0;
+
+protected:
+ Core::System& system;
};
} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index 20c7c39aa..926a1285d 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -13,10 +13,12 @@
namespace Service::Nvidia::Devices {
-nvdisp_disp0::nvdisp_disp0(std::shared_ptr<nvmap> nvmap_dev) : nvmap_dev(std::move(nvmap_dev)) {}
+nvdisp_disp0::nvdisp_disp0(Core::System& system, std::shared_ptr<nvmap> nvmap_dev)
+ : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {}
nvdisp_disp0 ::~nvdisp_disp0() = default;
-u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
+u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) {
UNIMPLEMENTED_MSG("Unimplemented ioctl");
return 0;
}
@@ -34,9 +36,8 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3
addr, offset, width, height, stride, static_cast<PixelFormat>(format),
transform, crop_rect};
- auto& instance = Core::System::GetInstance();
- instance.GetPerfStats().EndGameFrame();
- instance.GPU().SwapBuffers(framebuffer);
+ system.GetPerfStats().EndGameFrame();
+ system.GPU().SwapBuffers(&framebuffer);
}
} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
index 12f3ef825..e79e490ff 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
@@ -17,10 +17,11 @@ class nvmap;
class nvdisp_disp0 final : public nvdevice {
public:
- explicit nvdisp_disp0(std::shared_ptr<nvmap> nvmap_dev);
+ explicit nvdisp_disp0(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
~nvdisp_disp0() override;
- u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
+ u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) override;
/// Performs a screen flip, drawing the buffer pointed to by the handle.
void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride,
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 af62d33d2..24ab3f2e9 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
@@ -22,10 +22,12 @@ enum {
};
}
-nvhost_as_gpu::nvhost_as_gpu(std::shared_ptr<nvmap> nvmap_dev) : nvmap_dev(std::move(nvmap_dev)) {}
+nvhost_as_gpu::nvhost_as_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev)
+ : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {}
nvhost_as_gpu::~nvhost_as_gpu() = default;
-u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
+u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) {
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
command.raw, input.size(), output.size());
@@ -65,7 +67,7 @@ u32 nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>&
LOG_DEBUG(Service_NVDRV, "called, pages={:X}, page_size={:X}, flags={:X}", params.pages,
params.page_size, params.flags);
- auto& gpu = Core::System::GetInstance().GPU();
+ auto& gpu = system.GPU();
const u64 size{static_cast<u64>(params.pages) * static_cast<u64>(params.page_size)};
if (params.flags & 1) {
params.offset = gpu.MemoryManager().AllocateSpace(params.offset, size, 1);
@@ -85,7 +87,7 @@ u32 nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output)
std::vector<IoctlRemapEntry> entries(num_entries);
std::memcpy(entries.data(), input.data(), input.size());
- auto& gpu = Core::System::GetInstance().GPU();
+ auto& gpu = system.GPU();
for (const auto& entry : entries) {
LOG_WARNING(Service_NVDRV, "remap entry, offset=0x{:X} handle=0x{:X} pages=0x{:X}",
entry.offset, entry.nvmap_handle, entry.pages);
@@ -136,7 +138,7 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou
// case to prevent unexpected behavior.
ASSERT(object->id == params.nvmap_handle);
- auto& gpu = Core::System::GetInstance().GPU();
+ auto& gpu = system.GPU();
if (params.flags & 1) {
params.offset = gpu.MemoryManager().MapBufferEx(object->addr, params.offset, object->size);
@@ -173,8 +175,7 @@ u32 nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& ou
return 0;
}
- params.offset = Core::System::GetInstance().GPU().MemoryManager().UnmapBuffer(params.offset,
- itr->second.size);
+ params.offset = system.GPU().MemoryManager().UnmapBuffer(params.offset, itr->second.size);
buffer_mappings.erase(itr->second.offset);
std::memcpy(output.data(), &params, output.size());
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 eb14b1da8..30ca5f4c3 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
@@ -17,10 +17,11 @@ class nvmap;
class nvhost_as_gpu final : public nvdevice {
public:
- explicit nvhost_as_gpu(std::shared_ptr<nvmap> nvmap_dev);
+ explicit nvhost_as_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
~nvhost_as_gpu() override;
- u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
+ u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) override;
private:
enum class IoctlCommand : u32_le {
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index b39fb9ef9..9a66a5f88 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -7,14 +7,20 @@
#include "common/assert.h"
#include "common/logging/log.h"
+#include "core/core.h"
+#include "core/hle/kernel/readable_event.h"
+#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h"
+#include "video_core/gpu.h"
namespace Service::Nvidia::Devices {
-nvhost_ctrl::nvhost_ctrl() = default;
+nvhost_ctrl::nvhost_ctrl(Core::System& system, EventInterface& events_interface)
+ : nvdevice(system), events_interface{events_interface} {}
nvhost_ctrl::~nvhost_ctrl() = default;
-u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
+u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) {
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
command.raw, input.size(), output.size());
@@ -22,11 +28,15 @@ u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<
case IoctlCommand::IocGetConfigCommand:
return NvOsGetConfigU32(input, output);
case IoctlCommand::IocCtrlEventWaitCommand:
- return IocCtrlEventWait(input, output, false);
+ return IocCtrlEventWait(input, output, false, ctrl);
case IoctlCommand::IocCtrlEventWaitAsyncCommand:
- return IocCtrlEventWait(input, output, true);
+ return IocCtrlEventWait(input, output, true, ctrl);
case IoctlCommand::IocCtrlEventRegisterCommand:
return IocCtrlEventRegister(input, output);
+ case IoctlCommand::IocCtrlEventUnregisterCommand:
+ return IocCtrlEventUnregister(input, output);
+ case IoctlCommand::IocCtrlEventSignalCommand:
+ return IocCtrlEventSignal(input, output);
}
UNIMPLEMENTED_MSG("Unimplemented ioctl");
return 0;
@@ -41,23 +51,137 @@ u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>&
}
u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output,
- bool is_async) {
+ bool is_async, IoctlCtrl& ctrl) {
IocCtrlEventWaitParams params{};
std::memcpy(&params, input.data(), sizeof(params));
- LOG_WARNING(Service_NVDRV,
- "(STUBBED) called, syncpt_id={}, threshold={}, timeout={}, is_async={}",
- params.syncpt_id, params.threshold, params.timeout, is_async);
+ LOG_DEBUG(Service_NVDRV, "syncpt_id={}, threshold={}, timeout={}, is_async={}",
+ params.syncpt_id, params.threshold, params.timeout, is_async);
- // TODO(Subv): Implement actual syncpt waiting.
- params.value = 0;
+ if (params.syncpt_id >= MaxSyncPoints) {
+ return NvResult::BadParameter;
+ }
+
+ auto& gpu = system.GPU();
+ // This is mostly to take into account unimplemented features. As synced
+ // gpu is always synced.
+ if (!gpu.IsAsync()) {
+ return NvResult::Success;
+ }
+ auto lock = gpu.LockSync();
+ const u32 current_syncpoint_value = gpu.GetSyncpointValue(params.syncpt_id);
+ const s32 diff = current_syncpoint_value - params.threshold;
+ if (diff >= 0) {
+ params.value = current_syncpoint_value;
+ std::memcpy(output.data(), &params, sizeof(params));
+ return NvResult::Success;
+ }
+ const u32 target_value = current_syncpoint_value - diff;
+
+ if (!is_async) {
+ params.value = 0;
+ }
+
+ if (params.timeout == 0) {
+ std::memcpy(output.data(), &params, sizeof(params));
+ return NvResult::Timeout;
+ }
+
+ u32 event_id;
+ if (is_async) {
+ event_id = params.value & 0x00FF;
+ if (event_id >= MaxNvEvents) {
+ std::memcpy(output.data(), &params, sizeof(params));
+ return NvResult::BadParameter;
+ }
+ } else {
+ if (ctrl.fresh_call) {
+ const auto result = events_interface.GetFreeEvent();
+ if (result) {
+ event_id = *result;
+ } else {
+ LOG_CRITICAL(Service_NVDRV, "No Free Events available!");
+ event_id = params.value & 0x00FF;
+ }
+ } else {
+ event_id = ctrl.event_id;
+ }
+ }
+
+ EventState status = events_interface.status[event_id];
+ if (event_id < MaxNvEvents || status == EventState::Free || status == EventState::Registered) {
+ events_interface.SetEventStatus(event_id, EventState::Waiting);
+ events_interface.assigned_syncpt[event_id] = params.syncpt_id;
+ events_interface.assigned_value[event_id] = target_value;
+ if (is_async) {
+ params.value = params.syncpt_id << 4;
+ } else {
+ params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000;
+ }
+ params.value |= event_id;
+ events_interface.events[event_id].writable->Clear();
+ gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value);
+ if (!is_async && ctrl.fresh_call) {
+ ctrl.must_delay = true;
+ ctrl.timeout = params.timeout;
+ ctrl.event_id = event_id;
+ return NvResult::Timeout;
+ }
+ std::memcpy(output.data(), &params, sizeof(params));
+ return NvResult::Timeout;
+ }
std::memcpy(output.data(), &params, sizeof(params));
- return 0;
+ return NvResult::BadParameter;
}
u32 nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output) {
- LOG_WARNING(Service_NVDRV, "(STUBBED) called");
- // TODO(bunnei): Implement this.
- return 0;
+ IocCtrlEventRegisterParams params{};
+ std::memcpy(&params, input.data(), sizeof(params));
+ const u32 event_id = params.user_event_id & 0x00FF;
+ LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id);
+ if (event_id >= MaxNvEvents) {
+ return NvResult::BadParameter;
+ }
+ if (events_interface.registered[event_id]) {
+ return NvResult::BadParameter;
+ }
+ events_interface.RegisterEvent(event_id);
+ return NvResult::Success;
+}
+
+u32 nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output) {
+ IocCtrlEventUnregisterParams params{};
+ std::memcpy(&params, input.data(), sizeof(params));
+ const u32 event_id = params.user_event_id & 0x00FF;
+ LOG_DEBUG(Service_NVDRV, " called, user_event_id: {:X}", event_id);
+ if (event_id >= MaxNvEvents) {
+ return NvResult::BadParameter;
+ }
+ if (!events_interface.registered[event_id]) {
+ return NvResult::BadParameter;
+ }
+ events_interface.UnregisterEvent(event_id);
+ return NvResult::Success;
+}
+
+u32 nvhost_ctrl::IocCtrlEventSignal(const std::vector<u8>& input, std::vector<u8>& output) {
+ IocCtrlEventSignalParams params{};
+ std::memcpy(&params, input.data(), sizeof(params));
+ // TODO(Blinkhawk): This is normally called when an NvEvents timeout on WaitSynchronization
+ // It is believed from RE to cancel the GPU Event. However, better research is required
+ u32 event_id = params.user_event_id & 0x00FF;
+ LOG_WARNING(Service_NVDRV, "(STUBBED) called, user_event_id: {:X}", event_id);
+ if (event_id >= MaxNvEvents) {
+ return NvResult::BadParameter;
+ }
+ if (events_interface.status[event_id] == EventState::Waiting) {
+ auto& gpu = system.GPU();
+ if (gpu.CancelSyncptInterrupt(events_interface.assigned_syncpt[event_id],
+ events_interface.assigned_value[event_id])) {
+ events_interface.LiberateEvent(event_id);
+ events_interface.events[event_id].writable->Signal();
+ }
+ }
+ return NvResult::Success;
}
} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
index 6d0de2212..14e6e7e57 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
@@ -8,15 +8,17 @@
#include <vector>
#include "common/common_types.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
+#include "core/hle/service/nvdrv/nvdrv.h"
namespace Service::Nvidia::Devices {
class nvhost_ctrl final : public nvdevice {
public:
- nvhost_ctrl();
+ explicit nvhost_ctrl(Core::System& system, EventInterface& events_interface);
~nvhost_ctrl() override;
- u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
+ u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) override;
private:
enum class IoctlCommand : u32_le {
@@ -132,9 +134,16 @@ private:
u32 NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output);
- u32 IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, bool is_async);
+ u32 IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, bool is_async,
+ IoctlCtrl& ctrl);
u32 IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output);
+
+ u32 IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output);
+
+ u32 IocCtrlEventSignal(const std::vector<u8>& input, std::vector<u8>& output);
+
+ EventInterface& events_interface;
};
} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
index 0e28755bd..988effd90 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
@@ -12,10 +12,11 @@
namespace Service::Nvidia::Devices {
-nvhost_ctrl_gpu::nvhost_ctrl_gpu() = default;
+nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system) : nvdevice(system) {}
nvhost_ctrl_gpu::~nvhost_ctrl_gpu() = default;
-u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
+u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) {
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
command.raw, input.size(), output.size());
@@ -185,7 +186,7 @@ u32 nvhost_ctrl_gpu::GetGpuTime(const std::vector<u8>& input, std::vector<u8>& o
IoctlGetGpuTime params{};
std::memcpy(&params, input.data(), input.size());
- const auto ns = Core::Timing::CyclesToNs(Core::System::GetInstance().CoreTiming().GetTicks());
+ const auto ns = Core::Timing::CyclesToNs(system.CoreTiming().GetTicks());
params.gpu_time = static_cast<u64_le>(ns.count());
std::memcpy(output.data(), &params, output.size());
return 0;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
index 240435eea..2b035ae3f 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
@@ -13,10 +13,11 @@ namespace Service::Nvidia::Devices {
class nvhost_ctrl_gpu final : public nvdevice {
public:
- nvhost_ctrl_gpu();
+ explicit nvhost_ctrl_gpu(Core::System& system);
~nvhost_ctrl_gpu() override;
- u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
+ u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) override;
private:
enum class IoctlCommand : u32_le {
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index 8ce7bc7a5..241dac881 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -13,10 +13,12 @@
namespace Service::Nvidia::Devices {
-nvhost_gpu::nvhost_gpu(std::shared_ptr<nvmap> nvmap_dev) : nvmap_dev(std::move(nvmap_dev)) {}
+nvhost_gpu::nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev)
+ : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {}
nvhost_gpu::~nvhost_gpu() = default;
-u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
+u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) {
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
command.raw, input.size(), output.size());
@@ -119,8 +121,10 @@ u32 nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& ou
params.num_entries, params.flags, params.unk0, params.unk1, params.unk2,
params.unk3);
- params.fence_out.id = 0;
- params.fence_out.value = 0;
+ auto& gpu = system.GPU();
+ params.fence_out.id = assigned_syncpoints;
+ params.fence_out.value = gpu.GetSyncpointValue(assigned_syncpoints);
+ assigned_syncpoints++;
std::memcpy(output.data(), &params, output.size());
return 0;
}
@@ -143,7 +147,7 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
IoctlSubmitGpfifo params{};
std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo));
LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}",
- params.address, params.num_entries, params.flags);
+ params.address, params.num_entries, params.flags.raw);
ASSERT_MSG(input.size() == sizeof(IoctlSubmitGpfifo) +
params.num_entries * sizeof(Tegra::CommandListHeader),
@@ -153,10 +157,18 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
std::memcpy(entries.data(), &input[sizeof(IoctlSubmitGpfifo)],
params.num_entries * sizeof(Tegra::CommandListHeader));
- Core::System::GetInstance().GPU().PushGPUEntries(std::move(entries));
+ UNIMPLEMENTED_IF(params.flags.add_wait.Value() != 0);
+ UNIMPLEMENTED_IF(params.flags.add_increment.Value() != 0);
+
+ auto& gpu = system.GPU();
+ u32 current_syncpoint_value = gpu.GetSyncpointValue(params.fence_out.id);
+ if (params.flags.increment.Value()) {
+ params.fence_out.value += current_syncpoint_value;
+ } else {
+ params.fence_out.value = current_syncpoint_value;
+ }
+ gpu.PushGPUEntries(std::move(entries));
- params.fence_out.id = 0;
- params.fence_out.value = 0;
std::memcpy(output.data(), &params, sizeof(IoctlSubmitGpfifo));
return 0;
}
@@ -168,16 +180,24 @@ u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output)
IoctlSubmitGpfifo params{};
std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo));
LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}",
- params.address, params.num_entries, params.flags);
+ params.address, params.num_entries, params.flags.raw);
Tegra::CommandList entries(params.num_entries);
Memory::ReadBlock(params.address, entries.data(),
params.num_entries * sizeof(Tegra::CommandListHeader));
- Core::System::GetInstance().GPU().PushGPUEntries(std::move(entries));
+ UNIMPLEMENTED_IF(params.flags.add_wait.Value() != 0);
+ UNIMPLEMENTED_IF(params.flags.add_increment.Value() != 0);
+
+ auto& gpu = system.GPU();
+ u32 current_syncpoint_value = gpu.GetSyncpointValue(params.fence_out.id);
+ if (params.flags.increment.Value()) {
+ params.fence_out.value += current_syncpoint_value;
+ } else {
+ params.fence_out.value = current_syncpoint_value;
+ }
+ gpu.PushGPUEntries(std::move(entries));
- params.fence_out.id = 0;
- params.fence_out.value = 0;
std::memcpy(output.data(), &params, output.size());
return 0;
}
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
index 62beb5c0c..d2e8fbae9 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
@@ -10,6 +10,7 @@
#include "common/common_types.h"
#include "common/swap.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
+#include "core/hle/service/nvdrv/nvdata.h"
namespace Service::Nvidia::Devices {
@@ -20,10 +21,11 @@ constexpr u32 NVGPU_IOCTL_CHANNEL_KICKOFF_PB(0x1b);
class nvhost_gpu final : public nvdevice {
public:
- explicit nvhost_gpu(std::shared_ptr<nvmap> nvmap_dev);
+ explicit nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev);
~nvhost_gpu() override;
- u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
+ u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) override;
private:
enum class IoctlCommand : u32_le {
@@ -113,11 +115,7 @@ private:
static_assert(sizeof(IoctlGetErrorNotification) == 16,
"IoctlGetErrorNotification is incorrect size");
- struct IoctlFence {
- u32_le id;
- u32_le value;
- };
- static_assert(sizeof(IoctlFence) == 8, "IoctlFence is incorrect size");
+ static_assert(sizeof(Fence) == 8, "Fence is incorrect size");
struct IoctlAllocGpfifoEx {
u32_le num_entries;
@@ -132,13 +130,13 @@ private:
static_assert(sizeof(IoctlAllocGpfifoEx) == 32, "IoctlAllocGpfifoEx is incorrect size");
struct IoctlAllocGpfifoEx2 {
- u32_le num_entries; // in
- u32_le flags; // in
- u32_le unk0; // in (1 works)
- IoctlFence fence_out; // out
- u32_le unk1; // in
- u32_le unk2; // in
- u32_le unk3; // in
+ u32_le num_entries; // in
+ u32_le flags; // in
+ u32_le unk0; // in (1 works)
+ Fence fence_out; // out
+ u32_le unk1; // in
+ u32_le unk2; // in
+ u32_le unk3; // in
};
static_assert(sizeof(IoctlAllocGpfifoEx2) == 32, "IoctlAllocGpfifoEx2 is incorrect size");
@@ -153,10 +151,16 @@ private:
struct IoctlSubmitGpfifo {
u64_le address; // pointer to gpfifo entry structs
u32_le num_entries; // number of fence objects being submitted
- u32_le flags;
- IoctlFence fence_out; // returned new fence object for others to wait on
- };
- static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(IoctlFence),
+ union {
+ u32_le raw;
+ BitField<0, 1, u32_le> add_wait; // append a wait sync_point to the list
+ BitField<1, 1, u32_le> add_increment; // append an increment to the list
+ BitField<2, 1, u32_le> new_hw_format; // Mostly ignored
+ BitField<8, 1, u32_le> increment; // increment the returned fence
+ } flags;
+ Fence fence_out; // returned new fence object for others to wait on
+ };
+ static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(Fence),
"IoctlSubmitGpfifo is incorrect size");
struct IoctlGetWaitbase {
@@ -184,6 +188,7 @@ private:
u32 ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output);
std::shared_ptr<nvmap> nvmap_dev;
+ u32 assigned_syncpoints{};
};
} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
index f5e8ea7c3..f572ad30f 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
@@ -10,10 +10,11 @@
namespace Service::Nvidia::Devices {
-nvhost_nvdec::nvhost_nvdec() = default;
+nvhost_nvdec::nvhost_nvdec(Core::System& system) : nvdevice(system) {}
nvhost_nvdec::~nvhost_nvdec() = default;
-u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
+u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) {
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
command.raw, input.size(), output.size());
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
index 0e7b284f8..2710f0511 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
@@ -13,10 +13,11 @@ namespace Service::Nvidia::Devices {
class nvhost_nvdec final : public nvdevice {
public:
- nvhost_nvdec();
+ explicit nvhost_nvdec(Core::System& system);
~nvhost_nvdec() override;
- u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
+ u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) override;
private:
enum class IoctlCommand : u32_le {
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
index 3e0951ab0..38282956f 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
@@ -10,10 +10,11 @@
namespace Service::Nvidia::Devices {
-nvhost_nvjpg::nvhost_nvjpg() = default;
+nvhost_nvjpg::nvhost_nvjpg(Core::System& system) : nvdevice(system) {}
nvhost_nvjpg::~nvhost_nvjpg() = default;
-u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
+u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) {
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
command.raw, input.size(), output.size());
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
index 89fd5e95e..379766693 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
@@ -13,10 +13,11 @@ namespace Service::Nvidia::Devices {
class nvhost_nvjpg final : public nvdevice {
public:
- nvhost_nvjpg();
+ explicit nvhost_nvjpg(Core::System& system);
~nvhost_nvjpg() override;
- u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
+ u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) override;
private:
enum class IoctlCommand : u32_le {
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
index d544f0f31..70e8091db 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
@@ -10,10 +10,11 @@
namespace Service::Nvidia::Devices {
-nvhost_vic::nvhost_vic() = default;
+nvhost_vic::nvhost_vic(Core::System& system) : nvdevice(system) {}
nvhost_vic::~nvhost_vic() = default;
-u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
+u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) {
LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
command.raw, input.size(), output.size());
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h
index fc24c3f9c..7d111977e 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h
@@ -13,10 +13,11 @@ namespace Service::Nvidia::Devices {
class nvhost_vic final : public nvdevice {
public:
- nvhost_vic();
+ explicit nvhost_vic(Core::System& system);
~nvhost_vic() override;
- u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
+ u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) override;
private:
enum class IoctlCommand : u32_le {
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index 1ec796fc6..223b496b7 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -18,7 +18,7 @@ enum {
};
}
-nvmap::nvmap() = default;
+nvmap::nvmap(Core::System& system) : nvdevice(system) {}
nvmap::~nvmap() = default;
VAddr nvmap::GetObjectAddress(u32 handle) const {
@@ -28,7 +28,8 @@ VAddr nvmap::GetObjectAddress(u32 handle) const {
return object->addr;
}
-u32 nvmap::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
+u32 nvmap::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) {
switch (static_cast<IoctlCommand>(command.raw)) {
case IoctlCommand::Create:
return IocCreate(input, output);
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h
index 396230c19..bf4a101c2 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.h
+++ b/src/core/hle/service/nvdrv/devices/nvmap.h
@@ -16,13 +16,14 @@ namespace Service::Nvidia::Devices {
class nvmap final : public nvdevice {
public:
- nvmap();
+ explicit nvmap(Core::System& system);
~nvmap() override;
/// Returns the allocated address of an nvmap object given its handle.
VAddr GetObjectAddress(u32 handle) const;
- u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
+ u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output,
+ IoctlCtrl& ctrl) override;
/// Represents an nvmap object.
struct Object {