FRAGMENTSHADER* PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components) { PIXELSHADERUID uid; GetPixelShaderId(&uid, dstAlphaMode, components); // Check if the shader is already set if (last_entry) { if (uid == last_uid) { GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); ValidatePixelShaderIDs(API_OPENGL, last_entry->safe_uid, last_entry->shader.strprog, dstAlphaMode, components); return &last_entry->shader; } } last_uid = uid; PSCache::iterator iter = PixelShaders.find(uid); if (iter != PixelShaders.end()) { PSCacheEntry &entry = iter->second; last_entry = &entry; GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); ValidatePixelShaderIDs(API_OPENGL, entry.safe_uid, entry.shader.strprog, dstAlphaMode, components); return &last_entry->shader; } // Make an entry in the table PSCacheEntry& newentry = PixelShaders[uid]; last_entry = &newentry; const char *code = GeneratePixelShaderCode(dstAlphaMode, API_OPENGL, components); if (g_ActiveConfig.bEnableShaderDebugging && code) { GetSafePixelShaderId(&newentry.safe_uid, dstAlphaMode, components); newentry.shader.strprog = code; } #if defined(_DEBUG) || defined(DEBUGFAST) if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) { static int counter = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++); SaveData(szTemp, code); } #endif if (!code || !CompilePixelShader(newentry.shader, code)) { GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); return NULL; } INCSTAT(stats.numPixelShadersCreated); SETSTAT(stats.numPixelShadersAlive, PixelShaders.size()); GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); return &last_entry->shader; }
bool PixelShaderCache::SetShader(PSGRENDER_MODE PSGRenderMode, u32 components) { const API_TYPE api = ((D3D::GetCaps().PixelShaderVersion >> 8) & 0xFF) < 3 ? API_D3D9_SM20 : API_D3D9_SM30; PIXELSHADERUID uid; GetPixelShaderId(&uid, PSGRenderMode, components); // Check if the shader is already set if (last_entry) { if (uid == last_uid) { GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); ValidatePixelShaderIDs(api, last_entry->safe_uid, last_entry->code, PSGRenderMode, components); return last_entry->shader != NULL; } } last_uid = uid; // Check if the shader is already in the cache PSCache::iterator iter; iter = PixelShaders.find(uid); if (iter != PixelShaders.end()) { const PSCacheEntry &entry = iter->second; last_entry = &entry; if (entry.shader) D3D::SetPixelShader(entry.shader); GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); ValidatePixelShaderIDs(api, entry.safe_uid, entry.code, PSGRenderMode, components); return (entry.shader != NULL); } // Need to compile a new shader const char *code = GeneratePixelShaderCode(PSGRenderMode, api, components); if (g_ActiveConfig.bEnableShaderDebugging) { u32 code_hash = HashAdler32((const u8 *)code, strlen(code)); unique_shaders.insert(code_hash); SETSTAT(stats.numUniquePixelShaders, unique_shaders.size()); } #if defined(_DEBUG) || defined(DEBUGFAST) if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) { static int counter = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++); SaveData(szTemp, code); } #endif u8 *bytecode = 0; int bytecodelen = 0; if (!D3D::CompilePixelShader(code, (int)strlen(code), &bytecode, &bytecodelen)) { GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); return false; } // Insert the bytecode into the caches g_ps_disk_cache.Append(uid, bytecode, bytecodelen); // And insert it into the shader cache. bool success = InsertByteCode(uid, bytecode, bytecodelen, true); delete [] bytecode; if (g_ActiveConfig.bEnableShaderDebugging && success) { PixelShaders[uid].code = code; GetSafePixelShaderId(&PixelShaders[uid].safe_uid, PSGRenderMode, components); } GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); return success; }