1 /* 2 ----------------------------------------------------------------------------- 3 This source file is part of OGRE 4 (Object-oriented Graphics Rendering Engine) 5 For the latest info, see http://www.ogre3d.org/ 6 7 Copyright (c) 2000-2013 Torus Knot Software Ltd 8 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in 17 all copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 THE SOFTWARE. 26 ----------------------------------------------------------------------------- 27 */ 28 29 #include "OgreGLSLESProgramCommon.h" 30 #include "OgreGLSLESGpuProgram.h" 31 #include "OgreGpuProgramManager.h" 32 #include "OgreGLES2Util.h" 33 #include "OgreGLES2RenderSystem.h" 34 #include "OgreRoot.h" 35 36 namespace Ogre { 37 38 //----------------------------------------------------------------------- GLSLESProgramCommon(GLSLESGpuProgram * vertexProgram,GLSLESGpuProgram * fragmentProgram)39 GLSLESProgramCommon::GLSLESProgramCommon(GLSLESGpuProgram* vertexProgram, GLSLESGpuProgram* fragmentProgram) 40 : mVertexProgram(vertexProgram) 41 , mFragmentProgram(fragmentProgram) 42 , mUniformRefsBuilt(false) 43 , mLinked(false) 44 , mTriedToLinkAndFailed(false) 45 { 46 // init mCustomAttributesIndexes 47 for(size_t i = 0 ; i < VES_COUNT; i++) 48 for(size_t j = 0 ; j < OGRE_MAX_TEXTURE_COORD_SETS; j++) 49 { 50 mCustomAttributesIndexes[i][j] = NULL_CUSTOM_ATTRIBUTES_INDEX; 51 } 52 53 // Initialize the attribute to semantic map 54 mSemanticTypeMap.insert(SemanticToStringMap::value_type("vertex", VES_POSITION)); 55 mSemanticTypeMap.insert(SemanticToStringMap::value_type("blendWeights", VES_BLEND_WEIGHTS)); 56 mSemanticTypeMap.insert(SemanticToStringMap::value_type("normal", VES_NORMAL)); 57 mSemanticTypeMap.insert(SemanticToStringMap::value_type("colour", VES_DIFFUSE)); 58 mSemanticTypeMap.insert(SemanticToStringMap::value_type("secondary_colour", VES_SPECULAR)); 59 mSemanticTypeMap.insert(SemanticToStringMap::value_type("blendIndices", VES_BLEND_INDICES)); 60 mSemanticTypeMap.insert(SemanticToStringMap::value_type("tangent", VES_TANGENT)); 61 mSemanticTypeMap.insert(SemanticToStringMap::value_type("binormal", VES_BINORMAL)); 62 mSemanticTypeMap.insert(SemanticToStringMap::value_type("uv", VES_TEXTURE_COORDINATES)); 63 64 if ((!mVertexProgram || !mFragmentProgram) && 65 !Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS)) 66 { 67 OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, 68 "Attempted to create a shader program without both a vertex and fragment program.", 69 "GLSLESProgramCommon::GLSLESProgramCommon"); 70 } 71 72 // Initialise uniform cache 73 mUniformCache = new GLES2UniformCache(); 74 } 75 76 //----------------------------------------------------------------------- ~GLSLESProgramCommon(void)77 GLSLESProgramCommon::~GLSLESProgramCommon(void) 78 { 79 OGRE_CHECK_GL_ERROR(glDeleteProgram(mGLProgramHandle)); 80 81 delete mUniformCache; 82 mUniformCache = 0; 83 } 84 85 //----------------------------------------------------------------------- getCombinedName()86 Ogre::String GLSLESProgramCommon::getCombinedName() 87 { 88 String name; 89 if (mVertexProgram) 90 { 91 name += "Vertex Program:" ; 92 name += mVertexProgram->getName(); 93 } 94 if (mFragmentProgram) 95 { 96 name += " Fragment Program:" ; 97 name += mFragmentProgram->getName(); 98 } 99 name += "\n"; 100 101 return name; 102 } 103 104 //----------------------------------------------------------------------- getAttributeSemanticEnum(String type)105 VertexElementSemantic GLSLESProgramCommon::getAttributeSemanticEnum(String type) 106 { 107 VertexElementSemantic semantic = mSemanticTypeMap[type]; 108 if(semantic > 0) 109 { 110 return semantic; 111 } 112 else 113 { 114 assert(false && "Missing attribute!"); 115 return (VertexElementSemantic)0; 116 } 117 } 118 119 //----------------------------------------------------------------------- getAttributeSemanticString(VertexElementSemantic semantic)120 const char * GLSLESProgramCommon::getAttributeSemanticString(VertexElementSemantic semantic) 121 { 122 for (SemanticToStringMap::iterator i = mSemanticTypeMap.begin(); i != mSemanticTypeMap.end(); ++i) 123 { 124 if((*i).second == semantic) 125 return (*i).first.c_str(); 126 } 127 128 assert(false && "Missing attribute!"); 129 return 0; 130 } 131 132 //----------------------------------------------------------------------- getAttributeIndex(VertexElementSemantic semantic,uint index)133 GLint GLSLESProgramCommon::getAttributeIndex(VertexElementSemantic semantic, uint index) 134 { 135 GLint res = mCustomAttributesIndexes[semantic-1][index]; 136 if (res == NULL_CUSTOM_ATTRIBUTES_INDEX) 137 { 138 const char * attString = getAttributeSemanticString(semantic); 139 GLint attrib; 140 OGRE_CHECK_GL_ERROR(attrib = glGetAttribLocation(mGLProgramHandle, attString)); 141 142 // sadly position is a special case 143 if (attrib == NOT_FOUND_CUSTOM_ATTRIBUTES_INDEX && semantic == VES_POSITION) 144 { 145 OGRE_CHECK_GL_ERROR(attrib = glGetAttribLocation(mGLProgramHandle, "position")); 146 } 147 148 // for uv and other case the index is a part of the name 149 if (attrib == NOT_FOUND_CUSTOM_ATTRIBUTES_INDEX) 150 { 151 String attStringWithSemantic = String(attString) + StringConverter::toString(index); 152 OGRE_CHECK_GL_ERROR(attrib = glGetAttribLocation(mGLProgramHandle, attStringWithSemantic.c_str())); 153 } 154 155 // update mCustomAttributesIndexes with the index we found (or didn't find) 156 mCustomAttributesIndexes[semantic-1][index] = attrib; 157 res = attrib; 158 } 159 return res; 160 } 161 //----------------------------------------------------------------------- isAttributeValid(VertexElementSemantic semantic,uint index)162 bool GLSLESProgramCommon::isAttributeValid(VertexElementSemantic semantic, uint index) 163 { 164 return getAttributeIndex(semantic, index) != NOT_FOUND_CUSTOM_ATTRIBUTES_INDEX; 165 } 166 //----------------------------------------------------------------------- getMicrocodeFromCache(void)167 void GLSLESProgramCommon::getMicrocodeFromCache(void) 168 { 169 GpuProgramManager::Microcode cacheMicrocode = 170 GpuProgramManager::getSingleton().getMicrocodeFromCache(getCombinedName()); 171 172 // add to the microcode to the cache 173 String name; 174 name = getCombinedName(); 175 176 // turns out we need this param when loading 177 GLenum binaryFormat = 0; 178 179 cacheMicrocode->seek(0); 180 181 // get size of binary 182 cacheMicrocode->read(&binaryFormat, sizeof(GLenum)); 183 184 if(getGLES2SupportRef()->checkExtension("GL_OES_get_program_binary") || gleswIsSupported(3, 0)) 185 { 186 GLint binaryLength = static_cast<GLint>(cacheMicrocode->size() - sizeof(GLenum)); 187 188 // load binary 189 OGRE_CHECK_GL_ERROR(glProgramBinaryOES(mGLProgramHandle, 190 binaryFormat, 191 cacheMicrocode->getPtr(), 192 binaryLength)); 193 } 194 195 GLint success = 0; 196 OGRE_CHECK_GL_ERROR(glGetProgramiv(mGLProgramHandle, GL_LINK_STATUS, &success)); 197 if (!success) 198 { 199 // 200 // Something must have changed since the program binaries 201 // were cached away. Fallback to source shader loading path, 202 // and then retrieve and cache new program binaries once again. 203 // 204 compileAndLink(); 205 } 206 } 207 208 } // namespace Ogre 209