Forum Discussion

🚨 This forum is archived and read-only. To submit a forum post, please visit our new Developer Forum. 🚨
2EyeGuy's avatar
2EyeGuy
Adventurer
12 years ago

ovrHmd_EndFrame Access violation reading location 0x00000000

I'm getting an access violation reading location 0x00000000 in ovrHmd_EndFrame(hmd), using OpenGL, in Doom 3 BFG. Any idea what I'm (or you're) doing wrong?


/*
====================
RB_StereoRenderExecuteBackEndCommands

Renders the draw list twice, with slight modifications for left eye / right eye
====================
*/
void RB_StereoRenderExecuteBackEndCommands( const emptyCommand_t * const allCmds ) {
uint64 backEndStartTime = Sys_Microseconds();

// If we are in a monoscopic context, this draws to the only buffer, and is
// the same as GL_BACK. In a quad-buffer stereo context, this is necessary
// to prevent GL from forcing the rendering to go to both BACK_LEFT and
// BACK_RIGHT at a performance penalty.
// To allow stereo deghost processing, the views have to be copied to separate
// textures anyway, so there isn't any benefit to rendering to BACK_RIGHT for
// that eye.
qglDrawBuffer( GL_BACK_LEFT );

// create the stereoRenderImage if we haven't already
static idImage * stereoRenderImages[2];
for ( int i = 0; i < 2; i++ ) {
if ( stereoRenderImages[i] == NULL ) {
stereoRenderImages[i] = globalImages->ImageFromFunction( va("_stereoRender%i",i), R_MakeStereoRenderImage );
}

// resize the stereo render image if the main window has changed size
if ( stereoRenderImages[i]->GetUploadWidth() != renderSystem->GetWidth() ||
stereoRenderImages[i]->GetUploadHeight() != renderSystem->GetHeight() ) {
stereoRenderImages[i]->Resize( renderSystem->GetWidth(), renderSystem->GetHeight() );
}
EyeTexture[i].OGL.Header.API = ovrRenderAPI_OpenGL;
EyeTexture[i].OGL.Header.TextureSize = renderTargetSize;
EyeTexture[i].OGL.Header.RenderViewport = eyes[i].RenderViewport;
}



// In stereoRender mode, the front end has generated two RC_DRAW_VIEW commands
// with slightly different origins for each eye.

// TODO: only do the copy after the final view has been rendered, not mirror subviews?

// Render the 3D draw views from the screen origin so all the screen relative
// texture mapping works properly, then copy the portion we are going to use
// off to a texture.
bool foundEye[2] = { false, false };

/*ovrFrameTiming hmdFrameTiming =*/ ovrHmd_BeginFrame(hmd, 0);

for ( int stereoEye = 1; stereoEye >= -1; stereoEye -= 2 ) {
// set up the target texture we will draw to
const int targetEye = ( stereoEye == 1 ) ? 1 : 0;
ovrEyeType eye = ( stereoEye == 1 ) ? ovrEye_Right : ovrEye_Left;
ovrPosef eyePose = ovrHmd_BeginEyeRender(hmd, eye);

// Set the back end into a known default state to fix any stale render state issues
GL_SetDefaultState();
renderProgManager.Unbind();
renderProgManager.ZeroUniforms();

for ( const emptyCommand_t * cmds = allCmds; cmds != NULL; cmds = (const emptyCommand_t *)cmds->next ) {
switch ( cmds->commandId ) {
case RC_NOP:
break;
case RC_DRAW_VIEW_GUI:
case RC_DRAW_VIEW_3D:
{
const drawSurfsCommand_t * const dsc = (const drawSurfsCommand_t *)cmds;
const viewDef_t & eyeViewDef = *dsc->viewDef;

if ( eyeViewDef.renderView.viewEyeBuffer && eyeViewDef.renderView.viewEyeBuffer != stereoEye ) {
// this is the render view for the other eye
continue;
}

foundEye[ targetEye ] = true;
RB_DrawView( dsc, stereoEye );
if ( cmds->commandId == RC_DRAW_VIEW_GUI ) {
}
}
break;
case RC_SET_BUFFER:
RB_SetBuffer( cmds );
break;
case RC_COPY_RENDER:
RB_CopyRender( cmds );
break;
case RC_POST_PROCESS:
{
postProcessCommand_t * cmd = (postProcessCommand_t *)cmds;
if ( cmd->viewDef->renderView.viewEyeBuffer != stereoEye ) {
break;
}
RB_PostProcess( cmds );
}
break;
default:
common->Error( "RB_ExecuteBackEndCommands: bad commandId" );
break;
}
}

// copy to the target
stereoRenderImages[ targetEye ]->CopyFramebuffer( 0, 0, renderSystem->GetWidth(), renderSystem->GetHeight() );

EyeTexture[targetEye].OGL.TexId = stereoRenderImages[targetEye]->texnum;
ovrHmd_EndEyeRender(hmd, eye, eyePose, &EyeTexture[eye].Texture);

}

// perform the final compositing / warping / deghosting to the actual framebuffer(s)
assert( foundEye[0] && foundEye[1] );

GL_SetDefaultState();

RB_SetMVP( renderMatrix_identity );

// If we are in quad-buffer pixel format but testing another 3D mode,
// make sure we draw to both eyes. This is likely to be sub-optimal
// performance on most cards and drivers, but it is better than getting
// a confusing, half-ghosted view.
if ( renderSystem->GetStereo3DMode() != STEREO3D_QUAD_BUFFER ) {
glDrawBuffer( GL_BACK );
}

GL_State( GLS_DEPTHFUNC_ALWAYS );
GL_Cull( CT_TWO_SIDED );

// We just want to do a quad pass - so make sure we disable any texgen and
// set the texture matrix to the identity so we don't get anomalies from
// any stale uniform data being present from a previous draw call
const float texS[4] = { 1.0f, 0.0f, 0.0f, 0.0f };
const float texT[4] = { 0.0f, 1.0f, 0.0f, 0.0f };
renderProgManager.SetRenderParm( RENDERPARM_TEXTUREMATRIX_S, texS );
renderProgManager.SetRenderParm( RENDERPARM_TEXTUREMATRIX_T, texT );

// disable any texgen
const float texGenEnabled[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
renderProgManager.SetRenderParm( RENDERPARM_TEXGEN_0_ENABLED, texGenEnabled );

renderProgManager.BindShader_Texture();
GL_Color( 1, 1, 1, 1 );
static stereo3DMode_t old3Dmode = STEREO3D_OFF;
if (old3Dmode == STEREO3D_VR920 && renderSystem->GetStereo3DMode()!=STEREO3D_VR920) {
VR920_StopStereo3D();
}
switch( renderSystem->GetStereo3DMode() ) {
case STEREO3D_QUAD_BUFFER:
glDrawBuffer( GL_BACK_RIGHT );
GL_SelectTexture( 0 );
stereoRenderImages[1]->Bind();
GL_SelectTexture( 1 );
stereoRenderImages[0]->Bind();
RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );

glDrawBuffer( GL_BACK_LEFT );
GL_SelectTexture( 1 );
stereoRenderImages[1]->Bind();
GL_SelectTexture( 0 );
stereoRenderImages[0]->Bind();
RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );

break;
case STEREO3D_HDMI_720:
// HDMI 720P 3D
GL_SelectTexture( 0 );
stereoRenderImages[1]->Bind();
GL_SelectTexture( 1 );
stereoRenderImages[0]->Bind();
GL_ViewportAndScissor( 0, 0, 1280, 720 );
RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );

GL_SelectTexture( 0 );
stereoRenderImages[0]->Bind();
GL_SelectTexture( 1 );
stereoRenderImages[1]->Bind();
GL_ViewportAndScissor( 0, 750, 1280, 720 );
RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );

// force the HDMI 720P 3D guard band to a constant color
glScissor( 0, 720, 1280, 30 );
glClear( GL_COLOR_BUFFER_BIT );
break;
default:
case STEREO3D_RIFTSDK:
{
ovrHmd_EndFrame(hmd);
#if 0
// this is the new Facebook Oculus Rift SDK v0.3.1
renderProgManager.BindShader_StereoWarp();

// clear the entire screen to black
// we could be smart and only clear the areas we aren't going to draw on, but
// clears are fast...
glScissor ( 0, 0, glConfig.nativeScreenWidth, glConfig.nativeScreenHeight );
glClearColor( 0, 0, 0, 0 );
glClear( GL_COLOR_BUFFER_BIT );

// the size of the box that will get the warped pixels
// With the 7" displays, this will be less than half the screen width
//const int pixelDimensions = ( glConfig.nativeScreenWidth >> 1 );

// Always scissor to the half-screen boundary, but the viewports
// might cross that boundary if the lenses can be adjusted closer
// together.
glViewport(0, 0, glConfig.nativeScreenWidth >> 1, glConfig.nativeScreenHeight );
glScissor ( 0, 0, glConfig.nativeScreenWidth >> 1, glConfig.nativeScreenHeight );

idVec4 color( stereoRender_warpCenterX.GetFloat(), stereoRender_warpCenterY.GetFloat(), stereoRender_warpParmZ.GetFloat(), stereoRender_warpParmW.GetFloat() );
// don't use GL_Color(), because we don't want to clamp
renderProgManager.SetRenderParm( RENDERPARM_COLOR, color.ToFloatPtr() );

GL_SelectTexture( 0 );
stereoRenderImages[0]->Bind();
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );
RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );

