diff options
| author | 2020-02-03 16:56:25 -0500 | |
|---|---|---|
| committer | 2020-02-03 16:56:25 -0500 | |
| commit | c31ec00d676f6dda0bebee70d7a0b230e5babee9 (patch) | |
| tree | 52c674cace5652f5d359dedd02ee01f911559192 /src/video_core | |
| parent | Merge pull request #3374 from lioncash/udp (diff) | |
| parent | ci: Disable Vulkan for Windows MinGW builds (diff) | |
| download | yuzu-c31ec00d676f6dda0bebee70d7a0b230e5babee9.tar.gz yuzu-c31ec00d676f6dda0bebee70d7a0b230e5babee9.tar.xz yuzu-c31ec00d676f6dda0bebee70d7a0b230e5babee9.zip | |
Merge pull request #3337 from ReinUsesLisp/vulkan-staged
yuzu: Implement Vulkan frontend
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/video_core/buffer_cache/buffer_cache.h | 5 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/renderer_vulkan.cpp | 265 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_device.cpp | 6 | ||||
| -rw-r--r-- | src/video_core/shader/decode/other.cpp | 9 | ||||
| -rw-r--r-- | src/video_core/video_core.cpp | 15 |
6 files changed, 294 insertions, 7 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 04a25da4f..db9332d00 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -156,6 +156,7 @@ if (ENABLE_VULKAN) | |||
| 156 | renderer_vulkan/maxwell_to_vk.cpp | 156 | renderer_vulkan/maxwell_to_vk.cpp |
| 157 | renderer_vulkan/maxwell_to_vk.h | 157 | renderer_vulkan/maxwell_to_vk.h |
| 158 | renderer_vulkan/renderer_vulkan.h | 158 | renderer_vulkan/renderer_vulkan.h |
| 159 | renderer_vulkan/renderer_vulkan.cpp | ||
| 159 | renderer_vulkan/vk_blit_screen.cpp | 160 | renderer_vulkan/vk_blit_screen.cpp |
| 160 | renderer_vulkan/vk_blit_screen.h | 161 | renderer_vulkan/vk_blit_screen.h |
| 161 | renderer_vulkan/vk_buffer_cache.cpp | 162 | renderer_vulkan/vk_buffer_cache.cpp |
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 0510ed777..186aca61d 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -101,7 +101,10 @@ public: | |||
| 101 | void TickFrame() { | 101 | void TickFrame() { |
| 102 | ++epoch; | 102 | ++epoch; |
| 103 | while (!pending_destruction.empty()) { | 103 | while (!pending_destruction.empty()) { |
| 104 | if (pending_destruction.front()->GetEpoch() + 1 > epoch) { | 104 | // Delay at least 4 frames before destruction. |
| 105 | // This is due to triple buffering happening on some drivers. | ||
| 106 | static constexpr u64 epochs_to_destroy = 5; | ||
| 107 | if (pending_destruction.front()->GetEpoch() + epochs_to_destroy > epoch) { | ||
| 105 | break; | 108 | break; |
| 106 | } | 109 | } |
| 107 | pending_destruction.pop_front(); | 110 | pending_destruction.pop_front(); |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp new file mode 100644 index 000000000..d5032b432 --- /dev/null +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -0,0 +1,265 @@ | |||
| 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 <memory> | ||
| 6 | #include <optional> | ||
| 7 | #include <vector> | ||
| 8 | |||
| 9 | #include <fmt/format.h> | ||
| 10 | |||
| 11 | #include "common/assert.h" | ||
| 12 | #include "common/logging/log.h" | ||
| 13 | #include "common/telemetry.h" | ||
| 14 | #include "core/core.h" | ||
| 15 | #include "core/core_timing.h" | ||
| 16 | #include "core/frontend/emu_window.h" | ||
| 17 | #include "core/memory.h" | ||
| 18 | #include "core/perf_stats.h" | ||
| 19 | #include "core/settings.h" | ||
| 20 | #include "core/telemetry_session.h" | ||
| 21 | #include "video_core/gpu.h" | ||
| 22 | #include "video_core/renderer_vulkan/declarations.h" | ||
| 23 | #include "video_core/renderer_vulkan/renderer_vulkan.h" | ||
| 24 | #include "video_core/renderer_vulkan/vk_blit_screen.h" | ||
| 25 | #include "video_core/renderer_vulkan/vk_device.h" | ||
| 26 | #include "video_core/renderer_vulkan/vk_memory_manager.h" | ||
| 27 | #include "video_core/renderer_vulkan/vk_rasterizer.h" | ||
| 28 | #include "video_core/renderer_vulkan/vk_resource_manager.h" | ||
| 29 | #include "video_core/renderer_vulkan/vk_scheduler.h" | ||
| 30 | #include "video_core/renderer_vulkan/vk_swapchain.h" | ||
| 31 | |||
| 32 | namespace Vulkan { | ||
| 33 | |||
| 34 | namespace { | ||
| 35 | |||
| 36 | VkBool32 DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity_, | ||
| 37 | VkDebugUtilsMessageTypeFlagsEXT type, | ||
| 38 | const VkDebugUtilsMessengerCallbackDataEXT* data, | ||
| 39 | [[maybe_unused]] void* user_data) { | ||
| 40 | const vk::DebugUtilsMessageSeverityFlagBitsEXT severity{severity_}; | ||
| 41 | const char* message{data->pMessage}; | ||
| 42 | |||
| 43 | if (severity & vk::DebugUtilsMessageSeverityFlagBitsEXT::eError) { | ||
| 44 | LOG_CRITICAL(Render_Vulkan, "{}", message); | ||
| 45 | } else if (severity & vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning) { | ||
| 46 | LOG_WARNING(Render_Vulkan, "{}", message); | ||
| 47 | } else if (severity & vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo) { | ||
| 48 | LOG_INFO(Render_Vulkan, "{}", message); | ||
| 49 | } else if (severity & vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose) { | ||
| 50 | LOG_DEBUG(Render_Vulkan, "{}", message); | ||
| 51 | } | ||
| 52 | return VK_FALSE; | ||
| 53 | } | ||
| 54 | |||
| 55 | std::string GetReadableVersion(u32 version) { | ||
| 56 | return fmt::format("{}.{}.{}", VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version), | ||
| 57 | VK_VERSION_PATCH(version)); | ||
| 58 | } | ||
| 59 | |||
| 60 | std::string GetDriverVersion(const VKDevice& device) { | ||
| 61 | // Extracted from | ||
| 62 | // https://github.com/SaschaWillems/vulkan.gpuinfo.org/blob/5dddea46ea1120b0df14eef8f15ff8e318e35462/functions.php#L308-L314 | ||
| 63 | const u32 version = device.GetDriverVersion(); | ||
| 64 | |||
| 65 | if (device.GetDriverID() == vk::DriverIdKHR::eNvidiaProprietary) { | ||
| 66 | const u32 major = (version >> 22) & 0x3ff; | ||
| 67 | const u32 minor = (version >> 14) & 0x0ff; | ||
| 68 | const u32 secondary = (version >> 6) & 0x0ff; | ||
| 69 | const u32 tertiary = version & 0x003f; | ||
| 70 | return fmt::format("{}.{}.{}.{}", major, minor, secondary, tertiary); | ||
| 71 | } | ||
| 72 | if (device.GetDriverID() == vk::DriverIdKHR::eIntelProprietaryWindows) { | ||
| 73 | const u32 major = version >> 14; | ||
| 74 | const u32 minor = version & 0x3fff; | ||
| 75 | return fmt::format("{}.{}", major, minor); | ||
| 76 | } | ||
| 77 | |||
| 78 | return GetReadableVersion(version); | ||
| 79 | } | ||
| 80 | |||
| 81 | std::string BuildCommaSeparatedExtensions(std::vector<std::string> available_extensions) { | ||
| 82 | std::sort(std::begin(available_extensions), std::end(available_extensions)); | ||
| 83 | |||
| 84 | static constexpr std::size_t AverageExtensionSize = 64; | ||
| 85 | std::string separated_extensions; | ||
| 86 | separated_extensions.reserve(available_extensions.size() * AverageExtensionSize); | ||
| 87 | |||
| 88 | const auto end = std::end(available_extensions); | ||
| 89 | for (auto extension = std::begin(available_extensions); extension != end; ++extension) { | ||
| 90 | if (const bool is_last = extension + 1 == end; is_last) { | ||
| 91 | separated_extensions += *extension; | ||
| 92 | } else { | ||
| 93 | separated_extensions += fmt::format("{},", *extension); | ||
| 94 | } | ||
| 95 | } | ||
| 96 | return separated_extensions; | ||
| 97 | } | ||
| 98 | |||
| 99 | } // Anonymous namespace | ||
| 100 | |||
| 101 | RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system) | ||
| 102 | : RendererBase(window), system{system} {} | ||
| 103 | |||
| 104 | RendererVulkan::~RendererVulkan() { | ||
| 105 | ShutDown(); | ||
| 106 | } | ||
| 107 | |||
| 108 | void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | ||
| 109 | const auto& layout = render_window.GetFramebufferLayout(); | ||
| 110 | if (framebuffer && layout.width > 0 && layout.height > 0 && render_window.IsShown()) { | ||
| 111 | const VAddr framebuffer_addr = framebuffer->address + framebuffer->offset; | ||
| 112 | const bool use_accelerated = | ||
| 113 | rasterizer->AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride); | ||
| 114 | const bool is_srgb = use_accelerated && screen_info.is_srgb; | ||
| 115 | if (swapchain->HasFramebufferChanged(layout) || swapchain->GetSrgbState() != is_srgb) { | ||
| 116 | swapchain->Create(layout.width, layout.height, is_srgb); | ||
| 117 | blit_screen->Recreate(); | ||
| 118 | } | ||
| 119 | |||
| 120 | scheduler->WaitWorker(); | ||
| 121 | |||
| 122 | swapchain->AcquireNextImage(); | ||
| 123 | const auto [fence, render_semaphore] = blit_screen->Draw(*framebuffer, use_accelerated); | ||
| 124 | |||
| 125 | scheduler->Flush(false, render_semaphore); | ||
| 126 | |||
| 127 | if (swapchain->Present(render_semaphore, fence)) { | ||
| 128 | blit_screen->Recreate(); | ||
| 129 | } | ||
| 130 | |||
| 131 | render_window.SwapBuffers(); | ||
| 132 | rasterizer->TickFrame(); | ||
| 133 | } | ||
| 134 | |||
| 135 | render_window.PollEvents(); | ||
| 136 | } | ||
| 137 | |||
| 138 | bool RendererVulkan::Init() { | ||
| 139 | PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr{}; | ||
| 140 | render_window.RetrieveVulkanHandlers(&vkGetInstanceProcAddr, &instance, &surface); | ||
| 141 | const vk::DispatchLoaderDynamic dldi(instance, vkGetInstanceProcAddr); | ||
| 142 | |||
| 143 | std::optional<vk::DebugUtilsMessengerEXT> callback; | ||
| 144 | if (Settings::values.renderer_debug && dldi.vkCreateDebugUtilsMessengerEXT) { | ||
| 145 | callback = CreateDebugCallback(dldi); | ||
| 146 | if (!callback) { | ||
| 147 | return false; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | if (!PickDevices(dldi)) { | ||
| 152 | if (callback) { | ||
| 153 | instance.destroy(*callback, nullptr, dldi); | ||
| 154 | } | ||
| 155 | return false; | ||
| 156 | } | ||
| 157 | debug_callback = UniqueDebugUtilsMessengerEXT( | ||
| 158 | *callback, vk::ObjectDestroy<vk::Instance, vk::DispatchLoaderDynamic>( | ||
| 159 | instance, nullptr, device->GetDispatchLoader())); | ||
| 160 | |||
| 161 | Report(); | ||
| 162 | |||
| 163 | memory_manager = std::make_unique<VKMemoryManager>(*device); | ||
| 164 | |||
| 165 | resource_manager = std::make_unique<VKResourceManager>(*device); | ||
| 166 | |||
| 167 | const auto& framebuffer = render_window.GetFramebufferLayout(); | ||
| 168 | swapchain = std::make_unique<VKSwapchain>(surface, *device); | ||
| 169 | swapchain->Create(framebuffer.width, framebuffer.height, false); | ||
| 170 | |||
| 171 | scheduler = std::make_unique<VKScheduler>(*device, *resource_manager); | ||
| 172 | |||
| 173 | rasterizer = std::make_unique<RasterizerVulkan>(system, render_window, screen_info, *device, | ||
| 174 | *resource_manager, *memory_manager, *scheduler); | ||
| 175 | |||
| 176 | blit_screen = std::make_unique<VKBlitScreen>(system, render_window, *rasterizer, *device, | ||
| 177 | *resource_manager, *memory_manager, *swapchain, | ||
| 178 | *scheduler, screen_info); | ||
| 179 | |||
| 180 | return true; | ||
| 181 | } | ||
| 182 | |||
| 183 | void RendererVulkan::ShutDown() { | ||
| 184 | if (!device) { | ||
| 185 | return; | ||
| 186 | } | ||
| 187 | const auto dev = device->GetLogical(); | ||
| 188 | const auto& dld = device->GetDispatchLoader(); | ||
| 189 | if (dev && dld.vkDeviceWaitIdle) { | ||
| 190 | dev.waitIdle(dld); | ||
| 191 | } | ||
| 192 | |||
| 193 | rasterizer.reset(); | ||
| 194 | blit_screen.reset(); | ||
| 195 | scheduler.reset(); | ||
| 196 | swapchain.reset(); | ||
| 197 | memory_manager.reset(); | ||
| 198 | resource_manager.reset(); | ||
| 199 | device.reset(); | ||
| 200 | } | ||
| 201 | |||
| 202 | std::optional<vk::DebugUtilsMessengerEXT> RendererVulkan::CreateDebugCallback( | ||
| 203 | const vk::DispatchLoaderDynamic& dldi) { | ||
| 204 | const vk::DebugUtilsMessengerCreateInfoEXT callback_ci( | ||
| 205 | {}, | ||
| 206 | vk::DebugUtilsMessageSeverityFlagBitsEXT::eError | | ||
| 207 | vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | | ||
| 208 | vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo | | ||
| 209 | vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose, | ||
| 210 | vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | | ||
| 211 | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation | | ||
| 212 | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance, | ||
| 213 | &DebugCallback, nullptr); | ||
| 214 | vk::DebugUtilsMessengerEXT callback; | ||
| 215 | if (instance.createDebugUtilsMessengerEXT(&callback_ci, nullptr, &callback, dldi) != | ||
| 216 | vk::Result::eSuccess) { | ||
| 217 | LOG_ERROR(Render_Vulkan, "Failed to create debug callback"); | ||
| 218 | return {}; | ||
| 219 | } | ||
| 220 | return callback; | ||
| 221 | } | ||
| 222 | |||
| 223 | bool RendererVulkan::PickDevices(const vk::DispatchLoaderDynamic& dldi) { | ||
| 224 | const auto devices = instance.enumeratePhysicalDevices(dldi); | ||
| 225 | |||
| 226 | // TODO(Rodrigo): Choose device from config file | ||
| 227 | const s32 device_index = Settings::values.vulkan_device; | ||
| 228 | if (device_index < 0 || device_index >= static_cast<s32>(devices.size())) { | ||
| 229 | LOG_ERROR(Render_Vulkan, "Invalid device index {}!", device_index); | ||
| 230 | return false; | ||
| 231 | } | ||
| 232 | const vk::PhysicalDevice physical_device = devices[device_index]; | ||
| 233 | |||
| 234 | if (!VKDevice::IsSuitable(dldi, physical_device, surface)) { | ||
| 235 | return false; | ||
| 236 | } | ||
| 237 | |||
| 238 | device = std::make_unique<VKDevice>(dldi, physical_device, surface); | ||
| 239 | return device->Create(dldi, instance); | ||
| 240 | } | ||
| 241 | |||
| 242 | void RendererVulkan::Report() const { | ||
| 243 | const std::string vendor_name{device->GetVendorName()}; | ||
| 244 | const std::string model_name{device->GetModelName()}; | ||
| 245 | const std::string driver_version = GetDriverVersion(*device); | ||
| 246 | const std::string driver_name = fmt::format("{} {}", vendor_name, driver_version); | ||
| 247 | |||
| 248 | const std::string api_version = GetReadableVersion(device->GetApiVersion()); | ||
| 249 | |||
| 250 | const std::string extensions = BuildCommaSeparatedExtensions(device->GetAvailableExtensions()); | ||
| 251 | |||
| 252 | LOG_INFO(Render_Vulkan, "Driver: {}", driver_name); | ||
| 253 | LOG_INFO(Render_Vulkan, "Device: {}", model_name); | ||
| 254 | LOG_INFO(Render_Vulkan, "Vulkan: {}", api_version); | ||
| 255 | |||
| 256 | auto& telemetry_session = system.TelemetrySession(); | ||
| 257 | constexpr auto field = Telemetry::FieldType::UserSystem; | ||
| 258 | telemetry_session.AddField(field, "GPU_Vendor", vendor_name); | ||
| 259 | telemetry_session.AddField(field, "GPU_Model", model_name); | ||
| 260 | telemetry_session.AddField(field, "GPU_Vulkan_Driver", driver_name); | ||
| 261 | telemetry_session.AddField(field, "GPU_Vulkan_Version", api_version); | ||
| 262 | telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions); | ||
| 263 | } | ||
| 264 | |||
| 265 | } // namespace Vulkan \ No newline at end of file | ||
diff --git a/src/video_core/renderer_vulkan/vk_device.cpp b/src/video_core/renderer_vulkan/vk_device.cpp index 939eebe83..9840f26e5 100644 --- a/src/video_core/renderer_vulkan/vk_device.cpp +++ b/src/video_core/renderer_vulkan/vk_device.cpp | |||
| @@ -400,8 +400,10 @@ std::vector<const char*> VKDevice::LoadExtensions(const vk::DispatchLoaderDynami | |||
| 400 | VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, true); | 400 | VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, true); |
| 401 | Test(extension, ext_subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, | 401 | Test(extension, ext_subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, |
| 402 | false); | 402 | false); |
| 403 | Test(extension, nv_device_diagnostic_checkpoints, | 403 | if (Settings::values.renderer_debug) { |
| 404 | VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME, true); | 404 | Test(extension, nv_device_diagnostic_checkpoints, |
| 405 | VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME, true); | ||
| 406 | } | ||
| 405 | } | 407 | } |
| 406 | 408 | ||
| 407 | if (khr_shader_float16_int8) { | 409 | if (khr_shader_float16_int8) { |
diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp index 7321698b2..4944e9d69 100644 --- a/src/video_core/shader/decode/other.cpp +++ b/src/video_core/shader/decode/other.cpp | |||
| @@ -69,13 +69,16 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { | |||
| 69 | case OpCode::Id::MOV_SYS: { | 69 | case OpCode::Id::MOV_SYS: { |
| 70 | const Node value = [this, instr] { | 70 | const Node value = [this, instr] { |
| 71 | switch (instr.sys20) { | 71 | switch (instr.sys20) { |
| 72 | case SystemVariable::LaneId: | ||
| 73 | LOG_WARNING(HW_GPU, "MOV_SYS instruction with LaneId is incomplete"); | ||
| 74 | return Immediate(0U); | ||
| 72 | case SystemVariable::InvocationId: | 75 | case SystemVariable::InvocationId: |
| 73 | return Operation(OperationCode::InvocationId); | 76 | return Operation(OperationCode::InvocationId); |
| 74 | case SystemVariable::Ydirection: | 77 | case SystemVariable::Ydirection: |
| 75 | return Operation(OperationCode::YNegate); | 78 | return Operation(OperationCode::YNegate); |
| 76 | case SystemVariable::InvocationInfo: | 79 | case SystemVariable::InvocationInfo: |
| 77 | LOG_WARNING(HW_GPU, "MOV_SYS instruction with InvocationInfo is incomplete"); | 80 | LOG_WARNING(HW_GPU, "MOV_SYS instruction with InvocationInfo is incomplete"); |
| 78 | return Immediate(0u); | 81 | return Immediate(0U); |
| 79 | case SystemVariable::Tid: { | 82 | case SystemVariable::Tid: { |
| 80 | Node value = Immediate(0); | 83 | Node value = Immediate(0); |
| 81 | value = BitfieldInsert(value, Operation(OperationCode::LocalInvocationIdX), 0, 9); | 84 | value = BitfieldInsert(value, Operation(OperationCode::LocalInvocationIdX), 0, 9); |
| @@ -188,7 +191,7 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { | |||
| 188 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ConditionCode::T, "SYNC condition code used: {}", | 191 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ConditionCode::T, "SYNC condition code used: {}", |
| 189 | static_cast<u32>(cc)); | 192 | static_cast<u32>(cc)); |
| 190 | 193 | ||
| 191 | if (disable_flow_stack) { | 194 | if (decompiled) { |
| 192 | break; | 195 | break; |
| 193 | } | 196 | } |
| 194 | 197 | ||
| @@ -200,7 +203,7 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { | |||
| 200 | const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; | 203 | const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; |
| 201 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ConditionCode::T, "BRK condition code used: {}", | 204 | UNIMPLEMENTED_IF_MSG(cc != Tegra::Shader::ConditionCode::T, "BRK condition code used: {}", |
| 202 | static_cast<u32>(cc)); | 205 | static_cast<u32>(cc)); |
| 203 | if (disable_flow_stack) { | 206 | if (decompiled) { |
| 204 | break; | 207 | break; |
| 205 | } | 208 | } |
| 206 | 209 | ||
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index 8e947394c..a5f81a8a0 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp | |||
| @@ -3,19 +3,32 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | #include "common/logging/log.h" | ||
| 6 | #include "core/core.h" | 7 | #include "core/core.h" |
| 7 | #include "core/settings.h" | 8 | #include "core/settings.h" |
| 8 | #include "video_core/gpu_asynch.h" | 9 | #include "video_core/gpu_asynch.h" |
| 9 | #include "video_core/gpu_synch.h" | 10 | #include "video_core/gpu_synch.h" |
| 10 | #include "video_core/renderer_base.h" | 11 | #include "video_core/renderer_base.h" |
| 11 | #include "video_core/renderer_opengl/renderer_opengl.h" | 12 | #include "video_core/renderer_opengl/renderer_opengl.h" |
| 13 | #ifdef HAS_VULKAN | ||
| 14 | #include "video_core/renderer_vulkan/renderer_vulkan.h" | ||
| 15 | #endif | ||
| 12 | #include "video_core/video_core.h" | 16 | #include "video_core/video_core.h" |
| 13 | 17 | ||
| 14 | namespace VideoCore { | 18 | namespace VideoCore { |
| 15 | 19 | ||
| 16 | std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window, | 20 | std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window, |
| 17 | Core::System& system) { | 21 | Core::System& system) { |
| 18 | return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system); | 22 | switch (Settings::values.renderer_backend) { |
| 23 | case Settings::RendererBackend::OpenGL: | ||
| 24 | return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system); | ||
| 25 | #ifdef HAS_VULKAN | ||
| 26 | case Settings::RendererBackend::Vulkan: | ||
| 27 | return std::make_unique<Vulkan::RendererVulkan>(emu_window, system); | ||
| 28 | #endif | ||
| 29 | default: | ||
| 30 | return nullptr; | ||
| 31 | } | ||
| 19 | } | 32 | } |
| 20 | 33 | ||
| 21 | std::unique_ptr<Tegra::GPU> CreateGPU(Core::System& system) { | 34 | std::unique_ptr<Tegra::GPU> CreateGPU(Core::System& system) { |