Compare commits

...

1 Commits

Author SHA1 Message Date
354ce630f6 (WIP) add GL/Obj 2022-10-06 10:52:19 +09:00
4 changed files with 352 additions and 0 deletions

View File

@ -67,6 +67,7 @@ target_sources(nf7
common/audio_queue.hh common/audio_queue.hh
common/dir.hh common/dir.hh
common/dir_item.hh common/dir_item.hh
common/factory.hh
common/file_base.hh common/file_base.hh
common/file_holder.hh common/file_holder.hh
common/file_holder.cc common/file_holder.cc
@ -76,6 +77,7 @@ target_sources(nf7
common/generic_memento.hh common/generic_memento.hh
common/generic_type_info.hh common/generic_type_info.hh
common/generic_watcher.hh common/generic_watcher.hh
common/gl_obj.hh
common/gui_config.hh common/gui_config.hh
common/gui_context.hh common/gui_context.hh
common/gui_dnd.hh common/gui_dnd.hh
@ -133,6 +135,7 @@ target_sources(nf7
file/audio_context.cc file/audio_context.cc
file/audio_device.cc file/audio_device.cc
file/gl_obj.cc
file/luajit_context.cc file/luajit_context.cc
file/luajit_node.cc file/luajit_node.cc
file/node_imm.cc file/node_imm.cc

27
common/factory.hh Normal file
View File

@ -0,0 +1,27 @@
#pragma once
#include "nf7.hh"
#include "common/future.hh"
namespace nf7 {
template <typename T>
class Factory : public nf7::File::Interface {
public:
using Product = T;
Factory() = default;
Factory(const Factory&) = delete;
Factory(Factory&&) = delete;
Factory& operator=(const Factory&) = delete;
Factory& operator=(Factory&&) = delete;
virtual Product Create() noexcept = 0;
};
template <typename T>
using AsyncFactory = Factory<nf7::Future<T>>;
} // namespace nf7

83
common/gl_obj.hh Normal file
View File

@ -0,0 +1,83 @@
#pragma once
#include <cassert>
#include <memory>
#include <GL/glew.h>
#include "nf7.hh"
#include "common/factory.hh"
#include "common/future.hh"
namespace nf7::gl {
template <typename T>
class Obj final {
public:
Obj() = delete;
Obj(const std::shared_ptr<nf7::Context>& ctx, GLuint id) noexcept :
ctx_(ctx), id_(id) {
}
Obj(const std::shared_ptr<nf7::Context>& ctx) noexcept :
Obj(ctx, T::Gen()) {
}
~Obj() noexcept {
ctx_->env().ExecGL(ctx_, [id = id_]() { T::Delete(id); });
}
Obj(const Obj&) = delete;
Obj(Obj&&) = delete;
Obj& operator=(const Obj&) = delete;
Obj& operator=(Obj&&) = delete;
GLuint id() const noexcept { return id_; }
T& meta() noexcept { return meta_; }
const T& meta() const noexcept { return meta_; }
private:
std::shared_ptr<nf7::Context> ctx_;
GLuint id_;
T meta_;
};
struct Obj_BufferMeta final {
public:
GLenum type;
size_t size;
static GLuint Gen() noexcept {
GLuint id;
glGenBuffers(&id, 1);
return id;
}
static void Delete(GLuint id) noexcept {
glDeleteBuffers(&id);
}
};
using Buffer = Obj<Obj_BufferMeta>;
using BufferFactory = AsyncFactory<std::shared_ptr<Buffer>>;
struct Obj_BufferMeta final {
public:
GLenum type;
GLenum format;
uint32_t w, h, d;
static GLuint Gen() noexcept {
GLuint id;
glGenTextures(&id, 1);
return id;
}
static void Delete(GLuint id) noexcept {
glDeleteTextures(&id);
}
};
using Texture = Obj<Obj_TextureMeta>;
using TextureFactory = AsyncFactory<std::shared_ptr<Texture>>;
} // namespace nf7::gl

239
file/gl_obj.cc Normal file
View File

@ -0,0 +1,239 @@
#include <optional>
#include <span>
#include <string>
#include <string_view>
#include <typeinfo>
#include <vector>
#include <imgui.h>
#include <imgui_stdlib.h>
#include <implot.h>
#include <magic_enum.hh>
#include <yaml-cpp/yaml.h>
#include <yas/serialize.hpp>
#include <yas/types/utility/usertype.hpp>
#include "nf7.hh"
#include "common/dir_item.hh"
#include "common/generic_context.hh"
#include "common/generic_memento.hh"
#include "common/generic_type_info.hh"
#include "common/gl_obj.hh"
#include "common/life.hh"
#include "common/node.hh"
#include "common/ptr_selector.hh"
#include "common/yas_enum.hh"
namespace nf7 {
namespace {
template <typename T>
class ObjBase final : public nf7::File,
public nf7::DirItem, public nf7::Node, public T {
public:
ObjBase(nf7::File::TypeInfo& t, nf7::Env& env,
std::span<const std::string> inputs,
std::span<const std::string> outputs) noexcept :
nf7::File(t, env),
nf7::DirItem(nf7::DirItem::kTooltip),
nf7::Node(nf7::Node::kNone),
inputs_(inputs), outputs_(outputs) {
}
std::span<const std::string> GetInputs() const noexcept override {
return inputs_;
}
std::span<const std::string> GetOutputs() const noexcept override {
return outputs_;
}
Product Create() noexcept final {
if (!prod_) {
prod_ = Create_();
}
return *prod_;
}
nf7::File::Interface* interface(const std::type_info& t) noexcept override {
return nf7::InterfaceSelector<nf7::DirItem, T>(t).Select(this);
}
protected:
virtual Product Create_() noexcept = 0;
void DropCache() noexcept {
prod_ = std::nullopt;
}
const Product& prod() const noexcept {
// Product is always wrapped nf7::Future
return prod_ && prod_->done()? prod_->value(): nullptr;
}
private:
std::span<const std::string> inputs_;
std::span<const std::string> outputs_;
std::optional<Product> prod_;
};
class Buffer final : public ObjBase<nf7::gl::BufferFactory> {
public:
static inline const nf7::GenericTypeInfo<Buffer> kType = {
"GL/Buffer", {"nf7::DirItem",}};
static void UpdateTypeTooltip() noexcept {
ImGui::TextUnformatted("OpenGL buffer");
}
static inline const std::vector<std::string> kInputs = {
"resize", "upload", "download",
};
static inline const std::vector<std::string> kOutputs = {
"result",
};
class Lambda;
enum Type {
kArray,
kElement,
};
enum Usage {
kStaticDraw,
kDynamicDraw,
kStreamDraw,
kStaticRead,
kDynamicRead,
kStreamRead,
kStaticCopy,
kDynamicCopy,
kStreamCopy,
};
struct Data {
Type type;
Usage usage;
void serialize(auto& ar) {
ar(type, usage);
}
std::string Stringify() noexcept;
void Parse(const std::string& v);
};
Buffer(nf7::Env& env) noexcept :
ObjBase(kType, env, kInputs, kOutputs) {
}
Buffer(nf7::Deserializer& ar) noexcept : Buffer(ar.env()) {
ar(mem_.data());
}
void Serialize(nf7::Serializer&) const noexcept override {
ar(mem_.data());
}
std::unique_ptr<nf7::File> Clone(nf7::Env& env) const noexcept override {
return std::make_unique<Buffer>(env);
}
std::shared_ptr<nf7::Node::Lambda> CreateLambda(
const std::shared_ptr<nf7::Node::Lambda>& parent) noexcept override;
Product Create_() noexcept override {
// TODO
std::abort();
}
void UpdateTooltip() noexcept override {
if (auto prod = product()) {
ImGui::Text("size: %zu bytes", );
}
}
private:
nf7::Life<Buffer> life_;
nf7::GenericMemento<Data> data_;
};
std::string Buffer::Data::Stringify() noexcept {
YAML::Emitter st;
st << YAML::BeginMap;
st << YAML::Key << "type";
st << YAML::Value << std::string {magic_enum::enum_name(type)};
st << YAML::Key << "usage";
st << YAML::Value << std::string {magic_enum::enum_name(usage)};
st << YAML::EndMap;
return std::string {st.c_str(), st.size()};
}
void Buffer::Data::Parse(const std::string&)
try {
const auto yaml = YAML::Load(v);
const auto new_type = magic_enum::
enum_cast<Type>(yaml["type"].as<std::string>()).value();
const auto new_usage = magic_enum::
enum_cast<Usage>(yaml["usage"].as<std::string>()).value();
type = new_type;
usage = new_usage;
} catch (std::bad_optional_access&) {
throw nf7::Exception {"unknown enum"};
} catch (YAML::Exception& e) {
throw nf7::Exception {std::string {"YAML error: "}+e.what()};
}
}
} // namespace nf7
namespace magic_enum::customize {
template <>
constexpr customize_t magic_enum::customize::enum_name<nf7::Buffer::Type>(nf7::Buffer::Type v) noexcept {
switch (v) {
case nf7::Buffer::Type::kArray: return "array";
case nf7::Buffer::Type::kElement: return "element";
}
return invalid_tag;
}
template <>
constexpr customize_t magic_enum::customize::enum_name<nf7::BUffer::Usage>(nf7::Plot::SeriesFormat v) noexcept {
switch (v) {
case nf7::Buffer::Usage::kStaticDraw: return "StaticDraw";
case nf7::Buffer::Usage::kDynamicDraw: return "DynamicDraw";
case nf7::Buffer::Usage::kStreamDraw: return "StreamDraw";
case nf7::Buffer::Usage::kStaticRead: return "StaticRead";
case nf7::Buffer::Usage::kDynamicRead: return "DynamicRead";
case nf7::Buffer::Usage::kStreamRead: return "StreamRead";
case nf7::Buffer::Usage::kStaticCopy: return "StaticCopy";
case nf7::Buffer::Usage::kDynamicCopy: return "DynamicCopy";
case nf7::Buffer::Usage::kStreamCopy: return "StreamCopy";
}
return invalid_tag;
}
} // namespace magic_enum::customize
namespace yas::detail {
template <size_t F>
struct serializer<
yas::detail::type_prop::is_enum,
yas::detail::ser_case::use_internal_serializer,
F, nf7::Plot::SeriesType> :
nf7::EnumSerializer<nf7::Plot::SeriesType> {
};
template <size_t F>
struct serializer<
yas::detail::type_prop::is_enum,
yas::detail::ser_case::use_internal_serializer,
F, nf7::Plot::SeriesFormat> :
nf7::EnumSerializer<nf7::Plot::SeriesFormat> {
};
} // namespace yas::detail