vectorgraphics / asymptote

2D & 3D TeX-Aware Vector Graphics Language
https://asymptote.sourceforge.io/
GNU General Public License v3.0
533 stars 89 forks source link

Error initializing offscreen context: Depth=0 when render != 0 #392

Closed hshackle closed 10 months ago

hshackle commented 10 months ago

I'm running into problems with Aymptote if I try to run it with settings.render set to anything other than 0. I am running Asymptote 2.86-2 on Arch Linux, downloaded from the Arch repository. I took the following minimal example from the Asymptote tutorial:

settings.outformat="png";
settings.render = 16;
import three;
size(1cm,0);
draw((0, 0, 0) -- (1, 1, 1), linewidth(2pt)); 

and running asy -vv test.asy gives the following output:

Using configuration directory /home/hshackle/.asy
Using history /home/hshackle/.asy/history
Welcome to Asymptote version 2.86git
cd /home/hshackle
Processing test
Loading plain from /usr/share/asymptote/plain.asy
Including plain_constants from /usr/share/asymptote/plain_constants.asy
Loading version from /usr/share/asymptote/version.asy
Including plain_strings from /usr/share/asymptote/plain_strings.asy
Including plain_pens from /usr/share/asymptote/plain_pens.asy
Including plain_paths from /usr/share/asymptote/plain_paths.asy
Including plain_filldraw from /usr/share/asymptote/plain_filldraw.asy
Including plain_margins from /usr/share/asymptote/plain_margins.asy
Including plain_picture from /usr/share/asymptote/plain_picture.asy
Loading plain_scaling from /usr/share/asymptote/plain_scaling.asy
Loading simplex from /usr/share/asymptote/simplex.asy
Loading plain_bounds from /usr/share/asymptote/plain_bounds.asy
Including plain_scaling from /usr/share/asymptote/plain_scaling.asy
Including plain_prethree from /usr/share/asymptote/plain_prethree.asy
Including plain_Label from /usr/share/asymptote/plain_Label.asy
Including plain_arcs from /usr/share/asymptote/plain_arcs.asy
Including plain_boxes from /usr/share/asymptote/plain_boxes.asy
Including plain_shipout from /usr/share/asymptote/plain_shipout.asy
Including plain_markers from /usr/share/asymptote/plain_markers.asy
Including plain_arrows from /usr/share/asymptote/plain_arrows.asy
Including plain_debugger from /usr/share/asymptote/plain_debugger.asy
Loading test.asy from test.asy
Loading three from /usr/share/asymptote/three.asy
Loading math from /usr/share/asymptote/math.asy
Loading embed from /usr/share/asymptote/embed.asy
Including three_light from /usr/share/asymptote/three_light.asy
Including three_surface from /usr/share/asymptote/three_surface.asy
Loading bezulate from /usr/share/asymptote/bezulate.asy
Loading interpolate from /usr/share/asymptote/interpolate.asy
Loading graph_splinetype from /usr/share/asymptote/graph_splinetype.asy
Including three_margins from /usr/share/asymptote/three_margins.asy
Including three_tube from /usr/share/asymptote/three_tube.asy
Including three_arrows from /usr/share/asymptote/three_arrows.asy
adjusting camera to (4.98354040694537,4.00353062344247,2.04114065779814)
adjusting target to (0.483540406945365,0.50353062344247,0.541140657798142)
Allocating osmesa_buffer of size 1024x768x4x1
Offscreen context settings: Depth=0 Stencil=0 Accum=0
Error initializing offscreen context: Depth=0

There is no issue if I use settings.render = 0, but this leads to a very low-quality image.

johncbowman commented 10 months ago

Check asy --version. You need to install the missing OpenGL libraries and reconfigure.

hshackle commented 10 months ago

Sorry, I'm not sure if I follow - running asy --version gives:

Asymptote version 2.86git [(C) 2004 Andy Hammerlindl, John C. Bowman, Tom Prince]

ENABLED OPTIONS:
V3D      3D vector graphics output
WebGL    3D HTML rendering
OpenGL   3D OSMesa offscreen rendering
SSBO     GLSL shader storage buffer objects
GSL      GNU Scientific Library (special functions)
FFTW3    Fast Fourier transforms
XDR      External Data Representation (portable binary file format for V3D)
CURL     URL support
LSP      Language Server Protocol
Readline Interactive history and editing
Sigsegv  Distinguish stack overflows from segmentation faults
GC       Boehm garbage collector
threads  Render OpenGL in separate thread

DISABLED OPTIONS:
Eigen    Eigenvalue library

