use PBO for timelapse data read

This commit is contained in:
2019-11-05 18:25:25 +01:00
parent 4b6316bf68
commit 52ad58aec4
8 changed files with 212 additions and 9 deletions

View File

@@ -792,7 +792,7 @@ void App::rec_loop()
rec_running = true;
while(rec_running)
{
std::unique_ptr<Image> frame;
std::unique_ptr<PBO> frame;
std::unique_lock<std::mutex> lock(rec_mutex);
rec_cv.wait(lock, [this] { return !(rec_frames.empty() && rec_running); });
if (!rec_running)
@@ -809,7 +809,10 @@ void App::rec_loop()
lock.unlock();
if (frame && Canvas::I->m_encoder)
{
Canvas::I->m_encoder->encode(*frame);
ImageRef img;
img.create(frame->width, frame->height, frame->map());
Canvas::I->m_encoder->encode(img);
frame->unmap();
LOG("frame encoded");
}
update_rec_frames();

View File

@@ -96,7 +96,7 @@ public:
int rec_count = 0;
std::mutex rec_mutex;
std::condition_variable rec_cv;
std::deque<std::unique_ptr<Image>> rec_frames;
std::deque<std::unique_ptr<PBO>> rec_frames;
RTT uirtt;
Sampler sampler;

View File

@@ -89,18 +89,16 @@ void App::tick(float dt)
canvas->m_canvas->m_dirty_stroke = false;
LOG("rec tick");
Texture2D equirect;
PBO equirect;
App::I->render_task([&] {
Canvas::I->draw_merge(true);
equirect = Canvas::I->m_layers_merge.gen_equirect(Canvas::I->m_encoder->frame_size() / 4);
equirect = Canvas::I->m_layers_merge.gen_equirect_pbo(Canvas::I->m_encoder->frame_size() / 4);
});
auto img = std::make_unique<Image>(equirect.get_image());
{
std::lock_guard<std::mutex> lock(rec_mutex);
rec_frames.emplace_back(std::move(img));
rec_frames.emplace_back(std::make_unique<PBO>(std::move(equirect)));
rec_cv.notify_all();
}
equirect.destroy();
}
}
}

View File

