mirror of
https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
synced 2025-12-20 01:42:42 +00:00
NVDRV: Further improvements.
This commit is contained in:
@@ -112,17 +112,23 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
|
||||
}
|
||||
|
||||
if (params.fence.value == 0) {
|
||||
params.value.raw = syncpoint_manager.GetSyncpointMin(fence_id);
|
||||
if (!syncpoint_manager.IsSyncpointAllocated(params.fence.id)) {
|
||||
LOG_WARNING(Service_NVDRV,
|
||||
"Unallocated syncpt_id={}, threshold={}, timeout={}, is_allocation={}",
|
||||
params.fence.id, params.fence.value, params.timeout, is_allocation);
|
||||
} else {
|
||||
params.value.raw = syncpoint_manager.ReadSyncpointMinValue(fence_id);
|
||||
}
|
||||
return NvResult::Success;
|
||||
}
|
||||
|
||||
if (syncpoint_manager.IsSyncpointExpired(fence_id, params.fence.value)) {
|
||||
params.value.raw = syncpoint_manager.GetSyncpointMin(fence_id);
|
||||
if (syncpoint_manager.IsFenceSignalled(params.fence)) {
|
||||
params.value.raw = syncpoint_manager.ReadSyncpointMinValue(fence_id);
|
||||
return NvResult::Success;
|
||||
}
|
||||
|
||||
if (const auto new_value = syncpoint_manager.RefreshSyncpoint(fence_id);
|
||||
syncpoint_manager.IsSyncpointExpired(fence_id, params.fence.value)) {
|
||||
if (const auto new_value = syncpoint_manager.UpdateMin(fence_id);
|
||||
syncpoint_manager.IsFenceSignalled(params.fence)) {
|
||||
params.value.raw = new_value;
|
||||
return NvResult::Success;
|
||||
}
|
||||
@@ -296,7 +302,7 @@ NvResult nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::v
|
||||
EventState::Waiting) {
|
||||
auto& host1x_syncpoint_manager = system.Host1x().GetSyncpointManager();
|
||||
host1x_syncpoint_manager.DeregisterHostAction(event.assigned_syncpt, event.wait_handle);
|
||||
syncpoint_manager.RefreshSyncpoint(event.assigned_syncpt);
|
||||
syncpoint_manager.UpdateMin(event.assigned_syncpt);
|
||||
event.wait_handle = {};
|
||||
}
|
||||
event.fails++;
|
||||
|
||||
@@ -31,9 +31,7 @@ nvhost_gpu::nvhost_gpu(Core::System& system_, EventInterface& events_interface_,
|
||||
: nvdevice{system_}, events_interface{events_interface_}, core{core_},
|
||||
syncpoint_manager{core_.GetSyncpointManager()}, nvmap{core.GetNvMapFile()},
|
||||
channel_state{system.GPU().AllocateChannel()} {
|
||||
channel_fence.id = syncpoint_manager.AllocateSyncpoint();
|
||||
channel_fence.value =
|
||||
system_.Host1x().GetSyncpointManager().GetGuestSyncpointValue(channel_fence.id);
|
||||
channel_syncpoint = syncpoint_manager.AllocateSyncpoint(false);
|
||||
sm_exception_breakpoint_int_report_event =
|
||||
events_interface.CreateEvent("GpuChannelSMExceptionBreakpointInt");
|
||||
sm_exception_breakpoint_pause_report_event =
|
||||
@@ -191,10 +189,8 @@ NvResult nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8
|
||||
}
|
||||
|
||||
system.GPU().InitChannel(*channel_state);
|
||||
channel_fence.value =
|
||||
system.Host1x().GetSyncpointManager().GetGuestSyncpointValue(channel_fence.id);
|
||||
|
||||
params.fence_out = channel_fence;
|
||||
params.fence_out = syncpoint_manager.GetSyncpointFence(channel_syncpoint);
|
||||
|
||||
std::memcpy(output.data(), ¶ms, output.size());
|
||||
return NvResult::Success;
|
||||
@@ -222,14 +218,13 @@ static std::vector<Tegra::CommandHeader> BuildWaitCommandList(NvFence fence) {
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<Tegra::CommandHeader> BuildIncrementCommandList(NvFence fence,
|
||||
u32 add_increment) {
|
||||
static std::vector<Tegra::CommandHeader> BuildIncrementCommandList(NvFence fence) {
|
||||
std::vector<Tegra::CommandHeader> result{
|
||||
Tegra::BuildCommandHeader(Tegra::BufferMethods::SyncpointPayload, 1,
|
||||
Tegra::SubmissionMode::Increasing),
|
||||
{}};
|
||||
|
||||
for (u32 count = 0; count < add_increment; ++count) {
|
||||
for (u32 count = 0; count < 2; ++count) {
|
||||
result.emplace_back(Tegra::BuildCommandHeader(Tegra::BufferMethods::SyncpointOperation, 1,
|
||||
Tegra::SubmissionMode::Increasing));
|
||||
result.emplace_back(
|
||||
@@ -239,14 +234,12 @@ static std::vector<Tegra::CommandHeader> BuildIncrementCommandList(NvFence fence
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::vector<Tegra::CommandHeader> BuildIncrementWithWfiCommandList(NvFence fence,
|
||||
u32 add_increment) {
|
||||
static std::vector<Tegra::CommandHeader> BuildIncrementWithWfiCommandList(NvFence fence) {
|
||||
std::vector<Tegra::CommandHeader> result{
|
||||
Tegra::BuildCommandHeader(Tegra::BufferMethods::WaitForIdle, 1,
|
||||
Tegra::SubmissionMode::Increasing),
|
||||
{}};
|
||||
const std::vector<Tegra::CommandHeader> increment{
|
||||
BuildIncrementCommandList(fence, add_increment)};
|
||||
const std::vector<Tegra::CommandHeader> increment{BuildIncrementCommandList(fence)};
|
||||
|
||||
result.insert(result.end(), increment.begin(), increment.end());
|
||||
|
||||
@@ -260,35 +253,41 @@ NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>
|
||||
|
||||
auto& gpu = system.GPU();
|
||||
|
||||
std::scoped_lock lock(channel_mutex);
|
||||
|
||||
const auto bind_id = channel_state->bind_id;
|
||||
|
||||
params.fence_out.id = channel_fence.id;
|
||||
auto& flags = params.flags;
|
||||
|
||||
if (params.flags.add_wait.Value() &&
|
||||
!syncpoint_manager.IsSyncpointExpired(params.fence_out.id, params.fence_out.value)) {
|
||||
gpu.PushGPUEntries(bind_id, Tegra::CommandList{BuildWaitCommandList(params.fence_out)});
|
||||
}
|
||||
if (flags.fence_wait.Value()) {
|
||||
if (flags.increment_value.Value()) {
|
||||
return NvResult::BadParameter;
|
||||
}
|
||||
|
||||
if (params.flags.add_increment.Value() || params.flags.increment.Value()) {
|
||||
const u32 increment_value = params.flags.increment.Value() ? params.fence_out.value : 0;
|
||||
params.fence_out.value = syncpoint_manager.IncreaseSyncpoint(
|
||||
params.fence_out.id, params.AddIncrementValue() + increment_value);
|
||||
} else {
|
||||
params.fence_out.value = syncpoint_manager.GetSyncpointMax(params.fence_out.id);
|
||||
if (!syncpoint_manager.IsFenceSignalled(params.fence)) {
|
||||
gpu.PushGPUEntries(bind_id, Tegra::CommandList{BuildWaitCommandList(params.fence)});
|
||||
}
|
||||
}
|
||||
|
||||
gpu.PushGPUEntries(bind_id, std::move(entries));
|
||||
params.fence.id = channel_syncpoint;
|
||||
|
||||
if (params.flags.add_increment.Value()) {
|
||||
if (params.flags.suppress_wfi) {
|
||||
gpu.PushGPUEntries(bind_id, Tegra::CommandList{BuildIncrementCommandList(
|
||||
params.fence_out, params.AddIncrementValue())});
|
||||
u32 increment{(flags.fence_increment.Value() != 0 ? 2 : 0) +
|
||||
(flags.increment_value.Value() != 0 ? params.fence.value : 0)};
|
||||
params.fence.value = syncpoint_manager.IncrementSyncpointMaxExt(channel_syncpoint, increment);
|
||||
|
||||
if (flags.fence_increment.Value()) {
|
||||
if (flags.suppress_wfi.Value()) {
|
||||
gpu.PushGPUEntries(bind_id,
|
||||
Tegra::CommandList{BuildIncrementCommandList(params.fence)});
|
||||
} else {
|
||||
gpu.PushGPUEntries(bind_id, Tegra::CommandList{BuildIncrementWithWfiCommandList(
|
||||
params.fence_out, params.AddIncrementValue())});
|
||||
gpu.PushGPUEntries(bind_id,
|
||||
Tegra::CommandList{BuildIncrementWithWfiCommandList(params.fence)});
|
||||
}
|
||||
}
|
||||
|
||||
flags.raw = 0;
|
||||
|
||||
std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmitGpfifo));
|
||||
return NvResult::Success;
|
||||
}
|
||||
|
||||
@@ -163,17 +163,13 @@ private:
|
||||
u32_le num_entries{}; // number of fence objects being submitted
|
||||
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<4, 1, u32_le> suppress_wfi; // suppress wait for interrupt
|
||||
BitField<8, 1, u32_le> increment; // increment the returned fence
|
||||
BitField<0, 1, u32_le> fence_wait; // append a wait sync_point to the list
|
||||
BitField<1, 1, u32_le> fence_increment; // append an increment to the list
|
||||
BitField<2, 1, u32_le> new_hw_format; // mostly ignored
|
||||
BitField<4, 1, u32_le> suppress_wfi; // suppress wait for interrupt
|
||||
BitField<8, 1, u32_le> increment_value; // increment the returned fence
|
||||
} flags;
|
||||
NvFence fence_out{}; // returned new fence object for others to wait on
|
||||
|
||||
u32 AddIncrementValue() const {
|
||||
return flags.add_increment.Value() << 1;
|
||||
}
|
||||
NvFence fence{}; // returned new fence object for others to wait on
|
||||
};
|
||||
static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(NvFence),
|
||||
"IoctlSubmitGpfifo is incorrect size");
|
||||
@@ -213,7 +209,8 @@ private:
|
||||
NvCore::SyncpointManager& syncpoint_manager;
|
||||
NvCore::NvMap& nvmap;
|
||||
std::shared_ptr<Tegra::Control::ChannelState> channel_state;
|
||||
NvFence channel_fence;
|
||||
u32 channel_syncpoint;
|
||||
std::mutex channel_mutex;
|
||||
|
||||
// Events
|
||||
Kernel::KEvent* sm_exception_breakpoint_int_report_event;
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Service::Nvidia::Devices {
|
||||
u32 nvhost_nvdec::next_id{};
|
||||
|
||||
nvhost_nvdec::nvhost_nvdec(Core::System& system_, NvCore::Container& core)
|
||||
: nvhost_nvdec_common{system_, core} {}
|
||||
: nvhost_nvdec_common{system_, core, NvCore::ChannelType::NvDec} {}
|
||||
nvhost_nvdec::~nvhost_nvdec() = default;
|
||||
|
||||
NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
||||
|
||||
@@ -48,9 +48,10 @@ std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::s
|
||||
|
||||
std::unordered_map<DeviceFD, u32> nvhost_nvdec_common::fd_to_id{};
|
||||
|
||||
nvhost_nvdec_common::nvhost_nvdec_common(Core::System& system_, NvCore::Container& core_)
|
||||
: nvdevice{system_}, core{core_},
|
||||
syncpoint_manager{core.GetSyncpointManager()}, nvmap{core.GetNvMapFile()} {}
|
||||
nvhost_nvdec_common::nvhost_nvdec_common(Core::System& system_, NvCore::Container& core_,
|
||||
NvCore::ChannelType channel_type_)
|
||||
: nvdevice{system_}, core{core_}, syncpoint_manager{core.GetSyncpointManager()},
|
||||
nvmap{core.GetNvMapFile()}, channel_type{channel_type_} {}
|
||||
nvhost_nvdec_common::~nvhost_nvdec_common() = default;
|
||||
|
||||
NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) {
|
||||
@@ -88,7 +89,7 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, const std::vector<u8>& input,
|
||||
for (std::size_t i = 0; i < syncpt_increments.size(); i++) {
|
||||
const SyncptIncr& syncpt_incr = syncpt_increments[i];
|
||||
fence_thresholds[i] =
|
||||
syncpoint_manager.IncreaseSyncpoint(syncpt_incr.id, syncpt_incr.increments);
|
||||
syncpoint_manager.IncrementSyncpointMaxExt(syncpt_incr.id, syncpt_incr.increments);
|
||||
}
|
||||
}
|
||||
for (const auto& cmd_buffer : command_buffers) {
|
||||
@@ -116,10 +117,8 @@ NvResult nvhost_nvdec_common::GetSyncpoint(const std::vector<u8>& input, std::ve
|
||||
std::memcpy(¶ms, input.data(), sizeof(IoctlGetSyncpoint));
|
||||
LOG_DEBUG(Service_NVDRV, "called GetSyncpoint, id={}", params.param);
|
||||
|
||||
if (device_syncpoints[params.param] == 0 && system.GPU().UseNvdec()) {
|
||||
device_syncpoints[params.param] = syncpoint_manager.AllocateSyncpoint();
|
||||
}
|
||||
params.value = device_syncpoints[params.param];
|
||||
const u32 id{NvCore::SyncpointManager::channel_syncpoints[static_cast<u32>(channel_type)]};
|
||||
params.value = id;
|
||||
std::memcpy(output.data(), ¶ms, sizeof(IoctlGetSyncpoint));
|
||||
|
||||
return NvResult::Success;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <vector>
|
||||
#include "common/common_types.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/hle/service/nvdrv/core/syncpoint_manager.h"
|
||||
#include "core/hle/service/nvdrv/devices/nvdevice.h"
|
||||
|
||||
namespace Service::Nvidia {
|
||||
@@ -13,14 +14,14 @@ namespace Service::Nvidia {
|
||||
namespace NvCore {
|
||||
class Container;
|
||||
class NvMap;
|
||||
class SyncpointManager;
|
||||
} // namespace NvCore
|
||||
|
||||
namespace Devices {
|
||||
|
||||
class nvhost_nvdec_common : public nvdevice {
|
||||
public:
|
||||
explicit nvhost_nvdec_common(Core::System& system_, NvCore::Container& core);
|
||||
explicit nvhost_nvdec_common(Core::System& system_, NvCore::Container& core,
|
||||
NvCore::ChannelType channel_type);
|
||||
~nvhost_nvdec_common() override;
|
||||
|
||||
protected:
|
||||
@@ -121,6 +122,7 @@ protected:
|
||||
NvCore::Container& core;
|
||||
NvCore::SyncpointManager& syncpoint_manager;
|
||||
NvCore::NvMap& nvmap;
|
||||
NvCore::ChannelType channel_type;
|
||||
std::array<u32, MaxSyncPoints> device_syncpoints{};
|
||||
};
|
||||
}; // namespace Devices
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Service::Nvidia::Devices {
|
||||
u32 nvhost_vic::next_id{};
|
||||
|
||||
nvhost_vic::nvhost_vic(Core::System& system_, NvCore::Container& core)
|
||||
: nvhost_nvdec_common{system_, core} {}
|
||||
: nvhost_nvdec_common{system_, core, NvCore::ChannelType::VIC} {}
|
||||
|
||||
nvhost_vic::~nvhost_vic() = default;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user