improve GL/Texture to allocate image on initialization

This commit is contained in:
falsycat 2022-10-19 12:25:07 +09:00
parent 96fd71df07
commit 38fc3b680a
3 changed files with 59 additions and 34 deletions

View File

@ -25,12 +25,22 @@ 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) noexcept {
const std::shared_ptr<nf7::Context>& ctx,
GLenum type, GLint fmt, GLsizei w, GLsizei h, GLsizei d) noexcept {
nf7::Future<std::shared_ptr<Obj<Obj_TextureMeta>>>::Promise pro {ctx};
ctx->env().ExecGL(ctx, [ctx, type, pro]() mutable {
ctx->env().ExecGL(ctx, [ctx, type, fmt, w, h, d, pro]() mutable {
GLuint id;
glGenTextures(1, &id);
pro.Return(std::make_shared<Obj<Obj_TextureMeta>>(ctx, id, type));
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);
glTexImage2D(type, 0, fmt, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
glBindTexture(type, 0);
pro.Return(std::make_shared<Obj<Obj_TextureMeta>>(ctx, id, type, fmt, w, h, d));
});
return pro.future();
}

View File

@ -75,21 +75,23 @@ 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, GLenum type) noexcept;
const std::shared_ptr<nf7::Context>& ctx,
GLenum type, GLint fmt, GLsizei w, GLsizei h, GLsizei d) noexcept;
static void Delete(GLuint id) noexcept {
glDeleteTextures(1, &id);
}
Obj_TextureMeta() = delete;
Obj_TextureMeta(GLenum t) noexcept : type(t) {
Obj_TextureMeta(GLenum t, GLint f, GLsizei w, GLsizei h, GLsizei d) noexcept :
type(t), format(f), w(w), h(h), d(d) {
}
const GLenum type;
GLint format = 0;
uint32_t w = 0, h = 0, d = 0;
const GLenum type;
const GLint format;
const GLsizei w, h, d;
};
using Texture = Obj<Obj_TextureMeta>;
using TextureFactory = AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<Texture>>>;

View File

@ -392,7 +392,7 @@ struct Texture {
Texture& operator=(Texture&&) = default;
void serialize(auto& ar) {
ar(type_, format_, comp_);
ar(type_, format_, comp_, w_, h_, d_);
}
std::string Stringify() noexcept {
@ -404,6 +404,8 @@ struct Texture {
st << YAML::Value << std::string {magic_enum::enum_name(format_)};
st << YAML::Key << "comp";
st << YAML::Value << std::string {magic_enum::enum_name(comp_)};
st << YAML::Key << "size";
st << YAML::Value << YAML::Flow << std::vector<uint32_t> {w_, h_, d_};
st << YAML::EndMap;
return std::string {st.c_str(), st.size()};
}
@ -412,16 +414,27 @@ struct Texture {
try {
const auto yaml = YAML::Load(v);
const auto new_type = magic_enum::
const auto type = magic_enum::
enum_cast<Type>(yaml["type"].as<std::string>()).value();
const auto new_format = magic_enum::
const auto format = magic_enum::
enum_cast<Format>(yaml["format"].as<std::string>()).value();
const auto new_comp = magic_enum::
const auto comp = magic_enum::
enum_cast<Comp>(yaml["comp"].as<std::string>()).value();
const auto size = yaml["size"].as<std::vector<uint32_t>>();
type_ = new_type;
format_ = new_format;
comp_ = new_comp;
const auto dim = magic_enum::enum_integer(type) >> 4;
const auto itr = std::find(size.begin(), size.end(), 0);
if (dim > std::distance(size.begin(), itr)) {
throw nf7::Exception {"invalid size specification"};
}
type_ = type;
format_ = format;
comp_ = comp;
w_ = size.size() >= 1? size[0]: 0;
h_ = size.size() >= 2? size[1]: 0;
d_ = size.size() >= 3? size[2]: 0;
} catch (std::bad_optional_access&) {
throw nf7::Exception {"unknown enum"};
} catch (YAML::Exception& e) {
@ -429,7 +442,11 @@ struct Texture {
}
nf7::Future<std::shared_ptr<Product>> Create(const std::shared_ptr<nf7::Context>& ctx) noexcept {
return Product::Create(ctx, FromType(type_));
return Product::Create(
ctx, FromType(type_), ToInternalFormat(format_, comp_),
static_cast<GLsizei>(w_),
static_cast<GLsizei>(h_),
static_cast<GLsizei>(d_));
}
bool Handle(const std::shared_ptr<nf7::Node::Lambda>& handler,
@ -439,9 +456,7 @@ struct Texture {
const auto& v = in.value;
const auto vec = v.tuple("vec").vector();
auto& tex = **res;
auto& m = tex.meta();
uint32_t w = 0, h = 0, d = 0;
switch (type_) {
@ -452,8 +467,6 @@ struct Texture {
if (w == 0 || h == 0) return false;
break;
}
m.w = w, m.h = h, m.d = d;
m.format = ToInternalFormat(format_, comp_);
const auto vecsz =
w*h* // number of texels
@ -463,27 +476,25 @@ struct Texture {
throw nf7::Exception {"vector is too small"};
}
const auto type = ToCompType(format_);
const auto fmt = ToFormat(comp_);
handler->env().ExecGL(handler, [handler, res, &tex, &m, type, fmt, vec]() {
glBindTexture(m.type, tex.id());
switch (m.type) {
const auto type = ToCompType(format_);
handler->env().ExecGL(handler, [handler, res, &tex, w, h, d, fmt, type, vec]() {
const auto target = tex.meta().type;
glBindTexture(target, tex.id());
switch (target) {
case GL_TEXTURE_2D:
case GL_TEXTURE_RECTANGLE:
glTexImage2D(m.type, 0, m.format,
static_cast<GLsizei>(m.w),
static_cast<GLsizei>(m.h),
0, fmt, type, vec->data());
glTexSubImage2D(target, 0,
0, 0,
static_cast<GLsizei>(w), static_cast<GLsizei>(h),
fmt, type, vec->data());
break;
default:
assert(false);
break;
}
glTexParameteri(m.type, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(m.type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(m.type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(m.type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(m.type, 0);
glBindTexture(target, 0);
assert(0 == glGetError());
});
return true;
} else {
@ -524,6 +535,8 @@ struct Texture {
Format format_ = Format::U8;
Comp comp_ = Comp::RGBA;
uint32_t w_, h_, d_;
static GLenum FromType(Type t) {
return
t == Type::Tex2D? GL_TEXTURE_2D: