1 // Copyright 2018 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4 
5 #pragma once
6 
7 #include <array>
8 #include <cstddef>
9 #include <cstring>
10 #include <map>
11 #include <memory>
12 #include <optional>
13 #include <string>
14 #include <unordered_map>
15 #include <utility>
16 
17 #include "Common/CommonTypes.h"
18 #include "Common/File.h"
19 #include "Common/LinearDiskCache.h"
20 
21 #include "VideoCommon/AbstractPipeline.h"
22 #include "VideoCommon/AbstractShader.h"
23 #include "VideoCommon/AsyncShaderCompiler.h"
24 #include "VideoCommon/GXPipelineTypes.h"
25 #include "VideoCommon/GeometryShaderGen.h"
26 #include "VideoCommon/PixelShaderGen.h"
27 #include "VideoCommon/RenderState.h"
28 #include "VideoCommon/TextureCacheBase.h"
29 #include "VideoCommon/TextureConversionShader.h"
30 #include "VideoCommon/TextureConverterShaderGen.h"
31 #include "VideoCommon/UberShaderPixel.h"
32 #include "VideoCommon/UberShaderVertex.h"
33 #include "VideoCommon/VertexShaderGen.h"
34 
35 class NativeVertexFormat;
36 enum class AbstractTextureFormat : u32;
37 enum class APIType;
38 enum class TextureFormat;
39 enum class TLUTFormat;
40 
41 namespace VideoCommon
42 {
43 class ShaderCache final
44 {
45 public:
46   ShaderCache();
47   ~ShaderCache();
48 
49   // Perform at startup, create descriptor layouts, compiles all static shaders.
50   bool Initialize();
51   void Shutdown();
52 
53   // Compiles/loads cached shaders.
54   void InitializeShaderCache();
55 
56   // Changes the shader host config. Shaders should be reloaded afterwards.
SetHostConfig(const ShaderHostConfig & host_config)57   void SetHostConfig(const ShaderHostConfig& host_config) { m_host_config = host_config; }
58 
59   // Reloads/recreates all shaders and pipelines.
60   void Reload();
61 
62   // Retrieves all pending shaders/pipelines from the async compiler.
63   void RetrieveAsyncShaders();
64 
65   // Accesses ShaderGen shader caches
66   const AbstractPipeline* GetPipelineForUid(const GXPipelineUid& uid);
67   const AbstractPipeline* GetUberPipelineForUid(const GXUberPipelineUid& uid);
68 
69   // Accesses ShaderGen shader caches asynchronously.
70   // The optional will be empty if this pipeline is now background compiling.
71   std::optional<const AbstractPipeline*> GetPipelineForUidAsync(const GXPipelineUid& uid);
72 
73   // Shared shaders
GetScreenQuadVertexShader()74   const AbstractShader* GetScreenQuadVertexShader() const
75   {
76     return m_screen_quad_vertex_shader.get();
77   }
GetTextureCopyVertexShader()78   const AbstractShader* GetTextureCopyVertexShader() const
79   {
80     return m_texture_copy_vertex_shader.get();
81   }
GetEFBCopyVertexShader()82   const AbstractShader* GetEFBCopyVertexShader() const { return m_efb_copy_vertex_shader.get(); }
GetTexcoordGeometryShader()83   const AbstractShader* GetTexcoordGeometryShader() const
84   {
85     return m_texcoord_geometry_shader.get();
86   }
GetTextureCopyPixelShader()87   const AbstractShader* GetTextureCopyPixelShader() const
88   {
89     return m_texture_copy_pixel_shader.get();
90   }
GetColorGeometryShader()91   const AbstractShader* GetColorGeometryShader() const { return m_color_geometry_shader.get(); }
GetColorPixelShader()92   const AbstractShader* GetColorPixelShader() const { return m_color_pixel_shader.get(); }
93 
94   // EFB copy to RAM/VRAM pipelines
95   const AbstractPipeline*
96   GetEFBCopyToVRAMPipeline(const TextureConversionShaderGen::TCShaderUid& uid);
97   const AbstractPipeline* GetEFBCopyToRAMPipeline(const EFBCopyParams& uid);
98 
99   // RGBA8 framebuffer copy pipelines
GetRGBA8CopyPipeline()100   const AbstractPipeline* GetRGBA8CopyPipeline() const { return m_copy_rgba8_pipeline.get(); }
GetRGBA8StereoCopyPipeline()101   const AbstractPipeline* GetRGBA8StereoCopyPipeline() const
102   {
103     return m_rgba8_stereo_copy_pipeline.get();
104   }
105 
106   // Palette texture conversion pipelines
107   const AbstractPipeline* GetPaletteConversionPipeline(TLUTFormat format);
108 
109   // Texture reinterpret pipelines
110   const AbstractPipeline* GetTextureReinterpretPipeline(TextureFormat from_format,
111                                                         TextureFormat to_format);
112 
113   // Texture decoding compute shaders
114   const AbstractShader* GetTextureDecodingShader(TextureFormat format, TLUTFormat palette_format);
115 
116 private:
117   static constexpr size_t NUM_PALETTE_CONVERSION_SHADERS = 3;
118 
119   void WaitForAsyncCompiler();
120   void LoadCaches();
121   void ClearCaches();
122   void LoadPipelineUIDCache();
123   void ClosePipelineUIDCache();
124   void CompileMissingPipelines();
125   void QueueUberShaderPipelines();
126   bool CompileSharedPipelines();
127 
128   // GX shader compiler methods
129   std::unique_ptr<AbstractShader> CompileVertexShader(const VertexShaderUid& uid) const;
130   std::unique_ptr<AbstractShader>
131   CompileVertexUberShader(const UberShader::VertexShaderUid& uid) const;
132   std::unique_ptr<AbstractShader> CompilePixelShader(const PixelShaderUid& uid) const;
133   std::unique_ptr<AbstractShader>
134   CompilePixelUberShader(const UberShader::PixelShaderUid& uid) const;
135   const AbstractShader* InsertVertexShader(const VertexShaderUid& uid,
136                                            std::unique_ptr<AbstractShader> shader);
137   const AbstractShader* InsertVertexUberShader(const UberShader::VertexShaderUid& uid,
138                                                std::unique_ptr<AbstractShader> shader);
139   const AbstractShader* InsertPixelShader(const PixelShaderUid& uid,
140                                           std::unique_ptr<AbstractShader> shader);
141   const AbstractShader* InsertPixelUberShader(const UberShader::PixelShaderUid& uid,
142                                               std::unique_ptr<AbstractShader> shader);
143   const AbstractShader* CreateGeometryShader(const GeometryShaderUid& uid);
144   bool NeedsGeometryShader(const GeometryShaderUid& uid) const;
145 
146   // Should we use geometry shaders for EFB copies?
147   bool UseGeometryShaderForEFBCopies() const;
148 
149   // GX pipeline compiler methods
150   AbstractPipelineConfig
151   GetGXPipelineConfig(const NativeVertexFormat* vertex_format, const AbstractShader* vertex_shader,
152                       const AbstractShader* geometry_shader, const AbstractShader* pixel_shader,
153                       const RasterizationState& rasterization_state, const DepthState& depth_state,
154                       const BlendingState& blending_state);
155   std::optional<AbstractPipelineConfig> GetGXPipelineConfig(const GXPipelineUid& uid);
156   std::optional<AbstractPipelineConfig> GetGXPipelineConfig(const GXUberPipelineUid& uid);
157   const AbstractPipeline* InsertGXPipeline(const GXPipelineUid& config,
158                                            std::unique_ptr<AbstractPipeline> pipeline);
159   const AbstractPipeline* InsertGXUberPipeline(const GXUberPipelineUid& config,
160                                                std::unique_ptr<AbstractPipeline> pipeline);
161   void AddSerializedGXPipelineUID(const SerializedGXPipelineUid& uid);
162   void AppendGXPipelineUID(const GXPipelineUid& config);
163 
164   // ASync Compiler Methods
165   void QueueVertexShaderCompile(const VertexShaderUid& uid, u32 priority);
166   void QueueVertexUberShaderCompile(const UberShader::VertexShaderUid& uid, u32 priority);
167   void QueuePixelShaderCompile(const PixelShaderUid& uid, u32 priority);
168   void QueuePixelUberShaderCompile(const UberShader::PixelShaderUid& uid, u32 priority);
169   void QueuePipelineCompile(const GXPipelineUid& uid, u32 priority);
170   void QueueUberPipelineCompile(const GXUberPipelineUid& uid, u32 priority);
171 
172   // Populating various caches.
173   template <ShaderStage stage, typename K, typename T>
174   void LoadShaderCache(T& cache, APIType api_type, const char* type, bool include_gameid);
175   template <typename T>
176   void ClearShaderCache(T& cache);
177   template <typename KeyType, typename DiskKeyType, typename T>
178   void LoadPipelineCache(T& cache, LinearDiskCache<DiskKeyType, u8>& disk_cache, APIType api_type,
179                          const char* type, bool include_gameid);
180   template <typename T, typename Y>
181   void ClearPipelineCache(T& cache, Y& disk_cache);
182 
183   // Priorities for compiling. The lower the value, the sooner the pipeline is compiled.
184   // The shader cache is compiled last, as it is the least likely to be required. On demand
185   // shaders are always compiled before pending ubershaders, as we want to use the ubershader
186   // for as few frames as possible, otherwise we risk framerate drops.
187   enum : u32
188   {
189     COMPILE_PRIORITY_ONDEMAND_PIPELINE = 100,
190     COMPILE_PRIORITY_UBERSHADER_PIPELINE = 200,
191     COMPILE_PRIORITY_SHADERCACHE_PIPELINE = 300
192   };
193 
194   // Configuration bits.
195   APIType m_api_type;
196   ShaderHostConfig m_host_config = {};
197   std::unique_ptr<AsyncShaderCompiler> m_async_shader_compiler;
198 
199   // Shared shaders
200   std::unique_ptr<AbstractShader> m_screen_quad_vertex_shader;
201   std::unique_ptr<AbstractShader> m_texture_copy_vertex_shader;
202   std::unique_ptr<AbstractShader> m_efb_copy_vertex_shader;
203   std::unique_ptr<AbstractShader> m_texcoord_geometry_shader;
204   std::unique_ptr<AbstractShader> m_color_geometry_shader;
205   std::unique_ptr<AbstractShader> m_texture_copy_pixel_shader;
206   std::unique_ptr<AbstractShader> m_color_pixel_shader;
207 
208   // GX Shader Caches
209   template <typename Uid>
210   struct ShaderModuleCache
211   {
212     struct Shader
213     {
214       std::unique_ptr<AbstractShader> shader;
215       bool pending;
216     };
217     std::map<Uid, Shader> shader_map;
218     LinearDiskCache<Uid, u8> disk_cache;
219   };
220   ShaderModuleCache<VertexShaderUid> m_vs_cache;
221   ShaderModuleCache<GeometryShaderUid> m_gs_cache;
222   ShaderModuleCache<PixelShaderUid> m_ps_cache;
223   ShaderModuleCache<UberShader::VertexShaderUid> m_uber_vs_cache;
224   ShaderModuleCache<UberShader::PixelShaderUid> m_uber_ps_cache;
225 
226   // GX Pipeline Caches - .first - pipeline, .second - pending
227   std::map<GXPipelineUid, std::pair<std::unique_ptr<AbstractPipeline>, bool>> m_gx_pipeline_cache;
228   std::map<GXUberPipelineUid, std::pair<std::unique_ptr<AbstractPipeline>, bool>>
229       m_gx_uber_pipeline_cache;
230   File::IOFile m_gx_pipeline_uid_cache_file;
231   LinearDiskCache<SerializedGXPipelineUid, u8> m_gx_pipeline_disk_cache;
232   LinearDiskCache<SerializedGXUberPipelineUid, u8> m_gx_uber_pipeline_disk_cache;
233 
234   // EFB copy to VRAM/RAM pipelines
235   std::map<TextureConversionShaderGen::TCShaderUid, std::unique_ptr<AbstractPipeline>>
236       m_efb_copy_to_vram_pipelines;
237   std::map<EFBCopyParams, std::unique_ptr<AbstractPipeline>> m_efb_copy_to_ram_pipelines;
238 
239   // Copy pipeline for RGBA8 textures
240   std::unique_ptr<AbstractPipeline> m_copy_rgba8_pipeline;
241   std::unique_ptr<AbstractPipeline> m_rgba8_stereo_copy_pipeline;
242 
243   // Palette conversion pipelines
244   std::array<std::unique_ptr<AbstractPipeline>, NUM_PALETTE_CONVERSION_SHADERS>
245       m_palette_conversion_pipelines;
246 
247   // Texture reinterpreting pipeline
248   std::map<std::pair<TextureFormat, TextureFormat>, std::unique_ptr<AbstractPipeline>>
249       m_texture_reinterpret_pipelines;
250 
251   // Texture decoding shaders
252   std::map<std::pair<u32, u32>, std::unique_ptr<AbstractShader>> m_texture_decoding_shaders;
253 };
254 
255 }  // namespace VideoCommon
256 
257 extern std::unique_ptr<VideoCommon::ShaderCache> g_shader_cache;
258