use custom enum to represent metadata of GL objects

This commit is contained in:
falsycat 2022-10-25 11:43:56 +09:00
parent f869f191f2
commit d5b5e664d7
3 changed files with 65 additions and 83 deletions

View File

@ -14,12 +14,12 @@
namespace nf7::gl {
nf7::Future<std::shared_ptr<Obj<Obj_BufferMeta>>> Obj_BufferMeta::Create(
const std::shared_ptr<nf7::Context>& ctx, GLenum type) noexcept {
const std::shared_ptr<nf7::Context>& ctx, gl::BufferTarget target) noexcept {
nf7::Future<std::shared_ptr<Obj<Obj_BufferMeta>>>::Promise pro {ctx};
ctx->env().ExecGL(ctx, [=]() mutable {
GLuint id;
glGenBuffers(1, &id);
pro.Return(std::make_shared<Obj<Obj_BufferMeta>>(ctx, id, type));
pro.Return(std::make_shared<Obj<Obj_BufferMeta>>(ctx, id, target));
});
return pro.future();
}
@ -27,29 +27,29 @@ nf7::Future<std::shared_ptr<Obj<Obj_BufferMeta>>> Obj_BufferMeta::Create(
nf7::Future<std::shared_ptr<Obj<Obj_TextureMeta>>> Obj_TextureMeta::Create(
const std::shared_ptr<nf7::Context>& ctx,
GLenum type, GLint fmt, std::array<GLsizei, 3> size) noexcept {
gl::TextureTarget target, GLint fmt, std::array<GLsizei, 3> size) noexcept {
nf7::Future<std::shared_ptr<Obj<Obj_TextureMeta>>>::Promise pro {ctx};
ctx->env().ExecGL(ctx, [=]() mutable {
GLuint id;
glGenTextures(1, &id);
glBindTexture(type, id);
glTexParameteri(type, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
switch (type) {
case GL_TEXTURE_2D:
case GL_TEXTURE_RECTANGLE:
glTexImage2D(type, 0, fmt, size[0], size[1], 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
const auto t = gl::ToEnum(target);
glBindTexture(t, id);
glTexParameteri(t, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(t, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(t, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
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);
break;
default:
assert(false && "unknown texture type");
assert(false && "unknown texture target");
break;
}
glBindTexture(type, 0);
glBindTexture(t, 0);
pro.Return(std::make_shared<Obj<Obj_TextureMeta>>(ctx, id, type, fmt, size));
pro.Return(std::make_shared<Obj<Obj_TextureMeta>>(ctx, id, target, fmt, size));
});
return pro.future();
}
@ -57,11 +57,12 @@ 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,
GLenum type,
gl::ShaderType type,
const std::string& src) noexcept {
nf7::Future<std::shared_ptr<Obj<Obj_ShaderMeta>>>::Promise pro {ctx};
ctx->env().ExecGL(ctx, [=]() mutable {
const auto id = glCreateShader(type);
const auto t = gl::ToEnum(type);
const auto id = glCreateShader(t);
if (id == 0) {
pro.Throw<nf7::Exception>("failed to allocate new shader");
return;
@ -146,7 +147,7 @@ try {
// check all buffers
assert(attrs.size() == bufs.size());
for (auto& buf : bufs) {
if ((*buf.value()).meta().type != GL_ARRAY_BUFFER) {
if ((*buf.value()).meta().target != gl::BufferTarget::Array) {
throw nf7::Exception {"buffer is not Array"};
}
}
@ -164,7 +165,7 @@ try {
glVertexAttribPointer(
attr.index,
attr.size,
attr.type,
gl::ToEnum(attr.type),
attr.normalize,
attr.stride,
reinterpret_cast<GLvoid*>(static_cast<GLintptr>(attr.offset)));
@ -194,28 +195,7 @@ try {
// calculate size required to the buffer
size_t required = 0;
if (attr.divisor == 0 && vcnt > 0) {
required = static_cast<size_t>(attr.size)*vcnt;
switch (attr.type) {
case GL_UNSIGNED_BYTE:
case GL_BYTE:
required *= 1;
break;
case GL_UNSIGNED_SHORT:
case GL_SHORT:
case GL_HALF_FLOAT:
required *= 2;
break;
case GL_UNSIGNED_INT:
case GL_INT:
case GL_FLOAT:
required *= 4;
break;
case GL_DOUBLE:
required *= 8;
break;
default:
throw nf7::Exception {"unknown attribute type"};
}
required = static_cast<size_t>(attr.size)*vcnt*gl::GetByteSize(attr.type);
} else if (attr.divisor > 0 && icnt > 0) {
required = static_cast<size_t>(attr.stride)*(icnt-1) + attr.offset;
}
@ -230,7 +210,7 @@ try {
return v;
});
// register a future of the validation
// register the validation future
apro.Add(pro.future());
fus.emplace_back(pro.future());
}
@ -264,7 +244,7 @@ nf7::Future<std::shared_ptr<Obj<Obj_FramebufferMeta>>> Obj_FramebufferMeta::Crea
const char* err = nullptr;
glBindFramebuffer(GL_FRAMEBUFFER, id);
for (size_t i = 0; i < atts.size() && !err; ++i) {
glFramebufferTexture(GL_FRAMEBUFFER, atts[i].slot, (*texs[i])->id(), 0);
glFramebufferTexture(GL_FRAMEBUFFER, gl::ToEnum(atts[i].slot), (*texs[i])->id(), 0);
if (0 != glGetError()) {
err = "failed to attach texture";
}
@ -296,7 +276,7 @@ try {
auto fu = ctx->env().GetFileOrThrow(attachment.tex).
interfaceOrThrow<nf7::gl::TextureFactory>().Create().
Chain(nf7::Env::kGL, ctx, pro, [](auto& tex) {
if ((*tex)->meta().type != GL_TEXTURE_2D) {
if ((*tex)->meta().target != gl::TextureTarget::Tex2D) {
throw nf7::Exception {"only 2D texture is allowed"};
}
return tex;

View File

@ -12,6 +12,7 @@
#include "common/factory.hh"
#include "common/future.hh"
#include "common/gl_enum.hh"
#include "common/mutex.hh"
@ -57,17 +58,17 @@ 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, GLenum type) noexcept;
const std::shared_ptr<nf7::Context>& ctx, gl::BufferTarget target) noexcept;
static void Delete(GLuint id) noexcept {
glDeleteBuffers(1, &id);
}
Obj_BufferMeta() = delete;
Obj_BufferMeta(GLenum t) noexcept : type(t) {
Obj_BufferMeta(gl::BufferTarget t) noexcept : target(t) {
}
const GLenum type;
const gl::BufferTarget target;
size_t size = 0;
};
@ -80,18 +81,18 @@ struct Obj_TextureMeta final {
// 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,
GLenum type, GLint fmt, std::array<GLsizei, 3> size) noexcept;
gl::TextureTarget target, GLint fmt, std::array<GLsizei, 3> size) noexcept;
static void Delete(GLuint id) noexcept {
glDeleteTextures(1, &id);
}
Obj_TextureMeta() = delete;
Obj_TextureMeta(GLenum t, GLint f, std::array<GLsizei, 3> s) noexcept :
type(t), format(f), size(s) {
Obj_TextureMeta(gl::TextureTarget t, GLint f, std::array<GLsizei, 3> s) noexcept :
target(t), format(f), size(s) {
}
const GLenum type;
const gl::TextureTarget target;
const GLint format;
const std::array<GLsizei, 3> size;
};
@ -104,7 +105,7 @@ struct Obj_ShaderMeta final {
// 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,
GLenum type,
gl::ShaderType type,
const std::string& src) noexcept;
static void Delete(GLuint id) noexcept {
@ -112,10 +113,10 @@ struct Obj_ShaderMeta final {
}
Obj_ShaderMeta() = delete;
Obj_ShaderMeta(GLenum t) noexcept : type(t) {
Obj_ShaderMeta(gl::ShaderType t) noexcept : type(t) {
}
const GLenum type;
const gl::ShaderType type;
};
using Shader = Obj<Obj_ShaderMeta>;
using ShaderFactory = AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<Shader>>>;
@ -144,14 +145,14 @@ struct Obj_VertexArrayMeta final {
nf7::Future<std::vector<nf7::Mutex::Resource<std::shared_ptr<gl::Buffer>>>>;
struct Attr {
nf7::File::Id buffer;
GLuint index;
GLint size;
GLenum type;
bool normalize;
GLsizei stride;
uint64_t offset;
GLuint divisor;
nf7::File::Id buffer;
GLuint index;
GLint size;
gl::NumericType type;
bool normalize;
GLsizei stride;
uint64_t offset;
GLuint divisor;
};
// must be called from main or sub task
@ -189,8 +190,8 @@ struct Obj_FramebufferMeta final {
nf7::Future<std::vector<nf7::Mutex::Resource<std::shared_ptr<gl::Texture>>>>;
struct Attachment {
nf7::File::Id tex;
GLenum slot;
nf7::File::Id tex;
gl::FramebufferSlot slot;
};
// must be called from main or sub task

View File

@ -273,7 +273,7 @@ struct Buffer {
}
nf7::Future<std::shared_ptr<Product>> Create(const std::shared_ptr<nf7::Context>& ctx) noexcept {
return Product::Create(ctx, gl::ToEnum(target_));
return Product::Create(ctx, target_);
}
bool Handle(const std::shared_ptr<nf7::Node::Lambda>& handler,
@ -289,16 +289,17 @@ struct Buffer {
auto& buf = **res;
auto& m = buf.meta();
glBindBuffer(m.type, buf.id());
const auto t = gl::ToEnum(m.target);
glBindBuffer(t, buf.id());
{
if (m.size != vec->size()) {
m.size = vec->size();
glBufferData(m.type, n, vec->data(), usage);
glBufferData(t, n, vec->data(), usage);
} else {
glBufferSubData(m.type, 0, n, vec->data());
glBufferSubData(t, 0, n, vec->data());
}
}
glBindBuffer(m.type, 0);
glBindBuffer(t, 0);
assert(0 == glGetError());
});
return true;
@ -409,7 +410,7 @@ struct Texture {
[](auto x) { return static_cast<GLsizei>(x); });
// FIXME cast is unnecessary
return Product::Create(
ctx, gl::ToEnum(target_), static_cast<GLint>(gl::ToInternalFormat(numtype_, comp_)), size);
ctx, target_, static_cast<GLint>(gl::ToInternalFormat(numtype_, comp_)), size);
} catch (nf7::Exception&) {
return {std::current_exception()};
}
@ -449,12 +450,12 @@ struct Texture {
const auto fmt = gl::ToEnum(comp_);
const auto type = gl::ToEnum(numtype_);
handler->env().ExecGL(handler, [=, &tex]() {
const auto target = tex.meta().type;
glBindTexture(target, tex.id());
switch (target) {
const auto t = gl::ToEnum(tex.meta().target);
glBindTexture(t, tex.id());
switch (t) {
case GL_TEXTURE_2D:
case GL_TEXTURE_RECTANGLE:
glTexSubImage2D(target, 0,
glTexSubImage2D(t, 0,
static_cast<GLint>(offset[0]),
static_cast<GLint>(offset[1]),
static_cast<GLsizei>(size[0]),
@ -465,7 +466,7 @@ struct Texture {
assert(false);
break;
}
glBindTexture(target, 0);
glBindTexture(t, 0);
assert(0 == glGetError());
});
return true;
@ -486,10 +487,10 @@ struct Texture {
const auto bsize = static_cast<size_t>(texel)*GetCompCount(comp)*GetByteSize(numtype);
glBufferData(GL_PIXEL_PACK_BUFFER, static_cast<GLsizeiptr>(bsize), nullptr, GL_DYNAMIC_READ);
const auto target = tex.meta().type;
glBindTexture(target, tex.id());
glGetTexImage(target, 0, gl::ToEnum(comp), gl::ToEnum(numtype), nullptr);
glBindTexture(target, 0);
const auto t = gl::ToEnum(tex.meta().target);
glBindTexture(t, tex.id());
glGetTexImage(t, 0, gl::ToEnum(comp), gl::ToEnum(numtype), nullptr);
glBindTexture(t, 0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
assert(0 == glGetError());
@ -543,7 +544,7 @@ struct Texture {
const auto& m = prod->meta();
ImGui::Text("id: %" PRIiPTR, id);
if (m.type == GL_TEXTURE_2D) {
if (m.target == gl::TextureTarget::Tex2D) {
ImGui::Spacing();
ImGui::TextUnformatted("preview:");
ImGui::Image(reinterpret_cast<void*>(id),
@ -615,7 +616,7 @@ struct Shader {
nf7::Future<std::shared_ptr<Product>> Create(
const std::shared_ptr<nf7::Context>& ctx) noexcept {
// TODO: preprocessing GLSL source
return Product::Create(ctx, gl::ToEnum(type_), src_);
return Product::Create(ctx, type_, src_);
}
bool Handle(const std::shared_ptr<nf7::Node::Lambda>&,
@ -1012,7 +1013,7 @@ struct VertexArray {
.buffer = base.ResolveOrThrow(attr.buffer).id(),
.index = attr.index,
.size = attr.size,
.type = gl::ToEnum(attr.type),
.type = attr.type,
.normalize = attr.normalize,
.stride = attr.stride,
.offset = attr.offset,
@ -1123,7 +1124,7 @@ struct Framebuffer {
}
attachments.push_back({
.tex = fid,
.slot = gl::ToEnum(attachment.slot),
.slot = attachment.slot,
});
}
return Product::Create(ctx, std::move(attachments));