Unfortunately, contexts are already created from within the thread.
There’s a simple code I’m using to setup and test my rendering. Maybe there are some errors I’m unable to see…
class window
{
public:
window(int x, int y, int width, int height, const char * title, int affinity = -1)
{
HINSTANCE hInstance = GetModuleHandle(NULL);
// registration here
wnd = CreateWindow(title, title,
WS_CAPTION | WS_BORDER | WS_SIZEBOX | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX,
x, y, width, height,
NULL, NULL, hInstance, NULL);
if (!wnd)
throw std::runtime_error("CreateWindow failed!");
SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)this);
dc = GetDC(wnd);
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
24, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
1, // Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
24, // 24 Bit Z-Buffer (Depth Buffer)
8, // 8 Bit Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
int _pixelFormat = ChoosePixelFormat(dc, &pfd);
if (_pixelFormat == 0)
throw std::runtime_error("ChoosePixelFormat failed!");
if (SetPixelFormat(dc, _pixelFormat, &pfd) == FALSE)
throw std::runtime_error("SetPixelFormat failed!");
rc = wglCreateContext(dc);
wglMakeCurrent(dc, rc);
glewInit();
if ((WGLEW_NV_gpu_affinity) && (affinity != -1))
{
HGPUNV gpu;
wglEnumGpusNV(affinity, &gpu);
HGPUNV gpu_list [] = { gpu, nullptr };
affinity_dc = wglCreateAffinityDCNV(&gpu_list[0]);
if (!affinity_dc)
throw std::runtime_error("wglCreateAffinityDCNV failed!");
int _pixelFormat = ChoosePixelFormat(affinity_dc, &pfd);
if (_pixelFormat == 0)
throw std::runtime_error("ChoosePixelFormat failed!");
if (SetPixelFormat(affinity_dc, _pixelFormat, &pfd) == FALSE)
throw std::runtime_error("SetPixelFormat failed!");
affinity_rc = wglCreateContext(affinity_dc);
if (!affinity_rc)
throw std::runtime_error("wglCreateContext failed!");
if (!wglMakeCurrent(dc, affinity_rc))
throw std::runtime_error("wglMakeCurrent failed!");
}
ShowWindow(wnd, SW_SHOW);
UpdateWindow(wnd);
}
template <typename F>
void run(F fn)
{
MSG msg;
bool done = false;
while (!done)
{
while (PeekMessage(&msg, wnd, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
done = true;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
fn();
SwapBuffers(dc);
}
}
static LONG WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
window * w = (window*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
if ((!w) || (w->wnd != hWnd))
return (LONG) DefWindowProc(hWnd, uMsg, wParam, lParam);
switch (uMsg)
{
case WM_CREATE:
break;
case WM_PAINT:
break;
case WM_SIZE:
break;
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return (LONG) DefWindowProc(hWnd, uMsg, wParam, lParam);
}
...
};
void run(int x, int y, int w, int h, const char * title, int affinity = -1)
{
try
{
window wnd(x, y, w, h, title, affinity);
// create gbuffer fbo
// create shaders/programs
// load textures and meshes
wnd.run([&]()
{
// render to gbuffer fbo
// display result from gbuffer
});
}
catch (std::exception & e) { std::cout << e.what() << std::endl; }
catch(...) { std::cout << "Unknown exception!" << std::endl; }
return 0;
}
int main(int argc, char * argv [])
{
try
{
std::thread t1(run, 50, 50, 1024, 768, "win1", 0);
run(1920 + 50, 50, 1024, 768, "win2", 1);
t1.join();
}
catch (std::exception & e) { std::cout << e.what() << std::endl; }
catch (...) { std::cout << "Unknown exception!" << std::endl; }
}
For the purpose of testing there’s no data upload during render loop. There’s just binding of textures, binding of vertex buffers and glDrawArraysInstancedBaseInstance calls. Data for each draw call is sourced from shader storage buffer using gl_BaseInstanceID.