Buffer-related Python crashes with newer Panda versions

Let’s start with the most important thing:

Yes, you’re right, that did it :slight_smile: !

For those interested, here’s some working code for the first suggestion:

from panda3d.core import *
from direct.showbase.ShowBase import ShowBase


class MyApp(ShowBase):

    def __init__(self):

        ShowBase.__init__(self)

        #self.tex = Texture("buffer_tex")
        self.buffer = self.win.makeTextureBuffer("buffer", 256, 256)#, self.tex)
        self.depth_tex = Texture("depth_texture")
        self.buffer.addRenderTexture(self.depth_tex, GraphicsOutput.RTMBindOrCopy,
                                      GraphicsOutput.RTPDepth)


app = MyApp()
app.run()

The last part of the output now looks like this instead of the last line in the previous version:

:display:gsg:glgsg(debug): Binding texture depth_texture to depth attachment.
:display:gsg:glgsg(debug): loading texture with NULL image depth_texture
:display:gsg:glgsg(debug): loading new texture object for depth_texture, 256 x 2
56 x 1, z = 0, mipmaps 0, uses_mipmaps = 0
:display:gsg:glgsg(debug):   (initializing NULL image)
:display:gsg:glgsg(debug): Creating color renderbuffer.

And here is working code for the second suggestion:

from panda3d.core import *
from direct.showbase.ShowBase import ShowBase


class MyApp(ShowBase):

    def __init__(self):

        ShowBase.__init__(self)

        props = FrameBufferProperties()
        props.setDepthBits(32)
        #props.setFloatDepth(True) # this can be used as fix instead of the line above
        self.buffer = self.win.makeTextureBuffer("buffer", 256, 256, fbp=props)


app = MyApp()
app.run()

Note that in the second solution, using props.setFloatDepth(True) instead of props.setDepthBits(32) also works.

This time, the last part of the output is:

:display:gsg:glgsg(debug): Creating depth renderbuffer.
:display:gsg:glgsg(debug): Creating color renderbuffer.

So it seems it is indeed related to the depth-stencil renderbuffer setup.

There are however still a couple of other things I’d like to report, related to this.
In my own project, with the previous Panda versions, I used the following camera setup for picking objects based on their vertex color:

class PickingCamera(object):

    def __init__(self):

        self._tex = Texture("picking_texture")
        props = FrameBufferProperties()
        #props.setFloatColor(True) # makes it impossible to get a TexturePeeker
        props.setDepthBits(32)
        #props.setFloatDepth(True) # this can be used as fix instead of the line above
        self._buffer = base.win.makeTextureBuffer("picking_buffer",
                                                  1, 1,
                                                  self._tex,
                                                  to_ram=True,
                                                  fbp=props)
        self._buffer.setClearColor(VBase4())
        self._buffer.setClearColorActive(True)
        self._buffer.setSort(-100)
        self._tex_peeker = None
        self._np = base.makeCamera(self._buffer)
        self._mask = BitMask32.bit(21)
        self._pixel_color = VBase4()
        node = self._np.node()
        lens = node.getLens()
        lens.setFov(1.)
        cull_bounds = lens.makeBounds()
        lens.setFov(.1)
        node.setCullBounds(cull_bounds)
        node.setCameraMask(self._mask)

        state_np = NodePath("flat_color_state")
        state_np.setTextureOff(1)
        state_np.setMaterialOff(1)
        state_np.setShaderOff(1)
        state_np.setLightOff(1)
        state_np.setColorOff(1)
        state_np.setColorScaleOff(1)
        state_np.setRenderModeThickness(5, 1)
        state_np.setTransparency(TransparencyAttrib.MNone, 1)
        node.setInitialState(state_np.getState())

        base.taskMgr.add(self.__checkPixel, "get_pixel_under_mouse", priority=0)


    def __checkPixel(self, task):

        if not base.mouseWatcherNode.hasMouse():
          return task.cont

        screen_pos = base.mouseWatcherNode.getMouse()
        far_point = Point3()
        base.camLens.extrude(screen_pos, Point3(), far_point)
        self._np.lookAt(far_point)

        if not self._tex_peeker:
          self._tex_peeker = self._tex.peek()
          return task.cont

        self._tex_peeker.lookup(self._pixel_color, .5, .5)
        print "pixel color:", self._pixel_color # alpha always 1.

        return task.cont

