// // Copyright (C) 2013-2016 LunarG, Inc. // // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // // Neither the name of 3Dlabs Inc. Ltd. nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE) #ifndef _REFLECTION_INCLUDED #define _REFLECTION_INCLUDED #include "../Public/ShaderLang.h" #include "../Include/Types.h" #include #include // // A reflection database and its interface, consistent with the OpenGL API reflection queries. // namespace glslang { class TIntermediate; class TIntermAggregate; class TReflectionTraverser; // The full reflection database class TReflection { public: TReflection(EShReflectionOptions opts, EShLanguage first, EShLanguage last) : options(opts), firstStage(first), lastStage(last), badReflection(TObjectReflection::badReflection()) { for (int dim=0; dim<3; ++dim) localSize[dim] = 0; } virtual ~TReflection() {} // grow the reflection stage by stage bool addStage(EShLanguage, const TIntermediate&); // for mapping a uniform index to a uniform object's description int getNumUniforms() { return (int)indexToUniform.size(); } const TObjectReflection& getUniform(int i) const { if (i >= 0 && i < (int)indexToUniform.size()) return indexToUniform[i]; else return badReflection; } // for mapping a block index to the block's description int getNumUniformBlocks() const { return (int)indexToUniformBlock.size(); } const TObjectReflection& getUniformBlock(int i) const { if (i >= 0 && i < (int)indexToUniformBlock.size()) return indexToUniformBlock[i]; else return badReflection; } // for mapping an pipeline input index to the input's description int getNumPipeInputs() { return (int)indexToPipeInput.size(); } const TObjectReflection& getPipeInput(int i) const { if (i >= 0 && i < (int)indexToPipeInput.size()) return indexToPipeInput[i]; else return badReflection; } // for mapping an pipeline output index to the output's description int getNumPipeOutputs() { return (int)indexToPipeOutput.size(); } const TObjectReflection& getPipeOutput(int i) const { if (i >= 0 && i < (int)indexToPipeOutput.size()) return indexToPipeOutput[i]; else return badReflection; } // for mapping from an atomic counter to the uniform index int getNumAtomicCounters() const { return (int)atomicCounterUniformIndices.size(); } const TObjectReflection& getAtomicCounter(int i) const { if (i >= 0 && i < (int)atomicCounterUniformIndices.size()) return getUniform(atomicCounterUniformIndices[i]); else return badReflection; } // for mapping a buffer variable index to a buffer variable object's description int getNumBufferVariables() { return (int)indexToBufferVariable.size(); } const TObjectReflection& getBufferVariable(int i) const { if (i >= 0 && i < (int)indexToBufferVariable.size()) return indexToBufferVariable[i]; else return badReflection; } // for mapping a storage block index to the storage block's description int getNumStorageBuffers() const { return (int)indexToBufferBlock.size(); } const TObjectReflection& getStorageBufferBlock(int i) const { if (i >= 0 && i < (int)indexToBufferBlock.size()) return indexToBufferBlock[i]; else return badReflection; } // for mapping any name to its index (block names, uniform names and input/output names) int getIndex(const char* name) const { TNameToIndex::const_iterator it = nameToIndex.find(name); if (it == nameToIndex.end()) return -1; else return it->second; } // see getIndex(const char*) int getIndex(const TString& name) const { return getIndex(name.c_str()); } // for mapping any name to its index (only pipe input/output names) int getPipeIOIndex(const char* name, const bool inOrOut) const { TNameToIndex::const_iterator it = inOrOut ? pipeInNameToIndex.find(name) : pipeOutNameToIndex.find(name); if (it == (inOrOut ? pipeInNameToIndex.end() : pipeOutNameToIndex.end())) return -1; else return it->second; } // see gePipeIOIndex(const char*, const bool) int getPipeIOIndex(const TString& name, const bool inOrOut) const { return getPipeIOIndex(name.c_str(), inOrOut); } // Thread local size unsigned getLocalSize(int dim) const { return dim <= 2 ? localSize[dim] : 0; } void dump(); protected: friend class glslang::TReflectionTraverser; void buildCounterIndices(const TIntermediate&); void buildUniformStageMask(const TIntermediate& intermediate); void buildAttributeReflection(EShLanguage, const TIntermediate&); // Need a TString hash: typedef std::unordered_map TNameToIndex; typedef std::map TNameToIndex; typedef std::vector TMapIndexToReflection; typedef std::vector TIndices; TMapIndexToReflection& GetBlockMapForStorage(TStorageQualifier storage) { if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer) return indexToBufferBlock; return indexToUniformBlock; } TMapIndexToReflection& GetVariableMapForStorage(TStorageQualifier storage) { if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer) return indexToBufferVariable; return indexToUniform; } EShReflectionOptions options; EShLanguage firstStage; EShLanguage lastStage; TObjectReflection badReflection; // return for queries of -1 or generally out of range; has expected descriptions with in it for this TNameToIndex nameToIndex; // maps names to indexes; can hold all types of data: uniform/buffer and which function names have been processed TNameToIndex pipeInNameToIndex; // maps pipe in names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers. TNameToIndex pipeOutNameToIndex; // maps pipe out names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers. TMapIndexToReflection indexToUniform; TMapIndexToReflection indexToUniformBlock; TMapIndexToReflection indexToBufferVariable; TMapIndexToReflection indexToBufferBlock; TMapIndexToReflection indexToPipeInput; TMapIndexToReflection indexToPipeOutput; TIndices atomicCounterUniformIndices; unsigned int localSize[3]; }; } // end namespace glslang #endif // _REFLECTION_INCLUDED #endif // !GLSLANG_WEB && !GLSLANG_ANGLE