/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 |