如何解决GCP VM 上的自定义分辨率在 Windows Server 2019 上使用 T4 GPU
我目前正在寻找一种方法来在 Windows Server 2019 虚拟机上使用 C++ 设置完全自定义的分辨率。
我尝试了不同的方法来实现这一点,我可以在我的笔记本电脑上完成这项工作,但似乎对 GCP VM 有一些限制(或 Windows 服务器限制)。
我已经尝试使用 ChangedisplaySettings/ChangedisplaySettingsEx (winuser.h) 来做到这一点,我可以更改为已知分辨率,但无法使用自定义分辨率(即使使用 CDS_ENABLE_UNSAFE_MODE 也不行)。
DWORD deviceIndex = 0;
disPLAY_DEVICE displayDevice = { 0 };
displayDevice.cb = sizeof(disPLAY_DEVICE);
while (EnumdisplayDevices(NULL,deviceIndex,&displayDevice,0)) {
deviceIndex++;
DEVMODE dm = { 0 };
dm.dmSize = sizeof(DEVMODE);
DEVMODE finalDm = { 0 };
finalDm.dmSize = sizeof(DEVMODE);
//Check if able to retrieve current settings
if (!EnumdisplaySettings(displayDevice.DeviceName,ENUM_CURRENT_SETTINGS,&dm)) {
continue;
}
//Check if there is a difference in resolution list if UNSAFE_MODE is enabled or not (it seems to not change anything)
int result = ChangedisplaySettingsEx(displayDevice.DeviceName,&dm,CDS_disABLE_UNSAFE_MODES,NULL);
std::cout << "CDS_disABLE_UNSAFE_MODE" << std::endl;
if (result == disP_CHANGE_SUCCESSFUL) {
for (int i = 0; EnumdisplaySettings(displayDevice.DeviceName,i,&dm) != 0; i++) {
if (dm.dmBitsPerPel == 32) {
std::cout << i << ". Found available resolution : " << dm.dmPelsWidth << " x " << dm.dmPelsHeight << " x " << dm.dmBitsPerPel << " @ " << dm.dmdisplayFrequency << std::endl;
}
}
}
result = ChangedisplaySettingsEx(displayDevice.DeviceName,CDS_ENABLE_UNSAFE_MODES,NULL);
std::cout << "CDS_ENABLE_UNSAFE_MODE" << std::endl;
if (result == disP_CHANGE_SUCCESSFUL) {
for (int i = 0; EnumdisplaySettings(displayDevice.DeviceName,&dm) != 0; i++) {
if (dm.dmBitsPerPel == 32) {
std::cout << i << ". Found available resolution : " << dm.dmPelsWidth << " x " << dm.dmPelsHeight << " x " << dm.dmBitsPerPel << " @ " << dm.dmdisplayFrequency << std::endl;
}
}
}
std::cout << "Please enter width : ";
int width,height;
std::cin >> width;
std::cout << "Please enter height : ";
std::cin >> height;
dm.dmPelsWidth = width;
dm.dmPelsHeight = height;
if (width > height) {
dm.dmdisplayOrientation = DMDO_DEFAULT;
}
else {
dm.dmdisplayOrientation = DMDO_90;
}
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_disPLAYORIENTATION;
//result = ChangedisplaySettingsEx(displayDevice.DeviceName,NULL,CDS_TEST,NULL);
result = ChangedisplaySettingsEx(displayDevice.DeviceName,NULL);
if (result != disP_CHANGE_SUCCESSFUL) {
std::cout << "Impossible to ChangedisplaySettings" << endl;
}
else {
std::cout << "OK" << endl;
}
break;
}
然后我看了一下 nvapi,这里也是一样,我可以让它在我的 PC 上运行,但在 GCP 虚拟机上仍然没有......我找到了一种方法来让 nvapi 在我的本地 PC 上创建和使用自定义分辨率,但无法再次在 GCP VM 上运行...(代码示例找到 here)
nvapi_Status result = nvapi_ERROR;
NvU32 primarydisplayId = 0;
//Testing resolution
int horizontal = 1920,vertical = 1090;
result = nvapi_Initialize();
if (result != nvapi_OK) {
printf("Could not initialize nvapi");
return false;
}
MONITORINFOEX monInfo;
HMONITOR hMon;
const POINT ptZero = { 0,0 };
// determine the location of the primary monitor
hMon = MonitorFromPoint(ptZero,MONITOR_DEFAULTTOPRIMARY);
ZeroMemory(&monInfo,sizeof(monInfo));
monInfo.cbSize = sizeof(monInfo);
GetMonitorInfo(hMon,&monInfo);
result = nvapi_disP_GetGDIPrimarydisplayId(&primarydisplayId);
if (result != nvapi_OK) {
printf("Could not get display ID from device");
nvapi_Unload();
return false;
}
NvU32 deviceCount = 0;
NV_CUSTOM_disPLAY cd[nvapi_MAX_disPLAYS] = { 0 };
float refreshRate = 60;
// timing computation (to get timing that suits the changes made)
NV_TIMING_FLAG flag = { 0 };
NV_TIMING_INPUT timing = { 0 };
timing.version = NV_TIMING_INPUT_VER;
timing.height = vertical;
timing.width = horizontal;
timing.rr = refreshRate;
timing.flag = flag;
timing.type = NV_TIMING_OVERRIDE_CVT_RB;
result = nvapi_disP_GetTiming(primarydisplayId,&timing,&cd[0].timing);
if (result != nvapi_OK) {
printf("Failed to get timing for display"); // Failed to get custom display timing
nvapi_Unload();
return false;
}
cd[0].width = horizontal;
cd[0].height = vertical;
cd[0].xRatio = 1;
cd[0].yRatio = 1;
cd[0].srcPartition = { 0,1.0,1.0 };
cd[0].depth = 32;
cd[0].version = NV_CUSTOM_disPLAY_VER;
cd[0].colorFormat = NV_FORMAT_A8R8G8B8;
//Returns nvapi_ERROR on GCP but nvapi_OK on my laptop
result = nvapi_disP_TryCustomdisplay(&primarydisplayId,1,cd);
if (result != nvapi_OK) {
printf("Could not set custom resolution");
nvapi_disP_RevertCustomdisplayTrial(&primarydisplayId,1);
nvapi_Unload();
return false;
}
else {
nvapi_disP_SaveCustomdisplay(&primarydisplayId,true,true);
}
这部分在我的笔记本电脑上运行得很好,我可以使用新的动态分辨率(它适用于 1920x400、1920x500、1920x600),但不能在我的 GCP VM 上使用,这部分:
nvapi_disP_TryCustomdisplay(&primarydisplayId,cd);
总是返回 nvapi_ERROR
我发现了另一个技巧,我可以编辑这个注册表项:HKEY_LOCAL_MACHINE\SYstem\CurrentControlSet\Control\Video{RANDOM_ID}\0001\NV_Modes (这是一个old pdf,经过一些测试,它似乎仍然以这种方式工作) 如果我使用 nvapi 添加一些分辨率,然后我可以通过 ChangedisplaySettingsEx 函数设置此分辨率(它需要重新启动 GPU 驱动程序,或者重新启动 Windows 才能更改为新添加的分辨率)。 但是我需要能够旋转屏幕,玩“dmdisplayOrientation”,而且它似乎不能再次在 GCP VM 上工作,如果我授权例如 1920x1090,我可以将分辨率设置为此,但不能使用“dmdisplayOrientation”设置 1090x1920 = DMDO_90"(即使我也授权了 1090x1920...)
所以如果有人找到了方法,或者对如何做到这一点有任何想法,那就太好了,我现在没有想法了......
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。