gpt4 book ai didi

c++ - 在 Windows 上创建并行离屏 OpenGL 上下文

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:38:13 25 4
gpt4 key购买 nike

我正在尝试设置并行多 GPU 离屏渲染上下文。我使用“OpenGL Insights”一书第 27 章“NVIDIA Quadro 上的多 GPU 渲染”。我还研究了 wglCreateAffinityDCNV docs但仍然无法确定。

我的机器有 2 个 NVidia Quadro 4000 卡(无 SLI)。在 Windows 7 64 位上运行。我的工作流程是这样的:

  1. 使用 GLFW 创建默认窗口上下文。
  2. 映射 GPU 设备。
  3. 销毁默认的 GLFW 上下文。
  4. 为每个设备创建新的 GL 上下文(目前只尝试一个)
  5. 为每个上下文设置 boost 线程并使其在该线程中处于当前状态。
  6. 分别在每个线程上运行渲染程序。(不共享资源)

一切都是在没有错误的情况下创建和运行的,但是一旦我尝试从屏幕外的 FBO 读取像素,我在这里得到一个空指针:

GLubyte* ptr  = (GLubyte*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);

此外 glError 返回 "UNKNOWN ERROR"

我认为可能是多线程问题,但在单线程上运行时,相同的设置会产生相同的结果。所以我认为这与上下文创建有关。

这是我的做法:

  ////Creating default window with GLFW here .
.....
.....

创建屏幕外上下文:

  PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, //Flags
PFD_TYPE_RGBA, //The kind of framebuffer. RGBA or palette.
24, //Colordepth of the framebuffer.
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
24, //Number of bits for the depthbuffer
8, //Number of bits for the stencilbuffer
0, //Number of Aux buffers in the framebuffer.
PFD_MAIN_PLANE,
0,
0, 0, 0
};

void glMultiContext::renderingContext::createGPUContext(GPUEnum gpuIndex){

int pf;
HGPUNV hGPU[MAX_GPU];
HGPUNV GpuMask[MAX_GPU];

UINT displayDeviceIdx;
GPU_DEVICE gpuDevice;
bool bDisplay, bPrimary;
// Get a list of the first MAX_GPU GPUs in the system
if ((gpuIndex < MAX_GPU) && wglEnumGpusNV(gpuIndex, &hGPU[gpuIndex])) {

printf("Device# %d:\n", gpuIndex);

// Now get the detailed information about this device:
// how many displays it's attached to
displayDeviceIdx = 0;
if(wglEnumGpuDevicesNV(hGPU[gpuIndex], displayDeviceIdx, &gpuDevice))
{

bPrimary |= (gpuDevice.Flags & DISPLAY_DEVICE_PRIMARY_DEVICE) != 0;
printf(" Display# %d:\n", displayDeviceIdx);
printf(" Name: %s\n", gpuDevice.DeviceName);
printf(" String: %s\n", gpuDevice.DeviceString);
if(gpuDevice.Flags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
{
printf(" Attached to the desktop: LEFT=%d, RIGHT=%d, TOP=%d, BOTTOM=%d\n",
gpuDevice.rcVirtualScreen.left, gpuDevice.rcVirtualScreen.right, gpuDevice.rcVirtualScreen.top, gpuDevice.rcVirtualScreen.bottom);
}
else
{
printf(" Not attached to the desktop\n");
}

// See if it's the primary GPU
if(gpuDevice.Flags & DISPLAY_DEVICE_PRIMARY_DEVICE)
{
printf(" This is the PRIMARY Display Device\n");
}


}

///======================= CREATE a CONTEXT HERE
GpuMask[0] = hGPU[gpuIndex];
GpuMask[1] = NULL;
_affDC = wglCreateAffinityDCNV(GpuMask);

if(!_affDC)
{
printf( "wglCreateAffinityDCNV failed");
}

}

printf("GPU context created");
}

glMultiContext::renderingContext *
glMultiContext::createRenderingContext(GPUEnum gpuIndex)
{
glMultiContext::renderingContext *rc;

rc = new renderingContext(gpuIndex);

_pixelFormat = ChoosePixelFormat(rc->_affDC, &pfd);

if(_pixelFormat == 0)
{

printf("failed to choose pixel format");
return false;
}

DescribePixelFormat(rc->_affDC, _pixelFormat, sizeof(pfd), &pfd);

if(SetPixelFormat(rc->_affDC, _pixelFormat, &pfd) == FALSE)
{
printf("failed to set pixel format");
return false;
}

rc->_affRC = wglCreateContext(rc->_affDC);


if(rc->_affRC == 0)
{
printf("failed to create gl render context");
return false;
}


return rc;
}

//Call at the end to make it current :


bool glMultiContext::makeCurrent(renderingContext *rc)
{
if(!wglMakeCurrent(rc->_affDC, rc->_affRC))
{

printf("failed to make context current");
return false;
}

return true;
}

//// init OpenGL objects and rendering here :

..........
............

正如我所说,我在设备和上下文创建的任何阶段都没有遇到任何错误。我究竟做错了什么 ?

更新:

好吧,好像我发现了这个错误。我在调用 wglMakeCurrent() 之后调用了 glfwTerminate() ,所以看起来最新的使“非当前”也成为新的上下文。尽管它是有线的,因为 OpenGL 命令不断被执行.所以它在单个线程中工作。

但是现在,如果我使用 boost treads 生成另一个线程,我会收到初始错误。这是我的线程类:

GPUThread::GPUThread(void)
{
_thread =NULL;
_mustStop=false;
_frame=0;


_rc =glMultiContext::getInstance().createRenderingContext(GPU1);
assert(_rc);

glfwTerminate(); //terminate the initial window and context
if(!glMultiContext::getInstance().makeCurrent(_rc)){

printf("failed to make current!!!");
}
// init engine here (GLEW was already initiated)
engine = new Engine(800,600,1);

}
void GPUThread::Start(){



printf("threaded view setup ok");

///init thread here :
_thread=new boost::thread(boost::ref(*this));

_thread->join();

}
void GPUThread::Stop(){
// Signal the thread to stop (thread-safe)
_mustStopMutex.lock();
_mustStop=true;
_mustStopMutex.unlock();

// Wait for the thread to finish.
if (_thread!=NULL) _thread->join();

}
// Thread function
void GPUThread::operator () ()
{
bool mustStop;

do
{
// Display the next animation frame
DisplayNextFrame();
_mustStopMutex.lock();
mustStop=_mustStop;
_mustStopMutex.unlock();
} while (mustStop==false);

}


void GPUThread::DisplayNextFrame()
{

engine->Render(); //renders frame
if(_frame == 101){
_mustStop=true;
}
}

GPUThread::~GPUThread(void)
{
delete _view;
if(_rc != 0)
{
glMultiContext::getInstance().deleteRenderingContext(_rc);
_rc = 0;
}
if(_thread!=NULL)delete _thread;
}

最佳答案

最后我自己解决了问题。第一个问题是我在将另一个设备上下文设置为当前后调用了 glfwTerminate。这可能也卸载了新的上下文。第二个问题是我对提升线程的“笨拙”。我未能在自定义线程中初始化所有与渲染相关的对象,因为我在设置线程之前调用了 rc init 对象过程,如上例所示。

关于c++ - 在 Windows 上创建并行离屏 OpenGL 上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15760147/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com