summaryrefslogtreecommitdiff
path: root/source/slang/slang-ir-resolve-texture-format.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-09-26 09:44:08 -0700
committerGitHub <noreply@github.com>2024-09-26 09:44:08 -0700
commit5a0224a0773f6d7f5eae8515424af5fa8faa9c14 (patch)
treeac14b54ad253d4ac5413a3c86254929f332b9e1a /source/slang/slang-ir-resolve-texture-format.cpp
parent7398e1e09312ed4e19195e060de9a2c9a073fcc1 (diff)
Move texture format inference to frontend and add reflection api for it. (#5155)
Diffstat (limited to 'source/slang/slang-ir-resolve-texture-format.cpp')
-rw-r--r--source/slang/slang-ir-resolve-texture-format.cpp142
1 files changed, 142 insertions, 0 deletions
diff --git a/source/slang/slang-ir-resolve-texture-format.cpp b/source/slang/slang-ir-resolve-texture-format.cpp
new file mode 100644
index 000000000..7cd81fc2d
--- /dev/null
+++ b/source/slang/slang-ir-resolve-texture-format.cpp
@@ -0,0 +1,142 @@
+#include "slang-ir-resolve-texture-format.h"
+#include "slang-ir-insts.h"
+#include "slang-ir-clone.h"
+
+namespace Slang
+{
+ static IRType* replaceImageElementType(IRInst* originalType, IRInst* newElementType)
+ {
+ switch (originalType->getOp())
+ {
+ case kIROp_ArrayType:
+ case kIROp_UnsizedArrayType:
+ case kIROp_PtrType:
+ case kIROp_OutType:
+ case kIROp_RefType:
+ case kIROp_ConstRefType:
+ case kIROp_InOutType:
+ {
+ auto newInnerType = replaceImageElementType(originalType->getOperand(0), newElementType);
+ if (newInnerType != originalType->getOperand(0))
+ {
+ IRBuilder builder(originalType);
+ builder.setInsertBefore(originalType);
+ IRCloneEnv cloneEnv;
+ cloneEnv.mapOldValToNew.add(originalType->getOperand(0), newInnerType);
+ return (IRType*)cloneInst(&cloneEnv, &builder, originalType);
+ }
+ return (IRType*)originalType;
+ }
+
+ default:
+ if (as<IRResourceTypeBase>(originalType))
+ return (IRType*)newElementType;
+ return (IRType*)originalType;
+ }
+ }
+
+ static void resolveTextureFormatForParameter(IRInst* textureInst, IRTextureTypeBase* textureType)
+ {
+ ImageFormat format = (ImageFormat)(textureType->getFormat());
+ auto decor = textureInst->findDecoration<IRFormatDecoration>();
+ if (!decor)
+ return;
+ if (decor->getFormat() == (ImageFormat)textureType->getFormat())
+ return;
+
+ format = decor->getFormat();
+ if (format != ImageFormat::unknown)
+ {
+ IRBuilder builder(textureInst->getModule());
+ builder.setInsertBefore(textureInst);
+ auto formatArg = builder.getIntValue(builder.getUIntType(), IRIntegerValue(format));
+
+ auto newType = builder.getTextureType(
+ textureType->getElementType(),
+ textureType->getShapeInst(),
+ textureType->getIsArrayInst(),
+ textureType->getIsMultisampleInst(),
+ textureType->getSampleCountInst(),
+ textureType->getAccessInst(),
+ textureType->getIsShadowInst(),
+ textureType->getIsCombinedInst(),
+ formatArg);
+
+ List<IRUse*> typeReplacementWorkList;
+ HashSet<IRUse*> typeReplacementWorkListSet;
+
+ auto newInstType = (IRType*)replaceImageElementType(textureInst->getFullType(), newType);
+ textureInst->setFullType(newInstType);
+
+ for (auto use = textureInst->firstUse; use; use = use->nextUse)
+ {
+ if (typeReplacementWorkListSet.add(use))
+ typeReplacementWorkList.add(use);
+ }
+
+ // Update the types on dependent insts.
+ for (Index i = 0; i < typeReplacementWorkList.getCount(); i++)
+ {
+ auto use = typeReplacementWorkList[i];
+ auto user = use->getUser();
+ switch (user->getOp())
+ {
+ case kIROp_GetElementPtr:
+ case kIROp_GetElement:
+ case kIROp_Load:
+ case kIROp_Var:
+ {
+ auto newUserType = (IRType*)replaceImageElementType(user->getFullType(), newType);
+ if (newUserType != user->getFullType())
+ {
+ user->setFullType(newUserType);
+ for (auto u = user->firstUse; u; u = u->nextUse)
+ {
+ if (typeReplacementWorkListSet.add(u))
+ typeReplacementWorkList.add(u);
+ }
+ }
+ break;
+ }
+ case kIROp_Store:
+ {
+ auto store = as<IRStore>(user);
+ if (use == store->getValUse())
+ {
+ auto ptr = store->getPtr();
+ auto newPtrType = (IRType*)replaceImageElementType(ptr->getFullType(), newType);
+ if (newPtrType != ptr->getFullType())
+ {
+ ptr->setFullType(newPtrType);
+ for (auto u = ptr->firstUse; u; u = u->nextUse)
+ {
+ if (typeReplacementWorkListSet.add(u))
+ typeReplacementWorkList.add(u);
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ void resolveTextureFormat(IRModule* module)
+ {
+ for (auto globalInst : module->getGlobalInsts())
+ {
+ if (as<IRTextureTypeBase>(globalInst->getDataType()))
+ {
+ resolveTextureFormatForParameter(globalInst, (IRTextureTypeBase*)globalInst->getDataType());
+ }
+ else if (auto arrayType = as<IRArrayTypeBase>(globalInst->getDataType()))
+ {
+ if (as<IRTextureTypeBase>(arrayType->getElementType()))
+ {
+ resolveTextureFormatForParameter(globalInst, (IRTextureTypeBase*)arrayType->getElementType());
+ }
+ }
+ }
+ }
+}