idVec4 color2( stereoRender_warpCenterX.GetFloat(), stereoRender_warpCenterY.GetFloat(), stereoRender_warpParmZ.GetFloat(), stereoRender_warpParmW.GetFloat() );
// don't use GL_Color(), because we don't want to clamp
renderProgManager.SetRenderParm( RENDERPARM_COLOR, color2.ToFloatPtr() );

glViewport ( glConfig.nativeScreenWidth >> 1, 0, glConfig.nativeScreenWidth >> 1, glConfig.nativeScreenHeight );
glScissor ( glConfig.nativeScreenWidth >> 1, 0, glConfig.nativeScreenWidth >> 1, glConfig.nativeScreenHeight );

GL_SelectTexture( 0 );
stereoRenderImages[1]->Bind();
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );
RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );
#endif
break;
}

case STEREO3D_SIDE_BY_SIDE:
if ( stereoRender_warp.GetBool() ) {
// this is the Rift warp
// renderSystem->GetWidth() / GetHeight() have returned equal values (640 for initial Rift)
// and we are going to warp them onto a symetric square region of each half of the screen

renderProgManager.BindShader_StereoWarp();

// clear the entire screen to black
// we could be smart and only clear the areas we aren't going to draw on, but
// clears are fast...
glScissor ( 0, 0, glConfig.nativeScreenWidth, glConfig.nativeScreenHeight );
glClearColor( 0, 0, 0, 0 );
glClear( GL_COLOR_BUFFER_BIT );

// the size of the box that will get the warped pixels
// With the 7" displays, this will be less than half the screen width
const int pixelDimensions = ( glConfig.nativeScreenWidth >> 1 ) * stereoRender_warpTargetFraction.GetFloat();

// Always scissor to the half-screen boundary, but the viewports
// might cross that boundary if the lenses can be adjusted closer
// together.
glViewport( ( glConfig.nativeScreenWidth >> 1 ) - pixelDimensions,
( glConfig.nativeScreenHeight >> 1 ) - ( pixelDimensions >> 1 ),
pixelDimensions, pixelDimensions );
glScissor ( 0, 0, glConfig.nativeScreenWidth >> 1, glConfig.nativeScreenHeight );

idVec4 color( stereoRender_warpCenterX.GetFloat(), stereoRender_warpCenterY.GetFloat(), stereoRender_warpParmZ.GetFloat(), stereoRender_warpParmW.GetFloat() );
// don't use GL_Color(), because we don't want to clamp
renderProgManager.SetRenderParm( RENDERPARM_COLOR, color.ToFloatPtr() );

GL_SelectTexture( 0 );
stereoRenderImages[0]->Bind();
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );
RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );

idVec4 color2( stereoRender_warpCenterX.GetFloat(), stereoRender_warpCenterY.GetFloat(), stereoRender_warpParmZ.GetFloat(), stereoRender_warpParmW.GetFloat() );
// don't use GL_Color(), because we don't want to clamp
renderProgManager.SetRenderParm( RENDERPARM_COLOR, color2.ToFloatPtr() );

