Forcing hardware accelerated rendering

前端 未结 5 786
迷失自我
迷失自我 2021-01-08 00:58

I have an OpenGL library written in c++ that is used from a C# application using C++/CLI adapters. My problem is that if the application is used on laptops with Nvidia Optim

5条回答
  •  说谎
    说谎 (楼主)
    2021-01-08 01:27

    My solution working both on NVidia and AMD, without DllExport (without NuGet package UnmanagedExports), based on exported functions NvOptimusEnablement and AmdPowerXpressRequestHighPerformance:

    On VS2019 the aforementioned UnmanagedExports package doesn't seem to work properly. I couldn't find another working package for .NET framework that provides DllExport capability. That's why I developed my own solution using direct MSIL code with great help from Writing IL code on Visual Studio and IL Support.

    Steps to follow:

    1. Choose x86 or x64 platform for your exe (you cannot do it with AnyCPU setting)
    2. To .csproj file (.csproj for exe, not for any dll) add the following section which enables direct usage of MSIL code (you may put it generally anywhere, i.e. after ). For .net frameworks newer than 4.6.2 you may need to update paths to ildasm.exe:

      
        
          HideILFromCoreCompile;
          $(CoreCompileDependsOn);
        
        
          HideILFromCompile;
          $(CompileDependsOn);
          InitializeIL;
          CoreDecompile;
          CoreCompileIL;
        
      
      
        
          
        
      
      
        
          
          
        
      
      
        
          @(IntermediateAssembly->'%(RootDir)%(Directory)%(Filename).il', ' ')
          @(IntermediateAssembly->'%(RootDir)%(Directory)%(Filename).res', ' ')
        
      
      
        
          
        
        
          "$(FrameworkSdkPath)bin\ildasm.exe" /nobar /linenum /output:"$(ILFile)" @(IntermediateAssembly->'"%(FullPath)"', ' ')
        
        
          "$(FrameworkSdkPath)bin\NETFX 4.0 Tools\ildasm.exe" /nobar /linenum /output:"$(ILFile)" @(IntermediateAssembly->'"%(FullPath)"', ' ')
        
        
          "$(FrameworkSdkPath)bin\NETFX 4.5.1 Tools\ildasm.exe" /nobar /linenum /output:"$(ILFile)" @(IntermediateAssembly->'"%(FullPath)"', ' ')
        
        
          "$(FrameworkSdkPath)bin\NETFX 4.6 Tools\ildasm.exe" /nobar /linenum /output:"$(ILFile)" @(IntermediateAssembly->'"%(FullPath)"', ' ')
        
        
          "$(FrameworkSdkPath)bin\NETFX 4.6.1 Tools\ildasm.exe" /nobar /linenum /output:"$(ILFile)" @(IntermediateAssembly->'"%(FullPath)"', ' ')
        
        
          "$(FrameworkSdkPath)bin\NETFX 4.6.2 Tools\ildasm.exe" /nobar /linenum /output:"$(ILFile)" @(IntermediateAssembly->'"%(FullPath)"', ' ')
        
        
        
          
          
        
        
          $([System.IO.File]::ReadAllText($(ILFile)))
          // method ${method} forwardref removed for IL import
          \.method [^{}]+ cil managed forwardref[^}]+} // end of method (?<method>[^ \r\t\n]+)
          $([System.Text.RegularExpressions.Regex]::Replace($(ILSource), $(Pattern), $(Replacement)))
          \.method [^{}]+ cil managed[^\a]+"extern was not given a DllImport attribute"[^}]+} // end of method (?<method>[^ \r\t\n]+)
          $([System.Text.RegularExpressions.Regex]::Replace($(ILSource), $(Pattern), $(Replacement)))
        
        
        
          
        
        
      
      
        
          
        
        
          "$(FrameworkPath)\ilasm.exe" /nologo /quiet /output:@(IntermediateAssembly->'"%(FullPath)"', ' ')
        
        
          $(ILAsm) /alignment=$(FileAlignment)
        
        
          $(ILAsm) /base=$(BaseAddress)
        
        
          $(ILAsm) /dll
        
        
          $(ILAsm) /pdb
        
        
          $(ILAsm) /debug
        
        
          $(ILAsm) /optimize
        
        
          $(ILAsm) /pe64 /x64
        
        
          $(ILAsm) /pe64 /itanium
        
        
          $(ILAsm) /key:"$(AssemblyOriginatorKeyFile)"
        
        
          $(ILAsm) /resource:"$(ILResourceFile)"
        
        
          $(ILAsm) "$(ILFile)"
        
        
        
          
        
        
      
      
    3. Add a file with .il extension to your project (e.g. ForceDedicatedGraphicCard.il)
    4. Paste the code below to this file (instead of 'WindowsApplication1' you may enter your namespace):

       .class public WindowsApplication1.ForceDedicatedGraphicCard
       {
           .method public static int32 NvOptimusEnablement() cil managed
           {
               .export [1]
               ldc.i4.1
               ret
           }
           .method public static uint32 AmdPowerXpressRequestHighPerformance() cil managed
           {
               .export [2]
               ldc.i4.1
               ret
           }
       }
      
    5. Build project
    6. Check if the functions are exported using dumpbin.exe

      dumpbin.exe /exports your_project.exe
      
    7. Now the dedicated graphic card should be chosen automatically. If not, check if you have an updated driver - old drivers don't support these exported functions.

提交回复
热议问题