【小沐学C++】获取OpenGL版本号、双显卡切换技术代码实现(Optimus、NVAPI、CUDA)

58 篇文章 34 订阅
订阅专栏
16 篇文章 4 订阅
订阅专栏

在这里插入图片描述

“宠辱不惊,看庭前花开花落;去留无意,望天上云卷云舒。”

一、OpenGL支持库

OpenGL依赖各平台提供用于渲染的context以及具体实现方式,而各平台提供的实现不尽相同。这些实现主要有:Windows平台下的WGL、Linux下的Mesa/GLX、Mac OS X下的Cocoa/NSGL,以及跨平台的GLUT、GLFW、SDL等等。

OpenGL函数库相关的API有核心库(gl),实用库(glu),辅助库(aux)、实用工具库(glut),窗口库(glx、agl、wgl)和扩展函数库等。

gl是核心,glu是对gl的部分封装。glx、agl、wgl 是针对不同窗口系统的函数。glut是为跨平台的OpenGL程序的工具包,比aux功能强大(aux很大程度上已经被glut库取代。)。扩展函数库是硬件厂商为实现硬件更新利用OpenGL的扩展机制开发的函数。

OpenGL的竞争对手是Direct3D;OpenGL对应的开源实现是mesa 3D。

在这里插入图片描述

1、GLUT

官网地址: https://www.opengl.org/resources/libraries/glut/glut_downloads.php
在这里插入图片描述

GLUT是OpenGL工具库 OpenGL Utility Toolkit的缩写。
2000-03-22后,该库不再更新(最终版本3.7)。

GLUT (pronounced like the glut in gluttony) is the OpenGL Utility Toolkit, a window system independent toolkit for writing OpenGL programs. It implements a simple windowing application programming interface (API) for OpenGL. GLUT makes it considerably easier to learn about and explore OpenGL programming. GLUT provides a portable API so you can write a single OpenGL program that works on both Win32 PCs and X11 workstations.

2、freeglut

官网地址: http://freeglut.sourceforge.net/

GLUT或者FREEGLUT主要是1.0的基本函数功能;
2019-11-29后,该库不再更新(最终版本3.2.1)。

freeglut is a free-software/open-source alternative to the OpenGL Utility Toolkit (GLUT) library. GLUT was originally written by Mark Kilgard to support the sample programs in the second edition OpenGL ‘RedBook’. Since then, GLUT has been used in a wide variety of practical applications because it is simple, widely available and highly portable.
在这里插入图片描述

3、GLEW

官网地址: http://glew.sourceforge.net/

GLEW是使用OPENGL2.0之后的一个工具函数。
2017-7-31后,该库不再更新(最终版本2.1.0)。

The OpenGL Extension Wrangler Library (GLEW) is a cross-platform open-source C/C++ extension loading library. GLEW provides efficient run-time mechanisms for determining which OpenGL extensions are supported on the target platform. OpenGL core and extension functionality is exposed in a single header file. GLEW has been tested on a variety of operating systems, including Windows, Linux, Mac OS X, FreeBSD, Irix, and Solaris.
在这里插入图片描述

4、GLAD

官网地址:
https://glad.dav1d.de/
https://github.com/Dav1dde/glad

GLAD是继GL3W,GLEW之后,当前最新的用来访问OpenGL规范接口的第三方库。官方网址为https://glad.dav1d.de/。

该库仍然在更新,加油!!!
在这里插入图片描述

5、GLFW

官网地址: https://www.glfw.org/

GLFW是一个轻量级的,开源的,跨平台的library。支持OpenGL及OpenGL ES,用来管理窗口,读取输入,处理事件等。

该库仍然在更新,加油!!!

GLFW is an Open Source, multi-platform library for OpenGL, OpenGL ES and Vulkan development on the desktop. It provides a simple API for creating windows, contexts and surfaces, receiving input and events.

GLFW is written in C and supports Windows, macOS, X11 and Wayland.
GLFW is licensed under the zlib/libpng license.
在这里插入图片描述

6、Mesa

官网地址: https://mesa3d.org/

The Mesa 3D Graphics Library: Open source implementations of OpenGL, OpenGL ES, Vulkan, OpenCL, and more!

Mesa is primarily developed and used on Linux systems. But there’s also support for Windows, other flavors of Unix and other systems such as Haiku. We’re actively developing and maintaining several hardware and software drivers.

The primary API is OpenGL but there’s also support for OpenGL ES, Vulkan, EGL, OpenMAX, OpenCL, VDPAU, VA-API and XvMC.

Mesa3D provides an OpenGL implementation, just like NVidia’s, AMD’s, or Intel’s drivers provide an OpenGL implementation. They are all OpenGL implementations.

Mesa是Linux下的OpenGL实现。它提供了对AMD Radeon系列、Nvidia GPU、Intel i965, i945, i915以及VMWare虚拟GPU等多种硬件驱动的支持,同时也提供了对softpipe等多种软件驱动的支持。Mesa项目由Brian Paul于1993年8月创建,于1995年2月发布了第一个发行版,此后便受到越来越多的关注,如今Mesa已经是任何一个Linux版本首选的OpenGL实现。

