diff options
Diffstat (limited to '')
5 files changed, 53 insertions, 44 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index ce6065db2..4ee8c5733 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -16,7 +16,7 @@ namespace Service::Nvidia::Devices { 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; +nvdisp_disp0::~nvdisp_disp0() = default; NvResult nvdisp_disp0::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { @@ -42,15 +42,15 @@ void nvdisp_disp0::OnClose(DeviceFD fd) {} void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride, NVFlinger::BufferQueue::BufferTransformFlags transform, const Common::Rectangle<int>& crop_rect) { - VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle); + const VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle); LOG_TRACE(Service, "Drawing from address {:X} offset {:08X} Width {} Height {} Stride {} Format {}", addr, offset, width, height, stride, format); - using PixelFormat = Tegra::FramebufferConfig::PixelFormat; - const Tegra::FramebufferConfig framebuffer{ - addr, offset, width, height, stride, static_cast<PixelFormat>(format), - transform, crop_rect}; + const auto pixel_format = static_cast<Tegra::FramebufferConfig::PixelFormat>(format); + const auto transform_flags = static_cast<Tegra::FramebufferConfig::TransformFlags>(transform); + const Tegra::FramebufferConfig framebuffer{addr, offset, width, height, + stride, pixel_format, transform_flags, crop_rect}; system.GetPerfStats().EndSystemFrame(); system.GPU().SwapBuffers(&framebuffer); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 775e76330..f9b82b504 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -92,6 +92,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector if (syncpoint_manager.IsSyncpointExpired(params.syncpt_id, params.threshold)) { params.value = syncpoint_manager.GetSyncpointMin(params.syncpt_id); std::memcpy(output.data(), ¶ms, sizeof(params)); + events_interface.failed[event_id] = false; return NvResult::Success; } @@ -99,6 +100,7 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector syncpoint_manager.IsSyncpointExpired(params.syncpt_id, params.threshold)) { params.value = new_value; std::memcpy(output.data(), ¶ms, sizeof(params)); + events_interface.failed[event_id] = false; return NvResult::Success; } @@ -111,13 +113,13 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector event.event->GetWritableEvent().Signal(); return NvResult::Success; } - auto lock = gpu.LockSync(); const u32 current_syncpoint_value = event.fence.value; const s32 diff = current_syncpoint_value - params.threshold; if (diff >= 0) { event.event->GetWritableEvent().Signal(); params.value = current_syncpoint_value; std::memcpy(output.data(), ¶ms, sizeof(params)); + events_interface.failed[event_id] = false; return NvResult::Success; } const u32 target_value = current_syncpoint_value - diff; @@ -132,23 +134,34 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector } 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; + const bool bad_parameter = status != EventState::Free && status != EventState::Registered; + if (bad_parameter) { + std::memcpy(output.data(), ¶ms, sizeof(params)); + return NvResult::BadParameter; + } + 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; + event.event->GetWritableEvent().Clear(); + if (events_interface.failed[event_id]) { + { + auto lk = system.StallCPU(); + gpu.WaitFence(params.syncpt_id, target_value); + system.UnstallCPU(); } - params.value |= event_id; - event.event->GetWritableEvent().Clear(); - gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value); std::memcpy(output.data(), ¶ms, sizeof(params)); - return NvResult::Timeout; + events_interface.failed[event_id] = false; + return NvResult::Success; } + gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value); std::memcpy(output.data(), ¶ms, sizeof(params)); - return NvResult::BadParameter; + return NvResult::Timeout; } NvResult nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output) { @@ -201,6 +214,7 @@ NvResult nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::v if (events_interface.status[event_id] == EventState::Waiting) { events_interface.LiberateEvent(event_id); } + events_interface.failed[event_id] = true; syncpoint_manager.RefreshSyncpoint(events_interface.events[event_id].fence.id); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index c0a380088..54ac105d5 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -13,6 +13,14 @@ #include "video_core/memory_manager.h" namespace Service::Nvidia::Devices { +namespace { +Tegra::CommandHeader BuildFenceAction(Tegra::GPU::FenceOperation op, u32 syncpoint_id) { + Tegra::GPU::FenceAction result{}; + result.op.Assign(op); + result.syncpoint_id.Assign(syncpoint_id); + return {result.raw}; +} +} // namespace nvhost_gpu::nvhost_gpu(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, SyncpointManager& syncpoint_manager_) @@ -187,7 +195,7 @@ static std::vector<Tegra::CommandHeader> BuildWaitCommandList(Fence fence) { {fence.value}, Tegra::BuildCommandHeader(Tegra::BufferMethods::FenceAction, 1, Tegra::SubmissionMode::Increasing), - Tegra::GPU::FenceAction::Build(Tegra::GPU::FenceOperation::Acquire, fence.id), + BuildFenceAction(Tegra::GPU::FenceOperation::Acquire, fence.id), }; } @@ -200,8 +208,7 @@ static std::vector<Tegra::CommandHeader> BuildIncrementCommandList(Fence fence, for (u32 count = 0; count < add_increment; ++count) { result.emplace_back(Tegra::BuildCommandHeader(Tegra::BufferMethods::FenceAction, 1, Tegra::SubmissionMode::Increasing)); - result.emplace_back( - Tegra::GPU::FenceAction::Build(Tegra::GPU::FenceOperation::Increment, fence.id)); + result.emplace_back(BuildFenceAction(Tegra::GPU::FenceOperation::Increment, fence.id)); } return result; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index 845de724d..e61261f98 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp @@ -69,8 +69,7 @@ NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u std::vector<Reloc> relocs(params.relocation_count); std::vector<u32> reloc_shifts(params.relocation_count); std::vector<SyncptIncr> syncpt_increments(params.syncpoint_count); - std::vector<SyncptIncr> wait_checks(params.syncpoint_count); - std::vector<Fence> fences(params.fence_count); + std::vector<u32> fence_thresholds(params.fence_count); // Slice input into their respective buffers std::size_t offset = sizeof(IoctlSubmit); @@ -78,15 +77,13 @@ NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u offset += SliceVectors(input, relocs, params.relocation_count, offset); offset += SliceVectors(input, reloc_shifts, params.relocation_count, offset); offset += SliceVectors(input, syncpt_increments, params.syncpoint_count, offset); - offset += SliceVectors(input, wait_checks, params.syncpoint_count, offset); - offset += SliceVectors(input, fences, params.fence_count, offset); + offset += SliceVectors(input, fence_thresholds, params.fence_count, offset); auto& gpu = system.GPU(); if (gpu.UseNvdec()) { for (std::size_t i = 0; i < syncpt_increments.size(); i++) { const SyncptIncr& syncpt_incr = syncpt_increments[i]; - fences[i].id = syncpt_incr.id; - fences[i].value = + fence_thresholds[i] = syncpoint_manager.IncreaseSyncpoint(syncpt_incr.id, syncpt_incr.increments); } } @@ -98,11 +95,6 @@ NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u cmdlist.size() * sizeof(u32)); gpu.PushCommandBuffer(cmdlist); } - if (gpu.UseNvdec()) { - fences[0].value = syncpoint_manager.IncreaseSyncpoint(fences[0].id, 1); - Tegra::ChCommandHeaderList cmdlist{{(4 << 28) | fences[0].id}}; - gpu.PushCommandBuffer(cmdlist); - } std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmit)); // Some games expect command_buffers to be written back offset = sizeof(IoctlSubmit); @@ -110,8 +102,7 @@ NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u offset += WriteVectors(output, relocs, offset); offset += WriteVectors(output, reloc_shifts, offset); offset += WriteVectors(output, syncpt_increments, offset); - offset += WriteVectors(output, wait_checks, offset); - offset += WriteVectors(output, fences, offset); + offset += WriteVectors(output, fence_thresholds, offset); return NvResult::Success; } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h index af59f00d2..ae4199b79 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h @@ -56,19 +56,16 @@ protected: s32 target{}; s32 target_offset{}; }; - static_assert(sizeof(Reloc) == 0x10, "CommandBuffer has incorrect size"); + static_assert(sizeof(Reloc) == 0x10, "Reloc has incorrect size"); struct SyncptIncr { u32 id{}; u32 increments{}; + u32 unk0{}; + u32 unk1{}; + u32 unk2{}; }; - static_assert(sizeof(SyncptIncr) == 0x8, "CommandBuffer has incorrect size"); - - struct Fence { - u32 id{}; - u32 value{}; - }; - static_assert(sizeof(Fence) == 0x8, "CommandBuffer has incorrect size"); + static_assert(sizeof(SyncptIncr) == 0x14, "SyncptIncr has incorrect size"); struct IoctlGetSyncpoint { // Input |