// Calls glUseProgram() as a side effect CGLMShaderPair *CGLMShaderPairCache::SelectShaderPairInternal( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits, int rowIndex ) { CGLMShaderPair *result = NULL; #if GLMDEBUG int loglevel = gl_shaderpair_cachelog.GetInt(); #else const int loglevel = 0; #endif char vtempname[128]; int vtempindex = -1; vtempindex; int vtempcombo = -1; vtempcombo; char ptempname[128]; int ptempindex = -1; ptempindex; int ptempcombo = -1; ptempcombo; CGLMPairCacheEntry *row = HashRowPtr( rowIndex ); // Re-probe to find the oldest and first unoccupied entry (this func should be very rarely called if the cache is properly configured so re-scanning shouldn't matter). int hitway, emptyway, oldestway; HashRowProbe( row, vp, fp, extraKeyBits, hitway, emptyway, oldestway ); Assert( hitway == -1 ); // we missed. if there is no empty way, then somebody's getting evicted. int destway = -1; if (emptyway>=0) { destway = emptyway; if (loglevel >= 2) // misses logged at level 3 and higher { printf("\nSSP: miss - row %05d - ", rowIndex ); } } else { // evict the oldest way Assert( oldestway >= 0); // better not come back negative CGLMPairCacheEntry *evict = row + oldestway; Assert( evict->m_pair != NULL ); Assert( evict->m_pair != m_ctx->m_pBoundPair ); // just check ///////////////////////FIXME may need to do a shoot-down if the pair being evicted is currently active in the context m_evictions[ rowIndex ]++; // log eviction if desired if (loglevel >= 2) // misses logged at level 3 and higher { //evict->m_vertexProg->GetLabelIndexCombo( vtempname, sizeof(vtempname), &vtempindex, &vtempcombo ); //evict->m_fragmentProg->GetLabelIndexCombo( ptempname, sizeof(ptempname), &ptempindex, &ptempcombo ); //printf("\nSSP: miss - row %05d - [ %s/%d/%d %s/%d/%d ]'s %d'th eviction - ", rowIndex, vtempname, vtempindex, vtempcombo, ptempname, ptempindex, ptempcombo, m_evictions[ rowIndex ] ); evict->m_vertexProg->GetComboIndexNameString( vtempname, sizeof(vtempname) ); evict->m_fragmentProg->GetComboIndexNameString( ptempname, sizeof(ptempname) ); printf("\nSSP: miss - row %05d - [ %s + %s ]'s %d'th eviction - ", rowIndex, vtempname, ptempname, m_evictions[ rowIndex ] ); } delete evict->m_pair; evict->m_pair = NULL; memset( evict, 0, sizeof(*evict) ); destway = oldestway; } // make the new entry CGLMPairCacheEntry *newentry = row + destway; newentry->m_lastMark = m_mark; newentry->m_vertexProg = vp; newentry->m_fragmentProg = fp; newentry->m_extraKeyBits = extraKeyBits; newentry->m_pair = new CGLMShaderPair( m_ctx ); Assert( newentry->m_pair ); newentry->m_pair->SetProgramPair( vp, fp ); if (loglevel >= 2) // say a little bit more { //newentry->m_vertexProg->GetLabelIndexCombo( vtempname, sizeof(vtempname), &vtempindex, &vtempcombo ); //newentry->m_fragmentProg->GetLabelIndexCombo( ptempname, sizeof(ptempname), &ptempindex, &ptempcombo ); //printf("new [ %s/%d/%d %s/%d/%d ]", vtempname, vtempindex, vtempcombo, ptempname, ptempindex, ptempcombo ); newentry->m_vertexProg->GetComboIndexNameString( vtempname, sizeof(vtempname) ); newentry->m_fragmentProg->GetComboIndexNameString( ptempname, sizeof(ptempname) ); printf("new [ %s + %s ]", vtempname, ptempname ); } m_mark = m_mark+1; if (!m_mark) // somewhat unlikely this will ever be reached.. but we need to avoid zero as a mark value { m_mark = 1; } result = newentry->m_pair; if (glm_cacheprograms.GetInt()) { WriteToProgramCache( newentry->m_pair ); } return result; }
CGLMShaderPair *CGLMShaderPairCache::SelectShaderPair( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits ) { CGLMShaderPair *result = NULL; int loglevel = gl_shaderpair_cachelog/* .GetInt() */; char vtempname[128]; int vtempindex = -1; int vtempcombo = -1; char ptempname[128]; int ptempindex = -1; int ptempcombo = -1; // select row where pair would be found if it exists uint rowIndex = HashRowIndex( vp, fp, extraKeyBits ); CGLMPairCacheEntry *row = HashRowPtr( rowIndex ); // probe row and see if we get a hit int hitway = -1;int emptyway = -1; int oldestway = -1; HashRowProbe( row, vp, fp, extraKeyBits, &hitway, &emptyway, &oldestway ); if (hitway >=0) { // found it. mark it and return CGLMPairCacheEntry *hit = row + hitway; hit->m_lastMark = m_mark; m_mark = m_mark+1; if (!m_mark) // somewhat unlikely this will ever be reached.. but we need to avoid zero as a mark value { m_mark = 1; } // count the hit m_hits[ rowIndex ] ++; if (loglevel >= 3) // hits logged at level 3 and higher { printf("\nSSP: hit - row %05d - pair $%p (%d'th hit on row)",rowIndex, hit->m_pair, m_hits[ rowIndex ] ); } result = hit->m_pair; } else { // we missed. if there is no empty way, then somebody's getting evicted. int destway = -1; if (emptyway>=0) { destway = emptyway; if (loglevel >= 2) // misses logged at level 3 and higher { printf("\nSSP: miss - row %05d - ", rowIndex ); } } else { // evict the oldest way Assert( oldestway >= 0); // better not come back negative CGLMPairCacheEntry *evict = row + oldestway; Assert( evict->m_pair != NULL ); Assert( evict->m_pair != m_ctx->m_boundPair ); // just check ///////////////////////FIXME may need to do a shoot-down if the pair being evicted is currently active in the context m_evictions[ rowIndex ]++; // log eviction if desired if (loglevel >= 2) // misses logged at level 3 and higher { //evict->m_vertexProg->GetLabelIndexCombo( vtempname, sizeof(vtempname), &vtempindex, &vtempcombo ); //evict->m_fragmentProg->GetLabelIndexCombo( ptempname, sizeof(ptempname), &ptempindex, &ptempcombo ); //printf("\nSSP: miss - row %05d - [ %s/%d/%d %s/%d/%d ]'s %d'th eviction - ", rowIndex, vtempname, vtempindex, vtempcombo, ptempname, ptempindex, ptempcombo, m_evictions[ rowIndex ] ); evict->m_vertexProg->GetComboIndexNameString( vtempname, sizeof(vtempname) ); evict->m_fragmentProg->GetComboIndexNameString( ptempname, sizeof(ptempname) ); printf("\nSSP: miss - row %05d - [ %s + %s ]'s %d'th eviction - ", rowIndex, vtempname, ptempname, m_evictions[ rowIndex ] ); } delete evict->m_pair; evict->m_pair = NULL; memset( evict, 0, sizeof(*evict) ); destway = oldestway; } // make the new entry CGLMPairCacheEntry *newentry = row + destway; newentry->m_lastMark = m_mark; newentry->m_vertexProg = vp; newentry->m_fragmentProg = fp; newentry->m_extraKeyBits = extraKeyBits; newentry->m_pair = new CGLMShaderPair( m_ctx ); newentry->m_pair->SetProgramPair( vp, fp ); if (loglevel >= 2) // say a little bit more { //newentry->m_vertexProg->GetLabelIndexCombo( vtempname, sizeof(vtempname), &vtempindex, &vtempcombo ); //newentry->m_fragmentProg->GetLabelIndexCombo( ptempname, sizeof(ptempname), &ptempindex, &ptempcombo ); //printf("new [ %s/%d/%d %s/%d/%d ]", vtempname, vtempindex, vtempcombo, ptempname, ptempindex, ptempcombo ); newentry->m_vertexProg->GetComboIndexNameString( vtempname, sizeof(vtempname) ); newentry->m_fragmentProg->GetComboIndexNameString( ptempname, sizeof(ptempname) ); printf("new [ %s + %s ]", vtempname, ptempname ); } m_mark = m_mark+1; if (!m_mark) // somewhat unlikely this will ever be reached.. but we need to avoid zero as a mark value { m_mark = 1; } result = newentry->m_pair; /* if (glm_cacheprograms.GetInt()) { WriteToProgramCache( newentry->m_pair ); } */ } return result; }