nvfancontrol icon indicating copy to clipboard operation
nvfancontrol copied to clipboard

RTX Fan Control Windows

Open MaynardMiner opened this issue 5 years ago • 36 comments

Hello,

I was trying your controller in windows. I have multiple GPUs.

Found 8 available GPU(s)
GPU #0: GeForce GTX 1070
 COOLER-0

It doesn't seem like they all show up.

So I tried to set a fan speed:

nvfan -g 1 -l 40,50
WARN - No config file found; using default curve
thread 'main' panicked at 'index out of bounds: the len is 1 but the index is 1', /rustc/a53f9df32fbb0b5f4382caaad8f1a46f36ea887c\src\libcore\slice\mod.rs:2695:10
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

So I tried -g 0 (but instructions say must be > 0 )

nvfan -g 0 -l 40,50
WARN - No config file found; using default curve
INFO - NVIDIA driver version: 430.86
INFO - NVIDIA graphics adapter #0: GeForce GTX 1070
INFO -   GPU #0 coolers: COOLER-0
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: "NvAPI_GPU_GetFullName() failed; error -101"', src\libcore\result.rs:999:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

Am I using it wrong? I placed the recent nvapi .dll's in source directory, just like instructions.

Setup:

Mixture of RTX & GTX cards (8 total). I am trying to find a command line tool that will set fan speed for both. 64-bit Windows 10

MaynardMiner avatar Jul 08 '19 05:07 MaynardMiner

Oh- Gpu 0 in the example is a gtx card. #1 on the bus is an rtx.

However, if I am reading your script right, it looks like you came up with a way to handle dual fan control of rtx cards, which if that is the case, if I can get this to work- You would ne my hero

I have been spending days trying to write c++ script that will work for rtx cards, with no luck.

MaynardMiner avatar Jul 08 '19 06:07 MaynardMiner

Hi! Unfortunately testing is lacking on Windows and things tend to break. I only have one card and most people use nvfancontrol on Linux. There is room for improvement if you're willing to test!!

It is a bit troubling than only one device is enumerated although all of them are detected. This is probably some bug I need to identify.

Coolers being individually controllable depends both on the card, and the VBIOS of the card. Most RTX cards should allow that though.

Would it be possible to give me an overview of your system setup? For instance what kind of cards you have and in what sequence, ie. how they appear on the windows device manager. Can you also repeat the above scenarios with the debug flag (-d) enabled? It might give us some more insight.

foucault avatar Jul 08 '19 07:07 foucault

image

It's more just finding a command line tool that works in Windows, that supports RTX cards. I have went through many. It seems no one has been able to figure out how the hidden NVAPI methods for the cards, the only thing I have found is that the reason is likely because RTX cards have dual fan control.

image

C:\Users\Mayna\Documents\GitHub\nvfancontrol\target\release>nvfan.exe -p -d
Found 8 available GPU(s)
GPU #0: GeForce GTX 1070
 COOLER-0
C:\Users\Mayna\Documents\GitHub\nvfancontrol\target\release>nvfan.exe -g 0 -l 40,50 -d
WARN - No config file found; using default curve
DEBUG - Default configuration loaded
DEBUG - [[gpus]]
id = 0
enabled = true
points = [[41, 20], [49, 30], [57, 45], [66, 55], [75, 63], [78, 72], [80, 80]]
DEBUG - Curve points: [(41, 20), (49, 30), (57, 45), (66, 55), (75, 63), (78, 72), (80, 80)]
INFO - NVIDIA driver version: 430.86
INFO - NVIDIA graphics adapter #0: GeForce GTX 1070
INFO -   GPU #0 coolers: COOLER-0
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: "NvAPI_GPU_GetFullName() failed; error -101"', src\libcore\result.rs:999:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
DEBUG - Resetting fan control
C:\Users\Mayna\Documents\GitHub\nvfancontrol\target\release>nvfan.exe -g 1 -l 40,50 -d
WARN - No config file found; using default curve
DEBUG - Default configuration loaded
DEBUG - [[gpus]]
id = 1
enabled = true
points = [[41, 20], [49, 30], [57, 45], [66, 55], [75, 63], [78, 72], [80, 80]]
thread 'main' panicked at 'index out of bounds: the len is 1 but the index is 1', /rustc/a53f9df32fbb0b5f4382caaad8f1a46f36ea887c\src\libcore\slice\mod.rs:2695:10
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

