summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp625
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.h118
3 files changed, 745 insertions, 0 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 12c46e86f..ccfed4f2e 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -154,6 +154,8 @@ if (ENABLE_VULKAN)
154 renderer_vulkan/maxwell_to_vk.cpp 154 renderer_vulkan/maxwell_to_vk.cpp
155 renderer_vulkan/maxwell_to_vk.h 155 renderer_vulkan/maxwell_to_vk.h
156 renderer_vulkan/renderer_vulkan.h 156 renderer_vulkan/renderer_vulkan.h
157 renderer_vulkan/vk_blit_screen.cpp
158 renderer_vulkan/vk_blit_screen.h
157 renderer_vulkan/vk_buffer_cache.cpp 159 renderer_vulkan/vk_buffer_cache.cpp
158 renderer_vulkan/vk_buffer_cache.h 160 renderer_vulkan/vk_buffer_cache.h
159 renderer_vulkan/vk_compute_pass.cpp 161 renderer_vulkan/vk_compute_pass.cpp
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
new file mode 100644
index 000000000..7c8bff5d2
--- /dev/null
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -0,0 +1,625 @@
1// Copyright 2018 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include <array>
7#include <cstring>
8#include <memory>
9#include <tuple>
10#include <vector>
11
12#include "common/assert.h"
13#include "common/common_types.h"
14#include "common/math_util.h"
15
16#include "core/core.h"
17#include "core/frontend/emu_window.h"
18#include "core/memory.h"
19
20#include "video_core/gpu.h"
21#include "video_core/morton.h"
22#include "video_core/rasterizer_interface.h"
23#include "video_core/renderer_vulkan/declarations.h"
24#include "video_core/renderer_vulkan/renderer_vulkan.h"
25#include "video_core/renderer_vulkan/vk_blit_screen.h"
26#include "video_core/renderer_vulkan/vk_device.h"
27#include "video_core/renderer_vulkan/vk_image.h"
28#include "video_core/renderer_vulkan/vk_memory_manager.h"
29#include "video_core/renderer_vulkan/vk_resource_manager.h"
30#include "video_core/renderer_vulkan/vk_scheduler.h"
31#include "video_core/renderer_vulkan/vk_shader_util.h"
32#include "video_core/renderer_vulkan/vk_swapchain.h"
33#include "video_core/surface.h"
34
35namespace Vulkan {
36
37namespace {
38
39// Generated from the "shaders/" directory, read the instructions there.
40constexpr u8 blit_vertex_code[] = {
41 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, 0x08, 0x00, 0x27, 0x00, 0x00, 0x00,
42 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00,
43 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
44 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
45 0x0f, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
46 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
47 0x25, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00,
49 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
50 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
51 0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
52 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
53 0x48, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
54 0x48, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
55 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x11, 0x00, 0x00, 0x00,
57 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x25, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
62 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00,
63 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00,
64 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
65 0x04, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
66 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
67 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
68 0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
69 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
70 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
71 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00,
72 0x0e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
73 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x04, 0x00,
74 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00,
75 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00,
76 0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00,
77 0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00,
78 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00,
79 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00,
80 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00,
81 0x19, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
82 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
83 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x20, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00,
84 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00,
85 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00,
86 0x24, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00,
87 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00,
88 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
89 0x05, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
90 0x13, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
91 0x16, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00,
92 0x1a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
93 0x1d, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
94 0x06, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
95 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
96 0x1e, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x91, 0x00, 0x05, 0x00,
97 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
98 0x41, 0x00, 0x05, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
99 0x0f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x22, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
100 0x3d, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
101 0x3e, 0x00, 0x03, 0x00, 0x24, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00,
102 0x38, 0x00, 0x01, 0x00};
103
104constexpr u8 blit_fragment_code[] = {
105 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00,
106 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00,
107 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
108 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
109 0x0f, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
110 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
111 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
112 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00,
113 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00,
114 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00,
115 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
116 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00,
117 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
118 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
119 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
120 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x00, 0x00,
121 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00,
123 0x0b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
124 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
125 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00,
126 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
127 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
128 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00,
129 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
130 0x05, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
131 0x0d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
132 0x11, 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
133 0x0e, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00,
134 0x13, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00};
135
136struct ScreenRectVertex {
137 ScreenRectVertex() = default;
138 explicit ScreenRectVertex(f32 x, f32 y, f32 u, f32 v) : position{{x, y}}, tex_coord{{u, v}} {}
139
140 std::array<f32, 2> position;
141 std::array<f32, 2> tex_coord;
142
143 static vk::VertexInputBindingDescription GetDescription() {
144 return vk::VertexInputBindingDescription(0, sizeof(ScreenRectVertex),
145 vk::VertexInputRate::eVertex);
146 }
147
148 static std::array<vk::VertexInputAttributeDescription, 2> GetAttributes() {
149 return {vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32Sfloat,
150 offsetof(ScreenRectVertex, position)),
151 vk::VertexInputAttributeDescription(1, 0, vk::Format::eR32G32Sfloat,
152 offsetof(ScreenRectVertex, tex_coord))};
153 }
154};
155
156constexpr std::array<f32, 4 * 4> MakeOrthographicMatrix(f32 width, f32 height) {
157 // clang-format off
158 return { 2.f / width, 0.f, 0.f, 0.f,
159 0.f, 2.f / height, 0.f, 0.f,
160 0.f, 0.f, 1.f, 0.f,
161 -1.f, -1.f, 0.f, 1.f};
162 // clang-format on
163}
164
165std::size_t GetBytesPerPixel(const Tegra::FramebufferConfig& framebuffer) {
166 using namespace VideoCore::Surface;
167 return GetBytesPerPixel(PixelFormatFromGPUPixelFormat(framebuffer.pixel_format));
168}
169
170std::size_t GetSizeInBytes(const Tegra::FramebufferConfig& framebuffer) {
171 return static_cast<std::size_t>(framebuffer.stride) *
172 static_cast<std::size_t>(framebuffer.height) * GetBytesPerPixel(framebuffer);
173}
174
175vk::Format GetFormat(const Tegra::FramebufferConfig& framebuffer) {
176 switch (framebuffer.pixel_format) {
177 case Tegra::FramebufferConfig::PixelFormat::ABGR8:
178 return vk::Format::eA8B8G8R8UnormPack32;
179 case Tegra::FramebufferConfig::PixelFormat::RGB565:
180 return vk::Format::eR5G6B5UnormPack16;
181 default:
182 UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}",
183 static_cast<u32>(framebuffer.pixel_format));
184 return vk::Format::eA8B8G8R8UnormPack32;
185 }
186}
187
188} // Anonymous namespace
189
190struct VKBlitScreen::BufferData {
191 struct {
192 std::array<f32, 4 * 4> modelview_matrix;
193 } uniform;
194
195 std::array<ScreenRectVertex, 4> vertices;
196
197 // Unaligned image data goes here
198};
199
200VKBlitScreen::VKBlitScreen(Core::System& system, Core::Frontend::EmuWindow& render_window,
201 VideoCore::RasterizerInterface& rasterizer, const VKDevice& device,
202 VKResourceManager& resource_manager, VKMemoryManager& memory_manager,
203 VKSwapchain& swapchain, VKScheduler& scheduler,
204 const VKScreenInfo& screen_info)
205 : system{system}, render_window{render_window}, rasterizer{rasterizer}, device{device},
206 resource_manager{resource_manager}, memory_manager{memory_manager}, swapchain{swapchain},
207 scheduler{scheduler}, image_count{swapchain.GetImageCount()}, screen_info{screen_info} {
208 watches.resize(image_count);
209 std::generate(watches.begin(), watches.end(),
210 []() { return std::make_unique<VKFenceWatch>(); });
211
212 CreateStaticResources();
213 CreateDynamicResources();
214}
215
216VKBlitScreen::~VKBlitScreen() = default;
217
218void VKBlitScreen::Recreate() {
219 CreateDynamicResources();
220}
221
222std::tuple<VKFence&, vk::Semaphore> VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
223 bool use_accelerated) {
224 RefreshResources(framebuffer);
225
226 // Finish any pending renderpass
227 scheduler.RequestOutsideRenderPassOperationContext();
228
229 const u32 image_index = swapchain.GetImageIndex();
230 watches[image_index]->Watch(scheduler.GetFence());
231
232 VKImage* blit_image = use_accelerated ? screen_info.image : raw_images[image_index].get();
233
234 UpdateDescriptorSet(image_index, blit_image->GetPresentView());
235
236 BufferData data;
237 SetUniformData(data, framebuffer);
238 SetVertexData(data, framebuffer);
239
240 auto map = buffer_commit->Map();
241 std::memcpy(map.GetAddress(), &data, sizeof(data));
242
243 if (!use_accelerated) {
244 const u64 image_offset = GetRawImageOffset(framebuffer, image_index);
245
246 const auto pixel_format =
247 VideoCore::Surface::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format);
248 const VAddr framebuffer_addr = framebuffer.address + framebuffer.offset;
249 const auto host_ptr = system.Memory().GetPointer(framebuffer_addr);
250 rasterizer.FlushRegion(ToCacheAddr(host_ptr), GetSizeInBytes(framebuffer));
251
252 // TODO(Rodrigo): Read this from HLE
253 constexpr u32 block_height_log2 = 4;
254 VideoCore::MortonSwizzle(VideoCore::MortonSwizzleMode::MortonToLinear, pixel_format,
255 framebuffer.stride, block_height_log2, framebuffer.height, 0, 1, 1,
256 map.GetAddress() + image_offset, host_ptr);
257
258 blit_image->Transition(0, 1, 0, 1, vk::PipelineStageFlagBits::eTransfer,
259 vk::AccessFlagBits::eTransferWrite,
260 vk::ImageLayout::eTransferDstOptimal);
261
262 const vk::BufferImageCopy copy(image_offset, 0, 0,
263 {vk::ImageAspectFlagBits::eColor, 0, 0, 1}, {0, 0, 0},
264 {framebuffer.width, framebuffer.height, 1});
265 scheduler.Record([buffer_handle = *buffer, image = blit_image->GetHandle(),
266 copy](auto cmdbuf, auto& dld) {
267 cmdbuf.copyBufferToImage(buffer_handle, image, vk::ImageLayout::eTransferDstOptimal,
268 {copy}, dld);
269 });
270 }
271 map.Release();
272
273 blit_image->Transition(0, 1, 0, 1, vk::PipelineStageFlagBits::eFragmentShader,
274 vk::AccessFlagBits::eShaderRead,
275 vk::ImageLayout::eShaderReadOnlyOptimal);
276
277 scheduler.Record([renderpass = *renderpass, framebuffer = *framebuffers[image_index],
278 descriptor_set = descriptor_sets[image_index], buffer = *buffer,
279 size = swapchain.GetSize(), pipeline = *pipeline,
280 layout = *pipeline_layout](auto cmdbuf, auto& dld) {
281 const vk::ClearValue clear_color{std::array{0.0f, 0.0f, 0.0f, 1.0f}};
282 const vk::RenderPassBeginInfo renderpass_bi(renderpass, framebuffer, {{0, 0}, size}, 1,
283 &clear_color);
284
285 cmdbuf.beginRenderPass(renderpass_bi, vk::SubpassContents::eInline, dld);
286 cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline, dld);
287 cmdbuf.setViewport(
288 0,
289 {{0.0f, 0.0f, static_cast<f32>(size.width), static_cast<f32>(size.height), 0.0f, 1.0f}},
290 dld);
291 cmdbuf.setScissor(0, {{{0, 0}, size}}, dld);
292
293 cmdbuf.bindVertexBuffers(0, {buffer}, {offsetof(BufferData, vertices)}, dld);
294 cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, layout, 0, {descriptor_set}, {},
295 dld);
296 cmdbuf.draw(4, 1, 0, 0, dld);
297 cmdbuf.endRenderPass(dld);
298 });
299
300 return {scheduler.GetFence(), *semaphores[image_index]};
301}
302
303void VKBlitScreen::CreateStaticResources() {
304 CreateShaders();
305 CreateSemaphores();
306 CreateDescriptorPool();
307 CreateDescriptorSetLayout();
308 CreateDescriptorSets();
309 CreatePipelineLayout();
310 CreateSampler();
311}
312
313void VKBlitScreen::CreateDynamicResources() {
314 CreateRenderPass();
315 CreateFramebuffers();
316 CreateGraphicsPipeline();
317}
318
319void VKBlitScreen::RefreshResources(const Tegra::FramebufferConfig& framebuffer) {
320 if (framebuffer.width == raw_width && framebuffer.height == raw_height && !raw_images.empty()) {
321 return;
322 }
323 raw_width = framebuffer.width;
324 raw_height = framebuffer.height;
325 ReleaseRawImages();
326
327 CreateStagingBuffer(framebuffer);
328 CreateRawImages(framebuffer);
329}
330
331void VKBlitScreen::CreateShaders() {
332 vertex_shader = BuildShader(device, sizeof(blit_vertex_code), blit_vertex_code);
333 fragment_shader = BuildShader(device, sizeof(blit_fragment_code), blit_fragment_code);
334}
335
336void VKBlitScreen::CreateSemaphores() {
337 const auto dev = device.GetLogical();
338 const auto& dld = device.GetDispatchLoader();
339
340 semaphores.resize(image_count);
341 for (std::size_t i = 0; i < image_count; ++i) {
342 semaphores[i] = dev.createSemaphoreUnique({}, nullptr, dld);
343 }
344}
345
346void VKBlitScreen::CreateDescriptorPool() {
347 const std::array<vk::DescriptorPoolSize, 2> pool_sizes{
348 vk::DescriptorPoolSize{vk::DescriptorType::eUniformBuffer, image_count},
349 vk::DescriptorPoolSize{vk::DescriptorType::eCombinedImageSampler, image_count}};
350 const vk::DescriptorPoolCreateInfo pool_ci({}, image_count, static_cast<u32>(pool_sizes.size()),
351 pool_sizes.data());
352 const auto dev = device.GetLogical();
353 descriptor_pool = dev.createDescriptorPoolUnique(pool_ci, nullptr, device.GetDispatchLoader());
354}
355
356void VKBlitScreen::CreateRenderPass() {
357 const vk::AttachmentDescription color_attachment(
358 {}, swapchain.GetImageFormat(), vk::SampleCountFlagBits::e1, vk::AttachmentLoadOp::eClear,
359 vk::AttachmentStoreOp::eStore, vk::AttachmentLoadOp::eDontCare,
360 vk::AttachmentStoreOp::eDontCare, vk::ImageLayout::eUndefined,
361 vk::ImageLayout::ePresentSrcKHR);
362
363 const vk::AttachmentReference color_attachment_ref(0, vk::ImageLayout::eColorAttachmentOptimal);
364
365 const vk::SubpassDescription subpass_description({}, vk::PipelineBindPoint::eGraphics, 0,
366 nullptr, 1, &color_attachment_ref, nullptr,
367 nullptr, 0, nullptr);
368
369 const vk::SubpassDependency dependency(
370 VK_SUBPASS_EXTERNAL, 0, vk::PipelineStageFlagBits::eColorAttachmentOutput,
371 vk::PipelineStageFlagBits::eColorAttachmentOutput, {},
372 vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite, {});
373
374 const vk::RenderPassCreateInfo renderpass_ci({}, 1, &color_attachment, 1, &subpass_description,
375 1, &dependency);
376
377 const auto dev = device.GetLogical();
378 renderpass = dev.createRenderPassUnique(renderpass_ci, nullptr, device.GetDispatchLoader());
379}
380
381void VKBlitScreen::CreateDescriptorSetLayout() {
382 const std::array<vk::DescriptorSetLayoutBinding, 2> layout_bindings{
383 vk::DescriptorSetLayoutBinding(0, vk::DescriptorType::eUniformBuffer, 1,
384 vk::ShaderStageFlagBits::eVertex, nullptr),
385 vk::DescriptorSetLayoutBinding(1, vk::DescriptorType::eCombinedImageSampler, 1,
386 vk::ShaderStageFlagBits::eFragment, nullptr)};
387 const vk::DescriptorSetLayoutCreateInfo descriptor_layout_ci(
388 {}, static_cast<u32>(layout_bindings.size()), layout_bindings.data());
389
390 const auto dev = device.GetLogical();
391 const auto& dld = device.GetDispatchLoader();
392 descriptor_set_layout = dev.createDescriptorSetLayoutUnique(descriptor_layout_ci, nullptr, dld);
393}
394
395void VKBlitScreen::CreateDescriptorSets() {
396 const auto dev = device.GetLogical();
397 const auto& dld = device.GetDispatchLoader();
398
399 descriptor_sets.resize(image_count);
400 for (u32 i = 0; i < image_count; ++i) {
401 const vk::DescriptorSetLayout layout = *descriptor_set_layout;
402 const vk::DescriptorSetAllocateInfo descriptor_set_ai(*descriptor_pool, 1, &layout);
403 const vk::Result result =
404 dev.allocateDescriptorSets(&descriptor_set_ai, &descriptor_sets[i], dld);
405 ASSERT(result == vk::Result::eSuccess);
406 }
407}
408
409void VKBlitScreen::CreatePipelineLayout() {
410 const vk::PipelineLayoutCreateInfo pipeline_layout_ci({}, 1, &descriptor_set_layout.get(), 0,
411 nullptr);
412 const auto dev = device.GetLogical();
413 const auto& dld = device.GetDispatchLoader();
414 pipeline_layout = dev.createPipelineLayoutUnique(pipeline_layout_ci, nullptr, dld);
415}
416
417void VKBlitScreen::CreateGraphicsPipeline() {
418 const std::array shader_stages = {
419 vk::PipelineShaderStageCreateInfo({}, vk::ShaderStageFlagBits::eVertex, *vertex_shader,
420 "main", nullptr),
421 vk::PipelineShaderStageCreateInfo({}, vk::ShaderStageFlagBits::eFragment, *fragment_shader,
422 "main", nullptr)};
423
424 const auto vertex_binding_description = ScreenRectVertex::GetDescription();
425 const auto vertex_attrs_description = ScreenRectVertex::GetAttributes();
426 const vk::PipelineVertexInputStateCreateInfo vertex_input(
427 {}, 1, &vertex_binding_description, static_cast<u32>(vertex_attrs_description.size()),
428 vertex_attrs_description.data());
429
430 const vk::PipelineInputAssemblyStateCreateInfo input_assembly(
431 {}, vk::PrimitiveTopology::eTriangleStrip, false);
432
433 // Set a dummy viewport, it's going to be replaced by dynamic states.
434 const vk::Viewport viewport(0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f);
435 const vk::Rect2D scissor({0, 0}, {1, 1});
436
437 const vk::PipelineViewportStateCreateInfo viewport_state({}, 1, &viewport, 1, &scissor);
438
439 const vk::PipelineRasterizationStateCreateInfo rasterizer(
440 {}, false, false, vk::PolygonMode::eFill, vk::CullModeFlagBits::eNone,
441 vk::FrontFace::eClockwise, false, 0.0f, 0.0f, 0.0f, 1.0f);
442
443 const vk::PipelineMultisampleStateCreateInfo multisampling({}, vk::SampleCountFlagBits::e1,
444 false, 0.0f, nullptr, false, false);
445
446 const vk::PipelineColorBlendAttachmentState color_blend_attachment(
447 false, vk::BlendFactor::eZero, vk::BlendFactor::eZero, vk::BlendOp::eAdd,
448 vk::BlendFactor::eZero, vk::BlendFactor::eZero, vk::BlendOp::eAdd,
449 vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
450 vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA);
451
452 const vk::PipelineColorBlendStateCreateInfo color_blending(
453 {}, false, vk::LogicOp::eCopy, 1, &color_blend_attachment, {0.0f, 0.0f, 0.0f, 0.0f});
454
455 const std::array<vk::DynamicState, 2> dynamic_states = {vk::DynamicState::eViewport,
456 vk::DynamicState::eScissor};
457
458 const vk::PipelineDynamicStateCreateInfo dynamic_state(
459 {}, static_cast<u32>(dynamic_states.size()), dynamic_states.data());
460
461 const vk::GraphicsPipelineCreateInfo pipeline_ci(
462 {}, static_cast<u32>(shader_stages.size()), shader_stages.data(), &vertex_input,
463 &input_assembly, nullptr, &viewport_state, &rasterizer, &multisampling, nullptr,
464 &color_blending, &dynamic_state, *pipeline_layout, *renderpass, 0, nullptr, 0);
465
466 const auto dev = device.GetLogical();
467 const auto& dld = device.GetDispatchLoader();
468 pipeline = dev.createGraphicsPipelineUnique({}, pipeline_ci, nullptr, dld);
469}
470
471void VKBlitScreen::CreateSampler() {
472 const auto dev = device.GetLogical();
473 const auto& dld = device.GetDispatchLoader();
474 const vk::SamplerCreateInfo sampler_ci(
475 {}, vk::Filter::eLinear, vk::Filter::eLinear, vk::SamplerMipmapMode::eLinear,
476 vk::SamplerAddressMode::eClampToBorder, vk::SamplerAddressMode::eClampToBorder,
477 vk::SamplerAddressMode::eClampToBorder, 0.0f, false, 0.0f, false, vk::CompareOp::eNever,
478 0.0f, 0.0f, vk::BorderColor::eFloatOpaqueBlack, false);
479 sampler = dev.createSamplerUnique(sampler_ci, nullptr, dld);
480}
481
482void VKBlitScreen::CreateFramebuffers() {
483 const vk::Extent2D size{swapchain.GetSize()};
484 framebuffers.clear();
485 framebuffers.resize(image_count);
486
487 const auto dev = device.GetLogical();
488 const auto& dld = device.GetDispatchLoader();
489
490 for (u32 i = 0; i < image_count; ++i) {
491 const vk::ImageView image_view{swapchain.GetImageViewIndex(i)};
492 const vk::FramebufferCreateInfo framebuffer_ci({}, *renderpass, 1, &image_view, size.width,
493 size.height, 1);
494 framebuffers[i] = dev.createFramebufferUnique(framebuffer_ci, nullptr, dld);
495 }
496}
497
498void VKBlitScreen::ReleaseRawImages() {
499 for (u32 i = 0; i < static_cast<u32>(raw_images.size()); ++i) {
500 watches[i]->Wait();
501 }
502 raw_images.clear();
503 raw_buffer_commits.clear();
504 buffer.reset();
505 buffer_commit.reset();
506}
507
508void VKBlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) {
509 const auto dev = device.GetLogical();
510 const auto& dld = device.GetDispatchLoader();
511
512 const vk::BufferCreateInfo buffer_ci({}, CalculateBufferSize(framebuffer),
513 vk::BufferUsageFlagBits::eTransferSrc |
514 vk::BufferUsageFlagBits::eVertexBuffer |
515 vk::BufferUsageFlagBits::eUniformBuffer,
516 vk::SharingMode::eExclusive, 0, nullptr);
517 buffer = dev.createBufferUnique(buffer_ci, nullptr, dld);
518 buffer_commit = memory_manager.Commit(*buffer, true);
519}
520
521void VKBlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) {
522 raw_images.resize(image_count);
523 raw_buffer_commits.resize(image_count);
524
525 const auto format = GetFormat(framebuffer);
526 for (u32 i = 0; i < image_count; ++i) {
527 const vk::ImageCreateInfo image_ci(
528 {}, vk::ImageType::e2D, format, {framebuffer.width, framebuffer.height, 1}, 1, 1,
529 vk::SampleCountFlagBits::e1, vk::ImageTiling::eOptimal,
530 vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled,
531 vk::SharingMode::eExclusive, 0, nullptr, vk::ImageLayout::eUndefined);
532
533 raw_images[i] =
534 std::make_unique<VKImage>(device, scheduler, image_ci, vk::ImageAspectFlagBits::eColor);
535 raw_buffer_commits[i] = memory_manager.Commit(raw_images[i]->GetHandle(), false);
536 }
537}
538
539void VKBlitScreen::UpdateDescriptorSet(u32 image_index, vk::ImageView image_view) const {
540 const vk::DescriptorSet descriptor_set = descriptor_sets[image_index];
541
542 const vk::DescriptorBufferInfo buffer_info(*buffer, offsetof(BufferData, uniform),
543 sizeof(BufferData::uniform));
544 const vk::WriteDescriptorSet ubo_write(descriptor_set, 0, 0, 1,
545 vk::DescriptorType::eUniformBuffer, nullptr,
546 &buffer_info, nullptr);
547
548 const vk::DescriptorImageInfo image_info(*sampler, image_view,
549 vk::ImageLayout::eShaderReadOnlyOptimal);
550 const vk::WriteDescriptorSet sampler_write(descriptor_set, 1, 0, 1,
551 vk::DescriptorType::eCombinedImageSampler,
552 &image_info, nullptr, nullptr);
553
554 const auto dev = device.GetLogical();
555 const auto& dld = device.GetDispatchLoader();
556 dev.updateDescriptorSets({ubo_write, sampler_write}, {}, dld);
557}
558
559void VKBlitScreen::SetUniformData(BufferData& data,
560 const Tegra::FramebufferConfig& framebuffer) const {
561 const auto& layout = render_window.GetFramebufferLayout();
562 data.uniform.modelview_matrix =
563 MakeOrthographicMatrix(static_cast<f32>(layout.width), static_cast<f32>(layout.height));
564}
565
566void VKBlitScreen::SetVertexData(BufferData& data,
567 const Tegra::FramebufferConfig& framebuffer) const {
568 const auto& framebuffer_transform_flags = framebuffer.transform_flags;
569 const auto& framebuffer_crop_rect = framebuffer.crop_rect;
570
571 const Common::Rectangle<f32> texcoords{0.f, 0.f, 1.f, 1.f};
572 auto left = texcoords.left;
573 auto right = texcoords.right;
574
575 switch (framebuffer_transform_flags) {
576 case Tegra::FramebufferConfig::TransformFlags::Unset:
577 break;
578 case Tegra::FramebufferConfig::TransformFlags::FlipV:
579 // Flip the framebuffer vertically
580 left = texcoords.right;
581 right = texcoords.left;
582 break;
583 default:
584 UNIMPLEMENTED_MSG("Unsupported framebuffer_transform_flags={}",
585 static_cast<u32>(framebuffer_transform_flags));
586 break;
587 }
588
589 UNIMPLEMENTED_IF(framebuffer_crop_rect.top != 0);
590 UNIMPLEMENTED_IF(framebuffer_crop_rect.left != 0);
591
592 // Scale the output by the crop width/height. This is commonly used with 1280x720 rendering
593 // (e.g. handheld mode) on a 1920x1080 framebuffer.
594 f32 scale_u = 1.0f, scale_v = 1.0f;
595 if (framebuffer_crop_rect.GetWidth() > 0) {
596 scale_u = static_cast<f32>(framebuffer_crop_rect.GetWidth()) /
597 static_cast<f32>(screen_info.width);
598 }
599 if (framebuffer_crop_rect.GetHeight() > 0) {
600 scale_v = static_cast<f32>(framebuffer_crop_rect.GetHeight()) /
601 static_cast<f32>(screen_info.height);
602 }
603
604 const auto& screen = render_window.GetFramebufferLayout().screen;
605 const auto x = static_cast<f32>(screen.left);
606 const auto y = static_cast<f32>(screen.top);
607 const auto w = static_cast<f32>(screen.GetWidth());
608 const auto h = static_cast<f32>(screen.GetHeight());
609 data.vertices[0] = ScreenRectVertex(x, y, texcoords.top * scale_u, left * scale_v);
610 data.vertices[1] = ScreenRectVertex(x + w, y, texcoords.bottom * scale_u, left * scale_v);
611 data.vertices[2] = ScreenRectVertex(x, y + h, texcoords.top * scale_u, right * scale_v);
612 data.vertices[3] = ScreenRectVertex(x + w, y + h, texcoords.bottom * scale_u, right * scale_v);
613}
614
615u64 VKBlitScreen::CalculateBufferSize(const Tegra::FramebufferConfig& framebuffer) const {
616 return sizeof(BufferData) + GetSizeInBytes(framebuffer) * image_count;
617}
618
619u64 VKBlitScreen::GetRawImageOffset(const Tegra::FramebufferConfig& framebuffer,
620 u32 image_index) const {
621 constexpr auto first_image_offset = static_cast<u64>(sizeof(BufferData));
622 return first_image_offset + GetSizeInBytes(framebuffer) * image_index;
623}
624
625} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.h b/src/video_core/renderer_vulkan/vk_blit_screen.h
new file mode 100644
index 000000000..743bb0317
--- /dev/null
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.h
@@ -0,0 +1,118 @@
1// Copyright 2018 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <memory>
9#include <tuple>
10
11#include "video_core/renderer_vulkan/declarations.h"
12#include "video_core/renderer_vulkan/vk_memory_manager.h"
13#include "video_core/renderer_vulkan/vk_resource_manager.h"
14
15namespace Core {
16class System;
17}
18
19namespace Core::Frontend {
20class EmuWindow;
21}
22
23namespace Tegra {
24struct FramebufferConfig;
25}
26
27namespace VideoCore {
28class RasterizerInterface;
29}
30
31namespace Vulkan {
32
33struct ScreenInfo;
34class RasterizerVulkan;
35class VKDevice;
36class VKFence;
37class VKImage;
38class VKScheduler;
39class VKSwapchain;
40
41class VKBlitScreen final {
42public:
43 explicit VKBlitScreen(Core::System& system, Core::Frontend::EmuWindow& render_window,
44 VideoCore::RasterizerInterface& rasterizer, const VKDevice& device,
45 VKResourceManager& resource_manager, VKMemoryManager& memory_manager,
46 VKSwapchain& swapchain, VKScheduler& scheduler,
47 const VKScreenInfo& screen_info);
48 ~VKBlitScreen();
49
50 void Recreate();
51
52 std::tuple<VKFence&, vk::Semaphore> Draw(const Tegra::FramebufferConfig& framebuffer,
53 bool use_accelerated);
54
55private:
56 struct BufferData;
57
58 void CreateStaticResources();
59 void CreateShaders();
60 void CreateSemaphores();
61 void CreateDescriptorPool();
62 void CreateRenderPass();
63 void CreateDescriptorSetLayout();
64 void CreateDescriptorSets();
65 void CreatePipelineLayout();
66 void CreateGraphicsPipeline();
67 void CreateSampler();
68
69 void CreateDynamicResources();
70 void CreateFramebuffers();
71
72 void RefreshResources(const Tegra::FramebufferConfig& framebuffer);
73 void ReleaseRawImages();
74 void CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer);
75 void CreateRawImages(const Tegra::FramebufferConfig& framebuffer);
76
77 void UpdateDescriptorSet(u32 image_index, vk::ImageView image_view) const;
78 void SetUniformData(BufferData& data, const Tegra::FramebufferConfig& framebuffer) const;
79 void SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer) const;
80
81 u64 CalculateBufferSize(const Tegra::FramebufferConfig& framebuffer) const;
82 u64 GetRawImageOffset(const Tegra::FramebufferConfig& framebuffer, u32 image_index) const;
83
84 Core::System& system;
85 Core::Frontend::EmuWindow& render_window;
86 VideoCore::RasterizerInterface& rasterizer;
87 const VKDevice& device;
88 VKResourceManager& resource_manager;
89 VKMemoryManager& memory_manager;
90 VKSwapchain& swapchain;
91 VKScheduler& scheduler;
92 const u32 image_count;
93 const VKScreenInfo& screen_info;
94
95 UniqueShaderModule vertex_shader;
96 UniqueShaderModule fragment_shader;
97 UniqueDescriptorPool descriptor_pool;
98 UniqueDescriptorSetLayout descriptor_set_layout;
99 UniquePipelineLayout pipeline_layout;
100 UniquePipeline pipeline;
101 UniqueRenderPass renderpass;
102 std::vector<UniqueFramebuffer> framebuffers;
103 std::vector<vk::DescriptorSet> descriptor_sets;
104 UniqueSampler sampler;
105
106 UniqueBuffer buffer;
107 VKMemoryCommit buffer_commit;
108
109 std::vector<std::unique_ptr<VKFenceWatch>> watches;
110
111 std::vector<UniqueSemaphore> semaphores;
112 std::vector<std::unique_ptr<VKImage>> raw_images;
113 std::vector<VKMemoryCommit> raw_buffer_commits;
114 u32 raw_width = 0;
115 u32 raw_height = 0;
116};
117
118} // namespace Vulkan