NVIDIA Single Pass Stereo Rendering

Design / architecture / roadmap discussions related to future of Ogre3D (version 2.0 and above)
Post Reply
xrgo
OGRE Expert User
OGRE Expert User
Posts: 964
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 55

NVIDIA Single Pass Stereo Rendering

Post by xrgo » Thu Oct 26, 2017 5:15 pm

Hello! in my endless search for VR performance I started digging in the Nvidia VRWorks stuffs, and one thing that seems to be very powerful and simple to integrate is Single Pass Stereo Rendering
So if you're in to VR this can be very interesting for you.

But I've encountered some problems...

first some context. I've downloaded the VRWorks Graphics SDK 2.5, there's a sample on single pass stereo rendering with a pdf. Not sure if I can post the whole code/doc here since you need an account to download... so I'll be posting just the relevant stuffs.
BTW, you can test all this stuffs without any HMD, you just need a recent nvidia card, I have a 1070.

there are two options to do this, one is rendering each eye in to a separate layer of a texture array, but I don't think Ogre supports this... so the second option is to render each eye side by side in the same texture, I am trying this last one.

I am using OpenGL, so to enable the feature you just have to add the extensions to your vertex shader:
(I just added them to a @piece( custom_vs_uniformDeclaration ))

Code: Select all

#extension GL_NV_viewport_array2: require
#extension GL_NV_stereo_view_rendering: require
this will enable the use of a second gl_Position and a second gl_ViewportMask... so I modifed the vertex shader around line ~137 (values I copypasted from the docs)

Code: Select all

@property( !hlms_dual_paraboloid_mapping )
	gl_Position = worldPos * passBuf.viewProj + vec4(0.2, 0, 0, 0);
	gl_SecondaryPositionNV = worldPos * passBuf.viewProj - vec4(0.2, 0, 0, 0);
	gl_ViewportMask[0] = 1;
	gl_SecondaryViewportMaskNV[0] = 2;
@end
and WALLA!! things looks double!!!!!!!! OMFG!!
Image

so, the instance part seems to be working, very easy!
but they are in the same "space", so you need to render each eye in to a different viewport of the texture, this is suppose to be done with this:

Code: Select all

glViewportIndexedf(0, 0, 0, width, height);
glViewportIndexedf(1, width, 0, width, height);
but... it does nothing =(, I tried putting those lines at the beginning, and in all the framelistener methods, looks always the same.

I need help! maybe someone that's also interested in VR want to try to integrate this? seems reeaaally easy, I must be doing something stupid. I can send the relevant files via private message if you don't care to make an nvidia developer account.

Also noticed glViewportIndexedf needs opengl 4.1, and ogre says it uses 3.3, but I asked dark_sylinc and says that opengl works that way and it should work anyways, but just in case I forced version 430 in the file CrossPlatformSettings_piece_all.glsl of the hlms shader templates.

Cheers!!
0 x

al2950
OGRE Expert User
OGRE Expert User
Posts: 1163
Joined: Thu Dec 11, 2008 7:56 pm
Location: Bristol, UK
x 63

Re: NVIDIA Single Pass Stereo Rendering

Post by al2950 » Fri Oct 27, 2017 9:28 am

Sadly I have no advice, but I am very interested in what you achieve. Although I use DirectX so tempted to try the Dx route parallel to your GL route :)
0 x

zxz
Greenskin
Posts: 139
Joined: Sat Apr 16, 2016 9:25 pm
x 5

Re: NVIDIA Single Pass Stereo Rendering

Post by zxz » Fri Oct 27, 2017 11:33 am

This is very interesting.

I saw nvidia's presentation on simultaneous stereo rendering (during the 1080 unveiling), but I couldn't find the relevant extensions at the time, so I let it pass.

Could the viewport issue be caused by Ogre's glViewport calls breaking your multiple viewport settings?
0 x

xrgo
OGRE Expert User
OGRE Expert User
Posts: 964
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 55

Re: NVIDIA Single Pass Stereo Rendering

Post by xrgo » Fri Oct 27, 2017 6:43 pm

zxz wrote:Could the viewport issue be caused by Ogre's glViewport calls breaking your multiple viewport settings?
yes! that was it! thanks
now its kinda working, for some reason the obvious values for width and height dont work well, got to figure out the correct values yet
0 x

xrgo
OGRE Expert User
OGRE Expert User
Posts: 964
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 55

Re: NVIDIA Single Pass Stereo Rendering

Post by xrgo » Fri Oct 27, 2017 8:53 pm

So I changed this part of file OgreGL3PlusRenderSystem.cpp, line ~1520

Code: Select all

        //OGRE_CHECK_GL_ERROR(glViewport(x, y, w, h));

	glViewportIndexedf(0, x, y, 0.5*w, h);
	glViewportIndexedf(1, 0.5*w, y, 0.5*w, h);
and as I mentioned before it kinda works...
Image
as you can see, now I have 2 viewports (sky uses other hlms so its not instanced... yet).. but they both stretched half screen, I tried many values glViewportIndexedf and I couldn't make it work as it should.
I tried *vec2(0.5,1.0) via post process, but the right side its always black. I don't understand yet whats going on :P, but I am pretty close :D

