Jump to content
The Dark Mod Forums
Sign in to follow this  
cabalistic

I'm working on a VR version - early alpha

Recommended Posts

There is no overhead - you have to transfer the model matrices, anyway. Whether by glUniform or buffer. In fact, buffer upload is most likely faster, because you only have a single upload for the batch instead of repeatedly setting the glUniform. It takes a little more GPU memory, but it's not dramatic.

Note that UBOs have an array size limit of I think around 500 or so. For larger collections, you want to use SSBOs, which is what I did in my experiments.

  • Like 1

Share this post


Link to post
Share on other sites
10 minutes ago, cabalistic said:

There is no overhead - you have to transfer the model matrices, anyway. Whether by glUniform or buffer. In fact, buffer upload is most likely faster, because you only have a single upload for the batch instead of repeatedly setting the glUniform. It takes a little more GPU memory, but it's not dramatic.

Note that UBOs have an array size limit of I think around 500 or so. For larger collections, you want to use SSBOs, which is what I did in my experiments.

I think that even cap of 500 draws per call is not a problem. It would be awesome sauce to achieve even that.

But it will also require a separate depth shader for uniform blocks? Or unify depth pass so that it always uses a UBO, single or multi draw?

Now that we're using GLSL includes, that matrix stuff is shared across all shaders. I suppose we'll need some kind of #ifdef for shaders with UBO model/view matrices and regular uniforms? On the other hand, since it's already centralized like that, we might as well switch them all to UBO.

Share this post


Link to post
Share on other sites

Yes, you need a new set of shaders, no way around that. I'm not sure if you can make non-multipass use that same set on a GL3 feature base. Anyway, I used a single depth multi-draw command for all non-transparent objects, and then rendered the transparent ones classically on top. Since they use actual textures for drawing, it's not as easy to get them into a multi-draw call. But even if you do, since their fragment shader is much more costly, it still makes sense to have them separated from the solid ones and use a specialized fragment shader.

  • Like 1

Share this post


Link to post
Share on other sites
1 minute ago, cabalistic said:

Yes, you need a new set of shaders, no way around that. I'm not sure if you can make non-multipass use that same set on a GL3 feature base. Anyway, I used a single depth multi-draw command for all non-transparent objects, and then rendered the transparent ones classically on top. Since they use actual textures for drawing, it's not as easy to get them into a multi-draw call. But even if you do, since their fragment shader is much more costly, it still makes sense to have them separated from the solid ones and use a specialized fragment shader.

What about per-material (and potentially per-surface) polygon offset?

Share this post


Link to post
Share on other sites

Anything that applied an offset, I rendered separately (classically). Eventually, I think we need to migrate away from using the GL functions and doing our own offsetting in vertex shaders based on parameters. For one, it enables to use them in multi draws, and for another, they would actually be predictable. The GL polygon offsets are not - their effects can vary among GPUs and drivers.

  • Like 2

Share this post


Link to post
Share on other sites

I finally fixed the speed bug and did a quick test with MultiDraw.

It seems the nVidia driver does a good job of batching draw calls internally. It took 50K draws per frame (and resolution down to 540p) to start seeing difference in fps. You might get a slightly different result on a 1070 but for now it looks like a micro optimization.

Share this post


Link to post
Share on other sites

It's not about batching - it's about avoiding driver call overhead. Just to be clear, what it achieves is save CPU time in the backend, which in turn will get data to render to the GPU faster and avoid that the GPU needlessly idles. In order to profit from this, the GPU needs to be starving in the first place. If you have a poor GPU and run it at demanding settings, then yeah, it's possible you won't see much of an effect, because it wasn't the bottleneck. (It's also possible you're doing something wrong - you'd have to measure carefully with nSight to try and catch what's going on.)

But in my experiments, where I replaced depth and stencil shadow draws with multi draws, the effects were pretty clear. They cut down CPU time for those areas significantly and as a result allowed the GPU to render more quickly. Of course, stencil (and particularly depth) are often not the most significant parts of the scene, so the overall effect on FPS is not gigantic (but it was still measurable).

  • Like 1

Share this post


Link to post
Share on other sites

How do you use nSight to profile? I tried 'Capture frame' but it's just stuck on 30% eating cpu forever. I tried leaving it for a day but found the laptop rebooted in the evening.

Share this post


Link to post
Share on other sites

Capture frame should just work. If it's not, I'm afraid I don't know how to help you with that. You could try the standalone version of nSight, it worked better for me than the Visual Studio integrated one.

  • Like 1

Share this post


Link to post
Share on other sites
15 hours ago, duzenko said:

How do you use nSight to profile? I tried 'Capture frame' but it's just stuck on 30% eating cpu forever. I tried leaving it for a day but found the laptop rebooted in the evening.

You can also try renderDoc it has the benefit that it is GPU and OS agnostic. 

 

Handmade hero coder experience with renderDoc 

 

Edited by HMart
  • Like 2

Share this post


Link to post
Share on other sites

Hi, I'm new to this forum and I must say not a newbie but at an introductory level about graphics programming, and also a little C++ experience.

(I did code some things graphics-related in the past and dedicated a lot of time to inform myself of CG stuff.  But my "total hours" coding CG are really low.  Having read other users posts in this forum I see that right now I only reach the soles of their shoes).

What I'm about to say maybe was already spoken in this topic or another, but ... what about Vulkan?  (for achieving more 3D performance)

I've read talks about this between @HMart and @cabalisticand others, I'm aware of the implications and cabalistic's view that modern OpenGL could be a better choice for "porting" the renderer.

One of those was that modern OpenGL would need converting all shaders in TDM.  Does that apply to porting to Vulkan, too?

I'm trying to figure out which of these options would be "the shortest path" towards porting the renderer:

  • Current OpenGL -> Modern OpenGL -> Vulkan
  • Current OpenGL -> Vulkan
Edited by No Trickster
  • Like 1

Share this post


Link to post
Share on other sites

Yes, Vulkan would need porting shaders, too. Actually, the porting itself has been completed in the meantime, but Vulkan would need more - Vulkan requires compiled shaders in the SPIR-V format, so the entire pipeline for shaders would have to change somewhat.

The problem is, with Vulkan you'd basically have to completely reimplement the entire rendering pipeline and properly decouple some additional parts of the engine, all of which is a massive undertaking (though very educational, I'm sure). Modern OpenGL techniques, on the other hand, can be integrated piece by piece and coexist with the existing pipeline, so much more manageable. It's also doubtful that Vulkan would deliver significant improvements over modern OpenGL, because the engine has more glaring bottlenecks.

So, given the effort required and the expected negligible gains just make a Vulkan port rather impractical. Not saying that it wouldn't be fun to do, just not practical :)

  • Like 2

Share this post


Link to post
Share on other sites

I poked at the repo and was thrilled to see there are recent commits! How is progress on this going? Thief in VR has been one of my top wishlist items ever since I tried the CV1!

Share this post


Link to post
Share on other sites

It's going slow, but steady. Since Valve finally published on OpenXR runtime, I decided that I would go the OpenXR route for the new VR version, which I think makes the most sense. Unfortunately OpenXR is, like every Khronos API before it, an absolute pain to use, particularly compared to the simplicity that is OpenVR. So it's taking longer to learn and implement :D

  • Like 2

Share this post


Link to post
Share on other sites
Quote

like every Khronos API before it, an absolute pain to use

Yep, thats design by corporate committee for you. Unfortunately my graphics/game programming stopped many many years ago so I can't be much help with projects like this these days, but I think its great that its still being explored!

Share this post


Link to post
Share on other sites

I didn't want to necro the thread before for no reason, but it's recent now.  So I just want to say I'm really looking forward to this, and I love that you're still putting time into it!  OpenXR seems to be the way to go, so I'm sorry to hear it's a PITA.  But I hope it'll all be worth it in the end!

Edited by Inimitable
  • Like 1

Share this post


Link to post
Share on other sites

I'll probably open a new thread once I believe the new version to be ready for alpha testing. But since you're interested, I thought I might give a status update on my progress in the meantime:

  • all the backend rendering improvements I wanted to do before returning to VR are now merged to the base game and to be released in 2.09. This makes my life significantly easier in maintaining the VR mod, because I don't have to juggle additional rendering overhauls when merging changes from the base game.
  • I have the basic OpenXR setup done and can successfully initialize a VR session with it and acquire all the rendering resources I need.
  • Next up is getting actual rendering to the headset - this won't be a stereo rendering, yet, I just want to get some output so I can verify that what I've done so far actually works :D

The roadmap / vision for the first new release is roughly to get a decently usable keyboard/mouse sitting experience working. In particular, I hope to have the following improvements over the initial version I released:

  • usable UI, i.e. rendered to a virtual screen instead of glued to the eyes
  • decouple vertical mouse movement from the view, but possibly introduce an (optional) reticule to indicate the mouse's aim

Let's see how it goes. Can't promise a particular timeline, but I'll try to get something workable asap :)

  • Like 2

Share this post


Link to post
Share on other sites

This is really great news. I still pop into the old build from time to time. I admire your dedication, Cabalistic. It's been a few years now and I've seen similar sorts of projects fade away more often than not. Your work is much appreciated. 

Share this post


Link to post
Share on other sites

Baby steps: I've got headset tracking working, I think. It looks good in the 2D view, i.e. camera follows headset movement and orientation. Still no stereo rendering, though. That's the next step; in principle it shouldn't be too hard since all elements are now in place. However, I expect a lot of subtle rendering bugs where the contents of the eyes don't quite fit due to some obscure values that haven't properly been recalculated for the eye views :D

  • Like 2

Share this post


Link to post
Share on other sites

So, I got stereoscopic rendering working. Unfortunately, I'm currently unable to get OpenXR working reliably with SteamVR. It's throwing runtime errors, and generally seems to cause significant CPU overhead. It's entirely possible I'm doing something wrong, but the same code seems to work fine with the Oculus runtime, so this might also be early adopter pain on the SteamVR side. I'll need to dig a little deeper to determine whether I need to open bug reports or not.

Anyway, for the time being I added an OpenVR backend and am trying to keep them in sync. That shouldn't be too hard as long as I'm not diving into input handling.

Issues I'm currently focussing on:

  • Light scissors. They are vital for performance, but I need to recalculate them for each eye view, and if done improperly, they can lead to flickering lighting or even mismatched lighting between the eyes. It should be a fairly simple calculation, but oddly enough I still struggle with some border cases. Still, might be good enough for a first alpha.
  • Subviews, particularly mirrors, are broken, which is expected, since they need a different approach to adjust them to the eye views. Should hopefully not be too complicated to fix.

Other than that, I think the version I currently have is already a massive improvement over the previous alpha. UI (both menu and ingame elements) render to a virtual screen that is placed slightly in front of you. Not the most immersive solution for the ingame elements, as now the lightgem basically "floats" in the air in front of you, but it was a simple solution that makes everything usable in VR, so a good starting point, I think.

Also, I uncoupled the mouse vertical movement (pitch) from the VR view, which makes it a lot more tolerable to navigate in VR, I think. Downside is that it makes it a little harder to aim and pick up stuff with the mouse, as you don't have any indication where you are pointing at until an item lights up. Will need to figure out a way to render a simple 3D pointer target to indicate mouse aim.

Performance is alright; I'd hoped for more, but current headsets have increased the resolution quite a bit, and TDM is ultimately fill-rate limited. That means there's little (if any) room for AA or supersampling, and you better keep expensive effects like soft shadows or SSAO off - the latter isn't really that important for VR, anyway. I played through "New Job" with my Index set at 120 Hz and could keep that framerate most of the time, but there were a few instances with reprojection. Not too bad, though, but this is with an RTX 2080 Ti, so... There's still one relatively simple optimization that I can do that should save a bit of fillrate.

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites

I stumbled upon another little problem with the heatHaze shaders. They use some projection math to calculate their effect, and that does not play well in VR - it leads to eye bleed. I'm not familiar enough with how heatHaze works to know if there is a "proper" way to fix it for VR, but for the moment I've replaced the dynamic projection math with a fixed constant. Looks okayish, good enough for now, I hope.

I think I'm getting close to a new alpha version that I'd feel good enough to release :)

  • Like 3
  • Thanks 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...