implement load/unload frames
This commit is contained in:
@@ -9,6 +9,7 @@ RTT& Layer::rtt(int i, int frame /*= -1*/)
|
||||
{
|
||||
if (frame == -1)
|
||||
frame = m_frame_index;
|
||||
assert(m_frames[frame].m_rtt[i].valid());
|
||||
return m_frames[frame].m_rtt[i];
|
||||
}
|
||||
|
||||
@@ -145,71 +146,22 @@ void Layer::optimize(int frame /*= -1*/)
|
||||
LOG("optimized %d bytes", saved_bytes);
|
||||
}
|
||||
|
||||
void Layer::restore(const Snapshot& snap, int frame /*= -1*/)
|
||||
void Layer::restore(const LayerFrame::Snapshot& snap, int frame /*= -1*/)
|
||||
{
|
||||
if (frame == -1)
|
||||
frame = m_frame_index;
|
||||
clear({ 0, 0, 0, 0 }, frame);
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (snap.image[i] == nullptr || snap.m_dirty_face[i] == false || box_area(snap.m_dirty_box[i]) <= 0)
|
||||
{
|
||||
box(i, frame) = glm::vec4(snap.width, snap.height, 0, 0);
|
||||
face(i, frame) = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
box(i, frame) = snap.m_dirty_box[i];
|
||||
face(i, frame) = snap.m_dirty_face[i];
|
||||
|
||||
// TODO: this should not be recreated here!
|
||||
// Sorry I messed up with this,
|
||||
// it's just a quick fix DON'T SHIP!!
|
||||
//m_rtt[i].recreate();
|
||||
|
||||
App::I->render_task_async([this, i, &snap, frame]
|
||||
{
|
||||
rtt(i, frame).bindTexture();
|
||||
glm::vec2 box_sz = zw(box(i, frame)) - xy(box(i, frame));
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||
box(i, frame).x, box(i, frame).y,
|
||||
box_sz.x, box_sz.y, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
snap.image[i].get());
|
||||
rtt(i, frame).unbindTexture();
|
||||
LOG("restore frame %d face %d - %d bytes (%dx%d)", frame, i,
|
||||
(int)box_sz.x * (int)box_sz.y * 4, (int)box_sz.x, (int)box_sz.y);
|
||||
});
|
||||
}
|
||||
App::I->render_sync();
|
||||
auto loaded = m_frames[frame].gpu_load();
|
||||
m_frames[frame].restore(snap);
|
||||
if (!loaded) m_frames[frame].gpu_unload();
|
||||
}
|
||||
|
||||
Layer::Snapshot Layer::snapshot(int frame /*= -1*/, std::array<glm::vec4, 6>* dirty_box /*= nullptr*/, std::array<bool, 6>* dirty_face /*= nullptr*/)
|
||||
LayerFrame::Snapshot Layer::snapshot(int frame /*= -1*/, std::array<glm::vec4, 6>* dirty_box /*= nullptr*/, std::array<bool, 6>* dirty_face /*= nullptr*/)
|
||||
{
|
||||
if (frame == -1)
|
||||
frame = m_frame_index;
|
||||
Snapshot snap;
|
||||
snap.width = w;
|
||||
snap.height = h;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
snap.m_dirty_box[i] = dirty_box ? dirty_box->at(i) : box(i, frame);
|
||||
snap.m_dirty_face[i] = dirty_face ? dirty_face->at(i) : face(i, frame);
|
||||
|
||||
if (!snap.m_dirty_face[i])
|
||||
continue;
|
||||
|
||||
snap.image[i] = std::make_unique<uint8_t[]>(rtt(i, frame).bytes());
|
||||
|
||||
App::I->render_task_async([this, i, &snap, frame]
|
||||
{
|
||||
rtt(i, frame).bindFramebuffer();
|
||||
glm::vec2 box_sz = zw(snap.m_dirty_box[i]) - xy(snap.m_dirty_box[i]);
|
||||
glReadPixels(snap.m_dirty_box[i].x, snap.m_dirty_box[i].y,
|
||||
box_sz.x, box_sz.y, GL_RGBA, GL_UNSIGNED_BYTE, snap.image[i].get());
|
||||
rtt(i, frame).unbindFramebuffer();
|
||||
});
|
||||
}
|
||||
App::I->render_sync();
|
||||
auto loaded = m_frames[frame].gpu_load();
|
||||
auto snap = m_frames[frame].snapshot(dirty_box, dirty_face);
|
||||
if (!loaded) m_frames[frame].gpu_unload();
|
||||
return snap;
|
||||
}
|
||||
|
||||
@@ -229,24 +181,45 @@ bool Layer::create(int width, int height, std::string name)
|
||||
m_frames.clear();
|
||||
m_frames.emplace_back();
|
||||
m_frames.back().create(width, height);
|
||||
frames_gpu_update();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Layer::add_frame()
|
||||
{
|
||||
m_frames.emplace_back();
|
||||
return m_frames.back().create(w, h);
|
||||
m_frames.back().create(w, h);
|
||||
frames_gpu_update();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Layer::remove_frame(int frame)
|
||||
{
|
||||
m_frames.erase(m_frames.begin() + frame);
|
||||
m_frame_index = glm::clamp(m_frame_index, 0, (int)m_frames.size() - 1);
|
||||
frames_gpu_update();
|
||||
}
|
||||
|
||||
void Layer::duplicate_frame(int frame)
|
||||
{
|
||||
m_frames.insert(m_frames.begin() + frame + 1, m_frames[frame].clone());
|
||||
frames_gpu_update();
|
||||
}
|
||||
|
||||
void Layer::frames_gpu_update()
|
||||
{
|
||||
App::I->render_task_async([=]
|
||||
{
|
||||
for (int j = 0; j < m_frames.size(); j++)
|
||||
{
|
||||
int dist = glm::abs(j - m_frame_index);
|
||||
int onion = App::I->animation ? App::I->animation->get_onion_size() : 1;
|
||||
if (dist <= onion)
|
||||
m_frames[j].gpu_load();
|
||||
else
|
||||
m_frames[j].gpu_unload();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
int Layer::total_duration() const noexcept
|
||||
@@ -263,6 +236,8 @@ void Layer::goto_frame(int frame) noexcept
|
||||
for (i = 0; i < m_frames.size() && frame >= 0; i++)
|
||||
frame -= m_frames[i].m_duration;
|
||||
m_frame_index = i - 1;
|
||||
m_frames[m_frame_index].gpu_load();
|
||||
frames_gpu_update();
|
||||
}
|
||||
|
||||
void Layer::resize(int width, int height)
|
||||
@@ -275,7 +250,7 @@ void Layer::resize(int width, int height)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Layer::Snapshot::create(int w, int h)
|
||||
void LayerFrame::Snapshot::create(int w, int h)
|
||||
{
|
||||
width = w;
|
||||
height = h;
|
||||
@@ -288,7 +263,7 @@ void Layer::Snapshot::create(int w, int h)
|
||||
}
|
||||
}
|
||||
|
||||
void Layer::Snapshot::clear()
|
||||
void LayerFrame::Snapshot::clear()
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
@@ -298,7 +273,7 @@ void Layer::Snapshot::clear()
|
||||
}
|
||||
}
|
||||
|
||||
void Layer::Snapshot::optimize()
|
||||
void LayerFrame::Snapshot::optimize()
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
@@ -322,7 +297,7 @@ void Layer::Snapshot::optimize()
|
||||
}
|
||||
}
|
||||
|
||||
int Layer::Snapshot::memsize() const
|
||||
int LayerFrame::Snapshot::memsize() const
|
||||
{
|
||||
int ret = 0;
|
||||
for (int i = 0; i < 6; i++)
|
||||
@@ -372,22 +347,28 @@ LayerFrame& LayerFrame::operator=(LayerFrame&& other)
|
||||
bool LayerFrame::create(int width, int height, int duration /*= 1*/)
|
||||
{
|
||||
bool success = true;
|
||||
App::I->render_task([&]
|
||||
//App::I->render_task([&]
|
||||
//{
|
||||
// for (int i = 0; i < 6; i++)
|
||||
// {
|
||||
// if (!m_rtt[i].create(width, height))
|
||||
// {
|
||||
// success = false;
|
||||
// return;
|
||||
// }
|
||||
// m_rtt[i].bindFramebuffer();
|
||||
// m_rtt[i].clear();
|
||||
// m_rtt[i].unbindFramebuffer();
|
||||
// m_dirty_box[i] = glm::vec4(width, height, 0, 0); // reset bounding box
|
||||
// m_dirty_face[i] = false;
|
||||
// }
|
||||
//});
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (!m_rtt[i].create(width, height))
|
||||
{
|
||||
success = false;
|
||||
return;
|
||||
}
|
||||
m_rtt[i].bindFramebuffer();
|
||||
m_rtt[i].clear();
|
||||
m_rtt[i].unbindFramebuffer();
|
||||
m_dirty_box[i] = glm::vec4(width, height, 0, 0); // reset bounding box
|
||||
m_dirty_face[i] = false;
|
||||
}
|
||||
});
|
||||
m_dirty_box[i] = glm::vec4(width, height, 0, 0); // reset bounding box
|
||||
m_dirty_face[i] = false;
|
||||
}
|
||||
m_gpu_data = nullptr;
|
||||
m_duration = duration;
|
||||
w = width;
|
||||
h = height;
|
||||
@@ -396,6 +377,7 @@ bool LayerFrame::create(int width, int height, int duration /*= 1*/)
|
||||
|
||||
bool LayerFrame::resize(int width, int height)
|
||||
{
|
||||
bool loaded = gpu_load();
|
||||
glm::vec2 ratio = glm::vec2(width, height) / glm::vec2(w, h);
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
@@ -405,6 +387,7 @@ bool LayerFrame::resize(int width, int height)
|
||||
}
|
||||
w = width;
|
||||
h = height;
|
||||
if (!loaded) gpu_unload();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -442,17 +425,113 @@ void LayerFrame::clear(const glm::vec4& c)
|
||||
});
|
||||
}
|
||||
|
||||
LayerFrame LayerFrame::clone() const noexcept
|
||||
LayerFrame LayerFrame::clone() noexcept
|
||||
{
|
||||
LayerFrame dup;
|
||||
dup.m_duration = m_duration;
|
||||
dup.w = w;
|
||||
dup.h = h;
|
||||
bool loaded = gpu_load();
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
dup.m_rtt[i] = m_rtt[i].clone();
|
||||
dup.m_dirty_box[i] = m_dirty_box[i];
|
||||
dup.m_dirty_face[i] = m_dirty_face[i];
|
||||
}
|
||||
if (!loaded) gpu_unload();
|
||||
return dup;
|
||||
}
|
||||
|
||||
void LayerFrame::restore(const Snapshot& snap)
|
||||
{
|
||||
App::I->render_task([this, &snap]
|
||||
{
|
||||
clear({ 0, 0, 0, 0 });
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (!m_rtt[i].valid())
|
||||
m_rtt[i].create(w, h);
|
||||
|
||||
if (snap.image[i] == nullptr || snap.m_dirty_face[i] == false || box_area(snap.m_dirty_box[i]) <= 0)
|
||||
{
|
||||
m_dirty_box[i] = glm::vec4(snap.width, snap.height, 0, 0);
|
||||
m_dirty_face[i] = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
m_dirty_box[i] = snap.m_dirty_box[i];
|
||||
m_dirty_face[i] = snap.m_dirty_face[i];
|
||||
|
||||
// TODO: this should not be recreated here!
|
||||
// Sorry I messed up with this,
|
||||
// it's just a quick fix DON'T SHIP!!
|
||||
//m_rtt[i].recreate();
|
||||
|
||||
m_rtt[i].bindTexture();
|
||||
glm::vec2 box_sz = zw(m_dirty_box[i]) - xy(m_dirty_box[i]);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||
m_dirty_box[i].x, m_dirty_box[i].y,
|
||||
box_sz.x, box_sz.y, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
snap.image[i].get());
|
||||
m_rtt[i].unbindTexture();
|
||||
LOG("restore face %d - %d bytes (%dx%d)", i,
|
||||
(int)box_sz.x * (int)box_sz.y * 4, (int)box_sz.x, (int)box_sz.y);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
LayerFrame::Snapshot LayerFrame::snapshot(std::array<glm::vec4, 6>* dirty_box /*= nullptr*/, std::array<bool, 6>* dirty_face /*= nullptr*/)
|
||||
{
|
||||
Snapshot snap;
|
||||
snap.width = w;
|
||||
snap.height = h;
|
||||
App::I->render_task([this, &snap, dirty_face, dirty_box]
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
snap.m_dirty_box[i] = dirty_box ? dirty_box->at(i) : m_dirty_box[i];
|
||||
snap.m_dirty_face[i] = dirty_face ? dirty_face->at(i) : m_dirty_face[i];
|
||||
|
||||
if (!snap.m_dirty_face[i] || !m_rtt[i].valid())
|
||||
continue;
|
||||
|
||||
snap.image[i] = std::make_unique<uint8_t[]>(m_rtt[i].bytes());
|
||||
|
||||
m_rtt[i].bindFramebuffer();
|
||||
glm::vec2 box_sz = zw(snap.m_dirty_box[i]) - xy(snap.m_dirty_box[i]);
|
||||
glReadPixels(snap.m_dirty_box[i].x, snap.m_dirty_box[i].y,
|
||||
box_sz.x, box_sz.y, GL_RGBA, GL_UNSIGNED_BYTE, snap.image[i].get());
|
||||
m_rtt[i].unbindFramebuffer();
|
||||
}
|
||||
});
|
||||
return snap;
|
||||
}
|
||||
|
||||
bool LayerFrame::gpu_load() noexcept
|
||||
{
|
||||
if (m_gpu_data)
|
||||
{
|
||||
restore(*m_gpu_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& rtt : m_rtt)
|
||||
if (!rtt.valid())
|
||||
rtt.create(w, h);
|
||||
}
|
||||
m_gpu_data.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LayerFrame::gpu_unload() noexcept
|
||||
{
|
||||
bool ret = false; // already unloaded from gpu
|
||||
if (!m_gpu_data)
|
||||
{
|
||||
m_gpu_data = std::make_unique<Snapshot>(snapshot());
|
||||
ret = true; // previous state was loaded on gpu
|
||||
}
|
||||
for (auto& rtt : m_rtt)
|
||||
rtt.destroy();
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user