use tracy profiler's features
This commit is contained in:
parent
d33330b6c3
commit
31924ce5b2
@ -10,6 +10,8 @@
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <tracy/Tracy.hpp>
|
||||
|
||||
#include "common/aggregate_promise.hh"
|
||||
#include "common/factory.hh"
|
||||
#include "common/future.hh"
|
||||
@ -61,6 +63,7 @@ nf7::Future<std::shared_ptr<Obj<Obj_BufferMeta>>> Obj_BufferMeta::Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx) const noexcept {
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_BufferMeta>>>::Promise pro {ctx};
|
||||
ctx->env().ExecGL(ctx, [=, *this]() mutable {
|
||||
ZoneScopedN("create buffer");
|
||||
GLuint id;
|
||||
glGenBuffers(1, &id);
|
||||
pro.Return(std::make_shared<Obj<Obj_BufferMeta>>(ctx, id, *this));
|
||||
@ -73,6 +76,8 @@ nf7::Future<std::shared_ptr<Obj<Obj_TextureMeta>>> Obj_TextureMeta::Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx) const noexcept {
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_TextureMeta>>>::Promise pro {ctx};
|
||||
ctx->env().ExecGL(ctx, [=, *this]() mutable {
|
||||
ZoneScopedN("create texture");
|
||||
|
||||
GLuint id;
|
||||
glGenTextures(1, &id);
|
||||
|
||||
@ -108,6 +113,8 @@ nf7::Future<std::shared_ptr<Obj<Obj_ShaderMeta>>> Obj_ShaderMeta::Create(
|
||||
const std::string& src) const noexcept {
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_ShaderMeta>>>::Promise pro {ctx};
|
||||
ctx->env().ExecGL(ctx, [=, *this]() mutable {
|
||||
ZoneScopedN("create shader");
|
||||
|
||||
const auto t = gl::ToEnum(type);
|
||||
const auto id = glCreateShader(t);
|
||||
if (id == 0) {
|
||||
@ -119,10 +126,13 @@ nf7::Future<std::shared_ptr<Obj<Obj_ShaderMeta>>> Obj_ShaderMeta::Create(
|
||||
"#version 330\n"
|
||||
"#extension GL_ARB_shading_language_include: require\n";
|
||||
|
||||
const GLchar* str[] = {kHeader, src.c_str()};
|
||||
glShaderSource(id, 2, str, nullptr);
|
||||
glCompileShader(id);
|
||||
assert(0 == glGetError());
|
||||
{
|
||||
ZoneScopedN("compile");
|
||||
const GLchar* str[] = {kHeader, src.c_str()};
|
||||
glShaderSource(id, 2, str, nullptr);
|
||||
glCompileShader(id);
|
||||
assert(0 == glGetError());
|
||||
}
|
||||
|
||||
GLint status;
|
||||
glGetShaderiv(id, GL_COMPILE_STATUS, &status);
|
||||
@ -155,6 +165,8 @@ nf7::Future<std::shared_ptr<Obj<Obj_ProgramMeta>>> Obj_ProgramMeta::Create(
|
||||
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_ProgramMeta>>>::Promise pro {ctx};
|
||||
apro.future().Chain(nf7::Env::kGL, ctx, pro, [*this, ctx, shs = std::move(shs)](auto&) {
|
||||
ZoneScopedN("create program");
|
||||
|
||||
// check all shaders
|
||||
for (auto& sh : shs) { sh.value(); }
|
||||
|
||||
@ -168,7 +180,11 @@ nf7::Future<std::shared_ptr<Obj<Obj_ProgramMeta>>> Obj_ProgramMeta::Create(
|
||||
for (auto& sh : shs) {
|
||||
glAttachShader(id, (*sh.value())->id());
|
||||
}
|
||||
glLinkProgram(id);
|
||||
|
||||
{
|
||||
ZoneScopedN("link");
|
||||
glLinkProgram(id);
|
||||
}
|
||||
|
||||
// check status
|
||||
GLint status;
|
||||
@ -222,6 +238,8 @@ try {
|
||||
LockAttachments(ctx).Chain(
|
||||
nf7::Env::kGL, ctx, pro,
|
||||
[*this, ctx, pro](auto& bufs) mutable {
|
||||
ZoneScopedN("create va");
|
||||
|
||||
// check all buffers
|
||||
if (index) {
|
||||
assert(bufs.index);
|
||||
@ -340,6 +358,8 @@ nf7::Future<std::shared_ptr<Obj<Obj_FramebufferMeta>>> Obj_FramebufferMeta::Crea
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_FramebufferMeta>>>::Promise pro {ctx};
|
||||
LockAttachments(ctx).
|
||||
Chain(nf7::Env::kGL, ctx, pro, [ctx, *this](auto& k) mutable {
|
||||
ZoneScopedN("create fb");
|
||||
|
||||
GLuint id;
|
||||
glGenFramebuffers(1, &id);
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <tuple>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <tracy/Tracy.hpp>
|
||||
|
||||
#include "common/node.hh"
|
||||
#include "common/node_root_lambda.hh"
|
||||
|
||||
@ -53,7 +55,11 @@ void Thread::Resume(lua_State* L, int narg) noexcept {
|
||||
yield_ctx_.reset();
|
||||
|
||||
k.unlock();
|
||||
const auto ret = lua_resume(L, narg);
|
||||
int ret;
|
||||
{
|
||||
ZoneScopedN("lua_resume");
|
||||
ret = lua_resume(L, narg);
|
||||
}
|
||||
k.lock();
|
||||
|
||||
active_ = false;
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
#include <tracy/Tracy.hpp>
|
||||
|
||||
#include "nf7.hh"
|
||||
|
||||
#include "common/stopwatch.hh"
|
||||
@ -68,6 +70,7 @@ class Thread final : public nf7::Context,
|
||||
|
||||
auto self = shared_from_this();
|
||||
if (!entry) {
|
||||
ZoneScopedN("thread task execution");
|
||||
for (nf7::Stopwatch sw; sw.dur() < kTaskDur; ++tasks_done_) {
|
||||
auto t = q_.Pop();
|
||||
if (!t) break;
|
||||
|
@ -5,8 +5,11 @@
|
||||
#include <typeinfo>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <miniaudio.h>
|
||||
|
||||
#include <tracy/Tracy.hpp>
|
||||
|
||||
#include "nf7.hh"
|
||||
|
||||
#include "common/audio_queue.hh"
|
||||
@ -68,6 +71,7 @@ class AudioContext::Queue final : public nf7::audio::Queue,
|
||||
}
|
||||
void operator()(Task&& t) {
|
||||
if (!data_->broken) {
|
||||
ZoneScopedN("audio task");
|
||||
t(&data_->ctx);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <tracy/Tracy.hpp>
|
||||
|
||||
#include "nf7.hh"
|
||||
|
||||
#include "common/dir_item.hh"
|
||||
@ -65,6 +67,7 @@ class FontContext::Queue final : public nf7::font::Queue,
|
||||
}
|
||||
void operator()(Task&& t) noexcept {
|
||||
if (!data_->broken) {
|
||||
ZoneScopedN("font task");
|
||||
t(data_->ft);
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,8 @@
|
||||
|
||||
#include <magic_enum.hpp>
|
||||
|
||||
#include <tracy/Tracy.hpp>
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include <yas/serialize.hpp>
|
||||
@ -351,6 +353,9 @@ struct Buffer {
|
||||
const auto t = gl::ToEnum(buf.meta().target);
|
||||
glBindBuffer(t, buf.id());
|
||||
{
|
||||
ZoneScopedN("upload buffer");
|
||||
ZoneValue(vec->size());
|
||||
|
||||
auto& size = buf.param().size;
|
||||
if (size != vec->size()) {
|
||||
size = vec->size();
|
||||
@ -508,14 +513,16 @@ struct Texture {
|
||||
glBindTexture(t, tex.id());
|
||||
switch (t) {
|
||||
case GL_TEXTURE_2D:
|
||||
case GL_TEXTURE_RECTANGLE:
|
||||
case GL_TEXTURE_RECTANGLE: {
|
||||
ZoneScopedN("glTexSubImage2D");
|
||||
ZoneValue(buf->size());
|
||||
glTexSubImage2D(t, 0,
|
||||
static_cast<GLint>(offset[0]),
|
||||
static_cast<GLint>(offset[1]),
|
||||
static_cast<GLsizei>(size[0]),
|
||||
static_cast<GLsizei>(size[1]),
|
||||
fmt, type, buf->data());
|
||||
break;
|
||||
} break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
@ -554,25 +561,32 @@ struct Texture {
|
||||
const auto size = tex.meta().size;
|
||||
const auto texel = std::accumulate(size.begin(), size.end(), 1, std::multiplies<uint32_t> {});
|
||||
const auto bsize = texel*gl::GetCompCount(comp)*gl::GetByteSize(numtype);
|
||||
glBufferData(GL_PIXEL_PACK_BUFFER, static_cast<GLsizeiptr>(bsize), nullptr, GL_STREAM_READ);
|
||||
const auto t = gl::ToEnum(tex.meta().target);
|
||||
|
||||
const auto t = gl::ToEnum(tex.meta().target);
|
||||
glBindTexture(t, tex.id());
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glGetTexImage(t, 0, gl::ToEnum(comp), gl::ToEnum(numtype), nullptr);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
glBindTexture(t, 0);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
assert(0 == glGetError());
|
||||
{
|
||||
ZoneScopedN("request to download texture");
|
||||
glBufferData(GL_PIXEL_PACK_BUFFER, static_cast<GLsizeiptr>(bsize), nullptr, GL_STREAM_READ);
|
||||
|
||||
glBindTexture(t, tex.id());
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glGetTexImage(t, 0, gl::ToEnum(comp), gl::ToEnum(numtype), nullptr);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
glBindTexture(t, 0);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
assert(0 == glGetError());
|
||||
}
|
||||
|
||||
nf7::gl::ExecFenceSync(p.la).ThenIf([=, &tex](auto&) {
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
|
||||
|
||||
auto buf = std::make_shared<std::vector<uint8_t>>(bsize);
|
||||
|
||||
const auto ptr = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
|
||||
std::memcpy(buf->data(), ptr, static_cast<size_t>(bsize));
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
{
|
||||
ZoneScopedN("download texture");
|
||||
const auto ptr = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
|
||||
std::memcpy(buf->data(), ptr, static_cast<size_t>(bsize));
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
glDeleteBuffers(1, &pbo);
|
||||
@ -916,6 +930,8 @@ struct Program {
|
||||
|
||||
// execute drawing after successful locking
|
||||
apro.future().ThenIf(nf7::Env::kGL, p.la, [=, tex_fu = std::move(tex_fu)](auto&) {
|
||||
ZoneScopedN("draw");
|
||||
|
||||
const auto& fbo = *fbo_fu.value().first;
|
||||
const auto& vao = *vao_fu.value().first;
|
||||
const auto& prog = *p.obj;
|
||||
@ -956,8 +972,10 @@ struct Program {
|
||||
config.ApplyState();
|
||||
if (vao->meta().index) {
|
||||
const auto numtype = gl::ToEnum(vao->meta().index->numtype);
|
||||
ZoneScopedN("glDrawElementsInstanced");
|
||||
glDrawElementsInstanced(mode, count, numtype, nullptr, inst);
|
||||
} else {
|
||||
ZoneScopedN("glDrawArraysInstanced");
|
||||
glDrawArraysInstanced(mode, 0, count, inst);
|
||||
}
|
||||
config.RevertState();
|
||||
@ -1357,7 +1375,10 @@ struct Framebuffer {
|
||||
if (p.in.name == "clear") {
|
||||
(**p.obj).meta().LockAttachments(p.la).ThenIf(nf7::Env::kGL, p.la, [=](auto&) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, (**p.obj).id());
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
{
|
||||
ZoneScopedN("glClear");
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
});
|
||||
return true;
|
||||
@ -1386,9 +1407,12 @@ struct Framebuffer {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, src.id());
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst.id());
|
||||
|
||||
glBlitFramebuffer(rect[0], rect[1], rect[2], rect[3],
|
||||
rect[4], rect[5], rect[6], rect[7],
|
||||
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
{
|
||||
ZoneScopedN("glBlitFramebuffer");
|
||||
glBlitFramebuffer(rect[0], rect[1], rect[2], rect[3],
|
||||
rect[4], rect[5], rect[6], rect[7],
|
||||
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include <imgui.h>
|
||||
#include <lua.hpp>
|
||||
|
||||
#include <tracy/Tracy.hpp>
|
||||
|
||||
#include "nf7.hh"
|
||||
|
||||
#include "common/dir_item.hh"
|
||||
@ -67,8 +69,12 @@ class LuaContext::Queue final : public nf7::luajit::Queue,
|
||||
Runner(const std::shared_ptr<SharedData>& data) noexcept : data_(data) {
|
||||
}
|
||||
void operator()(Task&& t) {
|
||||
t(data_->L);
|
||||
{
|
||||
ZoneScopedN("LuaJIT task");
|
||||
t(data_->L);
|
||||
}
|
||||
if (data_->L) {
|
||||
ZoneScopedNC("GC", tracy::Color::Gray);
|
||||
lua_gc(data_->L, LUA_GCCOLLECT, 0);
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include <ImNodes.h>
|
||||
|
||||
#include <tracy/Tracy.hpp>
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include <yas/serialize.hpp>
|
||||
@ -218,6 +220,7 @@ try {
|
||||
|
||||
// start the thread
|
||||
ljq->Push(ctx, [ctx, ljq, th, pro, script = mem_->script](auto L) mutable {
|
||||
ZoneScopedN("build function for Node");
|
||||
L = th->Init(L);
|
||||
if (0 == luaL_loadstring(L, script.c_str())) {
|
||||
th->Resume(L, 0);
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#include <ImNodes.h>
|
||||
|
||||
#include <tracy/Tracy.hpp>
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include <yas/serialize.hpp>
|
||||
@ -141,6 +143,7 @@ class Expr::Lambda final : public nf7::Node::Lambda,
|
||||
void Handle(const nf7::Node::Lambda::Msg& in) noexcept override
|
||||
try {
|
||||
f_.EnforceAlive();
|
||||
ZoneScopedN("ExprTk");
|
||||
|
||||
auto& obj = f_->obj_;
|
||||
if (!obj) {
|
||||
|
136
main.cc
136
main.cc
@ -17,6 +17,8 @@
|
||||
#include <imgui_impl_opengl3.h>
|
||||
#include <implot.h>
|
||||
|
||||
#include <tracy/Tracy.hpp>
|
||||
|
||||
#include "nf7.hh"
|
||||
|
||||
#include "common/queue.hh"
|
||||
@ -63,18 +65,26 @@ nf7::Queue<std::exception_ptr> panicq_;
|
||||
|
||||
|
||||
void WorkerThread() noexcept {
|
||||
[[maybe_unused]] const char kThreadId[] = "SyncWorker";
|
||||
tracy::SetThreadName("SyncWorker");
|
||||
|
||||
std::unique_lock<std::mutex> k {cycle_mtx_};
|
||||
while (alive_) {
|
||||
// wait for the end of GUI update
|
||||
FrameMarkStart(kThreadId);
|
||||
|
||||
cycle_cv_.wait(k, []() { return cycle_ != kUpdate; });
|
||||
k.unlock();
|
||||
|
||||
// exec main tasks
|
||||
for (;;) {
|
||||
std::shared_lock<std::shared_mutex> sk {task_mtx_};
|
||||
auto task = mainq_.Pop();
|
||||
if (!task) break;
|
||||
try {
|
||||
ZoneScopedNC("main task", tracy::Color::Orange);
|
||||
if (task->first) {
|
||||
const auto str = task->first->GetDescription();
|
||||
ZoneText(str.data(), str.size());
|
||||
}
|
||||
task->second();
|
||||
} catch (nf7::Exception&) {
|
||||
sk.unlock();
|
||||
@ -89,6 +99,11 @@ void WorkerThread() noexcept {
|
||||
const auto task = subq_.Pop();
|
||||
if (!task) break;
|
||||
try {
|
||||
ZoneScopedNC("sub task", tracy::Color::Green);
|
||||
if (task->first) {
|
||||
const auto str = task->first->GetDescription();
|
||||
ZoneText(str.data(), str.size());
|
||||
}
|
||||
task->second();
|
||||
} catch (nf7::Exception&) {
|
||||
sk.unlock();
|
||||
@ -107,12 +122,19 @@ void WorkerThread() noexcept {
|
||||
k.lock();
|
||||
cycle_ = kUpdate;
|
||||
cycle_cv_.notify_all();
|
||||
|
||||
FrameMarkEnd(kThreadId);
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncThread() noexcept {
|
||||
[[maybe_unused]] const char kThreadId[] = "AsyncWorker";
|
||||
tracy::SetThreadName("AsyncWorker");
|
||||
|
||||
std::unique_lock<std::mutex> k {cycle_mtx_};
|
||||
while (alive_) {
|
||||
FrameMarkStart(kThreadId);
|
||||
|
||||
const auto until = asyncq_.next().value_or(nf7::Env::Time::max());
|
||||
cycle_cv_.wait_until(k, until, []() { return !alive_ || !asyncq_.idle(); });
|
||||
k.unlock();
|
||||
@ -122,6 +144,11 @@ void AsyncThread() noexcept {
|
||||
auto task = asyncq_.Pop();
|
||||
if (!task) break;
|
||||
try {
|
||||
ZoneScopedNC("async task", tracy::Color::Blue);
|
||||
if (task->first) {
|
||||
const auto str = task->first->GetDescription();
|
||||
ZoneText(str.data(), str.size());
|
||||
}
|
||||
task->second();
|
||||
} catch (nf7::Exception&) {
|
||||
sk.unlock();
|
||||
@ -129,10 +156,15 @@ void AsyncThread() noexcept {
|
||||
}
|
||||
}
|
||||
k.lock();
|
||||
|
||||
FrameMarkEnd(kThreadId);
|
||||
}
|
||||
}
|
||||
|
||||
void GLThread(GLFWwindow* window) noexcept {
|
||||
[[maybe_unused]] const char kThreadId[] = "AsyncWorker";
|
||||
tracy::SetThreadName("GLWorker");
|
||||
|
||||
std::unique_lock<std::mutex> k {cycle_mtx_};
|
||||
|
||||
// does nothing when the first cycle because the main thread is using GL context
|
||||
@ -141,6 +173,8 @@ void GLThread(GLFWwindow* window) noexcept {
|
||||
cycle_cv_.notify_all();
|
||||
|
||||
while (alive_) {
|
||||
FrameMarkStart(kThreadId);
|
||||
|
||||
// wait for the end of GUI drawing
|
||||
cycle_cv_.wait(k, []() { return cycle_ != kDraw; });
|
||||
k.unlock();
|
||||
@ -151,6 +185,11 @@ void GLThread(GLFWwindow* window) noexcept {
|
||||
auto task = glq_.Pop();
|
||||
if (!task) break;
|
||||
try {
|
||||
ZoneScopedNC("GL task", tracy::Color::Aqua);
|
||||
if (task->first) {
|
||||
const auto str = task->first->GetDescription();
|
||||
ZoneText(str.data(), str.size());
|
||||
}
|
||||
task->second();
|
||||
} catch (nf7::Exception&) {
|
||||
sk.unlock();
|
||||
@ -167,6 +206,8 @@ void GLThread(GLFWwindow* window) noexcept {
|
||||
cycle_ = kDraw;
|
||||
cycle_cv_.notify_all();
|
||||
}
|
||||
|
||||
FrameMarkEnd(kThreadId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,6 +217,8 @@ class Env final : public nf7::Env {
|
||||
static constexpr auto kFileName = "root.nf7";
|
||||
|
||||
Env() noexcept : nf7::Env(std::filesystem::current_path()) {
|
||||
ZoneScopedN("nf7::Env constructor");
|
||||
|
||||
// deserialize
|
||||
if (!std::filesystem::exists(kFileName)) {
|
||||
root_ = CreateRoot(*this);
|
||||
@ -196,6 +239,7 @@ class Env final : public nf7::Env {
|
||||
}
|
||||
|
||||
void TearDownRoot() noexcept {
|
||||
ZoneScoped;
|
||||
if (root_) {
|
||||
Save();
|
||||
root_->Isolate();
|
||||
@ -210,17 +254,21 @@ class Env final : public nf7::Env {
|
||||
bool notify = false;
|
||||
switch (type) {
|
||||
case kMain:
|
||||
TracyMessageL("queue main task");
|
||||
mainq_.Push({ctx, std::move(task)});
|
||||
break;
|
||||
case kSub:
|
||||
TracyMessageL("queue sub task");
|
||||
subq_.Push(time, {ctx, std::move(task)});
|
||||
notify = true;
|
||||
break;
|
||||
case kAsync:
|
||||
TracyMessageL("queue async task");
|
||||
asyncq_.Push(time, {ctx, std::move(task)});
|
||||
notify = true;
|
||||
break;
|
||||
case kGL:
|
||||
TracyMessageL("queue gl task");
|
||||
glq_.Push(time, {ctx, std::move(task)});
|
||||
notify = true;
|
||||
break;
|
||||
@ -254,10 +302,12 @@ class Env final : public nf7::Env {
|
||||
}
|
||||
|
||||
void Exit() noexcept override {
|
||||
TracyMessageL("exit requested");
|
||||
exit_requested_ = true;
|
||||
}
|
||||
void Save() noexcept override
|
||||
try {
|
||||
ZoneScoped;
|
||||
nf7::Serializer::Save(*this, kFileName, root_);
|
||||
} catch (nf7::Exception&) {
|
||||
panicq_.Push(std::current_exception());
|
||||
@ -267,6 +317,7 @@ class Env final : public nf7::Env {
|
||||
}
|
||||
|
||||
void Update() noexcept {
|
||||
ZoneScoped;
|
||||
ImGui::PushID(this);
|
||||
{
|
||||
if (root_) {
|
||||
@ -333,6 +384,8 @@ class Env final : public nf7::Env {
|
||||
|
||||
|
||||
void UpdatePanic() noexcept {
|
||||
ZoneScoped;
|
||||
|
||||
static std::exception_ptr ptr_;
|
||||
if (!ptr_) {
|
||||
if (auto ptr = panicq_.Pop()) {
|
||||
@ -438,18 +491,22 @@ int main(int, char**) {
|
||||
}
|
||||
|
||||
// main loop
|
||||
[[maybe_unused]] const char kThreadId[] = "GUI";
|
||||
::Env env;
|
||||
glfwShowWindow(window);
|
||||
while (!glfwWindowShouldClose(window) && !env.exitRequested()) {
|
||||
FrameMarkStart(kThreadId);
|
||||
nf7::Stopwatch sw;
|
||||
|
||||
// handle events
|
||||
glfwPollEvents();
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
{
|
||||
ZoneScopedN("handle events");
|
||||
glfwPollEvents();
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
// sync with worker thread
|
||||
// wait for sync thrad
|
||||
{
|
||||
cycle_ = kSyncUpdate;
|
||||
std::unique_lock<std::mutex> k {cycle_mtx_};
|
||||
@ -457,13 +514,15 @@ int main(int, char**) {
|
||||
cycle_cv_.wait(k, []() { return cycle_ == kUpdate; });
|
||||
}
|
||||
|
||||
// GUI update (OpenGL call is forbidden)
|
||||
assert(cycle_ == kUpdate);
|
||||
env.Update();
|
||||
UpdatePanic();
|
||||
ImGui::Render();
|
||||
{
|
||||
ZoneScopedN("update GUI");
|
||||
assert(cycle_ == kUpdate);
|
||||
env.Update();
|
||||
UpdatePanic();
|
||||
ImGui::Render();
|
||||
}
|
||||
|
||||
// sync with GL thread
|
||||
// wait for GL thread
|
||||
{
|
||||
cycle_ = kSyncDraw;
|
||||
std::unique_lock<std::mutex> k {cycle_mtx_};
|
||||
@ -472,15 +531,18 @@ int main(int, char**) {
|
||||
}
|
||||
|
||||
// GUI draw (OpenGL calls occur)
|
||||
assert(cycle_ == kDraw);
|
||||
glfwMakeContextCurrent(window);
|
||||
int w, h;
|
||||
glfwGetFramebufferSize(window, &w, &h);
|
||||
glViewport(0, 0, w, h);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
glfwSwapBuffers(window);
|
||||
glfwMakeContextCurrent(nullptr);
|
||||
{
|
||||
ZoneScopedN("update display");
|
||||
assert(cycle_ == kDraw);
|
||||
glfwMakeContextCurrent(window);
|
||||
int w, h;
|
||||
glfwGetFramebufferSize(window, &w, &h);
|
||||
glViewport(0, 0, w, h);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
glfwSwapBuffers(window);
|
||||
glfwMakeContextCurrent(nullptr);
|
||||
}
|
||||
|
||||
// sleep
|
||||
{
|
||||
@ -489,6 +551,8 @@ int main(int, char**) {
|
||||
cycle_cv_.notify_all();
|
||||
}
|
||||
std::this_thread::sleep_for(kFrameDur - sw.dur());
|
||||
|
||||
FrameMarkEnd(kThreadId);
|
||||
}
|
||||
|
||||
// sync with worker thread and tear down filesystem
|
||||
@ -508,7 +572,7 @@ int main(int, char**) {
|
||||
cycle_cv_.notify_all();
|
||||
}
|
||||
|
||||
// wait for all tasks
|
||||
TracyMessageL("waiting for all tasks");
|
||||
for (;;) {
|
||||
std::unique_lock<std::shared_mutex> sk {task_mtx_};
|
||||
if (!mainq_.size() && !subq_.size() && !asyncq_.size() && !glq_.size()) {
|
||||
@ -517,7 +581,7 @@ int main(int, char**) {
|
||||
std::this_thread::sleep_for(30ms);
|
||||
}
|
||||
|
||||
// exit worker and async threads
|
||||
TracyMessageL("exitting SyncWorker and AsyncWorker");
|
||||
{
|
||||
alive_ = false;
|
||||
cycle_ = kSyncUpdate;
|
||||
@ -527,7 +591,7 @@ int main(int, char**) {
|
||||
for (auto& th : th_async) th.join();
|
||||
th_worker.join();
|
||||
|
||||
// exit GL thread
|
||||
TracyMessageL("exitting GLWorker");
|
||||
{
|
||||
cycle_ = kSyncDraw;
|
||||
std::unique_lock<std::mutex> k {cycle_mtx_};
|
||||
@ -535,14 +599,18 @@ int main(int, char**) {
|
||||
}
|
||||
th_gl.join();
|
||||
|
||||
// tear down ImGUI
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImPlot::DestroyContext();
|
||||
ImGui::DestroyContext();
|
||||
{
|
||||
ZoneScopedN("tear down everything");
|
||||
|
||||
// tear down display
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
// tear down ImGUI
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImPlot::DestroyContext();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
// tear down display
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user