EDIT: it was the the quad pass for post process, I remove it and it works! now I have make it work so the glViewportIndexedf works just in the scene pass I want
0 x

xrgo
OGRE Expert User
OGRE Expert User
Posts: 964
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 55

Re: NVIDIA Single Pass Stereo Rendering

Post by xrgo » Sat Oct 28, 2017 3:02 am

some progress:
I workarounded the viewport pass problem by doing this in GL3PlusRenderSystem::_setViewport

Code: Select all

			if ( !vp->getSkiesEnabled() ) {
				glViewportIndexedf(0, x, y, 0.5*w, h);
				glViewportIndexedf(1, 0.5*w, y, 0.5*w, h);
			}
			else {
				OGRE_CHECK_GL_ERROR(glViewport(x, y, w, h));
			}
basically I am using an unused (for me) bool flag that viewports have to detect if I want to do stereoviewport stuffs, and for modify that flag in you app code:

Code: Select all

    Ogre::CompositorNode* renderingNode = mMainWorkspace->findNode( "MainEngineRenderingNode" );
    Ogre::CompositorPassScene* passScene = static_cast<Ogre::CompositorPassScene*>( renderingNode->_getPasses().at(1) ); //0 is clear
    passScene->getViewport()->setSkiesEnabled( false );
also wrap the shader code with @property( !hlms_shadowcaster ) so shadows don't get instanced

Code: Select all

	@property( !hlms_shadowcaster )
		gl_SecondaryPositionNV = worldPos * passBuf.viewProj - vec4(0.64, 0, 0, 0);
		gl_ViewportMask[0] = 1;
		gl_SecondaryViewportMaskNV[0] = 2;
	@end
so its mostly working now, still have to test a lot more
0 x

al2950
OGRE Expert User
OGRE Expert User
Posts: 1163
Joined: Thu Dec 11, 2008 7:56 pm
Location: Bristol, UK
x 63

Re: NVIDIA Single Pass Stereo Rendering

Post by al2950 » Sat Oct 28, 2017 8:24 am

Now the big question, what performance improvement do you get!?
0 x

xrgo
OGRE Expert User
OGRE Expert User
Posts: 964
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 55

Re: NVIDIA Single Pass Stereo Rendering

Post by xrgo » Sat Oct 28, 2017 2:34 pm

al2950 wrote:
Sat Oct 28, 2017 8:24 am
Now the big question, what performance improvement do you get!?
Yes! I will report on Monday because I have the vibe/cv1 at the office, I just have a dk2 here at home
0 x

xrgo
OGRE Expert User
OGRE Expert User
Posts: 964
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 55

Re: NVIDIA Single Pass Stereo Rendering

Post by xrgo » Sun Oct 29, 2017 6:35 pm

I added a property so this shader things don't mess with my app when no hmd is present.
So far working great, reflection looked weird/flat so I did this in the pixel shader:

Code: Select all

	@property( single_pass_stereo )
		vec3 viewDir	= normalize( -(inPs.pos - vec3( float( gl_FragCoord.x > @value( half_screen_width ) )*0.064, 0, 0 ) ) );
	@end
	@property( !single_pass_stereo )
		vec3 viewDir	= normalize( -inPs.pos );
	@end
so the viewDir of the right side of the viewport get adjusted as much as I offseted the right instance (0.064)

the only problem I (think I) have left is that I use many render to texture to simulate cameras, mirrors, etc, and I would like to not use the extension in those passes.. in other words use a different shader with property( single_pass_stereo ) as 0

EDIT: solved that last problem with the same skyflag that before:

Code: Select all

void yPbsListener::preparePassHash( const Ogre::CompositorShadowNode *shadowNode,
                              bool casterPass, bool dualParaboloid,
                              Ogre::SceneManager *sceneManager, Ogre::Hlms *hlms ){

    if( ...isHMDConnected ){
        hlms->_setProperty( "single_pass_stereo", !sceneManager->getCurrentViewport()->getSkiesEnabled() );
    }
    ....
Now I just need to test a lot and compare performance =D
0 x

xrgo
OGRE Expert User
OGRE Expert User
Posts: 964
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 55

Re: NVIDIA Single Pass Stereo Rendering

Post by xrgo » Mon Oct 30, 2017 3:24 pm

well.... bad news... I didn't get much performance increase, maybe 10% at best, that sucks... at least it something so I'll keep it. still have to double check I am not doing something stupid =)

another change I had to make:

CV1 right eye looked really bad, so I had to pass the viewProjMat for the right eye camera (that its no being used) to the passBuf, and use that for the secondary gl_position
0 x

zxz
Greenskin
Posts: 139
Joined: Sat Apr 16, 2016 9:25 pm
x 5

Re: NVIDIA Single Pass Stereo Rendering

Post by zxz » Mon Oct 30, 2017 4:44 pm

What's your GPU utilization? Perhaps you are GPU limited, and thus only see 10% improvement. Have you measured the CPU utilization before/after the change?
0 x

Post Reply