summaryrefslogtreecommitdiff
path: root/src/video_core/renderer_vulkan
diff options
context:
space:
mode:
authorGravatar liamwhite2023-01-06 09:59:59 -0500
committerGravatar GitHub2023-01-06 09:59:59 -0500
commit020dbcdbc76a6db68637ed82b8841df44bd5dd49 (patch)
treee67b5c0015f0b0cd34bee94df67d99742edc5d53 /src/video_core/renderer_vulkan
parentMerge pull request #9559 from FernandoS27/cached-writes (diff)
parentcommon: add setting for renderer clock workaround (diff)
downloadyuzu-020dbcdbc76a6db68637ed82b8841df44bd5dd49.tar.gz
yuzu-020dbcdbc76a6db68637ed82b8841df44bd5dd49.tar.xz
yuzu-020dbcdbc76a6db68637ed82b8841df44bd5dd49.zip
Merge pull request #9552 from liamwhite/turbo
vulkan: implement 'turbo mode' clock booster
Diffstat (limited to 'src/video_core/renderer_vulkan')
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp6
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.h5
-rw-r--r--src/video_core/renderer_vulkan/vk_turbo_mode.cpp205
-rw-r--r--src/video_core/renderer_vulkan/vk_turbo_mode.h26
4 files changed, 241 insertions, 1 deletions
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index bf97d25a4..1578cb206 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -78,6 +78,8 @@ std::string BuildCommaSeparatedExtensions(std::vector<std::string> available_ext
78 return separated_extensions; 78 return separated_extensions;
79} 79}
80 80
81} // Anonymous namespace
82
81Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dld, 83Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dld,
82 VkSurfaceKHR surface) { 84 VkSurfaceKHR surface) {
83 const std::vector<VkPhysicalDevice> devices = instance.EnumeratePhysicalDevices(); 85 const std::vector<VkPhysicalDevice> devices = instance.EnumeratePhysicalDevices();
@@ -89,7 +91,6 @@ Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dl
89 const vk::PhysicalDevice physical_device(devices[device_index], dld); 91 const vk::PhysicalDevice physical_device(devices[device_index], dld);
90 return Device(*instance, physical_device, surface, dld); 92 return Device(*instance, physical_device, surface, dld);
91} 93}
92} // Anonymous namespace
93 94
94RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, 95RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
95 Core::Frontend::EmuWindow& emu_window, 96 Core::Frontend::EmuWindow& emu_window,
@@ -109,6 +110,9 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
109 screen_info), 110 screen_info),
110 rasterizer(render_window, gpu, cpu_memory, screen_info, device, memory_allocator, 111 rasterizer(render_window, gpu, cpu_memory, screen_info, device, memory_allocator,
111 state_tracker, scheduler) { 112 state_tracker, scheduler) {
113 if (Settings::values.renderer_force_max_clock.GetValue()) {
114 turbo_mode.emplace(instance, dld);
115 }
112 Report(); 116 Report();
113} catch (const vk::Exception& exception) { 117} catch (const vk::Exception& exception) {
114 LOG_ERROR(Render_Vulkan, "Vulkan initialization failed with error: {}", exception.what()); 118 LOG_ERROR(Render_Vulkan, "Vulkan initialization failed with error: {}", exception.what());
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h
index e7bfecb20..009e75e0d 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.h
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.h
@@ -13,6 +13,7 @@
13#include "video_core/renderer_vulkan/vk_scheduler.h" 13#include "video_core/renderer_vulkan/vk_scheduler.h"
14#include "video_core/renderer_vulkan/vk_state_tracker.h" 14#include "video_core/renderer_vulkan/vk_state_tracker.h"
15#include "video_core/renderer_vulkan/vk_swapchain.h" 15#include "video_core/renderer_vulkan/vk_swapchain.h"
16#include "video_core/renderer_vulkan/vk_turbo_mode.h"
16#include "video_core/vulkan_common/vulkan_device.h" 17#include "video_core/vulkan_common/vulkan_device.h"
17#include "video_core/vulkan_common/vulkan_memory_allocator.h" 18#include "video_core/vulkan_common/vulkan_memory_allocator.h"
18#include "video_core/vulkan_common/vulkan_wrapper.h" 19#include "video_core/vulkan_common/vulkan_wrapper.h"
@@ -31,6 +32,9 @@ class GPU;
31 32
32namespace Vulkan { 33namespace Vulkan {
33 34
35Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dld,
36 VkSurfaceKHR surface);
37
34class RendererVulkan final : public VideoCore::RendererBase { 38class RendererVulkan final : public VideoCore::RendererBase {
35public: 39public:
36 explicit RendererVulkan(Core::TelemetrySession& telemtry_session, 40 explicit RendererVulkan(Core::TelemetrySession& telemtry_session,
@@ -74,6 +78,7 @@ private:
74 Swapchain swapchain; 78 Swapchain swapchain;
75 BlitScreen blit_screen; 79 BlitScreen blit_screen;
76 RasterizerVulkan rasterizer; 80 RasterizerVulkan rasterizer;
81 std::optional<TurboMode> turbo_mode;
77}; 82};
78 83
79} // namespace Vulkan 84} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_turbo_mode.cpp b/src/video_core/renderer_vulkan/vk_turbo_mode.cpp
new file mode 100644
index 000000000..852b86f84
--- /dev/null
+++ b/src/video_core/renderer_vulkan/vk_turbo_mode.cpp
@@ -0,0 +1,205 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/literals.h"
5#include "video_core/host_shaders/vulkan_turbo_mode_comp_spv.h"
6#include "video_core/renderer_vulkan/renderer_vulkan.h"
7#include "video_core/renderer_vulkan/vk_shader_util.h"
8#include "video_core/renderer_vulkan/vk_turbo_mode.h"
9#include "video_core/vulkan_common/vulkan_device.h"
10
11namespace Vulkan {
12
13using namespace Common::Literals;
14
15TurboMode::TurboMode(const vk::Instance& instance, const vk::InstanceDispatch& dld)
16 : m_device{CreateDevice(instance, dld, VK_NULL_HANDLE)}, m_allocator{m_device, false} {
17 m_thread = std::jthread([&](auto stop_token) { Run(stop_token); });
18}
19
20TurboMode::~TurboMode() = default;
21
22void TurboMode::Run(std::stop_token stop_token) {
23 auto& dld = m_device.GetLogical();
24
25 // Allocate buffer. 2MiB should be sufficient.
26 auto buffer = dld.CreateBuffer(VkBufferCreateInfo{
27 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
28 .pNext = nullptr,
29 .flags = 0,
30 .size = 2_MiB,
31 .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
32 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
33 .queueFamilyIndexCount = 0,
34 .pQueueFamilyIndices = nullptr,
35 });
36
37 // Commit some device local memory for the buffer.
38 auto commit = m_allocator.Commit(buffer, MemoryUsage::DeviceLocal);
39
40 // Create the descriptor pool to contain our descriptor.
41 constexpr VkDescriptorPoolSize pool_size{
42 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
43 .descriptorCount = 1,
44 };
45
46 auto descriptor_pool = dld.CreateDescriptorPool(VkDescriptorPoolCreateInfo{
47 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
48 .pNext = nullptr,
49 .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
50 .maxSets = 1,
51 .poolSizeCount = 1,
52 .pPoolSizes = &pool_size,
53 });
54
55 // Create the descriptor set layout from the pool.
56 constexpr VkDescriptorSetLayoutBinding layout_binding{
57 .binding = 0,
58 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
59 .descriptorCount = 1,
60 .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
61 .pImmutableSamplers = nullptr,
62 };
63
64 auto descriptor_set_layout = dld.CreateDescriptorSetLayout(VkDescriptorSetLayoutCreateInfo{
65 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
66 .pNext = nullptr,
67 .flags = 0,
68 .bindingCount = 1,
69 .pBindings = &layout_binding,
70 });
71
72 // Actually create the descriptor set.
73 auto descriptor_set = descriptor_pool.Allocate(VkDescriptorSetAllocateInfo{
74 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
75 .pNext = nullptr,
76 .descriptorPool = *descriptor_pool,
77 .descriptorSetCount = 1,
78 .pSetLayouts = descriptor_set_layout.address(),
79 });
80
81 // Create the shader.
82 auto shader = BuildShader(m_device, VULKAN_TURBO_MODE_COMP_SPV);
83
84 // Create the pipeline layout.
85 auto pipeline_layout = dld.CreatePipelineLayout(VkPipelineLayoutCreateInfo{
86 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
87 .pNext = nullptr,
88 .flags = 0,
89 .setLayoutCount = 1,
90 .pSetLayouts = descriptor_set_layout.address(),
91 .pushConstantRangeCount = 0,
92 .pPushConstantRanges = nullptr,
93 });
94
95 // Actually create the pipeline.
96 const VkPipelineShaderStageCreateInfo shader_stage{
97 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
98 .pNext = nullptr,
99 .flags = 0,
100 .stage = VK_SHADER_STAGE_COMPUTE_BIT,
101 .module = *shader,
102 .pName = "main",
103 .pSpecializationInfo = nullptr,
104 };
105
106 auto pipeline = dld.CreateComputePipeline(VkComputePipelineCreateInfo{
107 .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
108 .pNext = nullptr,
109 .flags = 0,
110 .stage = shader_stage,
111 .layout = *pipeline_layout,
112 .basePipelineHandle = VK_NULL_HANDLE,
113 .basePipelineIndex = 0,
114 });
115
116 // Create a fence to wait on.
117 auto fence = dld.CreateFence(VkFenceCreateInfo{
118 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
119 .pNext = nullptr,
120 .flags = 0,
121 });
122
123 // Create a command pool to allocate a command buffer from.
124 auto command_pool = dld.CreateCommandPool(VkCommandPoolCreateInfo{
125 .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
126 .pNext = nullptr,
127 .flags =
128 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
129 .queueFamilyIndex = m_device.GetGraphicsFamily(),
130 });
131
132 // Create a single command buffer.
133 auto cmdbufs = command_pool.Allocate(1, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
134 auto cmdbuf = vk::CommandBuffer{cmdbufs[0], m_device.GetDispatchLoader()};
135
136 while (!stop_token.stop_requested()) {
137 // Reset the fence.
138 fence.Reset();
139
140 // Update descriptor set.
141 const VkDescriptorBufferInfo buffer_info{
142 .buffer = *buffer,
143 .offset = 0,
144 .range = VK_WHOLE_SIZE,
145 };
146
147 const VkWriteDescriptorSet buffer_write{
148 .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
149 .pNext = nullptr,
150 .dstSet = descriptor_set[0],
151 .dstBinding = 0,
152 .dstArrayElement = 0,
153 .descriptorCount = 1,
154 .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
155 .pImageInfo = nullptr,
156 .pBufferInfo = &buffer_info,
157 .pTexelBufferView = nullptr,
158 };
159
160 dld.UpdateDescriptorSets(std::array{buffer_write}, {});
161
162 // Set up the command buffer.
163 cmdbuf.Begin(VkCommandBufferBeginInfo{
164 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
165 .pNext = nullptr,
166 .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
167 .pInheritanceInfo = nullptr,
168 });
169
170 // Clear the buffer.
171 cmdbuf.FillBuffer(*buffer, 0, VK_WHOLE_SIZE, 0);
172
173 // Bind descriptor set.
174 cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline_layout, 0,
175 descriptor_set, {});
176
177 // Bind the pipeline.
178 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
179
180 // Dispatch.
181 cmdbuf.Dispatch(64, 64, 1);
182
183 // Finish.
184 cmdbuf.End();
185
186 const VkSubmitInfo submit_info{
187 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
188 .pNext = nullptr,
189 .waitSemaphoreCount = 0,
190 .pWaitSemaphores = nullptr,
191 .pWaitDstStageMask = nullptr,
192 .commandBufferCount = 1,
193 .pCommandBuffers = cmdbuf.address(),
194 .signalSemaphoreCount = 0,
195 .pSignalSemaphores = nullptr,
196 };
197
198 m_device.GetGraphicsQueue().Submit(std::array{submit_info}, *fence);
199
200 // Wait for completion.
201 fence.Wait();
202 }
203}
204
205} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_turbo_mode.h b/src/video_core/renderer_vulkan/vk_turbo_mode.h
new file mode 100644
index 000000000..2060e2395
--- /dev/null
+++ b/src/video_core/renderer_vulkan/vk_turbo_mode.h
@@ -0,0 +1,26 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "common/polyfill_thread.h"
7#include "video_core/vulkan_common/vulkan_device.h"
8#include "video_core/vulkan_common/vulkan_memory_allocator.h"
9#include "video_core/vulkan_common/vulkan_wrapper.h"
10
11namespace Vulkan {
12
13class TurboMode {
14public:
15 explicit TurboMode(const vk::Instance& instance, const vk::InstanceDispatch& dld);
16 ~TurboMode();
17
18private:
19 void Run(std::stop_token stop_token);
20
21 Device m_device;
22 MemoryAllocator m_allocator;
23 std::jthread m_thread;
24};
25
26} // namespace Vulkan