Optimize linked shader lookup in ApplyShader().

We already iterate all (skipping that with an if helps, though), and the
list of shaders in most games is pretty small.  Using a map is not gaining
much, and actually makes the whole thing slower.

Cuts from 9.84% time in Tales of Phantasia X (lots of flushes) to 1.85%.
This commit is contained in:
Unknown W. Brackets 2013-06-29 13:49:38 -07:00
parent 6ce949a743
commit 386d51081c
2 changed files with 28 additions and 18 deletions

View file

@ -433,13 +433,13 @@ void ShaderManager::DirtyUniform(u32 what) {
}
void ShaderManager::Clear() {
for (LinkedShaderCache::iterator iter = linkedShaderCache.begin(); iter != linkedShaderCache.end(); ++iter) {
for (auto iter = linkedShaderCache.begin(); iter != linkedShaderCache.end(); ++iter) {
delete iter->ls;
}
for (auto iter = fsCache.begin(); iter != fsCache.end(); ++iter) {
delete iter->second;
}
for (FSCache::iterator iter = fsCache.begin(); iter != fsCache.end(); ++iter) {
delete iter->second;
}
for (VSCache::iterator iter = vsCache.begin(); iter != vsCache.end(); ++iter) {
for (auto iter = vsCache.begin(); iter != vsCache.end(); ++iter) {
delete iter->second;
}
linkedShaderCache.clear();
@ -494,12 +494,6 @@ LinkedShader *ShaderManager::ApplyShader(int prim) {
lastShader->stop();
}
// Deferred dirtying! Let's see if we can make this even more clever later.
for (LinkedShaderCache::iterator iter = linkedShaderCache.begin(); iter != linkedShaderCache.end(); ++iter) {
iter->second->dirtyUniforms |= shaderSwitchDirty;
}
shaderSwitchDirty = 0;
lastVSID = VSID;
lastFSID = FSID;
@ -541,15 +535,23 @@ LinkedShader *ShaderManager::ApplyShader(int prim) {
}
// Okay, we have both shaders. Let's see if there's a linked one.
std::pair<Shader*, Shader*> linkedID(vs, fs);
LinkedShader *ls = NULL;
LinkedShaderCache::iterator iter = linkedShaderCache.find(linkedID);
LinkedShader *ls;
if (iter == linkedShaderCache.end()) {
for (auto iter = linkedShaderCache.begin(); iter != linkedShaderCache.end(); ++iter) {
// Deferred dirtying! Let's see if we can make this even more clever later.
iter->ls->dirtyUniforms |= shaderSwitchDirty;
if (iter->vs == vs && iter->fs == fs) {
ls = iter->ls;
}
}
shaderSwitchDirty = 0;
if (ls == NULL) {
ls = new LinkedShader(vs, fs, vs->UseHWTransform()); // This does "use" automatically
linkedShaderCache[linkedID] = ls;
const LinkedShaderCacheEntry entry(vs, fs, ls);
linkedShaderCache.push_back(entry);
} else {
ls = iter->second;
ls->use();
}

View file

@ -166,7 +166,15 @@ public:
private:
void Clear();
typedef std::map<std::pair<Shader *, Shader *>, LinkedShader *> LinkedShaderCache;
struct LinkedShaderCacheEntry {
LinkedShaderCacheEntry(Shader *vs_, Shader *fs_, LinkedShader *ls_)
: vs(vs_), fs(fs_), ls(ls_) { }
Shader *vs;
Shader *fs;
LinkedShader *ls;
};
typedef std::vector<LinkedShaderCacheEntry> LinkedShaderCache;
LinkedShaderCache linkedShaderCache;
FragmentShaderID lastFSID;