glViewport( ( glConfig.nativeScreenWidth >> 1 ),
( glConfig.nativeScreenHeight >> 1 ) - ( pixelDimensions >> 1 ),
pixelDimensions, pixelDimensions );
glScissor ( glConfig.nativeScreenWidth >> 1, 0, glConfig.nativeScreenWidth >> 1, glConfig.nativeScreenHeight );

GL_SelectTexture( 0 );
stereoRenderImages[1]->Bind();
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );
RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );
break;
}
// a non-warped side-by-side-uncompressed (dual input cable) is rendered
// just like STEREO3D_SIDE_BY_SIDE_COMPRESSED, so fall through.
case STEREO3D_SIDE_BY_SIDE_COMPRESSED:
GL_SelectTexture( 0 );
stereoRenderImages[0]->Bind();
GL_SelectTexture( 1 );
stereoRenderImages[1]->Bind();
GL_ViewportAndScissor( 0, 0, renderSystem->GetWidth(), renderSystem->GetHeight() );
RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );

GL_SelectTexture( 0 );
stereoRenderImages[1]->Bind();
GL_SelectTexture( 1 );
stereoRenderImages[0]->Bind();
GL_ViewportAndScissor( renderSystem->GetWidth(), 0, renderSystem->GetWidth(), renderSystem->GetHeight() );
RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );
break;

case STEREO3D_TOP_AND_BOTTOM_COMPRESSED:
GL_SelectTexture( 1 );
stereoRenderImages[0]->Bind();
GL_SelectTexture( 0 );
stereoRenderImages[1]->Bind();
GL_ViewportAndScissor( 0, 0, renderSystem->GetWidth(), renderSystem->GetHeight() );
RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );

GL_SelectTexture( 1 );
stereoRenderImages[1]->Bind();
GL_SelectTexture( 0 );
stereoRenderImages[0]->Bind();
GL_ViewportAndScissor( 0, renderSystem->GetHeight(), renderSystem->GetWidth(), renderSystem->GetHeight() );
RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );
break;

case STEREO3D_INTERLACED:
// every other scanline
GL_SelectTexture( 0 );
stereoRenderImages[0]->Bind();
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );

GL_SelectTexture( 1 );
stereoRenderImages[1]->Bind();
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );

GL_ViewportAndScissor( 0, 0, renderSystem->GetWidth(), renderSystem->GetHeight()*2 );
renderProgManager.BindShader_StereoInterlace();
RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );

GL_SelectTexture( 0 );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

GL_SelectTexture( 1 );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

break;

case STEREO3D_VR920:
if (old3Dmode!=STEREO3D_VR920)
VR920_StartStereo3D();
static int vr920eye = 0;
if (!vr920eye && (vr920StereoHandle!=INVALID_HANDLE_VALUE)) {
IWRSTEREO_SetLR(vr920StereoHandle, 0);
GL_SelectTexture( 0 );
stereoRenderImages[0]->Bind();
GL_SelectTexture( 1 );
stereoRenderImages[1]->Bind();
GL_ViewportAndScissor( 0, 0, renderSystem->GetWidth(), renderSystem->GetHeight() );
RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );
} else {
IWRSTEREO_SetLR(vr920StereoHandle, 1);
GL_SelectTexture( 0 );
stereoRenderImages[1]->Bind();
GL_SelectTexture( 1 );
stereoRenderImages[0]->Bind();
GL_ViewportAndScissor( 0, 0, renderSystem->GetWidth(), renderSystem->GetHeight() );
RB_DrawElementsWithCounters( &backEnd.unitSquareSurface );
}
vr920eye = !vr920eye;
break;
}
old3Dmode = renderSystem->GetStereo3DMode();

// debug tool
RB_DrawFlickerBox();

// make sure the drawing is actually started
//qglFlush();

// we may choose to sync to the swapbuffers before the next frame

// stop rendering on this thread
uint64 backEndFinishTime = Sys_Microseconds();
backEnd.pc.totalMicroSec = backEndFinishTime - backEndStartTime;
}
No RepliesBe the first to reply