240 lines
5.9 KiB
C++
240 lines
5.9 KiB
C++
#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
|