1
0
forked from mirrors/0ad

Dynamic message subscriptions.

Allow components to individually subscribe/unsubscribe to messages,
instead of statically subscribing the entire component type. Use this
for most Interpolate/RenderSubmit messages, to avoid the performance
cost of passing those messages to a large number of components that will
just ignore them anyway.

On Azure Coast this reduces total time per frame by about 30% on a
CPU-bound system.

This was SVN commit r15400.
This commit is contained in:
Ykkrosh
2014-06-19 23:20:12 +00:00
parent ec7a452d4e
commit d936bde74a
12 changed files with 391 additions and 22 deletions
@@ -53,14 +53,10 @@ class CCmpSelectable : public ICmpSelectable
public:
static void ClassInit(CComponentManager& componentManager)
{
componentManager.SubscribeToMessageType(MT_Interpolate);
componentManager.SubscribeToMessageType(MT_RenderSubmit);
componentManager.SubscribeToMessageType(MT_OwnershipChanged);
componentManager.SubscribeToMessageType(MT_PositionChanged);
componentManager.SubscribeToMessageType(MT_TerrainChanged);
componentManager.SubscribeToMessageType(MT_WaterChanged);
// TODO: it'd be nice if we didn't get these messages except in the rare
// cases where we're actually drawing a selection highlight
}
DEFAULT_COMPONENT_ALLOCATOR(Selectable)
@@ -148,6 +144,10 @@ public:
m_OverlayDescriptor.m_LineTextureMask = CStrIntern(textureBasePath + outlineNode.GetChild("LineTextureMask").ToUTF8());
m_OverlayDescriptor.m_LineThickness = outlineNode.GetChild("LineThickness").ToFloat();
}
m_EnabledInterpolate = false;
m_EnabledRenderSubmit = false;
UpdateMessageSubscriptions();
}
virtual void Deinit() { }
@@ -200,11 +200,14 @@ public:
m_FadeBaselineAlpha = m_Color.a;
m_FadeDeltaAlpha = alpha - m_FadeBaselineAlpha;
m_FadeProgress = 0.f;
UpdateMessageSubscriptions();
}
virtual void SetVisibility(bool visible)
{
m_Visible = visible;
UpdateMessageSubscriptions();
}
virtual bool IsEditorOnly()
@@ -230,6 +233,16 @@ public:
/// Explicitly invalidates the static overlay.
void InvalidateStaticOverlay();
/**
* Subscribe/unsubscribe to MT_Interpolate, MT_RenderSubmit, depending on
* whether we will do any actual work when receiving them. (This is to avoid
* the performance cost of receiving messages in the typical case when the
* entity is not selected.)
*
* Must be called after changing m_Visible, m_FadeDeltaAlpha, m_Color.a
*/
void UpdateMessageSubscriptions();
private:
SOverlayDescriptor m_OverlayDescriptor;
SOverlayTexturedLine* m_BuildingOverlay;
@@ -238,6 +251,9 @@ private:
SOverlayLine* m_DebugBoundingBoxOverlay;
SOverlayLine* m_DebugSelectionBoxOverlay;
bool m_EnabledInterpolate;
bool m_EnabledRenderSubmit;
// Whether the selectable will be rendered.
bool m_Visible;
// Whether the entity is only selectable in Atlas editor
@@ -272,6 +288,8 @@ void CCmpSelectable::HandleMessage(const CMessage& msg, bool UNUSED(global))
{
case MT_Interpolate:
{
PROFILE3("Selectable::Interpolate");
const CMessageInterpolate& msgData = static_cast<const CMessageInterpolate&> (msg);
if (m_FadeDeltaAlpha != 0.f)
@@ -297,6 +315,8 @@ void CCmpSelectable::HandleMessage(const CMessage& msg, bool UNUSED(global))
if (m_Color.a > 0)
UpdateDynamicOverlay(msgData.offset);
UpdateMessageSubscriptions();
break;
}
case MT_OwnershipChanged:
@@ -333,6 +353,8 @@ void CCmpSelectable::HandleMessage(const CMessage& msg, bool UNUSED(global))
}
case MT_RenderSubmit:
{
PROFILE3("Selectable::RenderSubmit");
const CMessageRenderSubmit& msgData = static_cast<const CMessageRenderSubmit&> (msg);
RenderSubmit(msgData.collector);
@@ -341,6 +363,30 @@ void CCmpSelectable::HandleMessage(const CMessage& msg, bool UNUSED(global))
}
}
void CCmpSelectable::UpdateMessageSubscriptions()
{
bool needInterpolate = false;
bool needRenderSubmit = false;
if (m_FadeDeltaAlpha != 0.f || m_Color.a > 0)
needInterpolate = true;
if (m_Visible && m_Color.a > 0)
needRenderSubmit = true;
if (needInterpolate != m_EnabledInterpolate)
{
GetSimContext().GetComponentManager().DynamicSubscriptionNonsync(MT_Interpolate, this, needInterpolate);
m_EnabledInterpolate = needInterpolate;
}
if (needRenderSubmit != m_EnabledRenderSubmit)
{
GetSimContext().GetComponentManager().DynamicSubscriptionNonsync(MT_RenderSubmit, this, needRenderSubmit);
m_EnabledRenderSubmit = needRenderSubmit;
}
}
void CCmpSelectable::InvalidateStaticOverlay()
{
SAFE_DELETE(m_BuildingOverlay);