Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 6 of 6

Thread: Using glViewportArray for stereoscopic rendering on AMD cards

  1. #1
    Junior Member Newbie glnoob's Avatar
    Join Date
    Sep 2010
    Posts
    4

    Using glViewportArray for stereoscopic rendering on AMD cards

    I've implemented single-pass stereoscopic rendering using Nvidia's extension to double up the geometry and draw to a second viewport:
    https://www.khronos.org/registry/Ope..._rendering.txt
    https://www.khronos.org/registry/Ope...ortArray.xhtml

    Now I am writing a rendering path for AMD and Intel graphics, and I would like to optimize it as much as possible. I plan to set two viewports and then render all objects twice, once in each viewport. Without the Nvidia extension, what is the normal way that you are supposed to select a viewport for rendering?

  2. #2
    Junior Member Newbie glnoob's Avatar
    Join Date
    Sep 2010
    Posts
    4
    From the spec:
    Multiple viewports are available and are numbered zero through the value of MAX_VIEWPORTS minus one. If a geometry shader is active and writes to gl_- ViewportIndex, the viewport transformation uses the viewport corresponding to the value assigned to gl_ViewportIndex taken from an implementationdependent primitive vertex. If the value of the viewport index is outside the range zero to the value of MAX_VIEWPORTS minus one, the results of the viewport transformation are undefined. If no geometry shader is active, or if the active geometry shader does not write to gl_ViewportIndex, the viewport numbered zero is used by the viewport transformation.
    It appears that the only way you can specify a viewport to render to is by outputting a value in a geometry shader. Is that correct? As I understand it geometry shaders are very slow on discrete cards.

  3. #3
    Advanced Member Frequent Contributor arekkusu's Avatar
    Join Date
    Nov 2003
    Posts
    889
    Quote Originally Posted by glnoob View Post
    It appears that the only way you can specify a viewport to render to is by outputting a value in a geometry shader.
    Or with ARB_shader_viewport_layer_array or GL_NV_viewport_array2 or AMD_vertex_shader_viewport_index.


  4. #4
    Senior Member OpenGL Lord
    Join Date
    May 2009
    Posts
    6,046
    As I understand it geometry shaders are very slow on discrete cards.
    It all depends on what you're trying to do. Compared to the way you're rendering now, it would probably be faster to use a Geometry Shader. Why? Fewer draw calls and state changes.

    Your current solution is to render everything twice. My alternative is to render everything once, but have the GS emit two primitives. Now, that could cause performance problems, since the GS would have to transform each triangle twice in sequence (not to mention other sequential issues). You can side-step most of that by using GS instancing.

    Your GS would have two instances, and each instance would emit a single primitive to a single viewport/layer. This allows us to recover some parallelism, and can better allow the implementation to use the available resources.

    The problematic part of your ARB_shader_viewport_layer_array (or its equivalents) version is that it involves rendering every object twice, almost certainly with a state change between them (presumably, a uniform value describing which viewport/layer to use). You can avoid that in one of two ways.

    1. You can use instanced rendering, rather than render twice. You would use the `gl_InstanceID` to tell which viewport/layer for the VS to output to. Of course, this can only work if you're not already using instancing for something else.

    2. You can use multi-draw rendering and `gl_DrawID`, which is available through OpenGL 4.6 or ARB_shader_draw_parameters. Here, you use the multi-draw rendering command to render the same object twice. `gl_DrawID` would be used to detect which viewport/layer to write to.

    Note that I haven't implemented or profiled any of these, so feel free to take this advice with a grain of salt.

  5. #5
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    4,511
    Quote Originally Posted by Alfonse Reinheart View Post
    My alternative is to render everything once, but have the GS emit two primitives. Now, that could cause performance problems, since the GS would have to transform each triangle twice in sequence (not to mention other sequential issues). You can side-step most of that by using GS instancing.

    Your GS would have two instances, and each instance would emit a single primitive to a single viewport/layer. This allows us to recover some parallelism, and can better allow the implementation to use the available resources.
    I've done that on NVidia (w/ and w/o geom shader instancing) and the results weren't pretty. This is about the same speed as drawing the geometry twice from the CPU.

    One option the OP might consider checking out on the GPUs you care about is OVR_multiview / OVR_multiview2. From what I gather, these are like NV_stereo_view_rendering in that you only submit the geometry once, but it let's you modify more varying data per viewport than just gl_Position.x, potentially supports more than 2 viewports, and doesn't require you to use geometry shaders (which are just flat slow if you're pumping more than a small amount of geometry through them per frame).

    NVidia just add support for these 2 OVR extensions in their latest drivers. On Pascal, reportedly this internally and transparently instances the geometry (per viewport), but supposedly on Turing / RTX it sounds like this runs a single, wide, unified geometry pass for all viewports.

    UPDATE: Checking gpuinfo.org for OVR_multiview reports, it looks like NVidia may be the only one out there with this support on desktop GL GPUs.

  6. #6
    Newbie Newbie
    Join Date
    Oct 2018
    Posts
    1
    Did some work around “stereo instancing” a couple of years ago (before the "NV_stereo_view_rendering" extension):

    Efficient Stereoscopic Rendering of Building Information Models (BIM)
    http://jcgt.org/published/0005/03/01/paper-lowres.pdf

    -Paper includes GLSL shader-code for several options, also how to do it without any extension for viewport selection in vertex shader
    -Only used this on NVIDIA with “NV_viewport_array2”, but should be the same on AMD with “AMD_vertex_shader_viewport_index”
    -Paper also includes code on how to combine this with conventional instancing (basically, using the modulus operator (%) to distinguish between left and right instances)

    Please let me know if you need some more info!

    /Mikael

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •