AMD Gpu Memory dll

本文关键字:dll Memory Gpu AMD | 更新日期: 2023-09-27 18:06:12

我正在写一个c++ dll用于c#应用程序。dll将检查GPU内存总量和GPU内存使用情况。

现在我已经创建了三个方法。第一个初始化GLew和其他OpeGl的东西。第二个将读取GPU的总内存。最后一个将读取GPU使用情况。

初始化和总内存方法确实工作,但最后一个我得到一些问题。当我调用该方法时,它会停止,当我调试它时,我可以在delete[] id上设置一个断点;线路没有任何问题。但是它在返回可用行上没有返回任何东西(它没有到达那里)。当我删除delete [] 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;
    }
}

AMD Gpu Memory dll

因为我没有ATI卡来测试,我猜第一个wglGetGPUIDsAMD调用返回0,你分配一个0长度的数组(工作),最后你试图删除它(抛出)。在两者之间的某个地方,你用数据覆盖指针周围的内存(从而破坏保护并使VS抛出)。

现在看看你实际在用这个数组做什么,或者你知道你有多少个gpu,你从来没有真正使用过它们中的任何一个。您可以直接删除对wglGetGPUIDsAMD的调用和对数组的分配/释放,而只调用glGetIntegerv