c # — AMD Gpu Memory dll

Я пишу C ++ DLL для использования в приложении C #.
DLL проверит общий объем памяти GPU и использование памяти GPU.

Сейчас я создал три метода. Первый действительно инициализирует GLew и другие вещи OpeGl. Второй будет читать общую память графического процессора. И последний будет читать использование графического процессора.

Методы inialize и total memory работают, но с последним я получаю некоторые проблемы. Когда я вызываю метод, он останавливается, и когда я отлаживаю его, я могу установить точку останова на идентификаторах delete []; линия без проблем. Но он не возвращает ничего в строке возврата (он туда не попадает). Когда я удаляю строку delte [] ids, я получаю сообщение об ошибке:
‘Ошибка проверки времени выполнения # 2 — стек вокруг переменной’ nCurAvailMemoryInKB ‘был поврежден.’ Неужели я что-то неправильно прочитал об использовании памяти графического процессора?

__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;
}

Я создал тестовый вызывающий для Dll в C #:
Программа класса {

[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;
}
}

0

Решение

Так как у меня нет карты ATI для тестирования, я думаю, первое wglGetGPUIDsAMD Вызов возвращает 0, вы выделяете массив длиной 0 (который работает) и в конце вы пытаетесь удалить его (который выбрасывает). Где-то посередине вы перезаписываете память вокруг этого указателя данными (таким образом, повреждая охрану и заставляя VS бросать).

Теперь, глядя на то, что вы на самом деле делаете с этим массивом, или на знание того, сколько у вас графических процессоров, вы никогда не используете ни один из них. Вы можете буквально удалить оба вызова wglGetGPUIDsAMD и распределение / освобождение массива, и просто вызвать glGetIntegerv,

1

Другие решения