2016-04-30 76 views
29

好吧我一直在研究这个问题几天,所以让我回过头来看看到目前为止这导致我相信这可能是NVidia的驱动程序的问题,而不是我的代码。Nvidia显卡驱动引起明显的帧结局

基本上,我的游戏在运行几秒后开始口吃(随机帧需要70ms而不是16ms,在规则模式下)。如果在Nvidia控制面板(最新的驱动程序,Windows 10)中启用了名为“Threaded Optimization”的设置,则只会发生这种情况。不幸的是,此设置默认启用,我宁愿不必让人们调整设置以获得愉快的体验。

  • 游戏不是CPU或GPU密集型(2ms没有vsync的帧)。它不会调用任何需要同步数据的openGL函数,也不会传输任何缓冲区或从GPU读取任何数据。关于最简单的渲染器。

  • 问题始终存在,它只是在fmod中添加音频时才开始显着。 fmod不是这个的原因(更多后面的帖子)

  • 试图用NVidia调试问题Nsight使问题消失。 “开始收集数据”立即导致口吃消失。这里没有骰子。

  • 在Profiler中,很多cpu时间都花在“nvoglv32.dll”上。如果“线程优化”处于打开状态,此过程只会生成。我怀疑这是一个同步问题,所以我使用visual studio Concurrency Viewer进行调试。

  • A-HA! vsyncs

  • 调查的CPU时间,这些块NVIDIA的线程上,最早命名的功能,我可以在他们的调用堆栈得到的是“CreateToolhelp32Snapshot”后面很多的时间花在Thread32Next。我在早期查看CPU时间时发现了Profiler中的Thread32Next,因此这看起来好像我在正确的轨道上。

  • 因此,看起来像nvidia驱动程序定期抓取整个过程的快照出于某种原因?可能是什么原因,为什么它这样做,我该如何阻止它?

  • 此外,这也解释了为什么一旦我添加到fmod中后,问题就开始变得明显起来,因为它为所有进程线程获取信息,而fmod产生大量线程。

  • 任何帮助?这只是nvidia驱动程序中的一个错误,或者有什么我可以做的,以解决它,告诉人们禁用Threaded“优化”?

编辑1:同样的问题也出现在我的笔记本电脑上的当前nvidia驱动程序。所以,我没疯

编辑2:发生同样的问题上NVIDIA的驱动程序

+0

嘿,泰勒。 :)出于好奇 - 你有一些调试驱动程序安装或什么?我不能为我的生活猜想为什么图形驱动程序需要获取这种信息,除非它是出于某种调试/记录原因。 –

+0

nope。他们是来自nvidia网站的公开驱动程序。我甚至不知道我在哪里得到一个调试模式驱动程序... – TylerGlaiel

+0

也我应该提到我也尝试过在没有Visual Studio的情况下运行,以防万一Visual Studio注入了一些调试代码...相同问题 – TylerGlaiel

回答

0

恨不言自明的362版本(以前的主要版本),但我觉得它需要说。

线程化优化在许多游戏中引起口吃是众所周知的,即使那些利用多线程技术的游戏也是如此。除非您的应用程序与线程优化设置一起运行良好,否则唯一合乎逻辑的答案是告诉用户禁用它。如果用户固执而不想这样做,那是他们的错。

在最近的记忆,我能想到的唯一错误是旧版本的NVIDIA驱动程序的应用程序引起的W的葡萄酒运行死机/线程的优化,但是这无关你所描述的口吃问题。

+0

在这一点上,如果它不是Nvidia想要解决的问题(我确定了导致口吃的Windows功能,我认为),我只是要切换到directx,看起来问题不大。 – TylerGlaiel

+0

“这是他们的错”?!不,如果你的申请不起作用,那是你的错。 – Calvin1602

6

...或者是有什么 我能做些什么来解决它的其他人告诉禁用螺纹 “优化”?

是的。

您可以使用NVAPI为您的游戏创建自定义“应用程序配置文件”,并禁用其中的“线程优化”设置。

在NVIDIA网站上有一个.PDF file,有关于NVAPI使用的一些帮助和代码示例。

为了查看和管理您的所有NVIDIA配置文件,我推荐使用NVIDIA Inspector。它比默认的NVIDIA控制面板更方便。

而且,这里是它创建“应用程序配置文件”和“螺纹优化”禁用我的代码示例:

#include <stdlib.h> 
#include <stdio.h> 

#include <nvapi.h> 
#include <NvApiDriverSettings.h> 


const wchar_t* profileName    = L"Your Profile Name"; 
const wchar_t* appName     = L"YourGame.exe"; 
const wchar_t* appFriendlyName   = L"Your Game Casual Name"; 
const bool  threadedOptimization = false; 


void CheckError(NvAPI_Status status) 
{ 
    if (status == NVAPI_OK) 
     return; 

    NvAPI_ShortString szDesc = {0}; 
    NvAPI_GetErrorMessage(status, szDesc); 
    printf("NVAPI error: %s\n", szDesc); 
    exit(-1); 
} 


void SetNVUstring(NvAPI_UnicodeString& nvStr, const wchar_t* wcStr) 
{ 
    for (int i = 0; i < NVAPI_UNICODE_STRING_MAX; i++) 
     nvStr[i] = 0; 

    int i = 0; 
    while (wcStr[i] != 0) 
    { 
     nvStr[i] = wcStr[i]; 
     i++; 
    } 
} 


int main(int argc, char* argv[]) 
{ 
    NvAPI_Status status; 
    NvDRSSessionHandle hSession; 

    status = NvAPI_Initialize(); 
    CheckError(status); 

    status = NvAPI_DRS_CreateSession(&hSession); 
    CheckError(status); 

    status = NvAPI_DRS_LoadSettings(hSession); 
    CheckError(status); 


    // Fill Profile Info 
    NVDRS_PROFILE profileInfo; 
    profileInfo.version    = NVDRS_PROFILE_VER; 
    profileInfo.isPredefined  = 0; 
    SetNVUstring(profileInfo.profileName, profileName); 

    // Create Profile 
    NvDRSProfileHandle hProfile; 
    status = NvAPI_DRS_CreateProfile(hSession, &profileInfo, &hProfile); 
    CheckError(status); 


    // Fill Application Info 
    NVDRS_APPLICATION app; 
    app.version      = NVDRS_APPLICATION_VER_V1; 
    app.isPredefined    = 0; 
    SetNVUstring(app.appName, appName); 
    SetNVUstring(app.userFriendlyName, appFriendlyName); 
    SetNVUstring(app.launcher, L""); 
    SetNVUstring(app.fileInFolder, L""); 

    // Create Application 
    status = NvAPI_DRS_CreateApplication(hSession, hProfile, &app); 
    CheckError(status); 


    // Fill Setting Info 
    NVDRS_SETTING setting; 
    setting.version     = NVDRS_SETTING_VER; 
    setting.settingId    = OGL_THREAD_CONTROL_ID; 
    setting.settingType    = NVDRS_DWORD_TYPE; 
    setting.settingLocation   = NVDRS_CURRENT_PROFILE_LOCATION; 
    setting.isCurrentPredefined  = 0; 
    setting.isPredefinedValid  = 0; 
    setting.u32CurrentValue   = threadedOptimization ? OGL_THREAD_CONTROL_ENABLE : OGL_THREAD_CONTROL_DISABLE; 
    setting.u32PredefinedValue  = threadedOptimization ? OGL_THREAD_CONTROL_ENABLE : OGL_THREAD_CONTROL_DISABLE; 

    // Set Setting 
    status = NvAPI_DRS_SetSetting(hSession, hProfile, &setting); 
    CheckError(status); 


    // Apply (or save) our changes to the system 
    status = NvAPI_DRS_SaveSettings(hSession); 
    CheckError(status); 


    printf("Success.\n"); 

    NvAPI_DRS_DestroySession(hSession); 

    return 0; 
} 
+0

感谢代码,如果nvidia在我的游戏完成时没有修复它,可能最终不得不使用它 – TylerGlaiel

+0

请注意,配置文件在应用程序启动时(从其名称开始)由驱动程序加载,因此您需要重新启动它以使您的自定义配置文件生效。在安装程序中这样做可能是最好的。 – Calvin1602

1

感谢subGlitch的回答首先,根据该提案,我只是做一个更安全的一个,这将使您能够缓存和更改线程优化,然后进行恢复。

代码是象下面这样:

#include <stdlib.h> 
#include <stdio.h> 
#include <nvapi.h> 
#include <NvApiDriverSettings.h> 

enum NvThreadOptimization { 
    NV_THREAD_OPTIMIZATION_AUTO   = 0, 
    NV_THREAD_OPTIMIZATION_ENABLE  = 1, 
    NV_THREAD_OPTIMIZATION_DISABLE  = 2, 
    NV_THREAD_OPTIMIZATION_NO_SUPPORT = 3 
}; 

bool NvAPI_OK_Verify(NvAPI_Status status) 
{ 
    if (status == NVAPI_OK) 
     return true; 

    NvAPI_ShortString szDesc = {0}; 
    NvAPI_GetErrorMessage(status, szDesc); 

    char szResult[255]; 
    sprintf(szResult, "NVAPI error: %s\n\0", szDesc); 
    printf(szResult); 

    return false; 
} 

