Coverage Report

Created: 2026-09-01 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/glslang/glslang/MachineIndependent/iomapper.h
Line
Count
Source
1
//
2
// Copyright (C) 2016 LunarG, Inc.
3
//
4
// All rights reserved.
5
//
6
// Redistribution and use in source and binary forms, with or without
7
// modification, are permitted provided that the following conditions
8
// are met:
9
//
10
//    Redistributions of source code must retain the above copyright
11
//    notice, this list of conditions and the following disclaimer.
12
//
13
//    Redistributions in binary form must reproduce the above
14
//    copyright notice, this list of conditions and the following
15
//    disclaimer in the documentation and/or other materials provided
16
//    with the distribution.
17
//
18
//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
19
//    contributors may be used to endorse or promote products derived
20
//    from this software without specific prior written permission.
21
//
22
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
// POSSIBILITY OF SUCH DAMAGE.
34
//
35
36
#ifndef _IOMAPPER_INCLUDED
37
#define _IOMAPPER_INCLUDED
38
39
#include <cstdint>
40
#include <array>
41
#include <unordered_map>
42
#include <unordered_set>
43
//
44
// A reflection database and its interface, consistent with the OpenGL API reflection queries.
45
//
46
47
class TInfoSink;
48
49
namespace glslang {
50
51
class TIntermediate;
52
struct TVarEntryInfo;
53
// Base class for shared TIoMapResolver services, used by several derivations.
54
struct TDefaultIoResolverBase : public glslang::TIoMapResolver {
55
public:
56
    TDefaultIoResolverBase(const TIntermediate& intermediate);
57
    typedef std::vector<int> TSlotSet;
58
    typedef std::unordered_map<int, TSlotSet> TSlotSetMap;
59
    typedef std::array<TSlotSetMap, EResCount> TSlotSetMapResourceArray;
60
61
    // grow the reflection stage by stage
62
0
    void notifyBinding(EShLanguage, TVarEntryInfo& /*ent*/) override {}
63
0
    void notifyInOut(EShLanguage, TVarEntryInfo& /*ent*/) override {}
64
0
    void beginNotifications(EShLanguage) override {}
65
0
    void endNotifications(EShLanguage) override {}
66
0
    void beginResolve(EShLanguage) override {}
67
0
    void endResolve(EShLanguage) override {}
68
0
    void beginCollect(EShLanguage) override {}
69
0
    void endCollect(EShLanguage) override {}
70
0
    void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
71
0
    void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
72
    int getBaseBinding(EShLanguage stage, TResourceType res, unsigned int set) const;
73
    const std::vector<std::string>& getResourceSetBinding(EShLanguage stage) const;
74
    virtual TResourceType getResourceType(const glslang::TType& type) = 0;
75
    bool doAutoBindingMapping() const;
76
    bool doAutoLocationMapping() const;
77
    TSlotSet::iterator findSlot(int resource, int set, int slot);
78
    bool checkEmpty(int resource, int set, int slot);
79
0
    bool validateInOut(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; }
80
    int reserveSlot(int resource, int set, int slot, int size = 1);
81
    int getFreeSlot(int resource, int set, int base, int size = 1);
82
    int resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
83
    int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
84
    int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override;
85
    int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
86
    int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
87
0
    void addStage(EShLanguage stage, TIntermediate& stageIntermediate) override {
88
0
        if ((unsigned)stage < EShLangCount) {
89
0
            stageMask[(unsigned)stage] = true;
90
0
            stageIntermediates[(unsigned)stage] = &stageIntermediate;
91
0
        }
92
0
    }
93
    uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage);
94
95
    TSlotSetMapResourceArray slots;
96
    bool hasError = false;
97
98
protected:
99
    TDefaultIoResolverBase(TDefaultIoResolverBase&);
100
    TDefaultIoResolverBase& operator=(TDefaultIoResolverBase&);
101
    const TIntermediate& referenceIntermediate;
102
    int nextUniformLocation;
103
    int nextInputLocation;
104
    int nextOutputLocation;
105
    bool stageMask[EShLangCount + 1];
106
    const TIntermediate* stageIntermediates[EShLangCount];
107
108
    // Return descriptor set specific base if there is one, and the generic base otherwise.
109
0
    int selectBaseBinding(int base, int descriptorSetBase) const {
110
0
        return descriptorSetBase != -1 ? descriptorSetBase : base;
111
0
    }
112
113
0
    static int getLayoutSet(const glslang::TType& type) {
114
0
        if (type.getQualifier().hasSet())
115
0
            return type.getQualifier().layoutSet;
116
0
        else
117
0
            return 0;
118
0
    }
119
120
0
    static bool isSamplerType(const glslang::TType& type) {
121
0
        return type.getBasicType() == glslang::EbtSampler && type.getSampler().isPureSampler();
122
0
    }
123
124
0
    static bool isTextureType(const glslang::TType& type) {
125
0
        return (type.getBasicType() == glslang::EbtSampler && !type.getSampler().isCombined() &&
126
0
                (type.getSampler().isTexture() || type.getSampler().isSubpass()));
127
0
    }
128
129
0
    static bool isUboType(const glslang::TType& type) {
130
0
        return type.getQualifier().storage == EvqUniform && type.isStruct();
131
0
    }
132
133
0
    static bool isImageType(const glslang::TType& type) {
134
0
        return type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage();
135
0
    }
136
137
0
    static bool isSsboType(const glslang::TType& type) {
138
0
        return type.getQualifier().storage == EvqBuffer;
139
0
    }
140
141
0
    static bool isCombinedSamplerType(const glslang::TType& type) {
142
0
        return type.getBasicType() == glslang::EbtSampler && type.getSampler().isCombined();
143
0
    }
144
145
0
    static bool isAsType(const glslang::TType& type) {
146
0
        return type.getBasicType() == glslang::EbtAccStruct;
147
0
    }
148
149
0
    static bool isTensorType(const glslang::TType& type) {
150
0
        return type.isTensorARM();
151
0
    }
152
153
0
    static bool isValidGlslType(const glslang::TType& type) {
154
0
        // at most one must be true
155
0
        return (isSamplerType(type) + isTextureType(type) + isUboType(type) + isImageType(type) +
156
0
            isSsboType(type) + isCombinedSamplerType(type) + isAsType(type) + isTensorType(type)) <= 1;
157
0
    }
158
159
    // Return true if this is a SRV (shader resource view) type:
160
0
    static bool isSrvType(const glslang::TType& type) {
161
0
        return isTextureType(type) || type.getQualifier().storage == EvqBuffer;
162
0
    }
163
164
    // Return true if this is a UAV (unordered access view) type:
165
0
    static bool isUavType(const glslang::TType& type) {
166
0
        if (type.getQualifier().isReadOnly())
167
0
            return false;
168
0
        return (type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage()) ||
169
0
                (type.getQualifier().storage == EvqBuffer);
170
0
    }
171
};
172
173
// Default I/O resolver for OpenGL
174
struct TDefaultGlslIoResolver : public TDefaultIoResolverBase {
175
public:
176
    typedef std::map<TString, int> TVarSlotMap;  // <resourceName, location/binding>
177
    typedef std::map<int, TVarSlotMap> TSlotMap; // <resourceKey, TVarSlotMap>
178
    typedef std::array<TSlotMap, EResCount> TResourceSlotMap;
179
    TDefaultGlslIoResolver(const TIntermediate& intermediate);
180
0
    bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; }
