use PBO for timelapse data read
This commit is contained in:
@@ -792,7 +792,7 @@ void App::rec_loop()
|
|||||||
rec_running = true;
|
rec_running = true;
|
||||||
while(rec_running)
|
while(rec_running)
|
||||||
{
|
{
|
||||||
std::unique_ptr<Image> frame;
|
std::unique_ptr<PBO> frame;
|
||||||
std::unique_lock<std::mutex> lock(rec_mutex);
|
std::unique_lock<std::mutex> lock(rec_mutex);
|
||||||
rec_cv.wait(lock, [this] { return !(rec_frames.empty() && rec_running); });
|
rec_cv.wait(lock, [this] { return !(rec_frames.empty() && rec_running); });
|
||||||
if (!rec_running)
|
if (!rec_running)
|
||||||
@@ -809,7 +809,10 @@ void App::rec_loop()
|
|||||||
lock.unlock();
|
lock.unlock();
|
||||||
if (frame && Canvas::I->m_encoder)
|
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");
|
LOG("frame encoded");
|
||||||
}
|
}
|
||||||
update_rec_frames();
|
update_rec_frames();
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ public:
|
|||||||
int rec_count = 0;
|
int rec_count = 0;
|
||||||
std::mutex rec_mutex;
|
std::mutex rec_mutex;
|
||||||
std::condition_variable rec_cv;
|
std::condition_variable rec_cv;
|
||||||
std::deque<std::unique_ptr<Image>> rec_frames;
|
std::deque<std::unique_ptr<PBO>> rec_frames;
|
||||||
|
|
||||||
RTT uirtt;
|
RTT uirtt;
|
||||||
Sampler sampler;
|
Sampler sampler;
|
||||||
|
|||||||
@@ -89,18 +89,16 @@ void App::tick(float dt)
|
|||||||
canvas->m_canvas->m_dirty_stroke = false;
|
canvas->m_canvas->m_dirty_stroke = false;
|
||||||
LOG("rec tick");
|
LOG("rec tick");
|
||||||
|
|
||||||
Texture2D equirect;
|
PBO equirect;
|
||||||
App::I->render_task([&] {
|
App::I->render_task([&] {
|
||||||
Canvas::I->draw_merge(true);
|
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);
|
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();
|
rec_cv.notify_all();
|
||||||
}
|
}
|
||||||
equirect.destroy();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,6 +101,49 @@ Texture2D Layer::gen_equirect(glm::ivec2 size /*= { 0, 0 }*/)
|
|||||||
return ret;
|
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()
|
void Layer::destroy()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
|
|||||||
@@ -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);
|
LayerFrame::Snapshot snapshot(int frame = -1, std::array<glm::vec4, 6>* dirty_box = nullptr, std::array<bool, 6>* dirty_face = nullptr);
|
||||||
TextureCube gen_cube();
|
TextureCube gen_cube();
|
||||||
Texture2D gen_equirect(glm::ivec2 size = { 0, 0 });
|
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 restore(const LayerFrame::Snapshot& snap, int frame = -1);
|
||||||
void destroy();
|
void destroy();
|
||||||
void optimize(int frame = -1);
|
void optimize(int frame = -1);
|
||||||
|
|||||||
19
src/image.h
19
src/image.h
@@ -38,7 +38,7 @@ public:
|
|||||||
{
|
{
|
||||||
std::copy(data, data + size(), m_data.get());
|
std::copy(data, data + size(), m_data.get());
|
||||||
}
|
}
|
||||||
void destroy()
|
virtual void destroy()
|
||||||
{
|
{
|
||||||
width = 0;
|
width = 0;
|
||||||
height = 0;
|
height = 0;
|
||||||
@@ -56,3 +56,20 @@ public:
|
|||||||
bool read(BinaryStreamReader& r) override;
|
bool read(BinaryStreamReader& r) override;
|
||||||
void write(BinaryStreamWriter& w) const 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();
|
||||||
|
}
|
||||||
|
};
|
||||||
111
src/rtt.cpp
111
src/rtt.cpp
@@ -411,3 +411,114 @@ bool RTT::valid() const noexcept
|
|||||||
{
|
{
|
||||||
return texID || rboID || fboID;
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
30
src/rtt.h
30
src/rtt.h
@@ -1,6 +1,36 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "image.h"
|
#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
|
class RTT
|
||||||
{
|
{
|
||||||
int w = 0;
|
int w = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user