GLX则是在Linux上用于提供GL与窗口交互、窗口管理等等的一组API。它的作用与Windows的WGL、Mac OS X的AGL以及针对OpenGL ES的EGL相似。在Linux上,窗口创建、管理等API遵循X Window接口,而GLX提供了OpenGL与X Window交互的办法。因此GLX也可以运用于其他使用X Window的平台,例如FreeBSD等。
在这里插入图片描述

二、获取OpenGL版本号实现代码

1、glut+glew

#include "GL\glew.h"
#include "GL\glut.h"
#include <Windows.h>
#pragma comment(lib, "glew32.lib")
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")

int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	int wnd = glutCreateWindow("GLUT");

	glewInit();
	printf("OpenGL vendor string: %s\n", glGetString(GL_VENDOR));
	printf("OpenGL renderer string: %s\n", glGetString(GL_RENDERER));
	printf("OpenGL version string: %s\n", glGetString(GL_VERSION));

	glutDestroyWindow(wnd);
	return 0;
}

2、win32+glew

#include "GL\glew.h"
#include <Windows.h>

#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "glew32.lib")

typedef struct GLContextStruct
{
	HWND wnd;
	HDC dc;
	HGLRC rc;
} GLContext;

void InitContext(GLContext* ctx);
GLboolean CreateContext(GLContext* ctx);
void DestroyContext(GLContext* ctx);
void PrintExtensions(const char* s);

int main(int argc, char **argv)
{
	GLenum err;
	GLContext ctx;

	/* ---------------------------------------------------------------------- */
  /* create OpenGL rendering context */
	InitContext(&ctx);
	if (GL_TRUE == CreateContext(&ctx))
	{
		fprintf(stderr, "Error: CreateContext failed\n");
		DestroyContext(&ctx);
		return 1;
	}

	/* ---------------------------------------------------------------------- */
 /* initialize GLEW */
	glewExperimental = GL_TRUE;
	err = glewInit();
	if (GLEW_OK != err)
	{
		fprintf(stderr, "Error [main]: glewInit failed: %s\n", glewGetErrorString(err));
		DestroyContext(&ctx);
		return 1;
	}

	/* ---------------------------------------------------------------------- */
  /* output header information */
  /* OpenGL extensions */
	printf("OpenGL vendor string: %s\n", glGetString(GL_VENDOR));
	printf("OpenGL renderer string: %s\n", glGetString(GL_RENDERER));
	printf("OpenGL version string: %s\n", glGetString(GL_VERSION));
	printf("OpenGL extensions (GL_): \n");
	PrintExtensions((const char*)glGetString(GL_EXTENSIONS));

	/* GLU extensions */
	printf("GLU version string: %s\n", gluGetString(GLU_VERSION));
	printf("GLU extensions (GLU_): \n");
	PrintExtensions((const char*)gluGetString(GLU_EXTENSIONS));

	DestroyContext(&ctx);
	return 0;
}


void InitContext(GLContext* ctx)
{
	ctx->wnd = NULL;
	ctx->dc = NULL;
	ctx->rc = NULL;
}

GLboolean CreateContext(GLContext* ctx)
{
	WNDCLASS wc;
	PIXELFORMATDESCRIPTOR pfd;
	/* check for input */
	if (NULL == ctx) return GL_TRUE;
	/* register window class */
	ZeroMemory(&wc, sizeof(WNDCLASS));
	wc.hInstance = GetModuleHandle(NULL);
	wc.lpfnWndProc = DefWindowProc;
	wc.lpszClassName = "GLTEST";
	if (0 == RegisterClass(&wc)) return GL_TRUE;

	/* create window */
	ctx->wnd = CreateWindow("GLTEST", "GLTEST", 0, CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,
		GetModuleHandle(NULL), NULL);
	if (NULL == ctx->wnd) return GL_TRUE;
	/* get the device context */
	ctx->dc = GetDC(ctx->wnd);
	if (NULL == ctx->dc) return GL_TRUE;
	/* find pixel format */
	ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
	pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
	pfd.nVersion = 1;
	pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
	int visual = ChoosePixelFormat(ctx->dc, &pfd);
	if (0 == visual) return GL_TRUE;

	/* set the pixel format for the dc */
	if (FALSE == SetPixelFormat(ctx->dc, visual, &pfd)) return GL_TRUE;
	/* create rendering context */
	ctx->rc = wglCreateContext(ctx->dc);
	if (NULL == ctx->rc) return GL_TRUE;
	if (FALSE == wglMakeCurrent(ctx->dc, ctx->rc)) return GL_TRUE;
	return GL_FALSE;
}

void DestroyContext(GLContext* ctx)
{
	if (NULL == ctx) return;
	if (NULL != ctx->rc) wglMakeCurrent(NULL, NULL);
	if (NULL != ctx->rc) wglDeleteContext(wglGetCurrentContext());
	if (NULL != ctx->wnd && NULL != ctx->dc) ReleaseDC(ctx->wnd, ctx->dc);
	if (NULL != ctx->wnd) DestroyWindow(ctx->wnd);
	UnregisterClass("GLEW", GetModuleHandle(NULL));
}

/* do the magic to separate all extensions with comma's, except
   for the last one that _may_ terminate in a space. */