MaynardMiner avatar Jul 08 '19 13:07 MaynardMiner

I am a programmer myself, I wrote a C++ command line script that works for AMD, that controls fans. I just am not hugely familiar with rust, but if there is something you need me to try to or look at code-wise, I am familiar with how NVAPI works at this point, and have been picking apart the script enough to understand the basics of it.

MaynardMiner avatar Jul 08 '19 13:07 MaynardMiner

I believe I found where the error is. It seems like GPU handles are not properly allocated here so NvAPI_GPU_GetFullName fails because it cannot find a correct handle for any GPU past 0, hence the -101 error which is exactly that: NVAPI_EXPECTED_PHYSICAL_GPU_HANDLE. This will probably be the same for all functions that access the Physical GPU handles. I will try to put out a debug build for you to test hopefully within the weekend!

foucault avatar Jul 12 '19 11:07 foucault

No problem. I found the C# NVAPIwrapper github, and build a simple program to control fans. It seems like it worked fine for GTX, but the dual fans in RTX cards were not responding. I'm pretty sure they are using the same methods as your NVAPI wrapper.

https://github.com/falahati/NvAPIWrapper

GPU.PhysicalGPU.CoolerInformation

I don't think your rust wrapper will work with RTX series cards, regardless of it is working or not. NVIDIA has the methods for RTX fan control in Windows locked down/hidden good. Its frustrating.

MaynardMiner avatar Jul 12 '19 23:07 MaynardMiner

NVAPI is a mess of semi-hidden stuff with minimal documentation. However per-GPU coolers are essentially an array of length NVAPI_MAX_COOLERS_PER_GPU; presently 3 so technically information is retrieved (and hopefully applied on a per-cooler basis).

foucault avatar Jul 13 '19 00:07 foucault

internal const int MaxNumberOfCoolersPerGPU = 3;

Nvapiwrapper has it set.

What I get when running their method on RTX cards is NVAPI_NOT_SUPPORTED, and it looks like it is very similar to your function.

It seems that its not that its not an issue of targeting coolers, but that the method is not available for RTX GPU entirely. Or maybe NVAPIWrapper coded it wrong, but theirs works on GTX cards no problem. I think NVIDIA may have a new method to set coolers for RTX cards. I am going to consult linux nvctrl.h, and see if they have a separate function for it, with a different address or something as homework.

MaynardMiner avatar Jul 13 '19 00:07 MaynardMiner

Address=00A54220

ClientFanCoolers_SetControl( struct NvPhysicalGpuHandle__ *, unsigned long *,unsigned long *, int *, unsigned long *, int *)

This is what I see I when I set fan with a manufacturer controller.

Just thought I would share.

MaynardMiner avatar Jul 13 '19 01:07 MaynardMiner

One thing at a time! I think I fixed the issue where not all of the GPUs are enumerated. Can you please try this build and let me know of the output?

If you want to build from source here's the patch to master.

foucault avatar Jul 13 '19 18:07 foucault

