Hello Marco,
Marco Spoerl wrote:
Hello Carsten,
Thanks for your modified test app. First up, I think I have to mention
that we're using the 1.8 release here, not something fresh from the
repository. So I had to tweak it back a little bit to work with our
version of the library.
The following numbers are simply taken from the task manager.
29.000K when running idle
57.000K before exiting the leak function
31.000K after exiting the leak function
Increasing the number of iterations to 1000, I get the following
numbers.
29.000K when running idle
299.000K before exiting the leak function
61.000K after exiting the leak function
hm, that is indeed a lot of memory.
I've modified the program (attached) so that it now uses only one
texture and image [1] for grabbing and writes the result to disk (I
enabled readBuffer on the FBOViewport). Of course that means that the
grabbed images do not remain available for rendering (at least not
without loading them from disk again), neither in texture nor main memory.
With that change I don't see a massive increase in memory consumption.
So my guess would be that what you see above is (at least a good portion
of it) memory allocated by the graphics driver for the textures.
So, from my point of view, I'm still seeing the problem. Maybe I have
to use a newer version of the library? In that case, I'd be grateful for
any tips how to get a reliable revision.
Or do I have to change the way
I grab my textures? In our application, that preprocessing step easily
involves tens of thousands of texture grabs.
The best way for grabbing the textures depends on how you intend to use
them and the resources available. If you need all of them at once for
rendering there is probably not much that can be done, but to keep them
in texture memory, i.e. having a TextureChunk and Image for each of
them. If you only need a subset for rendering you could use a small
number of chunks and place the images you want to use in them (would
still require lots of main memory for all the images, but less texture
memory).
The last alternative is pretty much what the program does: use one chunk
and image and store the data on disk. You could later load in the
relevant images and place them in textures for rendering.
Hope it helps,
Carsten
[1] that is controlled with the SINGLE_IMAGE define near the top of the
program
#include <OSGConfig.h>
#include <OSGRefPtr.h>
#include <OSGGLUTWindow.h>
#include <OSGRenderAction.h>
#include <OSGPerspectiveCamera.h>
#include <OSGViewport.h>
#include <OSGPassiveBackground.h>
#include <OSGTransform.h>
#include <OSGGroup.h>
#include <OSGOrthographicCamera.h>
#include <OSGFBOViewport.h>
#include <OSGSolidBackground.h>
#include <OSGImage.h>
#include <OSGTextureChunk.h>
#include <OSGSimpleGeometry.h>
#include <OSGGLUT.h>
#include <sstream>
#define SINGLE_IMAGE 1
//-----------------------------------------------------------------------------
static const OSG::UInt32 TEX_SIZE = 256;
static const OSG::UInt32 NUM_ITERATIONS = 1000;
//-----------------------------------------------------------------------------
OSG::GLUTWindowRefPtr g_pWindow(OSG::NullFC);
OSG::RenderAction* g_pAction = 0;
OSG::FBOViewportRefPtr g_pFboViewport(OSG::NullFC);
OSG::TransformPtr g_pGeoTrans;
OSG::NodeRefPtr g_pGeoTransNode;
OSG::TextureChunkRefPtr g_pTexChunk;
OSG::ImageRefPtr g_pImage;
void reshape(int w, int h);
void display(void );
void key (unsigned char key, int, int);
void onCreateMain(int *argc, char *argv[])
{
// OSG init
OSG::osgInit(*argc, argv);
// GLUT init
glutInit(argc, argv);
glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
int winid = glutCreateWindow("OpenSG");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutKeyboardFunc(key);
g_pWindow = OSG::GLUTWindow ::create();
g_pAction = OSG::RenderAction::create();
// create viewport
OSG::NodePtr pCameraBeacon = OSG::makeCoredNode<OSG::Transform>();
OSG::TransformPtr pBeaconTrans = OSG::TransformPtr::dcast(pCameraBeacon->getCore());
OSG::beginEditCP(pBeaconTrans);
pBeaconTrans->editMatrix().setTranslate(OSG::Vec3f(0.0, 0.0, 2.0));
OSG::endEditCP (pBeaconTrans);
OSG::PerspectiveCameraPtr pPerspectiveCam = OSG::PerspectiveCamera::create();
OSG::beginEditCP(pPerspectiveCam);
pPerspectiveCam->setBeacon(pCameraBeacon);
pPerspectiveCam->setFov(OSG::deg2rad(90));
pPerspectiveCam->setNear(1);
pPerspectiveCam->setFar(1000);
OSG::endEditCP(pPerspectiveCam);
// create background
OSG::SolidBackgroundPtr pBackground = OSG::SolidBackground::create();
OSG::beginEditCP(pBackground);
pBackground->setColor(OSG::Color3f(0.0, 0.5, 0.0));
OSG::endEditCP(pBackground);
OSG::NodePtr pDummyRoot = OSG::makeCone(1.0, 0.5, 16, true, true);
OSG::GeometryPtr pDummyGeo = OSG::GeometryPtr::dcast(pDummyRoot->getCore());
OSG::beginEditCP(pDummyGeo);
pDummyGeo->setMaterial(OSG::getDefaultUnlitMaterial());
OSG::endEditCP (pDummyGeo);
OSG::ViewportPtr pViewport = OSG::Viewport::create();
OSG::beginEditCP(pViewport);
pViewport->setCamera(pPerspectiveCam);
pViewport->setBackground(pBackground);
pViewport->setRoot(pDummyRoot);
pViewport->setSize(0, 0, 1, 1);
OSG::endEditCP(pViewport);
// init OpenSG window
OSG::beginEditCP(g_pWindow);
g_pWindow->addPort(pViewport);
g_pWindow->setId(winid);
g_pWindow->init();
g_pWindow->deactivate();
OSG::endEditCP(g_pWindow);
}
void onCreateFbo()
{
// create nodes
OSG::NodePtr pCameraBeacon = OSG::makeCoredNode<OSG::Transform>();
// OSG::TransformPtr pBeaconTrans = OSG::TransformPtr::dcast(pCameraBeacon->getCore());
// OSG::beginEditCP(pBeaconTrans);
// pBeaconTrans->editMatrix().setTranslate(OSG::Vec3f(0.0, 0.0, -2.0));
// OSG::endEditCP (pBeaconTrans);
OSG::NodePtr pGeometryNode = OSG::makeBox(100.0, 10.0, 50.0, 1, 1, 1);
OSG::GeometryPtr pGeometry = OSG::GeometryPtr::dcast(pGeometryNode->getCore());
OSG::beginEditCP(pGeometry);
pGeometry->setMaterial(OSG::getDefaultUnlitMaterial());
OSG::endEditCP (pGeometry);
g_pGeoTransNode = OSG::makeCoredNode<OSG::Transform>(&g_pGeoTrans);
OSG::beginEditCP(g_pGeoTransNode);
g_pGeoTransNode->addChild(pGeometryNode);
OSG::endEditCP (g_pGeoTransNode);
// create root node
OSG::NodePtr pRootNode = OSG::makeCoredNode<OSG::Group>();
OSG::beginEditCP(pRootNode);
pRootNode->addChild(pCameraBeacon);
pRootNode->addChild(g_pGeoTransNode);
OSG::endEditCP(pRootNode);
// create camera
OSG::OrthographicCameraPtr pCamera = OSG::OrthographicCamera::create();
OSG::beginEditCP(pCamera);
pCamera->setBeacon(pCameraBeacon);
pCamera->setNear(0.1);
pCamera->setFar(100);
pCamera->setAspect(1);
pCamera->setVerticalSize(TEX_SIZE);
OSG::endEditCP(pCamera);
// create background
OSG::SolidBackgroundPtr pBackground = OSG::SolidBackground::create();
OSG::beginEditCP(pBackground);
pBackground->setColor(OSG::Color3f(0.6, 0.0, 0.0));
OSG::endEditCP(pBackground);
// create viewport
g_pFboViewport = OSG::FBOViewport::create();
OSG::beginEditCP(g_pFboViewport);
g_pFboViewport->setParent(g_pWindow);
g_pFboViewport->setRoot(pRootNode);
g_pFboViewport->setBackground(pBackground);
g_pFboViewport->setCamera(pCamera);
g_pFboViewport->setSize(0, 0, TEX_SIZE - 1, TEX_SIZE - 1);
g_pFboViewport->setStorageWidth(TEX_SIZE);
g_pFboViewport->setStorageHeight(TEX_SIZE);
g_pFboViewport->setGenCubemaps(false);
g_pFboViewport->setGenDepthmaps(false);
g_pFboViewport->setReadBuffer(true);
g_pFboViewport->setFboOn(true);
g_pFboViewport->setDirty(true);
OSG::endEditCP(g_pFboViewport);
}
// Standard GLUT callback functions
void display( void )
{
if (g_pWindow != OSG::NullFC)
{
g_pWindow->render(g_pAction);
}
}
void reshape( int w, int h )
{
if (g_pWindow != OSG::NullFC)
{
g_pWindow->resize(w, h);
}
glutPostRedisplay();
}
//-----------------------------------------------------------------------------
void grab(OSG::TextureChunkPtr pTexture, OSG::UInt32 i)
{
if (g_pFboViewport != OSG::NullFC)
{
OSG::beginEditCP(g_pGeoTrans);
g_pGeoTrans->editMatrix().setRotate(OSG::Quaternion(OSG::Vec3f(0.0, 0.0, 1.0), (6.28 / NUM_ITERATIONS) * i));
OSG::endEditCP (g_pGeoTrans);
#ifndef SINGLE_IMAGE
OSG::ImagePtr pImage = OSG::Image::create();
OSG::beginEditCP(pImage);
pImage->set(OSG::Image::OSG_RGBA_PF, TEX_SIZE, TEX_SIZE);
OSG::endEditCP(pImage);
OSG::beginEditCP(pTexture, OSG::TextureChunk::ImageFieldMask);
pTexture->setImage(pImage);
OSG::endEditCP(pTexture, OSG::TextureChunk::ImageFieldMask);
#endif
g_pAction->setAutoFrustum(false);
g_pAction->setCorrectTwoSidedLighting(false);
g_pAction->setFrustumCulling(false);
g_pAction->setOcclusionCulling(false);
g_pAction->setSmallFeatureCulling(false);
g_pAction->setSortTrans(false);
g_pAction->setStateSorting(false);
g_pAction->setStatistics(false);
g_pAction->setVolumeDrawing(false);
g_pAction->setZWriteTrans(false);
OSG::beginEditCP(g_pFboViewport);
g_pFboViewport->editMFTextures()->push_back(pTexture);
OSG::endEditCP(g_pFboViewport);
g_pFboViewport->render(g_pAction);
OSG::beginEditCP(g_pFboViewport);
g_pFboViewport->editMFTextures()->clear();
OSG::endEditCP(g_pFboViewport);
std::ostringstream fileName;
fileName << "texture_" << i << ".png";
#ifndef SINGLE_IMAGE
pImage->write(fileName.str().c_str());
#else
g_pImage->write(fileName.str().c_str());
#endif
}
}
//-----------------------------------------------------------------------------
OSG::TextureChunkPtr createTexture()
{
#ifndef SINGLE_IMAGE
OSG::Real32 maximumAnistropy;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maximumAnistropy);
maximumAnistropy = OSG::osgMin(maximumAnistropy, OSG::Real32(8.0));
OSG::TextureChunkPtr pTexture = OSG::TextureChunk::create();
OSG::beginEditCP(pTexture);
pTexture->setAnisotropy(maximumAnistropy);
pTexture->setMinFilter(GL_LINEAR);
pTexture->setMagFilter(GL_LINEAR);
pTexture->setWrapS(GL_CLAMP_TO_EDGE);
pTexture->setWrapT(GL_CLAMP_TO_EDGE);
pTexture->setTarget(GL_TEXTURE_2D);
pTexture->setInternalFormat(GL_RGBA8);
OSG::endEditCP(pTexture);
return pTexture;
#else
if(g_pTexChunk == OSG::NullFC)
{
OSG::Real32 maximumAnistropy;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maximumAnistropy);
maximumAnistropy = OSG::osgMin(maximumAnistropy, OSG::Real32(8.0));
g_pTexChunk = OSG::TextureChunk::create();
OSG::beginEditCP(g_pTexChunk);
g_pTexChunk->setAnisotropy(maximumAnistropy);
g_pTexChunk->setMinFilter(GL_LINEAR);
g_pTexChunk->setMagFilter(GL_LINEAR);
g_pTexChunk->setWrapS(GL_CLAMP_TO_EDGE);
g_pTexChunk->setWrapT(GL_CLAMP_TO_EDGE);
g_pTexChunk->setTarget(GL_TEXTURE_2D);
g_pTexChunk->setInternalFormat(GL_RGBA8);
OSG::endEditCP(g_pTexChunk);
}
if(g_pImage == OSG::NullFC)
{
g_pImage = OSG::Image::create();
OSG::beginEditCP(g_pImage);
g_pImage->set(OSG::Image::OSG_RGBA_PF, TEX_SIZE, TEX_SIZE);
OSG::endEditCP(g_pImage);
OSG::beginEditCP(g_pTexChunk, OSG::TextureChunk::ImageFieldMask);
g_pTexChunk->setImage(g_pImage);
OSG::endEditCP(g_pTexChunk, OSG::TextureChunk::ImageFieldMask);
}
return g_pTexChunk;
#endif
}
//-----------------------------------------------------------------------------
void leak()
{
std::cout << "calling 'leak'" << std::endl;
OSG::RefPtr<OSG::TextureChunkPtr> pTexture(OSG::NullFC);
for(OSG::UInt32 i = 0; i < NUM_ITERATIONS; ++i)
{
pTexture = createTexture();
grab(pTexture, i);
}
std::cout << "exiting 'leak'" << std::endl;
}
void
key(unsigned char key, int , int )
{
switch(key)
{
case 27: g_pWindow = OSG::NullFC;
g_pFboViewport = OSG::NullFC;
delete g_pAction;
g_pAction = NULL;
exit(1);
case 'l': leak();
break;
}
glutPostRedisplay();
}
// Initialize GLUT & OpenSG and set up the scene
int main (int argc, char **argv)
{
onCreateMain(&argc, argv);
onCreateFbo();
// GLUT main loop
glutMainLoop();
return 0;
}
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Opensg-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensg-users