@@ -101,6 +101,49 @@ Texture2D Layer::gen_equirect(glm::ivec2 size /*= { 0, 0 }*/)
return ret;
}
PBO Layer::gen_equirect_pbo(glm::ivec2 size /*= { 0, 0 }*/)
{
PBO pbo;
App::I->render_task([&]
{
gl_state gl;
gl.save();
TextureCube cube;
RTT latlong;
if (size.x == 0 || size.y == 0)
size = { w, h };
cube = gen_cube();
latlong.create(size.x * 4, size.y * 2);
glDisable(GL_BLEND);
latlong.bindFramebuffer();
latlong.clear({ 0, 1, 1, 1 });
glViewport(0, 0, latlong.getWidth(), latlong.getHeight());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, cube.m_cubetex_id);
ShaderManager::use(kShader::Equirect);
ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
ShaderManager::u_int(kShaderUniform::Tex, 0);
Canvas::I->m_sampler.bind(0);
Canvas::I->m_plane.draw_fill();
latlong.unbindFramebuffer();
pbo.create(latlong);
latlong.destroy();
cube.destroy();
gl.restore();
});
return pbo;
}
void Layer::destroy()
{
for (int i = 0; i < 6; i++)

View File

@@ -82,6 +82,7 @@ public:
LayerFrame::Snapshot snapshot(int frame = -1, std::array<glm::vec4, 6>* dirty_box = nullptr, std::array<bool, 6>* dirty_face = nullptr);
TextureCube gen_cube();
Texture2D gen_equirect(glm::ivec2 size = { 0, 0 });
PBO gen_equirect_pbo(glm::ivec2 size = { 0, 0 });
void restore(const LayerFrame::Snapshot& snap, int frame = -1);
void destroy();
void optimize(int frame = -1);

View File

@@ -38,7 +38,7 @@ public:
{
std::copy(data, data + size(), m_data.get());
}
void destroy()
virtual void destroy()
{
width = 0;
height = 0;
@@ -56,3 +56,20 @@ public:
bool read(BinaryStreamReader& r) override;
void write(BinaryStreamWriter& w) const override;
};
class ImageRef : public Image
{
public:
~ImageRef()
{
m_data.release();
}
virtual void destroy() override
{
width = 0;
height = 0;
comp = 0;
file_base = file_name = file_ext = "";
m_data.release();
}
};

View File

@@ -411,3 +411,114 @@ bool RTT::valid() const noexcept
{
return texID || rboID || fboID;
}
//////////////////////////////////////////////////////////////////////////
PBO::PBO(PBO&& other) noexcept
{
bound_slot = other.bound_slot;
buffer_id = other.buffer_id;
mapped_ptr = other.mapped_ptr;
width = other.width;
height = other.height;
other.bound_slot = 0;
other.buffer_id = 0;
other.mapped_ptr = nullptr;
other.width = 0;
other.height = 0;
}
PBO& PBO::operator=(PBO&& other) noexcept
{
bound_slot = other.bound_slot;
buffer_id = other.buffer_id;
mapped_ptr = other.mapped_ptr;
width = other.width;
height = other.height;
other.bound_slot = 0;
other.buffer_id = 0;
other.mapped_ptr = nullptr;
other.width = 0;
other.height = 0;
return *this;
}
PBO::~PBO() noexcept
{
destroy();
}
bool PBO::create() noexcept
{
App::I->render_task([this] {
glGenBuffers(1, &buffer_id);
});
return true;
}
bool PBO::create(RTT& rtt) noexcept
{
App::I->render_task([this, &rtt] {
width = rtt.getWidth();
height = rtt.getHeight();
rtt.bindFramebuffer();
glGenBuffers(1, &buffer_id);
glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer_id);
glBufferData(GL_PIXEL_PACK_BUFFER, width * height * 4, 0, GL_STREAM_DRAW);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
rtt.unbindFramebuffer();
});
return true;
}
void PBO::destroy() noexcept
{
if (buffer_id)
{
App::I->render_task_async([id=buffer_id] {
glDeleteBuffers(1, &id);
});
buffer_id = 0;
bound_slot = 0;
width = 0;
height = 0;
mapped_ptr = nullptr;
}
}
/*
void PBO::bind_read() noexcept
{
App::I->render_task([this] {
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer_id);
bound_slot = GL_PIXEL_UNPACK_BUFFER;
});
}
void PBO::unbind() noexcept
{
App::I->render_task([this] {
glBindBuffer(bound_slot, buffer_id);
});
}
*/
glm::uint8_t* PBO::map() noexcept
{
App::I->render_task([this] {
glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer_id);
mapped_ptr = (GLubyte*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
});
return mapped_ptr;
}
void PBO::unmap() noexcept
{
App::I->render_task([this] {
glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer_id);
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
});
}

View File

@@ -1,6 +1,36 @@
#pragma once
#include "image.h"
struct PBO
{
// copy
PBO(const PBO&) = delete;
PBO& operator=(const PBO&) = delete;
// move
PBO(PBO&& other) noexcept;
PBO& operator=(PBO&&) noexcept;
// default
PBO() noexcept = default;
~PBO() noexcept;
GLuint buffer_id = 0;
GLenum bound_slot = 0;
GLubyte* mapped_ptr = nullptr;
int width = 0;
int height = 0;
bool create() noexcept;
bool create(class RTT& rtt) noexcept;
void destroy() noexcept;
/*
void bind_read() noexcept;
void unbind() noexcept;
*/
uint8_t* map() noexcept;
void unmap() noexcept;
};
class RTT
{
int w = 0;