I would have expected OpenGL to be listed under "disabled options" if I was missing libraries. For what it's worth, I ran glxgears and glmark2 and both appear to run fine (I do not know whether these are relevant diagnostics - I just saw them appear in discussion before). I have freeglut 3.4.0-1 installed from the Arch repo.

user202729 commented 6 months ago

Looks like same issue as #361 .

For me, it works if the version is

$ asy --version
Asymptote version 2.87-25 [(C) 2004 Andy Hammerlindl, John C. Bowman, Tom Prince]

ENABLED OPTIONS:
V3D      3D vector graphics output
WebGL    3D HTML rendering
OpenGL   3D OpenGL rendering

On Arch Linux, for some reason the asymptote package uses offscreen rendering by default. As a workaround, asymptote-git can be used.

johncbowman commented 6 months ago

If asy --version shows

OpenGL 3D OSMesa offscreen rendering

it must have been configured with --enable-offscreen, which is only intended for headless servers with no GPU card (like http://asymptote.ualberta.ca/).

user202729 commented 6 months ago

Yes, but the no-offscreen rendering has a quirk that a window pops up every time I compile asymptote.

(edit: -iconify and -glOptions exist.)

Which library would I need to install to get off-screen rendering to work? (I assume OSMesa? but I already have it installed:

$  ls /usr/lib/libOSMesa* -1
/usr/lib/libOSMesa.so
/usr/lib/libOSMesa.so.8
/usr/lib/libOSMesa.so.8.0.0

as mentioned above I was just using the standard asymptote package on Arch Linux)

glmark2 seems to work fine off-screen as well:

$ glmark2 --off-screen
=======================================================
    glmark2 2023.01
=======================================================
    OpenGL Information
    GL_VENDOR:      Intel
    GL_RENDERER:    Mesa Intel(R) HD Graphics 5500 (BDW GT2)
    GL_VERSION:     4.6 (Compatibility Profile) Mesa 23.2.1-arch1.2
    Surface Config: buf=32 r=8 g=8 b=8 a=8 depth=24 stencil=0 samples=0
    Surface Size:   800x600 windowed
=======================================================
[build] use-vbo=false: FPS: 2552 FrameTime: 0.392 ms
[build] use-vbo=true: FPS: 3834 FrameTime: 0.261 ms
[texture] texture-filter=nearest: FPS: 2766 FrameTime: 0.362 ms
[texture] texture-filter=linear: FPS: 2575 FrameTime: 0.388 ms

Edit: For now, https://tex.stackexchange.com/questions/261101/how-do-i-run-asymptote-in-batch-mode-without-creating-windows gives a workaround -- create a virtual buffer X server.

user202729 commented 6 months ago

With some debugging work, I have reduced the problem to:

#include <iostream>
#include <cstdlib>
#include <GL/osmesa.h>

using namespace std;

int screenWidth = 800;
int screenHeight = 600;
unsigned char* osmesa_buffer;
OSMesaContext ctx;

int main() {
    cout << "Allocating osmesa_buffer of size " << screenWidth << "x"
             << screenHeight << "x4x" << sizeof(GLubyte) << endl;
    osmesa_buffer = new unsigned char[screenWidth * screenHeight * 4 * sizeof(GLubyte)];
    if (!osmesa_buffer) {
        cerr << "Cannot allocate image buffer." << endl;
        exit(-1);
    }

    const int attribs[] = {
        OSMESA_FORMAT, OSMESA_RGBA,
        OSMESA_DEPTH_BITS, 16,
        OSMESA_STENCIL_BITS, 0,
        OSMESA_ACCUM_BITS, 0,
        OSMESA_PROFILE, OSMESA_CORE_PROFILE,
        //OSMESA_PROFILE, OSMESA_COMPAT_PROFILE,
        OSMESA_CONTEXT_MAJOR_VERSION, 4,
        OSMESA_CONTEXT_MINOR_VERSION, 3,
        0, 0
    };

    ctx = OSMesaCreateContextAttribs(attribs, NULL);
    //ctx = OSMesaCreateContextExt(OSMESA_RGBA, 16, 0, 0, NULL);
    if (!ctx) exit(-1);

    if (!OSMesaMakeCurrent(ctx, osmesa_buffer, GL_UNSIGNED_BYTE, screenWidth, screenHeight)) {
        cerr << "OSMesaMakeCurrent failed." << endl;
        exit(-1);
    }

    int z = 0, s = 0, a = 0;
    glGetIntegerv(GL_DEPTH_BITS, &z);
    glGetIntegerv(GL_STENCIL_BITS, &s);
    glGetIntegerv(GL_ACCUM_RED_BITS, &a);
      cout << "Offscreen context settings: Depth=" << z << " Stencil=" << s
               << " Accum=" << a << endl;

    if (z <= 0) {
        cerr << "Error initializing offscreen context: Depth=" << z << endl;
        exit(-1);
    }

    OSMesaDestroyContext(ctx);
    delete[] osmesa_buffer;

    return 0;
}

Running the code above will output

Allocating osmesa_buffer of size 800x600x4x1
Offscreen context settings: Depth=0 Stencil=0 Accum=0
Error initializing offscreen context: Depth=0

on my machine.

I observe that:

Any idea what is going on? I'm not very familiar with OpenGL, so I'm not sure what's the difference between the core and compatibility profile (but note that the default profile is the compatibility profile)

In any case, whether or not you can reproduce the issue, I think we can just try to create the context the first way, then if depth = 0 then delete the context and recreate it the second way. There should be no harm?

(side note: problem is currently the official Arch Linux build of the package uses offscreen rendering. I think there is no disadvantage to using offscreen rendering?)


Might be relevant: my osmesa.h file contains

/*
 * Create an Off-Screen Mesa rendering context with attribute list.
 * The list is composed of (attribute, value) pairs and terminated with
 * attribute==0.  Supported Attributes:
 *
 * Attributes                    Values
 * --------------------------------------------------------------------------
 * OSMESA_FORMAT                 OSMESA_RGBA*, OSMESA_BGRA, OSMESA_ARGB, etc.
 * OSMESA_DEPTH_BITS             0*, 16, 24, 32
 * OSMESA_STENCIL_BITS           0*, 8
 * OSMESA_ACCUM_BITS             0*, 16
 * OSMESA_PROFILE                OSMESA_COMPAT_PROFILE*, OSMESA_CORE_PROFILE
 * OSMESA_CONTEXT_MAJOR_VERSION  1*, 2, 3
 * OSMESA_CONTEXT_MINOR_VERSION  0+
 *
 * Note: * = default value
 *
 * We return a context version >= what's specified by OSMESA_CONTEXT_MAJOR/
 * MINOR_VERSION for the given profile.  For example, if you request a GL 1.4
 * compat profile, you might get a GL 3.0 compat profile.
 * Otherwise, null is returned if the version/profile is not supported.
 *
 * New in Mesa 11.2
 */

it only has version up to 3? No version 4?

johncbowman commented 6 months ago

There shouldn't be any problem using OSMESA_COMPAT_PROFILE so I have made that change. But offscreen mode is only meant for a headless server lacking a GPU card or monitor. It isn't meant for normal interactive use:

In offscreen mode you will not have any interactive capability to adjust the camera position or zoom in on the scene (using the -V option). That means that you will only see 2D projections of your scene rather than true 3D vector graphics output. So if you want 3D vector graphics you must configure with --disable-offscreen. If Arch Linux is accidentally distributing a headless version of Asymptote that is a mistake that should be reported.

Incidentally, the brief OpenGL window that you see with --disable-offscreen (the default configuration option) is a normal feature of OpenGL. Either ignore it or specify the -iconify option on the command line to hide the rendering window used to project 3D graphics to 2D when the -noV option is specified (the default under UNIX).

Fortunately, all of these concerns will disappear when we migrate from OpenGL to Vulkan (hopefully in the 2.88 release). There won't be any phantom windows opening and, if absolutely needed, you will be able to control offscreen mode from the command line.

user202729 commented 6 months ago

There shouldn't be any problem using OSMESA_COMPAT_PROFILE so I have made that change.

Interesting. Still, we don't know why the bug happens with core profile though.

Incidentally, the brief OpenGL window that you see with --disable-offscreen (the default configuration option) is a normal feature of OpenGL. Either ignore it or specify the -iconify option on the command line to hide the rendering window used to project 3D graphics to 2D when the -noV option is specified (the default under UNIX).

(The actual reason I complain about the brief window is https://github.com/vectorgraphics/asymptote/issues/423 . Normal user won't find it a trouble because the glutHideWindow(); is already there.)

In offscreen mode you will not have any interactive capability to adjust the camera position or zoom in on the scene (using the -V option).

Good point. I guess this can be raised to the Arch Linux package maintainer...

vEnhance commented 5 months ago

Good point. I guess this can be raised to the Arch Linux package maintainer...

The account registration on the Arch bug tracker is currently disabled, so I've gone and filed the issue for you:

https://gitlab.archlinux.org/archlinux/packaging/packages/asymptote/-/issues/1