Skip to content

Commit

Permalink
[SUTK] Fixed inconsistent Renderable::update() calls and UIDriver::re…
Browse files Browse the repository at this point in the history
…nder() which led to high GPU usage
  • Loading branch information
ravi688 committed Dec 29, 2024
1 parent 96df9a1 commit bbb4185
Show file tree
Hide file tree
Showing 10 changed files with 71 additions and 30 deletions.
2 changes: 1 addition & 1 deletion sutk/include/sutk/Activatable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ namespace SUTK
public:
~Activatable() noexcept;

// mandatory to be called in overriding method
com::Bool isActive() const noexcept { return m_isActive; }
// mandatory to be called in overriding method
virtual void setActive(com::Bool isActive) noexcept;

// if called for the first time then it allocates memory for OnActiveEvent object
Expand Down
18 changes: 13 additions & 5 deletions sutk/include/sutk/NotebookView.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,21 +219,29 @@ namespace SUTK
NotebookPage* getRootPage() noexcept { return getTabBar()->getRootTab() ? getTabBar()->getRootTab()->getPage() : com::null_pointer<NotebookPage>(); }
NotebookPage* getCurrentPage() noexcept { return m_currentPage; }

template<NotebookPageType T>
T* createPage(const std::string_view labelStr, NotebookPage* afterPage = com::null_pointer<NotebookPage>()) noexcept;
template<NotebookPageType T = NotebookPage, typename... Args>
T* createPage(const std::string_view labelStr, Args&&... args) noexcept;
template<NotebookPageType T = NotebookPage, typename... Args>
T* createPageAfter(const std::string_view labelStr, NotebookPage* afterPage, Args&&... args) noexcept;
void viewPage(NotebookPage* page) noexcept;
void removePage(NotebookPage* page) noexcept;

void dump() noexcept;
};

template<NotebookPageType T, typename... Args>
T* NotebookView::createPage(const std::string_view labelStr, Args&&... args) noexcept
{
return createPageAfter<T, Args...>(labelStr, com::null_pointer<NotebookPage>(), std::forward<Args&&>(args)...);
}

template<NotebookPageType T>
T* NotebookView::createPage(const std::string_view labelStr, NotebookPage* afterPage) noexcept
template<NotebookPageType T, typename... Args>
T* NotebookView::createPageAfter(const std::string_view labelStr, NotebookPage* afterPage, Args&&... args) noexcept
{
// Create Container for the page
Container* container = createPageContainer();
// Create Page
T* page = getUIDriver().createObject<T>(container);
T* page = getUIDriver().createObject<T>(container, std::forward<Args&&>(args)...);
// Create Tab for the page
Tab* tab = createTab(labelStr, page, afterPage ? afterPage->getTab() : com::null_pointer<Tab>());
// Subscribe to tab select and deselect events to activate or deactivate the associate page
Expand Down
27 changes: 17 additions & 10 deletions sutk/include/sutk/Renderable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ namespace SUTK
RenderableContainer* m_container;
u32 m_drawOrder;
bool m_isDrawOrderDirty;
// Initially it is set to false
com::Bool m_isActiveDirty { };
com::Bool m_isRedraw;

// Called by UIDriver to reset the redraw flag
Expand Down Expand Up @@ -49,12 +51,25 @@ namespace SUTK
Renderable(UIDriver& driver, RenderableContainer* container = NULL) noexcept;
virtual ~Renderable() noexcept;

// Override of Activatable::setActive()
virtual void setActive(com::Bool isActive) noexcept;

// returns true, if GPU side data is out of sync with respect to the CPU side data, otherwise false
virtual bool isDirty() = 0;
// Must be called in the overriding method
virtual bool isDirty();
// updates (copies CPU side data to) GPU side data, and it may also create or recreate exisiting GPU Driver objects
virtual void update() = 0;
// Must be called in the overriding method
virtual void update();

bool isDrawOrderDirty() const noexcept { return m_isDrawOrderDirty; }
com::Bool isActiveDirty() const noexcept { return m_isActiveDirty; }
// Example:
// In Frame 0:
// setActive(com::False)
// isActiveForThisFrame() -> returns com::True
// In Frame 1:
// isActiveForThisFrame() -> returns com::False, given that update() has been called
com::Bool isActiveForThisFrame() const noexcept { return isActiveDirty() || isActive(); }

u32 getDrawOrder() const noexcept { return m_drawOrder; }

Expand Down Expand Up @@ -87,10 +102,6 @@ namespace SUTK
GfxDriverRenderable(UIDriver& driver, RenderableContainer* container = NULL) noexcept : Renderable(driver, container), m_handle(GFX_DRIVER_OBJECT_NULL_HANDLE) { }
virtual ~GfxDriverRenderable() = default;

// Implementation of Renderable
virtual bool isDirty() = 0;
virtual void update() = 0;

virtual void destroy() { }

void setClipRectGlobalCoords(const Rect2Df rect) noexcept;
Expand All @@ -110,9 +121,5 @@ namespace SUTK
GeometryRenderable(UIDriver& driver, RenderableContainer* container = NULL, RenderMode renderMode = RenderMode::Opaque) noexcept : GfxDriverRenderable(driver, container), m_geometry(driver, renderMode) { }
virtual ~GeometryRenderable() = default;
Geometry& getGeometry() noexcept { return m_geometry; }

// Implementation of GfxDriverRenderable
virtual bool isDirty() = 0;
virtual void update() = 0;
};
}
1 change: 0 additions & 1 deletion sutk/include/sutk/Text.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ namespace SUTK
// distance between two consecutive base lines in centimeters
f32 m_baselineHeight;

