diff --git a/README.md b/README.md index ba1123aee..049dfb30e 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 2636. +This is the source code for early-access 2637. ## Legal Notice diff --git a/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc b/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc index 74899034c..f1666700e 100755 --- a/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc +++ b/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc @@ -75,6 +75,14 @@ void AxxEmitX64::EmitMemoryRead(AxxEmitContext& ctx, IR::Inst* inst) { return; } + if (ordered && bitsize == 128) { + // Required for atomic 128-bit loads/stores + ctx.reg_alloc.ScratchGpr(HostLoc::RAX); + ctx.reg_alloc.ScratchGpr(HostLoc::RBX); + ctx.reg_alloc.ScratchGpr(HostLoc::RCX); + ctx.reg_alloc.ScratchGpr(HostLoc::RDX); + } + const Xbyak::Reg64 vaddr = ctx.reg_alloc.UseGpr(args[0]); const int value_idx = bitsize == 128 ? ctx.reg_alloc.ScratchXmm().getIdx() : ctx.reg_alloc.ScratchGpr().getIdx(); @@ -145,6 +153,14 @@ void AxxEmitX64::EmitMemoryWrite(AxxEmitContext& ctx, IR::Inst* inst) { return; } + if (ordered && bitsize == 128) { + // Required for atomic 128-bit loads/stores + ctx.reg_alloc.ScratchGpr(HostLoc::RAX); + ctx.reg_alloc.ScratchGpr(HostLoc::RBX); + ctx.reg_alloc.ScratchGpr(HostLoc::RCX); + ctx.reg_alloc.ScratchGpr(HostLoc::RDX); + } + const Xbyak::Reg64 vaddr = ctx.reg_alloc.UseGpr(args[0]); const int value_idx = bitsize == 128 ? ctx.reg_alloc.UseXmm(args[1]).getIdx() @@ -303,7 +319,15 @@ void AxxEmitX64::EmitExclusiveReadMemoryInline(AxxEmitContext& ctx, IR::Inst* in } auto args = ctx.reg_alloc.GetArgumentInfo(inst); - const bool ordered = IsOrdered(args[1].GetImmediateAccType()); + const bool ordered = true; + + if (ordered && bitsize == 128) { + // Required for atomic 128-bit loads/stores + ctx.reg_alloc.ScratchGpr(HostLoc::RAX); + ctx.reg_alloc.ScratchGpr(HostLoc::RBX); + ctx.reg_alloc.ScratchGpr(HostLoc::RCX); + ctx.reg_alloc.ScratchGpr(HostLoc::RDX); + } const Xbyak::Reg64 vaddr = ctx.reg_alloc.UseGpr(args[0]); const int value_idx = bitsize == 128 ? ctx.reg_alloc.ScratchXmm().getIdx() : ctx.reg_alloc.ScratchGpr().getIdx(); @@ -370,7 +394,7 @@ void AxxEmitX64::EmitExclusiveWriteMemoryInline(AxxEmitContext& ctx, IR::Inst* i } auto args = ctx.reg_alloc.GetArgumentInfo(inst); - const bool ordered = IsOrdered(args[2].GetImmediateAccType()); + const bool ordered = true; const auto value = [&] { if constexpr (bitsize == 128) { diff --git a/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h b/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h index c9ce765ed..e92ed7290 100755 --- a/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h +++ b/externals/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h @@ -201,10 +201,13 @@ template<> template const void* EmitReadMemoryMov(BlockOfCode& code, int value_idx, const Xbyak::RegExp& addr, bool ordered) { if (ordered) { - if constexpr (bitsize == 128) { - code.mfence(); - } else { + if constexpr (bitsize != 128) { code.xor_(Xbyak::Reg32{value_idx}, Xbyak::Reg32{value_idx}); + } else { + code.xor_(eax, eax); + code.xor_(ebx, ebx); + code.xor_(ecx, ecx); + code.xor_(edx, edx); } const void* fastmem_location = code.getCurr(); @@ -215,7 +218,7 @@ const void* EmitReadMemoryMov(BlockOfCode& code, int value_idx, const Xbyak::Reg break; case 16: code.lock(); - code.xadd(word[addr], Xbyak::Reg32{value_idx}); + code.xadd(word[addr], Xbyak::Reg16{value_idx}); break; case 32: code.lock(); @@ -226,8 +229,16 @@ const void* EmitReadMemoryMov(BlockOfCode& code, int value_idx, const Xbyak::Reg code.xadd(qword[addr], Xbyak::Reg64{value_idx}); break; case 128: - // TODO (HACK): Detect CPUs where this load is not atomic - code.movaps(Xbyak::Xmm{value_idx}, xword[addr]); + code.lock(); + code.cmpxchg16b(xword[addr]); + if (code.HasHostFeature(HostFeature::SSE41)) { + code.movq(Xbyak::Xmm{value_idx}, rax); + code.pinsrq(Xbyak::Xmm{value_idx}, rdx, 1); + } else { + code.movq(Xbyak::Xmm{value_idx}, rax); + code.movq(xmm0, rdx); + code.punpcklqdq(Xbyak::Xmm{value_idx}, xmm0); + } break; default: ASSERT_FALSE("Invalid bitsize"); @@ -261,6 +272,20 @@ const void* EmitReadMemoryMov(BlockOfCode& code, int value_idx, const Xbyak::Reg template const void* EmitWriteMemoryMov(BlockOfCode& code, const Xbyak::RegExp& addr, int value_idx, bool ordered) { if (ordered) { + if constexpr (bitsize == 128) { + code.xor_(eax, eax); + code.xor_(edx, edx); + if (code.HasHostFeature(HostFeature::SSE41)) { + code.movq(rbx, Xbyak::Xmm{value_idx}); + code.pextrq(rcx, Xbyak::Xmm{value_idx}, 1); + } else { + code.movaps(xmm0, Xbyak::Xmm{value_idx}); + code.movq(rbx, xmm0); + code.punpckhqdq(xmm0, xmm0); + code.movq(rcx, xmm0); + } + } + const void* fastmem_location = code.getCurr(); switch (bitsize) { case 8: @@ -275,10 +300,14 @@ const void* EmitWriteMemoryMov(BlockOfCode& code, const Xbyak::RegExp& addr, int case 64: code.xchg(qword[addr], Xbyak::Reg64{value_idx}); break; - case 128: - code.movaps(xword[addr], Xbyak::Xmm{value_idx}); - code.mfence(); + case 128: { + Xbyak::Label loop; + code.L(loop); + code.lock(); + code.cmpxchg16b(xword[addr]); + code.jnz(loop); break; + } default: ASSERT_FALSE("Invalid bitsize"); } diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 3703ca4c6..4208337db 100755 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -174,7 +174,7 @@ ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path_, ASSERT_MSG(dest != nullptr, "Newly created file with success cannot be found."); ASSERT_MSG(dest->WriteBytes(src->ReadAllBytes()) == src->GetSize(), - "Could not write all of the bytes but everything else has succeded."); + "Could not write all of the bytes but everything else has succeeded."); if (!src->GetContainingDirectory()->DeleteFile(Common::FS::GetFilename(src_path))) { // TODO(DarkLordZach): Find a better error code for this diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp index b3b8576a9..8467b50e4 100755 --- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp +++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp @@ -26,7 +26,7 @@ void NVDRV::Open(Kernel::HLERequestContext& ctx) { rb.Push(0); rb.PushEnum(NvResult::NotInitialized); - LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); + LOG_ERROR(Service_NVDRV, "NvServices is not initialized!"); return; } @@ -61,7 +61,7 @@ void NVDRV::Ioctl1(Kernel::HLERequestContext& ctx) { if (!is_initialized) { ServiceError(ctx, NvResult::NotInitialized); - LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); + LOG_ERROR(Service_NVDRV, "NvServices is not initialized!"); return; } @@ -87,7 +87,7 @@ void NVDRV::Ioctl2(Kernel::HLERequestContext& ctx) { if (!is_initialized) { ServiceError(ctx, NvResult::NotInitialized); - LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); + LOG_ERROR(Service_NVDRV, "NvServices is not initialized!"); return; } @@ -114,7 +114,7 @@ void NVDRV::Ioctl3(Kernel::HLERequestContext& ctx) { if (!is_initialized) { ServiceError(ctx, NvResult::NotInitialized); - LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); + LOG_ERROR(Service_NVDRV, "NvServices is not initialized!"); return; } @@ -139,7 +139,7 @@ void NVDRV::Close(Kernel::HLERequestContext& ctx) { if (!is_initialized) { ServiceError(ctx, NvResult::NotInitialized); - LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); + LOG_ERROR(Service_NVDRV, "NvServices is not initialized!"); return; } @@ -170,7 +170,7 @@ void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) { if (!is_initialized) { ServiceError(ctx, NvResult::NotInitialized); - LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); + LOG_ERROR(Service_NVDRV, "NvServices is not initialized!"); return; } diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_load.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_load.cpp index 57b4f0eee..60732215b 100755 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_load.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_load.cpp @@ -132,7 +132,7 @@ void Impl(TranslatorVisitor& v, u64 insn, bool is_bindless) { multisample = v.X(meta_reg++); } if (tld.clamp != 0) { - throw NotImplementedException("TLD.CL - CLAMP is not implmented"); + throw NotImplementedException("TLD.CL - CLAMP is not implemented"); } IR::TextureInstInfo info{}; info.type.Assign(GetType(tld.type)); diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_mipmap_level.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_mipmap_level.cpp index 311a9e763..f89ce1b68 100755 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_mipmap_level.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_mipmap_level.cpp @@ -81,7 +81,7 @@ void Impl(TranslatorVisitor& v, u64 insn, bool is_bindless) { } const tmml{insn}; if ((tmml.mask & 0b1100) != 0) { - throw NotImplementedException("TMML BA results are not implmented"); + throw NotImplementedException("TMML BA results are not implemented"); } const IR::Value coords{MakeCoords(v, tmml.coord_reg, tmml.type)}; diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 4a5de9ddf..f3a05ada9 100755 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -736,7 +736,7 @@ VkFormat Device::GetSupportedFormat(VkFormat wanted_format, VkFormatFeatureFlags } void Device::ReportLoss() const { - LOG_CRITICAL(Render_Vulkan, "Device loss occured!"); + LOG_CRITICAL(Render_Vulkan, "Device loss occurred!"); // Wait for the log to flush and for Nsight Aftermath to dump the results std::this_thread::sleep_for(std::chrono::seconds{15}); diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp index 53e629a5e..6679e9c53 100755 --- a/src/yuzu/configuration/configure_hotkeys.cpp +++ b/src/yuzu/configuration/configure_hotkeys.cpp @@ -35,8 +35,9 @@ ConfigureHotkeys::ConfigureHotkeys(Core::HID::HIDCore& hid_core, QWidget* parent ui->hotkey_list->setContextMenuPolicy(Qt::CustomContextMenu); ui->hotkey_list->setModel(model); - ui->hotkey_list->setColumnWidth(name_column, 200); - ui->hotkey_list->resizeColumnToContents(hotkey_column); + ui->hotkey_list->header()->setStretchLastSection(false); + ui->hotkey_list->header()->setSectionResizeMode(name_column, QHeaderView::ResizeMode::Stretch); + ui->hotkey_list->header()->setMinimumSectionSize(150); connect(ui->button_restore_defaults, &QPushButton::clicked, this, &ConfigureHotkeys::RestoreDefaults); @@ -76,8 +77,8 @@ void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) { } ui->hotkey_list->expandAll(); - ui->hotkey_list->resizeColumnToContents(name_column); ui->hotkey_list->resizeColumnToContents(hotkey_column); + ui->hotkey_list->resizeColumnToContents(controller_column); } void ConfigureHotkeys::changeEvent(QEvent* event) { diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp index 21e51d749..7893a85bb 100755 --- a/src/yuzu/configuration/configure_per_game_addons.cpp +++ b/src/yuzu/configuration/configure_per_game_addons.cpp @@ -47,6 +47,10 @@ ConfigurePerGameAddons::ConfigurePerGameAddons(Core::System& system_, QWidget* p item_model->setHeaderData(0, Qt::Horizontal, tr("Patch Name")); item_model->setHeaderData(1, Qt::Horizontal, tr("Version")); + tree_view->header()->setStretchLastSection(false); + tree_view->header()->setSectionResizeMode(0, QHeaderView::ResizeMode::Stretch); + tree_view->header()->setMinimumSectionSize(150); + // We must register all custom types with the Qt Automoc system so that we are able to use it // with signals/slots. In this case, QList falls under the umbrella of custom types. qRegisterMetaType>("QList"); @@ -138,5 +142,5 @@ void ConfigurePerGameAddons::LoadConfiguration() { item_model->appendRow(list_items.back()); } - tree_view->setColumnWidth(0, 5 * tree_view->width() / 16); + tree_view->resizeColumnToContents(1); }