C:\Users\Mayna\Desktop\nvfancontrol> nvfancontrol.exe -g 0 -l 40,50 -d
WARN - No config file found; using default curve
DEBUG - Default configuration loaded
DEBUG - [[gpus]]
id = 0
enabled = true
points = [[41, 20], [49, 30], [57, 45], [66, 55], [75, 63], [78, 72], [80, 80]]
DEBUG - Curve points: [(41, 20), (49, 30), (57, 45), (66, 55), (75, 63), (78, 72), (80, 80)]
INFO - NVIDIA driver version: 430.86
INFO - NVIDIA graphics adapter #0: GeForce GTX 1070
INFO -   GPU #0 coolers: COOLER-0
INFO - NVIDIA graphics adapter #1: GeForce RTX 2070
WARN - Could not get GPU cooler indices or unsupported OS
INFO - NVIDIA graphics adapter #2: GeForce GTX 1070
INFO -   GPU #2 coolers: COOLER-0
INFO - NVIDIA graphics adapter #3: GeForce GTX 1050 Ti
INFO -   GPU #3 coolers: COOLER-0
INFO - NVIDIA graphics adapter #4: GeForce RTX 2070
WARN - Could not get GPU cooler indices or unsupported OS
INFO - NVIDIA graphics adapter #5: GeForce RTX 2070
WARN - Could not get GPU cooler indices or unsupported OS
INFO - NVIDIA graphics adapter #6: GeForce RTX 2070
WARN - Could not get GPU cooler indices or unsupported OS
INFO - NVIDIA graphics adapter #7: GeForce RTX 2070
WARN - Could not get GPU cooler indices or unsupported OS
DEBUG - Temp: 38; Speed: [0] RPM ([0]%); Load: 0%; Mode: Auto
DEBUG - Temp: 38; Speed: [0] RPM ([0]%); Load: 0%; Mode: Auto
DEBUG - Temp: 38; Speed: [0] RPM ([0]%); Load: 0%; Mode: Auto
DEBUG - Temp: 38; Speed: [0] RPM ([0]%); Load: 0%; Mode: Auto
DEBUG - Temp: 38; Speed: [0] RPM ([0]%); Load: 0%; Mode: Auto
DEBUG - Temp: 38; Speed: [0] RPM ([0]%); Load: 0%; Mode: Auto
DEBUG - Temp: 38; Speed: [0] RPM ([0]%); Load: 0%; Mode: Auto
DEBUG - Temp: 38; Speed: [0] RPM ([0]%); Load: 0%; Mode: Auto
DEBUG - Temp: 38; Speed: [0] RPM ([0]%); Load: 0%; Mode: Auto
DEBUG - Temp: 38; Speed: [0] RPM ([0]%); Load: 0%; Mode: Auto
DEBUG - Temp: 38; Speed: [0] RPM ([0]%); Load: 0%; Mode: Auto
DEBUG - Temp: 38; Speed: [0] RPM ([0]%); Load: 0%; Mode: Auto
DEBUG - Interrupt signal
DEBUG - Exiting
DEBUG - Resetting fan control
C:\Users\Mayna\Desktop\nvfancontrol> nvfancontrol.exe -g 1 -l 40,50 -d
WARN - No config file found; using default curve
DEBUG - Default configuration loaded
DEBUG - [[gpus]]
id = 1
enabled = true
points = [[41, 20], [49, 30], [57, 45], [66, 55], [75, 63], [78, 72], [80, 80]]
thread 'main' panicked at 'index out of bounds: the len is 1 but the index is 1', /rustc/a53f9df32fbb0b5f4382caaad8f1a46f36ea887c\src\libcore\slice\mod.rs:2695:10
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

First one is gpu 0, which is GTX card. It doesn't change speed, but no errors. Second is GPU 1, which is an RTX card- Fails with error.

MaynardMiner avatar Jul 13 '19 21:07 MaynardMiner

May I also have the output of nvfancontrol -p ?

For the GTX 1070 is normal that the fan is at 0 since by default it will kick in once T ≥ 41C. Otherwise is a bit strange that no fans are found for the RTXs. I'm wondering if this is problem with my code or NVAPI. Need to investigate further...

foucault avatar Jul 13 '19 21:07 foucault

C:\Users\Mayna\Desktop\nvfancontrol>nvfancontrol.exe -p -d
Found 8 available GPU(s)
GPU #0: GeForce GTX 1070
 COOLER-0
GPU #1: GeForce RTX 2070

What I have found from poking at manufacturer software, is that there is two different calls for NVIDIA fans. GTX uses a call like yours:

SetFanSpeed(int,unsigned long)

While RTX uses a different call:

ClientFanCoolers_SetControl( struct NvPhysicalGpuHandle__ *, unsigned long *,unsigned long *, int *, unsigned long *, int *)

Both of them proceed:

IsMultiGpuFanControlLockingEnabled(void)

and

IsFanControLocked(void)

Likely to determine fan control state needs to be set to manual, and which function to use (old or new).

MaynardMiner avatar Jul 13 '19 21:07 MaynardMiner

