[2.3][Vulkan] Using RTT texture as Colibri widget's texture

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


CbbK
Gnoblar
Posts: 11
Joined: Sun Nov 22, 2020 3:29 pm
x 1

[2.3][Vulkan] Using RTT texture as Colibri widget's texture

Post by CbbK »

Hi, after switching to Ogre 2.3 and trying to enable Vulkan as render system I encountered the following issue :

OGRE EXCEPTION(1:InvalidStateException): Texture NavBallTexture is not in ResourceLayout::Texture nor RenderTargetReadOnly. Did you forget to expose it to compositor? Currently rendering to target: RenderWindow in VulkanRenderSystem::checkTextureLayout at D:\dev\ogre-next\RenderSystems\Vulkan\src\OgreVulkanRenderSystem.cpp (line 1541)

I have a Colibri widget using this material :

Code: Select all

hlms NavBall_UI unlit
{
	#diffuse_map is set at runtime
	depth_check off
	scene_blend alpha_blend
}

The texture is created and set when the widget is initialised (Colibri::Renderable::_initialize()):

Code: Select all

    //allocate texture we'll render on
    Ogre::Root *root = Ogre::Root::getSingletonPtr();
    Ogre::TextureGpuManager *textureManager = root->getRenderSystem()->getTextureGpuManager();
    _texture = textureManager->createTexture(
        "NavBallTexture",
        Ogre::GpuPageOutStrategy::Discard, Ogre::TextureFlags::RenderToTexture, Ogre::TextureTypes::Type2D );
    _texture->setResolution(512, 512);
    _texture->setPixelFormat(Ogre::PFG_RGBA32_FLOAT);
    _texture->scheduleTransitionTo(Ogre::GpuResidency::Resident);

Ogre::SceneManager *sceneManager = m_manager->getOgreSceneManager();
_camera = sceneManager->createCamera("NavBallCamera");
_camera->setNearClipDistance(0.01f);
_camera->setProjectionType(Ogre::PT_ORTHOGRAPHIC);
_camera->setOrthoWindow(2.5f, 2.5f);

Ogre::CompositorManager2 *compositorManager = root->getCompositorManager2();
_workspace = compositorManager->addWorkspace( sceneManager, _texture,
                                              _camera, "NavBallWorkspace", true );

// Find material and assign RTT texture to it
Ogre::Hlms *hlms = root->getHlmsManager()->getHlms( Ogre::HLMS_UNLIT );
Ogre::HlmsDatablock *datablock = hlms->getDatablock( "NavBall_UI" );
assert( dynamic_cast<Ogre::HlmsUnlitDatablock *>( datablock ) );
Ogre::HlmsUnlitDatablock *unlitDatablock = dynamic_cast<Ogre::HlmsUnlitDatablock *>(datablock);
unlitDatablock->setTexture(0u, _texture);  // Set texture

And the compositor :

Code: Select all

compositor_node NavBallNode
{
        in 0 rt_renderwindow

	target rt_renderwindow
	{
		pass clear
		{
                            colour_value 0.0 0.0 0.0 0.0
		}
		
		pass render_scene
		{
			rq_first	21
			rq_last		22
		}
	}
}

workspace NavBallWorkspace
{
        //Connect RenderWindow to FinalComposition's input channel #0
        connect_output NavBallNode 0
}

This topic seems to cover the issue somehow but I couldn't fix my problem :/
From my understanding I can't use the same texture as rendertarget and texture for the widget or at least need to put appropriate barriers, but how in the script?
I read in another topic that I could render the scene in a local texture then copy it in a render_quad pass, I tried that but the issue stayed exactly the same.
I also read about adding a listener and copying the texture after the last pass, but that seems overkill to bring back the texture, copy it in memory then resend it.
Which approach is the best for that please? What must I add in the scripts to make it work with Vulkan, or should I code everything instead of using scripts? Thanks

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5429
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1337

Re: [2.3][Vulkan] Using RTT texture as Colibri widget's texture

Post by dark_sylinc »

Hi!

You have two possible solutions:

1. After you manually update the workspace (or use a listener if it's auto updated) run this code:

Code: Select all

using namespace Ogre;
RenderSystem *renderSystem = m_secondaryManager->getOgreHlmsManager()->getRenderSystem();
BarrierSolver &solver = renderSystem->getBarrierSolver();

ResourceTransitionArray &barrier = solver.getNewResourceTransitionsArrayTmp();
solver.resolveTransition( barrier, _texture, ResourceLayout::Texture, ResourceAccess::Read,
						  1u << GPT_FRAGMENT_PROGRAM );
renderSystem->executeResourceTransition( barrier );

2. Tell your main compositor (the one that draws Colibri) about your texture:

Code: Select all

compositor_node Finalnode
{
        in 0 rt_renderwindow
        in 1 NavBallTexture

	target rt_renderwindow
	{
		pass colibri
		{
                           expose NavBallTexture
		}
	}
}

workspace MyFinalWorkspace
{
        // Connect RenderWindow to FinalNode input channel #0
        connect_output 0 FinalNode 0
        // Connect NavBallTexture to FinalNode input channel #1
        connect_output 1 FinalNode 1
}

And create your workspace in C++ with:

Code: Select all

	Ogre::CompositorChannelVec channels;
	channels.push_back( render_window );
	channels.push_back( _texture ); // points to NavBallTexture

	m_workspace =
		compositorManager->addWorkspace( m_secondaryManager->getOgreSceneManager(), channels,
										 camera, "MyFinalWorkspace", true );
CbbK
Gnoblar
Posts: 11
Joined: Sun Nov 22, 2020 3:29 pm
x 1

Re: [2.3][Vulkan] Using RTT texture as Colibri widget's texture

Post by CbbK »

Wonderful that works like a charm and your 1st solution integrates well with my code. Thank you!
For my information, do both of this solutions end up doing the same thing or would you encourage one over the other?

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5429
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1337

Re: [2.3][Vulkan] Using RTT texture as Colibri widget's texture

Post by dark_sylinc »

CbbK wrote: Fri Jul 12, 2024 9:14 pm

For my information, do both of this solutions end up doing the same thing or would you encourage one over the other?

In theory the second solution could (emphasis on COULD, not "will") result in slightly better performance.
However I don't like how it currently is, because I think it's currently not very user friendly to use.

Perhaps if you were ONLY to write:

Code: Select all

		pass colibri
		{
                           expose NavBallTexture
		}

Where "NavBallTexture" must match the name you set to textureMgr->createTexture(), do you think it will be easier?

CbbK
Gnoblar
Posts: 11
Joined: Sun Nov 22, 2020 3:29 pm
x 1

Re: [2.3][Vulkan] Using RTT texture as Colibri widget's texture

Post by CbbK »

It would indeed be easier as we wouldn't have to share the otherwise private texture pointer. The 1st solution would still have the advantage of keeping the widget autonomous, tending to it's own needs.
I'm still a bit unsure about the 'expose' keyword because I thought it worked the other way around : the NavBall compositor exposes the texture to the global level (it's its render target after all), in the final compositor shouldn't the keyword be 'require' or something similar? I guess you meant it the other way : the texture is part of the widget, which is rendered in the colibri pass, right?