diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/frontend/emu_window.h | 6 | ||||
| -rw-r--r-- | src/video_core/gpu.cpp | 5 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_device.cpp | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_device.h | 8 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 76 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.h | 1 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 4 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/renderer_vulkan.cpp | 14 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_swapchain.cpp | 15 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_swapchain.h | 14 | ||||
| -rw-r--r-- | src/yuzu/bootmanager.cpp | 12 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 13 | ||||
| -rw-r--r-- | src/yuzu/main.h | 1 | ||||
| -rw-r--r-- | src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp | 2 |
15 files changed, 121 insertions, 62 deletions
diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h index 95363b645..cf85ba29e 100644 --- a/src/core/frontend/emu_window.h +++ b/src/core/frontend/emu_window.h | |||
| @@ -131,6 +131,10 @@ public: | |||
| 131 | return active_config; | 131 | return active_config; |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | bool StrictContextRequired() const { | ||
| 135 | return strict_context_required; | ||
| 136 | } | ||
| 137 | |||
| 134 | /** | 138 | /** |
| 135 | * Requests the internal configuration to be replaced by the specified argument at some point in | 139 | * Requests the internal configuration to be replaced by the specified argument at some point in |
| 136 | * the future. | 140 | * the future. |
| @@ -207,6 +211,8 @@ protected: | |||
| 207 | 211 | ||
| 208 | WindowSystemInfo window_info; | 212 | WindowSystemInfo window_info; |
| 209 | 213 | ||
| 214 | bool strict_context_required = false; | ||
| 215 | |||
| 210 | private: | 216 | private: |
| 211 | /** | 217 | /** |
| 212 | * Handler called when the minimal client area was requested to be changed via SetConfig. | 218 | * Handler called when the minimal client area was requested to be changed via SetConfig. |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 28b38273e..c6d54be63 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -223,8 +223,6 @@ struct GPU::Impl { | |||
| 223 | /// core timing events. | 223 | /// core timing events. |
| 224 | void Start() { | 224 | void Start() { |
| 225 | gpu_thread.StartThread(*renderer, renderer->Context(), *scheduler); | 225 | gpu_thread.StartThread(*renderer, renderer->Context(), *scheduler); |
| 226 | cpu_context = renderer->GetRenderWindow().CreateSharedContext(); | ||
| 227 | cpu_context->MakeCurrent(); | ||
| 228 | } | 226 | } |
| 229 | 227 | ||
| 230 | void NotifyShutdown() { | 228 | void NotifyShutdown() { |
| @@ -235,6 +233,9 @@ struct GPU::Impl { | |||
| 235 | 233 | ||
| 236 | /// Obtain the CPU Context | 234 | /// Obtain the CPU Context |
| 237 | void ObtainContext() { | 235 | void ObtainContext() { |
| 236 | if (!cpu_context) { | ||
| 237 | cpu_context = renderer->GetRenderWindow().CreateSharedContext(); | ||
| 238 | } | ||
| 238 | cpu_context->MakeCurrent(); | 239 | cpu_context->MakeCurrent(); |
| 239 | } | 240 | } |
| 240 | 241 | ||
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index e2e3dac34..cee5c3247 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
| @@ -112,7 +112,7 @@ bool IsASTCSupported() { | |||
| 112 | } | 112 | } |
| 113 | } // Anonymous namespace | 113 | } // Anonymous namespace |
| 114 | 114 | ||
| 115 | Device::Device() { | 115 | Device::Device(Core::Frontend::EmuWindow& emu_window) { |
| 116 | if (!GLAD_GL_VERSION_4_6) { | 116 | if (!GLAD_GL_VERSION_4_6) { |
| 117 | LOG_ERROR(Render_OpenGL, "OpenGL 4.6 is not available"); | 117 | LOG_ERROR(Render_OpenGL, "OpenGL 4.6 is not available"); |
| 118 | throw std::runtime_error{"Insufficient version"}; | 118 | throw std::runtime_error{"Insufficient version"}; |
| @@ -126,9 +126,9 @@ Device::Device() { | |||
| 126 | const bool is_intel = vendor_name == "Intel"; | 126 | const bool is_intel = vendor_name == "Intel"; |
| 127 | 127 | ||
| 128 | #ifdef __unix__ | 128 | #ifdef __unix__ |
| 129 | const bool is_linux = true; | 129 | constexpr bool is_linux = true; |
| 130 | #else | 130 | #else |
| 131 | const bool is_linux = false; | 131 | constexpr bool is_linux = false; |
| 132 | #endif | 132 | #endif |
| 133 | 133 | ||
| 134 | bool disable_fast_buffer_sub_data = false; | 134 | bool disable_fast_buffer_sub_data = false; |
| @@ -193,9 +193,11 @@ Device::Device() { | |||
| 193 | } | 193 | } |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | strict_context_required = emu_window.StrictContextRequired(); | ||
| 196 | // Blocks AMD and Intel OpenGL drivers on Windows from using asynchronous shader compilation. | 197 | // Blocks AMD and Intel OpenGL drivers on Windows from using asynchronous shader compilation. |
| 198 | // Blocks EGL on Wayland from using asynchronous shader compilation. | ||
| 197 | use_asynchronous_shaders = Settings::values.use_asynchronous_shaders.GetValue() && | 199 | use_asynchronous_shaders = Settings::values.use_asynchronous_shaders.GetValue() && |
| 198 | !(is_amd || (is_intel && !is_linux)); | 200 | !(is_amd || (is_intel && !is_linux)) && !strict_context_required; |
| 199 | use_driver_cache = is_nvidia; | 201 | use_driver_cache = is_nvidia; |
| 200 | 202 | ||
| 201 | LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi); | 203 | LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi); |
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index 5ef51ebcf..2a72d84be 100644 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include <cstddef> | 6 | #include <cstddef> |
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "core/frontend/emu_window.h" | ||
| 8 | #include "shader_recompiler/stage.h" | 9 | #include "shader_recompiler/stage.h" |
| 9 | 10 | ||
| 10 | namespace Settings { | 11 | namespace Settings { |
| @@ -15,7 +16,7 @@ namespace OpenGL { | |||
| 15 | 16 | ||
| 16 | class Device { | 17 | class Device { |
| 17 | public: | 18 | public: |
| 18 | explicit Device(); | 19 | explicit Device(Core::Frontend::EmuWindow& emu_window); |
| 19 | 20 | ||
| 20 | [[nodiscard]] std::string GetVendorName() const; | 21 | [[nodiscard]] std::string GetVendorName() const; |
| 21 | 22 | ||
| @@ -173,6 +174,10 @@ public: | |||
| 173 | return can_report_memory; | 174 | return can_report_memory; |
| 174 | } | 175 | } |
| 175 | 176 | ||
| 177 | bool StrictContextRequired() const { | ||
| 178 | return strict_context_required; | ||
| 179 | } | ||
| 180 | |||
| 176 | private: | 181 | private: |
| 177 | static bool TestVariableAoffi(); | 182 | static bool TestVariableAoffi(); |
| 178 | static bool TestPreciseBug(); | 183 | static bool TestPreciseBug(); |
| @@ -216,6 +221,7 @@ private: | |||
| 216 | bool has_cbuf_ftou_bug{}; | 221 | bool has_cbuf_ftou_bug{}; |
| 217 | bool has_bool_ref_bug{}; | 222 | bool has_bool_ref_bug{}; |
| 218 | bool can_report_memory{}; | 223 | bool can_report_memory{}; |
| 224 | bool strict_context_required{}; | ||
| 219 | 225 | ||
| 220 | std::string vendor_name; | 226 | std::string vendor_name; |
| 221 | }; | 227 | }; |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index a59d0d24e..fff55d585 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -174,6 +174,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo | |||
| 174 | texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, program_manager{program_manager_}, | 174 | texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, program_manager{program_manager_}, |
| 175 | state_tracker{state_tracker_}, shader_notify{shader_notify_}, | 175 | state_tracker{state_tracker_}, shader_notify{shader_notify_}, |
| 176 | use_asynchronous_shaders{device.UseAsynchronousShaders()}, | 176 | use_asynchronous_shaders{device.UseAsynchronousShaders()}, |
| 177 | strict_context_required{device.StrictContextRequired()}, | ||
| 177 | profile{ | 178 | profile{ |
| 178 | .supported_spirv = 0x00010000, | 179 | .supported_spirv = 0x00010000, |
| 179 | 180 | ||
| @@ -255,9 +256,14 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | |||
| 255 | } | 256 | } |
| 256 | shader_cache_filename = base_dir / "opengl.bin"; | 257 | shader_cache_filename = base_dir / "opengl.bin"; |
| 257 | 258 | ||
| 258 | if (!workers) { | 259 | if (!workers && !strict_context_required) { |
| 259 | workers = CreateWorkers(); | 260 | workers = CreateWorkers(); |
| 260 | } | 261 | } |
| 262 | std::optional<Context> strict_context; | ||
| 263 | if (strict_context_required) { | ||
| 264 | strict_context.emplace(emu_window); | ||
| 265 | } | ||
| 266 | |||
| 261 | struct { | 267 | struct { |
| 262 | std::mutex mutex; | 268 | std::mutex mutex; |
| 263 | size_t total{}; | 269 | size_t total{}; |
| @@ -265,44 +271,49 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | |||
| 265 | bool has_loaded{}; | 271 | bool has_loaded{}; |
| 266 | } state; | 272 | } state; |
| 267 | 273 | ||
| 274 | const auto queue_work{[&](Common::UniqueFunction<void, Context*>&& work) { | ||
| 275 | if (strict_context_required) { | ||
| 276 | work(&strict_context.value()); | ||
| 277 | } else { | ||
| 278 | workers->QueueWork(std::move(work)); | ||
| 279 | } | ||
| 280 | }}; | ||
| 268 | const auto load_compute{[&](std::ifstream& file, FileEnvironment env) { | 281 | const auto load_compute{[&](std::ifstream& file, FileEnvironment env) { |
| 269 | ComputePipelineKey key; | 282 | ComputePipelineKey key; |
| 270 | file.read(reinterpret_cast<char*>(&key), sizeof(key)); | 283 | file.read(reinterpret_cast<char*>(&key), sizeof(key)); |
| 271 | workers->QueueWork( | 284 | queue_work([this, key, env = std::move(env), &state, &callback](Context* ctx) mutable { |
| 272 | [this, key, env = std::move(env), &state, &callback](Context* ctx) mutable { | 285 | ctx->pools.ReleaseContents(); |
| 273 | ctx->pools.ReleaseContents(); | 286 | auto pipeline{CreateComputePipeline(ctx->pools, key, env)}; |
| 274 | auto pipeline{CreateComputePipeline(ctx->pools, key, env)}; | 287 | std::scoped_lock lock{state.mutex}; |
| 275 | std::scoped_lock lock{state.mutex}; | 288 | if (pipeline) { |
| 276 | if (pipeline) { | 289 | compute_cache.emplace(key, std::move(pipeline)); |
| 277 | compute_cache.emplace(key, std::move(pipeline)); | 290 | } |
| 278 | } | 291 | ++state.built; |
| 279 | ++state.built; | 292 | if (state.has_loaded) { |
| 280 | if (state.has_loaded) { | 293 | callback(VideoCore::LoadCallbackStage::Build, state.built, state.total); |
| 281 | callback(VideoCore::LoadCallbackStage::Build, state.built, state.total); | 294 | } |
| 282 | } | 295 | }); |
| 283 | }); | ||
| 284 | ++state.total; | 296 | ++state.total; |
| 285 | }}; | 297 | }}; |
| 286 | const auto load_graphics{[&](std::ifstream& file, std::vector<FileEnvironment> envs) { | 298 | const auto load_graphics{[&](std::ifstream& file, std::vector<FileEnvironment> envs) { |
| 287 | GraphicsPipelineKey key; | 299 | GraphicsPipelineKey key; |
| 288 | file.read(reinterpret_cast<char*>(&key), sizeof(key)); | 300 | file.read(reinterpret_cast<char*>(&key), sizeof(key)); |
| 289 | workers->QueueWork( | 301 | queue_work([this, key, envs = std::move(envs), &state, &callback](Context* ctx) mutable { |
| 290 | [this, key, envs = std::move(envs), &state, &callback](Context* ctx) mutable { | 302 | boost::container::static_vector<Shader::Environment*, 5> env_ptrs; |
| 291 | boost::container::static_vector<Shader::Environment*, 5> env_ptrs; | 303 | for (auto& env : envs) { |
| 292 | for (auto& env : envs) { | 304 | env_ptrs.push_back(&env); |
| 293 | env_ptrs.push_back(&env); | 305 | } |
| 294 | } | 306 | ctx->pools.ReleaseContents(); |
| 295 | ctx->pools.ReleaseContents(); | 307 | auto pipeline{CreateGraphicsPipeline(ctx->pools, key, MakeSpan(env_ptrs), false)}; |
| 296 | auto pipeline{CreateGraphicsPipeline(ctx->pools, key, MakeSpan(env_ptrs), false)}; | 308 | std::scoped_lock lock{state.mutex}; |
| 297 | std::scoped_lock lock{state.mutex}; | 309 | if (pipeline) { |
| 298 | if (pipeline) { | 310 | graphics_cache.emplace(key, std::move(pipeline)); |
| 299 | graphics_cache.emplace(key, std::move(pipeline)); | 311 | } |
| 300 | } | 312 | ++state.built; |
| 301 | ++state.built; | 313 | if (state.has_loaded) { |
| 302 | if (state.has_loaded) { | 314 | callback(VideoCore::LoadCallbackStage::Build, state.built, state.total); |
| 303 | callback(VideoCore::LoadCallbackStage::Build, state.built, state.total); | 315 | } |
| 304 | } | 316 | }); |
| 305 | }); | ||
| 306 | ++state.total; | 317 | ++state.total; |
| 307 | }}; | 318 | }}; |
| 308 | LoadPipelines(stop_loading, shader_cache_filename, CACHE_VERSION, load_compute, load_graphics); | 319 | LoadPipelines(stop_loading, shader_cache_filename, CACHE_VERSION, load_compute, load_graphics); |
| @@ -314,6 +325,9 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | |||
| 314 | state.has_loaded = true; | 325 | state.has_loaded = true; |
| 315 | lock.unlock(); | 326 | lock.unlock(); |
| 316 | 327 | ||
| 328 | if (strict_context_required) { | ||
| 329 | return; | ||
| 330 | } | ||
| 317 | workers->WaitForRequests(stop_loading); | 331 | workers->WaitForRequests(stop_loading); |
| 318 | if (!use_asynchronous_shaders) { | 332 | if (!use_asynchronous_shaders) { |
| 319 | workers.reset(); | 333 | workers.reset(); |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index 53ffea904..f82420592 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h | |||
| @@ -69,6 +69,7 @@ private: | |||
| 69 | StateTracker& state_tracker; | 69 | StateTracker& state_tracker; |
| 70 | VideoCore::ShaderNotify& shader_notify; | 70 | VideoCore::ShaderNotify& shader_notify; |
| 71 | const bool use_asynchronous_shaders; | 71 | const bool use_asynchronous_shaders; |
| 72 | const bool strict_context_required; | ||
| 72 | 73 | ||
| 73 | GraphicsPipelineKey graphics_key{}; | 74 | GraphicsPipelineKey graphics_key{}; |
| 74 | GraphicsPipeline* current_pipeline{}; | 75 | GraphicsPipeline* current_pipeline{}; |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 5b5e178ad..bc75680f0 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -140,8 +140,8 @@ RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_, | |||
| 140 | Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, | 140 | Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, |
| 141 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) | 141 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) |
| 142 | : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_}, | 142 | : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_}, |
| 143 | emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, state_tracker{}, | 143 | emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, device{emu_window_}, |
| 144 | program_manager{device}, | 144 | state_tracker{}, program_manager{device}, |
| 145 | rasterizer(emu_window, gpu, cpu_memory, device, screen_info, program_manager, state_tracker) { | 145 | rasterizer(emu_window, gpu, cpu_memory, device, screen_info, program_manager, state_tracker) { |
| 146 | if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) { | 146 | if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) { |
| 147 | glEnable(GL_DEBUG_OUTPUT); | 147 | glEnable(GL_DEBUG_OUTPUT); |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 18be54729..f502a7d09 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -139,23 +139,25 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 139 | RenderScreenshot(*framebuffer, use_accelerated); | 139 | RenderScreenshot(*framebuffer, use_accelerated); |
| 140 | 140 | ||
| 141 | bool has_been_recreated = false; | 141 | bool has_been_recreated = false; |
| 142 | const auto recreate_swapchain = [&] { | 142 | const auto recreate_swapchain = [&](u32 width, u32 height) { |
| 143 | if (!has_been_recreated) { | 143 | if (!has_been_recreated) { |
| 144 | has_been_recreated = true; | 144 | has_been_recreated = true; |
| 145 | scheduler.Finish(); | 145 | scheduler.Finish(); |
| 146 | } | 146 | } |
| 147 | const Layout::FramebufferLayout layout = render_window.GetFramebufferLayout(); | 147 | swapchain.Create(width, height, is_srgb); |
| 148 | swapchain.Create(layout.width, layout.height, is_srgb); | ||
| 149 | }; | 148 | }; |
| 150 | if (swapchain.NeedsRecreation(is_srgb)) { | 149 | |
| 151 | recreate_swapchain(); | 150 | const Layout::FramebufferLayout layout = render_window.GetFramebufferLayout(); |
| 151 | if (swapchain.NeedsRecreation(is_srgb) || swapchain.GetWidth() != layout.width || | ||
| 152 | swapchain.GetHeight() != layout.height) { | ||
| 153 | recreate_swapchain(layout.width, layout.height); | ||
| 152 | } | 154 | } |
| 153 | bool is_outdated; | 155 | bool is_outdated; |
| 154 | do { | 156 | do { |
| 155 | swapchain.AcquireNextImage(); | 157 | swapchain.AcquireNextImage(); |
| 156 | is_outdated = swapchain.IsOutDated(); | 158 | is_outdated = swapchain.IsOutDated(); |
| 157 | if (is_outdated) { | 159 | if (is_outdated) { |
| 158 | recreate_swapchain(); | 160 | recreate_swapchain(layout.width, layout.height); |
| 159 | } | 161 | } |
| 160 | } while (is_outdated); | 162 | } while (is_outdated); |
| 161 | if (has_been_recreated) { | 163 | if (has_been_recreated) { |
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index d7be417f5..b6810eef9 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp | |||
| @@ -67,17 +67,19 @@ VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, u32 wi | |||
| 67 | 67 | ||
| 68 | } // Anonymous namespace | 68 | } // Anonymous namespace |
| 69 | 69 | ||
| 70 | Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_, u32 width, | 70 | Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_, |
| 71 | u32 height, bool srgb) | 71 | u32 width_, u32 height_, bool srgb) |
| 72 | : surface{surface_}, device{device_}, scheduler{scheduler_} { | 72 | : surface{surface_}, device{device_}, scheduler{scheduler_} { |
| 73 | Create(width, height, srgb); | 73 | Create(width_, height_, srgb); |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | Swapchain::~Swapchain() = default; | 76 | Swapchain::~Swapchain() = default; |
| 77 | 77 | ||
| 78 | void Swapchain::Create(u32 width, u32 height, bool srgb) { | 78 | void Swapchain::Create(u32 width_, u32 height_, bool srgb) { |
| 79 | is_outdated = false; | 79 | is_outdated = false; |
| 80 | is_suboptimal = false; | 80 | is_suboptimal = false; |
| 81 | width = width_; | ||
| 82 | height = height_; | ||
| 81 | 83 | ||
| 82 | const auto physical_device = device.GetPhysical(); | 84 | const auto physical_device = device.GetPhysical(); |
| 83 | const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)}; | 85 | const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)}; |
| @@ -88,7 +90,7 @@ void Swapchain::Create(u32 width, u32 height, bool srgb) { | |||
| 88 | device.GetLogical().WaitIdle(); | 90 | device.GetLogical().WaitIdle(); |
| 89 | Destroy(); | 91 | Destroy(); |
| 90 | 92 | ||
| 91 | CreateSwapchain(capabilities, width, height, srgb); | 93 | CreateSwapchain(capabilities, srgb); |
| 92 | CreateSemaphores(); | 94 | CreateSemaphores(); |
| 93 | CreateImageViews(); | 95 | CreateImageViews(); |
| 94 | 96 | ||
| @@ -148,8 +150,7 @@ void Swapchain::Present(VkSemaphore render_semaphore) { | |||
| 148 | } | 150 | } |
| 149 | } | 151 | } |
| 150 | 152 | ||
| 151 | void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, u32 width, u32 height, | 153 | void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bool srgb) { |
| 152 | bool srgb) { | ||
| 153 | const auto physical_device{device.GetPhysical()}; | 154 | const auto physical_device{device.GetPhysical()}; |
| 154 | const auto formats{physical_device.GetSurfaceFormatsKHR(surface)}; | 155 | const auto formats{physical_device.GetSurfaceFormatsKHR(surface)}; |
| 155 | const auto present_modes{physical_device.GetSurfacePresentModesKHR(surface)}; | 156 | const auto present_modes{physical_device.GetSurfacePresentModesKHR(surface)}; |
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h index 111b3902d..caf1ff32b 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.h +++ b/src/video_core/renderer_vulkan/vk_swapchain.h | |||
| @@ -80,9 +80,16 @@ public: | |||
| 80 | return *present_semaphores[frame_index]; | 80 | return *present_semaphores[frame_index]; |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | u32 GetWidth() const { | ||
| 84 | return width; | ||
| 85 | } | ||
| 86 | |||
| 87 | u32 GetHeight() const { | ||
| 88 | return height; | ||
| 89 | } | ||
| 90 | |||
| 83 | private: | 91 | private: |
| 84 | void CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, u32 width, u32 height, | 92 | void CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bool srgb); |
| 85 | bool srgb); | ||
| 86 | void CreateSemaphores(); | 93 | void CreateSemaphores(); |
| 87 | void CreateImageViews(); | 94 | void CreateImageViews(); |
| 88 | 95 | ||
| @@ -105,6 +112,9 @@ private: | |||
| 105 | std::vector<u64> resource_ticks; | 112 | std::vector<u64> resource_ticks; |
| 106 | std::vector<vk::Semaphore> present_semaphores; | 113 | std::vector<vk::Semaphore> present_semaphores; |
| 107 | 114 | ||
| 115 | u32 width; | ||
| 116 | u32 height; | ||
| 117 | |||
| 108 | u32 image_index{}; | 118 | u32 image_index{}; |
| 109 | u32 frame_index{}; | 119 | u32 frame_index{}; |
| 110 | 120 | ||
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 5b5b6fed8..1a47fb9c9 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp | |||
| @@ -61,8 +61,6 @@ void EmuThread::run() { | |||
| 61 | 61 | ||
| 62 | // Main process has been loaded. Make the context current to this thread and begin GPU and CPU | 62 | // Main process has been loaded. Make the context current to this thread and begin GPU and CPU |
| 63 | // execution. | 63 | // execution. |
| 64 | gpu.Start(); | ||
| 65 | |||
| 66 | gpu.ObtainContext(); | 64 | gpu.ObtainContext(); |
| 67 | 65 | ||
| 68 | emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0); | 66 | emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0); |
| @@ -77,6 +75,7 @@ void EmuThread::run() { | |||
| 77 | emit LoadProgress(VideoCore::LoadCallbackStage::Complete, 0, 0); | 75 | emit LoadProgress(VideoCore::LoadCallbackStage::Complete, 0, 0); |
| 78 | 76 | ||
| 79 | gpu.ReleaseContext(); | 77 | gpu.ReleaseContext(); |
| 78 | gpu.Start(); | ||
| 80 | 79 | ||
| 81 | system.GetCpuManager().OnGpuReady(); | 80 | system.GetCpuManager().OnGpuReady(); |
| 82 | 81 | ||
| @@ -224,6 +223,7 @@ class RenderWidget : public QWidget { | |||
| 224 | public: | 223 | public: |
| 225 | explicit RenderWidget(GRenderWindow* parent) : QWidget(parent), render_window(parent) { | 224 | explicit RenderWidget(GRenderWindow* parent) : QWidget(parent), render_window(parent) { |
| 226 | setAttribute(Qt::WA_NativeWindow); | 225 | setAttribute(Qt::WA_NativeWindow); |
| 226 | setAttribute(Qt::WA_DontCreateNativeAncestors); | ||
| 227 | setAttribute(Qt::WA_PaintOnScreen); | 227 | setAttribute(Qt::WA_PaintOnScreen); |
| 228 | } | 228 | } |
| 229 | 229 | ||
| @@ -314,6 +314,8 @@ GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_, | |||
| 314 | input_subsystem->Initialize(); | 314 | input_subsystem->Initialize(); |
| 315 | this->setMouseTracking(true); | 315 | this->setMouseTracking(true); |
| 316 | 316 | ||
| 317 | strict_context_required = QGuiApplication::platformName() == QStringLiteral("wayland"); | ||
| 318 | |||
| 317 | connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete); | 319 | connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete); |
| 318 | connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &GMainWindow::OnExecuteProgram, | 320 | connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &GMainWindow::OnExecuteProgram, |
| 319 | Qt::QueuedConnection); | 321 | Qt::QueuedConnection); |
| @@ -952,6 +954,12 @@ void GRenderWindow::OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal | |||
| 952 | 954 | ||
| 953 | bool GRenderWindow::InitializeOpenGL() { | 955 | bool GRenderWindow::InitializeOpenGL() { |
| 954 | #ifdef HAS_OPENGL | 956 | #ifdef HAS_OPENGL |
| 957 | if (!QOpenGLContext::supportsThreadedOpenGL()) { | ||
| 958 | QMessageBox::warning(this, tr("OpenGL not available!"), | ||
| 959 | tr("OpenGL shared contexts are not supported.")); | ||
| 960 | return false; | ||
| 961 | } | ||
| 962 | |||
| 955 | // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, | 963 | // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, |
| 956 | // WA_DontShowOnScreen, WA_DeleteOnClose | 964 | // WA_DontShowOnScreen, WA_DeleteOnClose |
| 957 | auto child = new OpenGLRenderWidget(this); | 965 | auto child = new OpenGLRenderWidget(this); |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 6c204416f..885e24990 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -2915,9 +2915,14 @@ static QScreen* GuessCurrentScreen(QWidget* window) { | |||
| 2915 | }); | 2915 | }); |
| 2916 | } | 2916 | } |
| 2917 | 2917 | ||
| 2918 | bool GMainWindow::UsingExclusiveFullscreen() { | ||
| 2919 | return Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive || | ||
| 2920 | QGuiApplication::platformName() == QStringLiteral("wayland"); | ||
| 2921 | } | ||
| 2922 | |||
| 2918 | void GMainWindow::ShowFullscreen() { | 2923 | void GMainWindow::ShowFullscreen() { |
| 2919 | const auto show_fullscreen = [](QWidget* window) { | 2924 | const auto show_fullscreen = [this](QWidget* window) { |
| 2920 | if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive) { | 2925 | if (UsingExclusiveFullscreen()) { |
| 2921 | window->showFullScreen(); | 2926 | window->showFullScreen(); |
| 2922 | return; | 2927 | return; |
| 2923 | } | 2928 | } |
| @@ -2945,7 +2950,7 @@ void GMainWindow::ShowFullscreen() { | |||
| 2945 | 2950 | ||
| 2946 | void GMainWindow::HideFullscreen() { | 2951 | void GMainWindow::HideFullscreen() { |
| 2947 | if (ui->action_Single_Window_Mode->isChecked()) { | 2952 | if (ui->action_Single_Window_Mode->isChecked()) { |
| 2948 | if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive) { | 2953 | if (UsingExclusiveFullscreen()) { |
| 2949 | showNormal(); | 2954 | showNormal(); |
| 2950 | restoreGeometry(UISettings::values.geometry); | 2955 | restoreGeometry(UISettings::values.geometry); |
| 2951 | } else { | 2956 | } else { |
| @@ -2959,7 +2964,7 @@ void GMainWindow::HideFullscreen() { | |||
| 2959 | statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked()); | 2964 | statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked()); |
| 2960 | ui->menubar->show(); | 2965 | ui->menubar->show(); |
| 2961 | } else { | 2966 | } else { |
| 2962 | if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive) { | 2967 | if (UsingExclusiveFullscreen()) { |
| 2963 | render_window->showNormal(); | 2968 | render_window->showNormal(); |
| 2964 | render_window->restoreGeometry(UISettings::values.renderwindow_geometry); | 2969 | render_window->restoreGeometry(UISettings::values.renderwindow_geometry); |
| 2965 | } else { | 2970 | } else { |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 62d629973..27644fae5 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -320,6 +320,7 @@ private slots: | |||
| 320 | void OnDisplayTitleBars(bool); | 320 | void OnDisplayTitleBars(bool); |
| 321 | void InitializeHotkeys(); | 321 | void InitializeHotkeys(); |
| 322 | void ToggleFullscreen(); | 322 | void ToggleFullscreen(); |
| 323 | bool UsingExclusiveFullscreen(); | ||
| 323 | void ShowFullscreen(); | 324 | void ShowFullscreen(); |
| 324 | void HideFullscreen(); | 325 | void HideFullscreen(); |
| 325 | void ToggleWindowMode(); | 326 | void ToggleWindowMode(); |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index 37dd1747c..31f28a507 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | |||
| @@ -115,7 +115,7 @@ bool EmuWindow_SDL2::IsShown() const { | |||
| 115 | 115 | ||
| 116 | void EmuWindow_SDL2::OnResize() { | 116 | void EmuWindow_SDL2::OnResize() { |
| 117 | int width, height; | 117 | int width, height; |
| 118 | SDL_GetWindowSize(render_window, &width, &height); | 118 | SDL_GL_GetDrawableSize(render_window, &width, &height); |
| 119 | UpdateCurrentFramebufferLayout(width, height); | 119 | UpdateCurrentFramebufferLayout(width, height); |
| 120 | } | 120 | } |
| 121 | 121 | ||
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp index 9b660c13c..ddcb048d6 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp | |||
| @@ -104,6 +104,8 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste | |||
| 104 | exit(1); | 104 | exit(1); |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | strict_context_required = strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0; | ||
| 108 | |||
| 107 | SetWindowIcon(); | 109 | SetWindowIcon(); |
| 108 | 110 | ||
| 109 | if (fullscreen) { | 111 | if (fullscreen) { |