ShaderCache.cpp 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611
  1. // Copyright 2018 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "VideoCommon/ShaderCache.h"
  4. #include <fmt/format.h>
  5. #include "Common/Assert.h"
  6. #include "Common/FileUtil.h"
  7. #include "Common/MsgHandler.h"
  8. #include "Core/ConfigManager.h"
  9. #include "VideoCommon/AbstractGfx.h"
  10. #include "VideoCommon/ConstantManager.h"
  11. #include "VideoCommon/DriverDetails.h"
  12. #include "VideoCommon/FramebufferManager.h"
  13. #include "VideoCommon/FramebufferShaderGen.h"
  14. #include "VideoCommon/Present.h"
  15. #include "VideoCommon/Statistics.h"
  16. #include "VideoCommon/VertexLoaderManager.h"
  17. #include "VideoCommon/VertexManagerBase.h"
  18. #include "VideoCommon/VideoCommon.h"
  19. #include "VideoCommon/VideoConfig.h"
  20. #include <imgui.h>
  21. std::unique_ptr<VideoCommon::ShaderCache> g_shader_cache;
  22. namespace VideoCommon
  23. {
  24. ShaderCache::ShaderCache() : m_api_type{APIType::Nothing}
  25. {
  26. }
  27. ShaderCache::~ShaderCache()
  28. {
  29. ClearCaches();
  30. }
  31. bool ShaderCache::Initialize()
  32. {
  33. m_api_type = g_ActiveConfig.backend_info.api_type;
  34. m_host_config.bits = ShaderHostConfig::GetCurrent().bits;
  35. if (!CompileSharedPipelines())
  36. return false;
  37. m_async_shader_compiler = g_gfx->CreateAsyncShaderCompiler();
  38. m_frame_end_handler = AfterFrameEvent::Register([this](Core::System&) { RetrieveAsyncShaders(); },
  39. "RetrieveAsyncShaders");
  40. return true;
  41. }
  42. void ShaderCache::InitializeShaderCache()
  43. {
  44. m_async_shader_compiler->ResizeWorkerThreads(g_ActiveConfig.GetShaderPrecompilerThreads());
  45. // Load shader and UID caches.
  46. if (g_ActiveConfig.bShaderCache && m_api_type != APIType::Nothing)
  47. {
  48. LoadCaches();
  49. LoadPipelineUIDCache();
  50. }
  51. // Queue ubershader precompiling if required.
  52. if (g_ActiveConfig.UsingUberShaders())
  53. QueueUberShaderPipelines();
  54. // Compile all known UIDs.
  55. CompileMissingPipelines();
  56. if (g_ActiveConfig.bWaitForShadersBeforeStarting)
  57. WaitForAsyncCompiler();
  58. // Switch to the runtime shader compiler thread configuration.
  59. m_async_shader_compiler->ResizeWorkerThreads(g_ActiveConfig.GetShaderCompilerThreads());
  60. }
  61. void ShaderCache::Reload()
  62. {
  63. WaitForAsyncCompiler();
  64. ClosePipelineUIDCache();
  65. ClearCaches();
  66. if (!CompileSharedPipelines())
  67. PanicAlertFmt("Failed to compile shared pipelines after reload.");
  68. if (g_ActiveConfig.bShaderCache)
  69. LoadCaches();
  70. // Switch to the precompiling shader configuration while we rebuild.
  71. m_async_shader_compiler->ResizeWorkerThreads(g_ActiveConfig.GetShaderPrecompilerThreads());
  72. // We don't need to explicitly recompile the individual ubershaders here, as the pipelines
  73. // UIDs are still be in the map. Therefore, when these are rebuilt, the shaders will also
  74. // be recompiled.
  75. CompileMissingPipelines();
  76. if (g_ActiveConfig.bWaitForShadersBeforeStarting)
  77. WaitForAsyncCompiler();
  78. m_async_shader_compiler->ResizeWorkerThreads(g_ActiveConfig.GetShaderCompilerThreads());
  79. }
  80. void ShaderCache::RetrieveAsyncShaders()
  81. {
  82. m_async_shader_compiler->RetrieveWorkItems();
  83. }
  84. void ShaderCache::Shutdown()
  85. {
  86. // This may leave shaders uncommitted to the cache, but it's better than blocking shutdown
  87. // until everything has finished compiling.
  88. if (m_async_shader_compiler)
  89. m_async_shader_compiler->StopWorkerThreads();
  90. ClosePipelineUIDCache();
  91. }
  92. const AbstractPipeline* ShaderCache::GetPipelineForUid(const GXPipelineUid& uid)
  93. {
  94. auto it = m_gx_pipeline_cache.find(uid);
  95. if (it != m_gx_pipeline_cache.end() && !it->second.second)
  96. return it->second.first.get();
  97. const bool exists_in_cache = it != m_gx_pipeline_cache.end();
  98. std::unique_ptr<AbstractPipeline> pipeline;
  99. std::optional<AbstractPipelineConfig> pipeline_config = GetGXPipelineConfig(uid);
  100. if (pipeline_config)
  101. pipeline = g_gfx->CreatePipeline(*pipeline_config);
  102. if (g_ActiveConfig.bShaderCache && !exists_in_cache)
  103. AppendGXPipelineUID(uid);
  104. return InsertGXPipeline(uid, std::move(pipeline));
  105. }
  106. std::optional<const AbstractPipeline*> ShaderCache::GetPipelineForUidAsync(const GXPipelineUid& uid)
  107. {
  108. auto it = m_gx_pipeline_cache.find(uid);
  109. if (it != m_gx_pipeline_cache.end())
  110. {
  111. // .second is the pending flag, i.e. compiling in the background.
  112. if (!it->second.second)
  113. return it->second.first.get();
  114. else
  115. return {};
  116. }
  117. AppendGXPipelineUID(uid);
  118. QueuePipelineCompile(uid, COMPILE_PRIORITY_ONDEMAND_PIPELINE);
  119. return {};
  120. }
  121. const AbstractPipeline* ShaderCache::GetUberPipelineForUid(const GXUberPipelineUid& uid)
  122. {
  123. auto it = m_gx_uber_pipeline_cache.find(uid);
  124. if (it != m_gx_uber_pipeline_cache.end() && !it->second.second)
  125. return it->second.first.get();
  126. std::unique_ptr<AbstractPipeline> pipeline;
  127. std::optional<AbstractPipelineConfig> pipeline_config = GetGXPipelineConfig(uid);
  128. if (pipeline_config)
  129. pipeline = g_gfx->CreatePipeline(*pipeline_config);
  130. return InsertGXUberPipeline(uid, std::move(pipeline));
  131. }
  132. void ShaderCache::WaitForAsyncCompiler()
  133. {
  134. bool running = true;
  135. constexpr auto update_ui_progress = [](size_t completed, size_t total) {
  136. const float center_x = ImGui::GetIO().DisplaySize.x * 0.5f;
  137. const float center_y = ImGui::GetIO().DisplaySize.y * 0.5f;
  138. const float scale = ImGui::GetIO().DisplayFramebufferScale.x;
  139. ImGui::SetNextWindowSize(ImVec2(400.0f * scale, 50.0f * scale), ImGuiCond_Always);
  140. ImGui::SetNextWindowPos(ImVec2(center_x, center_y), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
  141. if (ImGui::Begin(Common::GetStringT("Compiling Shaders").c_str(), nullptr,
  142. ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs |
  143. ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings |
  144. ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoNav |
  145. ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing))
  146. {
  147. ImGui::Text("Compiling shaders: %zu/%zu", completed, total);
  148. ImGui::ProgressBar(static_cast<float>(completed) /
  149. static_cast<float>(std::max(total, static_cast<size_t>(1))),
  150. ImVec2(-1.0f, 0.0f), "");
  151. }
  152. ImGui::End();
  153. g_presenter->Present();
  154. };
  155. while (running &&
  156. (m_async_shader_compiler->HasPendingWork() || m_async_shader_compiler->HasCompletedWork()))
  157. {
  158. running = m_async_shader_compiler->WaitUntilCompletion(update_ui_progress);
  159. m_async_shader_compiler->RetrieveWorkItems();
  160. }
  161. // An extra Present to clear the screen
  162. g_presenter->Present();
  163. }
  164. template <typename SerializedUidType, typename UidType>
  165. static void SerializePipelineUid(const UidType& uid, SerializedUidType& serialized_uid)
  166. {
  167. // Convert to disk format. Ensure all padding bytes are zero.
  168. std::memset(reinterpret_cast<u8*>(&serialized_uid), 0, sizeof(serialized_uid));
  169. serialized_uid.vertex_decl = uid.vertex_format->GetVertexDeclaration();
  170. serialized_uid.vs_uid = uid.vs_uid;
  171. serialized_uid.gs_uid = uid.gs_uid;
  172. serialized_uid.ps_uid = uid.ps_uid;
  173. serialized_uid.rasterization_state_bits = uid.rasterization_state.hex;
  174. serialized_uid.depth_state_bits = uid.depth_state.hex;
  175. serialized_uid.blending_state_bits = uid.blending_state.hex;
  176. }
  177. template <typename UidType, typename SerializedUidType>
  178. static void UnserializePipelineUid(const SerializedUidType& uid, UidType& real_uid)
  179. {
  180. real_uid.vertex_format = VertexLoaderManager::GetOrCreateMatchingFormat(uid.vertex_decl);
  181. real_uid.vs_uid = uid.vs_uid;
  182. real_uid.gs_uid = uid.gs_uid;
  183. real_uid.ps_uid = uid.ps_uid;
  184. real_uid.rasterization_state.hex = uid.rasterization_state_bits;
  185. real_uid.depth_state.hex = uid.depth_state_bits;
  186. real_uid.blending_state.hex = uid.blending_state_bits;
  187. }
  188. template <ShaderStage stage, typename K, typename T>
  189. void ShaderCache::LoadShaderCache(T& cache, APIType api_type, const char* type, bool include_gameid)
  190. {
  191. class CacheReader : public Common::LinearDiskCacheReader<K, u8>
  192. {
  193. public:
  194. CacheReader(T& cache_) : cache(cache_) {}
  195. void Read(const K& key, const u8* value, u32 value_size) override
  196. {
  197. auto shader = g_gfx->CreateShaderFromBinary(stage, value, value_size);
  198. if (shader)
  199. {
  200. auto& entry = cache.shader_map[key];
  201. entry.shader = std::move(shader);
  202. entry.pending = false;
  203. switch (stage)
  204. {
  205. case ShaderStage::Vertex:
  206. INCSTAT(g_stats.num_vertex_shaders_created);
  207. INCSTAT(g_stats.num_vertex_shaders_alive);
  208. break;
  209. case ShaderStage::Pixel:
  210. INCSTAT(g_stats.num_pixel_shaders_created);
  211. INCSTAT(g_stats.num_pixel_shaders_alive);
  212. break;
  213. default:
  214. break;
  215. }
  216. }
  217. }
  218. private:
  219. T& cache;
  220. };
  221. std::string filename = GetDiskShaderCacheFileName(api_type, type, include_gameid, true);
  222. CacheReader reader(cache);
  223. u32 count = cache.disk_cache.OpenAndRead(filename, reader);
  224. INFO_LOG_FMT(VIDEO, "Loaded {} cached shaders from {}", count, filename);
  225. }
  226. template <typename T>
  227. void ShaderCache::ClearShaderCache(T& cache)
  228. {
  229. cache.disk_cache.Sync();
  230. cache.disk_cache.Close();
  231. cache.shader_map.clear();
  232. }
  233. template <typename KeyType, typename DiskKeyType, typename T>
  234. void ShaderCache::LoadPipelineCache(T& cache, Common::LinearDiskCache<DiskKeyType, u8>& disk_cache,
  235. APIType api_type, const char* type, bool include_gameid)
  236. {
  237. class CacheReader : public Common::LinearDiskCacheReader<DiskKeyType, u8>
  238. {
  239. public:
  240. CacheReader(ShaderCache* this_ptr_, T& cache_) : this_ptr(this_ptr_), cache(cache_) {}
  241. bool AnyFailed() const { return failed; }
  242. void Read(const DiskKeyType& key, const u8* value, u32 value_size) override
  243. {
  244. KeyType real_uid;
  245. UnserializePipelineUid(key, real_uid);
  246. // Skip those which are already compiled.
  247. if (failed || cache.contains(real_uid))
  248. return;
  249. auto config = this_ptr->GetGXPipelineConfig(real_uid);
  250. if (!config)
  251. return;
  252. auto pipeline = g_gfx->CreatePipeline(*config, value, value_size);
  253. if (!pipeline)
  254. {
  255. // If any of the pipelines fail to create, consider the cache stale.
  256. failed = true;
  257. return;
  258. }
  259. auto& entry = cache[real_uid];
  260. entry.first = std::move(pipeline);
  261. entry.second = false;
  262. }
  263. private:
  264. ShaderCache* this_ptr;
  265. T& cache;
  266. bool failed = false;
  267. };
  268. std::string filename = GetDiskShaderCacheFileName(api_type, type, include_gameid, true);
  269. CacheReader reader(this, cache);
  270. const u32 count = disk_cache.OpenAndRead(filename, reader);
  271. INFO_LOG_FMT(VIDEO, "Loaded {} cached pipelines from {}", count, filename);
  272. // If any of the pipelines in the cache failed to create, it's likely because of a change of
  273. // driver version, or system configuration. In this case, when the UID cache picks up the pipeline
  274. // later on, we'll write a duplicate entry to the pipeline cache. There's also no point in keeping
  275. // the old cache data around, so discard and recreate the disk cache.
  276. if (reader.AnyFailed())
  277. {
  278. WARN_LOG_FMT(VIDEO, "Failed to load one or more pipelines from cache '{}'. Discarding.",
  279. filename);
  280. disk_cache.Close();
  281. File::Delete(filename);
  282. disk_cache.OpenAndRead(filename, reader);
  283. }
  284. }
  285. template <typename T, typename Y>
  286. void ShaderCache::ClearPipelineCache(T& cache, Y& disk_cache)
  287. {
  288. disk_cache.Sync();
  289. disk_cache.Close();
  290. // Set the pending flag to false, and destroy the pipeline.
  291. for (auto& it : cache)
  292. {
  293. it.second.first.reset();
  294. it.second.second = false;
  295. }
  296. }
  297. void ShaderCache::LoadCaches()
  298. {
  299. // Ubershader caches, if present.
  300. if (g_ActiveConfig.backend_info.bSupportsShaderBinaries)
  301. {
  302. LoadShaderCache<ShaderStage::Vertex, UberShader::VertexShaderUid>(m_uber_vs_cache, m_api_type,
  303. "uber-vs", false);
  304. LoadShaderCache<ShaderStage::Pixel, UberShader::PixelShaderUid>(m_uber_ps_cache, m_api_type,
  305. "uber-ps", false);
  306. // We also share geometry shaders, as there aren't many variants.
  307. if (m_host_config.backend_geometry_shaders)
  308. LoadShaderCache<ShaderStage::Geometry, GeometryShaderUid>(m_gs_cache, m_api_type, "gs",
  309. false);
  310. // Specialized shaders, gameid-specific.
  311. LoadShaderCache<ShaderStage::Vertex, VertexShaderUid>(m_vs_cache, m_api_type, "specialized-vs",
  312. true);
  313. LoadShaderCache<ShaderStage::Pixel, PixelShaderUid>(m_ps_cache, m_api_type, "specialized-ps",
  314. true);
  315. }
  316. if (g_ActiveConfig.backend_info.bSupportsPipelineCacheData)
  317. {
  318. LoadPipelineCache<GXPipelineUid, SerializedGXPipelineUid>(
  319. m_gx_pipeline_cache, m_gx_pipeline_disk_cache, m_api_type, "specialized-pipeline", true);
  320. LoadPipelineCache<GXUberPipelineUid, SerializedGXUberPipelineUid>(
  321. m_gx_uber_pipeline_cache, m_gx_uber_pipeline_disk_cache, m_api_type, "uber-pipeline",
  322. false);
  323. }
  324. }
  325. void ShaderCache::ClearCaches()
  326. {
  327. ClearPipelineCache(m_gx_pipeline_cache, m_gx_pipeline_disk_cache);
  328. ClearShaderCache(m_vs_cache);
  329. ClearShaderCache(m_gs_cache);
  330. ClearShaderCache(m_ps_cache);
  331. ClearPipelineCache(m_gx_uber_pipeline_cache, m_gx_uber_pipeline_disk_cache);
  332. ClearShaderCache(m_uber_vs_cache);
  333. ClearShaderCache(m_uber_ps_cache);
  334. m_screen_quad_vertex_shader.reset();
  335. m_texture_copy_vertex_shader.reset();
  336. m_efb_copy_vertex_shader.reset();
  337. m_texcoord_geometry_shader.reset();
  338. m_color_geometry_shader.reset();
  339. m_texture_copy_pixel_shader.reset();
  340. m_color_pixel_shader.reset();
  341. m_efb_copy_to_vram_pipelines.clear();
  342. m_efb_copy_to_ram_pipelines.clear();
  343. m_copy_rgba8_pipeline.reset();
  344. m_rgba8_stereo_copy_pipeline.reset();
  345. for (auto& pipeline : m_palette_conversion_pipelines)
  346. pipeline.reset();
  347. m_texture_reinterpret_pipelines.clear();
  348. m_texture_decoding_shaders.clear();
  349. SETSTAT(g_stats.num_pixel_shaders_created, 0);
  350. SETSTAT(g_stats.num_pixel_shaders_alive, 0);
  351. SETSTAT(g_stats.num_vertex_shaders_created, 0);
  352. SETSTAT(g_stats.num_vertex_shaders_alive, 0);
  353. }
  354. void ShaderCache::CompileMissingPipelines()
  355. {
  356. // Queue all uids with a null pipeline for compilation.
  357. for (auto& it : m_gx_pipeline_cache)
  358. {
  359. if (!it.second.first)
  360. QueuePipelineCompile(it.first, COMPILE_PRIORITY_SHADERCACHE_PIPELINE);
  361. }
  362. for (auto& it : m_gx_uber_pipeline_cache)
  363. {
  364. if (!it.second.first)
  365. QueueUberPipelineCompile(it.first, COMPILE_PRIORITY_UBERSHADER_PIPELINE);
  366. }
  367. }
  368. std::unique_ptr<AbstractShader> ShaderCache::CompileVertexShader(const VertexShaderUid& uid) const
  369. {
  370. const ShaderCode source_code =
  371. GenerateVertexShaderCode(m_api_type, m_host_config, uid.GetUidData());
  372. return g_gfx->CreateShaderFromSource(ShaderStage::Vertex, source_code.GetBuffer());
  373. }
  374. std::unique_ptr<AbstractShader>
  375. ShaderCache::CompileVertexUberShader(const UberShader::VertexShaderUid& uid) const
  376. {
  377. const ShaderCode source_code =
  378. UberShader::GenVertexShader(m_api_type, m_host_config, uid.GetUidData());
  379. return g_gfx->CreateShaderFromSource(ShaderStage::Vertex, source_code.GetBuffer(),
  380. fmt::to_string(*uid.GetUidData()));
  381. }
  382. std::unique_ptr<AbstractShader> ShaderCache::CompilePixelShader(const PixelShaderUid& uid) const
  383. {
  384. const ShaderCode source_code =
  385. GeneratePixelShaderCode(m_api_type, m_host_config, uid.GetUidData(), {});
  386. return g_gfx->CreateShaderFromSource(ShaderStage::Pixel, source_code.GetBuffer());
  387. }
  388. std::unique_ptr<AbstractShader>
  389. ShaderCache::CompilePixelUberShader(const UberShader::PixelShaderUid& uid) const
  390. {
  391. const ShaderCode source_code =
  392. UberShader::GenPixelShader(m_api_type, m_host_config, uid.GetUidData(), {});
  393. return g_gfx->CreateShaderFromSource(ShaderStage::Pixel, source_code.GetBuffer(),
  394. fmt::to_string(*uid.GetUidData()));
  395. }
  396. const AbstractShader* ShaderCache::InsertVertexShader(const VertexShaderUid& uid,
  397. std::unique_ptr<AbstractShader> shader)
  398. {
  399. auto& entry = m_vs_cache.shader_map[uid];
  400. entry.pending = false;
  401. if (shader && !entry.shader)
  402. {
  403. if (g_ActiveConfig.bShaderCache && g_ActiveConfig.backend_info.bSupportsShaderBinaries)
  404. {
  405. auto binary = shader->GetBinary();
  406. if (!binary.empty())
  407. m_vs_cache.disk_cache.Append(uid, binary.data(), static_cast<u32>(binary.size()));
  408. }
  409. INCSTAT(g_stats.num_vertex_shaders_created);
  410. INCSTAT(g_stats.num_vertex_shaders_alive);
  411. entry.shader = std::move(shader);
  412. }
  413. return entry.shader.get();
  414. }
  415. const AbstractShader* ShaderCache::InsertVertexUberShader(const UberShader::VertexShaderUid& uid,
  416. std::unique_ptr<AbstractShader> shader)
  417. {
  418. auto& entry = m_uber_vs_cache.shader_map[uid];
  419. entry.pending = false;
  420. if (shader && !entry.shader)
  421. {
  422. if (g_ActiveConfig.bShaderCache && g_ActiveConfig.backend_info.bSupportsShaderBinaries)
  423. {
  424. auto binary = shader->GetBinary();
  425. if (!binary.empty())
  426. m_uber_vs_cache.disk_cache.Append(uid, binary.data(), static_cast<u32>(binary.size()));
  427. }
  428. INCSTAT(g_stats.num_vertex_shaders_created);
  429. INCSTAT(g_stats.num_vertex_shaders_alive);
  430. entry.shader = std::move(shader);
  431. }
  432. return entry.shader.get();
  433. }
  434. const AbstractShader* ShaderCache::InsertPixelShader(const PixelShaderUid& uid,
  435. std::unique_ptr<AbstractShader> shader)
  436. {
  437. auto& entry = m_ps_cache.shader_map[uid];
  438. entry.pending = false;
  439. if (shader && !entry.shader)
  440. {
  441. if (g_ActiveConfig.bShaderCache && g_ActiveConfig.backend_info.bSupportsShaderBinaries)
  442. {
  443. auto binary = shader->GetBinary();
  444. if (!binary.empty())
  445. m_ps_cache.disk_cache.Append(uid, binary.data(), static_cast<u32>(binary.size()));
  446. }
  447. INCSTAT(g_stats.num_pixel_shaders_created);
  448. INCSTAT(g_stats.num_pixel_shaders_alive);
  449. entry.shader = std::move(shader);
  450. }
  451. return entry.shader.get();
  452. }
  453. const AbstractShader* ShaderCache::InsertPixelUberShader(const UberShader::PixelShaderUid& uid,
  454. std::unique_ptr<AbstractShader> shader)
  455. {
  456. auto& entry = m_uber_ps_cache.shader_map[uid];
  457. entry.pending = false;
  458. if (shader && !entry.shader)
  459. {
  460. if (g_ActiveConfig.bShaderCache && g_ActiveConfig.backend_info.bSupportsShaderBinaries)
  461. {
  462. auto binary = shader->GetBinary();
  463. if (!binary.empty())
  464. m_uber_ps_cache.disk_cache.Append(uid, binary.data(), static_cast<u32>(binary.size()));
  465. }
  466. INCSTAT(g_stats.num_pixel_shaders_created);
  467. INCSTAT(g_stats.num_pixel_shaders_alive);
  468. entry.shader = std::move(shader);
  469. }
  470. return entry.shader.get();
  471. }
  472. const AbstractShader* ShaderCache::CreateGeometryShader(const GeometryShaderUid& uid)
  473. {
  474. const ShaderCode source_code =
  475. GenerateGeometryShaderCode(m_api_type, m_host_config, uid.GetUidData());
  476. std::unique_ptr<AbstractShader> shader =
  477. g_gfx->CreateShaderFromSource(ShaderStage::Geometry, source_code.GetBuffer(),
  478. fmt::format("Geometry shader: {}", *uid.GetUidData()));
  479. auto& entry = m_gs_cache.shader_map[uid];
  480. entry.pending = false;
  481. if (shader && !entry.shader)
  482. {
  483. if (g_ActiveConfig.bShaderCache && g_ActiveConfig.backend_info.bSupportsShaderBinaries)
  484. {
  485. auto binary = shader->GetBinary();
  486. if (!binary.empty())
  487. m_gs_cache.disk_cache.Append(uid, binary.data(), static_cast<u32>(binary.size()));
  488. }
  489. entry.shader = std::move(shader);
  490. }
  491. return entry.shader.get();
  492. }
  493. bool ShaderCache::NeedsGeometryShader(const GeometryShaderUid& uid) const
  494. {
  495. return m_host_config.backend_geometry_shaders && !uid.GetUidData()->IsPassthrough();
  496. }
  497. bool ShaderCache::UseGeometryShaderForEFBCopies() const
  498. {
  499. return m_host_config.backend_geometry_shaders && m_host_config.stereo;
  500. }
  501. AbstractPipelineConfig ShaderCache::GetGXPipelineConfig(
  502. const NativeVertexFormat* vertex_format, const AbstractShader* vertex_shader,
  503. const AbstractShader* geometry_shader, const AbstractShader* pixel_shader,
  504. const RasterizationState& rasterization_state, const DepthState& depth_state,
  505. const BlendingState& blending_state, AbstractPipelineUsage usage)
  506. {
  507. AbstractPipelineConfig config = {};
  508. config.usage = usage;
  509. config.vertex_format = vertex_format;
  510. config.vertex_shader = vertex_shader;
  511. config.geometry_shader = geometry_shader;
  512. config.pixel_shader = pixel_shader;
  513. config.rasterization_state = rasterization_state;
  514. config.depth_state = depth_state;
  515. config.blending_state = blending_state;
  516. config.framebuffer_state = g_framebuffer_manager->GetEFBFramebufferState();
  517. return config;
  518. }
  519. /// Edits the UID based on driver bugs and other special configurations
  520. static GXPipelineUid ApplyDriverBugs(const GXPipelineUid& in)
  521. {
  522. GXPipelineUid out;
  523. // TODO: static_assert(std::is_trivially_copyable_v<GXPipelineUid>);
  524. // GXPipelineUid is not trivially copyable because RasterizationState and BlendingState aren't
  525. // either, but we can pretend it is for now. This will be improved after PR #10848 is finished.
  526. memcpy(static_cast<void*>(&out), static_cast<const void*>(&in), sizeof(out)); // copy padding
  527. pixel_shader_uid_data* ps = out.ps_uid.GetUidData();
  528. BlendingState& blend = out.blending_state;
  529. if (ps->ztest == EmulatedZ::ForcedEarly && !out.depth_state.updateenable)
  530. {
  531. // No need to force early depth test if you're not writing z
  532. ps->ztest = EmulatedZ::Early;
  533. }
  534. // If framebuffer fetch is available, we can emulate logic ops in the fragment shader
  535. // and don't need the below blend approximation
  536. if (blend.logicopenable && !g_ActiveConfig.backend_info.bSupportsLogicOp &&
  537. !g_ActiveConfig.backend_info.bSupportsFramebufferFetch)
  538. {
  539. if (!blend.LogicOpApproximationIsExact())
  540. WARN_LOG_FMT(VIDEO,
  541. "Approximating logic op with blending, this will produce incorrect rendering.");
  542. if (blend.LogicOpApproximationWantsShaderHelp())
  543. {
  544. ps->emulate_logic_op_with_blend = true;
  545. ps->logic_op_mode = static_cast<u32>(blend.logicmode.Value());
  546. }
  547. blend.ApproximateLogicOpWithBlending();
  548. }
  549. const bool benefits_from_ps_dual_source_off =
  550. (!g_ActiveConfig.backend_info.bSupportsDualSourceBlend &&
  551. g_ActiveConfig.backend_info.bSupportsFramebufferFetch) ||
  552. DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING);
  553. if (benefits_from_ps_dual_source_off && !blend.RequiresDualSrc())
  554. {
  555. // Only use dual-source blending when required on drivers that don't support it very well.
  556. ps->no_dual_src = true;
  557. blend.usedualsrc = false;
  558. }
  559. if (g_ActiveConfig.backend_info.bSupportsFramebufferFetch)
  560. {
  561. bool fbfetch_blend = false;
  562. if ((DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DISCARD_WITH_EARLY_Z) ||
  563. !g_ActiveConfig.backend_info.bSupportsEarlyZ) &&
  564. ps->ztest == EmulatedZ::ForcedEarly)
  565. {
  566. ps->ztest = EmulatedZ::EarlyWithFBFetch;
  567. fbfetch_blend |= static_cast<bool>(out.blending_state.blendenable);
  568. ps->no_dual_src = true;
  569. }
  570. fbfetch_blend |= blend.logicopenable && !g_ActiveConfig.backend_info.bSupportsLogicOp;
  571. fbfetch_blend |= blend.usedualsrc && !g_ActiveConfig.backend_info.bSupportsDualSourceBlend;
  572. if (fbfetch_blend)
  573. {
  574. ps->no_dual_src = true;
  575. if (blend.logicopenable)
  576. {
  577. ps->logic_op_enable = true;
  578. ps->logic_op_mode = static_cast<u32>(blend.logicmode.Value());
  579. blend.logicopenable = false;
  580. }
  581. if (blend.blendenable)
  582. {
  583. ps->blend_enable = true;
  584. ps->blend_src_factor = blend.srcfactor;
  585. ps->blend_src_factor_alpha = blend.srcfactoralpha;
  586. ps->blend_dst_factor = blend.dstfactor;
  587. ps->blend_dst_factor_alpha = blend.dstfactoralpha;
  588. ps->blend_subtract = blend.subtract;
  589. ps->blend_subtract_alpha = blend.subtractAlpha;
  590. blend.blendenable = false;
  591. }
  592. }
  593. }
  594. // force dual src off if we can't support it
  595. if (!g_ActiveConfig.backend_info.bSupportsDualSourceBlend)
  596. {
  597. ps->no_dual_src = true;
  598. blend.usedualsrc = false;
  599. }
  600. if (ps->ztest == EmulatedZ::ForcedEarly && !g_ActiveConfig.backend_info.bSupportsEarlyZ)
  601. {
  602. // These things should be false
  603. ASSERT(!ps->zfreeze);
  604. // ZCOMPLOC HACK:
  605. // The only way to emulate alpha test + early-z is to force early-z in the shader.
  606. // As this isn't available on all drivers and as we can't emulate this feature otherwise,
  607. // we are only able to choose which one we want to respect more.
  608. // Tests seem to have proven that writing depth even when the alpha test fails is more
  609. // important that a reliable alpha test, so we just force the alpha test to always succeed.
  610. // At least this seems to be less buggy.
  611. ps->ztest = EmulatedZ::EarlyWithZComplocHack;
  612. }
  613. if (g_ActiveConfig.UseVSForLinePointExpand() &&
  614. (out.rasterization_state.primitive == PrimitiveType::Points ||
  615. out.rasterization_state.primitive == PrimitiveType::Lines))
  616. {
  617. // All primitives are expanded to triangles in the vertex shader
  618. vertex_shader_uid_data* vs = out.vs_uid.GetUidData();
  619. const PortableVertexDeclaration& decl = out.vertex_format->GetVertexDeclaration();
  620. vs->position_has_3_elems = decl.position.components >= 3;
  621. vs->texcoord_elem_count = 0;
  622. for (int i = 0; i < 8; i++)
  623. {
  624. if (decl.texcoords[i].enable)
  625. {
  626. ASSERT(decl.texcoords[i].components <= 3);
  627. vs->texcoord_elem_count |= decl.texcoords[i].components << (i * 2);
  628. }
  629. }
  630. out.vertex_format = nullptr;
  631. if (out.rasterization_state.primitive == PrimitiveType::Points)
  632. vs->vs_expand = VSExpand::Point;
  633. else
  634. vs->vs_expand = VSExpand::Line;
  635. PrimitiveType prim = g_ActiveConfig.backend_info.bSupportsPrimitiveRestart ?
  636. PrimitiveType::TriangleStrip :
  637. PrimitiveType::Triangles;
  638. out.rasterization_state.primitive = prim;
  639. out.gs_uid.GetUidData()->primitive_type = static_cast<u32>(prim);
  640. }
  641. return out;
  642. }
  643. std::optional<AbstractPipelineConfig>
  644. ShaderCache::GetGXPipelineConfig(const GXPipelineUid& config_in)
  645. {
  646. GXPipelineUid config = ApplyDriverBugs(config_in);
  647. const AbstractShader* vs;
  648. auto vs_iter = m_vs_cache.shader_map.find(config.vs_uid);
  649. if (vs_iter != m_vs_cache.shader_map.end() && !vs_iter->second.pending)
  650. vs = vs_iter->second.shader.get();
  651. else
  652. vs = InsertVertexShader(config.vs_uid, CompileVertexShader(config.vs_uid));
  653. PixelShaderUid ps_uid = config.ps_uid;
  654. ClearUnusedPixelShaderUidBits(m_api_type, m_host_config, &ps_uid);
  655. const AbstractShader* ps;
  656. auto ps_iter = m_ps_cache.shader_map.find(ps_uid);
  657. if (ps_iter != m_ps_cache.shader_map.end() && !ps_iter->second.pending)
  658. ps = ps_iter->second.shader.get();
  659. else
  660. ps = InsertPixelShader(ps_uid, CompilePixelShader(ps_uid));
  661. if (!vs || !ps)
  662. return {};
  663. const AbstractShader* gs = nullptr;
  664. if (NeedsGeometryShader(config.gs_uid))
  665. {
  666. auto gs_iter = m_gs_cache.shader_map.find(config.gs_uid);
  667. if (gs_iter != m_gs_cache.shader_map.end() && !gs_iter->second.pending)
  668. gs = gs_iter->second.shader.get();
  669. else
  670. gs = CreateGeometryShader(config.gs_uid);
  671. if (!gs)
  672. return {};
  673. }
  674. return GetGXPipelineConfig(config.vertex_format, vs, gs, ps, config.rasterization_state,
  675. config.depth_state, config.blending_state, AbstractPipelineUsage::GX);
  676. }
  677. /// Edits the UID based on driver bugs and other special configurations
  678. static GXUberPipelineUid ApplyDriverBugs(const GXUberPipelineUid& in)
  679. {
  680. GXUberPipelineUid out;
  681. // TODO: static_assert(std::is_trivially_copyable_v<GXUberPipelineUid>);
  682. // GXUberPipelineUid is not trivially copyable because RasterizationState and BlendingState aren't
  683. // either, but we can pretend it is for now. This will be improved after PR #10848 is finished.
  684. memcpy(static_cast<void*>(&out), static_cast<const void*>(&in), sizeof(out)); // Copy padding
  685. if (g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader)
  686. out.vertex_format = nullptr;
  687. // If framebuffer fetch is available, we can emulate logic ops in the fragment shader
  688. // and don't need the below blend approximation
  689. if (out.blending_state.logicopenable && !g_ActiveConfig.backend_info.bSupportsLogicOp &&
  690. !g_ActiveConfig.backend_info.bSupportsFramebufferFetch)
  691. {
  692. if (!out.blending_state.LogicOpApproximationIsExact())
  693. WARN_LOG_FMT(VIDEO,
  694. "Approximating logic op with blending, this will produce incorrect rendering.");
  695. out.blending_state.ApproximateLogicOpWithBlending();
  696. }
  697. if (g_ActiveConfig.backend_info.bSupportsFramebufferFetch)
  698. {
  699. // Always blend in shader
  700. out.blending_state.hex = 0;
  701. out.blending_state.colorupdate = in.blending_state.colorupdate.Value();
  702. out.blending_state.alphaupdate = in.blending_state.alphaupdate.Value();
  703. out.ps_uid.GetUidData()->no_dual_src = true;
  704. }
  705. else if (!g_ActiveConfig.backend_info.bSupportsDualSourceBlend ||
  706. (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING) &&
  707. !out.blending_state.RequiresDualSrc()))
  708. {
  709. out.blending_state.usedualsrc = false;
  710. out.ps_uid.GetUidData()->no_dual_src = true;
  711. }
  712. if (g_ActiveConfig.UseVSForLinePointExpand())
  713. {
  714. // All primitives are expanded to triangles in the vertex shader
  715. PrimitiveType prim = g_ActiveConfig.backend_info.bSupportsPrimitiveRestart ?
  716. PrimitiveType::TriangleStrip :
  717. PrimitiveType::Triangles;
  718. out.rasterization_state.primitive = prim;
  719. out.gs_uid.GetUidData()->primitive_type = static_cast<u32>(prim);
  720. }
  721. return out;
  722. }
  723. std::optional<AbstractPipelineConfig>
  724. ShaderCache::GetGXPipelineConfig(const GXUberPipelineUid& config_in)
  725. {
  726. GXUberPipelineUid config = ApplyDriverBugs(config_in);
  727. const AbstractShader* vs;
  728. auto vs_iter = m_uber_vs_cache.shader_map.find(config.vs_uid);
  729. if (vs_iter != m_uber_vs_cache.shader_map.end() && !vs_iter->second.pending)
  730. vs = vs_iter->second.shader.get();
  731. else
  732. vs = InsertVertexUberShader(config.vs_uid, CompileVertexUberShader(config.vs_uid));
  733. UberShader::PixelShaderUid ps_uid = config.ps_uid;
  734. UberShader::ClearUnusedPixelShaderUidBits(m_api_type, m_host_config, &ps_uid);
  735. const AbstractShader* ps;
  736. auto ps_iter = m_uber_ps_cache.shader_map.find(ps_uid);
  737. if (ps_iter != m_uber_ps_cache.shader_map.end() && !ps_iter->second.pending)
  738. ps = ps_iter->second.shader.get();
  739. else
  740. ps = InsertPixelUberShader(ps_uid, CompilePixelUberShader(ps_uid));
  741. if (!vs || !ps)
  742. return {};
  743. const AbstractShader* gs = nullptr;
  744. if (NeedsGeometryShader(config.gs_uid))
  745. {
  746. auto gs_iter = m_gs_cache.shader_map.find(config.gs_uid);
  747. if (gs_iter != m_gs_cache.shader_map.end() && !gs_iter->second.pending)
  748. gs = gs_iter->second.shader.get();
  749. else
  750. gs = CreateGeometryShader(config.gs_uid);
  751. if (!gs)
  752. return {};
  753. }
  754. return GetGXPipelineConfig(config.vertex_format, vs, gs, ps, config.rasterization_state,
  755. config.depth_state, config.blending_state,
  756. AbstractPipelineUsage::GXUber);
  757. }
  758. const AbstractPipeline* ShaderCache::InsertGXPipeline(const GXPipelineUid& config,
  759. std::unique_ptr<AbstractPipeline> pipeline)
  760. {
  761. auto& entry = m_gx_pipeline_cache[config];
  762. entry.second = false;
  763. if (!entry.first && pipeline)
  764. {
  765. entry.first = std::move(pipeline);
  766. if (g_ActiveConfig.bShaderCache)
  767. {
  768. auto cache_data = entry.first->GetCacheData();
  769. if (!cache_data.empty())
  770. {
  771. SerializedGXPipelineUid disk_uid;
  772. SerializePipelineUid(config, disk_uid);
  773. m_gx_pipeline_disk_cache.Append(disk_uid, cache_data.data(),
  774. static_cast<u32>(cache_data.size()));
  775. }
  776. }
  777. }
  778. return entry.first.get();
  779. }
  780. const AbstractPipeline*
  781. ShaderCache::InsertGXUberPipeline(const GXUberPipelineUid& config,
  782. std::unique_ptr<AbstractPipeline> pipeline)
  783. {
  784. auto& entry = m_gx_uber_pipeline_cache[config];
  785. entry.second = false;
  786. if (!entry.first && pipeline)
  787. {
  788. entry.first = std::move(pipeline);
  789. if (g_ActiveConfig.bShaderCache)
  790. {
  791. auto cache_data = entry.first->GetCacheData();
  792. if (!cache_data.empty())
  793. {
  794. SerializedGXUberPipelineUid disk_uid;
  795. SerializePipelineUid(config, disk_uid);
  796. m_gx_uber_pipeline_disk_cache.Append(disk_uid, cache_data.data(),
  797. static_cast<u32>(cache_data.size()));
  798. }
  799. }
  800. }
  801. return entry.first.get();
  802. }
  803. void ShaderCache::LoadPipelineUIDCache()
  804. {
  805. constexpr u32 CACHE_FILE_MAGIC = 0x44495550; // PUID
  806. constexpr size_t CACHE_HEADER_SIZE = sizeof(u32) + sizeof(u32);
  807. std::string filename =
  808. File::GetUserPath(D_CACHE_IDX) + SConfig::GetInstance().GetGameID() + ".uidcache";
  809. if (m_gx_pipeline_uid_cache_file.Open(filename, "rb+"))
  810. {
  811. // If an existing case exists, validate the version before reading entries.
  812. u32 existing_magic;
  813. u32 existing_version;
  814. bool uid_file_valid = false;
  815. if (m_gx_pipeline_uid_cache_file.ReadBytes(&existing_magic, sizeof(existing_magic)) &&
  816. m_gx_pipeline_uid_cache_file.ReadBytes(&existing_version, sizeof(existing_version)) &&
  817. existing_magic == CACHE_FILE_MAGIC && existing_version == GX_PIPELINE_UID_VERSION)
  818. {
  819. // Ensure the expected size matches the actual size of the file. If it doesn't, it means
  820. // the cache file may be corrupted, and we should not proceed with loading potentially
  821. // garbage or invalid UIDs.
  822. const u64 file_size = m_gx_pipeline_uid_cache_file.GetSize();
  823. const size_t uid_count =
  824. static_cast<size_t>(file_size - CACHE_HEADER_SIZE) / sizeof(SerializedGXPipelineUid);
  825. const size_t expected_size = uid_count * sizeof(SerializedGXPipelineUid) + CACHE_HEADER_SIZE;
  826. uid_file_valid = file_size == expected_size;
  827. if (uid_file_valid)
  828. {
  829. for (size_t i = 0; i < uid_count; i++)
  830. {
  831. SerializedGXPipelineUid serialized_uid;
  832. if (m_gx_pipeline_uid_cache_file.ReadBytes(&serialized_uid, sizeof(serialized_uid)))
  833. {
  834. // This just adds the pipeline to the map, it is compiled later.
  835. AddSerializedGXPipelineUID(serialized_uid);
  836. }
  837. else
  838. {
  839. uid_file_valid = false;
  840. break;
  841. }
  842. }
  843. }
  844. // We open the file for reading and writing, so we must seek to the end before writing.
  845. if (uid_file_valid)
  846. uid_file_valid = m_gx_pipeline_uid_cache_file.Seek(expected_size, File::SeekOrigin::Begin);
  847. }
  848. // If the file is invalid, close it. We re-open and truncate it below.
  849. if (!uid_file_valid)
  850. m_gx_pipeline_uid_cache_file.Close();
  851. }
  852. // If the file is not open, it means it was either corrupted or didn't exist.
  853. if (!m_gx_pipeline_uid_cache_file.IsOpen())
  854. {
  855. if (m_gx_pipeline_uid_cache_file.Open(filename, "wb"))
  856. {
  857. // Write the version identifier.
  858. m_gx_pipeline_uid_cache_file.WriteBytes(&CACHE_FILE_MAGIC, sizeof(GX_PIPELINE_UID_VERSION));
  859. m_gx_pipeline_uid_cache_file.WriteBytes(&GX_PIPELINE_UID_VERSION,
  860. sizeof(GX_PIPELINE_UID_VERSION));
  861. // Write any current UIDs out to the file.
  862. // This way, if we load a UID cache where the data was incomplete (e.g. Dolphin crashed),
  863. // we don't lose the existing UIDs which were previously at the beginning.
  864. for (const auto& it : m_gx_pipeline_cache)
  865. AppendGXPipelineUID(it.first);
  866. }
  867. }
  868. INFO_LOG_FMT(VIDEO, "Read {} pipeline UIDs from {}", m_gx_pipeline_cache.size(), filename);
  869. }
  870. void ShaderCache::ClosePipelineUIDCache()
  871. {
  872. // This is left as a method in case we need to append extra data to the file in the future.
  873. m_gx_pipeline_uid_cache_file.Close();
  874. }
  875. void ShaderCache::AddSerializedGXPipelineUID(const SerializedGXPipelineUid& uid)
  876. {
  877. GXPipelineUid real_uid;
  878. UnserializePipelineUid(uid, real_uid);
  879. auto iter = m_gx_pipeline_cache.find(real_uid);
  880. if (iter != m_gx_pipeline_cache.end())
  881. return;
  882. // Flag it as empty with a null pipeline object, for later compilation.
  883. auto& entry = m_gx_pipeline_cache[real_uid];
  884. entry.second = false;
  885. }
  886. void ShaderCache::AppendGXPipelineUID(const GXPipelineUid& config)
  887. {
  888. if (!m_gx_pipeline_uid_cache_file.IsOpen())
  889. return;
  890. SerializedGXPipelineUid disk_uid;
  891. SerializePipelineUid(config, disk_uid);
  892. if (!m_gx_pipeline_uid_cache_file.WriteBytes(&disk_uid, sizeof(disk_uid)))
  893. {
  894. WARN_LOG_FMT(VIDEO, "Writing pipeline UID to cache failed, closing file.");
  895. m_gx_pipeline_uid_cache_file.Close();
  896. }
  897. }
  898. void ShaderCache::QueueVertexShaderCompile(const VertexShaderUid& uid, u32 priority)
  899. {
  900. class VertexShaderWorkItem final : public AsyncShaderCompiler::WorkItem
  901. {
  902. public:
  903. VertexShaderWorkItem(ShaderCache* shader_cache_, const VertexShaderUid& uid_)
  904. : shader_cache(shader_cache_), uid(uid_)
  905. {
  906. }
  907. bool Compile() override
  908. {
  909. shader = shader_cache->CompileVertexShader(uid);
  910. return true;
  911. }
  912. void Retrieve() override { shader_cache->InsertVertexShader(uid, std::move(shader)); }
  913. private:
  914. ShaderCache* shader_cache;
  915. std::unique_ptr<AbstractShader> shader;
  916. VertexShaderUid uid;
  917. };
  918. m_vs_cache.shader_map[uid].pending = true;
  919. auto wi = m_async_shader_compiler->CreateWorkItem<VertexShaderWorkItem>(this, uid);
  920. m_async_shader_compiler->QueueWorkItem(std::move(wi), priority);
  921. }
  922. void ShaderCache::QueueVertexUberShaderCompile(const UberShader::VertexShaderUid& uid, u32 priority)
  923. {
  924. class VertexUberShaderWorkItem final : public AsyncShaderCompiler::WorkItem
  925. {
  926. public:
  927. VertexUberShaderWorkItem(ShaderCache* shader_cache_, const UberShader::VertexShaderUid& uid_)
  928. : shader_cache(shader_cache_), uid(uid_)
  929. {
  930. }
  931. bool Compile() override
  932. {
  933. shader = shader_cache->CompileVertexUberShader(uid);
  934. return true;
  935. }
  936. void Retrieve() override { shader_cache->InsertVertexUberShader(uid, std::move(shader)); }
  937. private:
  938. ShaderCache* shader_cache;
  939. std::unique_ptr<AbstractShader> shader;
  940. UberShader::VertexShaderUid uid;
  941. };
  942. m_uber_vs_cache.shader_map[uid].pending = true;
  943. auto wi = m_async_shader_compiler->CreateWorkItem<VertexUberShaderWorkItem>(this, uid);
  944. m_async_shader_compiler->QueueWorkItem(std::move(wi), priority);
  945. }
  946. void ShaderCache::QueuePixelShaderCompile(const PixelShaderUid& uid, u32 priority)
  947. {
  948. class PixelShaderWorkItem final : public AsyncShaderCompiler::WorkItem
  949. {
  950. public:
  951. PixelShaderWorkItem(ShaderCache* shader_cache_, const PixelShaderUid& uid_)
  952. : shader_cache(shader_cache_), uid(uid_)
  953. {
  954. }
  955. bool Compile() override
  956. {
  957. shader = shader_cache->CompilePixelShader(uid);
  958. return true;
  959. }
  960. void Retrieve() override { shader_cache->InsertPixelShader(uid, std::move(shader)); }
  961. private:
  962. ShaderCache* shader_cache;
  963. std::unique_ptr<AbstractShader> shader;
  964. PixelShaderUid uid;
  965. };
  966. m_ps_cache.shader_map[uid].pending = true;
  967. auto wi = m_async_shader_compiler->CreateWorkItem<PixelShaderWorkItem>(this, uid);
  968. m_async_shader_compiler->QueueWorkItem(std::move(wi), priority);
  969. }
  970. void ShaderCache::QueuePixelUberShaderCompile(const UberShader::PixelShaderUid& uid, u32 priority)
  971. {
  972. class PixelUberShaderWorkItem final : public AsyncShaderCompiler::WorkItem
  973. {
  974. public:
  975. PixelUberShaderWorkItem(ShaderCache* shader_cache_, const UberShader::PixelShaderUid& uid_)
  976. : shader_cache(shader_cache_), uid(uid_)
  977. {
  978. }
  979. bool Compile() override
  980. {
  981. shader = shader_cache->CompilePixelUberShader(uid);
  982. return true;
  983. }
  984. void Retrieve() override { shader_cache->InsertPixelUberShader(uid, std::move(shader)); }
  985. private:
  986. ShaderCache* shader_cache;
  987. std::unique_ptr<AbstractShader> shader;
  988. UberShader::PixelShaderUid uid;
  989. };
  990. m_uber_ps_cache.shader_map[uid].pending = true;
  991. auto wi = m_async_shader_compiler->CreateWorkItem<PixelUberShaderWorkItem>(this, uid);
  992. m_async_shader_compiler->QueueWorkItem(std::move(wi), priority);
  993. }
  994. void ShaderCache::QueuePipelineCompile(const GXPipelineUid& uid, u32 priority)
  995. {
  996. class PipelineWorkItem final : public AsyncShaderCompiler::WorkItem
  997. {
  998. public:
  999. PipelineWorkItem(ShaderCache* shader_cache_, const GXPipelineUid& uid_, u32 priority_)
  1000. : shader_cache(shader_cache_), uid(uid_), priority(priority_)
  1001. {
  1002. // Check if all the stages required for this pipeline have been compiled.
  1003. // If not, this work item becomes a no-op, and re-queues the pipeline for the next frame.
  1004. if (SetStagesReady())
  1005. config = shader_cache->GetGXPipelineConfig(uid);
  1006. }
  1007. bool SetStagesReady()
  1008. {
  1009. stages_ready = true;
  1010. GXPipelineUid actual_uid = ApplyDriverBugs(uid);
  1011. auto vs_it = shader_cache->m_vs_cache.shader_map.find(actual_uid.vs_uid);
  1012. stages_ready &= vs_it != shader_cache->m_vs_cache.shader_map.end() && !vs_it->second.pending;
  1013. if (vs_it == shader_cache->m_vs_cache.shader_map.end())
  1014. shader_cache->QueueVertexShaderCompile(actual_uid.vs_uid, priority);
  1015. PixelShaderUid ps_uid = actual_uid.ps_uid;
  1016. ClearUnusedPixelShaderUidBits(shader_cache->m_api_type, shader_cache->m_host_config, &ps_uid);
  1017. auto ps_it = shader_cache->m_ps_cache.shader_map.find(ps_uid);
  1018. stages_ready &= ps_it != shader_cache->m_ps_cache.shader_map.end() && !ps_it->second.pending;
  1019. if (ps_it == shader_cache->m_ps_cache.shader_map.end())
  1020. shader_cache->QueuePixelShaderCompile(ps_uid, priority);
  1021. return stages_ready;
  1022. }
  1023. bool Compile() override
  1024. {
  1025. if (config)
  1026. pipeline = g_gfx->CreatePipeline(*config);
  1027. return true;
  1028. }
  1029. void Retrieve() override
  1030. {
  1031. if (stages_ready)
  1032. {
  1033. shader_cache->InsertGXPipeline(uid, std::move(pipeline));
  1034. }
  1035. else
  1036. {
  1037. // Re-queue for next frame.
  1038. auto wi = shader_cache->m_async_shader_compiler->CreateWorkItem<PipelineWorkItem>(
  1039. shader_cache, uid, priority);
  1040. shader_cache->m_async_shader_compiler->QueueWorkItem(std::move(wi), priority);
  1041. }
  1042. }
  1043. private:
  1044. ShaderCache* shader_cache;
  1045. std::unique_ptr<AbstractPipeline> pipeline;
  1046. GXPipelineUid uid;
  1047. u32 priority;
  1048. std::optional<AbstractPipelineConfig> config;
  1049. bool stages_ready;
  1050. };
  1051. auto wi = m_async_shader_compiler->CreateWorkItem<PipelineWorkItem>(this, uid, priority);
  1052. m_async_shader_compiler->QueueWorkItem(std::move(wi), priority);
  1053. m_gx_pipeline_cache[uid].second = true;
  1054. }
  1055. void ShaderCache::QueueUberPipelineCompile(const GXUberPipelineUid& uid, u32 priority)
  1056. {
  1057. class UberPipelineWorkItem final : public AsyncShaderCompiler::WorkItem
  1058. {
  1059. public:
  1060. UberPipelineWorkItem(ShaderCache* shader_cache_, const GXUberPipelineUid& uid_, u32 priority_)
  1061. : shader_cache(shader_cache_), uid(uid_), priority(priority_)
  1062. {
  1063. // Check if all the stages required for this UberPipeline have been compiled.
  1064. // If not, this work item becomes a no-op, and re-queues the UberPipeline for the next frame.
  1065. if (SetStagesReady())
  1066. config = shader_cache->GetGXPipelineConfig(uid);
  1067. }
  1068. bool SetStagesReady()
  1069. {
  1070. stages_ready = true;
  1071. GXUberPipelineUid actual_uid = ApplyDriverBugs(uid);
  1072. auto vs_it = shader_cache->m_uber_vs_cache.shader_map.find(actual_uid.vs_uid);
  1073. stages_ready &=
  1074. vs_it != shader_cache->m_uber_vs_cache.shader_map.end() && !vs_it->second.pending;
  1075. if (vs_it == shader_cache->m_uber_vs_cache.shader_map.end())
  1076. shader_cache->QueueVertexUberShaderCompile(actual_uid.vs_uid, priority);
  1077. UberShader::PixelShaderUid ps_uid = actual_uid.ps_uid;
  1078. UberShader::ClearUnusedPixelShaderUidBits(shader_cache->m_api_type,
  1079. shader_cache->m_host_config, &ps_uid);
  1080. auto ps_it = shader_cache->m_uber_ps_cache.shader_map.find(ps_uid);
  1081. stages_ready &=
  1082. ps_it != shader_cache->m_uber_ps_cache.shader_map.end() && !ps_it->second.pending;
  1083. if (ps_it == shader_cache->m_uber_ps_cache.shader_map.end())
  1084. shader_cache->QueuePixelUberShaderCompile(ps_uid, priority);
  1085. return stages_ready;
  1086. }
  1087. bool Compile() override
  1088. {
  1089. if (config)
  1090. UberPipeline = g_gfx->CreatePipeline(*config);
  1091. return true;
  1092. }
  1093. void Retrieve() override
  1094. {
  1095. if (stages_ready)
  1096. {
  1097. shader_cache->InsertGXUberPipeline(uid, std::move(UberPipeline));
  1098. }
  1099. else
  1100. {
  1101. // Re-queue for next frame.
  1102. auto wi = shader_cache->m_async_shader_compiler->CreateWorkItem<UberPipelineWorkItem>(
  1103. shader_cache, uid, priority);
  1104. shader_cache->m_async_shader_compiler->QueueWorkItem(std::move(wi), priority);
  1105. }
  1106. }
  1107. private:
  1108. ShaderCache* shader_cache;
  1109. std::unique_ptr<AbstractPipeline> UberPipeline;
  1110. GXUberPipelineUid uid;
  1111. u32 priority;
  1112. std::optional<AbstractPipelineConfig> config;
  1113. bool stages_ready;
  1114. };
  1115. auto wi = m_async_shader_compiler->CreateWorkItem<UberPipelineWorkItem>(this, uid, priority);
  1116. m_async_shader_compiler->QueueWorkItem(std::move(wi), priority);
  1117. m_gx_uber_pipeline_cache[uid].second = true;
  1118. }
  1119. void ShaderCache::QueueUberShaderPipelines()
  1120. {
  1121. // Create a dummy vertex format with no attributes.
  1122. // All attributes will be enabled in GetUberVertexFormat.
  1123. PortableVertexDeclaration dummy_vertex_decl = {};
  1124. dummy_vertex_decl.position.components = 4;
  1125. dummy_vertex_decl.position.type = ComponentFormat::Float;
  1126. dummy_vertex_decl.position.enable = true;
  1127. dummy_vertex_decl.stride = sizeof(float) * 4;
  1128. NativeVertexFormat* dummy_vertex_format =
  1129. VertexLoaderManager::GetUberVertexFormat(dummy_vertex_decl);
  1130. auto QueueDummyPipeline =
  1131. [&](const UberShader::VertexShaderUid& vs_uid, const GeometryShaderUid& gs_uid,
  1132. const UberShader::PixelShaderUid& ps_uid, const BlendingState& blend) {
  1133. GXUberPipelineUid config;
  1134. config.vertex_format = dummy_vertex_format;
  1135. config.vs_uid = vs_uid;
  1136. config.gs_uid = gs_uid;
  1137. config.ps_uid = ps_uid;
  1138. config.rasterization_state = RenderState::GetCullBackFaceRasterizationState(
  1139. static_cast<PrimitiveType>(gs_uid.GetUidData()->primitive_type));
  1140. config.depth_state = RenderState::GetNoDepthTestingDepthState();
  1141. config.blending_state = blend;
  1142. if (ps_uid.GetUidData()->uint_output)
  1143. {
  1144. // uint_output is only ever enabled when logic ops are enabled.
  1145. config.blending_state.logicopenable = true;
  1146. config.blending_state.logicmode = LogicOp::And;
  1147. }
  1148. auto iter = m_gx_uber_pipeline_cache.find(config);
  1149. if (iter != m_gx_uber_pipeline_cache.end())
  1150. return;
  1151. auto& entry = m_gx_uber_pipeline_cache[config];
  1152. entry.second = false;
  1153. };
  1154. // Populate the pipeline configs with empty entries, these will be compiled afterwards.
  1155. UberShader::EnumerateVertexShaderUids([&](const UberShader::VertexShaderUid& vuid) {
  1156. UberShader::EnumeratePixelShaderUids([&](const UberShader::PixelShaderUid& puid) {
  1157. // UIDs must have compatible texgens, a mismatching combination will never be queried.
  1158. if (vuid.GetUidData()->num_texgens != puid.GetUidData()->num_texgens)
  1159. return;
  1160. UberShader::PixelShaderUid cleared_puid = puid;
  1161. UberShader::ClearUnusedPixelShaderUidBits(m_api_type, m_host_config, &cleared_puid);
  1162. EnumerateGeometryShaderUids([&](const GeometryShaderUid& guid) {
  1163. if (guid.GetUidData()->numTexGens != vuid.GetUidData()->num_texgens ||
  1164. (!guid.GetUidData()->IsPassthrough() && !m_host_config.backend_geometry_shaders))
  1165. {
  1166. return;
  1167. }
  1168. BlendingState blend = RenderState::GetNoBlendingBlendState();
  1169. QueueDummyPipeline(vuid, guid, cleared_puid, blend);
  1170. if (g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader)
  1171. {
  1172. // Not all GPUs need all the pipeline state compiled into shaders, so they tend to key
  1173. // compiled shaders based on some subset of the pipeline state.
  1174. // Some test results:
  1175. // (GPUs tested: AMD Radeon Pro 5600M, Nvidia GT 750M, Intel UHD 630,
  1176. // Intel Iris Pro 5200, Apple M1)
  1177. // MacOS Metal:
  1178. // - AMD, Nvidia, Intel GPUs: Shaders are keyed on vertex layout and whether or not
  1179. // dual source blend is enabled. That's it.
  1180. // - Apple GPUs: Shaders are keyed on vertex layout and all blending settings. We use
  1181. // framebuffer fetch here, so the only blending settings used by ubershaders are the
  1182. // alphaupdate and colorupdate ones. Also keyed on primitive type, but Metal supports
  1183. // setting it to "unknown" and we do for ubershaders (but MoltenVK won't).
  1184. // Windows Vulkan:
  1185. // - AMD, Nvidia: Definitely keyed on dual source blend, but the others seem more random
  1186. // Changing a setting on one shader will require a recompile, but changing the same
  1187. // setting on another won't. Compiling a copy with alphaupdate off, colorupdate off,
  1188. // and one with DSB on seems to get pretty good coverage though.
  1189. // Windows D3D12:
  1190. // - AMD: Keyed on dual source blend and vertex layout
  1191. // - Nvidia Kepler: No recompiles for changes to vertex layout or blend
  1192. blend.alphaupdate = false;
  1193. QueueDummyPipeline(vuid, guid, cleared_puid, blend);
  1194. blend.alphaupdate = true;
  1195. blend.colorupdate = false;
  1196. QueueDummyPipeline(vuid, guid, cleared_puid, blend);
  1197. blend.colorupdate = true;
  1198. if (!cleared_puid.GetUidData()->no_dual_src && !cleared_puid.GetUidData()->uint_output)
  1199. {
  1200. blend.blendenable = true;
  1201. blend.usedualsrc = true;
  1202. blend.srcfactor = SrcBlendFactor::SrcAlpha;
  1203. blend.dstfactor = DstBlendFactor::InvSrcAlpha;
  1204. QueueDummyPipeline(vuid, guid, cleared_puid, blend);
  1205. }
  1206. }
  1207. });
  1208. });
  1209. });
  1210. }
  1211. const AbstractPipeline*
  1212. ShaderCache::GetEFBCopyToVRAMPipeline(const TextureConversionShaderGen::TCShaderUid& uid)
  1213. {
  1214. auto iter = m_efb_copy_to_vram_pipelines.find(uid);
  1215. if (iter != m_efb_copy_to_vram_pipelines.end())
  1216. return iter->second.get();
  1217. auto shader_code = TextureConversionShaderGen::GeneratePixelShader(m_api_type, uid.GetUidData());
  1218. auto shader = g_gfx->CreateShaderFromSource(
  1219. ShaderStage::Pixel, shader_code.GetBuffer(),
  1220. fmt::format("EFB copy to VRAM pixel shader: {}", *uid.GetUidData()));
  1221. if (!shader)
  1222. {
  1223. m_efb_copy_to_vram_pipelines.emplace(uid, nullptr);
  1224. return nullptr;
  1225. }
  1226. AbstractPipelineConfig config = {};
  1227. config.vertex_format = nullptr;
  1228. config.vertex_shader = m_efb_copy_vertex_shader.get();
  1229. config.geometry_shader =
  1230. UseGeometryShaderForEFBCopies() ? m_texcoord_geometry_shader.get() : nullptr;
  1231. config.pixel_shader = shader.get();
  1232. config.rasterization_state = RenderState::GetNoCullRasterizationState(PrimitiveType::Triangles);
  1233. config.depth_state = RenderState::GetNoDepthTestingDepthState();
  1234. config.blending_state = RenderState::GetNoBlendingBlendState();
  1235. config.framebuffer_state = RenderState::GetRGBA8FramebufferState();
  1236. config.usage = AbstractPipelineUsage::Utility;
  1237. auto iiter = m_efb_copy_to_vram_pipelines.emplace(uid, g_gfx->CreatePipeline(config));
  1238. return iiter.first->second.get();
  1239. }
  1240. const AbstractPipeline* ShaderCache::GetEFBCopyToRAMPipeline(const EFBCopyParams& uid)
  1241. {
  1242. auto iter = m_efb_copy_to_ram_pipelines.find(uid);
  1243. if (iter != m_efb_copy_to_ram_pipelines.end())
  1244. return iter->second.get();
  1245. const std::string shader_code =
  1246. TextureConversionShaderTiled::GenerateEncodingShader(uid, m_api_type);
  1247. const auto shader = g_gfx->CreateShaderFromSource(
  1248. ShaderStage::Pixel, shader_code, fmt::format("EFB copy to RAM pixel shader: {}", uid));
  1249. if (!shader)
  1250. {
  1251. m_efb_copy_to_ram_pipelines.emplace(uid, nullptr);
  1252. return nullptr;
  1253. }
  1254. AbstractPipelineConfig config = {};
  1255. config.vertex_shader = m_screen_quad_vertex_shader.get();
  1256. config.pixel_shader = shader.get();
  1257. config.rasterization_state = RenderState::GetNoCullRasterizationState(PrimitiveType::Triangles);
  1258. config.depth_state = RenderState::GetNoDepthTestingDepthState();
  1259. config.blending_state = RenderState::GetNoBlendingBlendState();
  1260. config.framebuffer_state = RenderState::GetColorFramebufferState(AbstractTextureFormat::BGRA8);
  1261. config.usage = AbstractPipelineUsage::Utility;
  1262. auto iiter = m_efb_copy_to_ram_pipelines.emplace(uid, g_gfx->CreatePipeline(config));
  1263. return iiter.first->second.get();
  1264. }
  1265. bool ShaderCache::CompileSharedPipelines()
  1266. {
  1267. m_screen_quad_vertex_shader = g_gfx->CreateShaderFromSource(
  1268. ShaderStage::Vertex, FramebufferShaderGen::GenerateScreenQuadVertexShader(),
  1269. "Screen quad vertex shader");
  1270. m_texture_copy_vertex_shader = g_gfx->CreateShaderFromSource(
  1271. ShaderStage::Vertex, FramebufferShaderGen::GenerateTextureCopyVertexShader(),
  1272. "Texture copy vertex shader");
  1273. m_efb_copy_vertex_shader = g_gfx->CreateShaderFromSource(
  1274. ShaderStage::Vertex, TextureConversionShaderGen::GenerateVertexShader(m_api_type).GetBuffer(),
  1275. "EFB copy vertex shader");
  1276. if (!m_screen_quad_vertex_shader || !m_texture_copy_vertex_shader || !m_efb_copy_vertex_shader)
  1277. return false;
  1278. if (UseGeometryShaderForEFBCopies())
  1279. {
  1280. m_texcoord_geometry_shader = g_gfx->CreateShaderFromSource(
  1281. ShaderStage::Geometry, FramebufferShaderGen::GeneratePassthroughGeometryShader(1, 0),
  1282. "Texcoord passthrough geometry shader");
  1283. m_color_geometry_shader = g_gfx->CreateShaderFromSource(
  1284. ShaderStage::Geometry, FramebufferShaderGen::GeneratePassthroughGeometryShader(0, 1),
  1285. "Color passthrough geometry shader");
  1286. if (!m_texcoord_geometry_shader || !m_color_geometry_shader)
  1287. return false;
  1288. }
  1289. m_texture_copy_pixel_shader = g_gfx->CreateShaderFromSource(
  1290. ShaderStage::Pixel, FramebufferShaderGen::GenerateTextureCopyPixelShader(),
  1291. "Texture copy pixel shader");
  1292. m_color_pixel_shader = g_gfx->CreateShaderFromSource(
  1293. ShaderStage::Pixel, FramebufferShaderGen::GenerateColorPixelShader(), "Color pixel shader");
  1294. if (!m_texture_copy_pixel_shader || !m_color_pixel_shader)
  1295. return false;
  1296. AbstractPipelineConfig config;
  1297. config.vertex_format = nullptr;
  1298. config.vertex_shader = m_texture_copy_vertex_shader.get();
  1299. config.geometry_shader = nullptr;
  1300. config.pixel_shader = m_texture_copy_pixel_shader.get();
  1301. config.rasterization_state = RenderState::GetNoCullRasterizationState(PrimitiveType::Triangles);
  1302. config.depth_state = RenderState::GetNoDepthTestingDepthState();
  1303. config.blending_state = RenderState::GetNoBlendingBlendState();
  1304. config.framebuffer_state = RenderState::GetRGBA8FramebufferState();
  1305. config.usage = AbstractPipelineUsage::Utility;
  1306. m_copy_rgba8_pipeline = g_gfx->CreatePipeline(config);
  1307. if (!m_copy_rgba8_pipeline)
  1308. return false;
  1309. if (UseGeometryShaderForEFBCopies())
  1310. {
  1311. config.geometry_shader = m_texcoord_geometry_shader.get();
  1312. m_rgba8_stereo_copy_pipeline = g_gfx->CreatePipeline(config);
  1313. if (!m_rgba8_stereo_copy_pipeline)
  1314. return false;
  1315. }
  1316. if (m_host_config.backend_palette_conversion)
  1317. {
  1318. config.vertex_shader = m_screen_quad_vertex_shader.get();
  1319. config.geometry_shader = nullptr;
  1320. for (size_t i = 0; i < NUM_PALETTE_CONVERSION_SHADERS; i++)
  1321. {
  1322. TLUTFormat format = static_cast<TLUTFormat>(i);
  1323. auto shader = g_gfx->CreateShaderFromSource(
  1324. ShaderStage::Pixel,
  1325. TextureConversionShaderTiled::GeneratePaletteConversionShader(format, m_api_type),
  1326. fmt::format("Palette conversion pixel shader: {}", format));
  1327. if (!shader)
  1328. return false;
  1329. config.pixel_shader = shader.get();
  1330. m_palette_conversion_pipelines[i] = g_gfx->CreatePipeline(config);
  1331. if (!m_palette_conversion_pipelines[i])
  1332. return false;
  1333. }
  1334. }
  1335. return true;
  1336. }
  1337. const AbstractPipeline* ShaderCache::GetPaletteConversionPipeline(TLUTFormat format)
  1338. {
  1339. ASSERT(static_cast<size_t>(format) < NUM_PALETTE_CONVERSION_SHADERS);
  1340. return m_palette_conversion_pipelines[static_cast<size_t>(format)].get();
  1341. }
  1342. const AbstractPipeline* ShaderCache::GetTextureReinterpretPipeline(TextureFormat from_format,
  1343. TextureFormat to_format)
  1344. {
  1345. const auto key = std::make_pair(from_format, to_format);
  1346. auto iter = m_texture_reinterpret_pipelines.find(key);
  1347. if (iter != m_texture_reinterpret_pipelines.end())
  1348. return iter->second.get();
  1349. std::string shader_source =
  1350. FramebufferShaderGen::GenerateTextureReinterpretShader(from_format, to_format);
  1351. if (shader_source.empty())
  1352. {
  1353. m_texture_reinterpret_pipelines.emplace(key, nullptr);
  1354. return nullptr;
  1355. }
  1356. std::unique_ptr<AbstractShader> shader = g_gfx->CreateShaderFromSource(
  1357. ShaderStage::Pixel, shader_source,
  1358. fmt::format("Texture reinterpret pixel shader: {} to {}", from_format, to_format));
  1359. if (!shader)
  1360. {
  1361. m_texture_reinterpret_pipelines.emplace(key, nullptr);
  1362. return nullptr;
  1363. }
  1364. AbstractPipelineConfig config;
  1365. config.vertex_format = nullptr;
  1366. config.vertex_shader = m_screen_quad_vertex_shader.get();
  1367. config.geometry_shader = nullptr;
  1368. config.pixel_shader = shader.get();
  1369. config.rasterization_state = RenderState::GetNoCullRasterizationState(PrimitiveType::Triangles);
  1370. config.depth_state = RenderState::GetNoDepthTestingDepthState();
  1371. config.blending_state = RenderState::GetNoBlendingBlendState();
  1372. config.framebuffer_state = RenderState::GetRGBA8FramebufferState();
  1373. config.usage = AbstractPipelineUsage::Utility;
  1374. auto iiter = m_texture_reinterpret_pipelines.emplace(key, g_gfx->CreatePipeline(config));
  1375. return iiter.first->second.get();
  1376. }
  1377. const AbstractShader*
  1378. ShaderCache::GetTextureDecodingShader(TextureFormat format,
  1379. std::optional<TLUTFormat> palette_format)
  1380. {
  1381. const auto key = std::make_pair(static_cast<u32>(format),
  1382. static_cast<u32>(palette_format.value_or(TLUTFormat::IA8)));
  1383. const auto iter = m_texture_decoding_shaders.find(key);
  1384. if (iter != m_texture_decoding_shaders.end())
  1385. return iter->second.get();
  1386. const std::string shader_source =
  1387. TextureConversionShaderTiled::GenerateDecodingShader(format, palette_format, APIType::OpenGL);
  1388. if (shader_source.empty())
  1389. {
  1390. m_texture_decoding_shaders.emplace(key, nullptr);
  1391. return nullptr;
  1392. }
  1393. const std::string name =
  1394. palette_format.has_value() ?
  1395. fmt::format("Texture decoding compute shader: {}, {}", format, *palette_format) :
  1396. fmt::format("Texture decoding compute shader: {}", format);
  1397. std::unique_ptr<AbstractShader> shader =
  1398. g_gfx->CreateShaderFromSource(ShaderStage::Compute, shader_source, name);
  1399. if (!shader)
  1400. {
  1401. m_texture_decoding_shaders.emplace(key, nullptr);
  1402. return nullptr;
  1403. }
  1404. const auto iiter = m_texture_decoding_shaders.emplace(key, std::move(shader));
  1405. return iiter.first->second.get();
  1406. }
  1407. } // namespace VideoCommon