(WIP) improve GL/Framebuffer to use depth/stencil buffers
This commit is contained in:
parent
e607a587c1
commit
9fc39b986a
@ -247,10 +247,9 @@ try {
|
||||
return {std::current_exception()};
|
||||
}
|
||||
|
||||
nf7::Future<std::vector<nf7::Mutex::Resource<std::shared_ptr<gl::Buffer>>>>
|
||||
Obj_VertexArrayMeta::LockBuffers(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
const ValidationHint& vhint) const noexcept
|
||||
Obj_VertexArrayMeta::LockedBuffersFuture Obj_VertexArrayMeta::LockBuffers(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
const ValidationHint& vhint) const noexcept
|
||||
try {
|
||||
nf7::AggregatePromise apro {ctx};
|
||||
|
||||
@ -308,65 +307,82 @@ nf7::Future<std::shared_ptr<Obj<Obj_FramebufferMeta>>> Obj_FramebufferMeta::Crea
|
||||
const std::shared_ptr<nf7::Context>& ctx) const noexcept {
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_FramebufferMeta>>>::Promise pro {ctx};
|
||||
LockAttachments(ctx).
|
||||
Chain(nf7::Env::kGL, ctx, pro, [ctx, *this](auto& texs) mutable {
|
||||
assert(attachments.size() == texs.size());
|
||||
|
||||
Chain(nf7::Env::kGL, ctx, pro, [ctx, *this](auto& k) mutable {
|
||||
GLuint id;
|
||||
glGenFramebuffers(1, &id);
|
||||
|
||||
const char* err = nullptr;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, id);
|
||||
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";
|
||||
for (size_t i = 0; i < colors.size(); ++i) {
|
||||
if (const auto& tex = k.colors[i]) {
|
||||
glFramebufferTexture(GL_FRAMEBUFFER,
|
||||
static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i),
|
||||
(***tex).id(),
|
||||
0 /* = level */);
|
||||
}
|
||||
}
|
||||
if (k.depth) {
|
||||
glFramebufferTexture(GL_FRAMEBUFFER,
|
||||
GL_DEPTH_ATTACHMENT,
|
||||
(***k.depth).id(),
|
||||
0 /* = level */);
|
||||
}
|
||||
if (k.stencil) {
|
||||
glFramebufferTexture(GL_FRAMEBUFFER,
|
||||
GL_STENCIL_ATTACHMENT,
|
||||
(***k.stencil).id(),
|
||||
0 /* = level */);
|
||||
}
|
||||
|
||||
const auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
assert(0 == glGetError());
|
||||
|
||||
const auto ret = std::make_shared<Obj<Obj_FramebufferMeta>>(ctx, id, *this);
|
||||
if (0 != glGetError()) {
|
||||
throw nf7::Exception {"failed to setup framebuffer"};
|
||||
}
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
throw nf7::Exception {"invalid framebuffer status"};
|
||||
}
|
||||
if (err) {
|
||||
throw nf7::Exception {err};
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
return pro.future();
|
||||
}
|
||||
|
||||
nf7::Future<std::vector<nf7::Mutex::Resource<std::shared_ptr<gl::Texture>>>>
|
||||
Obj_FramebufferMeta::LockAttachments(
|
||||
const std::shared_ptr<nf7::Context>& ctx) const noexcept
|
||||
Obj_FramebufferMeta::LockedAttachmentsFuture Obj_FramebufferMeta::LockAttachments(
|
||||
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;
|
||||
fus.reserve(attachments.size());
|
||||
auto ret = std::make_shared<LockedAttachments>();
|
||||
|
||||
for (const auto& attachment : attachments) {
|
||||
nf7::AggregatePromise apro {ctx};
|
||||
|
||||
const auto lock = [&](nf7::File::Id id) {
|
||||
auto& factory = ctx->env().
|
||||
GetFileOrThrow(attachment.tex).
|
||||
GetFileOrThrow(id).
|
||||
interfaceOrThrow<nf7::gl::TextureFactory>();
|
||||
auto fu = LockAndValidate(ctx, factory, gl::TextureTarget::Tex2D);
|
||||
apro.Add(fu);
|
||||
fus.push_back(fu);
|
||||
return LockAndValidate(ctx, factory, gl::TextureTarget::Tex2D);
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < colors.size(); ++i) {
|
||||
const auto& color = colors[i];
|
||||
if (color && color->tex) {
|
||||
apro.Add(lock(color->tex).ThenIf([i, ret](auto& res) {
|
||||
ret->colors[i] = res;
|
||||
}));
|
||||
}
|
||||
}
|
||||
if (depth && depth->tex) {
|
||||
apro.Add(lock(depth->tex).ThenIf([ret](auto& res) {
|
||||
ret->depth = res;
|
||||
}));
|
||||
}
|
||||
if (stencil && stencil->tex) {
|
||||
apro.Add(lock(stencil->tex).ThenIf([ret](auto& res) {
|
||||
ret->stencil = res;
|
||||
}));
|
||||
}
|
||||
|
||||
nf7::Future<std::vector<nf7::Mutex::Resource<std::shared_ptr<gl::Texture>>>>::Promise pro {ctx};
|
||||
apro.future().Chain(pro, [fus = std::move(fus)](auto&) {
|
||||
std::vector<nf7::Mutex::Resource<std::shared_ptr<gl::Texture>>> ret;
|
||||
ret.reserve(fus.size());
|
||||
for (auto& fu : fus) {
|
||||
ret.emplace_back(fu.value());
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
LockedAttachmentsFuture::Promise pro {ctx};
|
||||
apro.future().Chain(pro, [ret](auto&) { return std::move(*ret); });
|
||||
return pro.future();
|
||||
} catch (nf7::Exception&) {
|
||||
return { std::current_exception() };
|
||||
|
@ -165,7 +165,7 @@ struct Obj_VertexArrayMeta final {
|
||||
|
||||
// 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(
|
||||
LockedBuffersFuture LockBuffers(
|
||||
const std::shared_ptr<nf7::Context>& ctx,
|
||||
const ValidationHint& vhint = {}) const noexcept;
|
||||
|
||||
@ -178,16 +178,24 @@ using VertexArrayFactory = AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<Ver
|
||||
|
||||
struct Obj_FramebufferMeta final {
|
||||
public:
|
||||
using LockedAttachmentsFuture =
|
||||
nf7::Future<std::vector<nf7::Mutex::Resource<std::shared_ptr<gl::Texture>>>>;
|
||||
static constexpr size_t kColorSlotCount = 8;
|
||||
|
||||
struct Param { };
|
||||
|
||||
struct Attachment {
|
||||
nf7::File::Id tex;
|
||||
gl::FramebufferSlot slot;
|
||||
nf7::File::Id tex;
|
||||
};
|
||||
|
||||
struct LockedAttachments {
|
||||
private:
|
||||
using TexRes = nf7::Mutex::Resource<std::shared_ptr<gl::Texture>>;
|
||||
public:
|
||||
std::array<std::optional<TexRes>, kColorSlotCount> colors;
|
||||
std::optional<TexRes> depth;
|
||||
std::optional<TexRes> stencil;
|
||||
};
|
||||
using LockedAttachmentsFuture = nf7::Future<LockedAttachments>;
|
||||
|
||||
static void Delete(GLuint id) noexcept {
|
||||
glDeleteFramebuffers(1, &id);
|
||||
}
|
||||
@ -196,11 +204,12 @@ struct Obj_FramebufferMeta final {
|
||||
nf7::Future<std::shared_ptr<Obj<Obj_FramebufferMeta>>> Create(
|
||||
const std::shared_ptr<nf7::Context>& ctx) const noexcept;
|
||||
|
||||
nf7::Future<std::vector<nf7::Mutex::Resource<std::shared_ptr<gl::Texture>>>>
|
||||
LockAttachments(
|
||||
const std::shared_ptr<nf7::Context>& ctx) const noexcept;
|
||||
LockedAttachmentsFuture LockAttachments(
|
||||
const std::shared_ptr<nf7::Context>& ctx) const noexcept;
|
||||
|
||||
std::vector<Attachment> attachments;
|
||||
std::array<std::optional<Attachment>, kColorSlotCount> colors;
|
||||
std::optional<Attachment> depth;
|
||||
std::optional<Attachment> stencil;
|
||||
};
|
||||
using Framebuffer = Obj<Obj_FramebufferMeta>;
|
||||
using FramebufferFactory = AsyncFactory<nf7::Mutex::Resource<std::shared_ptr<Framebuffer>>>;
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include <yas/serialize.hpp>
|
||||
#include <yas/types/std/array.hpp>
|
||||
#include <yas/types/std/optional.hpp>
|
||||
#include <yas/types/std/string.hpp>
|
||||
#include <yas/types/std/vector.hpp>
|
||||
#include <yas/types/utility/usertype.hpp>
|
||||
@ -1204,11 +1205,10 @@ struct Framebuffer {
|
||||
using Product = nf7::gl::Framebuffer;
|
||||
|
||||
struct Attachment {
|
||||
gl::FramebufferSlot slot;
|
||||
nf7::File::Path path;
|
||||
nf7::File::Path path;
|
||||
|
||||
void serialize(auto& ar) {
|
||||
ar(slot, path);
|
||||
ar(path);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1219,17 +1219,19 @@ struct Framebuffer {
|
||||
Framebuffer& operator=(Framebuffer&&) = default;
|
||||
|
||||
void serialize(auto& ar) {
|
||||
ar(attachments_);
|
||||
ar(colors_);
|
||||
}
|
||||
|
||||
std::string Stringify() noexcept {
|
||||
YAML::Emitter st;
|
||||
st << YAML::BeginMap;
|
||||
st << YAML::Key << "attachments";
|
||||
st << YAML::Key << "colors";
|
||||
st << YAML::Value << YAML::BeginMap;
|
||||
for (const auto& attachment : attachments_) {
|
||||
st << YAML::Key << std::string {magic_enum::enum_name(attachment.slot)};
|
||||
st << YAML::Value << attachment.path.Stringify();
|
||||
for (size_t i = 0; i < Product::Meta::kColorSlotCount; ++i) {
|
||||
if (colors_[i]) {
|
||||
st << YAML::Key << i;
|
||||
st << YAML::Value << colors_[i]->path.Stringify();
|
||||
}
|
||||
}
|
||||
st << YAML::EndMap;
|
||||
st << YAML::EndMap;
|
||||
@ -1237,18 +1239,19 @@ struct Framebuffer {
|
||||
}
|
||||
void Parse(const std::string& v)
|
||||
try {
|
||||
const auto yaml = YAML::Load(v);
|
||||
const auto& yaml_attachments = yaml["attachments"];
|
||||
std::vector<Attachment> attachments;
|
||||
for (auto [slot, name] : magic_enum::enum_entries<gl::FramebufferSlot>()) {
|
||||
if (const auto& yaml_attachment = yaml_attachments[std::string {name}]) {
|
||||
attachments.push_back({
|
||||
.slot = slot,
|
||||
.path = nf7::File::Path::Parse(yaml_attachment.as<std::string>()),
|
||||
const auto yaml = YAML::Load(v);
|
||||
const auto& yaml_colors = yaml["colors"];
|
||||
|
||||
std::array<std::optional<Attachment>, Product::Meta::kColorSlotCount> colors;
|
||||
for (size_t i = 0; i < Product::Meta::kColorSlotCount; ++i) {
|
||||
if (auto& yaml_color = yaml_colors[std::to_string(i)]) {
|
||||
colors[i].emplace(Attachment {
|
||||
.path = nf7::File::Path::Parse(yaml_color.as<std::string>()),
|
||||
});
|
||||
}
|
||||
}
|
||||
attachments_ = std::move(attachments);
|
||||
|
||||
colors_ = std::move(colors);
|
||||
} catch (std::bad_optional_access&) {
|
||||
throw nf7::Exception {std::string {"invalid enum"}};
|
||||
} catch (YAML::Exception& e) {
|
||||
@ -1260,16 +1263,12 @@ struct Framebuffer {
|
||||
auto& base = *p.file;
|
||||
Product::Meta meta;
|
||||
|
||||
for (auto& attachment : attachments_) {
|
||||
nf7::File::Id fid = 0;
|
||||
if (attachment.path.terms().size() > 0) {
|
||||
fid = base.ResolveOrThrow(attachment.path).id();
|
||||
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.attachments.push_back({
|
||||
.tex = fid,
|
||||
.slot = attachment.slot,
|
||||
});
|
||||
}
|
||||
return meta.Create(p.ctx);
|
||||
} catch (nf7::Exception&) {
|
||||
@ -1296,7 +1295,7 @@ struct Framebuffer {
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Attachment> attachments_;
|
||||
std::array<std::optional<Attachment>, Product::Meta::kColorSlotCount> colors_;
|
||||
};
|
||||
template <>
|
||||
struct ObjBase<Framebuffer>::TypeInfo final {
|
||||
|
Loading…
x
Reference in New Issue
Block a user