From 0d55df6dd188c3f5fb050878f0de041d3f13b4d0 Mon Sep 17 00:00:00 2001 From: rachytski Date: Sun, 29 Jul 2012 11:46:26 -0700 Subject: [PATCH] splitting the SkinPage::uploadQueue into small chunks and adding ECheckPoint packets between chunks for later fine-grained processing on GUI thread. --- yg/display_list.cpp | 5 ++++ yg/display_list.hpp | 1 + yg/geometry_renderer.cpp | 54 +++++++++++++++++++++++++++++++++++++--- yg/geometry_renderer.hpp | 6 +++++ yg/packets_queue.hpp | 2 +- yg/renderer.cpp | 14 ++++++++--- yg/renderer.hpp | 5 ++-- 7 files changed, 78 insertions(+), 9 deletions(-) diff --git a/yg/display_list.cpp b/yg/display_list.cpp index 2122475ea6..df25015d7b 100644 --- a/yg/display_list.cpp +++ b/yg/display_list.cpp @@ -84,6 +84,11 @@ namespace yg m_parent->processCommand(cmd); } + void DisplayList::addCheckPoint() + { + m_parent->addCheckPoint(); + } + void DisplayList::draw(math::Matrix const & m) { math::Matrix mv; diff --git a/yg/display_list.hpp b/yg/display_list.hpp index 0618cb91b4..3e81bc9a91 100644 --- a/yg/display_list.hpp +++ b/yg/display_list.hpp @@ -43,6 +43,7 @@ namespace yg void freeTexture(shared_ptr const & cmd); void freeStorage(shared_ptr const & cmd); void uploadData(shared_ptr const & cmd); + void addCheckPoint(); void draw(math::Matrix const & m); }; diff --git a/yg/geometry_renderer.cpp b/yg/geometry_renderer.cpp index 5efd6be78a..1279600968 100644 --- a/yg/geometry_renderer.cpp +++ b/yg/geometry_renderer.cpp @@ -83,15 +83,63 @@ namespace yg LOG(LINFO, ("UploadData: texture", m_texture->id(), ", count=", m_uploadQueue.size(), ", first=", r)); } - void GeometryRenderer::uploadTexture(SkinPage::TUploadQueue const & uploadQueue, - shared_ptr const & texture) + + void GeometryRenderer::uploadTextureImpl(SkinPage::TUploadQueue const & uploadQueue, + unsigned start, unsigned end, + shared_ptr const & texture, + bool shouldAddCheckPoint) { - shared_ptr command(new UploadData(uploadQueue, texture)); + vector > v; + v.reserve(end - start); + copy(&uploadQueue[0] + start, &uploadQueue[0] + end, back_inserter(v)); + + shared_ptr command(new UploadData(v, texture)); if (m_displayList) m_displayList->uploadData(command); else processCommand(command); + + if (shouldAddCheckPoint) + { + if (m_displayList) + m_displayList->addCheckPoint(); + else + addCheckPoint(); + } + } + + void GeometryRenderer::uploadTexture(SkinPage::TUploadQueue const & uploadQueue, + shared_ptr const & texture) + { + /// splitting the whole queue of commands into the chunks no more + /// than 100kb of uploadable data each + + /// tracking the number of bytes downloaded onto the texture + /// in a single shot. + unsigned bytesUploaded = 0; + unsigned bytesPerPixel = yg::formatSize(resourceManager()->params().m_texFormat); + unsigned prev = 0; + + for (unsigned i = 0; i < uploadQueue.size(); ++i) + { + shared_ptr const & style = uploadQueue[i]; + + bytesUploaded += style->m_texRect.SizeX() * style->m_texRect.SizeY() * bytesPerPixel; + + if (bytesUploaded > 64 * 1024) + { + uploadTextureImpl(uploadQueue, prev, i + 1, texture, true); + prev = i + 1; + bytesUploaded = 0; + } + } + + if (uploadQueue.size()) + { + uploadTextureImpl(uploadQueue, prev, uploadQueue.size(), texture, false); + bytesUploaded = 0; + } } void GeometryRenderer::DrawGeometry::perform() diff --git a/yg/geometry_renderer.hpp b/yg/geometry_renderer.hpp index ee48a84f55..b5cd195baf 100644 --- a/yg/geometry_renderer.hpp +++ b/yg/geometry_renderer.hpp @@ -23,6 +23,12 @@ namespace yg DisplayList * m_displayList; + void uploadTextureImpl(SkinPage::TUploadQueue const & uploadQueue, + unsigned start, + unsigned end, + shared_ptr const & texture, + bool shouldAddCheckPoint); + public: typedef Clipper base_t; diff --git a/yg/packets_queue.hpp b/yg/packets_queue.hpp index 2e2cded7cb..93bfeebf2c 100644 --- a/yg/packets_queue.hpp +++ b/yg/packets_queue.hpp @@ -79,7 +79,7 @@ namespace yg EType m_type; Packet(); - /// empty packet act as a frame delimiter + /// empty packet act as a frame delimiter or a checkpoint. explicit Packet(EType type); /// simple command Packet(shared_ptr const & command, diff --git a/yg/renderer.cpp b/yg/renderer.cpp index d1145e3cd4..d051f0b272 100644 --- a/yg/renderer.cpp +++ b/yg/renderer.cpp @@ -255,12 +255,14 @@ namespace yg void Renderer::processCommand(shared_ptr const & command, Packet::EType type, bool doForce) { - command->m_isDebugging = renderQueue() && !doForce; + if (command) + command->m_isDebugging = renderQueue() && !doForce; if (renderQueue() && !doForce) renderQueue()->processPacket(Packet(command, type)); else - command->perform(); + if (command) + command->perform(); } PacketsQueue * Renderer::renderQueue() @@ -268,12 +270,18 @@ namespace yg return m_renderQueue; } - void Renderer::markFrameBoundary() + void Renderer::addFramePoint() { if (m_renderQueue) m_renderQueue->processPacket(Packet(Packet::EFramePoint)); } + void Renderer::addCheckPoint() + { + if (m_renderQueue) + m_renderQueue->processPacket(Packet(Packet::ECheckPoint)); + } + void Renderer::completeCommands() { if (m_renderQueue) diff --git a/yg/renderer.hpp b/yg/renderer.hpp index f2d061ddd3..3b83a438e0 100644 --- a/yg/renderer.hpp +++ b/yg/renderer.hpp @@ -147,8 +147,9 @@ namespace yg void processCommand(shared_ptr const & command, Packet::EType type = Packet::ECommand, bool doForce = false); PacketsQueue * renderQueue(); - /// insert empty packet into glQueue to mark the frame boundary - void markFrameBoundary(); + void addCheckPoint(); + void addFramePoint(); + void completeCommands(); }; }