The above worked well, but with Panda 1.9.0 and later, the alpha component of the pixel color as returned by the TexturePeeker is always 1, while with older Panda versions it was either 0 or the alpha value of the vertex color (which I need to distinguish between different types of objects).
So it looks like something related to the TexturePeeker class has changed also?
Also note that calling setFloatColor(True) on the FrameBufferProperties for the offscreen buffer makes the call to peek() on the associated render texture return None, so maybe there’s a bug in there too? (This is not related to my laptop, btw.)

Then I found a workaround by using a PNMImage instead of a TexturePeeker, like this (new code indicated with “# workaround” comment):

class PickingCamera(object):

    def __init__(self):

        self._tex = Texture("picking_texture")
        self._img = PNMImage(1, 1) # workaround
        props = FrameBufferProperties()
        props.setFloatColor(True) # workaround
        props.setAlphaBits(32) # workaround
        props.setDepthBits(32)
        #props.setFloatDepth(True) # this can be used as fix instead of the line above
        self._buffer = base.win.makeTextureBuffer("picking_buffer",
                                                  1, 1,
                                                  self._tex,
                                                  to_ram=True,
                                                  fbp=props)
        self._buffer.setClearColor(VBase4())
        self._buffer.setClearColorActive(True)
        self._buffer.setSort(-100)
        self._np = base.makeCamera(self._buffer)
        self._mask = BitMask32.bit(21)
        self._pixel_color = VBase4()
        node = self._np.node()
        lens = node.getLens()
        lens.setFov(1.)
        cull_bounds = lens.makeBounds()
        lens.setFov(.1)
        node.setCullBounds(cull_bounds)
        node.setCameraMask(self._mask)

        state_np = NodePath("flat_color_state")
        state_np.setTextureOff(1)
        state_np.setMaterialOff(1)
        state_np.setShaderOff(1)
        state_np.setLightOff(1)
        state_np.setColorOff(1)
        state_np.setColorScaleOff(1)
        state_np.setRenderModeThickness(5, 1)
        state_np.setTransparency(TransparencyAttrib.MNone, 1)
        node.setInitialState(state_np.getState())

        base.taskMgr.add(self.__checkPixel, "get_pixel_under_mouse", priority=0)


    def __checkPixel(self, task):

        if not base.mouseWatcherNode.hasMouse():
          return task.cont

        screen_pos = base.mouseWatcherNode.getMouse()
        far_point = Point3()
        base.camLens.extrude(screen_pos, Point3(), far_point)
        self._np.lookAt(far_point)
        self._tex.store(self._img) # workaround
        self._pixel_color = self._img.getXelA(0, 0) # workaround
        print "pixel color:", self._pixel_color # always LVecBase4f(0, 0, 0, 0)

        return task.cont

This code works fine on my desktop, but again not on my laptop: the returned pixel color under the mouse is always LVecBase4f(0, 0, 0, 0).

Then about my laptop.

Processor / integrated graphics: Intel Core i3-390M / Graphics Media Accelerator HD (GMA HD)

If you’re interested, here you can find all the details of my laptop.

There’s nothing about Optimus in the BIOS, so I can’t check how it’s configured from there.
So I downloaded and ran this nVidia Optimus GPU State Viewer, and indeed it shows “NVIDIA GPU: OFF” while running Panda (or any other 3D) applications.
However, if I go to “3D Settings → Adjust image settings with preview” in the NVIDIA Control Panel, then the tool does say “NVIDIA GPU: ON” and lists nvcplui.exe as an application rendered by the NVIDIA card, so I know it’s not defective.

Updating the drivers seems like the obvious thing to do, but a previous bad experience has made me a bit reluctant to do so.