[Solved]Updating manualobect feels too slow. Any alternative for drawing a gui system?

Problems building or running the engine, queries about how to use features etc.
Bady
Halfling
Posts: 54
Joined: Sun Mar 16, 2014 1:47 am
x 4

[Solved]Updating manualobect feels too slow. Any alternative for drawing a gui system?

Post by Bady »

Ogre Version: :13.2.4:
Operating System: :Windows 10:
Render System: :DX9 DX11:

Hi.

I try to (re)write my gui system, what is based on manualobject. I noticed is the update time is too long even though I "only" want to update a thousand of triangles(text) at once.

I measured the vertex pushing time, and I got this result( the time is in microseconds/μs):

Code: Select all

22:55:44: Sender:consolewindow Entry count: 2 Elapsed time: 87.000000
22:55:44: Sender:headercaption Entry count: 7 Elapsed time: 157.000000
22:55:44: Sender:headerbuttona Entry count: 1 Elapsed time: 58.000000
22:55:44: Sender:headerbuttonb Entry count: 1 Elapsed time: 65.000000
22:55:44: Sender:headerbuttonc Entry count: 1 Elapsed time: 55.000000
22:55:44: Sender:functiontabs Entry count: 2 Elapsed time: 69.000000
22:55:44: Sender:logtabbutton Entry count: 1 Elapsed time: 52.000000
22:55:44: Sender:logtabbuttoncaption Entry count: 3 Elapsed time: 98.000000
22:55:44: Sender:logtab Entry count: 1 Elapsed time: 57.000000
22:55:44: Sender:logtextbox Entry count: 2 Elapsed time: 74.000000
22:55:44: Sender:logtextbox_line_0 Entry count: 59 Elapsed time: 1008.000000
22:55:44: Sender:logtextbox_line_1 Entry count: 74 Elapsed time: 1414.000000
22:55:44: Sender:logtextbox_line_2 Entry count: 37 Elapsed time: 734.000000
22:55:44: Sender:logtextbox_line_3 Entry count: 72 Elapsed time: 1395.000000
22:55:44: Sender:logtextbox_line_4 Entry count: 67 Elapsed time: 1254.000000
22:55:44: Sender:logtextbox_line_5 Entry count: 38 Elapsed time: 723.000000
22:55:44: Sender:logtextbox_line_6 Entry count: 75 Elapsed time: 1373.000000
22:55:44: Sender:logtextbox_line_7 Entry count: 78 Elapsed time: 1636.000000
22:55:44: Sender:logtextbox_line_8 Entry count: 74 Elapsed time: 1362.000000
22:55:44: Sender:logtextbox_line_9 Entry count: 104 Elapsed time: 1704.000000
22:55:44: Sender:logtextbox_line_10 Entry count: 79 Elapsed time: 1471.000000
22:55:44: Sender:logtextbox_line_11 Entry count: 64 Elapsed time: 1300.000000
22:55:44: Sender:logtextbox_line_12 Entry count: 50 Elapsed time: 859.000000
22:55:44: Sender:logtextbox_line_13 Entry count: 68 Elapsed time: 1352.000000
22:55:44: Sender:logtextbox_line_14 Entry count: 72 Elapsed time: 1362.000000
22:55:44: Sender:logtextbox_line_15 Entry count: 41 Elapsed time: 1144.000000
22:55:44: Sender:logtextbox_line_16 Entry count: 0 Elapsed time: 36.000000
22:55:44: Sender:logtextbox_line_17 Entry count: 0 Elapsed time: 29.000000

Here is how I define the manualobject

Code: Select all

void Layer::initmanual()
{
	Ogre::AxisAlignedBox aabInf;
	aabInf.setInfinite();
	Ogre::SceneManager* scenemanager = Ogre::Root::getSingletonPtr()->getSceneManager("MainScene");
	manual = scenemanager->createManualObject(widgetname +"_Guimanual");
	manual->setUseIdentityProjection(true);
	manual->setUseIdentityView(true);
	manual->setKeepDeclarationOrder(true);
	manual->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY);
	manual->setBoundingBox(aabInf);
	setqueueindex(getqueueindex() + 1);
	manual->setRenderQueueGroup(queueindex);
	manual->setCastShadows(false);
	manual->setDebugDisplayEnabled(false);
	manual->setDynamic(true);
	Layoutnode = scenemanager->getRootSceneNode()->createChildSceneNode();
	Layoutnode->attachObject(manual);
	Layoutnode->setPosition(0, 0, 0);
}

Here is the code I use for updating the manualobject:

Code: Select all


