From da89b1432645c1faa9274de82d110eda8c50a6b4 Mon Sep 17 00:00:00 2001 From: Arkwolf Date: Sat, 4 Jun 2022 14:55:54 +0800 Subject: [PATCH 1/7] add placeholders for abi enums --- sys/src/nvid.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sys/src/nvid.rs b/sys/src/nvid.rs index 661284a4..0af7ec62 100644 --- a/sys/src/nvid.rs +++ b/sys/src/nvid.rs @@ -650,4 +650,14 @@ Unknown_36E39E6B = 0x36e39e6b, /// `GPU_GetRasterOperators(hGpu, *mut u32)` Unknown_GetROPCount = 0xfdc129fa, +NvAPI_GSync_EnumSyncDevices = 1, +NvAPI_GSync_QueryCapabilities = 2, +NvAPI_GSync_GetTopology = 3, +NvAPI_GSync_SetSyncStateSettings = 4, +NvAPI_GSync_GetControlParameters = 5, +NvAPI_GSync_SetControlParameters = 6, +NvAPI_GSync_AdjustSyncDelay = 7, +NvAPI_GSync_GetSyncStatus = 8, +NvAPI_GSync_GetStatusParameters = 9, + } From 8cc129379131e4094947f2179504c5dabc349919 Mon Sep 17 00:00:00 2001 From: Arkwolf Date: Sat, 4 Jun 2022 14:56:23 +0800 Subject: [PATCH 2/7] add ffi bindings --- sys/src/gsync.rs | 224 +++++++++++++++++++++++++++++++++++++++++++++++ sys/src/lib.rs | 1 + 2 files changed, 225 insertions(+) create mode 100644 sys/src/gsync.rs diff --git a/sys/src/gsync.rs b/sys/src/gsync.rs new file mode 100644 index 00000000..8a9e4c02 --- /dev/null +++ b/sys/src/gsync.rs @@ -0,0 +1,224 @@ +use status::NvAPI_Status; +use handles::NvPhysicalGpuHandle; +use handles::NvGSyncDeviceHandle; + +nvstruct! { + pub struct NV_GSYNC_CAPABILITIES_V1 { + version: u32, + boardId: u32, + revision: u32, + capFlags: u32, + } +} + +const NV_GSYNC_CAPABILITIES_V1_SIZE: usize = 4 * 4; + +nvstruct! { + pub struct NV_GSYNC_CAPABILITIES_V2 { + v1: NV_GSYNC_CAPABILITIES_V1, + extendedRevision: u32, + } +} + +nvinherit! { NV_GSYNC_CAPABILITIES_V2(v1: NV_GSYNC_CAPABILITIES_V1) } + +const NV_GSYNC_CAPABILITIES_V2_SIZE: usize = NV_GSYNC_CAPABILITIES_V1_SIZE + 4; + +pub type NV_GSYNC_CAPABILITIES = NV_GSYNC_CAPABILITIES_V2; + +nvversion! { NV_GSYNC_CAPABILITIES_VER_1(NV_GSYNC_CAPABILITIES_V1 = NV_GSYNC_CAPABILITIES_V1_SIZE, 1) } +nvversion! { NV_GSYNC_CAPABILITIES_VER_2(NV_GSYNC_CAPABILITIES_V2 = NV_GSYNC_CAPABILITIES_V2_SIZE, 2) } +nvversion! { NV_GSYNC_CAPABILITIES_VER = NV_GSYNC_CAPABILITIES_VER_2 } + +nvenum! { + pub enum NVAPI_GSYNC_DISPLAY_SYNC_STATE / DisplaySyncState { + NVAPI_GSYNC_DISPLAY_SYNC_STATE_UNSYNCED / Unsynced = 0, + NVAPI_GSYNC_DISPLAY_SYNC_STATE_SLAVE / Slave = 1, + NVAPI_GSYNC_DISPLAY_SYNC_STATE_MASTER / Master = 2, + } +} + +nvstruct! { + pub struct NV_GSYNC_DISPLAY { + version: u32, + displayId: u32, + isMasterable: u32, + reserved: u32, + syncState: NVAPI_GSYNC_DISPLAY_SYNC_STATE, + } +} + +nvenum! { + pub enum NVAPI_GSYNC_GPU_TOPOLOGY_CONNECTOR / TopologyConnector { + NVAPI_GSYNC_GPU_TOPOLOGY_CONNECTOR_NONE / None = 0, + NVAPI_GSYNC_GPU_TOPOLOGY_CONNECTOR_PRIMARY / Primary = 1, + NVAPI_GSYNC_GPU_TOPOLOGY_CONNECTOR_SECONDARY / Secondary = 2, + NVAPI_GSYNC_GPU_TOPOLOGY_CONNECTOR_TERTIARY / Tertiary = 3, + NVAPI_GSYNC_GPU_TOPOLOGY_CONNECTOR_QUARTERNARY / Quarternary = 4, + } +} + +nvstruct! { + pub struct NV_GSYNC_GPU { + version: u32, + hPhysicalGpu: NvPhysicalGpuHandle, + connector: NVAPI_GSYNC_GPU_TOPOLOGY_CONNECTOR, + hProxyPhysicalGpu: NvPhysicalGpuHandle, + isSynced: u32, + reserved: u32, + } +} + +nvenum! { + pub enum NVAPI_GSYNC_POLARITY / Polarity { + NVAPI_GSYNC_POLARITY_RISING_EDGE / RisingEdge = 0, + NVAPI_GSYNC_POLARITY_FALLING_EDGE / FallingEdge = 1, + NVAPI_GSYNC_POLARITY_BOTH_EDGES / BothEdges = 2, + } +} + +nvenum! { + pub enum NVAPI_GSYNC_VIDEO_MODE / VideoMode { + NVAPI_GSYNC_VIDEO_MODE_NONE / None = 0, + NVAPI_GSYNC_VIDEO_MODE_TTL / TTL = 1, + NVAPI_GSYNC_VIDEO_MODE_NTSCPALSECAM / NtscPalCam = 2, + NVAPI_GSYNC_VIDEO_MODE_HDTV / Hdtv = 3, + NVAPI_GSYNC_VIDEO_MODE_COMPOSITE / Composite = 4, + } +} + +nvenum! { + pub enum NVAPI_GSYNC_SYNC_SOURCE / SyncSource { + NVAPI_GSYNC_SYNC_SOURCE_VSYNC / VSync = 0, + NVAPI_GSYNC_SYNC_SOURCE_HOUSESYNC / HouseSync = 1, + } +} + +nvstruct! { + pub struct NV_GSYNC_DELAY { + version: u32, + numLines: u32, + numPixels: u32, + maxLines: u32, + minPixels: u32, + } +} + +nvstruct! { + pub struct NV_GSYNC_CONTROL_PARAMS { + version: u32, + polarity: NVAPI_GSYNC_POLARITY, + vmode: NVAPI_GSYNC_VIDEO_MODE, + interval: u32, + source: NVAPI_GSYNC_SYNC_SOURCE, + interlaceMode: u32, + syncSourceIsOutput: u32, + reserved: u32, + syncSkew: NV_GSYNC_DELAY, + startupDelay: NV_GSYNC_DELAY, + } +} + +nvenum! { + pub enum NVAPI_GSYNC_DELAY_TYPE / DelayType { + NVAPI_GSYNC_DELAY_TYPE_UNKNOWN / Unknown = 0, + NVAPI_GSYNC_DELAY_TYPE_SYNC_SKEW / SyncSkew = 1, + NVAPI_GSYNC_DELAY_TYPE_STARTUP / Startup = 2, + } +} + +nvstruct! { + pub struct NV_GSYNC_STATUS { + version: u32, + bIsSynced: u32, + bIsStereoSynced: u32, + bIsSyncSignalAvailable: u32, + } +} + +nvenum! { + pub enum NVAPI_GSYNC_RJ45_IO / RJ45_IO { + NVAPI_GSYNC_RJ45_OUTPUT / Output = 0, + NVAPI_GSYNC_RJ45_INPUT / Input = 1, + NVAPI_GSYNC_RJ45_UNUSED / Unused = 2, + } +} + +pub const NVAPI_MAX_RJ45_PER_GSYNC: usize = 2; + +nvstruct! { + pub struct NV_GSYNC_STATUS_PARAMS_V1 { + version: u32, + refreshRate: u32, + RJ45_IO: [NVAPI_GSYNC_RJ45_IO; NVAPI_MAX_RJ45_PER_GSYNC], + RJ45_Ethernet: [u32; NVAPI_MAX_RJ45_PER_GSYNC], + houseSyncIncoming: u32, + bHouseSync: u32, + } +} + +const NV_GSYNC_STATUS_PARAMS_V1_SIZE: usize = std::mem::size_of::(); + +nvstruct! { + pub struct NV_GSYNC_STATUS_PARAMS_V2 { + v1: NV_GSYNC_STATUS_PARAMS_V1, + bInternalSlave: u32, + reserved: u32, + } +} + +nvinherit! { NV_GSYNC_STATUS_PARAMS_V2(v1: NV_GSYNC_STATUS_PARAMS_V1) } + +const NV_GSYNC_STATUS_PARAMS_V2_SIZE: usize = std::mem::size_of::(); + +pub type NV_GSYNC_STATUS_PARAMS = NV_GSYNC_STATUS_PARAMS_V2; + +nvversion! { NV_GSYNC_STATUS_PARAMS_VER_1(NV_GSYNC_STATUS_PARAMS_V1 = NV_GSYNC_STATUS_PARAMS_V1_SIZE, 1) } +nvversion! { NV_GSYNC_STATUS_PARAMS_VER_2(NV_GSYNC_STATUS_PARAMS_V2 = NV_GSYNC_STATUS_PARAMS_V2_SIZE, 2) } +nvversion! { NV_GSYNC_STATUS_PARAMS_VER = NV_GSYNC_STATUS_PARAMS_VER_2 } + +nvapi! { + pub type GSync_EnumSyncDevicesFn = extern "C" fn(nvGSyncHandles: *mut NvGSyncDeviceHandle, gsyncCount: *mut u32) -> NvAPI_Status; + pub unsafe fn NvAPI_GSync_EnumSyncDevices; +} + +nvapi! { + pub type GSync_QueryCapabilitiesFn = extern "C" fn(hNvGSyncDevice: NvGSyncDeviceHandle, pNvGSyncCapabilities: *mut NV_GSYNC_CAPABILITIES) -> NvAPI_Status; + pub unsafe fn NvAPI_GSync_QueryCapabilities; +} + +nvapi! { + pub type GSync_GetTopologyFn = extern "C" fn(hNvGSyncDevice: NvGSyncDeviceHandle, gsyncGpuCount: *mut u32, gsyncGPUs: *mut NV_GSYNC_GPU, gsyncDisplayCount: u32, gsyncDisplays: *mut NV_GSYNC_DISPLAY) -> NvAPI_Status; + pub unsafe fn NvAPI_GSync_GetTopology; +} + +nvapi! { + pub type GSync_SetSyncStateSettingsFn = extern "C" fn(gsyncDisplayCount: u32, pGsyncDisplays: NV_GSYNC_DISPLAY, flags: u32) -> NvAPI_Status; + pub unsafe fn NvAPI_GSync_SetSyncStateSettings; +} + +nvapi! { + pub type GSync_GetControlParametersFn = extern "C" fn(hNvGSyncDevice: NvGSyncDeviceHandle, pGsyncControls: *mut NV_GSYNC_CONTROL_PARAMS) -> NvAPI_Status; + pub unsafe fn NvAPI_GSync_GetControlParameters; +} + +nvapi! { + pub type GSync_SetControlParametersFn = extern "C" fn(hNvGSyncDevice: NvGSyncDeviceHandle, pGsyncControls: *mut NV_GSYNC_CONTROL_PARAMS) -> NvAPI_Status; + pub unsafe fn NvAPI_GSync_SetControlParameters; +} + +nvapi! { + // Parameter should be pointer? + pub type GSync_AdjustSyncDelayFn = extern "C" fn(hNvGSyncDevice: NvGSyncDeviceHandle, delayType: NVAPI_GSYNC_DELAY_TYPE, pGsyncDelay: *mut NV_GSYNC_DELAY, syncSteps: *mut u32) -> NvAPI_Status; + pub unsafe fn NvAPI_GSync_AdjustSyncDelay; +} + +nvapi! { + pub type GSync_GetSyncStatusFn = extern "C" fn(hNvGSyncDevice: NvGSyncDeviceHandle, hPhysicalGpu: NvPhysicalGpuHandle, status: *mut NV_GSYNC_STATUS) -> NvAPI_Status; + pub unsafe fn NvAPI_GSync_GetSyncStatus; +} + +nvapi! { + pub type GSync_GetStatusParametersFn = extern "C" fn(hNvGSyncDevice: NvGSyncDeviceHandle, pStatusParams: *mut NV_GSYNC_STATUS_PARAMS) -> NvAPI_Status; + pub unsafe fn NvAPI_GSync_GetStatusParameters; +} \ No newline at end of file diff --git a/sys/src/lib.rs b/sys/src/lib.rs index 5c221b73..d522df35 100644 --- a/sys/src/lib.rs +++ b/sys/src/lib.rs @@ -21,6 +21,7 @@ pub mod nvid; pub mod nvapi; pub mod status; pub mod types; +pub mod gsync; /// NVAPI Handles - These handles are retrieved from various calls and passed in /// to others in NvAPI These are meant to be opaque types. Do not assume they From 4d91659037eff4b46b80a06538500695240dddbc Mon Sep 17 00:00:00 2001 From: Arkwolf Date: Sat, 4 Jun 2022 14:56:43 +0800 Subject: [PATCH 3/7] skeleton gsync object --- src/gsync.rs | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/gsync.rs diff --git a/src/gsync.rs b/src/gsync.rs new file mode 100644 index 00000000..3190f37a --- /dev/null +++ b/src/gsync.rs @@ -0,0 +1,9 @@ + +#[derive(Debug)] +pub struct GSyncDevice(sys::handles::NvGSyncDeviceHandle); + +impl GSyncDevice { + pub fn handle(&self) -> &sys::handles::NvGSyncDeviceHandle { + &self.0 + } +} \ No newline at end of file From 5b2e61a1b51bc39346eb9dc2851e9870e476d2b4 Mon Sep 17 00:00:00 2001 From: Arkwolf Date: Sat, 4 Jun 2022 16:06:45 +0800 Subject: [PATCH 4/7] add max sync device constant --- sys/src/types.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/src/types.rs b/sys/src/types.rs index 9c520e7b..41ee430e 100644 --- a/sys/src/types.rs +++ b/sys/src/types.rs @@ -69,6 +69,8 @@ pub const NVAPI_MAX_ACPI_IDS: usize = 16; pub const NVAPI_MAX_VIEW_MODES: usize = 8; pub const NVAPI_MAX_HEADS_PER_GPU: usize = 32; +pub const NVAPI_MAX_GSYNC_DEVICES: usize = 4; + /// Maximum heads, each with `NVAPI_DESKTOP_RES` resolution pub const NV_MAX_HEADS: usize = 4; /// Maximum number of input video streams, each with a `NVAPI_VIDEO_SRC_INFO` From a7bb68fcfc85d149c6743ca12c39835a3ccba876 Mon Sep 17 00:00:00 2001 From: Arkwolf Date: Sat, 4 Jun 2022 16:07:07 +0800 Subject: [PATCH 5/7] prep status for external use --- sys/src/gsync.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sys/src/gsync.rs b/sys/src/gsync.rs index 8a9e4c02..647bbb84 100644 --- a/sys/src/gsync.rs +++ b/sys/src/gsync.rs @@ -128,14 +128,18 @@ nvenum! { } nvstruct! { + #[derive(Debug, Default)] pub struct NV_GSYNC_STATUS { - version: u32, - bIsSynced: u32, - bIsStereoSynced: u32, - bIsSyncSignalAvailable: u32, + pub version: u32, + pub bIsSynced: u32, + pub bIsStereoSynced: u32, + pub bIsSyncSignalAvailable: u32, } } +// TODO: this most likely wont work and needs to be updated. +nvversion! { NV_GSYNC_STATUS_VER(NV_GSYNC_STATUS = 0, 1) /* temp */} + nvenum! { pub enum NVAPI_GSYNC_RJ45_IO / RJ45_IO { NVAPI_GSYNC_RJ45_OUTPUT / Output = 0, @@ -178,7 +182,7 @@ nvversion! { NV_GSYNC_STATUS_PARAMS_VER_2(NV_GSYNC_STATUS_PARAMS_V2 = NV_GSYNC_S nvversion! { NV_GSYNC_STATUS_PARAMS_VER = NV_GSYNC_STATUS_PARAMS_VER_2 } nvapi! { - pub type GSync_EnumSyncDevicesFn = extern "C" fn(nvGSyncHandles: *mut NvGSyncDeviceHandle, gsyncCount: *mut u32) -> NvAPI_Status; + pub type GSync_EnumSyncDevicesFn = extern "C" fn(nvGSyncHandles: *mut [NvGSyncDeviceHandle; super::types::NVAPI_MAX_GSYNC_DEVICES], gsyncCount: *mut u32) -> NvAPI_Status; pub unsafe fn NvAPI_GSync_EnumSyncDevices; } From 1c2c321692da263259183906bfd7587e64dbd9ad Mon Sep 17 00:00:00 2001 From: Arkwolf Date: Sat, 4 Jun 2022 16:07:30 +0800 Subject: [PATCH 6/7] begin sync card implementation --- src/gsync.rs | 33 +++++++++++++++++++++++++++++++-- src/lib.rs | 1 + 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/gsync.rs b/src/gsync.rs index 3190f37a..b40b868d 100644 --- a/src/gsync.rs +++ b/src/gsync.rs @@ -1,9 +1,38 @@ +use sys::{self}; +use sys::gsync::{self}; + +use crate::PhysicalGpu; #[derive(Debug)] -pub struct GSyncDevice(sys::handles::NvGSyncDeviceHandle); +pub struct GSyncDevice { + handle: sys::handles::NvGSyncDeviceHandle, +} impl GSyncDevice { + pub fn new(handle: sys::handles::NvGSyncDeviceHandle) -> Self { + Self {handle} + } + pub fn handle(&self) -> &sys::handles::NvGSyncDeviceHandle { - &self.0 + &self.handle + } + + pub fn get_sync_devices() -> sys::Result> { + trace!("gsync.enumerate()"); + let mut handles = [Default::default(); sys::types::NVAPI_MAX_GSYNC_DEVICES]; + let mut len = 0; + match unsafe { gsync::NvAPI_GSync_EnumSyncDevices(&mut handles, &mut len) } { + status => sys::status_result(status).map(move |_| handles[..len as usize].iter().cloned().map(|x| GSyncDevice::new(x)).collect()), + } + } + + pub fn get_sync_status(&self, gpu: PhysicalGpu) -> sys::Result { + let mut status: gsync::NV_GSYNC_STATUS::default(); + status.version = gsync::NV_GSYNC_STATUS_VER; + match unsafe { + gsync::NvAPI_GSync_GetSyncStatus(*self.handle(), *gpu.handle(), &mut status) + } { + status => sys::status_result(status) + } } } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 5fb8306f..133cab47 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ mod pstate; mod clock; mod thermal; mod gpu; +mod gsync; mod info; #[cfg(feature = "i2c")] mod i2c_impl; From b455da7f9ecaf854e1800c3259989ec980ab0f1d Mon Sep 17 00:00:00 2001 From: MajorArkwolf Date: Sun, 5 Jun 2022 12:51:08 +0800 Subject: [PATCH 7/7] add address locations to functions. --- sys/src/nvid.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/sys/src/nvid.rs b/sys/src/nvid.rs index 0af7ec62..5d6dc7ae 100644 --- a/sys/src/nvid.rs +++ b/sys/src/nvid.rs @@ -650,14 +650,15 @@ Unknown_36E39E6B = 0x36e39e6b, /// `GPU_GetRasterOperators(hGpu, *mut u32)` Unknown_GetROPCount = 0xfdc129fa, -NvAPI_GSync_EnumSyncDevices = 1, -NvAPI_GSync_QueryCapabilities = 2, -NvAPI_GSync_GetTopology = 3, -NvAPI_GSync_SetSyncStateSettings = 4, -NvAPI_GSync_GetControlParameters = 5, -NvAPI_GSync_SetControlParameters = 6, -NvAPI_GSync_AdjustSyncDelay = 7, -NvAPI_GSync_GetSyncStatus = 8, -NvAPI_GSync_GetStatusParameters = 9, +//source: nvapi.h +NvAPI_GSync_EnumSyncDevices = 0x0D9639601, +NvAPI_GSync_QueryCapabilities = 0x44A3F1D1, +NvAPI_GSync_GetTopology = 0x4562BC38, +NvAPI_GSync_SetSyncStateSettings = 0x60ACDFDD, +NvAPI_GSync_GetControlParameters = 0x16DE1C6A, +NvAPI_GSync_SetControlParameters = 0x8BBFF88B, +NvAPI_GSync_AdjustSyncDelay = 0x2D11FF51, +NvAPI_GSync_GetSyncStatus = 0x0F1F5B434, +NvAPI_GSync_GetStatusParameters = 0x70D404EC, }