support depth/stencil buffer
This commit is contained in:
parent
9fc39b986a
commit
fa1a29c325
@ -2,6 +2,7 @@
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <GL/glew.h>
|
||||
@ -85,6 +86,102 @@ inline uint8_t GetCompCount(ColorComp c) noexcept {
|
||||
}
|
||||
|
||||
|
||||
enum class InternalFormat : uint8_t {
|
||||
R8 = 0x01,
|
||||
RG8 = 0x02,
|
||||
RGB8 = 0x03,
|
||||
RGBA8 = 0x04,
|
||||
|
||||
RF32 = 0x11,
|
||||
RGF32 = 0x12,
|
||||
RGBF32 = 0x13,
|
||||
RGBAF32 = 0x14,
|
||||
|
||||
Depth16 = 0x21,
|
||||
Depth24 = 0x31,
|
||||
DepthF32 = 0x41,
|
||||
|
||||
Depth24_Stencil8 = 0x22,
|
||||
DepthF32_Stencil8 = 0x32,
|
||||
};
|
||||
template <>
|
||||
struct EnumMeta<InternalFormat> {
|
||||
static inline const std::unordered_map<InternalFormat, GLenum> glmap = {
|
||||
{InternalFormat::R8, GL_R8},
|
||||
{InternalFormat::RG8, GL_RG8},
|
||||
{InternalFormat::RGB8, GL_RGB8},
|
||||
{InternalFormat::RGBA8, GL_RGBA8},
|
||||
{InternalFormat::RF32, GL_R32F},
|
||||
{InternalFormat::RGF32, GL_RG32F},
|
||||
{InternalFormat::RGBF32, GL_RGB32F},
|
||||
{InternalFormat::RGBAF32, GL_RGBA32F},
|
||||
{InternalFormat::Depth16, GL_DEPTH_COMPONENT16},
|
||||
{InternalFormat::Depth24, GL_DEPTH_COMPONENT24},
|
||||
{InternalFormat::DepthF32, GL_DEPTH_COMPONENT32F},
|
||||
{InternalFormat::Depth24_Stencil8, GL_DEPTH24_STENCIL8},
|
||||
{InternalFormat::DepthF32_Stencil8, GL_DEPTH32F_STENCIL8},
|
||||
};
|
||||
};
|
||||
inline uint8_t GetByteSize(InternalFormat fmt) noexcept {
|
||||
switch (fmt) {
|
||||
case InternalFormat::R8: return 1;
|
||||
case InternalFormat::RG8: return 2;
|
||||
case InternalFormat::RGB8: return 3;
|
||||
case InternalFormat::RGBA8: return 4;
|
||||
case InternalFormat::RF32: return 4;
|
||||
case InternalFormat::RGF32: return 8;
|
||||
case InternalFormat::RGBF32: return 12;
|
||||
case InternalFormat::RGBAF32: return 16;
|
||||
case InternalFormat::Depth16: return 2;
|
||||
case InternalFormat::Depth24: return 3;
|
||||
case InternalFormat::DepthF32: return 4;
|
||||
case InternalFormat::Depth24_Stencil8: return 4;
|
||||
case InternalFormat::DepthF32_Stencil8: return 5;
|
||||
}
|
||||
std::abort();
|
||||
}
|
||||
inline ColorComp GetColorComp(InternalFormat fmt) {
|
||||
switch (fmt) {
|
||||
case InternalFormat::R8: return ColorComp::R;
|
||||
case InternalFormat::RG8: return ColorComp::RG;
|
||||
case InternalFormat::RGB8: return ColorComp::RGB;
|
||||
case InternalFormat::RGBA8: return ColorComp::RGBA;
|
||||
case InternalFormat::RF32: return ColorComp::R;
|
||||
case InternalFormat::RGF32: return ColorComp::RG;
|
||||
case InternalFormat::RGBF32: return ColorComp::RGB;
|
||||
case InternalFormat::RGBAF32: return ColorComp::RGBA;
|
||||
default: throw nf7::Exception {"does not have color component"};
|
||||
}
|
||||
}
|
||||
inline NumericType GetNumericType(InternalFormat fmt) {
|
||||
switch (fmt) {
|
||||
case InternalFormat::R8:
|
||||
case InternalFormat::RG8:
|
||||
case InternalFormat::RGB8:
|
||||
case InternalFormat::RGBA8:
|
||||
return NumericType::U8;
|
||||
case InternalFormat::RF32:
|
||||
case InternalFormat::RGF32:
|
||||
case InternalFormat::RGBF32:
|
||||
case InternalFormat::RGBAF32:
|
||||
return NumericType::F32;
|
||||
default:
|
||||
throw nf7::Exception {"does not have color component"};
|
||||
}
|
||||
}
|
||||
inline bool IsColor(InternalFormat fmt) noexcept {
|
||||
return (magic_enum::enum_integer(fmt) & 0xF0) <= 1;
|
||||
}
|
||||
inline bool HasDepth(InternalFormat fmt) noexcept {
|
||||
return !IsColor(fmt);
|
||||
}
|
||||
inline bool HasStencil(InternalFormat fmt) noexcept {
|
||||
return
|
||||
fmt == InternalFormat::Depth24_Stencil8 ||
|
||||
fmt == InternalFormat::DepthF32_Stencil8;
|
||||
}
|
||||
|
||||
|
||||
enum class BufferTarget {
|
||||
Array,
|
||||
ElementArray,
|
||||
@ -138,31 +235,6 @@ struct EnumMeta<TextureTarget> {
|
||||
inline uint8_t GetDimension(TextureTarget t) noexcept {
|
||||
return magic_enum::enum_integer(t) & 0xF;
|
||||
}
|
||||
inline GLenum ToInternalFormat(NumericType n, ColorComp c) {
|
||||
GLenum ret = 0;
|
||||
switch (n) {
|
||||
case NumericType::U8:
|
||||
ret =
|
||||
c == ColorComp::R? GL_R8:
|
||||
c == ColorComp::RG? GL_RG8:
|
||||
c == ColorComp::RGB? GL_RGB8:
|
||||
c == ColorComp::RGBA? GL_RGBA8: 0;
|
||||
break;
|
||||
case NumericType::F32:
|
||||
ret =
|
||||
c == ColorComp::R? GL_R32F:
|
||||
c == ColorComp::RG? GL_RG32F:
|
||||
c == ColorComp::RGB? GL_RGB32F:
|
||||
c == ColorComp::RGBA? GL_RGBA32F: 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (ret == 0) {
|
||||
throw nf7::Exception {"invalid numtype and comp pair"};
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
enum class ShaderType {
|
||||
|
@ -81,16 +81,20 @@ nf7::Future<std::shared_ptr<Obj<Obj_TextureMeta>>> Obj_TextureMeta::Create(
|
||||
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);
|
||||
|
||||
const auto ifmt = static_cast<GLint>(gl::ToEnum(format));
|
||||
const GLenum fmt = gl::IsColor(format)? GL_RED: GL_DEPTH_COMPONENT;
|
||||
switch (gl::GetDimension(target)) {
|
||||
case 2:
|
||||
glTexImage2D(t, 0, format, size[0], size[1], 0,
|
||||
GL_RED, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexImage2D(t, 0, ifmt, size[0], size[1], 0,
|
||||
fmt, GL_UNSIGNED_BYTE, nullptr);
|
||||
break;
|
||||
default:
|
||||
assert(false && "unknown texture target");
|
||||
break;
|
||||
}
|
||||
glBindTexture(t, 0);
|
||||
assert(0 == glGetError());
|
||||
|
||||
pro.Return(std::make_shared<Obj<Obj_TextureMeta>>(ctx, id, *this));
|
||||
});
|
||||
|
@ -83,7 +83,7 @@ struct Obj_TextureMeta final {
|
||||
const std::shared_ptr<nf7::Context>& ctx) const noexcept;
|
||||
|
||||
gl::TextureTarget target;
|
||||
GLint format;
|
||||
gl::InternalFormat format;
|
||||
std::array<GLsizei, 3> size;
|
||||
};
|
||||
using Texture = Obj<Obj_TextureMeta>;
|
||||
|
103
file/gl_obj.cc
103
file/gl_obj.cc
@ -397,7 +397,7 @@ struct Texture {
|
||||
Texture& operator=(Texture&&) = default;
|
||||
|
||||
void serialize(auto& ar) {
|
||||
ar(target_, numtype_, comp_, size_);
|
||||
ar(target_, ifmt_, size_);
|
||||
}
|
||||
|
||||
std::string Stringify() noexcept {
|
||||
@ -405,10 +405,8 @@ struct Texture {
|
||||
st << YAML::BeginMap;
|
||||
st << YAML::Key << "target";
|
||||
st << YAML::Value << std::string {magic_enum::enum_name(target_)};
|
||||
st << YAML::Key << "numtype";
|
||||
st << YAML::Value << std::string {magic_enum::enum_name(numtype_)};
|
||||
st << YAML::Key << "comp";
|
||||
st << YAML::Value << std::string {magic_enum::enum_name(comp_)};
|
||||
st << YAML::Key << "ifmt";
|
||||
st << YAML::Value << std::string {magic_enum::enum_name(ifmt_)};
|
||||
st << YAML::Key << "size";
|
||||
st << YAML::Value << YAML::Flow;
|
||||
st << YAML::BeginSeq;
|
||||
@ -426,10 +424,8 @@ struct Texture {
|
||||
|
||||
const auto target = magic_enum::
|
||||
enum_cast<gl::TextureTarget>(yaml["target"].as<std::string>()).value();
|
||||
const auto numtype = magic_enum::
|
||||
enum_cast<gl::NumericType>(yaml["numtype"].as<std::string>()).value();
|
||||
const auto comp = magic_enum::
|
||||
enum_cast<gl::ColorComp>(yaml["comp"].as<std::string>()).value();
|
||||
const auto ifmt = magic_enum::
|
||||
enum_cast<gl::InternalFormat>(yaml["ifmt"].as<std::string>()).value();
|
||||
const auto size = yaml["size"].as<std::vector<uint32_t>>();
|
||||
|
||||
const auto dim = gl::GetDimension(target);
|
||||
@ -439,8 +435,7 @@ struct Texture {
|
||||
}
|
||||
|
||||
target_ = target;
|
||||
numtype_ = numtype;
|
||||
comp_ = comp;
|
||||
ifmt_ = ifmt;
|
||||
|
||||
std::copy(size.begin(), size.begin()+dim, size_.begin());
|
||||
std::fill(size_.begin()+dim, size_.end(), 1);
|
||||
@ -454,7 +449,7 @@ struct Texture {
|
||||
try {
|
||||
Product::Meta meta {
|
||||
.target = target_,
|
||||
.format = static_cast<GLint>(gl::ToInternalFormat(numtype_, comp_)),
|
||||
.format = ifmt_,
|
||||
.size = {},
|
||||
};
|
||||
std::transform(size_.begin(), size_.end(), meta.size.begin(),
|
||||
@ -489,13 +484,13 @@ struct Texture {
|
||||
}
|
||||
|
||||
const auto texel = std::accumulate(size.begin(), size.end(), 1, std::multiplies<uint32_t> {});
|
||||
const auto vecsz = texel*gl::GetCompCount(comp_)*gl::GetByteSize(numtype_);
|
||||
const auto vecsz = texel*gl::GetByteSize(ifmt_);
|
||||
if (vec->size() < static_cast<size_t>(vecsz)) {
|
||||
throw nf7::Exception {"vector is too small"};
|
||||
}
|
||||
|
||||
const auto fmt = gl::ToEnum(comp_);
|
||||
const auto type = gl::ToEnum(numtype_);
|
||||
const auto fmt = gl::ToEnum(gl::GetColorComp(ifmt_));
|
||||
const auto type = gl::ToEnum(gl::GetNumericType(ifmt_));
|
||||
p.la->env().ExecGL(p.la, [=, &tex]() {
|
||||
const auto t = gl::ToEnum(tex.meta().target);
|
||||
glBindTexture(t, tex.id());
|
||||
@ -517,9 +512,10 @@ struct Texture {
|
||||
assert(0 == glGetError());
|
||||
});
|
||||
return true;
|
||||
|
||||
} else if (p.in.name == "download") {
|
||||
auto numtype = numtype_;
|
||||
auto comp = comp_;
|
||||
auto numtype = gl::GetNumericType(ifmt_);
|
||||
auto comp = gl::GetColorComp(ifmt_);
|
||||
try {
|
||||
try {
|
||||
numtype = magic_enum::enum_cast<
|
||||
@ -543,7 +539,7 @@ struct Texture {
|
||||
const auto& tex = **p.obj;
|
||||
const auto size = tex.meta().size;
|
||||
const auto texel = std::accumulate(size.begin(), size.end(), 1, std::multiplies<uint32_t> {});
|
||||
const auto bsize = static_cast<size_t>(texel)*GetCompCount(comp)*GetByteSize(numtype);
|
||||
const auto bsize = texel*gl::GetCompCount(comp)*gl::GetByteSize(numtype);
|
||||
glBufferData(GL_PIXEL_PACK_BUFFER, static_cast<GLsizeiptr>(bsize), nullptr, GL_STREAM_READ);
|
||||
|
||||
const auto t = gl::ToEnum(tex.meta().target);
|
||||
@ -559,7 +555,7 @@ struct Texture {
|
||||
auto buf = std::make_shared<std::vector<uint8_t>>(bsize);
|
||||
|
||||
const auto ptr = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
|
||||
std::memcpy(buf->data(), ptr, bsize);
|
||||
std::memcpy(buf->data(), ptr, static_cast<size_t>(bsize));
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
@ -585,17 +581,13 @@ struct Texture {
|
||||
|
||||
void UpdateTooltip(const std::shared_ptr<Product>& prod) noexcept {
|
||||
const auto t = magic_enum::enum_name(target_);
|
||||
ImGui::Text("target : %.*s", static_cast<int>(t.size()), t.data());
|
||||
ImGui::Text("target: %.*s", static_cast<int>(t.size()), t.data());
|
||||
|
||||
const auto f = magic_enum::enum_name(numtype_);
|
||||
ImGui::Text("numtype: %.*s", static_cast<int>(f.size()), f.data());
|
||||
const auto c = magic_enum::enum_name(ifmt_);
|
||||
ImGui::Text("ifmt : %.*s",
|
||||
static_cast<int>(c.size()), c.data());
|
||||
|
||||
const auto c = magic_enum::enum_name(comp_);
|
||||
ImGui::Text("comp : %.*s (%" PRIu8 " values)",
|
||||
static_cast<int>(c.size()), c.data(),
|
||||
magic_enum::enum_integer(comp_));
|
||||
|
||||
ImGui::Text("size : %" PRIu32 " x %" PRIu32 " x %" PRIu32, size_[0], size_[1], size_[2]);
|
||||
ImGui::Text("size : %" PRIu32 " x %" PRIu32 " x %" PRIu32, size_[0], size_[1], size_[2]);
|
||||
|
||||
ImGui::Spacing();
|
||||
if (prod) {
|
||||
@ -613,9 +605,8 @@ struct Texture {
|
||||
}
|
||||
|
||||
private:
|
||||
gl::TextureTarget target_ = gl::TextureTarget::Rect;
|
||||
gl::NumericType numtype_ = gl::NumericType::U8;
|
||||
gl::ColorComp comp_ = gl::ColorComp::RGBA;
|
||||
gl::TextureTarget target_ = gl::TextureTarget::Rect;
|
||||
gl::InternalFormat ifmt_ = gl::InternalFormat::RGBA8;
|
||||
|
||||
std::array<uint32_t, 3> size_ = {256, 256, 1};
|
||||
};
|
||||
@ -1219,7 +1210,7 @@ struct Framebuffer {
|
||||
Framebuffer& operator=(Framebuffer&&) = default;
|
||||
|
||||
void serialize(auto& ar) {
|
||||
ar(colors_);
|
||||
ar(colors_, depth_, stencil_);
|
||||
}
|
||||
|
||||
std::string Stringify() noexcept {
|
||||
@ -1234,6 +1225,14 @@ struct Framebuffer {
|
||||
}
|
||||
}
|
||||
st << YAML::EndMap;
|
||||
if (depth_) {
|
||||
st << YAML::Key << "depth";
|
||||
st << YAML::Value << depth_->path.Stringify();
|
||||
}
|
||||
if (stencil_) {
|
||||
st << YAML::Key << "stencil";
|
||||
st << YAML::Value << stencil_->path.Stringify();
|
||||
}
|
||||
st << YAML::EndMap;
|
||||
return std::string {st.c_str(), st.size()};
|
||||
}
|
||||
@ -1242,16 +1241,26 @@ struct Framebuffer {
|
||||
const auto yaml = YAML::Load(v);
|
||||
const auto& yaml_colors = yaml["colors"];
|
||||
|
||||
std::array<std::optional<Attachment>, Product::Meta::kColorSlotCount> colors;
|
||||
Framebuffer ret;
|
||||
for (size_t i = 0; i < Product::Meta::kColorSlotCount; ++i) {
|
||||
if (auto& yaml_color = yaml_colors[std::to_string(i)]) {
|
||||
colors[i].emplace(Attachment {
|
||||
ret.colors_[i].emplace(Attachment {
|
||||
.path = nf7::File::Path::Parse(yaml_color.as<std::string>()),
|
||||
});
|
||||
}
|
||||
}
|
||||
if (const auto& yaml_depth = yaml["depth"]) {
|
||||
ret.depth_.emplace(Attachment {
|
||||
.path = nf7::File::Path::Parse(yaml_depth.as<std::string>()),
|
||||
});
|
||||
}
|
||||
if (const auto& yaml_stencil = yaml["stencil"]) {
|
||||
ret.stencil_.emplace(Attachment {
|
||||
.path = nf7::File::Path::Parse(yaml_stencil.as<std::string>()),
|
||||
});
|
||||
}
|
||||
|
||||
colors_ = std::move(colors);
|
||||
*this = std::move(ret);
|
||||
} catch (std::bad_optional_access&) {
|
||||
throw nf7::Exception {std::string {"invalid enum"}};
|
||||
} catch (YAML::Exception& e) {
|
||||
@ -1263,13 +1272,29 @@ struct Framebuffer {
|
||||
auto& base = *p.file;
|
||||
Product::Meta meta;
|
||||
|
||||
const auto resolveAndWatch = [&](const auto& path) {
|
||||
const auto fid = base.ResolveOrThrow(path).id();
|
||||
p.watch->Watch(fid);
|
||||
return fid;
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < Product::Meta::kColorSlotCount; ++i) {
|
||||
if (const auto& color = colors_[i]) {
|
||||
const auto fid = base.ResolveOrThrow(color->path).id();
|
||||
meta.colors[i].emplace(Product::Meta::Attachment { .tex = fid, });
|
||||
p.watch->Watch(fid);
|
||||
meta.colors[i].emplace(Product::Meta::Attachment {
|
||||
.tex = resolveAndWatch(color->path),
|
||||
});
|
||||
}
|
||||
}
|
||||
if (depth_) {
|
||||
meta.depth.emplace(Product::Meta::Attachment {
|
||||
.tex = resolveAndWatch(depth_->path),
|
||||
});
|
||||
}
|
||||
if (stencil_) {
|
||||
meta.stencil.emplace(Product::Meta::Attachment {
|
||||
.tex = resolveAndWatch(stencil_->path),
|
||||
});
|
||||
}
|
||||
return meta.Create(p.ctx);
|
||||
} catch (nf7::Exception&) {
|
||||
return {std::current_exception()};
|
||||
@ -1296,6 +1321,8 @@ struct Framebuffer {
|
||||
|
||||
private:
|
||||
std::array<std::optional<Attachment>, Product::Meta::kColorSlotCount> colors_;
|
||||
std::optional<Attachment> depth_;
|
||||
std::optional<Attachment> stencil_;
|
||||
};
|
||||
template <>
|
||||
struct ObjBase<Framebuffer>::TypeInfo final {
|
||||
|
Loading…
x
Reference in New Issue
Block a user