summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2020-01-20 22:32:16 -0400
committerGravatar GitHub2020-01-20 22:32:16 -0400
commit79e0991d9bbe41065978bfcf7cc67523a1f04a9c (patch)
tree0e2c0250235c475faa06a18e88c6dfbdf471fa50 /src
parentMerge pull request #3334 from bunnei/time-fix (diff)
parentvk_blit_screen: Address feedback (diff)
downloadyuzu-79e0991d9bbe41065978bfcf7cc67523a1f04a9c.tar.gz
yuzu-79e0991d9bbe41065978bfcf7cc67523a1f04a9c.tar.xz
yuzu-79e0991d9bbe41065978bfcf7cc67523a1f04a9c.zip
Merge pull request #3330 from ReinUsesLisp/vk-blit-screen
vk_blit_screen: Initial implementation
Diffstat (limited to 'src')
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp627
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.h119
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.h10
5 files changed, 754 insertions, 6 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..855cfc883
--- /dev/null
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -0,0 +1,627 @@
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 std::size_t 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, static_cast<u32>(image_count)},
349 vk::DescriptorPoolSize{vk::DescriptorType::eCombinedImageSampler,
350 static_cast<u32>(image_count)}};
351 const vk::DescriptorPoolCreateInfo pool_ci(
352 {}, static_cast<u32>(image_count), static_cast<u32>(pool_sizes.size()), pool_sizes.data());
353 const auto dev = device.GetLogical();
354 descriptor_pool = dev.createDescriptorPoolUnique(pool_ci, nullptr, device.GetDispatchLoader());
355}
356
357void VKBlitScreen::CreateRenderPass() {
358 const vk::AttachmentDescription color_attachment(
359 {}, swapchain.GetImageFormat(), vk::SampleCountFlagBits::e1, vk::AttachmentLoadOp::eClear,
360 vk::AttachmentStoreOp::eStore, vk::AttachmentLoadOp::eDontCare,
361 vk::AttachmentStoreOp::eDontCare, vk::ImageLayout::eUndefined,
362 vk::ImageLayout::ePresentSrcKHR);
363
364 const vk::AttachmentReference color_attachment_ref(0, vk::ImageLayout::eColorAttachmentOptimal);
365
366 const vk::SubpassDescription subpass_description({}, vk::PipelineBindPoint::eGraphics, 0,
367 nullptr, 1, &color_attachment_ref, nullptr,
368 nullptr, 0, nullptr);
369
370 const vk::SubpassDependency dependency(
371 VK_SUBPASS_EXTERNAL, 0, vk::PipelineStageFlagBits::eColorAttachmentOutput,
372 vk::PipelineStageFlagBits::eColorAttachmentOutput, {},
373 vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite, {});
374
375 const vk::RenderPassCreateInfo renderpass_ci({}, 1, &color_attachment, 1, &subpass_description,
376 1, &dependency);
377
378 const auto dev = device.GetLogical();
379 renderpass = dev.createRenderPassUnique(renderpass_ci, nullptr, device.GetDispatchLoader());
380}
381
382void VKBlitScreen::CreateDescriptorSetLayout() {
383 const std::array<vk::DescriptorSetLayoutBinding, 2> layout_bindings{
384 vk::DescriptorSetLayoutBinding(0, vk::DescriptorType::eUniformBuffer, 1,
385 vk::ShaderStageFlagBits::eVertex, nullptr),
386 vk::DescriptorSetLayoutBinding(1, vk::DescriptorType::eCombinedImageSampler, 1,
387 vk::ShaderStageFlagBits::eFragment, nullptr)};
388 const vk::DescriptorSetLayoutCreateInfo descriptor_layout_ci(
389 {}, static_cast<u32>(layout_bindings.size()), layout_bindings.data());
390
391 const auto dev = device.GetLogical();
392 const auto& dld = device.GetDispatchLoader();
393 descriptor_set_layout = dev.createDescriptorSetLayoutUnique(descriptor_layout_ci, nullptr, dld);
394}
395
396void VKBlitScreen::CreateDescriptorSets() {
397 const auto dev = device.GetLogical();
398 const auto& dld = device.GetDispatchLoader();
399
400 descriptor_sets.resize(image_count);
401 for (std::size_t i = 0; i < image_count; ++i) {
402 const vk::DescriptorSetLayout layout = *descriptor_set_layout;
403 const vk::DescriptorSetAllocateInfo descriptor_set_ai(*descriptor_pool, 1, &layout);
404 const vk::Result result =
405 dev.allocateDescriptorSets(&descriptor_set_ai, &descriptor_sets[i], dld);
406 ASSERT(result == vk::Result::eSuccess);
407 }
408}
409
410void VKBlitScreen::CreatePipelineLayout() {
411 const vk::PipelineLayoutCreateInfo pipeline_layout_ci({}, 1, &descriptor_set_layout.get(), 0,
412 nullptr);
413 const auto dev = device.GetLogical();
414 const auto& dld = device.GetDispatchLoader();
415 pipeline_layout = dev.createPipelineLayoutUnique(pipeline_layout_ci, nullptr, dld);
416}
417
418void VKBlitScreen::CreateGraphicsPipeline() {
419 const std::array shader_stages = {
420 vk::PipelineShaderStageCreateInfo({}, vk::ShaderStageFlagBits::eVertex, *vertex_shader,
421 "main", nullptr),
422 vk::PipelineShaderStageCreateInfo({}, vk::ShaderStageFlagBits::eFragment, *fragment_shader,
423 "main", nullptr)};
424
425 const auto vertex_binding_description = ScreenRectVertex::GetDescription();
426 const auto vertex_attrs_description = ScreenRectVertex::GetAttributes();
427 const vk::PipelineVertexInputStateCreateInfo vertex_input(
428 {}, 1, &vertex_binding_description, static_cast<u32>(vertex_attrs_description.size()),
429 vertex_attrs_description.data());
430
431 const vk::PipelineInputAssemblyStateCreateInfo input_assembly(
432 {}, vk::PrimitiveTopology::eTriangleStrip, false);
433
434 // Set a dummy viewport, it's going to be replaced by dynamic states.
435 const vk::Viewport viewport(0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f);
436 const vk::Rect2D scissor({0, 0}, {1, 1});
437
438 const vk::PipelineViewportStateCreateInfo viewport_state({}, 1, &viewport, 1, &scissor);
439
440 const vk::PipelineRasterizationStateCreateInfo rasterizer(
441 {}, false, false, vk::PolygonMode::eFill, vk::CullModeFlagBits::eNone,
442 vk::FrontFace::eClockwise, false, 0.0f, 0.0f, 0.0f, 1.0f);
443
444 const vk::PipelineMultisampleStateCreateInfo multisampling({}, vk::SampleCountFlagBits::e1,
445 false, 0.0f, nullptr, false, false);
446
447 const vk::PipelineColorBlendAttachmentState color_blend_attachment(
448 false, vk::BlendFactor::eZero, vk::BlendFactor::eZero, vk::BlendOp::eAdd,
449 vk::BlendFactor::eZero, vk::BlendFactor::eZero, vk::BlendOp::eAdd,
450 vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
451 vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA);
452
453 const vk::PipelineColorBlendStateCreateInfo color_blending(
454 {}, false, vk::LogicOp::eCopy, 1, &color_blend_attachment, {0.0f, 0.0f, 0.0f, 0.0f});
455
456 const std::array<vk::DynamicState, 2> dynamic_states = {vk::DynamicState::eViewport,
457 vk::DynamicState::eScissor};
458
459 const vk::PipelineDynamicStateCreateInfo dynamic_state(
460 {}, static_cast<u32>(dynamic_states.size()), dynamic_states.data());
461
462 const vk::GraphicsPipelineCreateInfo pipeline_ci(
463 {}, static_cast<u32>(shader_stages.size()), shader_stages.data(), &vertex_input,
464 &input_assembly, nullptr, &viewport_state, &rasterizer, &multisampling, nullptr,
465 &color_blending, &dynamic_state, *pipeline_layout, *renderpass, 0, nullptr, 0);
466
467 const auto dev = device.GetLogical();
468 const auto& dld = device.GetDispatchLoader();
469 pipeline = dev.createGraphicsPipelineUnique({}, pipeline_ci, nullptr, dld);
470}
471
472void VKBlitScreen::CreateSampler() {
473 const auto dev = device.GetLogical();
474 const auto& dld = device.GetDispatchLoader();
475 const vk::SamplerCreateInfo sampler_ci(
476 {}, vk::Filter::eLinear, vk::Filter::eLinear, vk::SamplerMipmapMode::eLinear,
477 vk::SamplerAddressMode::eClampToBorder, vk::SamplerAddressMode::eClampToBorder,
478 vk::SamplerAddressMode::eClampToBorder, 0.0f, false, 0.0f, false, vk::CompareOp::eNever,
479 0.0f, 0.0f, vk::BorderColor::eFloatOpaqueBlack, false);
480 sampler = dev.createSamplerUnique(sampler_ci, nullptr, dld);
481}
482
483void VKBlitScreen::CreateFramebuffers() {
484 const vk::Extent2D size{swapchain.GetSize()};
485 framebuffers.clear();
486 framebuffers.resize(image_count);
487
488 const auto dev = device.GetLogical();
489 const auto& dld = device.GetDispatchLoader();
490
491 for (std::size_t i = 0; i < image_count; ++i) {
492 const vk::ImageView image_view{swapchain.GetImageViewIndex(i)};
493 const vk::FramebufferCreateInfo framebuffer_ci({}, *renderpass, 1, &image_view, size.width,
494 size.height, 1);
495 framebuffers[i] = dev.createFramebufferUnique(framebuffer_ci, nullptr, dld);
496 }
497}
498
499void VKBlitScreen::ReleaseRawImages() {
500 for (std::size_t i = 0; i < raw_images.size(); ++i) {
501 watches[i]->Wait();
502 }
503 raw_images.clear();
504 raw_buffer_commits.clear();
505 buffer.reset();
506 buffer_commit.reset();
507}
508
509void VKBlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) {
510 const auto dev = device.GetLogical();
511 const auto& dld = device.GetDispatchLoader();
512
513 const vk::BufferCreateInfo buffer_ci({}, CalculateBufferSize(framebuffer),
514 vk::BufferUsageFlagBits::eTransferSrc |
515 vk::BufferUsageFlagBits::eVertexBuffer |
516 vk::BufferUsageFlagBits::eUniformBuffer,
517 vk::SharingMode::eExclusive, 0, nullptr);
518 buffer = dev.createBufferUnique(buffer_ci, nullptr, dld);
519 buffer_commit = memory_manager.Commit(*buffer, true);
520}
521
522void VKBlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) {
523 raw_images.resize(image_count);
524 raw_buffer_commits.resize(image_count);
525
526 const auto format = GetFormat(framebuffer);
527 for (std::size_t i = 0; i < image_count; ++i) {
528 const vk::ImageCreateInfo image_ci(
529 {}, vk::ImageType::e2D, format, {framebuffer.width, framebuffer.height, 1}, 1, 1,
530 vk::SampleCountFlagBits::e1, vk::ImageTiling::eOptimal,
531 vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled,
532 vk::SharingMode::eExclusive, 0, nullptr, vk::ImageLayout::eUndefined);
533
534 raw_images[i] =
535 std::make_unique<VKImage>(device, scheduler, image_ci, vk::ImageAspectFlagBits::eColor);
536 raw_buffer_commits[i] = memory_manager.Commit(raw_images[i]->GetHandle(), false);
537 }
538}
539
540void VKBlitScreen::UpdateDescriptorSet(std::size_t image_index, vk::ImageView image_view) const {
541 const vk::DescriptorSet descriptor_set = descriptor_sets[image_index];
542
543 const vk::DescriptorBufferInfo buffer_info(*buffer, offsetof(BufferData, uniform),
544 sizeof(BufferData::uniform));
545 const vk::WriteDescriptorSet ubo_write(descriptor_set, 0, 0, 1,
546 vk::DescriptorType::eUniformBuffer, nullptr,
547 &buffer_info, nullptr);
548
549 const vk::DescriptorImageInfo image_info(*sampler, image_view,
550 vk::ImageLayout::eShaderReadOnlyOptimal);
551 const vk::WriteDescriptorSet sampler_write(descriptor_set, 1, 0, 1,
552 vk::DescriptorType::eCombinedImageSampler,
553 &image_info, nullptr, nullptr);
554
555 const auto dev = device.GetLogical();
556 const auto& dld = device.GetDispatchLoader();
557 dev.updateDescriptorSets({ubo_write, sampler_write}, {}, dld);
558}
559
560void VKBlitScreen::SetUniformData(BufferData& data,
561 const Tegra::FramebufferConfig& framebuffer) const {
562 const auto& layout = render_window.GetFramebufferLayout();
563 data.uniform.modelview_matrix =
564 MakeOrthographicMatrix(static_cast<f32>(layout.width), static_cast<f32>(layout.height));
565}
566
567void VKBlitScreen::SetVertexData(BufferData& data,
568 const Tegra::FramebufferConfig& framebuffer) const {
569 const auto& framebuffer_transform_flags = framebuffer.transform_flags;
570 const auto& framebuffer_crop_rect = framebuffer.crop_rect;
571
572 static constexpr Common::Rectangle<f32> texcoords{0.f, 0.f, 1.f, 1.f};
573 auto left = texcoords.left;
574 auto right = texcoords.right;
575
576 switch (framebuffer_transform_flags) {
577 case Tegra::FramebufferConfig::TransformFlags::Unset:
578 break;
579 case Tegra::FramebufferConfig::TransformFlags::FlipV:
580 // Flip the framebuffer vertically
581 left = texcoords.right;
582 right = texcoords.left;
583 break;
584 default:
585 UNIMPLEMENTED_MSG("Unsupported framebuffer_transform_flags={}",
586 static_cast<u32>(framebuffer_transform_flags));
587 break;
588 }
589
590 UNIMPLEMENTED_IF(framebuffer_crop_rect.top != 0);
591 UNIMPLEMENTED_IF(framebuffer_crop_rect.left != 0);
592
593 // Scale the output by the crop width/height. This is commonly used with 1280x720 rendering
594 // (e.g. handheld mode) on a 1920x1080 framebuffer.
595 f32 scale_u = 1.0f;
596 f32 scale_v = 1.0f;
597 if (framebuffer_crop_rect.GetWidth() > 0) {
598 scale_u = static_cast<f32>(framebuffer_crop_rect.GetWidth()) /
599 static_cast<f32>(screen_info.width);
600 }
601 if (framebuffer_crop_rect.GetHeight() > 0) {
602 scale_v = static_cast<f32>(framebuffer_crop_rect.GetHeight()) /
603 static_cast<f32>(screen_info.height);
604 }
605
606 const auto& screen = render_window.GetFramebufferLayout().screen;
607 const auto x = static_cast<f32>(screen.left);
608 const auto y = static_cast<f32>(screen.top);
609 const auto w = static_cast<f32>(screen.GetWidth());
610 const auto h = static_cast<f32>(screen.GetHeight());
611 data.vertices[0] = ScreenRectVertex(x, y, texcoords.top * scale_u, left * scale_v);
612 data.vertices[1] = ScreenRectVertex(x + w, y, texcoords.bottom * scale_u, left * scale_v);
613 data.vertices[2] = ScreenRectVertex(x, y + h, texcoords.top * scale_u, right * scale_v);
614 data.vertices[3] = ScreenRectVertex(x + w, y + h, texcoords.bottom * scale_u, right * scale_v);
615}
616
617u64 VKBlitScreen::CalculateBufferSize(const Tegra::FramebufferConfig& framebuffer) const {
618 return sizeof(BufferData) + GetSizeInBytes(framebuffer) * image_count;
619}
620
621u64 VKBlitScreen::GetRawImageOffset(const Tegra::FramebufferConfig& framebuffer,
622 std::size_t image_index) const {
623 constexpr auto first_image_offset = static_cast<u64>(sizeof(BufferData));
624 return first_image_offset + GetSizeInBytes(framebuffer) * image_index;
625}
626
627} // 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..ea680b3f5
--- /dev/null
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.h
@@ -0,0 +1,119 @@
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(std::size_t 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,
83 std::size_t image_index) const;
84
85 Core::System& system;
86 Core::Frontend::EmuWindow& render_window;
87 VideoCore::RasterizerInterface& rasterizer;
88 const VKDevice& device;
89 VKResourceManager& resource_manager;
90 VKMemoryManager& memory_manager;
91 VKSwapchain& swapchain;
92 VKScheduler& scheduler;
93 const std::size_t image_count;
94 const VKScreenInfo& screen_info;
95
96 UniqueShaderModule vertex_shader;
97 UniqueShaderModule fragment_shader;
98 UniqueDescriptorPool descriptor_pool;
99 UniqueDescriptorSetLayout descriptor_set_layout;
100 UniquePipelineLayout pipeline_layout;
101 UniquePipeline pipeline;
102 UniqueRenderPass renderpass;
103 std::vector<UniqueFramebuffer> framebuffers;
104 std::vector<vk::DescriptorSet> descriptor_sets;
105 UniqueSampler sampler;
106
107 UniqueBuffer buffer;
108 VKMemoryCommit buffer_commit;
109
110 std::vector<std::unique_ptr<VKFenceWatch>> watches;
111
112 std::vector<UniqueSemaphore> semaphores;
113 std::vector<std::unique_ptr<VKImage>> raw_images;
114 std::vector<VKMemoryCommit> raw_buffer_commits;
115 u32 raw_width = 0;
116 u32 raw_height = 0;
117};
118
119} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp
index ebc68f030..f47b691a8 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.cpp
+++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp
@@ -123,7 +123,7 @@ bool VKSwapchain::Present(vk::Semaphore render_semaphore, VKFence& fence) {
123 123
124 ASSERT(fences[image_index] == nullptr); 124 ASSERT(fences[image_index] == nullptr);
125 fences[image_index] = &fence; 125 fences[image_index] = &fence;
126 frame_index = (frame_index + 1) % image_count; 126 frame_index = (frame_index + 1) % static_cast<u32>(image_count);
127 return recreated; 127 return recreated;
128} 128}
129 129
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h
index a1e7938d2..2f3b2ccd5 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.h
+++ b/src/video_core/renderer_vulkan/vk_swapchain.h
@@ -40,19 +40,19 @@ public:
40 return extent; 40 return extent;
41 } 41 }
42 42
43 u32 GetImageCount() const { 43 std::size_t GetImageCount() const {
44 return image_count; 44 return image_count;
45 } 45 }
46 46
47 u32 GetImageIndex() const { 47 std::size_t GetImageIndex() const {
48 return image_index; 48 return image_index;
49 } 49 }
50 50
51 vk::Image GetImageIndex(u32 index) const { 51 vk::Image GetImageIndex(std::size_t index) const {
52 return images[index]; 52 return images[index];
53 } 53 }
54 54
55 vk::ImageView GetImageViewIndex(u32 index) const { 55 vk::ImageView GetImageViewIndex(std::size_t index) const {
56 return *image_views[index]; 56 return *image_views[index];
57 } 57 }
58 58
@@ -77,7 +77,7 @@ private:
77 77
78 UniqueSwapchainKHR swapchain; 78 UniqueSwapchainKHR swapchain;
79 79
80 u32 image_count{}; 80 std::size_t image_count{};
81 std::vector<vk::Image> images; 81 std::vector<vk::Image> images;
82 std::vector<UniqueImageView> image_views; 82 std::vector<UniqueImageView> image_views;
83 std::vector<UniqueFramebuffer> framebuffers; 83 std::vector<UniqueFramebuffer> framebuffers;