void PrintExtensions(const char* s)
{
	char t[80];
	int i = 0;
	char* p = 0;

	t[79] = '\0';
	while (*s)
	{
		t[i++] = *s;
		if (*s == ' ')
		{
			if (*(s + 1) != '\0') {
				t[i - 1] = ',';
				t[i] = ' ';
				p = &t[i++];
			}
			else /* zoinks! last one terminated in a space! */
			{
				t[i - 1] = '\0';
			}
		}
		if (i > 80 - 5)
		{
			*p = t[i] = '\0';
			printf("    %s\n", t);
			p++;
			i = (int)strlen(p);
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
			strcpy_s(t, sizeof(t), p);
#else
			strcpy(t, p);
#endif
		}
		s++;
	}
	t[i] = '\0';
	printf("    %s.\n", t);
}

3、glfw+glad

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "glfw3.lib")

int main(int argc, char **argv)
{
	const unsigned int SCR_WIDTH = 800;
	const unsigned int SCR_HEIGHT = 600;

	glfwInit();
	//glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	//glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "GLFW", NULL, NULL);
	if (window == NULL)
	{
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);

	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cout << "Failed to initialize GLAD" << std::endl;
		return -1;
	}
	printf("OpenGL vendor string: %s\n", glGetString(GL_VENDOR));
	printf("OpenGL renderer string: %s\n", glGetString(GL_RENDERER));
	printf("OpenGL version string: %s\n", glGetString(GL_VERSION));
	
	glfwTerminate();
	return 0;
}

4、Android

opengles 1.1: info.reqGlEsVersion= 0x00010001
opengles 2.0: info.reqGlEsVersion= 0x00020000

public class MainActivity extends AppCompatActivity {

    private AppBarConfiguration appBarConfiguration;
    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        setSupportActionBar(binding.toolbar);

        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
        appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);

        binding.fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        // 获取设备的OpenGL ES的版本号
        ActivityManager am =(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        ConfigurationInfo info = am.getDeviceConfigurationInfo();
        String hex = Integer.toHexString (info.reqGlEsVersion);
        System.out.println("OpenGL ES版本:" + hex + "(" + info.reqGlEsVersion+")");

    }

5、WebGL

https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API
WebGL(Web图形库)是一个JavaScript API,可在任何兼容的Web浏览器中渲染高性能的交互式3D和2D图形,而无需使用插件。WebGL通过引入一个与OpenGL ES 2.0非常一致的API来做到这一点,该API可以在HTML5 元素中使用。 这种一致性使API可以利用用户设备提供的硬件图形加速。

目前支持 WebGL 的浏览器有:Firefox 4+, Google Chrome 9+, Opera 12+, Safari 5.1+, Internet Explorer 11+和Microsoft Edge build 10240+;然而, WebGL一些特性也需要用户的硬件设备支持。

WebGL 2 API引入了对大部分的OpenGL ES 3.0功能集的支持; 它是通过WebGL2RenderingContext界面提供的。

webgl_test1.html文件内容如下:

<!DOCTYPE html>
<html>
<head>
    <meta lang="en">
    <meta charset="UTF-8">
    <title>WebGL Test</title>
    <link href="style/style.css">
    <script type="text/javascript" src="webgl_test1.js"></script>
</head>
<body>
<canvas id="canvas" width="200px" height="200px"></canvas>
</body>
</html>

webgl_test1.js文件内容如下:

/**
 * Created by Tomcat on 2022-01-05
 */
window.onload = function () {

    //获取canvas元素
    var canvas = document.getElementById('canvas');
    
	//获取绘制二维上下文
    var gl = canvas.getContext('webgl');
    if (!gl) {
        console.log("Failed");
        return;
    }
   
	//打印OpenGL信息
	const gl1 = canvas.getContext("webgl");
	if (!gl1) { console.log("WebGL1不支持!"); }
	
	const gl2 = canvas.getContext("webgl2");
	if (!gl2) { console.log("WebGL2不支持!"); }
	
	var info1 = gl.getParameter(gl.VERSION);
	if (info1) { console.log(info1); }
	
	var info2 = gl.getParameter(gl.SHADING_LANGUAGE_VERSION);
	if (info2) { console.log(info2); }
	
}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>

<head>
  <title>3D Simulation</title>
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    #mycanvas,
    #viewContainer,
    body,
    html {
      width: 100%;
      height: 100%
    }

    body,
    html {
      border: 0;
      padding: 0;
      margin: 0;
      position: fixed
    }
</style>
</head>

<body>
    <div id="viewContainer">
        <canvas id="mycanvas" width="1920" height="1080">Loading...</canvas>
    </div>

    <script type="text/javascript">
    var gl;
    var c = null;

    function sleep(milliseconds) {
      var start = new Date().getTime();
      for (var i = 0; i < 1e7; i++) {
        if ((new Date().getTime() - start) > milliseconds) {
          break;
        }
      }
    }

    function initGL() {
      if (!window.WebGLRenderingContext) {
        alert("Your browser does not accept WebGL content");
        window.location = "http://get.webgl.org";
      } else {
        try {
          c = document.getElementById("mycanvas");
          // c = = document.querySelector("#mycanvas");
          gl = c.getContext("webgl");
          if (!gl) {
            gl = c.getContext("experimental-webgl");
          }
          if (!gl) {
            alert("Could not initialise WebGL");
            //alert("无法初始化WebGL,你的浏览器、操作系统或硬件等可能不支持WebGL。");
          }
        } catch (e) {
          alert("Could not initialise WebGL: " + e);
        }
      }
    }

    window.onload = function () {
      webGLStart();
    }
    function webGLStart() {
        initGL();

        // 使用完全不透明的黑色清除所有图像
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        // 用上面指定的颜色清除缓冲区
        gl.clear(gl.COLOR_BUFFER_BIT);
    }
    </script>

