early-access version 2637
This commit is contained in:
parent
0d49569ca5
commit
0397c1ff98
10 changed files with 84 additions and 26 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 2636.
|
This is the source code for early-access 2637.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,14 @@ void AxxEmitX64::EmitMemoryRead(AxxEmitContext& ctx, IR::Inst* inst) {
|
||||||
return;
|
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 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();
|
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;
|
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 Xbyak::Reg64 vaddr = ctx.reg_alloc.UseGpr(args[0]);
|
||||||
const int value_idx = bitsize == 128
|
const int value_idx = bitsize == 128
|
||||||
? ctx.reg_alloc.UseXmm(args[1]).getIdx()
|
? 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);
|
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 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();
|
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);
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
const bool ordered = IsOrdered(args[2].GetImmediateAccType());
|
const bool ordered = true;
|
||||||
|
|
||||||
const auto value = [&] {
|
const auto value = [&] {
|
||||||
if constexpr (bitsize == 128) {
|
if constexpr (bitsize == 128) {
|
||||||
|
|
|
@ -201,10 +201,13 @@ template<>
|
||||||
template<std::size_t bitsize>
|
template<std::size_t bitsize>
|
||||||
const void* EmitReadMemoryMov(BlockOfCode& code, int value_idx, const Xbyak::RegExp& addr, bool ordered) {
|
const void* EmitReadMemoryMov(BlockOfCode& code, int value_idx, const Xbyak::RegExp& addr, bool ordered) {
|
||||||
if (ordered) {
|
if (ordered) {
|
||||||
if constexpr (bitsize == 128) {
|
if constexpr (bitsize != 128) {
|
||||||
code.mfence();
|
|
||||||
} else {
|
|
||||||
code.xor_(Xbyak::Reg32{value_idx}, Xbyak::Reg32{value_idx});
|
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();
|
const void* fastmem_location = code.getCurr();
|
||||||
|
@ -215,7 +218,7 @@ const void* EmitReadMemoryMov(BlockOfCode& code, int value_idx, const Xbyak::Reg
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
code.lock();
|
code.lock();
|
||||||
code.xadd(word[addr], Xbyak::Reg32{value_idx});
|
code.xadd(word[addr], Xbyak::Reg16{value_idx});
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
code.lock();
|
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});
|
code.xadd(qword[addr], Xbyak::Reg64{value_idx});
|
||||||
break;
|
break;
|
||||||
case 128:
|
case 128:
|
||||||
// TODO (HACK): Detect CPUs where this load is not atomic
|
code.lock();
|
||||||
code.movaps(Xbyak::Xmm{value_idx}, xword[addr]);
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
ASSERT_FALSE("Invalid bitsize");
|
ASSERT_FALSE("Invalid bitsize");
|
||||||
|
@ -261,6 +272,20 @@ const void* EmitReadMemoryMov(BlockOfCode& code, int value_idx, const Xbyak::Reg
|
||||||
template<std::size_t bitsize>
|
template<std::size_t bitsize>
|
||||||
const void* EmitWriteMemoryMov(BlockOfCode& code, const Xbyak::RegExp& addr, int value_idx, bool ordered) {
|
const void* EmitWriteMemoryMov(BlockOfCode& code, const Xbyak::RegExp& addr, int value_idx, bool ordered) {
|
||||||
if (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();
|
const void* fastmem_location = code.getCurr();
|
||||||
switch (bitsize) {
|
switch (bitsize) {
|
||||||
case 8:
|
case 8:
|
||||||
|
@ -275,10 +300,14 @@ const void* EmitWriteMemoryMov(BlockOfCode& code, const Xbyak::RegExp& addr, int
|
||||||
case 64:
|
case 64:
|
||||||
code.xchg(qword[addr], Xbyak::Reg64{value_idx});
|
code.xchg(qword[addr], Xbyak::Reg64{value_idx});
|
||||||
break;
|
break;
|
||||||
case 128:
|
case 128: {
|
||||||
code.movaps(xword[addr], Xbyak::Xmm{value_idx});
|
Xbyak::Label loop;
|
||||||
code.mfence();
|
code.L(loop);
|
||||||
|
code.lock();
|
||||||
|
code.cmpxchg16b(xword[addr]);
|
||||||
|
code.jnz(loop);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
ASSERT_FALSE("Invalid bitsize");
|
ASSERT_FALSE("Invalid bitsize");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 != nullptr, "Newly created file with success cannot be found.");
|
||||||
|
|
||||||
ASSERT_MSG(dest->WriteBytes(src->ReadAllBytes()) == src->GetSize(),
|
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))) {
|
if (!src->GetContainingDirectory()->DeleteFile(Common::FS::GetFilename(src_path))) {
|
||||||
// TODO(DarkLordZach): Find a better error code for this
|
// TODO(DarkLordZach): Find a better error code for this
|
||||||
|
|
|
@ -26,7 +26,7 @@ void NVDRV::Open(Kernel::HLERequestContext& ctx) {
|
||||||
rb.Push<DeviceFD>(0);
|
rb.Push<DeviceFD>(0);
|
||||||
rb.PushEnum(NvResult::NotInitialized);
|
rb.PushEnum(NvResult::NotInitialized);
|
||||||
|
|
||||||
LOG_ERROR(Service_NVDRV, "NvServices is not initalized!");
|
LOG_ERROR(Service_NVDRV, "NvServices is not initialized!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ void NVDRV::Ioctl1(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
if (!is_initialized) {
|
if (!is_initialized) {
|
||||||
ServiceError(ctx, NvResult::NotInitialized);
|
ServiceError(ctx, NvResult::NotInitialized);
|
||||||
LOG_ERROR(Service_NVDRV, "NvServices is not initalized!");
|
LOG_ERROR(Service_NVDRV, "NvServices is not initialized!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ void NVDRV::Ioctl2(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
if (!is_initialized) {
|
if (!is_initialized) {
|
||||||
ServiceError(ctx, NvResult::NotInitialized);
|
ServiceError(ctx, NvResult::NotInitialized);
|
||||||
LOG_ERROR(Service_NVDRV, "NvServices is not initalized!");
|
LOG_ERROR(Service_NVDRV, "NvServices is not initialized!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ void NVDRV::Ioctl3(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
if (!is_initialized) {
|
if (!is_initialized) {
|
||||||
ServiceError(ctx, NvResult::NotInitialized);
|
ServiceError(ctx, NvResult::NotInitialized);
|
||||||
LOG_ERROR(Service_NVDRV, "NvServices is not initalized!");
|
LOG_ERROR(Service_NVDRV, "NvServices is not initialized!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ void NVDRV::Close(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
if (!is_initialized) {
|
if (!is_initialized) {
|
||||||
ServiceError(ctx, NvResult::NotInitialized);
|
ServiceError(ctx, NvResult::NotInitialized);
|
||||||
LOG_ERROR(Service_NVDRV, "NvServices is not initalized!");
|
LOG_ERROR(Service_NVDRV, "NvServices is not initialized!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
if (!is_initialized) {
|
if (!is_initialized) {
|
||||||
ServiceError(ctx, NvResult::NotInitialized);
|
ServiceError(ctx, NvResult::NotInitialized);
|
||||||
LOG_ERROR(Service_NVDRV, "NvServices is not initalized!");
|
LOG_ERROR(Service_NVDRV, "NvServices is not initialized!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,7 @@ void Impl(TranslatorVisitor& v, u64 insn, bool is_bindless) {
|
||||||
multisample = v.X(meta_reg++);
|
multisample = v.X(meta_reg++);
|
||||||
}
|
}
|
||||||
if (tld.clamp != 0) {
|
if (tld.clamp != 0) {
|
||||||
throw NotImplementedException("TLD.CL - CLAMP is not implmented");
|
throw NotImplementedException("TLD.CL - CLAMP is not implemented");
|
||||||
}
|
}
|
||||||
IR::TextureInstInfo info{};
|
IR::TextureInstInfo info{};
|
||||||
info.type.Assign(GetType(tld.type));
|
info.type.Assign(GetType(tld.type));
|
||||||
|
|
|
@ -81,7 +81,7 @@ void Impl(TranslatorVisitor& v, u64 insn, bool is_bindless) {
|
||||||
} const tmml{insn};
|
} const tmml{insn};
|
||||||
|
|
||||||
if ((tmml.mask & 0b1100) != 0) {
|
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)};
|
const IR::Value coords{MakeCoords(v, tmml.coord_reg, tmml.type)};
|
||||||
|
|
||||||
|
|
|
@ -736,7 +736,7 @@ VkFormat Device::GetSupportedFormat(VkFormat wanted_format, VkFormatFeatureFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::ReportLoss() const {
|
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
|
// Wait for the log to flush and for Nsight Aftermath to dump the results
|
||||||
std::this_thread::sleep_for(std::chrono::seconds{15});
|
std::this_thread::sleep_for(std::chrono::seconds{15});
|
||||||
|
|
|
@ -35,8 +35,9 @@ ConfigureHotkeys::ConfigureHotkeys(Core::HID::HIDCore& hid_core, QWidget* parent
|
||||||
ui->hotkey_list->setContextMenuPolicy(Qt::CustomContextMenu);
|
ui->hotkey_list->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
ui->hotkey_list->setModel(model);
|
ui->hotkey_list->setModel(model);
|
||||||
|
|
||||||
ui->hotkey_list->setColumnWidth(name_column, 200);
|
ui->hotkey_list->header()->setStretchLastSection(false);
|
||||||
ui->hotkey_list->resizeColumnToContents(hotkey_column);
|
ui->hotkey_list->header()->setSectionResizeMode(name_column, QHeaderView::ResizeMode::Stretch);
|
||||||
|
ui->hotkey_list->header()->setMinimumSectionSize(150);
|
||||||
|
|
||||||
connect(ui->button_restore_defaults, &QPushButton::clicked, this,
|
connect(ui->button_restore_defaults, &QPushButton::clicked, this,
|
||||||
&ConfigureHotkeys::RestoreDefaults);
|
&ConfigureHotkeys::RestoreDefaults);
|
||||||
|
@ -76,8 +77,8 @@ void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->hotkey_list->expandAll();
|
ui->hotkey_list->expandAll();
|
||||||
ui->hotkey_list->resizeColumnToContents(name_column);
|
|
||||||
ui->hotkey_list->resizeColumnToContents(hotkey_column);
|
ui->hotkey_list->resizeColumnToContents(hotkey_column);
|
||||||
|
ui->hotkey_list->resizeColumnToContents(controller_column);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureHotkeys::changeEvent(QEvent* event) {
|
void ConfigureHotkeys::changeEvent(QEvent* event) {
|
||||||
|
|
|
@ -47,6 +47,10 @@ ConfigurePerGameAddons::ConfigurePerGameAddons(Core::System& system_, QWidget* p
|
||||||
item_model->setHeaderData(0, Qt::Horizontal, tr("Patch Name"));
|
item_model->setHeaderData(0, Qt::Horizontal, tr("Patch Name"));
|
||||||
item_model->setHeaderData(1, Qt::Horizontal, tr("Version"));
|
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
|
// 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.
|
// with signals/slots. In this case, QList falls under the umbrella of custom types.
|
||||||
qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>");
|
qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>");
|
||||||
|
@ -138,5 +142,5 @@ void ConfigurePerGameAddons::LoadConfiguration() {
|
||||||
item_model->appendRow(list_items.back());
|
item_model->appendRow(list_items.back());
|
||||||
}
|
}
|
||||||
|
|
||||||
tree_view->setColumnWidth(0, 5 * tree_view->width() / 16);
|
tree_view->resizeColumnToContents(1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue