// Copyright 2016 Dolphin Emulator Project // Licensed under GPLv2+ // Refer to the license.txt file included. #pragma once #include #include "Common/CommonTypes.h" #include "VideoBackends/Vulkan/Constants.h" #include "VideoBackends/Vulkan/TextureCache.h" #include "VideoCommon/FramebufferManagerBase.h" namespace Vulkan { class StagingTexture2D; class StateTracker; class StreamBuffer; class Texture2D; class VertexFormat; class XFBSource; class FramebufferManager : public FramebufferManagerBase { public: FramebufferManager(); ~FramebufferManager(); static FramebufferManager* GetInstance(); bool Initialize(); VkRenderPass GetEFBLoadRenderPass() const { return m_efb_load_render_pass; } VkRenderPass GetEFBClearRenderPass() const { return m_efb_clear_render_pass; } u32 GetEFBWidth() const { return m_efb_width; } u32 GetEFBHeight() const { return m_efb_height; } u32 GetEFBLayers() const { return m_efb_layers; } VkSampleCountFlagBits GetEFBSamples() const { return m_efb_samples; } Texture2D* GetEFBColorTexture() const { return m_efb_color_texture.get(); } Texture2D* GetEFBDepthTexture() const { return m_efb_depth_texture.get(); } VkFramebuffer GetEFBFramebuffer() const { return m_efb_framebuffer; } void GetTargetSize(unsigned int* width, unsigned int* height) override; std::unique_ptr CreateXFBSource(unsigned int target_width, unsigned int target_height, unsigned int layers) override; // GPU EFB textures -> Guest void CopyToRealXFB(u32 xfb_addr, u32 fb_stride, u32 fb_height, const EFBRectangle& source_rc, float gamma = 1.0f) override; void ResizeEFBTextures(); // Recompile shaders, use when MSAA mode changes. void RecreateRenderPass(); void RecompileShaders(); // Reinterpret pixel format of EFB color texture. // Assumes no render pass is currently in progress. // Swaps EFB framebuffers, so re-bind afterwards. void ReinterpretPixelData(int convtype); // This render pass can be used for other readback operations. VkRenderPass GetColorCopyForReadbackRenderPass() const { return m_copy_color_render_pass; } // Resolve color/depth textures to a non-msaa texture, and return it. Texture2D* ResolveEFBColorTexture(const VkRect2D& region); Texture2D* ResolveEFBDepthTexture(const VkRect2D& region); // 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(); private: struct EFBPokeVertex { float position[4]; u32 color; }; bool CreateEFBRenderPass(); void DestroyEFBRenderPass(); bool CreateEFBFramebuffer(); void DestroyEFBFramebuffer(); bool CompileConversionShaders(); void DestroyConversionShaders(); bool CreateReadbackRenderPasses(); void DestroyReadbackRenderPasses(); bool CompileReadbackShaders(); void DestroyReadbackShaders(); bool CreateReadbackTextures(); void DestroyReadbackTextures(); bool CreateReadbackFramebuffer(); void DestroyReadbackFramebuffer(); void CreatePokeVertexFormat(); bool CreatePokeVertexBuffer(); void DestroyPokeVertexBuffer(); bool CompilePokeShaders(); void DestroyPokeShaders(); bool PopulateColorReadbackTexture(); bool PopulateDepthReadbackTexture(); void CreatePokeVertices(std::vector* destination_list, u32 x, u32 y, float z, u32 color); void DrawPokeVertices(const EFBPokeVertex* vertices, size_t vertex_count, bool write_color, bool write_depth); VkRenderPass m_efb_load_render_pass = VK_NULL_HANDLE; VkRenderPass m_efb_clear_render_pass = VK_NULL_HANDLE; VkRenderPass m_depth_resolve_render_pass = VK_NULL_HANDLE; u32 m_efb_width = 0; u32 m_efb_height = 0; u32 m_efb_layers = 1; VkSampleCountFlagBits m_efb_samples = VK_SAMPLE_COUNT_1_BIT; 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_resolve_depth_texture; VkFramebuffer m_efb_framebuffer = VK_NULL_HANDLE; VkFramebuffer m_efb_convert_framebuffer = VK_NULL_HANDLE; VkFramebuffer m_depth_resolve_framebuffer = VK_NULL_HANDLE; // Format conversion shaders VkShaderModule m_ps_rgb8_to_rgba6 = VK_NULL_HANDLE; VkShaderModule m_ps_rgba6_to_rgb8 = VK_NULL_HANDLE; VkShaderModule m_ps_depth_resolve = VK_NULL_HANDLE; // EFB readback texture std::unique_ptr m_color_copy_texture; std::unique_ptr m_depth_copy_texture; VkFramebuffer m_color_copy_framebuffer = VK_NULL_HANDLE; VkFramebuffer m_depth_copy_framebuffer = VK_NULL_HANDLE; // 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 poke drawing setup std::unique_ptr m_poke_vertex_format; std::unique_ptr m_poke_vertex_stream_buffer; std::vector m_color_poke_vertices; std::vector m_depth_poke_vertices; VkPrimitiveTopology m_poke_primitive_topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; VkRenderPass m_copy_color_render_pass = VK_NULL_HANDLE; VkRenderPass m_copy_depth_render_pass = VK_NULL_HANDLE; VkShaderModule m_copy_color_shader = VK_NULL_HANDLE; VkShaderModule m_copy_depth_shader = VK_NULL_HANDLE; VkShaderModule m_poke_vertex_shader = VK_NULL_HANDLE; VkShaderModule m_poke_geometry_shader = VK_NULL_HANDLE; VkShaderModule m_poke_fragment_shader = VK_NULL_HANDLE; }; // The XFB source class simply wraps a texture cache entry. // All the required functionality is provided by TextureCache. class XFBSource final : public XFBSourceBase { public: explicit XFBSource(std::unique_ptr texture); ~XFBSource(); TextureCache::TCacheEntry* GetTexture() const { return m_texture.get(); } // Guest -> GPU EFB Textures void DecodeToTexture(u32 xfb_addr, u32 fb_width, u32 fb_height) override; // Used for virtual XFB void CopyEFB(float gamma) override; private: std::unique_ptr m_texture; }; } // namespace Vulkan