</body>
</html>

三、NVIDIA® Optimus™ 技术(双显卡切换技术)

1、Optimus技术简介

官网地址:
https://www.nvidia.cn/technologies/optimus/

NVIDIA Optimus 是NVIDIA 公司最新开发的双显卡,基于双显卡的智能切换技术,能够根据系统的负载自动切换独立显卡和集成显卡的运行。Optimus技术可完全自动地发挥作用,无需手动更改设置值,用户即可体验更长的电池续航时间以及惊人的视觉效果。

Optimus能够在后台运行,对用户运行的程序没有任何干扰,可无缝地计算出最大限度优化笔记本计算体验的方式。

Optimus(优驰)技术能对笔记本电脑进行智能优化,从而可在您需要时提供卓越的图形性能,同时还可延长电池续航时间,让您享受更长的欢乐时光。

Windows XP/Vista并不支持NVIDIA Optimus。也不能禁用集显。
在这里插入图片描述
在这里插入图片描述

2、Optimus编程指南

官网相关资料地址:
https://docs.nvidia.com/gameworks/content/technologies/desktop/optimus.htm
https://developer.download.nvidia.cn/devzone/devcenter/gamegraphics/files/OptimusRenderingPolicies.pdf

(NVIDIA Optimus Programming Guide)Enabling NVIDIA High Performance Graphics Rendering on Optimus Systems。This feature is enabled using the following set of methods, listed in order from highest to lowest precedence:

  1. Forced Rendering Mode
  2. Right-Click Context Menu
  3. Application Profile Settings
  4. Static Library Bindings
  5. Global Variable NvOptimusEnablement (new in Driver Release 302)
  6. Global Profile Settings

总结:本文档描述了应用程序可用于启用和公开 NVIDIA 高性能图形处理器以在 Optimus 配置中进行渲染的6种方法。

3、Application Profile Settings(上文第3种方法,NVAPI)

上文第3种方法,通过程序集成nvapi库的功能进行设置,达到程序运行在独立高性能显卡上的效果。

NVAPI官网地址: https://developer.nvidia.com/nvapi
在这里插入图片描述
在这里插入图片描述
NVAPI是NVIDIA®(英伟达™)的核心软件开发工具包,允许直接访问所有Windows平台上NVIDIA GPU(图形处理器)和驱动程序。NVAPI对那些超出人们所熟悉的DirectX和OpenGL图形API的操作类别提供支持。最初只开放给原始设备制造商和游戏开发工具,现在所有对在NVIDIA GPU上构建Windows应用程序感兴趣的开发人员都可以下载NVAPI。

官方nVidia API具有所需的NvAPI_DRS_ *函数。

这里有一个工作流: NvAPI_Initialize (如果失败,则表示用户没有nVidia GPU,这不是错误), NvAPI_DRS_CreateSession , NvAPI_DRS_LoadSettings , NvAPI_DRS_FindProfileByName 。

如果没有找到, NvAPI_DRS_CreateProfile和三个调用NvAPI_DRS_SetSetting ,设置三个DWORD属性:

  • SHIM_MCCOMPAT_ID = SHIM_MCCOMPAT_ENABLE
  • SHIM_RENDERING_MODE_ID = SHIM_RENDERING_MODE_ENABLE
  • SHIM_RENDERING_OPTIONS_ID = SHIM_RENDERING_OPTIONS_DEFAULT_RENDERING_MODE

然后,调用NvAPI_DRS_GetProfileInfo获取应用程序的数量,然后调用NvAPI_DRS_GetProfileInfo ,然后搜索EXE路径。

卸载时,通过调用NvAPI_DRS_FindProfileByName ,然后调用NvAPI_DRS_FindProfileByName删除完整的配置文件。

最后,调用NvAPI_DRS_SaveSettings 。

