manually created texture is not released Topic is solved

Problems building or running the engine, queries about how to use features etc.
Post Reply
bro
Gnoblar
Posts: 18
Joined: Fri May 20, 2022 6:15 am
x 5

manually created texture is not released

Post by bro »

Ogre Version: : 13.4
Operating System: : Linux Fedora 35
Render System: :OpenGL 3+

I have an application with a main window based on ApplicationContextQt that is working fine.

At some point, i want to create a top down image of the scene without changing the current context (point of view, viewport...)
=> for that purpose i want to temporarly create a texture i'll be rendering into and then do what i need to with the resulting image (export, process...).

I ended up with the following code :

Code: Select all

void capture(
    Ogre::SceneManager* scene_manager,
    const std::string& id,
    double x,
    double y,
    double z,
    double head,
    double pitch,
    double roll,
    double size_y,
    double size_z,
    double near_clip,
    double far_clip,
    double scale_mpp,
    Ogre::PixelFormat pixel_format,
    const Ogre::ColourValue& clear_color,
    std::function<void(const Ogre::PixelBox&)> use_data)

{
  auto* cam = scene_manager->createCamera(fmt::format("{}_camera", id));
  cam->setProjectionType(Ogre::ProjectionType::PT_ORTHOGRAPHIC);
  cam->setNearClipDistance(near_clip);
  cam->setFarClipDistance(far_clip);
  cam->setAutoAspectRatio(false);

  cam->setOrthoWindow(size_y, size_z);
  const auto tex_width = int(size_y / scale_mpp);
  const auto tex_height = int(size_z / scale_mpp);

  auto* node = scene_manager->getRootSceneNode()->createChildSceneNode();
  node->attachObject(cam);

  // place camera in world RD-convetion
  // note that ogre camera look towards -Z, while RD-conv is to gaze along X
  node->setPosition(SimOgreCommon::GeoHelpers::rdXYZ_to_ogre(x, y, z));
  node->setOrientation(
      SimOgreCommon::GeoHelpers::rdHPR_to_ogre(head, pitch, roll) *
      Ogre::Quaternion{-Ogre::Degree(90.0), Ogre::Vector3::UNIT_Y});

  Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().createManual(
      fmt::format("{}_tex", id),
      Resource3dDatabase::getComputationDefault(),
      Ogre::TEX_TYPE_2D,
      tex_width,
      tex_height,
      0,
      pixel_format,
      Ogre::TU_RENDERTARGET);

  Ogre::HardwarePixelBufferSharedPtr buffer = tex->getBuffer();
  auto* renderer = buffer->getRenderTarget();
  auto* viewport = renderer->addViewport(cam);
  viewport->setAutoUpdated(false);
  viewport->setClearEveryFrame(true);
  viewport->setBackgroundColour(clear_color);
  viewport->setOverlaysEnabled(false);
  viewport->setShadowsEnabled(false);

  // render
  viewport->update();

  // transfer buffer from gpu to cpu: lock buffer to read into it
  {
    buffer->lock(Ogre::HardwareBuffer::LockOptions::HBL_READ_ONLY);
    const Ogre::PixelBox& pixel_box = buffer->getCurrentLock();

use_data(pixel_box);

buffer->unlock();
  }

  // clean up
  scene_manager->getRootSceneNode()->removeAndDestroyChild(node);
  scene_manager->destroyCamera(cam);
}

note:
the detail of following methods is not relevant here:
'SimOgreCommon::GeoHelpers::rdXYZ_to_ogre' -> returns a vector3
'SimOgreCommon::GeoHelpers::rdHPR_to_ogre' -> returns a quaternion
'Resource3dDatabase::getComputationDefault' -> returns a string that refers to a resource group that was previously created

As an example, I use following lambda as 'use_data' function:

Code: Select all

[&](const Ogre::PixelBox& pixel_box) {
                QImage img{
                    static_cast<Ogre::uint8*>(pixel_box.data),
                    int(pixel_box.getWidth()),
                    int(pixel_box.getHeight()),
                    QImage::Format_ARGB32};
                img.save(QString::fromStdString(filepath), nullptr);
              });

This method is ok in term of generating the data i want.

My concern is that i can't call my 'capture' method twice with the same id :
The second time i get following exception :

Code: Select all

terminate called after throwing an instance of 'Ogre::ItemIdentityException'
  what():  ItemIdentityException: Texture with the name agent_capture_tex already exists. in ResourceManager::add at /xxxxxxxx/ogre-13.4.0/OgreMain/src/OgreResourceManager.cpp (line 152)

To my understanding the texture is not deleted when the "capure function" ends. correct?
What shall i do to release it?
I tried to Ogre::TextureManager::getSingleton().remove(fmt::format("{}_tex", id)); at the end of "capture function" but i still get the exception.

Of course i can have specific id for ech call to the "capture function" but i'm concerned by the fact that the texture is not released while i don't need it any longer.

bro
Gnoblar
Posts: 18
Joined: Fri May 20, 2022 6:15 am
x 5

Re: manually created texture is not released

Post by bro »

actually the problem was the proper identification of the texture to be removed.

i did :
Ogre::TextureManager::getSingleton().remove(fmt::format("{}_tex", id));

without providing the identification of the group the texture is in.

correct call is (in mycontext) :
Ogre::TextureManager::getSingleton().remove(
fmt::format("{}_tex", id), Resource3dDatabase::getComputationDefault());

wich makes the texture be removed and thus the id gets available for next call.

another (nicer) option is :

Ogre::TextureManager::getSingleton().remove(tex);

This solves my release problem.

For my understanding: why is the removal not done when the texture shared pointer ref counter reaches 0 (which i assume happens at the end of the function call) ?

Post Reply