1 // 2 // Copyright (C) 2013-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 _REFLECTION_INCLUDED 37 #define _REFLECTION_INCLUDED 38 39 #include "../Public/ShaderLang.h" 40 #include "../Include/Types.h" 41 42 #include <list> 43 #include <set> 44 45 // 46 // A reflection database and its interface, consistent with the OpenGL API reflection queries. 47 // 48 49 namespace glslang { 50 51 class TIntermediate; 52 class TIntermAggregate; 53 class TReflectionTraverser; 54 55 // The full reflection database 56 class TReflection { 57 public: TReflection(EShReflectionOptions opts,EShLanguage first,EShLanguage last)58 TReflection(EShReflectionOptions opts, EShLanguage first, EShLanguage last) 59 : options(opts), firstStage(first), lastStage(last), badReflection(TObjectReflection::badReflection()) 60 { 61 for (int dim=0; dim<3; ++dim) 62 localSize[dim] = 0; 63 } 64 ~TReflection()65 virtual ~TReflection() {} 66 67 // grow the reflection stage by stage 68 bool addStage(EShLanguage, const TIntermediate&); 69 70 // for mapping a uniform index to a uniform object's description getNumUniforms()71 int getNumUniforms() { return (int)indexToUniform.size(); } getUniform(int i)72 const TObjectReflection& getUniform(int i) const 73 { 74 if (i >= 0 && i < (int)indexToUniform.size()) 75 return indexToUniform[i]; 76 else 77 return badReflection; 78 } 79 80 // for mapping a block index to the block's description getNumUniformBlocks()81 int getNumUniformBlocks() const { return (int)indexToUniformBlock.size(); } getUniformBlock(int i)82 const TObjectReflection& getUniformBlock(int i) const 83 { 84 if (i >= 0 && i < (int)indexToUniformBlock.size()) 85 return indexToUniformBlock[i]; 86 else 87 return badReflection; 88 } 89 90 // for mapping an pipeline input index to the input's description getNumPipeInputs()91 int getNumPipeInputs() { return (int)indexToPipeInput.size(); } getPipeInput(int i)92 const TObjectReflection& getPipeInput(int i) const 93 { 94 if (i >= 0 && i < (int)indexToPipeInput.size()) 95 return indexToPipeInput[i]; 96 else 97 return badReflection; 98 } 99 100 // for mapping an pipeline output index to the output's description getNumPipeOutputs()101 int getNumPipeOutputs() { return (int)indexToPipeOutput.size(); } getPipeOutput(int i)102 const TObjectReflection& getPipeOutput(int i) const 103 { 104 if (i >= 0 && i < (int)indexToPipeOutput.size()) 105 return indexToPipeOutput[i]; 106 else 107 return badReflection; 108 } 109 110 // for mapping from an atomic counter to the uniform index getNumAtomicCounters()111 int getNumAtomicCounters() const { return (int)atomicCounterUniformIndices.size(); } getAtomicCounter(int i)112 const TObjectReflection& getAtomicCounter(int i) const 113 { 114 if (i >= 0 && i < (int)atomicCounterUniformIndices.size()) 115 return getUniform(atomicCounterUniformIndices[i]); 116 else 117 return badReflection; 118 } 119 120 // for mapping a buffer variable index to a buffer variable object's description getNumBufferVariables()121 int getNumBufferVariables() { return (int)indexToBufferVariable.size(); } getBufferVariable(int i)122 const TObjectReflection& getBufferVariable(int i) const 123 { 124 if (i >= 0 && i < (int)indexToBufferVariable.size()) 125 return indexToBufferVariable[i]; 126 else 127 return badReflection; 128 } 129 130 // for mapping a storage block index to the storage block's description getNumStorageBuffers()131 int getNumStorageBuffers() const { return (int)indexToBufferBlock.size(); } getStorageBufferBlock(int i)132 const TObjectReflection& getStorageBufferBlock(int i) const 133 { 134 if (i >= 0 && i < (int)indexToBufferBlock.size()) 135 return indexToBufferBlock[i]; 136 else 137 return badReflection; 138 } 139 140 // for mapping any name to its index (block names, uniform names and input/output names) getIndex(const char * name)141 int getIndex(const char* name) const 142 { 143 TNameToIndex::const_iterator it = nameToIndex.find(name); 144 if (it == nameToIndex.end()) 145 return -1; 146 else 147 return it->second; 148 } 149 150 // see getIndex(const char*) getIndex(const TString & name)151 int getIndex(const TString& name) const { return getIndex(name.c_str()); } 152 153 154 // for mapping any name to its index (only pipe input/output names) getPipeIOIndex(const char * name,const bool inOrOut)155 int getPipeIOIndex(const char* name, const bool inOrOut) const 156 { 157 TNameToIndex::const_iterator it = inOrOut ? pipeInNameToIndex.find(name) : pipeOutNameToIndex.find(name); 158 if (it == (inOrOut ? pipeInNameToIndex.end() : pipeOutNameToIndex.end())) 159 return -1; 160 else 161 return it->second; 162 } 163 164 // see gePipeIOIndex(const char*, const bool) getPipeIOIndex(const TString & name,const bool inOrOut)165 int getPipeIOIndex(const TString& name, const bool inOrOut) const { return getPipeIOIndex(name.c_str(), inOrOut); } 166 167 // Thread local size getLocalSize(int dim)168 unsigned getLocalSize(int dim) const { return dim <= 2 ? localSize[dim] : 0; } 169 170 void dump(); 171 172 protected: 173 friend class glslang::TReflectionTraverser; 174 175 void buildCounterIndices(const TIntermediate&); 176 void buildUniformStageMask(const TIntermediate& intermediate); 177 void buildAttributeReflection(EShLanguage, const TIntermediate&); 178 179 // Need a TString hash: typedef std::unordered_map<TString, int> TNameToIndex; 180 typedef std::map<std::string, int> TNameToIndex; 181 typedef std::vector<TObjectReflection> TMapIndexToReflection; 182 typedef std::vector<int> TIndices; 183 GetBlockMapForStorage(TStorageQualifier storage)184 TMapIndexToReflection& GetBlockMapForStorage(TStorageQualifier storage) 185 { 186 if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer) 187 return indexToBufferBlock; 188 return indexToUniformBlock; 189 } GetVariableMapForStorage(TStorageQualifier storage)190 TMapIndexToReflection& GetVariableMapForStorage(TStorageQualifier storage) 191 { 192 if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer) 193 return indexToBufferVariable; 194 return indexToUniform; 195 } 196 197 EShReflectionOptions options; 198 199 EShLanguage firstStage; 200 EShLanguage lastStage; 201 202 TObjectReflection badReflection; // return for queries of -1 or generally out of range; has expected descriptions with in it for this 203 TNameToIndex nameToIndex; // maps names to indexes; can hold all types of data: uniform/buffer and which function names have been processed 204 TNameToIndex pipeInNameToIndex; // maps pipe in names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers. 205 TNameToIndex pipeOutNameToIndex; // maps pipe out names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers. 206 TMapIndexToReflection indexToUniform; 207 TMapIndexToReflection indexToUniformBlock; 208 TMapIndexToReflection indexToBufferVariable; 209 TMapIndexToReflection indexToBufferBlock; 210 TMapIndexToReflection indexToPipeInput; 211 TMapIndexToReflection indexToPipeOutput; 212 TIndices atomicCounterUniformIndices; 213 214 unsigned int localSize[3]; 215 }; 216 217 } // end namespace glslang 218 219 #endif // _REFLECTION_INCLUDED 220