diff --git a/include/nbl/asset/material_compiler3/CTrueIR.h b/include/nbl/asset/material_compiler3/CTrueIR.h index d9a65e8719..ce71a419f7 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 { return 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 @@ -876,6 +878,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);} @@ -951,6 +955,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);} @@ -990,12 +996,16 @@ 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);} inline COrenNayar() = default; + NBL_API2 void printDot(std::ostringstream& sstr, const core::string& selfID) const override final; + protected: COPY_DEFAULT_IMPL }; @@ -1019,6 +1029,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);} @@ -1035,6 +1047,8 @@ class CTrueIR : public CNodePool // TODO: turn into an asset! inline CCookTorrance() = default; + NBL_API2 void printDot(std::ostringstream& sstr, const core::string& selfID) const override final; + // inline bool isEtaReciprocal() const {return ndfParams.params[2].padding[0];} inline void setEtaReciprocal(const bool value) {ndfParams.params[2].padding[0] = value;} @@ -1488,7 +1502,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 cfcf1f3a1b..c7238d5033 100644 --- a/src/nbl/asset/material_compiler3/CTrueIR.cpp +++ b/src/nbl/asset/material_compiler3/CTrueIR.cpp @@ -296,7 +296,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 @@ -310,6 +365,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) @@ -325,5 +385,31 @@ 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); +} + template class CTrueIR::CSpectralVariable; } \ No newline at end of file