int Pass::getD3DIASignatureSize() { if(m_pActiveStatesLayer == NULL) return 0; if(m_pActiveStatesLayer->program) return m_pActiveStatesLayer->program->getD3DIASignatureSize(); if(m_pActiveStatesLayer->programPipeline) { int i=0; IProgram* prg = m_pActiveStatesLayer->programPipeline->getShaderProgram(i++); while(prg) { int f = prg->getProgramShaderFlags(); if(f & FX_VERTEX_SHADER_BIT) return prg->getD3DIASignatureSize(); prg = m_pActiveStatesLayer->programPipeline->getShaderProgram(i++); } } return 0; }
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; } }
Uniform* UniformCUDA::updateTextures(ShadowedData* data, Pass *pass, int layerID, bool bCreateIfNeeded) { CUresult res; CUarray cuArray = NULL; if(data && data->tex.pRes) { // texture reference taken from the CUDA program : // the uniform texture will take care of this with : //CUtexref texRef; cuModuleGetTexRef(&texRef, getModule(), name); cuArray = static_cast<ResourceCUDA*>(data->tex.pRes)->mapResource(); } if(cuArray) { for(int i=0; i<(int)m_targets.size(); i++) { STarget &t = m_targets[i]; if(((pass == NULL) || ((t.pass == pass)&&(t.passLayerId == layerID)))&&(t.ttype == TCUDA)) { res = cuTexRefSetArray( (CUtexref)t.cudaTexRef, cuArray, CU_TRSA_OVERRIDE_FORMAT ); if(res) { LOGE("Error>> CUDA failed to set texture reference to CUDA sampler\n"); return false; } } } } // // a pass ptr was specified and nothing found, we shall try to find the uniform in the pass program // if(pass && bCreateIfNeeded) { STarget t; int p = 0; t.uniformLocation = -1; t.dirty = false; t.valid = false; t.pass = pass; t.ttype = TCUDA; t.passLayerId = layerID; t.shaderProgramNumber = 0; // cast it to CUDAProgram : it can't be another class in this case IProgram* prg = pass->getProgram(layerID); // NOTE: TODO... make the test cleaner ! Hacky for now. // a non-separable program with 0 ID can only be a CUDA program... well... if(prg && (prg->getProgram()==0)) { CUmodule module = (CUmodule)(static_cast<CUDAProgram*>(prg)->m_cuModule); CUtexref texRef; res = cuModuleGetTexRef(&texRef, module, m_name.c_str()); t.cudaTexRef = texRef; if(res) { LOGI("Warning : texture %s referenced in the pass %s is not used in the Cuda module of this pass\n", pass->getName(), m_name.c_str()); } else // Store the target if the shader needed it { // NOTE: maybe we should use a std::map<pass,target> for targets... int i = 0; for(i=0; i<(int)m_targets.size(); i++) if((m_targets[i].pass == pass) && (m_targets[i].passLayerId == layerID) && (m_targets[i].ttype == t.ttype)) { m_targets[i] = t; break; } if(i == m_targets.size()) { m_targets.push_back(t); pass->addUniform(this, i); } // prepare the resource related to this texture // maybe we should put this call somewhere else if(data && data->tex.pRes) static_cast<ResourceCUDA*>(data->tex.pRes)->setupAsCUDATexture(); // update again now we found it return UniformCUDA::updateForTarget(data, i); } } } return this; }