summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/FramebufferManager.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/VideoCommon/FramebufferManager.h')
-rw-r--r--Source/Core/VideoCommon/FramebufferManager.h171
1 files changed, 171 insertions, 0 deletions
diff --git a/Source/Core/VideoCommon/FramebufferManager.h b/Source/Core/VideoCommon/FramebufferManager.h
new file mode 100644
index 0000000000..d0de7b62b1
--- /dev/null
+++ b/Source/Core/VideoCommon/FramebufferManager.h
@@ -0,0 +1,171 @@
+// Copyright 2010 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+#include <memory>
+
+#include "Common/CommonTypes.h"
+#include "VideoCommon/AbstractTexture.h"
+#include "VideoCommon/RenderState.h"
+#include "VideoCommon/TextureConfig.h"
+
+class AbstractFramebuffer;
+class AbstractPipeline;
+class AbstractStagingTexture;
+class NativeVertexFormat;
+
+enum class EFBReinterpretType
+{
+ RGB8ToRGB565 = 0,
+ RGB8ToRGBA6 = 1,
+ RGBA6ToRGB8 = 2,
+ RGBA6ToRGB565 = 3,
+ RGB565ToRGB8 = 4,
+ RGB565ToRGBA6 = 5
+};
+constexpr u32 NUM_EFB_REINTERPRET_TYPES = 6;
+
+inline bool AddressRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
+{
+ return !((aLower >= bUpper) || (bLower >= aUpper));
+}
+
+class FramebufferManager final
+{
+public:
+ FramebufferManager();
+ virtual ~FramebufferManager();
+
+ // Does not require the framebuffer to be created. Slower than direct queries.
+ static AbstractTextureFormat GetEFBColorFormat();
+ static AbstractTextureFormat GetEFBDepthFormat();
+ static TextureConfig GetEFBColorTextureConfig();
+ static TextureConfig GetEFBDepthTextureConfig();
+
+ // Accessors.
+ AbstractTexture* GetEFBColorTexture() const { return m_efb_color_texture.get(); }
+ AbstractTexture* GetEFBDepthTexture() const { return m_efb_depth_texture.get(); }
+ AbstractFramebuffer* GetEFBFramebuffer() const { return m_efb_framebuffer.get(); }
+ u32 GetEFBWidth() const { return m_efb_color_texture->GetWidth(); }
+ u32 GetEFBHeight() const { return m_efb_color_texture->GetHeight(); }
+ u32 GetEFBLayers() const { return m_efb_color_texture->GetLayers(); }
+ u32 GetEFBSamples() const { return m_efb_color_texture->GetSamples(); }
+ bool IsEFBMultisampled() const { return m_efb_color_texture->IsMultisampled(); }
+ bool IsEFBStereo() const { return m_efb_color_texture->GetLayers() > 1; }
+ FramebufferState GetEFBFramebufferState() const;
+
+ // First-time setup.
+ bool Initialize();
+
+ // Recreate EFB framebuffers, call when the EFB size (IR) changes.
+ void RecreateEFBFramebuffer();
+
+ // Recompile shaders, use when MSAA mode changes.
+ void RecompileShaders();
+
+ // This is virtual, because D3D has both normalized and integer framebuffers.
+ void BindEFBFramebuffer();
+
+ // Resolve color/depth textures to a non-msaa texture, and return it.
+ AbstractTexture* ResolveEFBColorTexture(const MathUtil::Rectangle<int>& region);
+ AbstractTexture* ResolveEFBDepthTexture(const MathUtil::Rectangle<int>& region);
+
+ // Reinterpret pixel format of EFB color texture.
+ // Assumes no render pass is currently in progress.
+ // Swaps EFB framebuffers, so re-bind afterwards.
+ bool ReinterpretPixelData(EFBReinterpretType convtype);
+
+ // Clears the EFB using shaders.
+ void ClearEFB(const MathUtil::Rectangle<int>& rc, bool clear_color, bool clear_alpha,
+ bool clear_z, u32 color, u32 z);
+
+ // Reads a framebuffer value back from the GPU. This may block if the cache is not current.
+ u32 PeekEFBColor(u32 x, u32 y);
+ float PeekEFBDepth(u32 x, u32 y);
+ void InvalidatePeekCache();
+
+ // Writes a value to the framebuffer. This will never block, and writes will be batched.
+ void PokeEFBColor(u32 x, u32 y, u32 color);
+ void PokeEFBDepth(u32 x, u32 y, float depth);
+ void FlushEFBPokes();
+
+protected:
+ struct EFBPokeVertex
+ {
+ float position[4];
+ u32 color;
+ };
+ static_assert(std::is_standard_layout<EFBPokeVertex>::value, "EFBPokeVertex is standard-layout");
+
+ bool CreateEFBFramebuffer();
+ void DestroyEFBFramebuffer();
+
+ bool CompileConversionPipelines();
+ void DestroyConversionPipelines();
+
+ bool CompileReadbackPipelines();
+ void DestroyReadbackPipelines();
+
+ bool CreateReadbackFramebuffer();
+ void DestroyReadbackFramebuffer();
+
+ bool CompileClearPipelines();
+ void DestroyClearPipelines();
+
+ bool CompilePokePipelines();
+ void DestroyPokePipelines();
+
+ bool PopulateColorReadbackTexture();
+ bool PopulateDepthReadbackTexture();
+
+ void CreatePokeVertices(std::vector<EFBPokeVertex>* destination_list, u32 x, u32 y, float z,
+ u32 color);
+
+ void DrawPokeVertices(const EFBPokeVertex* vertices, u32 vertex_count,
+ const AbstractPipeline* pipeline);
+
+ std::unique_ptr<AbstractTexture> m_efb_color_texture;
+ std::unique_ptr<AbstractTexture> m_efb_convert_color_texture;
+ std::unique_ptr<AbstractTexture> m_efb_depth_texture;
+ std::unique_ptr<AbstractTexture> m_efb_resolve_color_texture;
+ std::unique_ptr<AbstractTexture> m_efb_depth_resolve_texture;
+
+ std::unique_ptr<AbstractFramebuffer> m_efb_framebuffer;
+ std::unique_ptr<AbstractFramebuffer> m_efb_convert_framebuffer;
+ std::unique_ptr<AbstractFramebuffer> m_efb_depth_resolve_framebuffer;
+ std::unique_ptr<AbstractPipeline> m_efb_depth_resolve_pipeline;
+
+ // Format conversion shaders
+ std::array<std::unique_ptr<AbstractPipeline>, 6> m_format_conversion_pipelines;
+
+ // EFB readback texture
+ std::unique_ptr<AbstractTexture> m_color_copy_texture;
+ std::unique_ptr<AbstractTexture> m_depth_copy_texture;
+ std::unique_ptr<AbstractFramebuffer> m_color_copy_framebuffer;
+ std::unique_ptr<AbstractFramebuffer> m_depth_copy_framebuffer;
+ std::unique_ptr<AbstractPipeline> m_color_copy_pipeline;
+ std::unique_ptr<AbstractPipeline> m_depth_copy_pipeline;
+
+ // CPU-side EFB readback texture
+ std::unique_ptr<AbstractStagingTexture> m_color_readback_texture;
+ std::unique_ptr<AbstractStagingTexture> m_depth_readback_texture;
+ bool m_color_readback_texture_valid = false;
+ bool m_depth_readback_texture_valid = false;
+
+ // EFB clear pipelines
+ // Indexed by [color_write_enabled][alpha_write_enabled][depth_write_enabled]
+ std::array<std::array<std::array<std::unique_ptr<AbstractPipeline>, 2>, 2>, 2>
+ m_efb_clear_pipelines;
+
+ // EFB poke drawing setup
+ std::unique_ptr<NativeVertexFormat> m_poke_vertex_format;
+ std::unique_ptr<AbstractPipeline> m_color_poke_pipeline;
+ std::unique_ptr<AbstractPipeline> m_depth_poke_pipeline;
+ std::vector<EFBPokeVertex> m_color_poke_vertices;
+ std::vector<EFBPokeVertex> m_depth_poke_vertices;
+};
+
+extern std::unique_ptr<FramebufferManager> g_framebuffer_manager;