bool m_isDirty;
bool m_isClippingEnabled;

// data and rendering attributes
Expand Down
4 changes: 3 additions & 1 deletion sutk/source/RenderRect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@ namespace SUTK

bool RenderRect::isDirty() noexcept
{
return isRectDirty() || m_isColorDirty || m_isGeometryDirty;
return GeometryRenderable::isDirty() || isRectDirty() || m_isColorDirty || m_isGeometryDirty;
}

void RenderRect::update() noexcept
{
// Mandatory to be called in the overriding method
GeometryRenderable::update();
if(m_isPosDirty)
{
// auto& gfxDriver = getGfxDriver();
Expand Down
4 changes: 3 additions & 1 deletion sutk/source/RenderRectArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@ namespace SUTK

bool RenderRectFillArray::isDirty()
{
return m_isRectsDirty || m_isColorDirty || m_isActiveDirty;
return GeometryRenderable::isDirty() || m_isRectsDirty || m_isColorDirty || m_isActiveDirty;
}

void RenderRectFillArray::update()
{
// Mandatory to be called in the overriding method
GeometryRenderable::update();
if(m_isActiveDirty)
{
auto handle = getGfxDriverObjectHandle();
Expand Down
17 changes: 17 additions & 0 deletions sutk/source/Renderable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,23 @@ namespace SUTK
setDrawOrder(getContainer()->getDepth());
}

void Renderable::setActive(com::Bool isActive) noexcept
{
if(Activatable::isActive() != isActive)
m_isActiveDirty = com::True;
Activatable::setActive(isActive);
}

bool Renderable::isDirty()
{
return static_cast<bool>(m_isActiveDirty);
}

void Renderable::update()
{
m_isActiveDirty = com::False;
}

void GfxDriverRenderable::setClipRectGlobalCoords(const Rect2Df rect) noexcept
{
auto handle = getGfxDriverObjectHandle();
Expand Down
14 changes: 9 additions & 5 deletions sutk/source/SmallText.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,13 @@ namespace SUTK

bool SmallText::isDirty()
{
return m_isPosDirty || m_isDataDirty || m_isPointSizeDirty || m_isColorRangesDirty || m_isColorDirty;
return GfxDriverRenderable::isDirty() || m_isPosDirty || m_isDataDirty || m_isPointSizeDirty || m_isColorRangesDirty || m_isColorDirty;
}
void SmallText::update()
{
// Mandatory to be called in the overriding method
GfxDriverRenderable::update();

// NOTE: Order of function calls are important here

// should be updated before any updates to character array
Expand All @@ -64,15 +67,14 @@ namespace SUTK

if(m_isPosDirty)
{
// This must be set false before calling getAlignedPosition() to avoid non-terminating recursion
m_isPosDirty = false;
Vec2Df pos = m_pos;
if(getContainer() != NULL)
{
pos = getAlignedPosition(m_pos);
pos = getContainer()->getLocalCoordsToScreenCoords(pos);
}
getGfxDriver().setTextPosition(getGfxDriverObjectHandle(), { pos.x, pos.y, 0.0f });
m_isPosDirty = false;
}

// should be updated after character array has been updated with setTextData().
Expand Down Expand Up @@ -122,14 +124,16 @@ namespace SUTK
LineCountType SmallText::getColPosFromCoord(f32 coord) noexcept
{
// Ensure GPU side data is updated so that we get correct output from getTextGlyphIndexFromCoord()
if(isDirty())
// NOTE: Data (chars) and PointSize both affect the value returned by getTextGlyphIndexFromCoord()
if(m_isDataDirty || m_isPointSizeDirty)
update();
return getGfxDriver().getTextGlyphIndexFromCoord(getGfxDriverObjectHandle(), coord);
}
f32 SmallText::getCoordFromColPos(LineCountType col) noexcept
{
// Ensure GPU side data is updated so that we get correct output from getTextGlyphIndexFromCoord()
if(isDirty())
// NOTE: Data (chars) and PointSize both affect the value returned by getTextGlyphIndexFromCoord()
if(m_isDataDirty || m_isPointSizeDirty)
update();
return getGfxDriver().getTextCoordFromGlyphIndex(getGfxDriverObjectHandle(), col);
}
Expand Down
6 changes: 4 additions & 2 deletions sutk/source/Text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace SUTK
template<> CursorPosition<LineCountType> CursorPosition<LineCountType>::EndOfText() { return { END_OF_TEXT, END_OF_LINE }; }
template<> CursorPosition<LineCountType> CursorPosition<LineCountType>::EndOfLine(LineCountType line) { return { line, END_OF_LINE }; }

Text::Text(UIDriver& driver, RenderableContainer* container) noexcept : Renderable(driver, container), m_textGroup(GFX_DRIVER_OBJECT_NULL_HANDLE), m_baselineHeight(0), m_isDirty(false), m_isClippingEnabled(false), m_color(SUTK::Color4::yellow()), m_pointSize(12)
Text::Text(UIDriver& driver, RenderableContainer* container) noexcept : Renderable(driver, container), m_textGroup(GFX_DRIVER_OBJECT_NULL_HANDLE), m_baselineHeight(0), m_isClippingEnabled(false), m_color(SUTK::Color4::yellow()), m_pointSize(12)
{
m_textGroup = getGfxDriver().createTextGroup(RenderMode::Transparent);
m_baselineHeight = getGfxDriver().getTextGroupBaselineHeightInCentimeters(m_textGroup, m_pointSize);
Expand Down Expand Up @@ -50,7 +50,7 @@ namespace SUTK

bool Text::isDirty()
{
if(m_isDirty)
if(Renderable::isDirty())
return true;

for(std::size_t i = 0; i < m_lines.size(); i++)
Expand All @@ -62,6 +62,8 @@ namespace SUTK

void Text::update()
{
// Mandatory to be called in the overriding method
Renderable::update();
for(std::size_t i = 0; i < m_lines.size(); i++)
{
LineText* line = m_lines[i];
Expand Down
8 changes: 4 additions & 4 deletions sutk/source/UIDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,17 +95,17 @@ namespace SUTK
for(auto it = m_renderables.begin(); it != m_renderables.end(); it++)
{
Renderable* renderable = *it;
if(!isRerender && renderable->isRedraw())
if(!isRerender && renderable->isActiveForThisFrame() && renderable->isRedraw())
{
isRerender = com::True;
renderable->setRedraw(com::False);
}
// Only update Renderables which are active and dirty
if(renderable->isActive() && renderable->isDirty())
if(renderable->isActiveForThisFrame() && renderable->isDirty())
renderable->update();
// If at least Renderable's draw order is dirty then normalized draw orders need to be re-calculated
// and passed to the GPU driver
if(!isRecalculateDrawOrder && renderable->isDrawOrderDirty())
if(!isRecalculateDrawOrder && renderable->isActiveForThisFrame() && renderable->isDrawOrderDirty())
isRecalculateDrawOrder = com::True;
// Keep track of minimum and maximum draw order values
u32 drawOrder = renderable->getDrawOrder();
Expand Down Expand Up @@ -134,7 +134,7 @@ namespace SUTK
for(auto it = m_renderables.begin(); it != m_renderables.end(); it++)
{
Renderable* renderable = (*it);
if(isDrawOrderRangeChanged || renderable->isDrawOrderDirty())
if(isDrawOrderRangeChanged || (renderable->isActiveForThisFrame() && renderable->isDrawOrderDirty()))
{
auto normDrawOrder = drawOrderRange ? ((1.0f - static_cast<f32>(renderable->getDrawOrder() - minDrawOrder) * normalizeFactor) * 99.0f) : 0;
renderable->updateNormalizedDrawOrder(normDrawOrder);
Expand Down

0 comments on commit bbb4185

Please sign in to comment.