Compare commits
1 Commits
2edd7d9e88
...
354ce630f6
Author | SHA1 | Date | |
---|---|---|---|
354ce630f6 |
@ -67,6 +67,7 @@ target_sources(nf7
|
||||
common/audio_queue.hh
|
||||
common/dir.hh
|
||||
common/dir_item.hh
|
||||
common/factory.hh
|
||||
common/file_base.hh
|
||||
common/file_holder.hh
|
||||
common/file_holder.cc
|
||||
@ -76,6 +77,7 @@ target_sources(nf7
|
||||
common/generic_memento.hh
|
||||
common/generic_type_info.hh
|
||||
common/generic_watcher.hh
|
||||
common/gl_obj.hh
|
||||
common/gui_config.hh
|
||||
common/gui_context.hh
|
||||
common/gui_dnd.hh
|
||||
@ -133,6 +135,7 @@ target_sources(nf7
|
||||
|
||||
file/audio_context.cc
|
||||
file/audio_device.cc
|
||||
file/gl_obj.cc
|
||||
file/luajit_context.cc
|
||||
file/luajit_node.cc
|
||||
file/node_imm.cc
|
||||
|
27
common/factory.hh
Normal file
27
common/factory.hh
Normal 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
83
common/gl_obj.hh
Normal 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
239
file/gl_obj.cc
Normal 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
|
Loading…
x
Reference in New Issue
Block a user