FramebufferManager.h 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. // Copyright 2010 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <array>
  5. #include <memory>
  6. #include <optional>
  7. #include <tuple>
  8. #include "Common/CommonTypes.h"
  9. #include "Common/EnumFormatter.h"
  10. #include "VideoCommon/AbstractFramebuffer.h"
  11. #include "VideoCommon/AbstractPipeline.h"
  12. #include "VideoCommon/AbstractStagingTexture.h"
  13. #include "VideoCommon/AbstractTexture.h"
  14. #include "VideoCommon/RenderState.h"
  15. #include "VideoCommon/TextureConfig.h"
  16. #include "VideoCommon/VideoEvents.h"
  17. class NativeVertexFormat;
  18. class PointerWrap;
  19. enum class EFBReinterpretType
  20. {
  21. RGB8ToRGB565 = 0,
  22. RGB8ToRGBA6 = 1,
  23. RGBA6ToRGB8 = 2,
  24. RGBA6ToRGB565 = 3,
  25. RGB565ToRGB8 = 4,
  26. RGB565ToRGBA6 = 5
  27. };
  28. constexpr u32 NUM_EFB_REINTERPRET_TYPES = 6;
  29. template <>
  30. struct fmt::formatter<EFBReinterpretType> : EnumFormatter<EFBReinterpretType::RGB565ToRGBA6>
  31. {
  32. static constexpr array_type names = {"RGB8 to RGB565", "RGB8 to RGBA6", "RGBA6 to RGB8",
  33. "RGB6 to RGB565", "RGB565 to RGB8", "RGB565 to RGBA6"};
  34. constexpr formatter() : EnumFormatter(names) {}
  35. };
  36. inline bool AddressRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
  37. {
  38. return !((aLower >= bUpper) || (bLower >= aUpper));
  39. }
  40. class FramebufferManager final
  41. {
  42. public:
  43. FramebufferManager();
  44. virtual ~FramebufferManager();
  45. // Does not require the framebuffer to be created. Slower than direct queries.
  46. static AbstractTextureFormat GetEFBColorFormat();
  47. static AbstractTextureFormat GetEFBDepthFormat();
  48. static AbstractTextureFormat GetEFBDepthCopyFormat();
  49. static TextureConfig GetEFBColorTextureConfig(u32 width, u32 height);
  50. static TextureConfig GetEFBDepthTextureConfig(u32 width, u32 height);
  51. // Accessors.
  52. AbstractTexture* GetEFBColorTexture() const { return m_efb_color_texture.get(); }
  53. AbstractTexture* GetEFBDepthTexture() const { return m_efb_depth_texture.get(); }
  54. AbstractFramebuffer* GetEFBFramebuffer() const { return m_efb_framebuffer.get(); }
  55. u32 GetEFBWidth() const { return m_efb_color_texture->GetWidth(); }
  56. u32 GetEFBHeight() const { return m_efb_color_texture->GetHeight(); }
  57. u32 GetEFBLayers() const { return m_efb_color_texture->GetLayers(); }
  58. u32 GetEFBSamples() const { return m_efb_color_texture->GetSamples(); }
  59. bool IsEFBMultisampled() const { return m_efb_color_texture->IsMultisampled(); }
  60. bool IsEFBStereo() const { return m_efb_color_texture->GetLayers() > 1; }
  61. FramebufferState GetEFBFramebufferState() const;
  62. // EFB coordinate conversion functions
  63. // Use this to convert a whole native EFB rect to backbuffer coordinates
  64. MathUtil::Rectangle<int> ConvertEFBRectangle(const MathUtil::Rectangle<int>& rc) const;
  65. unsigned int GetEFBScale() const;
  66. // Use this to upscale native EFB coordinates to IDEAL internal resolution
  67. int EFBToScaledX(int x) const;
  68. int EFBToScaledY(int y) const;
  69. // Floating point versions of the above - only use them if really necessary
  70. float EFBToScaledXf(float x) const;
  71. float EFBToScaledYf(float y) const;
  72. // First-time setup.
  73. bool Initialize();
  74. // Recreate EFB framebuffers, call when the EFB size (IR) changes.
  75. void RecreateEFBFramebuffer();
  76. // Recompile shaders, use when MSAA mode changes.
  77. void RecompileShaders();
  78. // This is virtual, because D3D has both normalized and integer framebuffers.
  79. void BindEFBFramebuffer();
  80. // Resolve color/depth textures to a non-msaa texture, and return it.
  81. AbstractTexture* ResolveEFBColorTexture(const MathUtil::Rectangle<int>& region);
  82. AbstractTexture* ResolveEFBDepthTexture(const MathUtil::Rectangle<int>& region,
  83. bool force_r32f = false);
  84. // Reinterpret pixel format of EFB color texture.
  85. // Assumes no render pass is currently in progress.
  86. // Swaps EFB framebuffers, so re-bind afterwards.
  87. bool ReinterpretPixelData(EFBReinterpretType convtype);
  88. PixelFormat GetPrevPixelFormat() const { return m_prev_efb_format; }
  89. void StorePixelFormat(PixelFormat new_format) { m_prev_efb_format = new_format; }
  90. // Clears the EFB using shaders.
  91. void ClearEFB(const MathUtil::Rectangle<int>& rc, bool clear_color, bool clear_alpha,
  92. bool clear_z, u32 color, u32 z);
  93. AbstractPipeline* GetClearPipeline(bool clear_color, bool clear_alpha, bool clear_z) const;
  94. // Reads a framebuffer value back from the GPU. This may block if the cache is not current.
  95. u32 PeekEFBColor(u32 x, u32 y);
  96. float PeekEFBDepth(u32 x, u32 y);
  97. void SetEFBCacheTileSize(u32 size);
  98. void InvalidatePeekCache(bool forced = true);
  99. void RefreshPeekCache();
  100. void FlagPeekCacheAsOutOfDate();
  101. void EndOfFrame();
  102. // Writes a value to the framebuffer. This will never block, and writes will be batched.
  103. void PokeEFBColor(u32 x, u32 y, u32 color);
  104. void PokeEFBDepth(u32 x, u32 y, float depth);
  105. void FlushEFBPokes();
  106. // Save state load/save.
  107. void DoState(PointerWrap& p);
  108. protected:
  109. struct EFBPokeVertex
  110. {
  111. float position[4];
  112. u32 color;
  113. };
  114. static_assert(std::is_standard_layout<EFBPokeVertex>::value, "EFBPokeVertex is standard-layout");
  115. struct EFBCacheTile
  116. {
  117. bool present;
  118. u8 frame_access_mask;
  119. };
  120. // EFB cache - for CPU EFB access
  121. // Tiles are ordered left-to-right, then top-to-bottom
  122. struct EFBCacheData
  123. {
  124. std::unique_ptr<AbstractTexture> texture;
  125. std::unique_ptr<AbstractFramebuffer> framebuffer;
  126. std::unique_ptr<AbstractStagingTexture> readback_texture;
  127. std::unique_ptr<AbstractPipeline> copy_pipeline;
  128. std::vector<EFBCacheTile> tiles;
  129. bool out_of_date;
  130. bool has_active_tiles;
  131. bool needs_refresh;
  132. bool needs_flush;
  133. };
  134. bool CreateEFBFramebuffer();
  135. void DestroyEFBFramebuffer();
  136. bool CompileConversionPipelines();
  137. void DestroyConversionPipelines();
  138. bool CompileReadbackPipelines();
  139. void DestroyReadbackPipelines();
  140. bool CreateReadbackFramebuffer();
  141. void DestroyReadbackFramebuffer();
  142. bool CompileClearPipelines();
  143. void DestroyClearPipelines();
  144. bool CompilePokePipelines();
  145. void DestroyPokePipelines();
  146. bool IsUsingTiledEFBCache() const;
  147. bool IsEFBCacheTilePresent(bool depth, u32 x, u32 y, u32* tile_index) const;
  148. MathUtil::Rectangle<int> GetEFBCacheTileRect(u32 tile_index) const;
  149. void PopulateEFBCache(bool depth, u32 tile_index, bool async = false);
  150. void CreatePokeVertices(std::vector<EFBPokeVertex>* destination_list, u32 x, u32 y, float z,
  151. u32 color);
  152. void DrawPokeVertices(const EFBPokeVertex* vertices, u32 vertex_count,
  153. const AbstractPipeline* pipeline);
  154. std::tuple<u32, u32> CalculateTargetSize();
  155. void DoLoadState(PointerWrap& p);
  156. void DoSaveState(PointerWrap& p);
  157. float m_efb_scale = 1.0f;
  158. PixelFormat m_prev_efb_format;
  159. std::unique_ptr<AbstractTexture> m_efb_color_texture;
  160. std::unique_ptr<AbstractTexture> m_efb_convert_color_texture;
  161. std::unique_ptr<AbstractTexture> m_efb_depth_texture;
  162. std::unique_ptr<AbstractTexture> m_efb_resolve_color_texture;
  163. std::unique_ptr<AbstractTexture> m_efb_depth_resolve_texture;
  164. std::unique_ptr<AbstractFramebuffer> m_efb_framebuffer;
  165. std::unique_ptr<AbstractFramebuffer> m_efb_convert_framebuffer;
  166. std::unique_ptr<AbstractFramebuffer> m_efb_color_resolve_framebuffer;
  167. std::unique_ptr<AbstractFramebuffer> m_efb_depth_resolve_framebuffer;
  168. std::unique_ptr<AbstractPipeline> m_efb_color_resolve_pipeline;
  169. std::unique_ptr<AbstractPipeline> m_efb_depth_resolve_pipeline;
  170. // Pipeline for restoring the contents of the EFB from a save state
  171. std::unique_ptr<AbstractPipeline> m_efb_restore_pipeline;
  172. // Format conversion shaders
  173. std::array<std::unique_ptr<AbstractPipeline>, 6> m_format_conversion_pipelines;
  174. // EFB cache - for CPU EFB access (EFB peeks/pokes), not for EFB copies
  175. // Width and height of a tile in pixels at 1x IR. 0 indicates non-tiled, in which case a single
  176. // tile is used for the entire EFB.
  177. // Note that as EFB peeks and pokes are a CPU feature, they always operate at 1x IR.
  178. u32 m_efb_cache_tile_size = 0;
  179. // Number of tiles that make up a row in m_efb_color_cache.tiles / m_efb_depth_cache.tiles.
  180. u32 m_efb_cache_tile_row_stride = 1;
  181. EFBCacheData m_efb_color_cache = {};
  182. EFBCacheData m_efb_depth_cache = {};
  183. // EFB clear pipelines
  184. // Indexed by [color_write_enabled][alpha_write_enabled][depth_write_enabled]
  185. std::array<std::array<std::array<std::unique_ptr<AbstractPipeline>, 2>, 2>, 2> m_clear_pipelines;
  186. // EFB poke drawing setup
  187. std::unique_ptr<NativeVertexFormat> m_poke_vertex_format;
  188. std::unique_ptr<AbstractPipeline> m_color_poke_pipeline;
  189. std::unique_ptr<AbstractPipeline> m_depth_poke_pipeline;
  190. std::vector<EFBPokeVertex> m_color_poke_vertices;
  191. std::vector<EFBPokeVertex> m_depth_poke_vertices;
  192. Common::EventHook m_end_of_frame_event;
  193. };
  194. extern std::unique_ptr<FramebufferManager> g_framebuffer_manager;