mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 13:57:57 -07:00
c85e0a2586
Keeps associated data together. It also eliminates the possibility of out parameters not being initialized properly. For example, consider the following example: -- some FramebufferManager implementation -- void FBMgrImpl::GetTargetSize(u32* width, u32* height) override { // Do nothing } -- somewhere else where the function is used -- u32 width, height; framebuffer_manager_instance->GetTargetSize(&width, &height); if (texture_width != width) <-- Uninitialized variable usage { ... } It makes it much more obvious to spot any initialization issues, because it requires something to be returned, as opposed to allowing an implementation to just not do anything.
191 lines
6.6 KiB
C++
191 lines
6.6 KiB
C++
// Copyright 2016 Dolphin Emulator Project
|
|
// Licensed under GPLv2+
|
|
// Refer to the license.txt file included.
|
|
|
|
#pragma once
|
|
|
|
#include <memory>
|
|
#include <utility>
|
|
|
|
#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; }
|
|
std::pair<u32, u32> GetTargetSize() const override;
|
|
|
|
std::unique_ptr<XFBSourceBase> 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<EFBPokeVertex>* 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<Texture2D> m_efb_color_texture;
|
|
std::unique_ptr<Texture2D> m_efb_convert_color_texture;
|
|
std::unique_ptr<Texture2D> m_efb_depth_texture;
|
|
std::unique_ptr<Texture2D> m_efb_resolve_color_texture;
|
|
std::unique_ptr<Texture2D> 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<Texture2D> m_color_copy_texture;
|
|
std::unique_ptr<Texture2D> 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<StagingTexture2D> m_color_readback_texture;
|
|
std::unique_ptr<StagingTexture2D> 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<VertexFormat> m_poke_vertex_format;
|
|
std::unique_ptr<StreamBuffer> m_poke_vertex_stream_buffer;
|
|
std::vector<EFBPokeVertex> m_color_poke_vertices;
|
|
std::vector<EFBPokeVertex> 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<TextureCache::TCacheEntry> 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<TextureCache::TCacheEntry> m_texture;
|
|
};
|
|
|
|
} // namespace Vulkan
|