NvThreadOptimization GetNVidiaThreadOptimization() 
{ 
    NvAPI_Status status; 
    NvDRSSessionHandle hSession; 
    NvThreadOptimization threadOptimization = NV_THREAD_OPTIMIZATION_NO_SUPPORT; 

    status = NvAPI_Initialize(); 
    if(!NvAPI_OK_Verify(status)) 
     return threadOptimization; 

    status = NvAPI_DRS_CreateSession(&hSession); 
    if(!NvAPI_OK_Verify(status)) 
     return threadOptimization; 

    status = NvAPI_DRS_LoadSettings(hSession); 
    if(!NvAPI_OK_Verify(status)) 
    { 
     NvAPI_DRS_DestroySession(hSession); 
     return threadOptimization;; 
    } 


    NvDRSProfileHandle hProfile; 
    status = NvAPI_DRS_GetBaseProfile(hSession, &hProfile); 
    if(!NvAPI_OK_Verify(status)) 
    { 
     NvAPI_DRS_DestroySession(hSession); 
     return threadOptimization;; 
    } 

    NVDRS_SETTING originalSetting; 
    originalSetting.version = NVDRS_SETTING_VER; 
    status = NvAPI_DRS_GetSetting(hSession, hProfile, OGL_THREAD_CONTROL_ID, &originalSetting); 
    if(NvAPI_OK_Verify(status)) 
    { 
     threadOptimization = (NvThreadOptimization)originalSetting.u32CurrentValue; 
    } 

    NvAPI_DRS_DestroySession(hSession); 

    return threadOptimization; 
} 

void SetNVidiaThreadOptimization(NvThreadOptimization threadedOptimization) 
{ 
    NvAPI_Status status; 
    NvDRSSessionHandle hSession; 

    if(threadedOptimization == NV_THREAD_OPTIMIZATION_NO_SUPPORT) 
     return; 

    status = NvAPI_Initialize(); 
    if(!NvAPI_OK_Verify(status)) 
     return; 

    status = NvAPI_DRS_CreateSession(&hSession); 
    if(!NvAPI_OK_Verify(status)) 
     return; 

    status = NvAPI_DRS_LoadSettings(hSession); 
    if(!NvAPI_OK_Verify(status)) 
    { 
     NvAPI_DRS_DestroySession(hSession); 
     return; 
    } 

    NvDRSProfileHandle hProfile; 
    status = NvAPI_DRS_GetBaseProfile(hSession, &hProfile); 
    if(!NvAPI_OK_Verify(status)) 
    { 
     NvAPI_DRS_DestroySession(hSession); 
     return; 
    } 

    NVDRS_SETTING setting; 
    setting.version     = NVDRS_SETTING_VER; 
    setting.settingId    = OGL_THREAD_CONTROL_ID; 
    setting.settingType    = NVDRS_DWORD_TYPE; 
    setting.u32CurrentValue   = (EValues_OGL_THREAD_CONTROL)threadedOptimization; 

    status = NvAPI_DRS_SetSetting(hSession, hProfile, &setting); 
    if(!NvAPI_OK_Verify(status)) 
    { 
     NvAPI_DRS_DestroySession(hSession); 
     return; 
    } 

    status = NvAPI_DRS_SaveSettings(hSession); 
    NvAPI_OK_Verify(status); 

    NvAPI_DRS_DestroySession(hSession); 
} 

基于两个接口以上(获取/套),你很可能保存原来的设置,并恢复它,当你的应用程序退出。这意味着您禁用线程优化的设置仅影响您自己的应用程序。

static NvThreadOptimization s_OriginalNVidiaThreadOptimization = NV_THREAD_OPTIMIZATION_NO_SUPPORT; 

// Set 
s_OriginalNVidiaThreadOptimization = GetNVidiaThreadOptimization(); 
if( s_OriginalNVidiaThreadOptimization != NV_THREAD_OPTIMIZATION_NO_SUPPORT 
    && s_OriginalNVidiaThreadOptimization != NV_THREAD_OPTIMIZATION_DISABLE) 
{ 
    SetNVidiaThreadOptimization(NV_THREAD_OPTIMIZATION_DISABLE); 
} 

//Restore 
if( s_OriginalNVidiaThreadOptimization != NV_THREAD_OPTIMIZATION_NO_SUPPORT 
    && s_OriginalNVidiaThreadOptimization != NV_THREAD_OPTIMIZATION_DISABLE) 
{ 
    SetNVidiaThreadOptimization(s_OriginalNVidiaThreadOptimization); 
}; 
相关问题