It is probably the case that the handling of per-fan speed is different for RTX. However we should still be able to enumerate the fans regardless but listing of fans fails (that's why the output of -p fails after the first RTX). I should try to fix that first before anything else.

That being said the signature ClientFanCooler_SetControl is slightly more complicated than I would've expected. I guess one is the cooler id and the other the actual speed but it's not clear what the rest of the arguments are.

foucault avatar Jul 13 '19 21:07 foucault

I was wrong

For GTX the function call is this:

	GpuGetCoolerSettings(struct NvPhysicalGpuHandle__ *,unsigned long,struct NV_GPU_GETCOOLER_SETTINGS_V4 *)
	GpuSetCoolerLevels(struct NvPhysicalGpuHandle__ *,unsigned long,struct NV_GPU_SETCOOLER_LEVEL_V2 *)

For RTX, it goes straight to this:

	ClientFanCoolers_SetControl(struct NvPhysicalGpuHandle__ *,unsigned long *,unsigned long *,int *,unsigned long *,int *)

I assume the unsigned long are meant to simulate NVU32 values. I'm not sure what the rest are.

MaynardMiner avatar Jul 13 '19 23:07 MaynardMiner

https://github.com/falahati/NvAPIWrapper/issues/10

I have also been talking about it here, if it interests you.

MaynardMiner avatar Jul 13 '19 23:07 MaynardMiner

I give up. Stupid NVIDIA ...We can't control our own fans in Windows, thought its as simple as pie in linux.

The only thing I have figured out I believe is 100% is:

ClientFanCoolers_SetControl( [gpu handle] , ?, ?, [fan speed %] , ?, ? )

NvAPI_QueryInterface(0x814B209F)

I spent waaaay too much time on this at this point. Its frustrating that NVIDIA has to be so annoying and not release methods. Most people want to keep their cards cooler than their factory settings.

MaynardMiner avatar Jul 14 '19 18:07 MaynardMiner

https://github.com/falahati/NvAPIWrapper/issues/10

We figured out new fan methods in windows. He solved in his wrapper, and I confirmed it works for him.

Just letting you know, if you wanted to make a Rust version. If you write something and need testing, just tag me.

MaynardMiner avatar Jul 24 '19 03:07 MaynardMiner

Yes I was monitoring the other thread. There are indeed different functions for RTX cards. I will try to code that path in once I have some time over the next few days. I'm definitely going to need some help testing.

foucault avatar Jul 24 '19 07:07 foucault

Following from #23 a test binary should print all fans for the card and their current levels and RPMs.

foucault avatar May 08 '20 23:05 foucault

Paging @Gordin I'm attaching a build with initial support for the new client API functions. I've done some light testing and it seems like it's working but I'd appreciate a couple more tests before merging in the changes. If you're compiling from source please use the rtx branch and compile with cargo build --features=rtx.

Ideally I'd like to have the following

  • The output of nvfancontrol -p: this should print GPUs and their coolers
  • The output of nvfancontrol -d -m: this should periodically print the temperatures, load and fan settings as well as control mode (manual or auto)
  • The output of nvfancontrol -d -f: this should do what the previous command does and additionally manage the fans according to the specified curve. Please make sure there isn't any other program trying to access the fans because funny things may happen!
  • If you have access to older GPUs (say 8xx, 9xx, 10xx) please try to run this build of nvfancontrol and check if it behaves as expected.

Again thanks for helping me debug this!!

nvfancontrol.zip

foucault avatar May 09 '20 16:05 foucault

I compiled it myself and it seems to be working. The first -m and -f was with afterburner still running, the second ones are without afterburner. The values all seem to be correct. The alternating 0 and 1XXX values are because the card has flickering issue when going from 0 to anything below ~38%. Should the anti-flickering stuff work with this build? That's what I wanted to use nvfancontrol for in the first place ^^

PS C:\Users\Gordin\Documents\code\nvfancontrol> .\target\debug\nvfancontrol.exe -d -p
Found 1 available GPU(s)
GPU #0: GeForce RTX 2070 SUPER
 COOLER-0
PS C:\Users\Gordin\Documents\code\nvfancontrol> .\target\debug\nvfancontrol.exe -d -m
WARN - No config file found; using default curve
DEBUG - Default configuration loaded
DEBUG - [[gpu]]
id = 0
enabled = true
points = [[41, 20], [49, 30], [57, 45], [66, 55], [75, 63], [78, 72], [80, 80]]
INFO - NVIDIA driver version: 445.87
INFO - NVIDIA graphics adapter #0: GeForce RTX 2070 SUPER
INFO -   GPU #0 coolers: COOLER-0
INFO - Option "-m" is present; curve will have no actual effect
DEBUG - Temp: 30; Speed: [1240] RPM ([28]%); Load: 2%; Mode: Manual
DEBUG - Temp: 30; Speed: [1189] RPM ([28]%); Load: 2%; Mode: Manual
DEBUG - Temp: 30; Speed: [1005] RPM ([28]%); Load: 1%; Mode: Manual
DEBUG - Temp: 30; Speed: [1197] RPM ([28]%); Load: 1%; Mode: Manual
DEBUG - Temp: 30; Speed: [0] RPM ([28]%); Load: 1%; Mode: Manual
DEBUG - Temp: 30; Speed: [1288] RPM ([28]%); Load: 1%; Mode: Manual
DEBUG - Temp: 30; Speed: [0] RPM ([28]%); Load: 1%; Mode: Manual
DEBUG - Temp: 30; Speed: [1441] RPM ([28]%); Load: 1%; Mode: Manual
DEBUG - Temp: 30; Speed: [0] RPM ([28]%); Load: 2%; Mode: Manual
DEBUG - Temp: 30; Speed: [1486] RPM ([28]%); Load: 2%; Mode: Manual
DEBUG - Temp: 30; Speed: [0] RPM ([28]%); Load: 7%; Mode: Manual
DEBUG - Temp: 30; Speed: [1249] RPM ([28]%); Load: 3%; Mode: Manual
DEBUG - Temp: 30; Speed: [1032] RPM ([28]%); Load: 3%; Mode: Manual
DEBUG - Interrupt signal
DEBUG - Exiting
DEBUG - Resetting fan control
PS C:\Users\Gordin\Documents\code\nvfancontrol> .\target\debug\nvfancontrol.exe -d -f
DEBUG - Default configuration loaded
DEBUG - [[gpu]]
id = 0
enabled = true
points = [[41, 20], [49, 30], [57, 45], [66, 55], [75, 63], [78, 72], [80, 80]]
DEBUG - Curve points: [(41, 20), (49, 30), (57, 45), (66, 55), (75, 63), (78, 72), (80, 80)]
INFO - NVIDIA driver version: 445.87
INFO - NVIDIA graphics adapter #0: GeForce RTX 2070 SUPER
INFO -   GPU #0 coolers: COOLER-0
DEBUG - Temp: 30; Speed: [1381] RPM ([28]%); Load: 2%; Mode: Auto
DEBUG - Temp: 30; Speed: [1309] RPM ([28]%); Load: 1%; Mode: Auto
DEBUG - Temp: 30; Speed: [0] RPM ([28]%); Load: 1%; Mode: Auto
DEBUG - Temp: 30; Speed: [1215] RPM ([28]%); Load: 1%; Mode: Auto
DEBUG - Temp: 30; Speed: [1278] RPM ([28]%); Load: 1%; Mode: Auto
DEBUG - Temp: 30; Speed: [1283] RPM ([28]%); Load: 1%; Mode: Auto
DEBUG - Interrupt signal
DEBUG - Exiting
DEBUG - Resetting fan control
PS C:\Users\Gordin\Documents\code\nvfancontrol> .\target\debug\nvfancontrol.exe -d -f
WARN - No config file found; using default curve
DEBUG - Default configuration loaded
DEBUG - [[gpu]]
id = 0
enabled = true
points = [[41, 20], [49, 30], [57, 45], [66, 55], [75, 63], [78, 72], [80, 80]]
DEBUG - Curve points: [(41, 20), (49, 30), (57, 45), (66, 55), (75, 63), (78, 72), (80, 80)]
INFO - NVIDIA driver version: 445.87
INFO - NVIDIA graphics adapter #0: GeForce RTX 2070 SUPER
INFO -   GPU #0 coolers: COOLER-0
DEBUG - Temp: 30; Speed: [0] RPM ([0]%); Load: 2%; Mode: Auto
DEBUG - Temp: 30; Speed: [0] RPM ([0]%); Load: 1%; Mode: Auto
DEBUG - Temp: 30; Speed: [0] RPM ([0]%); Load: 1%; Mode: Auto
DEBUG - Temp: 30; Speed: [0] RPM ([0]%); Load: 1%; Mode: Auto
DEBUG - Temp: 30; Speed: [0] RPM ([0]%); Load: 2%; Mode: Auto
DEBUG - Temp: 30; Speed: [0] RPM ([0]%); Load: 1%; Mode: Auto
DEBUG - Temp: 30; Speed: [0] RPM ([0]%); Load: 1%; Mode: Auto
DEBUG - Temp: 30; Speed: [0] RPM ([0]%); Load: 1%; Mode: Auto
DEBUG - Interrupt signal
DEBUG - Exiting
DEBUG - Resetting fan control
PS C:\Users\Gordin\Documents\code\nvfancontrol> .\target\debug\nvfancontrol.exe -d -m
WARN - No config file found; using default curve
DEBUG - Default configuration loaded
DEBUG - [[gpu]]
id = 0
enabled = true
points = [[41, 20], [49, 30], [57, 45], [66, 55], [75, 63], [78, 72], [80, 80]]
DEBUG - Curve points: [(41, 20), (49, 30), (57, 45), (66, 55), (75, 63), (78, 72), (80, 80)]
INFO - NVIDIA driver version: 445.87
INFO - NVIDIA graphics adapter #0: GeForce RTX 2070 SUPER
INFO -   GPU #0 coolers: COOLER-0
INFO - Option "-m" is present; curve will have no actual effect
DEBUG - Temp: 31; Speed: [0] RPM ([0]%); Load: 4%; Mode: Auto
DEBUG - Temp: 31; Speed: [0] RPM ([0]%); Load: 1%; Mode: Auto
DEBUG - Temp: 31; Speed: [0] RPM ([0]%); Load: 1%; Mode: Auto
DEBUG - Temp: 31; Speed: [0] RPM ([0]%); Load: 1%; Mode: Auto
DEBUG - Temp: 31; Speed: [0] RPM ([0]%); Load: 2%; Mode: Auto
DEBUG - Temp: 31; Speed: [0] RPM ([0]%); Load: 2%; Mode: Auto
DEBUG - Interrupt signal
DEBUG - Exiting
DEBUG - Resetting fan control

I have access to a 970 and a 1070, but no second PC and I'd rather not swap around the cards all day unless you think you're close to having everything work ^^

The cards had no problem Afterburner though. I looked at the SetFanSpeed call in Afterburner in a x32dbg, and it looks like (in the Graph) the only thing they are checking to decide whether to use the new API or not is the result from ClientFanCoolers_IsSupported. For me it goes to the right to the ClientFanCoolers_SetControl part, while for other cards it will use GpuSetCoolerLevels. SetFanSpeed

You can probably search for all calls of *Supported to figure out what calls to make. I don't use debuggers much but it looks like it could be easy for someone with experience. All the calls to nvapi have wrappers that look very similiar. There seem to be 10 different calls with "Supported" (that Afterburner uses):

Address   Type    Ordinal  Symbol                                                                           Symbol (undecorated)                                                                                                                                                                                                                                                                         
008141C0  Export  498      ?ClientFanCoolers_IsSupported@CNVAPIWrapper@@QAEHXZ                              public: int __thiscall CNVAPIWrapper::ClientFanCoolers_IsSupported(void)
00813520  Export  1881     ?IsCoreClockControlSupported@CNVAPIWrapper@@QAEHXZ                               public: int __thiscall CNVAPIWrapper::IsCoreClockControlSupported(void)
00813760  Export  1937     ?IsFramerateLimitControlSupported@CNVAPIWrapper@@QAEHXZ                          public: int __thiscall CNVAPIWrapper::IsFramerateLimitControlSupported(void)
00813520  Export  2035     ?IsMemoryClockControlSupported@CNVAPIWrapper@@QAEHXZ                             public: int __thiscall CNVAPIWrapper::IsMemoryClockControlSupported(void)
00816AF0  Export  2072     ?IsPerfClocksTestSupported@CNVAPIWrapper@@QAEHXZ                                 public: int __thiscall CNVAPIWrapper::IsPerfClocksTestSupported(void)
00813720  Export  2082     ?IsPerfPolicySupported@CNVAPIWrapper@@QAEHK@Z                                    public: int __thiscall CNVAPIWrapper::IsPerfPolicySupported(unsigned long)
00816560  Export  2131     ?IsShaderClockControlSupported@CNVAPIWrapper@@QAEHK@Z                            public: int __thiscall CNVAPIWrapper::IsShaderClockControlSupported(unsigned long)
00814C70  Export  2354     ?PS20_IsRelVoltageSupported@CNVAPIWrapper@@QAEHXZ                                public: int __thiscall CNVAPIWrapper::PS20_IsRelVoltageSupported(void)
00813510  Export  2355     ?PS20_IsSupported@CNVAPIWrapper@@QAEHXZ                                          public: int __thiscall CNVAPIWrapper::PS20_IsSupported(void)
00813D80  Export  2868     ?VFCurve_IsSupported@CNVAPIWrapper@@QAEHXZ                                       public: int __thiscall CNVAPIWrapper::VFCurve_IsSupported(void)

Gordin avatar May 09 '20 17:05 Gordin

OK so it looks like it's working but could you please actually produce some load on the GPU so that the curve kicks in? That's the only way to check if the *Set command is actually working and if it's working as intended.

The IsSupported should check for the new API. Need to find out what's its signature.

As for the flicker bit: please check. I don't have this issue with my card (fan is always ON) so I can't test it. All the lower level bits are abstracted away so if the curve is applied I can't see any reason why it won't work.

foucault avatar May 09 '20 18:05 foucault

OK, I tested with load and Reading the Coolers works, but Setting does not. When I first tested it, it looked like nvfancontrol was competing with Afterburner in setting the fan speed to 0, so I assumed it was working. As soon as it tries to set a value I'm getting

ERROR - Could not update fan speed: NvAPI_GPU_SetCoolerLevels() failed; error -104

but that's expected I guess because my card wants the ClientFanCoolers_SetControl This is with -d -f

Gordin avatar May 09 '20 18:05 Gordin

Yes, obviously because I did not update set_fanspeed! Will post an updated binary soon.

foucault avatar May 09 '20 18:05 foucault

OK this one looks like it's working without crashing. Give it a shot :-)

nvfancontrol.zip

foucault avatar May 09 '20 22:05 foucault

It works now :) The anti fan flickering also works but I guess that doesn't have anything to do with the actual nvapi calls anyway. Although, (this is really just a not very important feature request...), it would be nice to be able to configure the steps it uses, I'm ramping up to 38% and then down to 25%, so right now it goes down by 1% each tick which takes 13 seconds but when I do it manually I can just go down to 32% and then to 25% with a second apart and it will still work. This is from -d -f -r 25,35

