IProgram* ShaderModuleRepository::findProgram(ShaderType type, int numShaders, IShader ** pShaders) { int sz = (int)m_programs.size(); for(int i=0; i<sz; i++) { IProgram* p = m_programs[i].p; if(numShaders != p->getNumShaders()) continue; int j; for(j=0; j<numShaders; j++) { ShaderType t; IShader* pShd; pShd = p->getShader(0, &t); if(t != type) return NULL; if((pShd == NULL) || (findShader(pShd->getName()) == NULL) ) break; } if(j == numShaders) return p; } return NULL; }
/*************************************************************************/ /** ** ** **/ /*************************************************************************/ void Container::consolidateShaders() { ShaderModuleRepository* pShdRep = static_cast<ShaderModuleRepository*>(getShaderModuleRepositorySingleton()); std::set<IProgram *> usedPrograms; int sz = (int)m_shaderprograms.size(); for(int i=0; i<sz; i++) { //assert(m_shaderprograms[i]); CHECK_POINTER(m_shaderprograms[i]); usedPrograms.insert(m_shaderprograms[i]); } // Clear the table : we are about to re-create it m_shaderprograms.clear(); // Walk through techs/passes and check if any pass is using it TechVec::iterator it = m_techniques.begin(); while(it != m_techniques.end()) { Technique::PassVec::iterator ip = (*it)->m_passes.begin(); while(ip != (*it)->m_passes.end()) { Pass::StatesLayerMap::iterator isl = ip->pass->m_statesLayers.begin(); while(isl != ip->pass->m_statesLayers.end()) { IProgram* p; CHECK_TRUE_MSG(isl->second.program == NULL, "TODO: handle consolidation for non-separable programs"); if(isl->second.programPipeline) for(int i=0; p = isl->second.programPipeline->getShaderProgram(i); i++) { std::set<IProgram *>::iterator iip; // at last we have a program iip = usedPrograms.find(p); #ifdef _DEBUG //LOGD("Program %d (", p->getProgram() ); //IShader* pshd; //for(int ii=0; pshd = p->getShader(ii); ii++) // LOGD("%s ", pshd->getName()); #endif if(iip != usedPrograms.end()) { #ifdef _DEBUG LOGD("Program %d (", p->getProgram() ); IShader* pshd; for(int ii=0; pshd = p->getShader(ii); ii++) LOGD("%s ", pshd->getName()); LOGD(") Found as used by some pass (%s)\n", ip->pass->getName()); #endif usedPrograms.erase(iip); m_shaderprograms.push_back(p); // add it back, because used here } else { #ifdef _DEBUG //LOGD(") used in pass %s BUT not found\n", ip->pass->getName()); #endif } } // for() ++isl; } ++ip; } ++it; } std::set<IProgram *>::iterator iip = usedPrograms.begin(); while(iip != usedPrograms.end()) { #ifdef _DEBUG LOGD("Program %d (", (*iip)->getProgram() ); IShader* pshd; for(int ii=0; pshd = (*iip)->getShader(ii); ii++) LOGD("%s ", pshd->getName()); #endif int c = pShdRep->releaseProgram(*iip); if(c <= 0) { #ifdef _DEBUG LOGD(") Not used anymore anywhere. DELETING it\n"); #endif // good enough : query the first shader in the program switch((*iip)->getShader(0)->getType()) { case TGLSL: case THLSL: delete_Program(*iip); break; case TCUDA: delete_ProgramCUDA(*iip); break; } } else { #ifdef _DEBUG LOGD(") Still used as Global (%d)\n", c); #endif } ++iip; } }