refactor gl::Obj
This commit is contained in:
parent
694e9e34bb
commit
8ef4abd75e
102
common/gl_obj.cc
102
common/gl_obj.cc
@ -21,10 +21,10 @@ namespace nf7::gl {
|
||||
template <typename T>
|
||||
auto LockAndValidate(const std::shared_ptr<nf7::Context>& ctx,
|
||||
nf7::AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<T>>>& factory,
|
||||
std::function<void(const typename T::Meta&)>&& validator) noexcept {
|
||||
std::function<void(const T&)>&& validator) noexcept {
|
||||
typename nf7::Future<nf7::Mutex::Resource<std::shared_ptr<T>>>::Promise pro {ctx};
|
||||
factory.Create().Chain(pro, [validator](auto& v) {
|
||||
validator((*v)->meta());
|
||||
validator(**v);
|
||||
return v;
|
||||
});
|
||||
return pro.future();
|
||||
@ -33,13 +33,14 @@ static auto LockAndValidate(const std::shared_ptr<nf7::Context>& ctx,
|
||||
nf7::gl::BufferFactory& factory,
|
||||
nf7::gl::BufferTarget target,
|
||||
size_t required) noexcept {
|
||||
return LockAndValidate<gl::Buffer>(ctx, factory, [target, required](auto& m) {
|
||||
if (m.target != target) {
|
||||
return LockAndValidate<gl::Buffer>(ctx, factory, [target, required](auto& buf) {
|
||||
if (buf.meta().target != target) {
|
||||
throw nf7::Exception {"incompatible buffer target"};
|
||||
}
|
||||
if (m.size < required) {
|
||||
const auto size = buf.param().size;
|
||||
if (size < required) {
|
||||
std::stringstream st;
|
||||
st << "buffer shortage (" << m.size << "/" << required << ")";
|
||||
st << "buffer shortage (" << size << "/" << required << ")";
|
||||
throw nf7::Exception {st.str()};
|
||||
}
|
||||
});
|
||||
@ -47,8 +48,8 @@ static auto LockAndValidate(const std::shared_ptr<nf7::Context>& ctx,
|
||||
static auto LockAndValidate(const std::shared_ptr<nf7::Context>& ctx,
|
||||
nf7::gl::TextureFactory& factory,
|
||||
nf7::gl::TextureTarget target) noexcept {
|
||||
return LockAndValidate<gl::Texture>(ctx, factory, [target](auto& m) {
|
||||
if (m.target != target) {
|
||||
return LockAndValidate<gl::Texture>(ctx, factory, [target](auto& tex) {
|
||||
if (tex.meta().target != target) {
|
||||
throw nf7::Exception {"incompatible texture target"};
|
||||
}
|
||||
});
|
||||
@ -56,22 +57,21 @@ static auto LockAndValidate(const std::shared_ptr<nf7::Context>& ctx,
|
||||
|
||||
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_BufferMeta>>> Obj_BufferMeta::Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx, gl::BufferTarget target) noexcept {
|
||||
const std::shared_ptr<nf7::Context>& ctx) const noexcept {
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_BufferMeta>>>::Promise pro {ctx};
|
||||
ctx->env().ExecGL(ctx, [=]() mutable {
|
||||
ctx->env().ExecGL(ctx, [=, *this]() mutable {
|
||||
GLuint id;
|
||||
glGenBuffers(1, &id);
|
||||
pro.Return(std::make_shared<Obj<Obj_BufferMeta>>(ctx, id, target));
|
||||
pro.Return(std::make_shared<Obj<Obj_BufferMeta>>(ctx, id, *this));
|
||||
});
|
||||
return pro.future();
|
||||
}
|
||||
|
||||
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_TextureMeta>>> Obj_TextureMeta::Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
gl::TextureTarget target, GLint fmt, std::array<GLsizei, 3> size) noexcept {
|
||||
const std::shared_ptr<nf7::Context>& ctx) const noexcept {
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_TextureMeta>>>::Promise pro {ctx};
|
||||
ctx->env().ExecGL(ctx, [=]() mutable {
|
||||
ctx->env().ExecGL(ctx, [=, *this]() mutable {
|
||||
GLuint id;
|
||||
glGenTextures(1, &id);
|
||||
|
||||
@ -83,7 +83,8 @@ nf7::Future<std::shared_ptr<Obj<Obj_TextureMeta>>> Obj_TextureMeta::Create(
|
||||
glTexParameteri(t, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
switch (gl::GetDimension(target)) {
|
||||
case 2:
|
||||
glTexImage2D(t, 0, fmt, size[0], size[1], 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexImage2D(t, 0, format, size[0], size[1], 0,
|
||||
GL_RED, GL_UNSIGNED_BYTE, nullptr);
|
||||
break;
|
||||
default:
|
||||
assert(false && "unknown texture target");
|
||||
@ -91,7 +92,7 @@ nf7::Future<std::shared_ptr<Obj<Obj_TextureMeta>>> Obj_TextureMeta::Create(
|
||||
}
|
||||
glBindTexture(t, 0);
|
||||
|
||||
pro.Return(std::make_shared<Obj<Obj_TextureMeta>>(ctx, id, target, fmt, size));
|
||||
pro.Return(std::make_shared<Obj<Obj_TextureMeta>>(ctx, id, *this));
|
||||
});
|
||||
return pro.future();
|
||||
}
|
||||
@ -99,10 +100,9 @@ nf7::Future<std::shared_ptr<Obj<Obj_TextureMeta>>> Obj_TextureMeta::Create(
|
||||
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_ShaderMeta>>> Obj_ShaderMeta::Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
gl::ShaderType type,
|
||||
const std::string& src) noexcept {
|
||||
const std::string& src) const noexcept {
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_ShaderMeta>>>::Promise pro {ctx};
|
||||
ctx->env().ExecGL(ctx, [=]() mutable {
|
||||
ctx->env().ExecGL(ctx, [=, *this]() mutable {
|
||||
const auto t = gl::ToEnum(type);
|
||||
const auto id = glCreateShader(t);
|
||||
if (id == 0) {
|
||||
@ -122,7 +122,7 @@ nf7::Future<std::shared_ptr<Obj<Obj_ShaderMeta>>> Obj_ShaderMeta::Create(
|
||||
GLint status;
|
||||
glGetShaderiv(id, GL_COMPILE_STATUS, &status);
|
||||
if (status == GL_TRUE) {
|
||||
pro.Return(std::make_shared<Obj<Obj_ShaderMeta>>(ctx, id, type));
|
||||
pro.Return(std::make_shared<Obj<Obj_ShaderMeta>>(ctx, id, *this));
|
||||
} else {
|
||||
GLint len;
|
||||
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &len);
|
||||
@ -169,7 +169,7 @@ nf7::Future<std::shared_ptr<Obj<Obj_ProgramMeta>>> Obj_ProgramMeta::Create(
|
||||
GLint status;
|
||||
glGetProgramiv(id, GL_LINK_STATUS, &status);
|
||||
if (status == GL_TRUE) {
|
||||
return std::make_shared<Obj<Obj_ProgramMeta>>(ctx, id);
|
||||
return std::make_shared<Obj<Obj_ProgramMeta>>(ctx, id, gl::Program::Meta {});
|
||||
} else {
|
||||
GLint len;
|
||||
glGetProgramiv(id, GL_INFO_LOG_LENGTH, &len);
|
||||
@ -184,9 +184,7 @@ nf7::Future<std::shared_ptr<Obj<Obj_ProgramMeta>>> Obj_ProgramMeta::Create(
|
||||
|
||||
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_VertexArrayMeta>>> Obj_VertexArrayMeta::Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
const std::optional<Index>& index,
|
||||
std::vector<Attr>&& attrs) noexcept
|
||||
const std::shared_ptr<nf7::Context>& ctx) const noexcept
|
||||
try {
|
||||
if (index) {
|
||||
if (index->numtype != gl::NumericType::U8 &&
|
||||
@ -197,9 +195,9 @@ try {
|
||||
}
|
||||
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_VertexArrayMeta>>>::Promise pro {ctx};
|
||||
LockBuffers(ctx, index, attrs).Chain(
|
||||
LockBuffers(ctx).Chain(
|
||||
nf7::Env::kGL, ctx, pro,
|
||||
[ctx, index, attrs = std::move(attrs), pro](auto& bufs) mutable {
|
||||
[*this, ctx, pro](auto& bufs) mutable {
|
||||
// check all buffers
|
||||
if (index) {
|
||||
assert(bufs.size() == attrs.size()+1);
|
||||
@ -242,7 +240,7 @@ try {
|
||||
glBindVertexArray(0);
|
||||
assert(0 == glGetError());
|
||||
|
||||
return std::make_shared<Obj<Obj_VertexArrayMeta>>(ctx, id, index, std::move(attrs));
|
||||
return std::make_shared<Obj<Obj_VertexArrayMeta>>(ctx, id, *this);
|
||||
});
|
||||
return pro.future();
|
||||
} catch (nf7::Exception&) {
|
||||
@ -252,9 +250,7 @@ try {
|
||||
nf7::Future<std::vector<nf7::Mutex::Resource<std::shared_ptr<gl::Buffer>>>>
|
||||
Obj_VertexArrayMeta::LockBuffers(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
const std::optional<Index>& index,
|
||||
const std::vector<Attr>& attrs,
|
||||
const ValidationHint& vhint) noexcept
|
||||
const ValidationHint& vhint) const noexcept
|
||||
try {
|
||||
nf7::AggregatePromise apro {ctx};
|
||||
|
||||
@ -309,20 +305,22 @@ try {
|
||||
|
||||
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_FramebufferMeta>>> Obj_FramebufferMeta::Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
std::vector<Attachment>&& atts) noexcept {
|
||||
const std::shared_ptr<nf7::Context>& ctx) const noexcept {
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_FramebufferMeta>>>::Promise pro {ctx};
|
||||
LockAttachments(ctx, atts).
|
||||
Chain(nf7::Env::kGL, ctx, pro, [ctx, atts = std::move(atts)](auto& texs) mutable {
|
||||
assert(atts.size() == texs.size());
|
||||
LockAttachments(ctx).
|
||||
Chain(nf7::Env::kGL, ctx, pro, [ctx, *this](auto& texs) mutable {
|
||||
assert(attachments.size() == texs.size());
|
||||
|
||||
GLuint id;
|
||||
glGenFramebuffers(1, &id);
|
||||
|
||||
const char* err = nullptr;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, id);
|
||||
for (size_t i = 0; i < atts.size() && !err; ++i) {
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, gl::ToEnum(atts[i].slot), (*texs[i])->id(), 0);
|
||||
for (size_t i = 0; i < attachments.size() && !err; ++i) {
|
||||
glFramebufferTexture(GL_FRAMEBUFFER,
|
||||
gl::ToEnum(attachments[i].slot),
|
||||
(*texs[i])->id(),
|
||||
0 /* = level */);
|
||||
if (0 != glGetError()) {
|
||||
err = "failed to attach texture";
|
||||
}
|
||||
@ -331,11 +329,13 @@ nf7::Future<std::shared_ptr<Obj<Obj_FramebufferMeta>>> Obj_FramebufferMeta::Crea
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
assert(0 == glGetError());
|
||||
|
||||
const auto ret = std::make_shared<Obj<Obj_FramebufferMeta>>(ctx, id, std::move(atts));
|
||||
const auto ret = std::make_shared<Obj<Obj_FramebufferMeta>>(ctx, id, *this);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
throw nf7::Exception {"invalid framebuffer status"};
|
||||
}
|
||||
if (err) {
|
||||
throw nf7::Exception {err};
|
||||
}
|
||||
ThrowStatus(status);
|
||||
return ret;
|
||||
});
|
||||
return pro.future();
|
||||
@ -343,8 +343,7 @@ nf7::Future<std::shared_ptr<Obj<Obj_FramebufferMeta>>> Obj_FramebufferMeta::Crea
|
||||
|
||||
nf7::Future<std::vector<nf7::Mutex::Resource<std::shared_ptr<gl::Texture>>>>
|
||||
Obj_FramebufferMeta::LockAttachments(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
std::span<const Attachment> attachments) noexcept
|
||||
const std::shared_ptr<nf7::Context>& ctx) const noexcept
|
||||
try {
|
||||
nf7::AggregatePromise apro {ctx};
|
||||
std::vector<nf7::Future<nf7::Mutex::Resource<std::shared_ptr<gl::Texture>>>> fus;
|
||||
@ -373,25 +372,4 @@ try {
|
||||
return { std::current_exception() };
|
||||
}
|
||||
|
||||
void Obj_FramebufferMeta::ThrowStatus(GLenum status) {
|
||||
switch (status) {
|
||||
case GL_FRAMEBUFFER_COMPLETE:
|
||||
return;
|
||||
case GL_FRAMEBUFFER_UNDEFINED:
|
||||
throw nf7::Exception {"no framebuffer bound"};
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
|
||||
throw nf7::Exception {"no framebuffer bound"};
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
|
||||
throw nf7::Exception {"nothing attached"};
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
|
||||
throw nf7::Exception {"no color attachments"};
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED:
|
||||
throw nf7::Exception {"unsupported internal format"};
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
|
||||
throw nf7::Exception {"incomplete multisample"};
|
||||
default:
|
||||
throw nf7::Exception {"unknown framebuffer status"};
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace nf7::gl
|
||||
|
138
common/gl_obj.hh
138
common/gl_obj.hh
@ -22,17 +22,11 @@ namespace nf7::gl {
|
||||
template <typename T>
|
||||
class Obj final {
|
||||
public:
|
||||
using Meta = T;
|
||||
using Meta = T;
|
||||
using Param = typename Meta::Param;
|
||||
|
||||
// must be called from main or sub task
|
||||
template <typename... Args>
|
||||
static nf7::Future<std::shared_ptr<Obj<T>>> Create(Args&&... args) noexcept {
|
||||
return Meta::Create(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
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) {
|
||||
Obj(const std::shared_ptr<nf7::Context>& ctx, GLuint id, const Meta& meta) noexcept :
|
||||
ctx_(ctx), id_(id), meta_(meta) {
|
||||
}
|
||||
~Obj() noexcept {
|
||||
ctx_->env().ExecGL(ctx_, [id = id_]() { T::Delete(id); });
|
||||
@ -43,35 +37,34 @@ class Obj final {
|
||||
Obj& operator=(Obj&&) = delete;
|
||||
|
||||
GLuint id() const noexcept { return id_; }
|
||||
const Meta& meta() const noexcept { return meta_; }
|
||||
|
||||
T& meta() noexcept { return meta_; }
|
||||
const T& meta() const noexcept { return meta_; }
|
||||
Param& param() noexcept { return param_; }
|
||||
const Param& param() const noexcept { return param_; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<nf7::Context> ctx_;
|
||||
|
||||
T meta_;
|
||||
const GLuint id_;
|
||||
const Meta meta_;
|
||||
|
||||
Param param_;
|
||||
};
|
||||
|
||||
|
||||
struct Obj_BufferMeta final {
|
||||
public:
|
||||
// must be called from main or sub task
|
||||
static nf7::Future<std::shared_ptr<Obj<Obj_BufferMeta>>> Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx, gl::BufferTarget target) noexcept;
|
||||
struct Param { size_t size = 0; };
|
||||
|
||||
static void Delete(GLuint id) noexcept {
|
||||
glDeleteBuffers(1, &id);
|
||||
}
|
||||
|
||||
Obj_BufferMeta() = delete;
|
||||
Obj_BufferMeta(gl::BufferTarget t) noexcept : target(t) {
|
||||
}
|
||||
// must be called from main or sub task
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_BufferMeta>>> Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx) const noexcept;
|
||||
|
||||
const gl::BufferTarget target;
|
||||
|
||||
size_t size = 0;
|
||||
gl::BufferTarget target;
|
||||
};
|
||||
using Buffer = Obj<Obj_BufferMeta>;
|
||||
using BufferFactory = AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<Buffer>>>;
|
||||
@ -79,23 +72,19 @@ using BufferFactory = AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<Buffer>>
|
||||
|
||||
struct Obj_TextureMeta final {
|
||||
public:
|
||||
// must be called from main or sub task
|
||||
static nf7::Future<std::shared_ptr<Obj<Obj_TextureMeta>>> Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
gl::TextureTarget target, GLint fmt, std::array<GLsizei, 3> size) noexcept;
|
||||
struct Param { };
|
||||
|
||||
static void Delete(GLuint id) noexcept {
|
||||
glDeleteTextures(1, &id);
|
||||
}
|
||||
|
||||
Obj_TextureMeta() = delete;
|
||||
Obj_TextureMeta(gl::TextureTarget t, GLint f, std::array<GLsizei, 3> s) noexcept :
|
||||
target(t), format(f), size(s) {
|
||||
}
|
||||
// must be called from main or sub task
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_TextureMeta>>> Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx) const noexcept;
|
||||
|
||||
const gl::TextureTarget target;
|
||||
const GLint format;
|
||||
const std::array<GLsizei, 3> size;
|
||||
gl::TextureTarget target;
|
||||
GLint format;
|
||||
std::array<GLsizei, 3> size;
|
||||
};
|
||||
using Texture = Obj<Obj_TextureMeta>;
|
||||
using TextureFactory = AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<Texture>>>;
|
||||
@ -103,21 +92,18 @@ using TextureFactory = AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<Texture
|
||||
|
||||
struct Obj_ShaderMeta final {
|
||||
public:
|
||||
// must be called from main or sub task
|
||||
static nf7::Future<std::shared_ptr<Obj<Obj_ShaderMeta>>> Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
gl::ShaderType type,
|
||||
const std::string& src) noexcept;
|
||||
struct Param { };
|
||||
|
||||
static void Delete(GLuint id) noexcept {
|
||||
glDeleteShader(id);
|
||||
}
|
||||
|
||||
Obj_ShaderMeta() = delete;
|
||||
Obj_ShaderMeta(gl::ShaderType t) noexcept : type(t) {
|
||||
}
|
||||
// must be called from main or sub task
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_ShaderMeta>>> Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
const std::string& src) const noexcept;
|
||||
|
||||
const gl::ShaderType type;
|
||||
gl::ShaderType type;
|
||||
};
|
||||
using Shader = Obj<Obj_ShaderMeta>;
|
||||
using ShaderFactory = AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<Shader>>>;
|
||||
@ -125,16 +111,16 @@ using ShaderFactory = AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<Shader>>
|
||||
|
||||
struct Obj_ProgramMeta final {
|
||||
public:
|
||||
// must be called from main or sub task
|
||||
static nf7::Future<std::shared_ptr<Obj<Obj_ProgramMeta>>> Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
const std::vector<nf7::File::Id>& shaders) noexcept;
|
||||
struct Param { };
|
||||
|
||||
static void Delete(GLuint id) noexcept {
|
||||
glDeleteProgram(id);
|
||||
}
|
||||
|
||||
Obj_ProgramMeta() = default;
|
||||
// must be called from main or sub task
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_ProgramMeta>>> Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
const std::vector<nf7::File::Id>& shaders) noexcept;
|
||||
};
|
||||
using Program = Obj<Obj_ProgramMeta>;
|
||||
using ProgramFactory = AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<Program>>>;
|
||||
@ -142,6 +128,8 @@ using ProgramFactory = AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<Program
|
||||
|
||||
struct Obj_VertexArrayMeta final {
|
||||
public:
|
||||
struct Param { };
|
||||
|
||||
using LockedBuffersFuture =
|
||||
nf7::Future<std::vector<nf7::Mutex::Resource<std::shared_ptr<gl::Buffer>>>>;
|
||||
|
||||
@ -159,6 +147,7 @@ struct Obj_VertexArrayMeta final {
|
||||
uint64_t offset;
|
||||
GLuint divisor;
|
||||
};
|
||||
|
||||
struct ValidationHint {
|
||||
ValidationHint() noexcept { }
|
||||
|
||||
@ -166,40 +155,22 @@ struct Obj_VertexArrayMeta final {
|
||||
size_t instances = 0;
|
||||
};
|
||||
|
||||
// must be called from main or sub task
|
||||
static nf7::Future<std::shared_ptr<Obj<Obj_VertexArrayMeta>>> Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
const std::optional<Index>& index,
|
||||
std::vector<Attr>&& attrs) noexcept;
|
||||
|
||||
static void Delete(GLuint id) noexcept {
|
||||
glDeleteVertexArrays(1, &id);
|
||||
}
|
||||
|
||||
// must be called from main or sub task
|
||||
// it's guaranteed that the last element of the returned vector is an index buffer if index != std::nullopt
|
||||
static LockedBuffersFuture
|
||||
LockBuffers(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
const std::optional<Index>& index,
|
||||
const std::vector<Attr>& attrs,
|
||||
const ValidationHint& vhint = {}) noexcept;
|
||||
|
||||
Obj_VertexArrayMeta(const std::optional<Index>& idx,
|
||||
std::vector<Attr>&& a) noexcept :
|
||||
index(idx), attrs(std::move(a)) {
|
||||
}
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_VertexArrayMeta>>> Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx) const noexcept;
|
||||
|
||||
// must be called from main or sub task
|
||||
// it's guaranteed that the last element of the returned vector is an index buffer if index != std::nullopt
|
||||
nf7::Future<std::vector<nf7::Mutex::Resource<std::shared_ptr<gl::Buffer>>>> LockBuffers(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
const ValidationHint& vhint = {}) const noexcept {
|
||||
return LockBuffers(ctx, index, attrs, vhint);
|
||||
}
|
||||
const ValidationHint& vhint = {}) const noexcept;
|
||||
|
||||
const std::optional<Index> index;
|
||||
const std::vector<Attr> attrs;
|
||||
std::optional<Index> index;
|
||||
std::vector<Attr> attrs;
|
||||
};
|
||||
using VertexArray = Obj<Obj_VertexArrayMeta>;
|
||||
using VertexArrayFactory = AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<VertexArray>>>;
|
||||
@ -210,37 +181,26 @@ struct Obj_FramebufferMeta final {
|
||||
using LockedAttachmentsFuture =
|
||||
nf7::Future<std::vector<nf7::Mutex::Resource<std::shared_ptr<gl::Texture>>>>;
|
||||
|
||||
struct Param { };
|
||||
|
||||
struct Attachment {
|
||||
nf7::File::Id tex;
|
||||
gl::FramebufferSlot slot;
|
||||
};
|
||||
|
||||
// must be called from main or sub task
|
||||
static nf7::Future<std::shared_ptr<Obj<Obj_FramebufferMeta>>> Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
std::vector<Attachment>&& attachments) noexcept;
|
||||
|
||||
static void Delete(GLuint id) noexcept {
|
||||
glDeleteFramebuffers(1, &id);
|
||||
}
|
||||
|
||||
// must be called from main or sub task
|
||||
static LockedAttachmentsFuture LockAttachments(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
std::span<const Attachment> attachments) noexcept;
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_FramebufferMeta>>> Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx) const noexcept;
|
||||
|
||||
// must be called on GL thread
|
||||
static void ThrowStatus(GLenum status);
|
||||
nf7::Future<std::vector<nf7::Mutex::Resource<std::shared_ptr<gl::Texture>>>>
|
||||
LockAttachments(
|
||||
const std::shared_ptr<nf7::Context>& ctx) const noexcept;
|
||||
|
||||
Obj_FramebufferMeta(std::vector<Attachment>&& a) noexcept : attachments(std::move(a)) {
|
||||
}
|
||||
|
||||
nf7::Future<std::vector<nf7::Mutex::Resource<std::shared_ptr<gl::Texture>>>> LockAttachments(
|
||||
const std::shared_ptr<nf7::Context>& ctx) noexcept {
|
||||
return LockAttachments(ctx, attachments);
|
||||
}
|
||||
|
||||
const std::vector<Attachment> attachments;
|
||||
std::vector<Attachment> attachments;
|
||||
};
|
||||
using Framebuffer = Obj<Obj_FramebufferMeta>;
|
||||
using FramebufferFactory = AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<Framebuffer>>>;
|
||||
|
@ -317,7 +317,10 @@ struct Buffer {
|
||||
}
|
||||
|
||||
nf7::Future<std::shared_ptr<Product>> Create(const CreateParam& p) noexcept {
|
||||
return Product::Create(p.ctx, target_);
|
||||
const Product::Meta meta {
|
||||
.target = target_,
|
||||
};
|
||||
return meta.Create(p.ctx);
|
||||
}
|
||||
|
||||
bool Handle(const HandleParam<Product>& p) {
|
||||
@ -331,12 +334,12 @@ struct Buffer {
|
||||
const auto n = static_cast<GLsizeiptr>(vec->size());
|
||||
|
||||
auto& buf = **p.obj;
|
||||
auto& m = buf.meta();
|
||||
const auto t = gl::ToEnum(m.target);
|
||||
const auto t = gl::ToEnum(buf.meta().target);
|
||||
glBindBuffer(t, buf.id());
|
||||
{
|
||||
if (m.size != vec->size()) {
|
||||
m.size = vec->size();
|
||||
auto& size = buf.param().size;
|
||||
if (size != vec->size()) {
|
||||
size = vec->size();
|
||||
glBufferData(t, n, vec->data(), usage);
|
||||
} else {
|
||||
glBufferSubData(t, 0, n, vec->data());
|
||||
@ -357,7 +360,7 @@ struct Buffer {
|
||||
if (prod) {
|
||||
ImGui::Spacing();
|
||||
ImGui::Text(" id: %zu", static_cast<size_t>(prod->id()));
|
||||
ImGui::Text("size: %zu bytes", prod->meta().size);
|
||||
ImGui::Text("size: %zu bytes", prod->param().size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -448,12 +451,14 @@ struct Texture {
|
||||
|
||||
nf7::Future<std::shared_ptr<Product>> Create(const CreateParam& p) noexcept
|
||||
try {
|
||||
std::array<GLsizei, 3> size;
|
||||
std::transform(size_.begin(), size_.end(), size.begin(),
|
||||
Product::Meta meta {
|
||||
.target = target_,
|
||||
.format = static_cast<GLint>(gl::ToInternalFormat(numtype_, comp_)),
|
||||
.size = {},
|
||||
};
|
||||
std::transform(size_.begin(), size_.end(), meta.size.begin(),
|
||||
[](auto x) { return static_cast<GLsizei>(x); });
|
||||
// FIXME cast is unnecessary
|
||||
return Product::Create(
|
||||
p.ctx, target_, static_cast<GLint>(gl::ToInternalFormat(numtype_, comp_)), size);
|
||||
return meta.Create(p.ctx);
|
||||
} catch (nf7::Exception&) {
|
||||
return {std::current_exception()};
|
||||
}
|
||||
@ -676,7 +681,10 @@ struct Shader {
|
||||
auto preproc = std::make_shared<gl::ShaderPreproc>(p.ctx, ost, ist, std::move(path));
|
||||
preproc->ExecProcess();
|
||||
preproc->future().Chain(p.ctx, pro, [=, type = type_](auto&) mutable {
|
||||
Product::Create(p.ctx, type, ost->str()).Chain(pro);
|
||||
const Product::Meta meta {
|
||||
.type = type,
|
||||
};
|
||||
meta.Create(p.ctx, ost->str()).Chain(pro);
|
||||
});
|
||||
return pro.future().
|
||||
ThenIf(p.ctx, [=](auto&) mutable {
|
||||
@ -773,7 +781,7 @@ struct Program {
|
||||
p.watch->Watch(fid);
|
||||
shaders.push_back(fid);
|
||||
}
|
||||
return Product::Create(p.ctx, shaders);
|
||||
return Product::Meta().Create(p.ctx, shaders);
|
||||
} catch (nf7::Exception&) {
|
||||
return {std::current_exception()};
|
||||
}
|
||||
@ -917,9 +925,7 @@ struct Program {
|
||||
glUseProgram(0);
|
||||
assert(0 == glGetError());
|
||||
|
||||
try {
|
||||
nf7::gl::Framebuffer::Meta::ThrowStatus(status);
|
||||
} catch (nf7::Exception& e) {
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
p.log->Warn("framebuffer is broken");
|
||||
}
|
||||
});
|
||||
@ -1131,23 +1137,22 @@ struct VertexArray {
|
||||
nf7::Future<std::shared_ptr<Product>> Create(const CreateParam& p) noexcept
|
||||
try {
|
||||
auto& base = *p.file;
|
||||
Product::Meta meta;
|
||||
|
||||
std::optional<nf7::gl::VertexArray::Meta::Index> index;
|
||||
if (index_.terms().size() > 0) {
|
||||
const auto fid = base.ResolveOrThrow(index_).id();
|
||||
p.watch->Watch(fid);
|
||||
|
||||
index.emplace();
|
||||
index->buffer = fid;
|
||||
index->numtype = index_numtype_;
|
||||
meta.index.emplace();
|
||||
meta.index->buffer = fid;
|
||||
meta.index->numtype = index_numtype_;
|
||||
}
|
||||
|
||||
std::vector<Product::Meta::Attr> attrs;
|
||||
attrs.reserve(attrs_.size());
|
||||
meta.attrs.reserve(attrs_.size());
|
||||
for (auto& attr : attrs_) {
|
||||
const auto fid = base.ResolveOrThrow(attr.buffer).id();
|
||||
p.watch->Watch(fid);
|
||||
attrs.push_back({
|
||||
meta.attrs.push_back({
|
||||
.buffer = fid,
|
||||
.location = attr.location,
|
||||
.size = attr.size,
|
||||
@ -1158,7 +1163,7 @@ struct VertexArray {
|
||||
.divisor = attr.divisor,
|
||||
});
|
||||
}
|
||||
return Product::Create(p.ctx, index, std::move(attrs));
|
||||
return meta.Create(p.ctx);
|
||||
} catch (nf7::Exception&) {
|
||||
return {std::current_exception()};
|
||||
}
|
||||
@ -1253,20 +1258,20 @@ struct Framebuffer {
|
||||
nf7::Future<std::shared_ptr<Product>> Create(const CreateParam& p) noexcept
|
||||
try {
|
||||
auto& base = *p.file;
|
||||
Product::Meta meta;
|
||||
|
||||
std::vector<nf7::gl::Framebuffer::Meta::Attachment> attachments;
|
||||
for (auto& attachment : attachments_) {
|
||||
nf7::File::Id fid = 0;
|
||||
if (attachment.path.terms().size() > 0) {
|
||||
fid = base.ResolveOrThrow(attachment.path).id();
|
||||
p.watch->Watch(fid);
|
||||
}
|
||||
attachments.push_back({
|
||||
meta.attachments.push_back({
|
||||
.tex = fid,
|
||||
.slot = attachment.slot,
|
||||
});
|
||||
}
|
||||
return Product::Create(p.ctx, std::move(attachments));
|
||||
return meta.Create(p.ctx);
|
||||
} catch (nf7::Exception&) {
|
||||
return {std::current_exception()};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user