c# - AMD Gpu 内存 dll

标签 c# c++ dll gpu amd-processor

我正在编写用于 C# 应用程序的 C++ dll。 该 dll 将检查总的 GPU 内存和 GPU 内存的使用情况。

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

初始化和总内存方法确实有效,但最后一个方法我遇到了一些问题。当我调用方法时它停止,当我调试它时我可以在 delete[] ids 上设置断点;行没有任何问题。但它不会在 return available 行上返回任何内容(它没有到达那里)。当我删除 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;
    }
}

最佳答案

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

现在看看你实际用那个阵列做什么,或者你有多少 GPU 的知识,你实际上从未使用过它们中的任何一个。您可以从字面上删除对 wglGetGPUIDsAMD 和数组分配/解除分配的调用,而只需调用 glGetIntegerv

关于c# - AMD Gpu 内存 dll,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23999996/

相关文章:

c++ - 为什么 sizeof(std::mutex)==40 (gcc,clang,icc)?

c++ - 覆盖来自 kernel32 的调用

c# - 替换 lambdas 的自定义函数包含、StartsWith 和 EndsWith

c# - 将引用类型对象的数组从 C# 编码到 C++

c++ - cmake .. 做什么?

c# - System.Net.Http DLL 未复制到 bin 文件夹中 - IdentityServer4.AccessTokenValidation

visual-studio-2008 - 在 visual studio c++ 2008 中包含 dll

c# - iOS 模态弹出窗口开始透明但变成空白

c# - 使用Dataadapter更新时出现DBConcurrency异常

c++ - 在 C++ 中为 const 变量赋值