DEBUG - Temp: 38; Speed: [774] RPM ([25]%); Load: 36%; Mode: Manual
DEBUG - FanFlickerFix: preventing fan-off
DEBUG - FanFlickerFix [25, 35]: requested change from InRange(25) to InRange(25) (decrease), staying at 25%
DEBUG - Temp: 38; Speed: [776] RPM ([25]%); Load: 35%; Mode: Manual
DEBUG - FanFlickerFix: preventing fan-off
DEBUG - FanFlickerFix [25, 35]: requested change from InRange(25) to InRange(25) (decrease), staying at 25%
DEBUG - Temp: 36; Speed: [777] RPM ([25]%); Load: 4%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from InRange(25) to Below(23) (decrease), staying at 25%
DEBUG - Temp: 44; Speed: [775] RPM ([25]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from InRange(25) to InRange(25) (decrease), staying at 25%
DEBUG - Temp: 45; Speed: [776] RPM ([25]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from InRange(25) to InRange(26) (increase), setting 26%
DEBUG - Temp: 46; Speed: [774] RPM ([25]%); Load: 95%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from InRange(26) to InRange(27) (increase), setting 27%
DEBUG - Temp: 47; Speed: [803] RPM ([26]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from InRange(27) to InRange(28) (increase), setting 28%
DEBUG - Temp: 48; Speed: [838] RPM ([27]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from InRange(28) to InRange(28) (decrease), staying at 28%
DEBUG - Temp: 48; Speed: [871] RPM ([28]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from InRange(28) to InRange(30) (increase), setting 30%
DEBUG - Temp: 49; Speed: [872] RPM ([28]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from InRange(30) to InRange(31) (increase), setting 31%
DEBUG - Temp: 50; Speed: [923] RPM ([30]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from InRange(31) to InRange(31) (decrease), staying at 31%
DEBUG - Temp: 50; Speed: [960] RPM ([31]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from InRange(31) to InRange(33) (increase), setting 33%
DEBUG - Temp: 50; Speed: [966] RPM ([31]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from InRange(33) to InRange(33) (decrease), staying at 33%
DEBUG - Temp: 51; Speed: [1022] RPM ([33]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from InRange(33) to InRange(35) (increase), setting 35%
DEBUG - Temp: 51; Speed: [1026] RPM ([33]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from InRange(35) to InRange(35) (decrease), staying at 35%
DEBUG - Temp: 52; Speed: [1080] RPM ([35]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from InRange(35) to Above(37) (increase), setting 37%
DEBUG - Temp: 53; Speed: [1088] RPM ([35]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from Above(37) to Above(37) (decrease), staying at 37%
DEBUG - Temp: 53; Speed: [1147] RPM ([37]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from Above(37) to Above(37) (decrease), staying at 37%
DEBUG - Temp: 53; Speed: [1151] RPM ([37]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from Above(37) to Above(39) (increase), setting 39%
DEBUG - Temp: 54; Speed: [1147] RPM ([37]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from Above(39) to Above(39) (decrease), staying at 39%
DEBUG - Temp: 54; Speed: [1214] RPM ([39]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from Above(39) to Above(41) (increase), setting 41%
DEBUG - Temp: 55; Speed: [1214] RPM ([39]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from Above(41) to Above(41) (decrease), staying at 41%
DEBUG - Temp: 55; Speed: [1267] RPM ([41]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from Above(41) to Above(41) (decrease), staying at 41%
DEBUG - Temp: 55; Speed: [1274] RPM ([41]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from Above(41) to Above(43) (increase), setting 43%
DEBUG - Temp: 56; Speed: [1274] RPM ([41]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from Above(43) to Above(43) (decrease), staying at 43%
DEBUG - Temp: 56; Speed: [1334] RPM ([43]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from Above(43) to Above(43) (decrease), staying at 43%
DEBUG - Temp: 56; Speed: [1335] RPM ([43]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from Above(43) to Above(43) (decrease), staying at 43%
DEBUG - Temp: 56; Speed: [1336] RPM ([43]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from Above(43) to Above(43) (decrease), staying at 43%
DEBUG - Temp: 56; Speed: [1336] RPM ([43]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from Above(43) to Above(45) (increase), setting 45%
DEBUG - Temp: 57; Speed: [1333] RPM ([43]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from Above(45) to Above(45) (decrease), staying at 45%
DEBUG - Temp: 57; Speed: [1398] RPM ([45]%); Load: 98%; Mode: Manual
DEBUG - FanFlickerFix [25, 35]: requested change from Above(45) to Above(45) (decrease), staying at 45%

Gordin avatar May 09 '20 23:05 Gordin

That's good! We're getting closer. It's still unclear whether there is indeed a NVAPI call for the IsSupported function or Afterburner uses some logic to determine it. In any case if there is a function for that it's going to take a while to debug afterburner to find its magic code. Unfortunately everything in the NVAPI is hidden behind the nvapi_QueryInterface function which takes a magic number and returns a pointer to a function. For anything that's not on the public API you will have to go through debuggers and I'm not really familiar with them especially on Windows. In any case I'll try to provide a unified solution and then merge the changes so there might be another binary for you to test soon.

For fanflicker we should probably involve @tzh1043 as the original author of that code, but this is not relevant to this issue; open a new issue if you want to pursue it further.

foucault avatar May 10 '20 00:05 foucault

Hm, from what I've seen in the debugger I think it is an NVAPI call. All the NVAPI calls from afterburner have the same structure, and they all have the magic number value hardcoded in them. I'll see if I have time today to look at this again, I can probably find the magic value and at least the number of arguments.

Gordin avatar May 10 '20 14:05 Gordin

Nevermind, ClientFanCoolers_IsSupported is not n NVAPI call it's just (X + 0x1538) >> 6 & 1. Not sure what X is yet... Edit: (X + 0x1538) is obviously a pointer to something, I'm bad at this (:

Gordin avatar May 10 '20 19:05 Gordin