34 votes

Pilote graphique Nvidia causant ainsi des cadre bégaiement

Ok j'ai fait des recherches sur ce problème depuis quelques jours maintenant, permettez-moi de passer plus de ce que je sais jusqu'à présent qui m'amène à croire que cela peut être un problème avec NVidia pilote et pas de mon code.

Fondamentalement, mon jeu commence à bégayer après l'exécution de quelques secondes (images aléatoires prendre 70ms au lieu de 16ms, sur un regularish modèle). Cela se produit UNIQUEMENT si un paramètre appelé "Fileté Optimisation" est activé dans le panneau de configuration Nvidia (pilotes les plus récents, windows 10). Malheureusement, ce paramètre est activé par défaut et je préfère ne pas avoir d'avoir les gens à modifier leurs paramètres pour obtenir une expérience agréable.

  • Le jeu n'est pas CPU ou GPU intensif (2ms un cadre sans vsync sur). Ce n'est pas tout appel de fonctions openGL qui en ont besoin pour synchroniser les données, et il n'est pas en streaming les tampons ou de la lecture des données de la carte graphique ou quoi que ce soit. Le plus simple possible moteur de rendu.

  • Le problème était toujours là, il a juste commencé à devenir perceptible quand je l'ai ajouté dans fmod pour le son. fmod n'est pas la cause de cette (plus tard dans le post)

  • Essayez de déboguer le problème avec NVidia Nsight fait le problème. "Commencer à Recueillir des Données" instantanément provoque des interruptions de s'en aller. Pas de dés ici.

  • Dans le générateur de profils, beaucoup de temps cpu est passé en "nvoglv32.dll". Ce procédé ne génère si Fileté Optimisation est sur. Je soupçonne que c'est un problème de synchronisation, donc je debug avec visual studio Simultanéité de la Visionneuse.

  • A-HA! vsyncs

  • Enquête sur ces blocs de temps CPU sur la carte nvidia fil, la première fonction nommée je peux obtenir dans leur pile des appels est "CreateToolhelp32Snapshot" suivie par un grand nombre de temps passé dans Thread32Next. J'ai remarqué Thread32Next dans le profiler quand on regarde les temps de calcul plus tôt si cela ne semble pas comme je suis sur la bonne voie.

  • De sorte qu'il ressemble périodiquement le pilote nvidia est d'attraper un aperçu de l'ensemble du processus pour une raison quelconque? Ce que pourrait être la raison, pourquoi est-il en train de faire cela, et comment puis-je l'arrêter?

  • Aussi ce qui explique pourquoi le problème a commencé à devenir perceptible une fois j'ai ajouté dans fmod, parce que son accaparement des info pour tous les processus fils, et fmod engendre beaucoup de discussions.

  • Toute aide? Est-ce juste un bug dans la nvidia pilote ou est-il quelque chose que je peux faire pour le réparer d'autres de dire aux gens de désactiver Fileté "Optimisation"?

edit 1: Le même problème se produit avec les actuels pilotes nvidia sur mon pc portable. Donc, je ne suis pas fou

edit 2: le même problème se produit sur la version 362 (version précédente) de nvidia pilote

8voto

subGlitch Points 96

... ou est-il quelque chose Je peux faire d'autres de dire aux gens de désactiver Filetée "L'optimisation"?

Oui.

Vous pouvez créer des "Profil d'Application" pour votre jeu à l'aide de NVAPI et désactiver "Fileté Optimisation" de réglage à l'.

Il y a un .Fichier PDF sur le site NVIDIA avec de l'aide et des exemples de code concernant NVAPI d'utilisation.

Afin de voir et de gérer tous vos NVIDIA profils je recommande l'utilisation de NVIDIA Inspector. Il est plus pratique que la valeur par défaut du Panneau de configuration NVIDIA.

Aussi, voici mon exemple de code qui crée "Profil d'Application" avec "Fileté Optimisation" désactivé:

#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;
}

1voto

Alex Points 11

Merci pour subGlitch réponse du premier, fondé sur cette proposition, je viens de le rendre plus sécuritaire, ce qui vous permettrait de cache et de changer le fil de l'optimisation, de la restaurer par la suite.

Le Code est comme ci-dessous:

#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);
}

Basé sur les deux interfaces (Get/Set) ci-dessus, vous pouvez enregistrer le réglage d'origine et de les restaurer lorsque votre application se ferme. Cela signifie que votre paramètre pour désactiver le fil de l'optimisation, seulement un impact sur votre propre application.

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);
};

1voto

user6277017 Points 9

De la haine à l'évidence, mais je pense que ça doit être dit.

Fileté optimisation est connu pour causer des interruptions dans de nombreux jeux, même ceux qui prennent le parti du multithreading. À moins que votre application fonctionne bien avec la partie filetée du paramètre d'optimisation, la seule réponse logique est de dire à vos utilisateurs pour le désactiver. Si les utilisateurs sont têtus et ne veulent pas le faire, c'est de leur faute.

Le seul bug dans la mémoire récente, je pense que les anciennes versions du pilote nvidia causé des applications w/ fileté optimisation de l'exécution dans le Vin de crash, mais qui n'a aucun rapport avec le bégaiement problème que vous décrivez.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X