Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot create multiple instances #34

Closed
al2950 opened this issue Feb 22, 2021 · 7 comments
Closed

Cannot create multiple instances #34

al2950 opened this issue Feb 22, 2021 · 7 comments

Comments

@al2950
Copy link

al2950 commented Feb 22, 2021

m_defaultTextDatablock[i] = hlms->createDatablock( c_defaultTextDatablockNames[i],

I would like to create multiple GUI's to offscreen render targets, but this line prevents me from creating multiple instances of the ColibriManager. Just needs a check to see if datablock already exists

@darksylinc
Copy link
Owner

darksylinc commented Feb 22, 2021

Hi!

Does it work if you change it to?

m_defaultTextDatablock[i] = hlms->getDatablock( c_defaultTextDatablockNames[i] );
if( !m_defaultTextDatablock[i] )
{
	m_defaultTextDatablock[i] = hlms->createDatablock(
		c_defaultTextDatablockNames[i], c_defaultTextDatablockNames[i], macroblock,
		blendblock, Ogre::HlmsParamVec() );
}

I ask because you may encounter more issues later as I never tried more than one manager.

If that doesn't work then try:

 String name = c_defaultTextDatablockNames[i] + toString( Ogre::Id::generateNewId<ColibriManager>() );
	m_defaultTextDatablock[i] = hlms->createDatablock(
		c_defaultTextDatablockNames[i] + , c_defaultTextDatablockNames[i], macroblock,
		blendblock, Ogre::HlmsParamVec() );

Btw although I created Colibri thinking it could be used to render more than 1 GUI with the same ColibriManager, I never really explored that idea and there are a few caveats:

  1. Colibri assumes there is 1 canvas, and one RT (when it comes to pixel sizes) per ColibriManager. This is all data that is living in ColibriManager and should be per canvas (1 canvas = 1 GUI or RenderTarget) assuming we'd like to have 1 ColibriManager for all the GUIs:
Ogre::Vector2				m_canvasSize;
Ogre::Vector2				m_invCanvasSize2x;
/// Size of a pixel on the screen in canvas units.
Ogre::Vector2				m_pixelSize;
Ogre::Vector2				m_pixelSize2x;
Ogre::Vector2				m_halfWindowResolution;
Ogre::Vector2				m_invWindowResolution2x;
float						m_canvasAspectRatio;
float						m_canvasInvAspectRatio;

/// Window and/or Widget currently being in focus
FocusPair		m_cursorFocusedPair;
FocusPair		m_keyboardFocusedPair;
bool			m_allowingScrollAlways;
bool			m_allowingScrollGestureWhileButtonDown;
bool			m_mouseCursorButtonDown;
Ogre::Vector2	m_mouseCursorPosNdc; ///NDC = Normalized Device Coordinates
bool			m_primaryButtonDown;
Borders::Borders m_keyDirDown;
float			m_keyRepeatWaitTimer;

uint32_t		m_keyTextInputDown;
uint16_t		m_keyModInputDown;

/// Controls how much to wait before we start repeating
float			m_keyRepeatDelay;
/// Controls how fast we repeat
float			m_timeDelayPerKeyStroke;
  1. From a rendering perspective, you could just apply a compositor render pass to just more than RenderTarget. The only issues is that currently there would be no way to specify which canvas to render to. But overall this would be the easiest part
  2. Multiple ColibriManagers should be possible (except for minor details like you're having now). This may be the best course of action (100% isolation, also path of least resistance). The main issue I see is that ideally ShaperManager could be shared between managers to avoid wasting memory on text rendering. Otherwise each manager will have its own dynamic cache of characters with the same data in them, when it could be shared

@al2950
Copy link
Author

al2950 commented Feb 22, 2021

So yes that is how I fixed the datablock issue.

I then thought it would be just a case 'fudging' the Colibrigui custom pass and pass provider. Sadly its seems much more complicated as when that is setup is asserts and crashes later here;
https://github.com/darksylinc/colibrigui/blob/master/src/ColibriGui/ColibriManager.cpp#L1462

I will have a closer look at it tomorrow.

@darksylinc
Copy link
Owner

Actually it sounds like ColibriManager::prepareRenderCommands is getting called twice for the same manager instead of one per manager (which would make it a custom pass provider issue)

Check the value of 'this' for the calls

@al2950
Copy link
Author

al2950 commented Feb 23, 2021

So the previous issue was caused by update not being called on the second instance. However with that sorted, 1 instance has corrupted text, and the other renders nearly nothing. (blue window is first instance, red windows is 2nd instance)

collibri on multiple outputs 1

My colleague, who is not that familiar with Ogre, is actually working on this task. So I might have to have a closer look at this at a later stage, although I did notice that the HLMSCache was a static variable which seemed odd.

darksylinc added a commit that referenced this issue Mar 3, 2021
- m_defaultTextDatablock must only be created once
- HlmsColibri must have the proper glyph atlas otherwise the characters will
be rendered as if they're corrupted. Ideally ShaperManagers should be
shared between ColibriManagers for maximum effciency
@darksylinc
Copy link
Owner

Ok I took a look at your code.

You started off with 2 windows which makes it harder. You should've started with two RenderTextures and render those into a single window. That takes away the pain of dealing with two Windows (also SDL and Ogre are fighting due to the hacky way the windows are created).

Anyways the corrupt text problem seems to be fixed.

HLMSCache being static should remain static. It's only a stub pointer because apiObjects.lastHlmsCache must not be nullptr. i.e.
&c_dummyCache is only acting as a nullptr replacement.

The 2nd window is rendering something... but then NaNs are taking over. For some reason

@darksylinc
Copy link
Owner

darksylinc commented Mar 3, 2021

OK Mystery solved. The 2nd window was rendering fine. It was user error.

You were not calling layout2->layout(); thus many widgets had a size of 0, causing 1 / 0, then 0 * inf, then NaN, but rendering was as expected (widgets of 0 size should not appear on screen)

@darksylinc
Copy link
Owner

darksylinc commented Mar 3, 2021

This issue seems to be fixed now thus I'm closing it

image

PS. your code in OpenGL isn't working due to this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants