1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
|
// 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"
#include "VideoCommon/RenderState.h"
class AbstractStagingTexture;
namespace Vulkan
{
class StateTracker;
class StreamBuffer;
class Texture2D;
class VertexFormat;
class VKTexture;
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; }
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; }
u32 GetEFBWidth() const;
u32 GetEFBHeight() const;
u32 GetEFBLayers() const;
VkSampleCountFlagBits GetEFBSamples() const;
MultisamplingState GetEFBMultisamplingState() const;
void RecreateEFBFramebuffer();
// Recompile shaders, use when MSAA mode changes.
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);
// Returns the texture that the EFB color texture is resolved to when multisampling is enabled.
// Ensure ResolveEFBColorTexture is called before this method.
Texture2D* GetResolvedEFBColorTexture() const { return m_efb_resolve_color_texture.get(); }
// 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 CreateEFBRenderPasses();
bool CreateEFBFramebuffer();
void DestroyEFBFramebuffer();
bool CompileConversionShaders();
void DestroyConversionShaders();
bool CreateReadbackRenderPasses();
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;
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<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 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;
PrimitiveType m_poke_primitive = PrimitiveType::TriangleStrip;
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;
};
} // namespace Vulkan
|