diff options
Diffstat (limited to 'src')
23 files changed, 173 insertions, 76 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/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp index 26dec7147..053e8f9dd 100644 --- a/src/core/hle/service/audio/audin_u.cpp +++ b/src/core/hle/service/audio/audin_u.cpp | |||
| @@ -203,8 +203,9 @@ private: | |||
| 203 | }; | 203 | }; |
| 204 | 204 | ||
| 205 | AudInU::AudInU(Core::System& system_) | 205 | AudInU::AudInU(Core::System& system_) |
| 206 | : ServiceFramework{system_, "audin:u"}, service_context{system_, "AudInU"}, | 206 | : ServiceFramework{system_, "audin:u", ServiceThreadType::CreateNew}, |
| 207 | impl{std::make_unique<AudioCore::AudioIn::Manager>(system_)} { | 207 | service_context{system_, "AudInU"}, impl{std::make_unique<AudioCore::AudioIn::Manager>( |
| 208 | system_)} { | ||
| 208 | // clang-format off | 209 | // clang-format off |
| 209 | static const FunctionInfo functions[] = { | 210 | static const FunctionInfo functions[] = { |
| 210 | {0, &AudInU::ListAudioIns, "ListAudioIns"}, | 211 | {0, &AudInU::ListAudioIns, "ListAudioIns"}, |
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 991e30ba1..29751f075 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp | |||
| @@ -26,8 +26,9 @@ public: | |||
| 26 | explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager, | 26 | explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager, |
| 27 | size_t session_id, const std::string& device_name, | 27 | size_t session_id, const std::string& device_name, |
| 28 | const AudioOutParameter& in_params, u32 handle, u64 applet_resource_user_id) | 28 | const AudioOutParameter& in_params, u32 handle, u64 applet_resource_user_id) |
| 29 | : ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"}, | 29 | : ServiceFramework{system_, "IAudioOut", ServiceThreadType::CreateNew}, |
| 30 | event{service_context.CreateEvent("AudioOutEvent")}, | 30 | service_context{system_, "IAudioOut"}, event{service_context.CreateEvent( |
| 31 | "AudioOutEvent")}, | ||
| 31 | impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} { | 32 | impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} { |
| 32 | 33 | ||
| 33 | // clang-format off | 34 | // clang-format off |
| @@ -220,8 +221,9 @@ private: | |||
| 220 | }; | 221 | }; |
| 221 | 222 | ||
| 222 | AudOutU::AudOutU(Core::System& system_) | 223 | AudOutU::AudOutU(Core::System& system_) |
| 223 | : ServiceFramework{system_, "audout:u"}, service_context{system_, "AudOutU"}, | 224 | : ServiceFramework{system_, "audout:u", ServiceThreadType::CreateNew}, |
| 224 | impl{std::make_unique<AudioCore::AudioOut::Manager>(system_)} { | 225 | service_context{system_, "AudOutU"}, impl{std::make_unique<AudioCore::AudioOut::Manager>( |
| 226 | system_)} { | ||
| 225 | // clang-format off | 227 | // clang-format off |
| 226 | static const FunctionInfo functions[] = { | 228 | static const FunctionInfo functions[] = { |
| 227 | {0, &AudOutU::ListAudioOuts, "ListAudioOuts"}, | 229 | {0, &AudOutU::ListAudioOuts, "ListAudioOuts"}, |
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index ead16c321..3a1c231b6 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp | |||
| @@ -35,9 +35,10 @@ public: | |||
| 35 | AudioCore::AudioRendererParameterInternal& params, | 35 | AudioCore::AudioRendererParameterInternal& params, |
| 36 | Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, | 36 | Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, |
| 37 | u32 process_handle, u64 applet_resource_user_id, s32 session_id) | 37 | u32 process_handle, u64 applet_resource_user_id, s32 session_id) |
| 38 | : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"}, | 38 | : ServiceFramework{system_, "IAudioRenderer", ServiceThreadType::CreateNew}, |
| 39 | rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_}, | 39 | service_context{system_, "IAudioRenderer"}, rendered_event{service_context.CreateEvent( |
| 40 | impl{std::make_unique<Renderer>(system_, manager, rendered_event)} { | 40 | "IAudioRendererEvent")}, |
| 41 | manager{manager_}, impl{std::make_unique<Renderer>(system_, manager, rendered_event)} { | ||
| 41 | // clang-format off | 42 | // clang-format off |
| 42 | static const FunctionInfo functions[] = { | 43 | static const FunctionInfo functions[] = { |
| 43 | {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"}, | 44 | {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"}, |
| @@ -242,8 +243,10 @@ class IAudioDevice final : public ServiceFramework<IAudioDevice> { | |||
| 242 | public: | 243 | public: |
| 243 | explicit IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision, | 244 | explicit IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision, |
| 244 | u32 device_num) | 245 | u32 device_num) |
| 245 | : ServiceFramework{system_, "IAudioDevice"}, service_context{system_, "IAudioDevice"}, | 246 | : ServiceFramework{system_, "IAudioDevice", ServiceThreadType::CreateNew}, |
| 246 | impl{std::make_unique<AudioDevice>(system_, applet_resource_user_id, revision)}, | 247 | service_context{system_, "IAudioDevice"}, impl{std::make_unique<AudioDevice>( |
| 248 | system_, applet_resource_user_id, | ||
| 249 | revision)}, | ||
| 247 | event{service_context.CreateEvent(fmt::format("IAudioDeviceEvent-{}", device_num))} { | 250 | event{service_context.CreateEvent(fmt::format("IAudioDeviceEvent-{}", device_num))} { |
| 248 | static const FunctionInfo functions[] = { | 251 | static const FunctionInfo functions[] = { |
| 249 | {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"}, | 252 | {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"}, |
| @@ -418,7 +421,7 @@ private: | |||
| 418 | }; | 421 | }; |
| 419 | 422 | ||
| 420 | AudRenU::AudRenU(Core::System& system_) | 423 | AudRenU::AudRenU(Core::System& system_) |
| 421 | : ServiceFramework{system_, "audren:u"}, | 424 | : ServiceFramework{system_, "audren:u", ServiceThreadType::CreateNew}, |
| 422 | service_context{system_, "audren:u"}, impl{std::make_unique<Manager>(system_)} { | 425 | service_context{system_, "audren:u"}, impl{std::make_unique<Manager>(system_)} { |
| 423 | // clang-format off | 426 | // clang-format off |
| 424 | static const FunctionInfo functions[] = { | 427 | static const FunctionInfo functions[] = { |
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_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 558b8db56..84d36fea6 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp | |||
| @@ -285,6 +285,9 @@ void BufferCacheRuntime::BindQuadArrayIndexBuffer(u32 first, u32 count) { | |||
| 285 | 285 | ||
| 286 | void BufferCacheRuntime::BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size, | 286 | void BufferCacheRuntime::BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size, |
| 287 | u32 stride) { | 287 | u32 stride) { |
| 288 | if (index >= device.GetMaxVertexInputBindings()) { | ||
| 289 | return; | ||
| 290 | } | ||
| 288 | if (device.IsExtExtendedDynamicStateSupported()) { | 291 | if (device.IsExtExtendedDynamicStateSupported()) { |
| 289 | scheduler.Record([index, buffer, offset, size, stride](vk::CommandBuffer cmdbuf) { | 292 | scheduler.Record([index, buffer, offset, size, stride](vk::CommandBuffer cmdbuf) { |
| 290 | const VkDeviceSize vk_offset = buffer != VK_NULL_HANDLE ? offset : 0; | 293 | const VkDeviceSize vk_offset = buffer != VK_NULL_HANDLE ? offset : 0; |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 006128638..4b10fe7bc 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -529,7 +529,9 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { | |||
| 529 | static_vector<VkVertexInputBindingDivisorDescriptionEXT, 32> vertex_binding_divisors; | 529 | static_vector<VkVertexInputBindingDivisorDescriptionEXT, 32> vertex_binding_divisors; |
| 530 | static_vector<VkVertexInputAttributeDescription, 32> vertex_attributes; | 530 | static_vector<VkVertexInputAttributeDescription, 32> vertex_attributes; |
| 531 | if (key.state.dynamic_vertex_input) { | 531 | if (key.state.dynamic_vertex_input) { |
| 532 | for (size_t index = 0; index < key.state.attributes.size(); ++index) { | 532 | const size_t num_vertex_arrays = std::min( |
| 533 | key.state.attributes.size(), static_cast<size_t>(device.GetMaxVertexInputBindings())); | ||
| 534 | for (size_t index = 0; index < num_vertex_arrays; ++index) { | ||
| 533 | const u32 type = key.state.DynamicAttributeType(index); | 535 | const u32 type = key.state.DynamicAttributeType(index); |
| 534 | if (!stage_infos[0].loads.Generic(index) || type == 0) { | 536 | if (!stage_infos[0].loads.Generic(index) || type == 0) { |
| 535 | continue; | 537 | continue; |
| @@ -551,7 +553,9 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { | |||
| 551 | }); | 553 | }); |
| 552 | } | 554 | } |
| 553 | } else { | 555 | } else { |
| 554 | for (size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { | 556 | const size_t num_vertex_arrays = std::min( |
| 557 | Maxwell::NumVertexArrays, static_cast<size_t>(device.GetMaxVertexInputBindings())); | ||
| 558 | for (size_t index = 0; index < num_vertex_arrays; ++index) { | ||
| 555 | const bool instanced = key.state.binding_divisors[index] != 0; | 559 | const bool instanced = key.state.binding_divisors[index] != 0; |
| 556 | const auto rate = | 560 | const auto rate = |
| 557 | instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; | 561 | instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX; |
| @@ -580,6 +584,8 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { | |||
| 580 | }); | 584 | }); |
| 581 | } | 585 | } |
| 582 | } | 586 | } |
| 587 | ASSERT(vertex_attributes.size() <= device.GetMaxVertexInputAttributes()); | ||
| 588 | |||
| 583 | VkPipelineVertexInputStateCreateInfo vertex_input_ci{ | 589 | VkPipelineVertexInputStateCreateInfo vertex_input_ci{ |
| 584 | .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, | 590 | .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, |
| 585 | .pNext = nullptr, | 591 | .pNext = nullptr, |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 81f5f3e11..86fdde014 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -341,6 +341,15 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device | |||
| 341 | .support_snorm_render_buffer = true, | 341 | .support_snorm_render_buffer = true, |
| 342 | .support_viewport_index_layer = device.IsExtShaderViewportIndexLayerSupported(), | 342 | .support_viewport_index_layer = device.IsExtShaderViewportIndexLayerSupported(), |
| 343 | }; | 343 | }; |
| 344 | |||
| 345 | if (device.GetMaxVertexInputAttributes() < Maxwell::NumVertexAttributes) { | ||
| 346 | LOG_WARNING(Render_Vulkan, "maxVertexInputAttributes is too low: {} < {}", | ||
| 347 | device.GetMaxVertexInputAttributes(), Maxwell::NumVertexAttributes); | ||
| 348 | } | ||
| 349 | if (device.GetMaxVertexInputBindings() < Maxwell::NumVertexArrays) { | ||
| 350 | LOG_WARNING(Render_Vulkan, "maxVertexInputBindings is too low: {} < {}", | ||
| 351 | device.GetMaxVertexInputBindings(), Maxwell::NumVertexArrays); | ||
| 352 | } | ||
| 344 | } | 353 | } |
| 345 | 354 | ||
| 346 | PipelineCache::~PipelineCache() = default; | 355 | PipelineCache::~PipelineCache() = default; |
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/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 6a2ad4b1d..67540cb80 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -1380,6 +1380,10 @@ void Device::SetupFeatures() { | |||
| 1380 | is_shader_storage_image_multisample = features.shaderStorageImageMultisample; | 1380 | is_shader_storage_image_multisample = features.shaderStorageImageMultisample; |
| 1381 | is_blit_depth_stencil_supported = TestDepthStencilBlits(); | 1381 | is_blit_depth_stencil_supported = TestDepthStencilBlits(); |
| 1382 | is_optimal_astc_supported = IsOptimalAstcSupported(features); | 1382 | is_optimal_astc_supported = IsOptimalAstcSupported(features); |
| 1383 | |||
| 1384 | const VkPhysicalDeviceLimits& limits{properties.limits}; | ||
| 1385 | max_vertex_input_attributes = limits.maxVertexInputAttributes; | ||
| 1386 | max_vertex_input_bindings = limits.maxVertexInputBindings; | ||
| 1383 | } | 1387 | } |
| 1384 | 1388 | ||
| 1385 | void Device::SetupProperties() { | 1389 | void Device::SetupProperties() { |
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index db802437c..391b7604c 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h | |||
| @@ -368,6 +368,14 @@ public: | |||
| 368 | return must_emulate_bgr565; | 368 | return must_emulate_bgr565; |
| 369 | } | 369 | } |
| 370 | 370 | ||
| 371 | u32 GetMaxVertexInputAttributes() const { | ||
| 372 | return max_vertex_input_attributes; | ||
| 373 | } | ||
| 374 | |||
| 375 | u32 GetMaxVertexInputBindings() const { | ||
| 376 | return max_vertex_input_bindings; | ||
| 377 | } | ||
| 378 | |||
| 371 | private: | 379 | private: |
| 372 | /// Checks if the physical device is suitable. | 380 | /// Checks if the physical device is suitable. |
| 373 | void CheckSuitability(bool requires_swapchain) const; | 381 | void CheckSuitability(bool requires_swapchain) const; |
| @@ -467,6 +475,8 @@ private: | |||
| 467 | bool supports_d24_depth{}; ///< Supports D24 depth buffers. | 475 | bool supports_d24_depth{}; ///< Supports D24 depth buffers. |
| 468 | bool cant_blit_msaa{}; ///< Does not support MSAA<->MSAA blitting. | 476 | bool cant_blit_msaa{}; ///< Does not support MSAA<->MSAA blitting. |
| 469 | bool must_emulate_bgr565{}; ///< Emulates BGR565 by swizzling RGB565 format. | 477 | bool must_emulate_bgr565{}; ///< Emulates BGR565 by swizzling RGB565 format. |
| 478 | u32 max_vertex_input_attributes{}; ///< Max vertex input attributes in pipeline | ||
| 479 | u32 max_vertex_input_bindings{}; ///< Max vertex input buffers in pipeline | ||
| 470 | 480 | ||
| 471 | // Telemetry parameters | 481 | // Telemetry parameters |
| 472 | std::string vendor_name; ///< Device's driver name. | 482 | std::string vendor_name; ///< Device's driver name. |
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) { |