use PBO for timelapse data read
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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++)
|
||||
|
||||
@@ -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);
|
||||
|
||||
19
src/image.h
19
src/image.h
@@ -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();
|
||||
}
|
||||
};
|
||||
111
src/rtt.cpp
111
src/rtt.cpp
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
30
src/rtt.h
30
src/rtt.h
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user