From c942470fc988194b90084dba248b73575d08972c Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 15 May 2026 16:12:41 +0700 Subject: [PATCH 1/2] INode getCapabilities method for getting metadata capabilities, use in rewriteSingleLayer to set metadata --- .../nbl/asset/material_compiler3/CTrueIR.h | 12 ++- src/nbl/asset/material_compiler3/CTrueIR.cpp | 76 +++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/include/nbl/asset/material_compiler3/CTrueIR.h b/include/nbl/asset/material_compiler3/CTrueIR.h index afc3a6604e..9a08f031cd 100644 --- a/include/nbl/asset/material_compiler3/CTrueIR.h +++ b/include/nbl/asset/material_compiler3/CTrueIR.h @@ -219,6 +219,8 @@ class CTrueIR : public CNodePool // TODO: turn into an asset! }; virtual EFinalType getFinalType() const = 0; + virtual uint16_t getCapabilities() const = 0; + const auto& getHash() const {return hash;} // only call once the nodes underneath are linked up (because it doesn't call recursively), returning empty hash means error/invalid node @@ -862,6 +864,8 @@ class CTrueIR : public CNodePool // TODO: turn into an asset! public: inline EFinalType getFinalType() const override {return EFinalType::CEmitter;} + uint16_t getCapabilities() const override final; + inline uint8_t getChildCount() const override final { return 0; } inline const std::string_view getTypeName() const override {return TYPE_NAME_STR(CEmitter);} @@ -937,6 +941,8 @@ class CTrueIR : public CNodePool // TODO: turn into an asset! public: inline EFinalType getFinalType() const override {return EFinalType::CDeltaTransmission;} + uint16_t getCapabilities() const override final; + inline uint8_t getChildCount() const override final { return 0; } inline const std::string_view getTypeName() const override {return TYPE_NAME_STR(CDeltaTransmission);} @@ -971,6 +977,8 @@ class CTrueIR : public CNodePool // TODO: turn into an asset! inline EFinalType getFinalType() const override {return EFinalType::COrenNayar;} + uint16_t getCapabilities() const override final; + inline uint8_t getChildCount() const override final { return 0; } inline const std::string_view getTypeName() const override {return TYPE_NAME_STR(COrenNayar);} @@ -998,6 +1006,8 @@ class CTrueIR : public CNodePool // TODO: turn into an asset! public: inline EFinalType getFinalType() const override {return EFinalType::CCookTorrance;} + uint16_t getCapabilities() const override final; + inline uint8_t getChildCount() const override final { return 1; } inline const std::string_view getTypeName() const override {return TYPE_NAME_STR(CCookTorrance);} @@ -1427,7 +1437,7 @@ class CTrueIR : public CNodePool // TODO: turn into an asset! const CTrueIR* const src; CTrueIR* const dst; - const SMaterial::SMetadata* pMetadata; + SMaterial::SMetadata* pMetadata; }; struct SRewriteSession final { diff --git a/src/nbl/asset/material_compiler3/CTrueIR.cpp b/src/nbl/asset/material_compiler3/CTrueIR.cpp index d6f05bd104..b424af5e71 100644 --- a/src/nbl/asset/material_compiler3/CTrueIR.cpp +++ b/src/nbl/asset/material_compiler3/CTrueIR.cpp @@ -292,7 +292,62 @@ bool CTrueIR::SRewriteSession::rewriteSingleLayer(typed_pointer_typegetObjectPool(); + const auto& srcPool = args.src->getObjectPool(); + SMaterial::SMetadata metadata = {}; + + core::vector> stack; + stack.reserve(32); + stack.push_back(oriented); + // use a hashmap to not explore whole DAG + core::unordered_map, typed_pointer_type> substitutions; + while (!stack.empty()) + { + const auto entry = stack.back(); + const auto* const node = srcPool.deref(entry); + if (!node) + return false; + const auto childCount = node->getChildCount(); + if (auto& copyH = substitutions[entry]; !copyH) + { + for (uint8_t c = 0; c < childCount; c++) + { + const auto childH = node->getChildHandle(c); + if (auto child = srcPool.deref(childH); !child) + continue; + stack.push_back(childH); + } + + copyH = node->copy(args.dst); + if (!copyH) + return false; + } + else + { + auto* const copy = dstPool.deref(copyH); + for (uint8_t c = 0; c < childCount; c++) + { + const auto childH = node->getChildHandle(c); + if (!childH) + continue; + auto found = substitutions.find(childH); + assert(found != substitutions.end()); + copy->setChild(dstPool, c, found->second); + } + stack.pop_back(); + + if (node->getFinalType() == INode::EFinalType::CSpectralVariable) + { + const auto* factor = dynamic_cast(node); + metadata.usedUVSlots.set(factor->uvSlot(), true); + } + metadata.capabilities |= core::bitflag(node->getCapabilities()); + } + } + // TODO: combine layer meta with `retval.metadata` + args.pMetadata->usedUVSlots = metadata.usedUVSlots; + args.pMetadata->capabilities |= metadata.capabilities; // TODO: deduplicate, collect metadata and insert into current IR @@ -306,6 +361,11 @@ void CTrueIR::ISpectralVariableFactor::printDot(std::ostringstream& sstr, const printDotParameterSet(*pWonky(), getKnotCount(), sstr, selfID, {}); } +uint16_t CTrueIR::CEmitter::getCapabilities() const +{ + return static_cast(SMaterial::SMetadata::ECapabilityBits::NonSpatiallyVaryingEmissive | SMaterial::SMetadata::ECapabilityBits::NotBlackhole); +} + void CTrueIR::CEmitter::printDot(std::ostringstream& sstr, const core::string& selfID) const { if (profile) @@ -321,11 +381,27 @@ void CTrueIR::CEmitter::printDot(std::ostringstream& sstr, const core::string& s } } +uint16_t CTrueIR::CDeltaTransmission::getCapabilities() const +{ + return static_cast(SMaterial::SMetadata::ECapabilityBits::DeltaTransmissive | SMaterial::SMetadata::ECapabilityBits::NotBlackhole); +} + +uint16_t CTrueIR::COrenNayar::getCapabilities() const +{ + return static_cast(SMaterial::SMetadata::ECapabilityBits::OrenNayar | SMaterial::SMetadata::ECapabilityBits::NonDelta | SMaterial::SMetadata::ECapabilityBits::NotBlackhole); +} + void CTrueIR::COrenNayar::printDot(std::ostringstream& sstr, const core::string& selfID) const { ndfParams.printDot(sstr, selfID); } +uint16_t CTrueIR::CCookTorrance::getCapabilities() const +{ + // TODO: could be either beckmann or ggx, also anisotropic? maybe get from ndf params? + return static_cast(SMaterial::SMetadata::ECapabilityBits::GGX | SMaterial::SMetadata::ECapabilityBits::NonDelta | SMaterial::SMetadata::ECapabilityBits::NotBlackhole); +} + void CTrueIR::CCookTorrance::printDot(std::ostringstream& sstr, const core::string& selfID) const { ndfParams.printDot(sstr, selfID); From fa59ef96afbcfe7de7c6d7394e9ab4408161ab9c Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 18 May 2026 16:17:28 +0700 Subject: [PATCH 2/2] getCapabilities should not be abstract method --- include/nbl/asset/material_compiler3/CTrueIR.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/nbl/asset/material_compiler3/CTrueIR.h b/include/nbl/asset/material_compiler3/CTrueIR.h index 9a08f031cd..dff476af9d 100644 --- a/include/nbl/asset/material_compiler3/CTrueIR.h +++ b/include/nbl/asset/material_compiler3/CTrueIR.h @@ -219,7 +219,7 @@ class CTrueIR : public CNodePool // TODO: turn into an asset! }; virtual EFinalType getFinalType() const = 0; - virtual uint16_t getCapabilities() const = 0; + virtual uint16_t getCapabilities() const { return 0; }; const auto& getHash() const {return hash;}