From 52ad58aec44f8ee7393e40fca8227b78681d1ae1 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Tue, 5 Nov 2019 18:25:25 +0100 Subject: [PATCH] use PBO for timelapse data read --- src/app.cpp | 7 ++- src/app.h | 2 +- src/app_events.cpp | 8 ++-- src/canvas_layer.cpp | 43 +++++++++++++++++ src/canvas_layer.h | 1 + src/image.h | 19 +++++++- src/rtt.cpp | 111 +++++++++++++++++++++++++++++++++++++++++++ src/rtt.h | 30 ++++++++++++ 8 files changed, 212 insertions(+), 9 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index ae9b143..6fce98d 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -792,7 +792,7 @@ void App::rec_loop() rec_running = true; while(rec_running) { - std::unique_ptr frame; + std::unique_ptr frame; std::unique_lock 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(); diff --git a/src/app.h b/src/app.h index a3a0542..a3905a9 100644 --- a/src/app.h +++ b/src/app.h @@ -96,7 +96,7 @@ public: int rec_count = 0; std::mutex rec_mutex; std::condition_variable rec_cv; - std::deque> rec_frames; + std::deque> rec_frames; RTT uirtt; Sampler sampler; diff --git a/src/app_events.cpp b/src/app_events.cpp index a91745c..77180d8 100644 --- a/src/app_events.cpp +++ b/src/app_events.cpp @@ -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(equirect.get_image()); { std::lock_guard lock(rec_mutex); - rec_frames.emplace_back(std::move(img)); + rec_frames.emplace_back(std::make_unique(std::move(equirect))); rec_cv.notify_all(); } - equirect.destroy(); } } } diff --git a/src/canvas_layer.cpp b/src/canvas_layer.cpp index 44a7467..0b7ce9d 100644 --- a/src/canvas_layer.cpp +++ b/src/canvas_layer.cpp @@ -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++) diff --git a/src/canvas_layer.h b/src/canvas_layer.h index 34cd428..edcf757 100644 --- a/src/canvas_layer.h +++ b/src/canvas_layer.h @@ -82,6 +82,7 @@ public: LayerFrame::Snapshot snapshot(int frame = -1, std::array* dirty_box = nullptr, std::array* 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); diff --git a/src/image.h b/src/image.h index 7cc3900..a49ba98 100644 --- a/src/image.h +++ b/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(); + } +}; \ No newline at end of file diff --git a/src/rtt.cpp b/src/rtt.cpp index e0aac8d..4c1d1ba 100644 --- a/src/rtt.cpp +++ b/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); + }); +} diff --git a/src/rtt.h b/src/rtt.h index 05e495a..fd54d76 100644 --- a/src/rtt.h +++ b/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;