summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-ir-resolve-texture-format.cpp
blob: df30f1dc6e1444288bdf70cfc1b535f7d3714ee8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include "slang-ir-resolve-texture-format.h"

#include "slang-ir-clone.h"
#include "slang-ir-insts.h"

namespace Slang
{
static IRType* replaceImageElementType(IRInst* originalType, IRInst* newElementType)
{
    switch (originalType->getOp())
    {
    case kIROp_ArrayType:
    case kIROp_UnsizedArrayType:
    case kIROp_PtrType:
    case kIROp_OutParamType:
    case kIROp_RefParamType:
    case kIROp_BorrowInParamType:
    case kIROp_BorrowInOutParamType:
        {
            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());
            }
        }
    }
}
} // namespace Slang