//NVAPI R470, 2021/07/13
//VC++2017
//Create by tomcat on 2022-01-09
#include "nvapi/nvapi.h"
#include "nvapi/NvApiDriverSettings.h"
int addExeToNvidiaGpu()
{
	//
	wchar_t szProfileName[256] = { 0 };
	wchar_t szAppName[256] = { 0 };
	GetModuleFileNameW(NULL, szAppName, 256);
	wchar_t* pFileName = wcsrchr(szAppName, '\\');
	if (pFileName) pFileName++;
	if (pFileName) wcscpy(szProfileName, pFileName);

	//
	NvAPI_Status status = NVAPI_OK;
	status = NvAPI_Initialize();
	if (status != NVAPI_OK)
	{
		return -1;
	}
	NvDRSSessionHandle hSession = 0;
	status = NvAPI_DRS_CreateSession(&hSession);
	if (status != NVAPI_OK)
	{
		return -2;
	}
	status = NvAPI_DRS_LoadSettings(hSession);
	if (status != NVAPI_OK)
	{
		return -3;
	}

	NvDRSProfileHandle hProfile = 0;
	NvAPI_UnicodeString profile_name = {0};
	memcpy_s(profile_name, sizeof(profile_name), szProfileName, wcslen(szProfileName) * sizeof(wchar_t));
	status = NvAPI_DRS_FindProfileByName(hSession, profile_name, &hProfile);
	if (status == NVAPI_OK) {
		status = NvAPI_DRS_DeleteProfile(hSession, hProfile);
		if (status != NVAPI_OK)
		{
			return -10;
		}
		status = NvAPI_DRS_SaveSettings(hSession);
		if (status != NVAPI_OK)
		{
			return -11;
		}
		status = NvAPI_DRS_LoadSettings(hSession);
		if (status != NVAPI_OK)
		{
			return -12;
		}
	}
	
	NVDRS_PROFILE drsProfile = { 0 };
	drsProfile.version = NVDRS_PROFILE_VER;
	drsProfile.isPredefined = 0;
	memcpy_s(drsProfile.profileName, sizeof(drsProfile.profileName), szProfileName, wcslen(szProfileName) * sizeof(wchar_t));
	status = NvAPI_DRS_CreateProfile(hSession, &drsProfile, &hProfile);
	if (status != NVAPI_OK)
	{
		return -13;
	}

	NVDRS_APPLICATION app;
	memset(&app, 0, sizeof(NVDRS_APPLICATION));
	app.version = NVDRS_APPLICATION_VER;
	app.isPredefined = 0;
	memcpy_s(app.appName, sizeof(app.appName), szAppName, 256 * sizeof(wchar_t));
	memcpy_s(app.userFriendlyName, sizeof(app.appName), szAppName, 256 * sizeof(wchar_t));
	status = NvAPI_DRS_CreateApplication(hSession, hProfile, &app);
	if (status != NVAPI_OK)
	{
		return -14;
	}

	NVDRS_SETTING drsSetting = { 0 };
	drsSetting.version = NVDRS_SETTING_VER;
	drsSetting = NVDRS_SETTING();
	drsSetting.version = NVDRS_SETTING_VER;
	drsSetting.settingId = SHIM_MCCOMPAT_ID;
	drsSetting.settingType = NVDRS_DWORD_TYPE;
	drsSetting.u32CurrentValue = SHIM_MCCOMPAT_ENABLE;
	status = NvAPI_DRS_SetSetting(hSession, hProfile, &drsSetting);
	if (status != NVAPI_OK)
	{
		return -15;
	}

	drsSetting = NVDRS_SETTING();
	drsSetting.version = NVDRS_SETTING_VER;
	drsSetting.settingId = SHIM_RENDERING_MODE_ID;
	drsSetting.settingType = NVDRS_DWORD_TYPE;
	drsSetting.u32CurrentValue = SHIM_RENDERING_MODE_ENABLE;
	status = NvAPI_DRS_SetSetting(hSession, hProfile, &drsSetting);
	if (status != NVAPI_OK)
	{
		return -16;
	}

	drsSetting = NVDRS_SETTING();
	drsSetting.version = NVDRS_SETTING_VER;
	drsSetting.settingId = SHIM_RENDERING_OPTIONS_ID;
	drsSetting.settingType = NVDRS_DWORD_TYPE;
	drsSetting.u32CurrentValue = SHIM_RENDERING_OPTIONS_DEFAULT_RENDERING_MODE;
	status = NvAPI_DRS_SetSetting(hSession, hProfile, &drsSetting);
	if (status != NVAPI_OK)
	{
		return -17;
	}
	status = NvAPI_DRS_SaveSettings(hSession);
	if (status != NVAPI_OK)
	{
		return -18;
	}
	status = NvAPI_DRS_DestroySession(hSession);
	if (status != NVAPI_OK)
	{
		return -19;
	}
	hSession = 0;
	NvAPI_Unload();
	return 0;
}

4、Static Library Bindings(上文第4种方法,CUDA)

上文第4种方法,通过程序静态链接一些第三方库,达到程序运行在独立高性能显卡上的效果。

https://developer.download.nvidia.cn/compute/cuda/docs/CUDA_Developer_Guide_for_Optimus_Platforms.pdf

As of Release 302, the current list of libraries are vcamp110.dll, vcamp110d.dll, nvapi.dll, nvapi64.dll, opencl.dll, nvcuda.dll, and cudart*.*.

如果你的笔记本有两块显卡,一块是Intel的集成显卡(IGP),一块是Nvidia的独立GPU,你的笔记本一般采用了Optimus技术。在使用CUDA的时候,务必要理解Optimus,才能很好的使用你的笔记本来开发CUDA程序。

在这里插入图片描述
另外关于cuda开发包的安装介绍如下:
https://developer.nvidia.com/cuda-toolkit-archive
在这里插入图片描述
在这里插入图片描述

CUDA开发包和NVIDIA显卡驱动的版本对应关系如下:
https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html
在这里插入图片描述
cuda开发包安装完毕之后,在命令行输入:

nvcc -V

在这里插入图片描述
在NVIDIA控制面板查看你的电脑显卡能支持的cuda最大版本,如下图所示:
在这里插入图片描述
在这里插入图片描述

5、Global Variable NvOptimusEnablement(上文第5种方法)

上文第5种方法,通过定义导出变量NvOptimusEnablement ,控制程序运行在独立高性能显卡上。

