// Copyright 2010 Dolphin Emulator Project // Licensed under GPLv2+ // Refer to the license.txt file included. #pragma once #include #include #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& region); AbstractTexture* ResolveEFBDepthTexture(const MathUtil::Rectangle& 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& 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::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* destination_list, u32 x, u32 y, float z, u32 color); void DrawPokeVertices(const EFBPokeVertex* vertices, u32 vertex_count, const AbstractPipeline* pipeline); std::unique_ptr m_efb_color_texture; std::unique_ptr m_efb_convert_color_texture; std::unique_ptr m_efb_depth_texture; std::unique_ptr m_efb_resolve_color_texture; std::unique_ptr m_efb_depth_resolve_texture; std::unique_ptr m_efb_framebuffer; std::unique_ptr m_efb_convert_framebuffer; std::unique_ptr m_efb_depth_resolve_framebuffer; std::unique_ptr m_efb_depth_resolve_pipeline; // Format conversion shaders std::array, 6> m_format_conversion_pipelines; // EFB readback texture std::unique_ptr m_color_copy_texture; std::unique_ptr m_depth_copy_texture; std::unique_ptr m_color_copy_framebuffer; std::unique_ptr m_depth_copy_framebuffer; std::unique_ptr m_color_copy_pipeline; std::unique_ptr m_depth_copy_pipeline; // CPU-side EFB readback texture std::unique_ptr m_color_readback_texture; std::unique_ptr 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, 2>, 2>, 2> m_efb_clear_pipelines; // EFB poke drawing setup std::unique_ptr m_poke_vertex_format; std::unique_ptr m_color_poke_pipeline; std::unique_ptr m_depth_poke_pipeline; std::vector m_color_poke_vertices; std::vector m_depth_poke_vertices; }; extern std::unique_ptr g_framebuffer_manager;