diff options
Diffstat (limited to 'src')
18 files changed, 269 insertions, 79 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt index 21e4e1afd..df760440f 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt | |||
| @@ -18,7 +18,8 @@ enum class IntSetting(override val key: String) : AbstractIntSetting { | |||
| 18 | RENDERER_ANTI_ALIASING("anti_aliasing"), | 18 | RENDERER_ANTI_ALIASING("anti_aliasing"), |
| 19 | RENDERER_SCREEN_LAYOUT("screen_layout"), | 19 | RENDERER_SCREEN_LAYOUT("screen_layout"), |
| 20 | RENDERER_ASPECT_RATIO("aspect_ratio"), | 20 | RENDERER_ASPECT_RATIO("aspect_ratio"), |
| 21 | AUDIO_OUTPUT_ENGINE("output_engine"); | 21 | AUDIO_OUTPUT_ENGINE("output_engine"), |
| 22 | MAX_ANISOTROPY("max_anisotropy"); | ||
| 22 | 23 | ||
| 23 | override fun getInt(needsGlobal: Boolean): Int = NativeConfig.getInt(key, needsGlobal) | 24 | override fun getInt(needsGlobal: Boolean): Int = NativeConfig.getInt(key, needsGlobal) |
| 24 | 25 | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt index 2e97aee2c..12f7aa1ab 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt | |||
| @@ -245,6 +245,15 @@ abstract class SettingsItem( | |||
| 245 | ) | 245 | ) |
| 246 | put( | 246 | put( |
| 247 | SingleChoiceSetting( | 247 | SingleChoiceSetting( |
| 248 | IntSetting.MAX_ANISOTROPY, | ||
| 249 | R.string.anisotropic_filtering, | ||
| 250 | R.string.anisotropic_filtering_description, | ||
| 251 | R.array.anisoEntries, | ||
| 252 | R.array.anisoValues | ||
| 253 | ) | ||
| 254 | ) | ||
| 255 | put( | ||
| 256 | SingleChoiceSetting( | ||
| 248 | IntSetting.AUDIO_OUTPUT_ENGINE, | 257 | IntSetting.AUDIO_OUTPUT_ENGINE, |
| 249 | R.string.audio_output_engine, | 258 | R.string.audio_output_engine, |
| 250 | 0, | 259 | 0, |
| @@ -298,6 +307,7 @@ abstract class SettingsItem( | |||
| 298 | 307 | ||
| 299 | override val key: String = FASTMEM_COMBINED | 308 | override val key: String = FASTMEM_COMBINED |
| 300 | override val isRuntimeModifiable: Boolean = false | 309 | override val isRuntimeModifiable: Boolean = false |
| 310 | override val pairedSettingKey = BooleanSetting.CPU_DEBUG_MODE.key | ||
| 301 | override val defaultValue: Boolean = true | 311 | override val defaultValue: Boolean = true |
| 302 | override val isSwitchable: Boolean = true | 312 | override val isSwitchable: Boolean = true |
| 303 | override var global: Boolean | 313 | override var global: Boolean |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt index a7e965589..db1a1076c 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt | |||
| @@ -149,6 +149,7 @@ class SettingsFragmentPresenter( | |||
| 149 | add(IntSetting.RENDERER_VSYNC.key) | 149 | add(IntSetting.RENDERER_VSYNC.key) |
| 150 | add(IntSetting.RENDERER_SCALING_FILTER.key) | 150 | add(IntSetting.RENDERER_SCALING_FILTER.key) |
| 151 | add(IntSetting.RENDERER_ANTI_ALIASING.key) | 151 | add(IntSetting.RENDERER_ANTI_ALIASING.key) |
| 152 | add(IntSetting.MAX_ANISOTROPY.key) | ||
| 152 | add(IntSetting.RENDERER_SCREEN_LAYOUT.key) | 153 | add(IntSetting.RENDERER_SCREEN_LAYOUT.key) |
| 153 | add(IntSetting.RENDERER_ASPECT_RATIO.key) | 154 | add(IntSetting.RENDERER_ASPECT_RATIO.key) |
| 154 | add(BooleanSetting.PICTURE_IN_PICTURE.key) | 155 | add(BooleanSetting.PICTURE_IN_PICTURE.key) |
diff --git a/src/android/app/src/main/res/layout/list_item_setting_switch.xml b/src/android/app/src/main/res/layout/list_item_setting_switch.xml index 5cb84182e..1c08e2e1b 100644 --- a/src/android/app/src/main/res/layout/list_item_setting_switch.xml +++ b/src/android/app/src/main/res/layout/list_item_setting_switch.xml | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | android:layout_width="0dp" | 24 | android:layout_width="0dp" |
| 25 | android:layout_height="wrap_content" | 25 | android:layout_height="wrap_content" |
| 26 | android:layout_marginEnd="24dp" | 26 | android:layout_marginEnd="24dp" |
| 27 | android:gravity="center_vertical" | 27 | android:layout_gravity="center_vertical" |
| 28 | android:orientation="vertical" | 28 | android:orientation="vertical" |
| 29 | android:layout_weight="1"> | 29 | android:layout_weight="1"> |
| 30 | 30 | ||
diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index e3915ef4f..c882a8e62 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml | |||
| @@ -267,4 +267,21 @@ | |||
| 267 | <item>3</item> | 267 | <item>3</item> |
| 268 | </integer-array> | 268 | </integer-array> |
| 269 | 269 | ||
| 270 | <string-array name="anisoEntries"> | ||
| 271 | <item>@string/auto</item> | ||
| 272 | <item>@string/slider_default</item> | ||
| 273 | <item>@string/multiplier_two</item> | ||
| 274 | <item>@string/multiplier_four</item> | ||
| 275 | <item>@string/multiplier_eight</item> | ||
| 276 | <item>@string/multiplier_sixteen</item> | ||
| 277 | </string-array> | ||
| 278 | <integer-array name="anisoValues"> | ||
| 279 | <item>0</item> | ||
| 280 | <item>1</item> | ||
| 281 | <item>2</item> | ||
| 282 | <item>3</item> | ||
| 283 | <item>4</item> | ||
| 284 | <item>5</item> | ||
| 285 | </integer-array> | ||
| 286 | |||
| 270 | </resources> | 287 | </resources> |
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 0b80b04a4..4d5c268fe 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml | |||
| @@ -225,6 +225,8 @@ | |||
| 225 | <string name="renderer_reactive_flushing_description">Improves rendering accuracy in some games at the cost of performance.</string> | 225 | <string name="renderer_reactive_flushing_description">Improves rendering accuracy in some games at the cost of performance.</string> |
| 226 | <string name="use_disk_shader_cache">Disk shader cache</string> | 226 | <string name="use_disk_shader_cache">Disk shader cache</string> |
| 227 | <string name="use_disk_shader_cache_description">Reduces stuttering by locally storing and loading generated shaders.</string> | 227 | <string name="use_disk_shader_cache_description">Reduces stuttering by locally storing and loading generated shaders.</string> |
| 228 | <string name="anisotropic_filtering">Anisotropic filtering</string> | ||
| 229 | <string name="anisotropic_filtering_description">Improves the quality of textures when viewed at oblique angles</string> | ||
| 228 | 230 | ||
| 229 | <!-- Debug settings strings --> | 231 | <!-- Debug settings strings --> |
| 230 | <string name="cpu">CPU</string> | 232 | <string name="cpu">CPU</string> |
| @@ -506,6 +508,12 @@ | |||
| 506 | <string name="oboe">oboe</string> | 508 | <string name="oboe">oboe</string> |
| 507 | <string name="cubeb">cubeb</string> | 509 | <string name="cubeb">cubeb</string> |
| 508 | 510 | ||
| 511 | <!-- Anisotropic filtering options --> | ||
| 512 | <string name="multiplier_two">2x</string> | ||
| 513 | <string name="multiplier_four">4x</string> | ||
| 514 | <string name="multiplier_eight">8x</string> | ||
| 515 | <string name="multiplier_sixteen">16x</string> | ||
| 516 | |||
| 509 | <!-- Black backgrounds theme --> | 517 | <!-- Black backgrounds theme --> |
| 510 | <string name="use_black_backgrounds">Black backgrounds</string> | 518 | <string name="use_black_backgrounds">Black backgrounds</string> |
| 511 | <string name="use_black_backgrounds_description">When using the dark theme, apply black backgrounds.</string> | 519 | <string name="use_black_backgrounds_description">When using the dark theme, apply black backgrounds.</string> |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 96ab39cb8..a8b3d480c 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -987,6 +987,8 @@ if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) | |||
| 987 | arm/dynarmic/dynarmic_cp15.h | 987 | arm/dynarmic/dynarmic_cp15.h |
| 988 | arm/dynarmic/dynarmic_exclusive_monitor.cpp | 988 | arm/dynarmic/dynarmic_exclusive_monitor.cpp |
| 989 | arm/dynarmic/dynarmic_exclusive_monitor.h | 989 | arm/dynarmic/dynarmic_exclusive_monitor.h |
| 990 | hle/service/jit/jit_code_memory.cpp | ||
| 991 | hle/service/jit/jit_code_memory.h | ||
| 990 | hle/service/jit/jit_context.cpp | 992 | hle/service/jit/jit_context.cpp |
| 991 | hle/service/jit/jit_context.h | 993 | hle/service/jit/jit_context.h |
| 992 | hle/service/jit/jit.cpp | 994 | hle/service/jit/jit.cpp |
diff --git a/src/core/hle/kernel/k_capabilities.cpp b/src/core/hle/kernel/k_capabilities.cpp index 274fee493..d2288c30d 100644 --- a/src/core/hle/kernel/k_capabilities.cpp +++ b/src/core/hle/kernel/k_capabilities.cpp | |||
| @@ -185,6 +185,10 @@ Result KCapabilities::ProcessMapRegionCapability(const u32 cap, F f) { | |||
| 185 | case RegionType::NoMapping: | 185 | case RegionType::NoMapping: |
| 186 | break; | 186 | break; |
| 187 | case RegionType::KernelTraceBuffer: | 187 | case RegionType::KernelTraceBuffer: |
| 188 | if constexpr (!IsKTraceEnabled) { | ||
| 189 | break; | ||
| 190 | } | ||
| 191 | [[fallthrough]]; | ||
| 188 | case RegionType::OnMemoryBootImage: | 192 | case RegionType::OnMemoryBootImage: |
| 189 | case RegionType::DTB: | 193 | case RegionType::DTB: |
| 190 | R_TRY(f(MemoryRegions[static_cast<u32>(type)], perm)); | 194 | R_TRY(f(MemoryRegions[static_cast<u32>(type)], perm)); |
| @@ -330,8 +334,6 @@ Result KCapabilities::SetCapabilities(std::span<const u32> caps, KProcessPageTab | |||
| 330 | 334 | ||
| 331 | // Map the range. | 335 | // Map the range. |
| 332 | R_TRY(this->MapRange_(cap, size_cap, page_table)); | 336 | R_TRY(this->MapRange_(cap, size_cap, page_table)); |
| 333 | } else if (GetCapabilityType(cap) == CapabilityType::MapRegion && !IsKTraceEnabled) { | ||
| 334 | continue; | ||
| 335 | } else { | 337 | } else { |
| 336 | R_TRY(this->SetCapability(cap, set_flags, set_svc, page_table)); | 338 | R_TRY(this->SetCapability(cap, set_flags, set_svc, page_table)); |
| 337 | } | 339 | } |
diff --git a/src/core/hle/service/jit/jit.cpp b/src/core/hle/service/jit/jit.cpp index a94d05e19..77aa6d7d1 100644 --- a/src/core/hle/service/jit/jit.cpp +++ b/src/core/hle/service/jit/jit.cpp | |||
| @@ -4,11 +4,11 @@ | |||
| 4 | #include "core/arm/debug.h" | 4 | #include "core/arm/debug.h" |
| 5 | #include "core/arm/symbols.h" | 5 | #include "core/arm/symbols.h" |
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/hle/kernel/k_code_memory.h" | ||
| 8 | #include "core/hle/kernel/k_transfer_memory.h" | 7 | #include "core/hle/kernel/k_transfer_memory.h" |
| 9 | #include "core/hle/result.h" | 8 | #include "core/hle/result.h" |
| 10 | #include "core/hle/service/ipc_helpers.h" | 9 | #include "core/hle/service/ipc_helpers.h" |
| 11 | #include "core/hle/service/jit/jit.h" | 10 | #include "core/hle/service/jit/jit.h" |
| 11 | #include "core/hle/service/jit/jit_code_memory.h" | ||
| 12 | #include "core/hle/service/jit/jit_context.h" | 12 | #include "core/hle/service/jit/jit_context.h" |
| 13 | #include "core/hle/service/server_manager.h" | 13 | #include "core/hle/service/server_manager.h" |
| 14 | #include "core/hle/service/service.h" | 14 | #include "core/hle/service/service.h" |
| @@ -23,10 +23,12 @@ struct CodeRange { | |||
| 23 | 23 | ||
| 24 | class IJitEnvironment final : public ServiceFramework<IJitEnvironment> { | 24 | class IJitEnvironment final : public ServiceFramework<IJitEnvironment> { |
| 25 | public: | 25 | public: |
| 26 | explicit IJitEnvironment(Core::System& system_, Kernel::KProcess& process_, CodeRange user_rx, | 26 | explicit IJitEnvironment(Core::System& system_, |
| 27 | CodeRange user_ro) | 27 | Kernel::KScopedAutoObject<Kernel::KProcess>&& process_, |
| 28 | : ServiceFramework{system_, "IJitEnvironment"}, process{&process_}, | 28 | CodeMemory&& user_rx_, CodeMemory&& user_ro_) |
| 29 | context{process->GetMemory()} { | 29 | : ServiceFramework{system_, "IJitEnvironment"}, process{std::move(process_)}, |
| 30 | user_rx{std::move(user_rx_)}, user_ro{std::move(user_ro_)}, | ||
| 31 | context{system_.ApplicationMemory()} { | ||
| 30 | // clang-format off | 32 | // clang-format off |
| 31 | static const FunctionInfo functions[] = { | 33 | static const FunctionInfo functions[] = { |
| 32 | {0, &IJitEnvironment::GenerateCode, "GenerateCode"}, | 34 | {0, &IJitEnvironment::GenerateCode, "GenerateCode"}, |
| @@ -39,10 +41,13 @@ public: | |||
| 39 | RegisterHandlers(functions); | 41 | RegisterHandlers(functions); |
| 40 | 42 | ||
| 41 | // Identity map user code range into sysmodule context | 43 | // Identity map user code range into sysmodule context |
| 42 | configuration.user_ro_memory = user_ro; | 44 | configuration.user_rx_memory.size = user_rx.GetSize(); |
| 43 | configuration.user_rx_memory = user_rx; | 45 | configuration.user_rx_memory.offset = user_rx.GetAddress(); |
| 44 | configuration.sys_ro_memory = user_ro; | 46 | configuration.user_ro_memory.size = user_ro.GetSize(); |
| 45 | configuration.sys_rx_memory = user_rx; | 47 | configuration.user_ro_memory.offset = user_ro.GetAddress(); |
| 48 | |||
| 49 | configuration.sys_rx_memory = configuration.user_rx_memory; | ||
| 50 | configuration.sys_ro_memory = configuration.user_ro_memory; | ||
| 46 | } | 51 | } |
| 47 | 52 | ||
| 48 | void GenerateCode(HLERequestContext& ctx) { | 53 | void GenerateCode(HLERequestContext& ctx) { |
| @@ -318,6 +323,8 @@ private: | |||
| 318 | } | 323 | } |
| 319 | 324 | ||
| 320 | Kernel::KScopedAutoObject<Kernel::KProcess> process; | 325 | Kernel::KScopedAutoObject<Kernel::KProcess> process; |
| 326 | CodeMemory user_rx; | ||
| 327 | CodeMemory user_ro; | ||
| 321 | GuestCallbacks callbacks; | 328 | GuestCallbacks callbacks; |
| 322 | JITConfiguration configuration; | 329 | JITConfiguration configuration; |
| 323 | JITContext context; | 330 | JITContext context; |
| @@ -335,6 +342,7 @@ public: | |||
| 335 | RegisterHandlers(functions); | 342 | RegisterHandlers(functions); |
| 336 | } | 343 | } |
| 337 | 344 | ||
| 345 | private: | ||
| 338 | void CreateJitEnvironment(HLERequestContext& ctx) { | 346 | void CreateJitEnvironment(HLERequestContext& ctx) { |
| 339 | LOG_DEBUG(Service_JIT, "called"); | 347 | LOG_DEBUG(Service_JIT, "called"); |
| 340 | 348 | ||
| @@ -380,20 +388,35 @@ public: | |||
| 380 | return; | 388 | return; |
| 381 | } | 389 | } |
| 382 | 390 | ||
| 383 | const CodeRange user_rx{ | 391 | CodeMemory rx, ro; |
| 384 | .offset = GetInteger(rx_mem->GetSourceAddress()), | 392 | Result res; |
| 385 | .size = parameters.rx_size, | ||
| 386 | }; | ||
| 387 | 393 | ||
| 388 | const CodeRange user_ro{ | 394 | res = rx.Initialize(*process, *rx_mem, parameters.rx_size, |
| 389 | .offset = GetInteger(ro_mem->GetSourceAddress()), | 395 | Kernel::Svc::MemoryPermission::ReadExecute, generate_random); |
| 390 | .size = parameters.ro_size, | 396 | if (R_FAILED(res)) { |
| 391 | }; | 397 | LOG_ERROR(Service_JIT, "rx_mem could not be mapped for handle=0x{:08X}", rx_mem_handle); |
| 398 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 399 | rb.Push(res); | ||
| 400 | return; | ||
| 401 | } | ||
| 402 | |||
| 403 | res = ro.Initialize(*process, *ro_mem, parameters.ro_size, | ||
| 404 | Kernel::Svc::MemoryPermission::Read, generate_random); | ||
| 405 | if (R_FAILED(res)) { | ||
| 406 | LOG_ERROR(Service_JIT, "ro_mem could not be mapped for handle=0x{:08X}", ro_mem_handle); | ||
| 407 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 408 | rb.Push(res); | ||
| 409 | return; | ||
| 410 | } | ||
| 392 | 411 | ||
| 393 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 412 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 394 | rb.Push(ResultSuccess); | 413 | rb.Push(ResultSuccess); |
| 395 | rb.PushIpcInterface<IJitEnvironment>(system, *process, user_rx, user_ro); | 414 | rb.PushIpcInterface<IJitEnvironment>(system, std::move(process), std::move(rx), |
| 415 | std::move(ro)); | ||
| 396 | } | 416 | } |
| 417 | |||
| 418 | private: | ||
| 419 | std::mt19937_64 generate_random{}; | ||
| 397 | }; | 420 | }; |
| 398 | 421 | ||
| 399 | void LoopProcess(Core::System& system) { | 422 | void LoopProcess(Core::System& system) { |
diff --git a/src/core/hle/service/jit/jit_code_memory.cpp b/src/core/hle/service/jit/jit_code_memory.cpp new file mode 100644 index 000000000..2b480488a --- /dev/null +++ b/src/core/hle/service/jit/jit_code_memory.cpp | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/jit/jit_code_memory.h" | ||
| 5 | |||
| 6 | namespace Service::JIT { | ||
| 7 | |||
| 8 | Result CodeMemory::Initialize(Kernel::KProcess& process, Kernel::KCodeMemory& code_memory, | ||
| 9 | size_t size, Kernel::Svc::MemoryPermission perm, | ||
| 10 | std::mt19937_64& generate_random) { | ||
| 11 | auto& page_table = process.GetPageTable(); | ||
| 12 | const u64 alias_code_start = | ||
| 13 | GetInteger(page_table.GetAliasCodeRegionStart()) / Kernel::PageSize; | ||
| 14 | const u64 alias_code_size = page_table.GetAliasCodeRegionSize() / Kernel::PageSize; | ||
| 15 | |||
| 16 | // NOTE: This will retry indefinitely until mapping the code memory succeeds. | ||
| 17 | while (true) { | ||
| 18 | // Generate a new trial address. | ||
| 19 | const u64 mapped_address = | ||
| 20 | (alias_code_start + (generate_random() % alias_code_size)) * Kernel::PageSize; | ||
| 21 | |||
| 22 | // Try to map the address | ||
| 23 | R_TRY_CATCH(code_memory.MapToOwner(mapped_address, size, perm)) { | ||
| 24 | R_CATCH(Kernel::ResultInvalidMemoryRegion) { | ||
| 25 | // If we could not map here, retry. | ||
| 26 | continue; | ||
| 27 | } | ||
| 28 | } | ||
| 29 | R_END_TRY_CATCH; | ||
| 30 | |||
| 31 | // Set members. | ||
| 32 | m_code_memory = std::addressof(code_memory); | ||
| 33 | m_size = size; | ||
| 34 | m_address = mapped_address; | ||
| 35 | m_perm = perm; | ||
| 36 | |||
| 37 | // Open a new reference to the code memory. | ||
| 38 | m_code_memory->Open(); | ||
| 39 | |||
| 40 | // We succeeded. | ||
| 41 | R_SUCCEED(); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | void CodeMemory::Finalize() { | ||
| 46 | if (m_code_memory) { | ||
| 47 | R_ASSERT(m_code_memory->UnmapFromOwner(m_address, m_size)); | ||
| 48 | m_code_memory->Close(); | ||
| 49 | } | ||
| 50 | |||
| 51 | m_code_memory = nullptr; | ||
| 52 | } | ||
| 53 | |||
| 54 | } // namespace Service::JIT | ||
diff --git a/src/core/hle/service/jit/jit_code_memory.h b/src/core/hle/service/jit/jit_code_memory.h new file mode 100644 index 000000000..6376d4c4e --- /dev/null +++ b/src/core/hle/service/jit/jit_code_memory.h | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <random> | ||
| 7 | |||
| 8 | #include "core/hle/kernel/k_code_memory.h" | ||
| 9 | |||
| 10 | namespace Service::JIT { | ||
| 11 | |||
| 12 | class CodeMemory { | ||
| 13 | public: | ||
| 14 | YUZU_NON_COPYABLE(CodeMemory); | ||
| 15 | |||
| 16 | explicit CodeMemory() = default; | ||
| 17 | |||
| 18 | CodeMemory(CodeMemory&& rhs) { | ||
| 19 | std::swap(m_code_memory, rhs.m_code_memory); | ||
| 20 | std::swap(m_size, rhs.m_size); | ||
| 21 | std::swap(m_address, rhs.m_address); | ||
| 22 | std::swap(m_perm, rhs.m_perm); | ||
| 23 | } | ||
| 24 | |||
| 25 | ~CodeMemory() { | ||
| 26 | this->Finalize(); | ||
| 27 | } | ||
| 28 | |||
| 29 | public: | ||
| 30 | Result Initialize(Kernel::KProcess& process, Kernel::KCodeMemory& code_memory, size_t size, | ||
| 31 | Kernel::Svc::MemoryPermission perm, std::mt19937_64& generate_random); | ||
| 32 | void Finalize(); | ||
| 33 | |||
| 34 | size_t GetSize() const { | ||
| 35 | return m_size; | ||
| 36 | } | ||
| 37 | |||
| 38 | u64 GetAddress() const { | ||
| 39 | return m_address; | ||
| 40 | } | ||
| 41 | |||
| 42 | private: | ||
| 43 | Kernel::KCodeMemory* m_code_memory{}; | ||
| 44 | size_t m_size{}; | ||
| 45 | u64 m_address{}; | ||
| 46 | Kernel::Svc::MemoryPermission m_perm{}; | ||
| 47 | }; | ||
| 48 | |||
| 49 | } // namespace Service::JIT | ||
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index ed023fcfe..89ebab08e 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp | |||
| @@ -96,9 +96,9 @@ Id ImageType(EmitContext& ctx, const ImageDescriptor& desc, Id sampled_type) { | |||
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | Id DefineVariable(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin, | 98 | Id DefineVariable(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin, |
| 99 | spv::StorageClass storage_class) { | 99 | spv::StorageClass storage_class, std::optional<Id> initializer = std::nullopt) { |
| 100 | const Id pointer_type{ctx.TypePointer(storage_class, type)}; | 100 | const Id pointer_type{ctx.TypePointer(storage_class, type)}; |
| 101 | const Id id{ctx.AddGlobalVariable(pointer_type, storage_class)}; | 101 | const Id id{ctx.AddGlobalVariable(pointer_type, storage_class, initializer)}; |
| 102 | if (builtin) { | 102 | if (builtin) { |
| 103 | ctx.Decorate(id, spv::Decoration::BuiltIn, *builtin); | 103 | ctx.Decorate(id, spv::Decoration::BuiltIn, *builtin); |
| 104 | } | 104 | } |
| @@ -144,11 +144,12 @@ Id DefineInput(EmitContext& ctx, Id type, bool per_invocation, | |||
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | Id DefineOutput(EmitContext& ctx, Id type, std::optional<u32> invocations, | 146 | Id DefineOutput(EmitContext& ctx, Id type, std::optional<u32> invocations, |
| 147 | std::optional<spv::BuiltIn> builtin = std::nullopt) { | 147 | std::optional<spv::BuiltIn> builtin = std::nullopt, |
| 148 | std::optional<Id> initializer = std::nullopt) { | ||
| 148 | if (invocations && ctx.stage == Stage::TessellationControl) { | 149 | if (invocations && ctx.stage == Stage::TessellationControl) { |
| 149 | type = ctx.TypeArray(type, ctx.Const(*invocations)); | 150 | type = ctx.TypeArray(type, ctx.Const(*invocations)); |
| 150 | } | 151 | } |
| 151 | return DefineVariable(ctx, type, builtin, spv::StorageClass::Output); | 152 | return DefineVariable(ctx, type, builtin, spv::StorageClass::Output, initializer); |
| 152 | } | 153 | } |
| 153 | 154 | ||
| 154 | void DefineGenericOutput(EmitContext& ctx, size_t index, std::optional<u32> invocations) { | 155 | void DefineGenericOutput(EmitContext& ctx, size_t index, std::optional<u32> invocations) { |
| @@ -811,10 +812,14 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 811 | labels.push_back(OpLabel()); | 812 | labels.push_back(OpLabel()); |
| 812 | } | 813 | } |
| 813 | if (info.stores.ClipDistances()) { | 814 | if (info.stores.ClipDistances()) { |
| 814 | literals.push_back(static_cast<u32>(IR::Attribute::ClipDistance0) >> 2); | 815 | if (profile.max_user_clip_distances >= 4) { |
| 815 | labels.push_back(OpLabel()); | 816 | literals.push_back(static_cast<u32>(IR::Attribute::ClipDistance0) >> 2); |
| 816 | literals.push_back(static_cast<u32>(IR::Attribute::ClipDistance4) >> 2); | 817 | labels.push_back(OpLabel()); |
| 817 | labels.push_back(OpLabel()); | 818 | } |
| 819 | if (profile.max_user_clip_distances >= 8) { | ||
| 820 | literals.push_back(static_cast<u32>(IR::Attribute::ClipDistance4) >> 2); | ||
| 821 | labels.push_back(OpLabel()); | ||
| 822 | } | ||
| 818 | } | 823 | } |
| 819 | OpSelectionMerge(end_block, spv::SelectionControlMask::MaskNone); | 824 | OpSelectionMerge(end_block, spv::SelectionControlMask::MaskNone); |
| 820 | OpSwitch(compare_index, default_label, literals, labels); | 825 | OpSwitch(compare_index, default_label, literals, labels); |
| @@ -843,17 +848,21 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 843 | ++label_index; | 848 | ++label_index; |
| 844 | } | 849 | } |
| 845 | if (info.stores.ClipDistances()) { | 850 | if (info.stores.ClipDistances()) { |
| 846 | AddLabel(labels[label_index]); | 851 | if (profile.max_user_clip_distances >= 4) { |
| 847 | const Id pointer{OpAccessChain(output_f32, clip_distances, masked_index)}; | 852 | AddLabel(labels[label_index]); |
| 848 | OpStore(pointer, store_value); | 853 | const Id pointer{OpAccessChain(output_f32, clip_distances, masked_index)}; |
| 849 | OpReturn(); | 854 | OpStore(pointer, store_value); |
| 850 | ++label_index; | 855 | OpReturn(); |
| 851 | AddLabel(labels[label_index]); | 856 | ++label_index; |
| 852 | const Id fixed_index{OpIAdd(U32[1], masked_index, Const(4U))}; | 857 | } |
| 853 | const Id pointer2{OpAccessChain(output_f32, clip_distances, fixed_index)}; | 858 | if (profile.max_user_clip_distances >= 8) { |
| 854 | OpStore(pointer2, store_value); | 859 | AddLabel(labels[label_index]); |
| 855 | OpReturn(); | 860 | const Id fixed_index{OpIAdd(U32[1], masked_index, Const(4U))}; |
| 856 | ++label_index; | 861 | const Id pointer{OpAccessChain(output_f32, clip_distances, fixed_index)}; |
| 862 | OpStore(pointer, store_value); | ||
| 863 | OpReturn(); | ||
| 864 | ++label_index; | ||
| 865 | } | ||
| 857 | } | 866 | } |
| 858 | AddLabel(end_block); | 867 | AddLabel(end_block); |
| 859 | OpUnreachable(); | 868 | OpUnreachable(); |
| @@ -1532,9 +1541,16 @@ void EmitContext::DefineOutputs(const IR::Program& program) { | |||
| 1532 | if (stage == Stage::Fragment) { | 1541 | if (stage == Stage::Fragment) { |
| 1533 | throw NotImplementedException("Storing ClipDistance in fragment stage"); | 1542 | throw NotImplementedException("Storing ClipDistance in fragment stage"); |
| 1534 | } | 1543 | } |
| 1535 | const Id type{TypeArray( | 1544 | if (profile.max_user_clip_distances > 0) { |
| 1536 | F32[1], Const(std::min(info.used_clip_distances, profile.max_user_clip_distances)))}; | 1545 | const u32 used{std::min(profile.max_user_clip_distances, 8u)}; |
| 1537 | clip_distances = DefineOutput(*this, type, invocations, spv::BuiltIn::ClipDistance); | 1546 | const std::array<Id, 8> zero{f32_zero_value, f32_zero_value, f32_zero_value, |
| 1547 | f32_zero_value, f32_zero_value, f32_zero_value, | ||
| 1548 | f32_zero_value, f32_zero_value}; | ||
| 1549 | const Id type{TypeArray(F32[1], Const(used))}; | ||
| 1550 | const Id initializer{ConstantComposite(type, std::span(zero).subspan(0, used))}; | ||
| 1551 | clip_distances = | ||
| 1552 | DefineOutput(*this, type, invocations, spv::BuiltIn::ClipDistance, initializer); | ||
| 1553 | } | ||
| 1538 | } | 1554 | } |
| 1539 | if (info.stores[IR::Attribute::Layer] && | 1555 | if (info.stores[IR::Attribute::Layer] && |
| 1540 | (profile.support_viewport_index_layer_non_geometry || stage == Stage::Geometry)) { | 1556 | (profile.support_viewport_index_layer_non_geometry || stage == Stage::Geometry)) { |
diff --git a/src/video_core/texture_cache/decode_bc.cpp b/src/video_core/texture_cache/decode_bc.cpp index 3e26474a3..a018c6df4 100644 --- a/src/video_core/texture_cache/decode_bc.cpp +++ b/src/video_core/texture_cache/decode_bc.cpp | |||
| @@ -60,66 +60,72 @@ u32 ConvertedBytesPerBlock(VideoCore::Surface::PixelFormat pixel_format) { | |||
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | template <auto decompress, PixelFormat pixel_format> | 62 | template <auto decompress, PixelFormat pixel_format> |
| 63 | void DecompressBlocks(std::span<const u8> input, std::span<u8> output, Extent3D extent, | 63 | void DecompressBlocks(std::span<const u8> input, std::span<u8> output, BufferImageCopy& copy, |
| 64 | bool is_signed = false) { | 64 | bool is_signed = false) { |
| 65 | const u32 out_bpp = ConvertedBytesPerBlock(pixel_format); | 65 | const u32 out_bpp = ConvertedBytesPerBlock(pixel_format); |
| 66 | const u32 block_width = std::min(extent.width, BLOCK_SIZE); | 66 | const u32 block_size = BlockSize(pixel_format); |
| 67 | const u32 block_height = std::min(extent.height, BLOCK_SIZE); | 67 | const u32 width = copy.image_extent.width; |
| 68 | const u32 pitch = extent.width * out_bpp; | 68 | const u32 height = copy.image_extent.height * copy.image_subresource.num_layers; |
| 69 | const u32 depth = copy.image_extent.depth; | ||
| 70 | const u32 block_width = std::min(width, BLOCK_SIZE); | ||
| 71 | const u32 block_height = std::min(height, BLOCK_SIZE); | ||
| 72 | const u32 pitch = width * out_bpp; | ||
| 69 | size_t input_offset = 0; | 73 | size_t input_offset = 0; |
| 70 | size_t output_offset = 0; | 74 | size_t output_offset = 0; |
| 71 | for (u32 slice = 0; slice < extent.depth; ++slice) { | 75 | for (u32 slice = 0; slice < depth; ++slice) { |
| 72 | for (u32 y = 0; y < extent.height; y += block_height) { | 76 | for (u32 y = 0; y < height; y += block_height) { |
| 73 | size_t row_offset = 0; | 77 | size_t src_offset = input_offset; |
| 74 | for (u32 x = 0; x < extent.width; | 78 | size_t dst_offset = output_offset; |
| 75 | x += block_width, row_offset += block_width * out_bpp) { | 79 | for (u32 x = 0; x < width; x += block_width) { |
| 76 | const u8* src = input.data() + input_offset; | 80 | const u8* src = input.data() + src_offset; |
| 77 | u8* const dst = output.data() + output_offset + row_offset; | 81 | u8* const dst = output.data() + dst_offset; |
| 78 | if constexpr (IsSigned(pixel_format)) { | 82 | if constexpr (IsSigned(pixel_format)) { |
| 79 | decompress(src, dst, x, y, extent.width, extent.height, is_signed); | 83 | decompress(src, dst, x, y, width, height, is_signed); |
| 80 | } else { | 84 | } else { |
| 81 | decompress(src, dst, x, y, extent.width, extent.height); | 85 | decompress(src, dst, x, y, width, height); |
| 82 | } | 86 | } |
| 83 | input_offset += BlockSize(pixel_format); | 87 | src_offset += block_size; |
| 88 | dst_offset += block_width * out_bpp; | ||
| 84 | } | 89 | } |
| 90 | input_offset += copy.buffer_row_length * block_size / block_width; | ||
| 85 | output_offset += block_height * pitch; | 91 | output_offset += block_height * pitch; |
| 86 | } | 92 | } |
| 87 | } | 93 | } |
| 88 | } | 94 | } |
| 89 | 95 | ||
| 90 | void DecompressBCn(std::span<const u8> input, std::span<u8> output, Extent3D extent, | 96 | void DecompressBCn(std::span<const u8> input, std::span<u8> output, BufferImageCopy& copy, |
| 91 | VideoCore::Surface::PixelFormat pixel_format) { | 97 | VideoCore::Surface::PixelFormat pixel_format) { |
| 92 | switch (pixel_format) { | 98 | switch (pixel_format) { |
| 93 | case PixelFormat::BC1_RGBA_UNORM: | 99 | case PixelFormat::BC1_RGBA_UNORM: |
| 94 | case PixelFormat::BC1_RGBA_SRGB: | 100 | case PixelFormat::BC1_RGBA_SRGB: |
| 95 | DecompressBlocks<bcn::DecodeBc1, PixelFormat::BC1_RGBA_UNORM>(input, output, extent); | 101 | DecompressBlocks<bcn::DecodeBc1, PixelFormat::BC1_RGBA_UNORM>(input, output, copy); |
| 96 | break; | 102 | break; |
| 97 | case PixelFormat::BC2_UNORM: | 103 | case PixelFormat::BC2_UNORM: |
| 98 | case PixelFormat::BC2_SRGB: | 104 | case PixelFormat::BC2_SRGB: |
| 99 | DecompressBlocks<bcn::DecodeBc2, PixelFormat::BC2_UNORM>(input, output, extent); | 105 | DecompressBlocks<bcn::DecodeBc2, PixelFormat::BC2_UNORM>(input, output, copy); |
| 100 | break; | 106 | break; |
| 101 | case PixelFormat::BC3_UNORM: | 107 | case PixelFormat::BC3_UNORM: |
| 102 | case PixelFormat::BC3_SRGB: | 108 | case PixelFormat::BC3_SRGB: |
| 103 | DecompressBlocks<bcn::DecodeBc3, PixelFormat::BC3_UNORM>(input, output, extent); | 109 | DecompressBlocks<bcn::DecodeBc3, PixelFormat::BC3_UNORM>(input, output, copy); |
| 104 | break; | 110 | break; |
| 105 | case PixelFormat::BC4_SNORM: | 111 | case PixelFormat::BC4_SNORM: |
| 106 | case PixelFormat::BC4_UNORM: | 112 | case PixelFormat::BC4_UNORM: |
| 107 | DecompressBlocks<bcn::DecodeBc4, PixelFormat::BC4_UNORM>( | 113 | DecompressBlocks<bcn::DecodeBc4, PixelFormat::BC4_UNORM>( |
| 108 | input, output, extent, pixel_format == PixelFormat::BC4_SNORM); | 114 | input, output, copy, pixel_format == PixelFormat::BC4_SNORM); |
| 109 | break; | 115 | break; |
| 110 | case PixelFormat::BC5_SNORM: | 116 | case PixelFormat::BC5_SNORM: |
| 111 | case PixelFormat::BC5_UNORM: | 117 | case PixelFormat::BC5_UNORM: |
| 112 | DecompressBlocks<bcn::DecodeBc5, PixelFormat::BC5_UNORM>( | 118 | DecompressBlocks<bcn::DecodeBc5, PixelFormat::BC5_UNORM>( |
| 113 | input, output, extent, pixel_format == PixelFormat::BC5_SNORM); | 119 | input, output, copy, pixel_format == PixelFormat::BC5_SNORM); |
| 114 | break; | 120 | break; |
| 115 | case PixelFormat::BC6H_SFLOAT: | 121 | case PixelFormat::BC6H_SFLOAT: |
| 116 | case PixelFormat::BC6H_UFLOAT: | 122 | case PixelFormat::BC6H_UFLOAT: |
| 117 | DecompressBlocks<bcn::DecodeBc6, PixelFormat::BC6H_UFLOAT>( | 123 | DecompressBlocks<bcn::DecodeBc6, PixelFormat::BC6H_UFLOAT>( |
| 118 | input, output, extent, pixel_format == PixelFormat::BC6H_SFLOAT); | 124 | input, output, copy, pixel_format == PixelFormat::BC6H_SFLOAT); |
| 119 | break; | 125 | break; |
| 120 | case PixelFormat::BC7_SRGB: | 126 | case PixelFormat::BC7_SRGB: |
| 121 | case PixelFormat::BC7_UNORM: | 127 | case PixelFormat::BC7_UNORM: |
| 122 | DecompressBlocks<bcn::DecodeBc7, PixelFormat::BC7_UNORM>(input, output, extent); | 128 | DecompressBlocks<bcn::DecodeBc7, PixelFormat::BC7_UNORM>(input, output, copy); |
| 123 | break; | 129 | break; |
| 124 | default: | 130 | default: |
| 125 | LOG_WARNING(HW_GPU, "Unimplemented BCn decompression {}", pixel_format); | 131 | LOG_WARNING(HW_GPU, "Unimplemented BCn decompression {}", pixel_format); |
diff --git a/src/video_core/texture_cache/decode_bc.h b/src/video_core/texture_cache/decode_bc.h index 41d1ec0a3..4e3b9b8ac 100644 --- a/src/video_core/texture_cache/decode_bc.h +++ b/src/video_core/texture_cache/decode_bc.h | |||
| @@ -13,7 +13,7 @@ namespace VideoCommon { | |||
| 13 | 13 | ||
| 14 | [[nodiscard]] u32 ConvertedBytesPerBlock(VideoCore::Surface::PixelFormat pixel_format); | 14 | [[nodiscard]] u32 ConvertedBytesPerBlock(VideoCore::Surface::PixelFormat pixel_format); |
| 15 | 15 | ||
| 16 | void DecompressBCn(std::span<const u8> input, std::span<u8> output, Extent3D extent, | 16 | void DecompressBCn(std::span<const u8> input, std::span<u8> output, BufferImageCopy& copy, |
| 17 | VideoCore::Surface::PixelFormat pixel_format); | 17 | VideoCore::Surface::PixelFormat pixel_format); |
| 18 | 18 | ||
| 19 | } // namespace VideoCommon | 19 | } // namespace VideoCommon |
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp index 15596c925..fcf70068e 100644 --- a/src/video_core/texture_cache/util.cpp +++ b/src/video_core/texture_cache/util.cpp | |||
| @@ -837,6 +837,7 @@ boost::container::small_vector<BufferImageCopy, 16> UnswizzleImage(Tegra::Memory | |||
| 837 | std::span<u8> output) { | 837 | std::span<u8> output) { |
| 838 | const size_t guest_size_bytes = input.size_bytes(); | 838 | const size_t guest_size_bytes = input.size_bytes(); |
| 839 | const u32 bpp_log2 = BytesPerBlockLog2(info.format); | 839 | const u32 bpp_log2 = BytesPerBlockLog2(info.format); |
| 840 | const Extent2D tile_size = DefaultBlockSize(info.format); | ||
| 840 | const Extent3D size = info.size; | 841 | const Extent3D size = info.size; |
| 841 | 842 | ||
| 842 | if (info.type == ImageType::Linear) { | 843 | if (info.type == ImageType::Linear) { |
| @@ -847,7 +848,7 @@ boost::container::small_vector<BufferImageCopy, 16> UnswizzleImage(Tegra::Memory | |||
| 847 | return {{ | 848 | return {{ |
| 848 | .buffer_offset = 0, | 849 | .buffer_offset = 0, |
| 849 | .buffer_size = guest_size_bytes, | 850 | .buffer_size = guest_size_bytes, |
| 850 | .buffer_row_length = info.pitch >> bpp_log2, | 851 | .buffer_row_length = info.pitch * tile_size.width >> bpp_log2, |
| 851 | .buffer_image_height = size.height, | 852 | .buffer_image_height = size.height, |
| 852 | .image_subresource = | 853 | .image_subresource = |
| 853 | { | 854 | { |
| @@ -862,7 +863,6 @@ boost::container::small_vector<BufferImageCopy, 16> UnswizzleImage(Tegra::Memory | |||
| 862 | const LevelInfo level_info = MakeLevelInfo(info); | 863 | const LevelInfo level_info = MakeLevelInfo(info); |
| 863 | const s32 num_layers = info.resources.layers; | 864 | const s32 num_layers = info.resources.layers; |
| 864 | const s32 num_levels = info.resources.levels; | 865 | const s32 num_levels = info.resources.levels; |
| 865 | const Extent2D tile_size = DefaultBlockSize(info.format); | ||
| 866 | const std::array level_sizes = CalculateLevelSizes(level_info, num_levels); | 866 | const std::array level_sizes = CalculateLevelSizes(level_info, num_levels); |
| 867 | const Extent2D gob = GobSize(bpp_log2, info.block.height, info.tile_width_spacing); | 867 | const Extent2D gob = GobSize(bpp_log2, info.block.height, info.tile_width_spacing); |
| 868 | const u32 layer_size = CalculateLevelBytes(level_sizes, num_levels); | 868 | const u32 layer_size = CalculateLevelBytes(level_sizes, num_levels); |
| @@ -926,8 +926,6 @@ void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8 | |||
| 926 | 926 | ||
| 927 | const auto input_offset = input.subspan(copy.buffer_offset); | 927 | const auto input_offset = input.subspan(copy.buffer_offset); |
| 928 | copy.buffer_offset = output_offset; | 928 | copy.buffer_offset = output_offset; |
| 929 | copy.buffer_row_length = mip_size.width; | ||
| 930 | copy.buffer_image_height = mip_size.height; | ||
| 931 | 929 | ||
| 932 | const auto recompression_setting = Settings::values.astc_recompression.GetValue(); | 930 | const auto recompression_setting = Settings::values.astc_recompression.GetValue(); |
| 933 | const bool astc = IsPixelFormatASTC(info.format); | 931 | const bool astc = IsPixelFormatASTC(info.format); |
| @@ -972,16 +970,14 @@ void ConvertImage(std::span<const u8> input, const ImageInfo& info, std::span<u8 | |||
| 972 | bpp_div; | 970 | bpp_div; |
| 973 | output_offset += static_cast<u32>(copy.buffer_size); | 971 | output_offset += static_cast<u32>(copy.buffer_size); |
| 974 | } else { | 972 | } else { |
| 975 | const Extent3D image_extent{ | 973 | DecompressBCn(input_offset, output.subspan(output_offset), copy, info.format); |
| 976 | .width = copy.image_extent.width, | ||
| 977 | .height = copy.image_extent.height * copy.image_subresource.num_layers, | ||
| 978 | .depth = copy.image_extent.depth, | ||
| 979 | }; | ||
| 980 | DecompressBCn(input_offset, output.subspan(output_offset), image_extent, info.format); | ||
| 981 | output_offset += copy.image_extent.width * copy.image_extent.height * | 974 | output_offset += copy.image_extent.width * copy.image_extent.height * |
| 982 | copy.image_subresource.num_layers * | 975 | copy.image_subresource.num_layers * |
| 983 | ConvertedBytesPerBlock(info.format); | 976 | ConvertedBytesPerBlock(info.format); |
| 984 | } | 977 | } |
| 978 | |||
| 979 | copy.buffer_row_length = mip_size.width; | ||
| 980 | copy.buffer_image_height = mip_size.height; | ||
| 985 | } | 981 | } |
| 986 | } | 982 | } |
| 987 | 983 | ||
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 059fcf041..c789c1e59 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -5342,6 +5342,10 @@ int main(int argc, char* argv[]) { | |||
| 5342 | if (QString::fromLocal8Bit(qgetenv("DISPLAY")).isEmpty()) { | 5342 | if (QString::fromLocal8Bit(qgetenv("DISPLAY")).isEmpty()) { |
| 5343 | qputenv("DISPLAY", ":0"); | 5343 | qputenv("DISPLAY", ":0"); |
| 5344 | } | 5344 | } |
| 5345 | |||
| 5346 | // Fix the Wayland appId. This needs to match the name of the .desktop file without the .desktop | ||
| 5347 | // suffix. | ||
| 5348 | QGuiApplication::setDesktopFileName(QStringLiteral("org.yuzu_emu.yuzu")); | ||
| 5345 | #endif | 5349 | #endif |
| 5346 | 5350 | ||
| 5347 | SetHighDPIAttributes(); | 5351 | SetHighDPIAttributes(); |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index 5153cdb79..1a35d471c 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | |||
| @@ -20,7 +20,7 @@ EmuWindow_SDL2::EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem_, Co | |||
| 20 | : input_subsystem{input_subsystem_}, system{system_} { | 20 | : input_subsystem{input_subsystem_}, system{system_} { |
| 21 | input_subsystem->Initialize(); | 21 | input_subsystem->Initialize(); |
| 22 | if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0) { | 22 | if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0) { |
| 23 | LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting..."); | 23 | LOG_CRITICAL(Frontend, "Failed to initialize SDL2: {}, Exiting...", SDL_GetError()); |
| 24 | exit(1); | 24 | exit(1); |
| 25 | } | 25 | } |
| 26 | SDL_SetMainReady(); | 26 | SDL_SetMainReady(); |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp index 9ed47d453..8b916f05c 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp | |||
| @@ -28,7 +28,8 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste | |||
| 28 | SDL_SysWMinfo wm; | 28 | SDL_SysWMinfo wm; |
| 29 | SDL_VERSION(&wm.version); | 29 | SDL_VERSION(&wm.version); |
| 30 | if (SDL_GetWindowWMInfo(render_window, &wm) == SDL_FALSE) { | 30 | if (SDL_GetWindowWMInfo(render_window, &wm) == SDL_FALSE) { |
| 31 | LOG_CRITICAL(Frontend, "Failed to get information from the window manager"); | 31 | LOG_CRITICAL(Frontend, "Failed to get information from the window manager: {}", |
| 32 | SDL_GetError()); | ||
| 32 | std::exit(EXIT_FAILURE); | 33 | std::exit(EXIT_FAILURE); |
| 33 | } | 34 | } |
| 34 | 35 | ||