#define PUSH_VERTEX(MANUALOBJECT, X, Y, UV, COLOUR)\
MANUALOBJECT->position(X, Y, -1);\
MANUALOBJECT->textureCoord(UV.x, UV.y);\
MANUALOBJECT->colour(COLOUR); 
.
.
.
void LayoutManager::redraw(Widget* dirtywidget)
{
	if (dirtywidget->isdirty())
	{
		//more widget share the same manual, the child can get the parent's manual
		Ogre::ManualObject* Layoutmanual = dirtywidget->getmanual();
		if (dirtywidget->isdrawed()) Layoutmanual->beginUpdate(dirtywidget->getmanualindex());
		else
		{
			int manualindex = Layoutmanual->getNumSections();
			dirtywidget->setmanualindex(manualindex);
			dirtywidget->markasdrawed();
			std::string materialname = dirtywidget->getmaterialname();
			Layoutmanual->begin(materialname, Ogre::RenderOperation::OT_TRIANGLE_LIST);
		}
		int trianglecounter = 0;

	std::vector<data::Widgetdrawdata> widgetdrawdata = dirtywidget->getwidgetdrawdata();
	Layoutmanual->estimateVertexCount((widgetdrawdata.size() * 4) + 4);
	Layoutmanual->estimateIndexCount((widgetdrawdata.size() * 6) + 12);
	functions.debugtimestart();//time measuring point start
	for (auto widget = widgetdrawdata.begin(); widget != widgetdrawdata.end(); ++widget)
	{
		PUSH_VERTEX(Layoutmanual, widget->position.left, widget->position.top, widget->mUV[0], widget->colour);
		PUSH_VERTEX(Layoutmanual, widget->position.left, widget->position.bottom, widget->mUV[1], widget->colour);
		PUSH_VERTEX(Layoutmanual, widget->position.right, widget->position.top, widget->mUV[2], widget->colour);
		PUSH_VERTEX(Layoutmanual, widget->position.right, widget->position.bottom, widget->mUV[3], widget->colour);
		Layoutmanual->triangle(0 + trianglecounter, 1 + trianglecounter, 2 + trianglecounter);
		Layoutmanual->triangle(2 + trianglecounter, 1 + trianglecounter, 3 + trianglecounter);
		trianglecounter += 4;
		
	}
	functions.debugtimeend(dirtywidget->getname() + " Entry count: " + functions.converttostring(widgetdrawdata.size()));//time measuring point end
	Layoutmanual->end();
	dirtywidget->markasclean();
}
std::vector<Widget*> childwidgets = dirtywidget->getchildwidgets();
for (int i = 0; i < childwidgets.size(); i++) redraw(childwidgets[i]);
}

I drawing every elements(buttons/captions/ textboxes, etc) on a different section. So I only need to redraw only that section.
The slowness won't be the problem most of the time, but for example, if I want to scroll the text, I have no other option, just to redraw the whole text again.
I knew it's not the fastest,but Is updating manualobject really is this slow? one millisecond for 70-ish triangles feels way off.
Do I miss something, or declared something wrong? Is there any way to speed up omhow?
Or is there any other options to draw 2d elements more efficiently?

I looked around to find a gui for ogre, but I didn't found any good so far. Either missing something I want or over complicated, or simply not working.

Last edited by Bady on Mon May 20, 2024 5:09 pm, edited 1 time in total.
The last sceneblender
paroj
OGRE Team Member
OGRE Team Member
Posts: 2141
Joined: Sun Mar 30, 2014 2:51 pm
x 1151

Re: Updating manualobect feels too slow. Any alternative for drawing a gui system?

Post by paroj »

are you benchmarking a debug build?

rpgplayerrobin
Orc Shaman
Posts: 721
Joined: Wed Mar 18, 2009 3:03 am
x 401

Re: Updating manualobect feels too slow. Any alternative for drawing a gui system?

Post by rpgplayerrobin »

I use an altered version of Gorilla. For my game it handles each screen in 2 batches at most (one for text and one for all other UI elements, since the text uses its own specific texture filtering for better quality on all font sizes).

but for example, if I want to scroll the text, I have no other option, just to redraw the whole text again.
I knew it's not the fastest

That is the standard way to do it. If I move the position of a single text object, the entire screen will have to be "re-rendered" and be sent to the graphics card. But that should not be that big of a deal most of the time.
For me the only time it is a bigger deal (as in actual FPS drop) is when a huge amount of text is changing its position or alpha each frame, but that rarely happens.

If your system uses a section in the manual object per UI element type or something, maybe updating one section needs to resend all other buffers to the hardware? Maybe that is what is slowing it down in that case, I am not sure since I don't use the standard manual object class anymore.

Here is a post detailing the one I use instead, which is much faster than the standard manual object class:
viewtopic.php?p=547857#p547857

Also, as paroj asked, are you benchmarking it in release or debug? :D

User avatar
sercero
Bronze Sponsor
Bronze Sponsor
Posts: 495
Joined: Sun Jan 18, 2015 4:20 pm
Location: Buenos Aires, Argentina
x 179

Re: Updating manualobect feels too slow. Any alternative for drawing a gui system?

Post by sercero »

If you are considering other GUI systems, I recommend MyGUI: https://github.com/MyGUI/mygui

Bady
Halfling
Posts: 54
Joined: Sun Mar 16, 2014 1:47 am
x 4

Re: Updating manualobect feels too slow. Any alternative for drawing a gui system?

Post by Bady »

paroj wrote: Sun May 19, 2024 10:57 pm

are you benchmarking a debug build?

rpgplayerrobin wrote: Mon May 20, 2024 1:05 am

Also, as paroj asked, are you benchmarking it in release or debug? :D

I am so embarrassed right now. I totally forgot I am in debug mode. :oops: Sorry.

But It worth asking help, because without it I wouldn't know about your manualobject modification, rpgplayerrobin!You are awesome! Thank you.

sercero wrote: Mon May 20, 2024 12:39 pm

If you are considering other GUI systems, I recommend MyGUI: https://github.com/MyGUI/mygui

I used MyGui, and the layer definition is too complicated for me, and can't load fontfile directly, what I already solved in my gui. Thanks for the recommendation tho.

The last sceneblender