add GL/Program
This commit is contained in:
parent
94615b3669
commit
451094c9fc
@ -78,7 +78,6 @@ target_sources(nf7
|
||||
common/generic_memento.hh
|
||||
common/generic_type_info.hh
|
||||
common/generic_watcher.hh
|
||||
common/gl_fence.hh
|
||||
common/gl_obj.hh
|
||||
common/gui_config.hh
|
||||
common/gui_context.hh
|
||||
|
@ -1,46 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "nf7.hh"
|
||||
|
||||
#include "common/future.hh"
|
||||
|
||||
|
||||
namespace nf7::gl {
|
||||
|
||||
inline void Await(const std::shared_ptr<nf7::Context>& ctx,
|
||||
nf7::Future<std::monostate>::Promise& pro,
|
||||
GLsync sync) noexcept {
|
||||
GLsizei len;
|
||||
GLint v;
|
||||
glGetSynciv(sync, GL_SYNC_STATUS, sizeof(v), &len, &v);
|
||||
assert(0 == glGetError());
|
||||
|
||||
if (v == GL_SIGNALED) {
|
||||
glDeleteSync(sync);
|
||||
pro.Return({});
|
||||
} else {
|
||||
ctx->env().ExecGL(ctx, [ctx, pro, sync]() mutable {
|
||||
Await(ctx, pro, sync);
|
||||
}, nf7::Env::Clock::now() + std::chrono::milliseconds(10));
|
||||
}
|
||||
}
|
||||
|
||||
// The returned future will be finalized on GL thread.
|
||||
inline nf7::Future<std::monostate> ExecFenceSync(
|
||||
const std::shared_ptr<nf7::Context>& ctx) noexcept {
|
||||
nf7::Future<std::monostate>::Promise pro {ctx};
|
||||
|
||||
ctx->env().ExecGL(ctx, [ctx, pro]() mutable {
|
||||
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
assert(0 == glGetError());
|
||||
Await(ctx, pro, sync);
|
||||
});
|
||||
return pro.future();
|
||||
}
|
||||
|
||||
} // namespace nf7::gl
|
@ -18,7 +18,6 @@ namespace nf7::gl {
|
||||
template <typename T>
|
||||
class Obj final {
|
||||
public:
|
||||
Obj() = delete;
|
||||
template <typename... Args>
|
||||
Obj(const std::shared_ptr<nf7::Context>& ctx, GLuint id, Args&&... args) noexcept :
|
||||
ctx_(ctx), meta_(std::forward<Args>(args)...), id_(id? id: meta_.Gen()) {
|
||||
@ -109,4 +108,19 @@ struct Obj_ShaderMeta final {
|
||||
using Shader = Obj<Obj_ShaderMeta>;
|
||||
using ShaderFactory = AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<Shader>>>;
|
||||
|
||||
|
||||
struct Obj_ProgramMeta final {
|
||||
public:
|
||||
Obj_ProgramMeta() = default;
|
||||
|
||||
GLuint Gen() noexcept {
|
||||
return glCreateProgram();
|
||||
}
|
||||
static void Delete(GLuint id) noexcept {
|
||||
glDeleteProgram(id);
|
||||
}
|
||||
};
|
||||
using Program = Obj<Obj_ProgramMeta>;
|
||||
using ProgramFactory = AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<Program>>>;
|
||||
|
||||
} // namespace nf7::gl
|
||||
|
141
file/gl_obj.cc
141
file/gl_obj.cc
@ -14,10 +14,13 @@
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include <yas/serialize.hpp>
|
||||
#include <yas/types/std/string.hpp>
|
||||
#include <yas/types/std/vector.hpp>
|
||||
#include <yas/types/utility/usertype.hpp>
|
||||
|
||||
#include "nf7.hh"
|
||||
|
||||
#include "common/aggregate_promise.hh"
|
||||
#include "common/dir_item.hh"
|
||||
#include "common/factory.hh"
|
||||
#include "common/file_base.hh"
|
||||
@ -25,7 +28,6 @@
|
||||
#include "common/generic_memento.hh"
|
||||
#include "common/generic_type_info.hh"
|
||||
#include "common/generic_watcher.hh"
|
||||
#include "common/gl_fence.hh"
|
||||
#include "common/gl_obj.hh"
|
||||
#include "common/gui_config.hh"
|
||||
#include "common/life.hh"
|
||||
@ -48,6 +50,7 @@ class ObjBase : public nf7::FileBase,
|
||||
using Resource = nf7::Mutex::Resource<Product>;
|
||||
using ResourceFuture = nf7::Future<Resource>;
|
||||
using ResourcePromise = typename ResourceFuture::Promise;
|
||||
using ThisFactory = nf7::AsyncFactory<Resource>;
|
||||
|
||||
struct TypeInfo;
|
||||
|
||||
@ -154,8 +157,7 @@ class ObjBase : public nf7::FileBase,
|
||||
|
||||
nf7::File::Interface* interface(const std::type_info& t) noexcept override {
|
||||
return nf7::InterfaceSelector<
|
||||
nf7::DirItem, nf7::Memento, nf7::Node,
|
||||
nf7::AsyncFactory<std::shared_ptr<T>>>(t).Select(this, &mem_);
|
||||
nf7::DirItem, nf7::Memento, nf7::Node, ThisFactory>(t).Select(this, &mem_);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -687,6 +689,139 @@ struct ObjBase<Shader>::TypeInfo final {
|
||||
static inline const nf7::GenericTypeInfo<ObjBase<Shader>> kType = {"GL/Shader", {"nf7::DirItem"}};
|
||||
};
|
||||
|
||||
|
||||
struct Program {
|
||||
public:
|
||||
static void UpdateTypeTooltip() noexcept {
|
||||
ImGui::TextUnformatted("OpenGL program");
|
||||
}
|
||||
|
||||
static inline const std::vector<std::string> kInputs = {
|
||||
"draw",
|
||||
};
|
||||
static inline const std::vector<std::string> kOutputs = {
|
||||
"done",
|
||||
};
|
||||
|
||||
using Product = nf7::gl::Program;
|
||||
|
||||
Program() = default;
|
||||
Program(const Program&) = default;
|
||||
Program(Program&&) = default;
|
||||
Program& operator=(const Program&) = default;
|
||||
Program& operator=(Program&&) = default;
|
||||
|
||||
void serialize(auto& ar) {
|
||||
ar(shaders_);
|
||||
}
|
||||
|
||||
std::string Stringify() noexcept {
|
||||
YAML::Emitter st;
|
||||
st << YAML::BeginMap;
|
||||
st << YAML::Key << "shaders";
|
||||
st << YAML::Value << YAML::BeginSeq;
|
||||
for (const auto& shader : shaders_) {
|
||||
st << shader.Stringify();
|
||||
}
|
||||
st << YAML::EndSeq;
|
||||
st << YAML::EndMap;
|
||||
return std::string {st.c_str(), st.size()};
|
||||
}
|
||||
void Parse(const std::string& v)
|
||||
try {
|
||||
const auto yaml = YAML::Load(v);
|
||||
|
||||
std::vector<nf7::File::Path> shaders;
|
||||
for (const auto& shader : yaml["shaders"]) {
|
||||
shaders.push_back(
|
||||
nf7::File::Path::Parse(shader.as<std::string>()));
|
||||
}
|
||||
if (shaders.size() == 0) {
|
||||
throw nf7::Exception {"no shader is attached"};
|
||||
}
|
||||
|
||||
shaders_ = std::move(shaders);
|
||||
} catch (YAML::Exception& e) {
|
||||
throw nf7::Exception {std::string {"YAML error: "}+e.what()};
|
||||
}
|
||||
|
||||
nf7::Future<std::shared_ptr<Product>> Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx, nf7::Env::Watcher&) noexcept
|
||||
try {
|
||||
// TODO: setup watcher
|
||||
auto& base = ctx->env().GetFileOrThrow(ctx->initiator());
|
||||
|
||||
nf7::AggregatePromise sh_pro {ctx};
|
||||
std::vector<
|
||||
nf7::Future<
|
||||
nf7::Mutex::Resource<
|
||||
std::shared_ptr<nf7::gl::Shader>>>> sh;
|
||||
for (auto& path : shaders_) {
|
||||
sh.push_back(
|
||||
base.ResolveOrThrow(path).
|
||||
interfaceOrThrow<nf7::gl::ShaderFactory>().Create());
|
||||
sh_pro.Add(sh.back());
|
||||
}
|
||||
|
||||
nf7::Future<std::shared_ptr<Product>>::Promise pro {ctx};
|
||||
sh_pro.future().Then([ctx, pro, shaders = std::move(sh)](auto&) mutable {
|
||||
pro.Wrap([&]() {
|
||||
std::vector<std::shared_ptr<nf7::gl::Shader>> sh;
|
||||
for (auto& s : shaders) {
|
||||
sh.push_back(*s.value());
|
||||
}
|
||||
return Link(ctx, sh);
|
||||
});
|
||||
});
|
||||
return pro.future();
|
||||
} catch (nf7::Exception&) {
|
||||
return {std::current_exception()};
|
||||
}
|
||||
static std::shared_ptr<nf7::gl::Program> Link(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
const std::span<std::shared_ptr<nf7::gl::Shader>>& shaders) {
|
||||
auto prog = std::make_shared<nf7::gl::Program>(ctx, GLuint {0});
|
||||
assert(prog->id() > 0);
|
||||
for (auto& sh : shaders) {
|
||||
glAttachShader(prog->id(), sh->id());
|
||||
}
|
||||
glLinkProgram(prog->id());
|
||||
|
||||
GLint status;
|
||||
glGetProgramiv(prog->id(), GL_LINK_STATUS, &status);
|
||||
if (status == GL_TRUE) {
|
||||
return prog;
|
||||
} else {
|
||||
GLint len;
|
||||
glGetProgramiv(prog->id(), GL_INFO_LOG_LENGTH, &len);
|
||||
|
||||
std::string ret(static_cast<size_t>(len), ' ');
|
||||
glGetProgramInfoLog(prog->id(), len, nullptr, ret.data());
|
||||
throw nf7::Exception {std::move(ret)};
|
||||
}
|
||||
}
|
||||
|
||||
bool Handle(const std::shared_ptr<nf7::Node::Lambda>&,
|
||||
const nf7::Mutex::Resource<std::shared_ptr<Product>>&,
|
||||
const nf7::Node::Lambda::Msg&) {
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
void UpdateTooltip(const std::shared_ptr<Product>& prod) noexcept {
|
||||
if (prod) {
|
||||
ImGui::Text("id : %zu", static_cast<size_t>(prod->id()));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<nf7::File::Path> shaders_;
|
||||
};
|
||||
template <>
|
||||
struct ObjBase<Program>::TypeInfo final {
|
||||
static inline const nf7::GenericTypeInfo<ObjBase<Program>> kType = {"GL/Program", {"nf7::DirItem"}};
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace nf7
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user