【发布时间】:2014-07-22 21:26:27
【问题描述】:
我正在编写一个用于 C# 应用程序的 C++ dll。 该dll会检查总GPU内存和GPU内存的使用情况。
现在我已经创建了三个方法。第一个确实初始化了 GLew 和其他 OpeGl 的东西。第二个将读取 GPU 的总内存。最后一个会读取 GPU 使用情况。
初始化和总内存方法确实有效,但最后一个我遇到了一些问题。当我调用方法时它会停止,当我调试它时,我可以在 delete[] ids 上设置断点;线没有任何问题。但它不会在返回可用行上返回任何东西(它没有到达那里)。当我删除 delte[] ids 行时,出现错误: '运行时检查失败 #2 - 围绕变量'nCurAvailMemoryInKB' 的堆栈已损坏。'。读取 GPU 内存的使用情况是否有问题?
__declspec(dllexport) float getAvailableMemory()
{
int available = -1;
if (wglGetGPUIDsAMD && wglGetGPUInfoAMD)
{
UINT n = wglGetGPUIDsAMD(0, 0);
UINT * ids = new UINT[n];
wglGetGPUIDsAMD(n, ids);
GLint nCurAvailMemoryInKB = 0;
glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI,
&nCurAvailMemoryInKB);
available = nCurAvailMemoryInKB;
delete[] ids;
}
return available;
}
我在 C# 中为 Dll 创建了一个测试调用程序: 类程序 {
[DllImport("AmdLib.dll")]
public static extern bool init();
[DllImport("AmdLib.dll")]
public static extern int getTotalMemory();
[DllImport("AmdLib.dll")]
public static extern float getAvailableMemory();
static void Main(string[] args) {
init();
Console.WriteLine("Total");
Console.WriteLine(getTotalMemory());
Console.WriteLine("Available");
Console.WriteLine(getAvailableMemory());
}
}
完整的 C++ DLL 源代码如下所示:
#include <stdio.h>
#include <windows.h>
#include <GL/glew.h>
#include <GL/wglew.h>
#include <assert.h>
#include <vector>
#include <string>
using namespace std;
extern "C"
{
static HGLRC ctx = NULL;
__declspec(dllexport) bool init()
{
HWND hwnd = NULL;
HINSTANCE hinstance = (HINSTANCE)GetModuleHandle(NULL);
WNDCLASSA window_class;
window_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_GLOBALCLASS;
window_class.lpfnWndProc = DefWindowProc;
window_class.cbClsExtra = 0;
window_class.cbWndExtra = 0;
window_class.hInstance = hinstance;
window_class.hIcon = NULL;
window_class.hCursor = LoadCursor(NULL, IDC_ARROW);
window_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
window_class.lpszMenuName = NULL;
window_class.lpszClassName = "test_class";
ATOM atom = RegisterClassA(&window_class);
hwnd = CreateWindowA("test_class", "htest", WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 1, 1, 1, 1, NULL, NULL, hinstance, NULL);
if (hwnd == NULL) {
DWORD err = GetLastError();
return false;
}
HDC hDC = GetDC(hwnd);
if (hDC == NULL) {
return false;
}
PIXELFORMATDESCRIPTOR const pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_TYPE_RGBA,
0,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
0,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
int pixel_format = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, pixel_format, &pfd);
ctx = wglCreateContext(hDC);
if (ctx) {
if (!wglMakeCurrent(hDC, ctx)) {
return false;
}
}
ReleaseDC(hwnd, hDC);
GLenum glew = glewInit();
return true;
}
static void check_gl_error()
{
GLenum error = glGetError();
assert(error == GL_NO_ERROR);
}
__declspec(dllexport) int getTotalMemory()
{
if (wglGetGPUIDsAMD && wglGetGPUInfoAMD)
{
UINT n = wglGetGPUIDsAMD(0, 0);
UINT * ids = new UINT[n];
UINT total_mem_mb = 0;
wglGetGPUIDsAMD(n, ids);
wglGetGPUInfoAMD(ids[0], WGL_GPU_RAM_AMD, GL_UNSIGNED_INT, sizeof(UINT), &total_mem_mb);
delete[] ids;
return total_mem_mb;
}
return -1;
}
__declspec(dllexport) float getAvailableMemory()
{
int available = -1;
if (wglGetGPUIDsAMD && wglGetGPUInfoAMD)
{
UINT n = wglGetGPUIDsAMD(0, 0);
UINT * ids = new UINT[n];
wglGetGPUIDsAMD(n, ids);
GLint nCurAvailMemoryInKB = 0;
glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI,
&nCurAvailMemoryInKB);
available = nCurAvailMemoryInKB;
//delete[] ids;
}
return available;
}
}
【问题讨论】:
-
检查wglGetGPUIDsAMD函数指针是否初始化正确,其类型是否与库函数完全匹配。
-
wglGetGPUIDsAMD 确实正确初始化了指针。当我调试时,我可以看到 nCurAvailMemoryInKB 的正确值。但是当我在 glGetIntegerv 之后立即返回它时,我得到了“围绕变量 'nCurAvailMemoryInKB' 的堆栈已损坏”错误。
-
你解决了吗?我很想自己做这个……
标签: c# c++ dll gpu amd-processor