Global Variable NvOptimusEnablement (new in Driver Release 302):
Starting with the Release 302 drivers, application developers can direct the Optimus
driver at runtime to use the High Performance Graphics to render any application–even
those applications for which there is no existing application profile. They can do this by
exporting a global variable named NvOptimusEnablement. The Optimus driver looks for
the existence and value of the export. Only the LSB of the DWORD matters at this time. A value of 0x00000001 indicates that rendering should be performed using High
Performance Graphics. A value of 0x00000000 indicates that this method should be
ignored.

对于Intel + NVIDIA双GPU“Optimus”设置,应用程序NvOptimusEnablement可以按照OptimusRenderingPolicies.pdf中的说明进行导出。

在NV开发者网站上,有个关于Optimus的新文档,里面提到了在R302以上的驱动里,引入了一个启动NV卡的新方法。通过从exe中导出一个名为NvOptimusEnablement的全局变量,它为1的时候驱动就能切换到NV的显卡。通过这种方式,终于可以在程序中控制使用哪块显卡,并且没有性能下降问题。

为了使OpenGL能在移动平台上采用独显渲染,需要添加以下代码(主程序exe添加):

// http://developer.download.nvidia.com/devzone/devcenter/gamegraphics/files/OptimusRenderingPolicies.pdf
// The following line is to favor the high performance NVIDIA GPU if there are multiple GPUs
// Has to be .exe module to be correctly detected.
// N卡使用独显运行
extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;

// And the AMD equivalent
// Also has to be .exe module to be correctly detected.
// A显卡使用独显运行
extern "C" __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 0x00000001;

6、设置垂直同步

N卡默认开启垂直同步,如果要让FPS突破显示器刷新率,需要禁用垂直同步,首先需要引入GLEW。

#include <GL/wglew.h>
...
//禁用垂直同步
wglSwapIntervalEXT(0);

//启用垂直同步
wglSwapIntervalEXT(1);

四、显卡驱动厂商

1、NVIDIA

NVIDIA 驱动程序下载:
https://www.nvidia.cn/Download/index.aspx?lang=cn
https://www.nvidia.cn/geforce/drivers/
在这里插入图片描述

2、AMD

AMD 驱动程序与支持:
https://www.amd.com/zh-hans/support
在这里插入图片描述

3、Intel

https://www.intel.cn/content/www/cn/zh/support/products/80939/graphics.html#support-product-selector
在这里插入图片描述
在这里插入图片描述

五、显卡检测工具

1、GPU Caps Viewer

https://www.geeks3d.com/dl/show/657
GPU Caps Viewer is a graphics card / GPU information and monitoring utility that quickly describes the essential capabilities of your GPU including GPU type, amount of VRAM , OpenGL, Vulkan, OpenCL and CUDA API support level. It also comes with OpenGL and Vulkan real time 3D demos.
在这里插入图片描述
在这里插入图片描述

2、OpenGL Extensions Viewer

https://realtech-vr.com/home/glview
在这里插入图片描述
经过一番分析:
(1)这个程序运行环境依赖.net 4.6.1
(2)使用了Amazon Web Services for .Net
(3)使用了WPF
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、dxdiag(系统自带)

(1)打开“运行”窗口。
(2)输入"dxdiag",进入 DirectX诊断工具,即列出显卡信息。
在这里插入图片描述

4、nvidia-smi(NVidia驱动)

The NVIDIA System Management Interface (nvidia-smi) is a command line utility, based on top of the NVIDIA Management Library (NVML), intended to aid in the management and monitoring of NVIDIA GPU devices.

nvidia-smi
nvidia-smi -l 3
nvidia-smi --query-gpu=gpu_name,gpu_bus_id,vbios_version --format=csv
nvidia-smi --query-gpu=timestamp,memory.total,memory.free,memory.used,name,utilization.gpu,utilization.memory --format=csv -l 5

https://developer.nvidia.com/nvidia-system-management-interface

http://developer.download.nvidia.com/compute/cuda/6_0/rel/gdk/nvidia-smi.331.38.pdf

http://nvidia.custhelp.com/app/answers/detail/a_id/3751/~/useful-nvidia-smi-queries

Monitoring the framebuffer for NVIDIA GRID vGPU and GPU-passthrough

http://nvidia.custhelp.com/app/answers/detail/a_id/4108/~/monitoring-the-framebuffer-for-nvidia-grid-vgpu-and-gpu-passthrough

在这里插入图片描述

六、其他FAQ

6.1 nvidiaopenglrdp.exe

RDP远程桌面的OPENGL实在是太老了,必须下载英伟达它们提供的一个程序来驱动OpenGL:
nvidiaopenglrdp.exe。nvidia发布的 让windows的rdp远程桌面环境也可以使用 GrForce GPU来做终端桌面的OpenGL 加速补丁。windows远程桌面连接支持的问题,由于远程桌面仅提供通用的GDI+,可以运行OpenGL 1.1,但对高版本的程序需要安装客户端驱动支持。

来时无迹去无踪,去与来时事一同。何须更问浮生事,只此浮生在梦中。

结语

如果您觉得该方法或代码有一点点用处,可以给作者点个赞,或打赏杯咖啡;╮( ̄▽ ̄)╭
如果您感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进;o_O???
如果您需要相关功能的代码定制化开发,可以留言私信作者;(✿◡‿◡)
感谢各位大佬童鞋们的支持!( ´ ▽´ )ノ ( ´ ▽´)っ!!!



