forked from dolphin-emu/dolphin
		
	
		
			
				
	
	
		
			172 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			172 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// 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;
 |