181
    TResourceType getResourceType(const glslang::TType& type) override;
182
    int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override;
183
    int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
184
    int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
185
    void beginResolve(EShLanguage /*stage*/) override;
186
    void endResolve(EShLanguage stage) override;
187
    void beginCollect(EShLanguage) override;
188
    void endCollect(EShLanguage) override;
189
    void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
190
    void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
191
    // in/out symbol and uniform symbol are stored in the same resourceSlotMap, the storage key is used to identify each type of symbol.
192
    // We use stage and storage qualifier to construct a storage key. it can help us identify the same storage resource used in different stage.
193
    // if a resource is a program resource and we don't need know it usage stage, we can use same stage to build storage key.
194
    // Note: both stage and type must less then 0xffff.
195
0
    int buildStorageKey(EShLanguage stage, TStorageQualifier type) {
196
0
        assert(static_cast<uint32_t>(stage) <= 0x0000ffff && static_cast<uint32_t>(type) <= 0x0000ffff);
197
0
        return (stage << 16) | type;
198
0
    }
199
200
protected:
201
    // Use for mark pre stage, to get more interface symbol information.
202
    EShLanguage preStage;
203
    // Use for mark current shader stage for resolver
204
    EShLanguage currentStage;
205
    // Slot map for storage resource(location of uniform and interface symbol) It's a program share slot
206
    TResourceSlotMap resourceSlotMap;
207
    // Slot map for other resource(image, ubo, ssbo), It's a program share slot.
208
    TSlotMap storageSlotMap;
209
};
210
211
typedef std::map<TString, TVarEntryInfo> TVarLiveMap;
212
213
// I/O mapper for GLSL
214
class TGlslIoMapper : public TIoMapper {
215
public:
216
    TGlslIoMapper();
217
    virtual ~TGlslIoMapper();
218
    // If set, the uniform block with the given name will be changed to be backed by
219
    // push_constant if it's size is <= maxSize
220
0
    bool setAutoPushConstantBlock(const char* name, unsigned int maxSize, TLayoutPacking packing) override {
221
0
        autoPushConstantBlockName = name;
222
0
        autoPushConstantMaxSize = maxSize;
223
0
        autoPushConstantBlockPacking = packing;
224
0
        return true;
225
0
    }
226
    // grow the reflection stage by stage
227
    bool addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*) override;
228
    bool doMap(TIoMapResolver*, TInfoSink&) override;
229
    TIntermediate* intermediates[EShLangCount];
230
    bool hadError = false;
231
    bool relaxSetBindingLimits = false;
232
    EProfile profile;
233
    int version;
234
235
private:
236
    TString autoPushConstantBlockName;
237
    unsigned int autoPushConstantMaxSize;
238
    TLayoutPacking autoPushConstantBlockPacking;
239
    TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount],
240
                *uniformVarMap[EShLangCount];
241
};
242
243
} // end namespace glslang
244
245
#endif // _IOMAPPER_INCLUDED