在这里插入图片描述

C++获取OpenGL版本号的两种方法
草上爬的博客
06-02 1万+
C++获取OpenGL版本号的两种方法
nvapi for delphi or lazarus
08-29
nvdia显卡api nvapi 函数库 delphi 和 lazarus版本
R410-NVAPI显卡开发包.rar
01-11
R410-NVAPI显卡开发包 #include"nvapi_lite_salstart.h" #include"nvapi_lite_common.h" #include"nvapi_lite_sli.h" #include"nvapi_lite_surround.h" #include"nvapi_lite_stereo.h" #include"nvapi_lite_d3dext.h"
使用C++ checksum进行差错检测【100011679】
04-06
使用checksum进行差错检测,类似于udp的差错检测方式,使用回卷加法,之后将加和进行反码运算,放在数据的最开头,并且回卷加法使用8比特加法。
c++获取OpengL版本号的两种方法
06-02
源码,没啥说的
C++ windows 检测网络是否断开
03-22
检测当前的网络是否断开
C++检测键盘某键是否按下的方法
08-27
今天小编就为大家分享一篇C++检测键盘某键是否按下的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
检查OpenGL的版本
liji_digital的博客
09-18 2655
本文介绍如何在Qt框架下获取OpenGL的版本
Ubuntu20.04 配置OpenGL开发环境(并验证)
weixin_46457532的博客
07-25 5223
这一步可以查看我们手上的“树莓派”搭载的乌班图系统的显卡版本,并且它对OpenGL的支持信息。上面OpenGL version string: 3.1 Mesa 21.2.6可以看出OpenGL的版本为3.1。
OpenGL 代码1
最新发布
zczyyds的博客
10-12 43
代码OpenGL 代码1。
使用C++ 与ONNXRuntime部署yolov8旋转目标检测源码+模型(c++).zip
09-01
使用C++ 与ONNXRuntime部署yolov8旋转目标检测源码+模型(c++).zip
8.如何检测文件是否已经发生更改?(Visual C++编程 源代码
06-26
8.如何检测文件是否已经发生更改?(Visual C++编程 源代码)8.如何检测文件是否已经发生更改?(Visual C++编程 源代码)8.如何检测文件是否已经发生更改?(Visual C++编程 源代码)8.如何检测文件是否已经发生更改?(Visual C++编程 源代码)8.如何检测文件是否已经发生更改?(Visual C++编程 源代码)8.如何检测文件是否已经发生更改?(Visual C++编程 源代码)8.如何检测文件是否已经发生更改?(Visual C++编程 源代码)8.如何检测文件是否已经发生更改?(Visual C++编程 源代码)8.如何检测文件是否已经发生更改?(Visual C++编程 源代码)8.如何检测文件是否已经发生更改?(Visual C++编程 源代码)8.如何检测文件是否已经发生更改?(Visual C++编程 源代码)8.如何检测文件是否已经发生更改?(Visual C++编程 源代码)8.如何检测文件是否已经发生更改?(Visual C++编程 源代码)8.如何检测文件是否已经发生更改?(Visual C++编程 源代码)8.如何检测文件是否
NVAPI_R410-developer
11-22
NVAPI_R410-developer 2018年10月版本的NVAPI,可以对所有NVIDIA的GPU进行控制并实时获得GPU状态和运行情况。
NvAPI实现屏幕扩展和分辨率设置
11-23
NvAPI实现屏幕扩展和分辨率设置。扩展显示器用的是NVAPI R337 库需要自行从英伟达官网下。设置分辨率用的是Windows一系列的函数
OpenGL入门学习(十四) 【转】
shiqx429的专栏
09-08 939
 OpenGL从推出到现在,已经有相当长的一段时间了。其间,OpenGL不断的得到更新。到今天为止,正式的OpenGL已经有九个版本。(1.0, 1.1, 1.2, 1.2.1, 1.3, 1.4, 1.5, 2.0, 2.1)每个OpenGL版本的推出,都增加了一些当时流行的或者迫切需要的新功能。同时,到现在为止,OpenGL是向下兼容的,就是说如果某个功能在一个低版本中存在,则在更高版本中也一
OpenGL显卡编程
******************************************
03-15 1804
http://www.gameres.com/Articles/Program/Visual/3D/openglhw.htm文档目录:  OpenGL扩展  显卡差异  顶点/片断编程  Cg/RenderMonkey/及其他文档内容:  OpenGL扩展(OpenGL Extensions)  OpenGL和Direct3D比较起来,最大的一个长处就是其扩展机制。硬件厂商开发出一
Windows C++获取显卡支持的OpenGL最高版本
qiuzen的博客
10-02 992
Windows C++获取显卡支持的OpenGL最高版本
Windows-OpenGL版本检测
weixin_41111116的博客
10-27 1243
Windows-OpenGL版本检测
opengl获取窗口大小
06-08
你可以使用OpenGL的函数来获取窗口的大小。具体来说,可以使用glutGet()函数来获取当前窗口的宽度和高度。示例代码如下: ``` int width = glutGet(GLUT_WINDOW_WIDTH); int height = glutGet(GLUT_WINDOW_HEIGHT); ``` 请注意,此代码需要在OpenGL的初始化和渲染循环之后调用才能正确获取窗口大小。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

热门文章

  • ASCII码对照表【2023年汇总】 280884
  • ASCII码对照表(Unicode 字符集列表) 49127
  • 【小沐学C#】C#逆向反编译工具:JetBrains dotPeek 40477
  • ASCII码对照表(HTML颜色代码表) 31960
  • ASCII码对照表(emoji表情符号) 28160

分类专栏

  • Python 98篇
  • C/C++ 58篇
  • Web 62篇
  • AI 31篇
  • GIS 23篇
  • Android 15篇
  • ANSYS 8篇
  • ASCII 7篇
  • Unity3d 12篇
  • Qt 9篇
  • VC++ / MFC / WTL 5篇
  • C#.NET 10篇
  • 写作 12篇
  • Linux 15篇
  • Database 6篇
  • AR/VR 5篇
  • CAD 12篇
  • OpenGL 16篇
  • PHP 4篇
  • 夏虫语冰 9篇
  • 围炉夜话 4篇
  • 二十四节气 24篇

最新评论

  • 【小沐学GIS】基于Python绘制三维数字地球Earth(OpenGL)

    爱看书的小沐: 文章末尾处有qq联系方式

  • 【小沐学GIS】基于Python绘制三维数字地球Earth(OpenGL)

    2301_80387595: 博主您好 看了用Python画的动态地球感觉很震撼 想要一下源代码 学习一下 请问在哪能看到呢表情包表情包

  • 【小沐学GIS】基于C++绘制三维数字地球Earth(OpenGL、glfw、glut)第一期

    爱看书的小沐: 请私信表情包

  • 【小沐学GIS】基于C++绘制三维数字地球Earth(OpenGL、glfw、glut)第一期

    成都唯一周杰伦: 大佬,可以分享一下源码吗?不胜感激表情包

  • 【小沐学GIS】基于Python绘制三维数字地球Earth(OpenGL)

    爱看书的小沐: 表情包已私信回复您了表情包

您愿意向朋友推荐“博客详情页”吗?

  • 强烈不推荐
  • 不推荐
  • 一般般
  • 推荐
  • 强烈推荐
提交

最新文章

  • 【小沐学Java】VSCode搭建Java开发环境
  • 【小沐学QT】QT学习之路径问题汇总
  • 【小沐学Python】Python实现Web图表功能(Lux)
2024年25篇
2023年94篇
2022年99篇
2021年51篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

聚圣源男诗经女楚辞宝宝起名宝典仇恨之链泰剧繁峙房屋出租耿耿于怀是什么意思啊起公司名字的吉利字风水投机取巧的意思姓黄霸气男孩起名大全叠被子www.3rat.com艾弗森经典过人飞天蜈蚣明朝服饰八字缺土的起名念起来很萌的情侣名拉面炎字女孩起名混沌劫姓潘的少女起名字赵起名三个字男孩网上投资理财幼犬起名大全闹闹女巫店一周运势心酸的句子四川卤菜sqlitedev开店起哪些名巨蟹座男和什么座最配店起名天气之子百度云灵魂摆渡1淀粉肠小王子日销售额涨超10倍罗斯否认插足凯特王妃婚姻让美丽中国“从细节出发”清明节放假3天调休1天男孩疑遭霸凌 家长讨说法被踢出群国产伟哥去年销售近13亿网友建议重庆地铁不准乘客携带菜筐雅江山火三名扑火人员牺牲系谣言代拍被何赛飞拿着魔杖追着打月嫂回应掌掴婴儿是在赶虫子山西高速一大巴发生事故 已致13死高中生被打伤下体休学 邯郸通报李梦为奥运任务婉拒WNBA邀请19岁小伙救下5人后溺亡 多方发声王树国3次鞠躬告别西交大师生单亲妈妈陷入热恋 14岁儿子报警315晚会后胖东来又人满为患了倪萍分享减重40斤方法王楚钦登顶三项第一今日春分两大学生合买彩票中奖一人不认账张家界的山上“长”满了韩国人?周杰伦一审败诉网易房客欠租失踪 房东直发愁男子持台球杆殴打2名女店员被抓男子被猫抓伤后确诊“猫抓病”“重生之我在北大当嫡校长”槽头肉企业被曝光前生意红火男孩8年未见母亲被告知被遗忘恒大被罚41.75亿到底怎么缴网友洛杉矶偶遇贾玲杨倩无缘巴黎奥运张立群任西安交通大学校长黑马情侣提车了西双版纳热带植物园回应蜉蝣大爆发妈妈回应孩子在校撞护栏坠楼考生莫言也上北大硕士复试名单了韩国首次吊销离岗医生执照奥巴马现身唐宁街 黑色着装引猜测沈阳一轿车冲入人行道致3死2伤阿根廷将发行1万与2万面值的纸币外国人感慨凌晨的中国很安全男子被流浪猫绊倒 投喂者赔24万手机成瘾是影响睡眠质量重要因素春分“立蛋”成功率更高?胖东来员工每周单休无小长假“开封王婆”爆火:促成四五十对专家建议不必谈骨泥色变浙江一高校内汽车冲撞行人 多人受伤许家印被限制高消费

聚圣源 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化