bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components) { PixelShaderUid uid; GetPixelShaderUid(uid, dstAlphaMode, API_D3D, components); if (g_ActiveConfig.bEnableShaderDebugging) { PixelShaderCode code; GeneratePixelShaderCode(code, dstAlphaMode, API_D3D, components); pixel_uid_checker.AddToIndexAndCheck(code, uid, "Pixel", "p"); } // Check if the shader is already set if (last_entry) { if (uid == last_uid) { GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true); return (last_entry->shader != nullptr); } } 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; GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true); return (entry.shader != nullptr); } // Need to compile a new shader PixelShaderCode code; GeneratePixelShaderCode(code, dstAlphaMode, API_D3D, components); D3DBlob* pbytecode; if (!D3D::CompilePixelShader(code.GetBuffer(), &pbytecode)) { GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); return false; } // Insert the bytecode into the caches g_ps_disk_cache.Append(uid, pbytecode->Data(), pbytecode->Size()); bool success = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size()); pbytecode->Release(); if (g_ActiveConfig.bEnableShaderDebugging && success) { PixelShaders[uid].code = code.GetBuffer(); } GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); return success; }
bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode) { PixelShaderUid uid = GetPixelShaderUid(dstAlphaMode, API_OPENGL); // Check if the shader is already set if (last_entry) { if (uid == last_uid) { return true; } } last_uid = uid; // Check if the shader is already in the cache PSCache::iterator iter; iter = PixelShaders.find(uid); if (iter != PixelShaders.end()) { const std::string &entry = iter->second; last_entry = &entry; GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true); return true; } // Need to compile a new shader ShaderCode code = GeneratePixelShaderCode(dstAlphaMode, API_OPENGL); PixelShaders.insert(std::make_pair(uid, code.GetBuffer())); GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); return true; }
void ShaderCache::HandlePSUIDChange(PixelShaderUid ps_uid, DSTALPHA_MODE ps_dst_alpha_mode) { s_last_pixel_shader_uid = ps_uid; auto ps_iterator = s_ps_bytecode_cache.find(ps_uid); if (ps_iterator != s_ps_bytecode_cache.end()) { s_last_pixel_shader_bytecode = ps_iterator->second; GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); } else { ShaderCode ps_code = GeneratePixelShaderCode(APIType::D3D, ps_uid.GetUidData()); ID3DBlob* ps_bytecode = nullptr; if (!D3D::CompilePixelShader(ps_code.GetBuffer(), &ps_bytecode)) { GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); return; } s_last_pixel_shader_bytecode = InsertByteCode(ps_uid, &s_ps_bytecode_cache, ps_bytecode); s_ps_disk_cache.Append(ps_uid, reinterpret_cast<u8*>(ps_bytecode->GetBufferPointer()), static_cast<u32>(ps_bytecode->GetBufferSize())); SETSTAT(stats.numPixelShadersAlive, static_cast<int>(s_ps_bytecode_cache.size())); INCSTAT(stats.numPixelShadersCreated); } }
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; }
void ProgramShaderCache::GetShaderId(SHADERUID* uid, DSTALPHA_MODE dstAlphaMode, u32 components) { GetPixelShaderUid(uid->puid, dstAlphaMode, API_OPENGL, components); GetVertexShaderUid(uid->vuid, components, API_OPENGL); if (g_ActiveConfig.bEnableShaderDebugging) { PixelShaderCode pcode; GeneratePixelShaderCode(pcode, dstAlphaMode, API_OPENGL, components); pixel_uid_checker.AddToIndexAndCheck(pcode, uid->puid, "Pixel", "p"); VertexShaderCode vcode; GenerateVertexShaderCode(vcode, components, API_OPENGL); vertex_uid_checker.AddToIndexAndCheck(vcode, uid->vuid, "Vertex", "v"); } }
bool PixelShaderCache::SetShader() { PixelShaderUid uid = GetPixelShaderUid(); // Check if the shader is already set if (last_entry) { if (uid == last_uid) { GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); return (last_entry->shader != nullptr); } } 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; GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); return (entry.shader != nullptr); } // Need to compile a new shader ShaderCode code = GeneratePixelShaderCode(APIType::D3D, uid.GetUidData()); D3DBlob* pbytecode; if (!D3D::CompilePixelShader(code.GetBuffer(), &pbytecode)) { GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); return false; } // Insert the bytecode into the caches g_ps_disk_cache.Append(uid, pbytecode->Data(), pbytecode->Size()); bool success = InsertByteCode(uid, pbytecode->Data(), pbytecode->Size()); pbytecode->Release(); GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); return success; }
SHADER* ProgramShaderCache::SetShader ( DSTALPHA_MODE dstAlphaMode, u32 components ) { SHADERUID uid; GetShaderId(&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); last_entry->shader.Bind(); return &last_entry->shader; } } last_uid = uid; // Check if shader is already in cache PCache::iterator iter = pshaders.find(uid); if (iter != pshaders.end()) { PCacheEntry *entry = &iter->second; last_entry = entry; GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); last_entry->shader.Bind(); return &last_entry->shader; } // Make an entry in the table PCacheEntry& newentry = pshaders[uid]; last_entry = &newentry; newentry.in_cache = 0; VertexShaderCode vcode; PixelShaderCode pcode; GenerateVertexShaderCode(vcode, components, API_OPENGL); GeneratePixelShaderCode(pcode, dstAlphaMode, API_OPENGL, components); if (g_ActiveConfig.bEnableShaderDebugging) { newentry.shader.strvprog = vcode.GetBuffer(); newentry.shader.strpprog = pcode.GetBuffer(); } #if defined(_DEBUG) || defined(DEBUGFAST) if (g_ActiveConfig.iLog & CONF_SAVESHADERS) { static int counter = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%svs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++); SaveData(szTemp, vcode.GetBuffer()); sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++); SaveData(szTemp, pcode.GetBuffer()); } #endif if (!CompileShader(newentry.shader, vcode.GetBuffer(), pcode.GetBuffer())) { GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); return NULL; } INCSTAT(stats.numPixelShadersCreated); SETSTAT(stats.numPixelShadersAlive, pshaders.size()); GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); last_entry->shader.Bind(); return &last_entry->shader; }
SHADER* ProgramShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components, u32 primitive_type) { SHADERUID uid; GetShaderId(&uid, dstAlphaMode, components, primitive_type); // Check if the shader is already set if (last_entry) { if (uid == last_uid) { GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); last_entry->shader.Bind(); return &last_entry->shader; } } last_uid = uid; // Check if shader is already in cache PCache::iterator iter = pshaders.find(uid); if (iter != pshaders.end()) { PCacheEntry *entry = &iter->second; last_entry = entry; GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); last_entry->shader.Bind(); return &last_entry->shader; } // Make an entry in the table PCacheEntry& newentry = pshaders[uid]; last_entry = &newentry; newentry.in_cache = 0; VertexShaderCode vcode; PixelShaderCode pcode; ShaderCode gcode; GenerateVertexShaderCode(vcode, components, API_OPENGL); GeneratePixelShaderCode(pcode, dstAlphaMode, API_OPENGL, components); if (g_ActiveConfig.backend_info.bSupportsGeometryShaders && !uid.guid.GetUidData()->IsPassthrough()) GenerateGeometryShaderCode(gcode, primitive_type, API_OPENGL); if (g_ActiveConfig.bEnableShaderDebugging) { newentry.shader.strvprog = vcode.GetBuffer(); newentry.shader.strpprog = pcode.GetBuffer(); newentry.shader.strgprog = gcode.GetBuffer(); } #if defined(_DEBUG) || defined(DEBUGFAST) if (g_ActiveConfig.iLog & CONF_SAVESHADERS) { static int counter = 0; std::string filename = StringFromFormat("%svs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++); SaveData(filename, vcode.GetBuffer()); filename = StringFromFormat("%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++); SaveData(filename, pcode.GetBuffer()); if (gcode.GetBuffer() != nullptr) { filename = StringFromFormat("%sgs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++); SaveData(filename, gcode.GetBuffer()); } } #endif if (!CompileShader(newentry.shader, vcode.GetBuffer(), pcode.GetBuffer(), gcode.GetBuffer())) { GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); return nullptr; } INCSTAT(stats.numPixelShadersCreated); SETSTAT(stats.numPixelShadersAlive, pshaders.size()); GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); last_entry->shader.Bind(); 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; }