Just submitted this as a bug re****t to Nvidia, but I'm curious whether
anyone here has seen anything similar or can maybe reproduce the issue or
have any idea what's going on ? I suspect the pattern of ccycling through
a bunch of pbuffers is fairly unusual; the issue came up in a unittest
framework which builds a new pbuffer and context around each test case (of
which there are many in an executable). The code (at the end of the post)
is distilled down to show the essence of the problem.
-----
Summary
-------
The attached standalone test program (pb.cpp) p***** on a 32-bit
(Athlon-XP) system with a GeForce 7600 GS (AGP), but exhibits failures
on a 64-bit (Intel Q9450) system with a GeForce 9600 GT. (Both systems
up-to-date Debian Lenny with i386/amd64 as appropriate. 2.6.25 kernel).
The test can also be made to pass on 64-bit by not selecting the
"direct" option in glXCreateNewContext.
Detail
------
The code can simply be compiled with
g++ pb.cpp -o pb -lGL
and then run with
./pb
The program repeats a loop 8 times:
- create 1x1 pixel pbuffer and a "direct" context
- clear the pbuffer to a given RGBA color (different each iteration)
- read back the pbuffer content
- check the pbuffer content is what was expected
- re****t pass or fail accordingly
- clean up (destroy the pbuffer & GL context; disconnect from display)
On the 64bit+9600GT system, a typical output is:
Test 0 : [direct]......PASS
Test 1 : [direct]......FAIL: expected 0000ff00, got ffffffff
Test 2 : [direct]......FAIL: expected 00ff0000, got ffffffff
Test 3 : [direct]......FAIL: expected ff000000, got ffffffff
Test 4 : [direct]......FAIL: expected 000000ff, got ffffffff
Test 5 : [direct]......FAIL: expected 0000ff00, got ffffffff
Test 6 : [direct]......FAIL: expected 00ff0000, got ffffffff
Test 7 : [direct]......FAIL: expected ff000000, got ffffffff
however, it has occasionally been observed that the first two tests may
pass, and very rarely all tests have been seen to pass. Certainly the
first iteration always succeeds.
The presence of 0xffffffff in read-back data implies glReadPixels fails
to modify the value of "actual" at all; however no GL error is re****ted.
On the 32bit+7600GS system, the output is (as expected and desired)
Test 0 : [direct]......PASS
Test 1 : [direct]......PASS
Test 2 : [direct]......PASS
Test 3 : [direct]......PASS
Test 4 : [direct]......PASS
Test 5 : [direct]......PASS
Test 6 : [direct]......PASS
Test 7 : [direct]......PASS
The program can also be made to pass on the 64bit platform by changing
line 31 from
const bool use_direct=true;
to
const bool use_direct=false;
which disables use of DRI in the call to glXCreateNewContext.
This results in output:
Test 0 : [NOT direct]......PASS
Test 1 : [NOT direct]......PASS
Test 2 : [NOT direct]......PASS
Test 3 : [NOT direct]......PASS
Test 4 : [NOT direct]......PASS
Test 5 : [NOT direct]......PASS
Test 6 : [NOT direct]......PASS
Test 7 : [NOT direct]......PASS
Unfortunately I don't have access to any more nvidia systems to test
this further (and given one machine is AGP, and the other PCIe, I can't
even swap cards to investigate whether the issue is associated with the
GPU or the platform).
Background info
---------------
Both systems are up-to-date-at-time-of-writing Debian Lenny (i386 on the
Athlon, and64 on the Q9450) with 173.14.09-3 drivers installed by
"module assistant". Systems (including graphics) are in full working
order; normal OpenGL apps function perfectly etc.
-----
Here's the code (pb.cpp):
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/glx.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <stdlib.h>
#include <iostream>
#include <iomanip>
#include <sstream>
void bad(const char* error)
{
std::cerr
<< "FATAL ERROR: "
<< error
<< "\n";
exit(1);
}
int main(int argc,char** argv)
{
const int width=1;
const int height=1;
for (int i=0;i<8;i++)
{
const bool use_direct=true; // Change to false, and it all Just
Works.
std::cerr
<< "Test "
<< i
<< " : "
<< (use_direct ? "[direct]" : "[NOT direct]")
<< "...";
// Set up pbuffer and context
Display* display;
GLXPbuffer pbuffer;
GLXContext context;
const char*const display_name=getenv("DISPLAY");
if (!display_name)
bad("DISPLAY environment variable not set");
display=XOpenDisplay(display_name);
const int fb_attributes[]={
GLX_RENDER_TYPE,GLX_RGBA_BIT,
GLX_DRAWABLE_TYPE,GLX_PBUFFER_BIT,
GLX_RED_SIZE,8,
GLX_GREEN_SIZE,8,
GLX_BLUE_SIZE,8,
GLX_ALPHA_SIZE,8,
GLX_DEPTH_SIZE,0,
GLX_DOUBLEBUFFER,False,
0
};
int num_configs=0;
GLXFBConfig*const configs=
glXChooseFBConfig
(
display,
DefaultScreen(display),
fb_attributes,
&num_configs
);
if (!configs)
bad("glXChooseFBConfig matched no configs");
const int pb_attributes[]=
{
GLX_PBUFFER_WIDTH,width,
GLX_PBUFFER_HEIGHT,height,
0
};
pbuffer=
glXCreatePbuffer
(
display,
*configs,
pb_attributes
);
if (!pbuffer)
bad("glXCreatePbuffer failed");
context=
glXCreateNewContext
(
display,
*configs,
GLX_RGBA_TYPE,
0,
(use_direct ? True : False)
);
if (!context) bad("glXCreateNewContext failed");
glXMakeCurrent(display,pbuffer,context);
// Set one of RGBA channels in image, rest zero
glView****t(0,0,width,height);
glClearColor
(
(i%4==0 ? 1.0f : 0.0f),
(i%4==1 ? 1.0f : 0.0f),
(i%4==2 ? 1.0f : 0.0f),
(i%4==3 ? 1.0f : 0.0f)
);
glClear(GL_COLOR_BUFFER_BIT);
//No, glFlush or glFinish here doesn't help
//glFlush();
//glFinish();
// Read the single pixel back
unsigned int actual=0xffffffff;
glReadPixels(0,0,1,1,GL_RGBA,GL_UNSIGNED_BYTE,&actual);
// See if it's what we expected to see
const unsigned int expected=(0xff<<(8*i));
if (actual==expected)
{
std::cerr << "...PASS\n";
}
else
{
std::ostringstream msg;
msg
<< "...FAIL: "
<< "expected "
<< std::hex
<< std::setfill('0')
<< std::setw(8)
<< expected
<< ", "
<< "got "
<< std::hex
<< std::setfill('0')
<< std::setw(8)
<< actual << "\n";
std::cerr << msg.str();
}
if (glGetError()!=GL_NO_ERROR)
bad("glGetError indictated a problem");
// Clean up pbuffer and context
glXDestroyContext(display,context);
glXDestroyPbuffer(display,pbuffer);
XCloseDisplay(display);
}
return 0;
}


|