Сбой wglCreateContextAttribsARB в режиме отладки на платформе x64

Я столкнулся с проблемой, пытаясь отладить мое 64-битное приложение в Visual Studio 2015. Когда я переключаю его в режим отладки, он падает при создании окна. Что не произошло в 32-битном режиме;

Вот отредактированный код инициализации окна:

int indexPF;
WNDCLASS WinClass;

WinClass.style = CS_OWNDC | CS_PARENTDC;
WinClass.lpfnWndProc = WndProc;
WinClass.cbClsExtra = 0;
WinClass.cbWndExtra = 0;
WinClass.hInstance = hInstance;
WinClass.hIcon = LoadIcon(NULL, IDC_ICON);
WinClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WinClass.hbrBackground = (HBRUSH)GetStockObject(5);
WinClass.lpszMenuName = NULL;
WinClass.lpszClassName = "N2";

if (!RegisterClass(&WinClass))
{
...report error and terminate...
}

Logger::Inst() << " ~RegisterClass;" << endl;

//CREATE WINDOW

if (fullScreen)
{
if ((hwnd = CreateWindowEx(WS_EX_LEFT, "N2", "N2",
WS_POPUP,
0, 0, width, height,
NULL, NULL, hInstance, NULL)) == 0)
{
...report error and terminate...
}
}
else
{
if ((hwnd = CreateWindowEx(WS_EX_LEFT, "N2", "N2",
WS_OVERLAPPEDWINDOW,
0, 0, width, height,
NULL, NULL, hInstance, NULL)) == 0)
{
...report error and terminate...
}
}

Logger::Inst() << " ~CreateWindow;" << endl;

//PFD SETUP
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
24,
8, 0, PFD_MAIN_PLANE, 0, 0, 0x00FF00FF, 0
};

//HDC
if ((hdc = GetDC(hwnd)) == NULL)
{
...report error and terminate...
}

Logger::Inst() << " ~GotHDC;" << endl;

//SET PIXEL FORMAT
indexPF = ChoosePixelFormat(hdc, &pfd);
if (!indexPF)
{
...report error and terminate...
}

if (!SetPixelFormat(hdc, indexPF, &pfd))
{
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_SWAP_EXCHANGE;
indexPF = ChoosePixelFormat(hdc, &pfd);

if (!SetPixelFormat(hdc, indexPF, &pfd))
{
...report error and terminate...
}
}

Logger::Inst() << " ~SetPFD;" << endl;

//TEMP CONTEXT TO ACQUIRE POINTER
HGLRC tempContext = wglCreateContext(hdc);

if (!tempContext) {
...report error and terminate...
}

if (!wglMakeCurrent(hdc, tempContext)) {
...report error and terminate...
}

int major, minor; glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MINOR_VERSION, &minor);
if (major < 4 || minor < 1) {
...report error and terminate...
}

const int attribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, major,
WGL_CONTEXT_MINOR_VERSION_ARB, minor,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0, 0
};

PFNWGLCREATEBUFFERREGIONARBPROC wglCreateContextAttribsARB = (PFNWGLCREATEBUFFERREGIONARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
if (!wglCreateContextAttribsARB) {
...report error and terminate...
}

**!!! CRASH HERE !!!**
if (!(hglrc = (HGLRC)wglCreateContextAttribsARB(hdc, 0, (UINT)attribs))) {
...report error and terminate...
}

Отладчик показывает, что это происходит именно в wglCreateContextAttribsARB (nvoglv64.dll! 0000000074ccbdfa). Это полная загадка для меня. Единственная подсказка — после перехода на x64 требуются атрибуты, переданные как «UINT» вместо «const int *», я не понимаю, какую часть, даже не уверен, что преобразование между собой должно работать, кажется подозрительным. Идеи?

2

Решение

У вас есть опечатка: тип для wglCreateContextAttribsARB неправильно. Так должно быть PFNWGLCREATECONTEXTATTRIBSARBPROC,

Причина, по которой это сработало, когда вы работали с 32-разрядной версией, заключается в том, что сигнатура этих двух элементов в 32-разрядной системе практически одинакова:

wglCreateContextAttribsARB:

typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList);

wglCreateBufferRegionARB:

typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType);

Второй и третий параметры wglCreateContextAttribsARB являются указателями HGLRC это дескриптор, который является просто указателем), а второй и третий параметры wglCreateBufferRegionARB целые числа. В 32-разрядных системах указатели имеют 32-разрядный размер, поэтому сигнатуры практически одинаковы.

В 64-разрядных указатели имеют размер 64-разрядных, но целые числа по-прежнему 32-разрядные (при условии, что вы используете MSVC), поэтому эти два указателя, которые вы передавали, были усечены.

4

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

Других решений пока нет …

По вопросам рекламы [email protected]