threaded brush preview rendering

This commit is contained in:
2019-02-28 14:47:06 +01:00
parent e59dd66b46
commit f20f935d43
5 changed files with 71 additions and 4 deletions

View File

@@ -678,6 +678,7 @@ void App::terminate()
LOG("App::terminate");
TextureManager::invalidate();
ShaderManager::invalidate();
NodeStrokePreview::terminate_renderer();
layout.unload();
uirtt.destroy();
m_face_plane.destroy();

View File

@@ -573,6 +573,8 @@ int main(int argc, char** argv)
LOG("RegisterTouchWindow error: %s", GetLastErrorAsString().c_str());
}
async_lock();
LOG("init app");
App::I.init();
@@ -604,6 +606,8 @@ int main(int argc, char** argv)
LOG("SKIP init WinTab");
}
async_unlock();
LOG("change icon");
SendMessage(hWnd, WM_SETICON, ICON_SMALL,
(LPARAM)LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(IDI_ICON1)));

View File

@@ -7,6 +7,21 @@
#include "canvas.h"
#include "app.h"
std::atomic_int NodeStrokePreview::s_instances{ 0 };
std::atomic_bool NodeStrokePreview::s_running{ false };
std::thread NodeStrokePreview::s_renderer;
BlockingQueue<NodeStrokePreview*> NodeStrokePreview::s_queue;
void NodeStrokePreview::terminate_renderer()
{
if (s_running && s_renderer.joinable())
{
s_running = false;
s_queue.UnlockGetters();
s_renderer.join();
}
}
Node* NodeStrokePreview::clone_instantiate() const
{
return new NodeStrokePreview();
@@ -224,7 +239,7 @@ std::vector<NodeStrokePreview::StrokeFrame> NodeStrokePreview::stroke_draw_compu
return ret;
}
void NodeStrokePreview::draw_stroke()
void NodeStrokePreview::draw_stroke_immediate()
{
if (m_size.x == 0 || m_size.y == 0)
return;
@@ -458,6 +473,35 @@ void NodeStrokePreview::draw_stroke()
glClearColor(cc[0], cc[1], cc[2], cc[3]);
}
void NodeStrokePreview::draw_stroke()
{
if (m_size.x == 0 || m_size.y == 0)
return;
s_queue.mutex.lock();
if (!s_running)
{
s_running = true;
s_renderer = std::thread([] {
while (s_running)
{
auto node = s_queue.Get();
if (node)
{
node->async_start();
gl_state gl;
gl.save();
node->draw_stroke_immediate();
gl.restore();
node->async_end();
std::this_thread::sleep_for(std::chrono::milliseconds(30));
}
}
});
}
s_queue.mutex.unlock();
s_queue.PostUnique(this);
}
void NodeStrokePreview::draw()
{
//glEnable(GL_BLEND);

View File

@@ -25,6 +25,11 @@ class NodeStrokePreview : public NodeBorder
Sampler m_sampler_mipmap;
DynamicShape m_brush_shape;
public:
static std::atomic_int s_instances;
static std::atomic_bool s_running;
static std::thread s_renderer;
static BlockingQueue<NodeStrokePreview*> s_queue;
static void terminate_renderer();
std::shared_ptr<Brush> m_brush;
std::shared_ptr<Brush> m_dual_brush;
Stroke m_stroke;
@@ -43,6 +48,7 @@ public:
glm::vec4 stroke_draw_samples(std::array<vertex_t, 4>& P, Texture2D& blend_tex);
std::vector<StrokeFrame> stroke_draw_compute(Stroke& stroke) const;
void draw_stroke();
void draw_stroke_immediate();
virtual void draw() override;
virtual void handle_resize(glm::vec2 old_size, glm::vec2 new_size) override;
virtual void destroy_immediate() override;

View File

@@ -151,18 +151,18 @@ template<typename T> struct cbuffer
template<typename T, int Max = 0>
class BlockingQueue
{
public:
std::deque<T> q;
std::condition_variable post_cv;
std::condition_variable get_cv;
mutable std::mutex mutex;
public:
volatile bool unlocked = false;
BlockingQueue() = default;
BlockingQueue(const BlockingQueue& other) = delete;
BlockingQueue& operator=(const BlockingQueue& other) = delete;
BlockingQueue(BlockingQueue&& other) : q(std::move(q)) { }
BlockingQueue& operator=(BlockingQueue&& other) { q = std::move(q); return *this; }
void Post(T&& pkt)
void Post(T pkt)
{
std::unique_lock<std::mutex> lock(mutex);
if (Max > 0)
@@ -170,7 +170,19 @@ public:
post_cv.wait(lock, [&]() { return unlocked | (q.size() < Max); });
if (q.size() >= Max) return;
}
q.push_back(std::forward<T>(pkt));
q.push_back(pkt);
get_cv.notify_one();
}
void PostUnique(T pkt)
{
std::unique_lock<std::mutex> lock(mutex);
if (Max > 0)
{
post_cv.wait(lock, [&]() { return unlocked | (q.size() < Max); });
if (q.size() >= Max) return;
}
if (std::find(q.begin(), q.end(), pkt) == q.end());
q.push_back(pkt);
get_cv.notify_one();
}
T Get()