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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
|
// 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
|