Merge pull request #10209 from Pokechu22/assert-fmt
Assertion and panic alert improvements
This commit is contained in:
commit
3da6487531
|
@ -10,16 +10,10 @@ SRCDIR=Source
|
||||||
find $SRCDIR -name '*.cpp' -o -name '*.h' -o -name '*.c' | \
|
find $SRCDIR -name '*.cpp' -o -name '*.h' -o -name '*.c' | \
|
||||||
xgettext -s -p ./Languages/po -o dolphin-emu.pot --package-name="Dolphin Emulator" \
|
xgettext -s -p ./Languages/po -o dolphin-emu.pot --package-name="Dolphin Emulator" \
|
||||||
--keyword=_ \
|
--keyword=_ \
|
||||||
--keyword=wxTRANSLATE \
|
|
||||||
--keyword=AskYesNoT \
|
|
||||||
--keyword=AskYesNoFmtT \
|
--keyword=AskYesNoFmtT \
|
||||||
--keyword=CriticalAlertT \
|
|
||||||
--keyword=CriticalAlertFmtT \
|
--keyword=CriticalAlertFmtT \
|
||||||
--keyword=PanicAlertT \
|
|
||||||
--keyword=PanicAlertFmtT \
|
--keyword=PanicAlertFmtT \
|
||||||
--keyword=PanicYesNoT \
|
|
||||||
--keyword=PanicYesNoFmtT \
|
--keyword=PanicYesNoFmtT \
|
||||||
--keyword=SuccessAlertT \
|
|
||||||
--keyword=SuccessAlertFmtT \
|
--keyword=SuccessAlertFmtT \
|
||||||
--keyword=GetStringT \
|
--keyword=GetStringT \
|
||||||
--keyword=_trans \
|
--keyword=_trans \
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include <UICommon/GameFile.h>
|
#include <UICommon/GameFile.h>
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
#include <android/native_window_jni.h>
|
#include <android/native_window_jni.h>
|
||||||
#include <cinttypes>
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
|
#include "Common/HRWrap.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "Common/Thread.h"
|
#include "Common/Thread.h"
|
||||||
|
@ -66,11 +67,11 @@ static bool HandleWinAPI(std::string_view message, HRESULT result)
|
||||||
error = "Audio endpoint already in use!";
|
error = "Audio endpoint already in use!";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error = TStrToUTF8(_com_error(result).ErrorMessage()).c_str();
|
error = Common::GetHResultMessage(result);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ERROR_LOG_FMT(AUDIO, "WASAPI: {}: {}", message, error);
|
ERROR_LOG_FMT(AUDIO, "WASAPI: {}: {} ({:08x})", message, error, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SUCCEEDED(result);
|
return SUCCEEDED(result);
|
||||||
|
|
|
@ -5,13 +5,14 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cinttypes>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "Common/Align.h"
|
#include "Common/Align.h"
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
#include "Common/BitUtils.h"
|
#include "Common/BitUtils.h"
|
||||||
|
@ -307,13 +308,12 @@ void ARM64XEmitter::EncodeCompareBranchInst(u32 op, ARM64Reg Rt, const void* ptr
|
||||||
bool b64Bit = Is64Bit(Rt);
|
bool b64Bit = Is64Bit(Rt);
|
||||||
s64 distance = (s64)ptr - (s64)m_code;
|
s64 distance = (s64)ptr - (s64)m_code;
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, !(distance & 0x3), "%s: distance must be a multiple of 4: %" PRIx64,
|
ASSERT_MSG(DYNA_REC, !(distance & 0x3), "Distance must be a multiple of 4: {}", distance);
|
||||||
__func__, distance);
|
|
||||||
|
|
||||||
distance >>= 2;
|
distance >>= 2;
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, distance >= -0x40000 && distance <= 0x3FFFF,
|
ASSERT_MSG(DYNA_REC, distance >= -0x40000 && distance <= 0x3FFFF,
|
||||||
"%s: Received too large distance: %" PRIx64, __func__, distance);
|
"Received too large distance: {}", distance);
|
||||||
|
|
||||||
Write32((b64Bit << 31) | (0x34 << 24) | (op << 24) | (((u32)distance << 5) & 0xFFFFE0) |
|
Write32((b64Bit << 31) | (0x34 << 24) | (op << 24) | (((u32)distance << 5) & 0xFFFFE0) |
|
||||||
DecodeReg(Rt));
|
DecodeReg(Rt));
|
||||||
|
@ -325,13 +325,12 @@ void ARM64XEmitter::EncodeTestBranchInst(u32 op, ARM64Reg Rt, u8 bits, const voi
|
||||||
u8 b5 = (bits >> 5) & 0x1;
|
u8 b5 = (bits >> 5) & 0x1;
|
||||||
s64 distance = (s64)ptr - (s64)m_code;
|
s64 distance = (s64)ptr - (s64)m_code;
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, !(distance & 0x3), "%s: distance must be a multiple of 4: %" PRIx64,
|
ASSERT_MSG(DYNA_REC, !(distance & 0x3), "distance must be a multiple of 4: {}", distance);
|
||||||
__func__, distance);
|
|
||||||
|
|
||||||
distance >>= 2;
|
distance >>= 2;
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, distance >= -0x3FFF && distance < 0x3FFF,
|
ASSERT_MSG(DYNA_REC, distance >= -0x3FFF && distance < 0x3FFF, "Received too large distance: {}",
|
||||||
"%s: Received too large distance: %" PRIx64, __func__, distance);
|
distance);
|
||||||
|
|
||||||
Write32((b5 << 31) | (0x36 << 24) | (op << 24) | (b40 << 19) |
|
Write32((b5 << 31) | (0x36 << 24) | (op << 24) | (b40 << 19) |
|
||||||
((static_cast<u32>(distance) << 5) & 0x7FFE0) | DecodeReg(Rt));
|
((static_cast<u32>(distance) << 5) & 0x7FFE0) | DecodeReg(Rt));
|
||||||
|
@ -341,13 +340,12 @@ void ARM64XEmitter::EncodeUnconditionalBranchInst(u32 op, const void* ptr)
|
||||||
{
|
{
|
||||||
s64 distance = (s64)ptr - s64(m_code);
|
s64 distance = (s64)ptr - s64(m_code);
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, !(distance & 0x3), "%s: distance must be a multiple of 4: %" PRIx64,
|
ASSERT_MSG(DYNA_REC, !(distance & 0x3), "distance must be a multiple of 4: {}", distance);
|
||||||
__func__, distance);
|
|
||||||
|
|
||||||
distance >>= 2;
|
distance >>= 2;
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, distance >= -0x2000000LL && distance <= 0x1FFFFFFLL,
|
ASSERT_MSG(DYNA_REC, distance >= -0x2000000LL && distance <= 0x1FFFFFFLL,
|
||||||
"%s: Received too large distance: %" PRIx64, __func__, distance);
|
"Received too large distance: {}", distance);
|
||||||
|
|
||||||
Write32((op << 31) | (0x5 << 26) | (distance & 0x3FFFFFF));
|
Write32((op << 31) | (0x5 << 26) | (distance & 0x3FFFFFF));
|
||||||
}
|
}
|
||||||
|
@ -359,8 +357,7 @@ void ARM64XEmitter::EncodeUnconditionalBranchInst(u32 opc, u32 op2, u32 op3, u32
|
||||||
|
|
||||||
void ARM64XEmitter::EncodeExceptionInst(u32 instenc, u32 imm)
|
void ARM64XEmitter::EncodeExceptionInst(u32 instenc, u32 imm)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !(imm & ~0xFFFF), "%s: Exception instruction too large immediate: %d",
|
ASSERT_MSG(DYNA_REC, !(imm & ~0xFFFF), "Exception instruction too large immediate: {}", imm);
|
||||||
__func__, imm);
|
|
||||||
|
|
||||||
Write32((0xD4 << 24) | (ExcEnc[instenc][0] << 21) | (imm << 5) | (ExcEnc[instenc][1] << 2) |
|
Write32((0xD4 << 24) | (ExcEnc[instenc][0] << 21) | (imm << 5) | (ExcEnc[instenc][1] << 2) |
|
||||||
ExcEnc[instenc][2]);
|
ExcEnc[instenc][2]);
|
||||||
|
@ -395,8 +392,8 @@ void ARM64XEmitter::EncodeCondCompareImmInst(u32 op, ARM64Reg Rn, u32 imm, u32 n
|
||||||
{
|
{
|
||||||
bool b64Bit = Is64Bit(Rn);
|
bool b64Bit = Is64Bit(Rn);
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, !(imm & ~0x1F), "%s: too large immediate: %d", __func__, imm);
|
ASSERT_MSG(DYNA_REC, !(imm & ~0x1F), "too large immediate: {}", imm);
|
||||||
ASSERT_MSG(DYNA_REC, !(nzcv & ~0xF), "%s: Flags out of range: %d", __func__, nzcv);
|
ASSERT_MSG(DYNA_REC, !(nzcv & ~0xF), "Flags out of range: {}", nzcv);
|
||||||
|
|
||||||
Write32((b64Bit << 31) | (op << 30) | (1 << 29) | (0xD2 << 21) | (imm << 16) | (cond << 12) |
|
Write32((b64Bit << 31) | (op << 30) | (1 << 29) | (0xD2 << 21) | (imm << 16) | (cond << 12) |
|
||||||
(1 << 11) | (DecodeReg(Rn) << 5) | nzcv);
|
(1 << 11) | (DecodeReg(Rn) << 5) | nzcv);
|
||||||
|
@ -407,7 +404,7 @@ void ARM64XEmitter::EncodeCondCompareRegInst(u32 op, ARM64Reg Rn, ARM64Reg Rm, u
|
||||||
{
|
{
|
||||||
bool b64Bit = Is64Bit(Rm);
|
bool b64Bit = Is64Bit(Rm);
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, !(nzcv & ~0xF), "%s: Flags out of range: %d", __func__, nzcv);
|
ASSERT_MSG(DYNA_REC, !(nzcv & ~0xF), "Flags out of range: {}", nzcv);
|
||||||
|
|
||||||
Write32((b64Bit << 31) | (op << 30) | (1 << 29) | (0xD2 << 21) | (DecodeReg(Rm) << 16) |
|
Write32((b64Bit << 31) | (op << 30) | (1 << 29) | (0xD2 << 21) | (DecodeReg(Rm) << 16) |
|
||||||
(cond << 12) | (DecodeReg(Rn) << 5) | nzcv);
|
(cond << 12) | (DecodeReg(Rn) << 5) | nzcv);
|
||||||
|
@ -464,7 +461,7 @@ void ARM64XEmitter::EncodeLoadRegisterInst(u32 bitop, ARM64Reg Rt, u32 imm)
|
||||||
bool b64Bit = Is64Bit(Rt);
|
bool b64Bit = Is64Bit(Rt);
|
||||||
bool bVec = IsVector(Rt);
|
bool bVec = IsVector(Rt);
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, !(imm & 0xFFFFF), "%s: offset too large %d", __func__, imm);
|
ASSERT_MSG(DYNA_REC, !(imm & 0xFFFFF), "offset too large {}", imm);
|
||||||
|
|
||||||
if (b64Bit && bitop != 0x2) // LDRSW(0x2) uses 64bit reg, doesn't have 64bit bit set
|
if (b64Bit && bitop != 0x2) // LDRSW(0x2) uses 64bit reg, doesn't have 64bit bit set
|
||||||
bitop |= 0x1;
|
bitop |= 0x1;
|
||||||
|
@ -494,7 +491,7 @@ void ARM64XEmitter::EncodeLoadStorePairedInst(u32 op, ARM64Reg Rt, ARM64Reg Rt2,
|
||||||
else
|
else
|
||||||
imm >>= 2;
|
imm >>= 2;
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, !(imm & ~0xF), "%s: offset too large %d", __func__, imm);
|
ASSERT_MSG(DYNA_REC, !(imm & ~0xF), "offset too large {}", imm);
|
||||||
|
|
||||||
u32 opc = 0;
|
u32 opc = 0;
|
||||||
if (b128Bit)
|
if (b128Bit)
|
||||||
|
@ -515,7 +512,7 @@ void ARM64XEmitter::EncodeLoadStoreIndexedInst(u32 op, u32 op2, ARM64Reg Rt, ARM
|
||||||
|
|
||||||
u32 offset = imm & 0x1FF;
|
u32 offset = imm & 0x1FF;
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, !(imm < -256 || imm > 255), "%s: offset too large %d", __func__, imm);
|
ASSERT_MSG(DYNA_REC, !(imm < -256 || imm > 255), "offset too large {}", imm);
|
||||||
|
|
||||||
Write32((b64Bit << 30) | (op << 22) | (bVec << 26) | (offset << 12) | (op2 << 10) |
|
Write32((b64Bit << 30) | (op << 22) | (bVec << 26) | (offset << 12) | (op2 << 10) |
|
||||||
(DecodeReg(Rn) << 5) | DecodeReg(Rt));
|
(DecodeReg(Rn) << 5) | DecodeReg(Rt));
|
||||||
|
@ -533,10 +530,8 @@ void ARM64XEmitter::EncodeLoadStoreIndexedInst(u32 op, ARM64Reg Rt, ARM64Reg Rn,
|
||||||
else if (size == 16)
|
else if (size == 16)
|
||||||
imm >>= 1;
|
imm >>= 1;
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, imm >= 0, "%s(IndexType::Unsigned): offset must be positive %d", __func__,
|
ASSERT_MSG(DYNA_REC, imm >= 0, "(IndexType::Unsigned): offset must be positive {}", imm);
|
||||||
imm);
|
ASSERT_MSG(DYNA_REC, !(imm & ~0xFFF), "(IndexType::Unsigned): offset too large {}", imm);
|
||||||
ASSERT_MSG(DYNA_REC, !(imm & ~0xFFF), "%s(IndexType::Unsigned): offset too large %d", __func__,
|
|
||||||
imm);
|
|
||||||
|
|
||||||
Write32((b64Bit << 30) | (op << 22) | (bVec << 26) | (imm << 10) | (DecodeReg(Rn) << 5) |
|
Write32((b64Bit << 30) | (op << 22) | (bVec << 26) | (imm << 10) | (DecodeReg(Rn) << 5) |
|
||||||
DecodeReg(Rt));
|
DecodeReg(Rt));
|
||||||
|
@ -546,7 +541,7 @@ void ARM64XEmitter::EncodeMOVWideInst(u32 op, ARM64Reg Rd, u32 imm, ShiftAmount
|
||||||
{
|
{
|
||||||
bool b64Bit = Is64Bit(Rd);
|
bool b64Bit = Is64Bit(Rd);
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, !(imm & ~0xFFFF), "%s: immediate out of range: %d", __func__, imm);
|
ASSERT_MSG(DYNA_REC, !(imm & ~0xFFFF), "immediate out of range: {}", imm);
|
||||||
|
|
||||||
Write32((b64Bit << 31) | (op << 29) | (0x25 << 23) | (static_cast<u32>(pos) << 21) | (imm << 5) |
|
Write32((b64Bit << 31) | (op << 29) | (0x25 << 23) | (static_cast<u32>(pos) << 21) | (imm << 5) |
|
||||||
DecodeReg(Rd));
|
DecodeReg(Rd));
|
||||||
|
@ -574,7 +569,7 @@ void ARM64XEmitter::EncodeAddSubImmInst(u32 op, bool flags, u32 shift, u32 imm,
|
||||||
{
|
{
|
||||||
bool b64Bit = Is64Bit(Rd);
|
bool b64Bit = Is64Bit(Rd);
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, !(imm & ~0xFFF), "%s: immediate too large: %x", __func__, imm);
|
ASSERT_MSG(DYNA_REC, !(imm & ~0xFFF), "immediate too large: {}", imm);
|
||||||
|
|
||||||
Write32((b64Bit << 31) | (op << 30) | (flags << 29) | (0x11 << 24) | (shift << 22) | (imm << 10) |
|
Write32((b64Bit << 31) | (op << 30) | (flags << 29) | (0x11 << 24) | (shift << 22) | (imm << 10) |
|
||||||
(DecodeReg(Rn) << 5) | DecodeReg(Rd));
|
(DecodeReg(Rn) << 5) | DecodeReg(Rd));
|
||||||
|
@ -582,13 +577,14 @@ void ARM64XEmitter::EncodeAddSubImmInst(u32 op, bool flags, u32 shift, u32 imm,
|
||||||
|
|
||||||
void ARM64XEmitter::EncodeLogicalImmInst(u32 op, ARM64Reg Rd, ARM64Reg Rn, LogicalImm imm)
|
void ARM64XEmitter::EncodeLogicalImmInst(u32 op, ARM64Reg Rd, ARM64Reg Rn, LogicalImm imm)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNAREC, imm.valid, "Invalid logical immediate");
|
ASSERT_MSG(DYNA_REC, imm.valid, "Invalid logical immediate");
|
||||||
|
|
||||||
// Sometimes Rd is fixed to SP, but can still be 32bit or 64bit.
|
// Sometimes Rd is fixed to SP, but can still be 32bit or 64bit.
|
||||||
// Use Rn to determine bitness here.
|
// Use Rn to determine bitness here.
|
||||||
bool b64Bit = Is64Bit(Rn);
|
bool b64Bit = Is64Bit(Rn);
|
||||||
|
|
||||||
ASSERT_MSG(DYNAREC, b64Bit || !imm.n, "64-bit logical immediate does not fit in 32-bit register");
|
ASSERT_MSG(DYNA_REC, b64Bit || !imm.n,
|
||||||
|
"64-bit logical immediate does not fit in 32-bit register");
|
||||||
|
|
||||||
Write32((b64Bit << 31) | (op << 29) | (0x24 << 23) | (imm.n << 22) | (imm.r << 16) |
|
Write32((b64Bit << 31) | (op << 29) | (0x24 << 23) | (imm.n << 22) | (imm.r << 16) |
|
||||||
(imm.s << 10) | (DecodeReg(Rn) << 5) | DecodeReg(Rd));
|
(imm.s << 10) | (DecodeReg(Rn) << 5) | DecodeReg(Rd));
|
||||||
|
@ -612,7 +608,7 @@ void ARM64XEmitter::EncodeLoadStorePair(u32 op, u32 load, IndexType type, ARM64R
|
||||||
type_encode = 0b011;
|
type_encode = 0b011;
|
||||||
break;
|
break;
|
||||||
case IndexType::Unsigned:
|
case IndexType::Unsigned:
|
||||||
ASSERT_MSG(DYNA_REC, false, "%s doesn't support IndexType::Unsigned!", __func__);
|
ASSERT_MSG(DYNA_REC, false, "IndexType::Unsigned is not supported!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -626,7 +622,7 @@ void ARM64XEmitter::EncodeLoadStorePair(u32 op, u32 load, IndexType type, ARM64R
|
||||||
imm >>= 2;
|
imm >>= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, imm >= -64 && imm < 64, "imm too large for load/store pair!");
|
ASSERT_MSG(DYNA_REC, imm >= -64 && imm < 64, "imm too large for load/store pair! {}", imm);
|
||||||
|
|
||||||
Write32((op << 30) | (0b101 << 27) | (type_encode << 23) | (load << 22) | ((imm & 0x7F) << 15) |
|
Write32((op << 30) | (0b101 << 27) | (type_encode << 23) | (load << 22) | ((imm & 0x7F) << 15) |
|
||||||
(DecodeReg(Rt2) << 10) | (DecodeReg(Rn) << 5) | DecodeReg(Rt));
|
(DecodeReg(Rt2) << 10) | (DecodeReg(Rn) << 5) | DecodeReg(Rt));
|
||||||
|
@ -639,8 +635,7 @@ void ARM64XEmitter::EncodeAddressInst(u32 op, ARM64Reg Rd, s32 imm)
|
||||||
|
|
||||||
void ARM64XEmitter::EncodeLoadStoreUnscaled(u32 size, u32 op, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
|
void ARM64XEmitter::EncodeLoadStoreUnscaled(u32 size, u32 op, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !(imm < -256 || imm > 255), "%s received too large offset: %d", __func__,
|
ASSERT_MSG(DYNA_REC, !(imm < -256 || imm > 255), "offset too large: {}", imm);
|
||||||
imm);
|
|
||||||
|
|
||||||
Write32((size << 30) | (0b111 << 27) | (op << 22) | ((imm & 0x1FF) << 12) | (DecodeReg(Rn) << 5) |
|
Write32((size << 30) | (0b111 << 27) | (op << 22) | ((imm & 0x1FF) << 12) | (DecodeReg(Rn) << 5) |
|
||||||
DecodeReg(Rt));
|
DecodeReg(Rt));
|
||||||
|
@ -694,16 +689,16 @@ void ARM64XEmitter::SetJumpTarget(FixupBranch const& branch)
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case FixupBranch::Type::CBZ:
|
case FixupBranch::Type::CBZ:
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, IsInRangeImm19(distance), "%s(%d): Received too large distance: %" PRIx64,
|
ASSERT_MSG(DYNA_REC, IsInRangeImm19(distance),
|
||||||
__func__, static_cast<int>(branch.type), distance);
|
"Branch type {}: Received too large distance: {}", branch.type, distance);
|
||||||
const bool b64Bit = Is64Bit(branch.reg);
|
const bool b64Bit = Is64Bit(branch.reg);
|
||||||
inst = (b64Bit << 31) | (0x1A << 25) | (Not << 24) | (MaskImm19(distance) << 5) |
|
inst = (b64Bit << 31) | (0x1A << 25) | (Not << 24) | (MaskImm19(distance) << 5) |
|
||||||
DecodeReg(branch.reg);
|
DecodeReg(branch.reg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FixupBranch::Type::BConditional:
|
case FixupBranch::Type::BConditional:
|
||||||
ASSERT_MSG(DYNA_REC, IsInRangeImm19(distance), "%s(%d): Received too large distance: %" PRIx64,
|
ASSERT_MSG(DYNA_REC, IsInRangeImm19(distance),
|
||||||
__func__, static_cast<int>(branch.type), distance);
|
"Branch type {}: Received too large distance: {}", branch.type, distance);
|
||||||
inst = (0x2A << 25) | (MaskImm19(distance) << 5) | branch.cond;
|
inst = (0x2A << 25) | (MaskImm19(distance) << 5) | branch.cond;
|
||||||
break;
|
break;
|
||||||
case FixupBranch::Type::TBNZ:
|
case FixupBranch::Type::TBNZ:
|
||||||
|
@ -711,20 +706,20 @@ void ARM64XEmitter::SetJumpTarget(FixupBranch const& branch)
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case FixupBranch::Type::TBZ:
|
case FixupBranch::Type::TBZ:
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, IsInRangeImm14(distance), "%s(%d): Received too large distance: %" PRIx64,
|
ASSERT_MSG(DYNA_REC, IsInRangeImm14(distance),
|
||||||
__func__, static_cast<int>(branch.type), distance);
|
"Branch type {}: Received too large distance: {}", branch.type, distance);
|
||||||
inst = ((branch.bit & 0x20) << 26) | (0x1B << 25) | (Not << 24) | ((branch.bit & 0x1F) << 19) |
|
inst = ((branch.bit & 0x20) << 26) | (0x1B << 25) | (Not << 24) | ((branch.bit & 0x1F) << 19) |
|
||||||
(MaskImm14(distance) << 5) | DecodeReg(branch.reg);
|
(MaskImm14(distance) << 5) | DecodeReg(branch.reg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FixupBranch::Type::B:
|
case FixupBranch::Type::B:
|
||||||
ASSERT_MSG(DYNA_REC, IsInRangeImm26(distance), "%s(%d): Received too large distance: %" PRIx64,
|
ASSERT_MSG(DYNA_REC, IsInRangeImm26(distance),
|
||||||
__func__, static_cast<int>(branch.type), distance);
|
"Branch type {}: Received too large distance: {}", branch.type, distance);
|
||||||
inst = (0x5 << 26) | MaskImm26(distance);
|
inst = (0x5 << 26) | MaskImm26(distance);
|
||||||
break;
|
break;
|
||||||
case FixupBranch::Type::BL:
|
case FixupBranch::Type::BL:
|
||||||
ASSERT_MSG(DYNA_REC, IsInRangeImm26(distance), "%s(%d): Received too large distance: %" PRIx64,
|
ASSERT_MSG(DYNA_REC, IsInRangeImm26(distance),
|
||||||
__func__, static_cast<int>(branch.type), distance);
|
"Branch type {}: Received too large distance: {}", branch.type, distance);
|
||||||
inst = (0x25 << 26) | MaskImm26(distance);
|
inst = (0x25 << 26) | MaskImm26(distance);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -815,7 +810,7 @@ void ARM64XEmitter::B(CCFlags cond, const void* ptr)
|
||||||
distance >>= 2;
|
distance >>= 2;
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, IsInRangeImm19(distance),
|
ASSERT_MSG(DYNA_REC, IsInRangeImm19(distance),
|
||||||
"%s: Received too large distance: %p->%p %" PRIi64 " %" PRIx64, __func__, m_code, ptr,
|
"Received too large distance: {}->{} (dist {} {:#x})", fmt::ptr(m_code), fmt::ptr(ptr),
|
||||||
distance, distance);
|
distance, distance);
|
||||||
Write32((0x54 << 24) | (MaskImm19(distance) << 5) | cond);
|
Write32((0x54 << 24) | (MaskImm19(distance) << 5) | cond);
|
||||||
}
|
}
|
||||||
|
@ -1434,24 +1429,21 @@ void ARM64XEmitter::BFI(ARM64Reg Rd, ARM64Reg Rn, u32 lsb, u32 width)
|
||||||
{
|
{
|
||||||
u32 size = Is64Bit(Rn) ? 64 : 32;
|
u32 size = Is64Bit(Rn) ? 64 : 32;
|
||||||
ASSERT_MSG(DYNA_REC, lsb < size && width >= 1 && width <= size - lsb,
|
ASSERT_MSG(DYNA_REC, lsb < size && width >= 1 && width <= size - lsb,
|
||||||
"%s passed lsb %d and width %d which is greater than the register size!", __func__,
|
"lsb {} and width {} is greater than the register size {}!", lsb, width, size);
|
||||||
lsb, width);
|
|
||||||
BFM(Rd, Rn, (size - lsb) % size, width - 1);
|
BFM(Rd, Rn, (size - lsb) % size, width - 1);
|
||||||
}
|
}
|
||||||
void ARM64XEmitter::BFXIL(ARM64Reg Rd, ARM64Reg Rn, u32 lsb, u32 width)
|
void ARM64XEmitter::BFXIL(ARM64Reg Rd, ARM64Reg Rn, u32 lsb, u32 width)
|
||||||
{
|
{
|
||||||
u32 size = Is64Bit(Rn) ? 64 : 32;
|
u32 size = Is64Bit(Rn) ? 64 : 32;
|
||||||
ASSERT_MSG(DYNA_REC, lsb < size && width >= 1 && width <= size - lsb,
|
ASSERT_MSG(DYNA_REC, lsb < size && width >= 1 && width <= size - lsb,
|
||||||
"%s passed lsb %d and width %d which is greater than the register size!", __func__,
|
"lsb {} and width {} is greater than the register size {}!", lsb, width, size);
|
||||||
lsb, width);
|
|
||||||
BFM(Rd, Rn, lsb, lsb + width - 1);
|
BFM(Rd, Rn, lsb, lsb + width - 1);
|
||||||
}
|
}
|
||||||
void ARM64XEmitter::UBFIZ(ARM64Reg Rd, ARM64Reg Rn, u32 lsb, u32 width)
|
void ARM64XEmitter::UBFIZ(ARM64Reg Rd, ARM64Reg Rn, u32 lsb, u32 width)
|
||||||
{
|
{
|
||||||
u32 size = Is64Bit(Rn) ? 64 : 32;
|
u32 size = Is64Bit(Rn) ? 64 : 32;
|
||||||
ASSERT_MSG(DYNA_REC, lsb < size && width >= 1 && width <= size - lsb,
|
ASSERT_MSG(DYNA_REC, lsb < size && width >= 1 && width <= size - lsb,
|
||||||
"%s passed lsb %d and width %d which is greater than the register size!", __func__,
|
"lsb {} and width {} is greater than the register size {}!", lsb, width, size);
|
||||||
lsb, width);
|
|
||||||
UBFM(Rd, Rn, (size - lsb) % size, width - 1);
|
UBFM(Rd, Rn, (size - lsb) % size, width - 1);
|
||||||
}
|
}
|
||||||
void ARM64XEmitter::EXTR(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u32 shift)
|
void ARM64XEmitter::EXTR(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u32 shift)
|
||||||
|
@ -1472,7 +1464,7 @@ void ARM64XEmitter::SXTH(ARM64Reg Rd, ARM64Reg Rn)
|
||||||
}
|
}
|
||||||
void ARM64XEmitter::SXTW(ARM64Reg Rd, ARM64Reg Rn)
|
void ARM64XEmitter::SXTW(ARM64Reg Rd, ARM64Reg Rn)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, Is64Bit(Rd), "%s requires 64bit register as destination", __func__);
|
ASSERT_MSG(DYNA_REC, Is64Bit(Rd), "64bit register required as destination");
|
||||||
SBFM(Rd, Rn, 0, 31);
|
SBFM(Rd, Rn, 0, 31);
|
||||||
}
|
}
|
||||||
void ARM64XEmitter::UXTB(ARM64Reg Rd, ARM64Reg Rn)
|
void ARM64XEmitter::UXTB(ARM64Reg Rd, ARM64Reg Rn)
|
||||||
|
@ -1763,7 +1755,7 @@ void ARM64XEmitter::LDUR(ARM64Reg Rt, ARM64Reg Rn, s32 imm)
|
||||||
}
|
}
|
||||||
void ARM64XEmitter::LDURSW(ARM64Reg Rt, ARM64Reg Rn, s32 imm)
|
void ARM64XEmitter::LDURSW(ARM64Reg Rt, ARM64Reg Rn, s32 imm)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !Is64Bit(Rt), "%s must have a 64bit destination register!", __func__);
|
ASSERT_MSG(DYNA_REC, !Is64Bit(Rt), "Must have a 64bit destination register!");
|
||||||
EncodeLoadStoreUnscaled(2, 2, Rt, Rn, imm);
|
EncodeLoadStoreUnscaled(2, 2, Rt, Rn, imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2015,7 +2007,7 @@ void ARM64XEmitter::ABI_PushRegisters(BitSet32 registers)
|
||||||
STP(IndexType::Signed, odd_reg, even_reg, ARM64Reg::SP, 16 * (i + 1));
|
STP(IndexType::Signed, odd_reg, even_reg, ARM64Reg::SP, 16 * (i + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, it == registers.end(), "%s registers don't match.", __func__);
|
ASSERT_MSG(DYNA_REC, it == registers.end(), "Registers don't match: {:b}", registers.m_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARM64XEmitter::ABI_PopRegisters(BitSet32 registers, BitSet32 ignore_mask)
|
void ARM64XEmitter::ABI_PopRegisters(BitSet32 registers, BitSet32 ignore_mask)
|
||||||
|
@ -2052,7 +2044,7 @@ void ARM64XEmitter::ABI_PopRegisters(BitSet32 registers, BitSet32 ignore_mask)
|
||||||
else
|
else
|
||||||
LDP(IndexType::Post, first, second, ARM64Reg::SP, stack_size);
|
LDP(IndexType::Post, first, second, ARM64Reg::SP, stack_size);
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, it == registers.end(), "%s registers don't match.", __func__);
|
ASSERT_MSG(DYNA_REC, it == registers.end(), "Registers don't match: {:b}", registers.m_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Float Emitter
|
// Float Emitter
|
||||||
|
@ -2076,10 +2068,10 @@ void ARM64FloatEmitter::EmitLoadStoreImmediate(u8 size, u32 opc, IndexType type,
|
||||||
if (type == IndexType::Unsigned)
|
if (type == IndexType::Unsigned)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !(imm & ((size - 1) >> 3)),
|
ASSERT_MSG(DYNA_REC, !(imm & ((size - 1) >> 3)),
|
||||||
"%s(IndexType::Unsigned) immediate offset must be aligned to size! (%d) (%p)",
|
"(IndexType::Unsigned) immediate offset must be aligned to size! ({}) ({})", imm,
|
||||||
__func__, imm, m_emit->GetCodePtr());
|
fmt::ptr(m_emit->GetCodePtr()));
|
||||||
ASSERT_MSG(DYNA_REC, imm >= 0, "%s(IndexType::Unsigned) immediate offset must be positive!",
|
ASSERT_MSG(DYNA_REC, imm >= 0, "(IndexType::Unsigned) immediate offset must be positive! ({})",
|
||||||
__func__);
|
imm);
|
||||||
if (size == 16)
|
if (size == 16)
|
||||||
imm >>= 1;
|
imm >>= 1;
|
||||||
else if (size == 32)
|
else if (size == 32)
|
||||||
|
@ -2093,7 +2085,7 @@ void ARM64FloatEmitter::EmitLoadStoreImmediate(u8 size, u32 opc, IndexType type,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !(imm < -256 || imm > 255),
|
ASSERT_MSG(DYNA_REC, !(imm < -256 || imm > 255),
|
||||||
"%s immediate offset must be within range of -256 to 256!", __func__);
|
"immediate offset must be within range of -256 to 256! {}", imm);
|
||||||
encoded_imm = (imm & 0x1FF) << 2;
|
encoded_imm = (imm & 0x1FF) << 2;
|
||||||
if (type == IndexType::Post)
|
if (type == IndexType::Post)
|
||||||
encoded_imm |= 1;
|
encoded_imm |= 1;
|
||||||
|
@ -2109,7 +2101,7 @@ void ARM64FloatEmitter::EmitLoadStoreImmediate(u8 size, u32 opc, IndexType type,
|
||||||
void ARM64FloatEmitter::EmitScalar2Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd,
|
void ARM64FloatEmitter::EmitScalar2Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd,
|
||||||
ARM64Reg Rn, ARM64Reg Rm)
|
ARM64Reg Rn, ARM64Reg Rm)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !IsQuad(Rd), "%s only supports double and single registers!", __func__);
|
ASSERT_MSG(DYNA_REC, !IsQuad(Rd), "Only double and single registers are supported!");
|
||||||
|
|
||||||
Write32((M << 31) | (S << 29) | (0b11110001 << 21) | (type << 22) | (DecodeReg(Rm) << 16) |
|
Write32((M << 31) | (S << 29) | (0b11110001 << 21) | (type << 22) | (DecodeReg(Rm) << 16) |
|
||||||
(opcode << 12) | (1 << 11) | (DecodeReg(Rn) << 5) | DecodeReg(Rd));
|
(opcode << 12) | (1 << 11) | (DecodeReg(Rn) << 5) | DecodeReg(Rd));
|
||||||
|
@ -2118,7 +2110,7 @@ void ARM64FloatEmitter::EmitScalar2Source(bool M, bool S, u32 type, u32 opcode,
|
||||||
void ARM64FloatEmitter::EmitScalarThreeSame(bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn,
|
void ARM64FloatEmitter::EmitScalarThreeSame(bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn,
|
||||||
ARM64Reg Rm)
|
ARM64Reg Rm)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !IsQuad(Rd), "%s only supports double and single registers!", __func__);
|
ASSERT_MSG(DYNA_REC, !IsQuad(Rd), "Only double and single registers are supported!");
|
||||||
|
|
||||||
Write32((1 << 30) | (U << 29) | (0b11110001 << 21) | (size << 22) | (DecodeReg(Rm) << 16) |
|
Write32((1 << 30) | (U << 29) | (0b11110001 << 21) | (size << 22) | (DecodeReg(Rm) << 16) |
|
||||||
(opcode << 11) | (1 << 10) | (DecodeReg(Rn) << 5) | DecodeReg(Rd));
|
(opcode << 11) | (1 << 10) | (DecodeReg(Rn) << 5) | DecodeReg(Rd));
|
||||||
|
@ -2127,7 +2119,7 @@ void ARM64FloatEmitter::EmitScalarThreeSame(bool U, u32 size, u32 opcode, ARM64R
|
||||||
void ARM64FloatEmitter::EmitThreeSame(bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn,
|
void ARM64FloatEmitter::EmitThreeSame(bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn,
|
||||||
ARM64Reg Rm)
|
ARM64Reg Rm)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !IsSingle(Rd), "%s doesn't support singles!", __func__);
|
ASSERT_MSG(DYNA_REC, !IsSingle(Rd), "Singles are not supported!");
|
||||||
bool quad = IsQuad(Rd);
|
bool quad = IsQuad(Rd);
|
||||||
|
|
||||||
Write32((quad << 30) | (U << 29) | (0b1110001 << 21) | (size << 22) | (DecodeReg(Rm) << 16) |
|
Write32((quad << 30) | (U << 29) | (0b1110001 << 21) | (size << 22) | (DecodeReg(Rm) << 16) |
|
||||||
|
@ -2148,7 +2140,7 @@ void ARM64FloatEmitter::EmitScalar2RegMisc(bool U, u32 size, u32 opcode, ARM64Re
|
||||||
|
|
||||||
void ARM64FloatEmitter::Emit2RegMisc(bool Q, bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn)
|
void ARM64FloatEmitter::Emit2RegMisc(bool Q, bool U, u32 size, u32 opcode, ARM64Reg Rd, ARM64Reg Rn)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !IsSingle(Rd), "%s doesn't support singles!", __func__);
|
ASSERT_MSG(DYNA_REC, !IsSingle(Rd), "Singles are not supported!");
|
||||||
|
|
||||||
Write32((Q << 30) | (U << 29) | (0b1110001 << 21) | (size << 22) | (opcode << 12) | (1 << 11) |
|
Write32((Q << 30) | (U << 29) | (0b1110001 << 21) | (size << 22) | (opcode << 12) | (1 << 11) |
|
||||||
(DecodeReg(Rn) << 5) | DecodeReg(Rd));
|
(DecodeReg(Rn) << 5) | DecodeReg(Rd));
|
||||||
|
@ -2157,7 +2149,7 @@ void ARM64FloatEmitter::Emit2RegMisc(bool Q, bool U, u32 size, u32 opcode, ARM64
|
||||||
void ARM64FloatEmitter::EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode, bool S, u32 size,
|
void ARM64FloatEmitter::EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode, bool S, u32 size,
|
||||||
ARM64Reg Rt, ARM64Reg Rn)
|
ARM64Reg Rt, ARM64Reg Rn)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !IsSingle(Rt), "%s doesn't support singles!", __func__);
|
ASSERT_MSG(DYNA_REC, !IsSingle(Rt), "Singles are not supported!");
|
||||||
bool quad = IsQuad(Rt);
|
bool quad = IsQuad(Rt);
|
||||||
|
|
||||||
Write32((quad << 30) | (0b1101 << 24) | (L << 22) | (R << 21) | (opcode << 13) | (S << 12) |
|
Write32((quad << 30) | (0b1101 << 24) | (L << 22) | (R << 21) | (opcode << 13) | (S << 12) |
|
||||||
|
@ -2167,7 +2159,7 @@ void ARM64FloatEmitter::EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode,
|
||||||
void ARM64FloatEmitter::EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode, bool S, u32 size,
|
void ARM64FloatEmitter::EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode, bool S, u32 size,
|
||||||
ARM64Reg Rt, ARM64Reg Rn, ARM64Reg Rm)
|
ARM64Reg Rt, ARM64Reg Rn, ARM64Reg Rm)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !IsSingle(Rt), "%s doesn't support singles!", __func__);
|
ASSERT_MSG(DYNA_REC, !IsSingle(Rt), "Singles are not supported!");
|
||||||
bool quad = IsQuad(Rt);
|
bool quad = IsQuad(Rt);
|
||||||
|
|
||||||
Write32((quad << 30) | (0x1B << 23) | (L << 22) | (R << 21) | (DecodeReg(Rm) << 16) |
|
Write32((quad << 30) | (0x1B << 23) | (L << 22) | (R << 21) | (DecodeReg(Rm) << 16) |
|
||||||
|
@ -2176,7 +2168,7 @@ void ARM64FloatEmitter::EmitLoadStoreSingleStructure(bool L, bool R, u32 opcode,
|
||||||
|
|
||||||
void ARM64FloatEmitter::Emit1Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd, ARM64Reg Rn)
|
void ARM64FloatEmitter::Emit1Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd, ARM64Reg Rn)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !IsQuad(Rd), "%s doesn't support vector!", __func__);
|
ASSERT_MSG(DYNA_REC, !IsQuad(Rd), "Vector is not supported!");
|
||||||
|
|
||||||
Write32((M << 31) | (S << 29) | (0xF1 << 21) | (type << 22) | (opcode << 15) | (1 << 14) |
|
Write32((M << 31) | (S << 29) | (0xF1 << 21) | (type << 22) | (opcode << 15) | (1 << 14) |
|
||||||
(DecodeReg(Rn) << 5) | DecodeReg(Rd));
|
(DecodeReg(Rn) << 5) | DecodeReg(Rd));
|
||||||
|
@ -2185,7 +2177,7 @@ void ARM64FloatEmitter::Emit1Source(bool M, bool S, u32 type, u32 opcode, ARM64R
|
||||||
void ARM64FloatEmitter::EmitConversion(bool sf, bool S, u32 type, u32 rmode, u32 opcode,
|
void ARM64FloatEmitter::EmitConversion(bool sf, bool S, u32 type, u32 rmode, u32 opcode,
|
||||||
ARM64Reg Rd, ARM64Reg Rn)
|
ARM64Reg Rd, ARM64Reg Rn)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, Rn <= ARM64Reg::SP, "%s only supports GPR as source!", __func__);
|
ASSERT_MSG(DYNA_REC, Rn <= ARM64Reg::SP, "Only GPRs are supported as source!");
|
||||||
|
|
||||||
Write32((sf << 31) | (S << 29) | (0xF1 << 21) | (type << 22) | (rmode << 19) | (opcode << 16) |
|
Write32((sf << 31) | (S << 29) | (0xF1 << 21) | (type << 22) | (rmode << 19) | (opcode << 16) |
|
||||||
(DecodeReg(Rn) << 5) | DecodeReg(Rd));
|
(DecodeReg(Rn) << 5) | DecodeReg(Rd));
|
||||||
|
@ -2272,7 +2264,7 @@ void ARM64FloatEmitter::EmitConversion2(bool sf, bool S, bool direction, u32 typ
|
||||||
|
|
||||||
void ARM64FloatEmitter::EmitCompare(bool M, bool S, u32 op, u32 opcode2, ARM64Reg Rn, ARM64Reg Rm)
|
void ARM64FloatEmitter::EmitCompare(bool M, bool S, u32 op, u32 opcode2, ARM64Reg Rn, ARM64Reg Rm)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !IsQuad(Rn), "%s doesn't support vector!", __func__);
|
ASSERT_MSG(DYNA_REC, !IsQuad(Rn), "Vector is not supported!");
|
||||||
bool is_double = IsDouble(Rn);
|
bool is_double = IsDouble(Rn);
|
||||||
|
|
||||||
Write32((M << 31) | (S << 29) | (0xF1 << 21) | (is_double << 22) | (DecodeReg(Rm) << 16) |
|
Write32((M << 31) | (S << 29) | (0xF1 << 21) | (is_double << 22) | (DecodeReg(Rm) << 16) |
|
||||||
|
@ -2282,7 +2274,7 @@ void ARM64FloatEmitter::EmitCompare(bool M, bool S, u32 op, u32 opcode2, ARM64Re
|
||||||
void ARM64FloatEmitter::EmitCondSelect(bool M, bool S, CCFlags cond, ARM64Reg Rd, ARM64Reg Rn,
|
void ARM64FloatEmitter::EmitCondSelect(bool M, bool S, CCFlags cond, ARM64Reg Rd, ARM64Reg Rn,
|
||||||
ARM64Reg Rm)
|
ARM64Reg Rm)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !IsQuad(Rd), "%s doesn't support vector!", __func__);
|
ASSERT_MSG(DYNA_REC, !IsQuad(Rd), "Vector is not supported!");
|
||||||
bool is_double = IsDouble(Rd);
|
bool is_double = IsDouble(Rd);
|
||||||
|
|
||||||
Write32((M << 31) | (S << 29) | (0xF1 << 21) | (is_double << 22) | (DecodeReg(Rm) << 16) |
|
Write32((M << 31) | (S << 29) | (0xF1 << 21) | (is_double << 22) | (DecodeReg(Rm) << 16) |
|
||||||
|
@ -2291,7 +2283,7 @@ void ARM64FloatEmitter::EmitCondSelect(bool M, bool S, CCFlags cond, ARM64Reg Rd
|
||||||
|
|
||||||
void ARM64FloatEmitter::EmitPermute(u32 size, u32 op, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
|
void ARM64FloatEmitter::EmitPermute(u32 size, u32 op, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !IsSingle(Rd), "%s doesn't support singles!", __func__);
|
ASSERT_MSG(DYNA_REC, !IsSingle(Rd), "Singles are not supported!");
|
||||||
|
|
||||||
bool quad = IsQuad(Rd);
|
bool quad = IsQuad(Rd);
|
||||||
|
|
||||||
|
@ -2309,7 +2301,7 @@ void ARM64FloatEmitter::EmitPermute(u32 size, u32 op, ARM64Reg Rd, ARM64Reg Rn,
|
||||||
|
|
||||||
void ARM64FloatEmitter::EmitScalarImm(bool M, bool S, u32 type, u32 imm5, ARM64Reg Rd, u32 imm8)
|
void ARM64FloatEmitter::EmitScalarImm(bool M, bool S, u32 type, u32 imm5, ARM64Reg Rd, u32 imm8)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !IsQuad(Rd), "%s doesn't support vector!", __func__);
|
ASSERT_MSG(DYNA_REC, !IsQuad(Rd), "Vector is not supported!");
|
||||||
|
|
||||||
bool is_double = !IsSingle(Rd);
|
bool is_double = !IsSingle(Rd);
|
||||||
|
|
||||||
|
@ -2320,7 +2312,7 @@ void ARM64FloatEmitter::EmitScalarImm(bool M, bool S, u32 type, u32 imm5, ARM64R
|
||||||
void ARM64FloatEmitter::EmitShiftImm(bool Q, bool U, u32 immh, u32 immb, u32 opcode, ARM64Reg Rd,
|
void ARM64FloatEmitter::EmitShiftImm(bool Q, bool U, u32 immh, u32 immb, u32 opcode, ARM64Reg Rd,
|
||||||
ARM64Reg Rn)
|
ARM64Reg Rn)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, immh, "%s bad encoding! Can't have zero immh", __func__);
|
ASSERT_MSG(DYNA_REC, immh != 0, "Can't have zero immh");
|
||||||
|
|
||||||
Write32((Q << 30) | (U << 29) | (0xF << 24) | (immh << 19) | (immb << 16) | (opcode << 11) |
|
Write32((Q << 30) | (U << 29) | (0xF << 24) | (immh << 19) | (immb << 16) | (opcode << 11) |
|
||||||
(1 << 10) | (DecodeReg(Rn) << 5) | DecodeReg(Rd));
|
(1 << 10) | (DecodeReg(Rn) << 5) | DecodeReg(Rd));
|
||||||
|
@ -2370,7 +2362,7 @@ void ARM64FloatEmitter::EmitLoadStoreMultipleStructurePost(u32 size, bool L, u32
|
||||||
void ARM64FloatEmitter::EmitScalar1Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd,
|
void ARM64FloatEmitter::EmitScalar1Source(bool M, bool S, u32 type, u32 opcode, ARM64Reg Rd,
|
||||||
ARM64Reg Rn)
|
ARM64Reg Rn)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !IsQuad(Rd), "%s doesn't support vector!", __func__);
|
ASSERT_MSG(DYNA_REC, !IsQuad(Rd), "Vector is not supported!");
|
||||||
|
|
||||||
Write32((M << 31) | (S << 29) | (0xF1 << 21) | (type << 22) | (opcode << 15) | (1 << 14) |
|
Write32((M << 31) | (S << 29) | (0xF1 << 21) | (type << 22) | (opcode << 15) | (1 << 14) |
|
||||||
(DecodeReg(Rn) << 5) | DecodeReg(Rd));
|
(DecodeReg(Rn) << 5) | DecodeReg(Rd));
|
||||||
|
@ -2388,8 +2380,7 @@ void ARM64FloatEmitter::EmitVectorxElement(bool U, u32 size, bool L, u32 opcode,
|
||||||
|
|
||||||
void ARM64FloatEmitter::EmitLoadStoreUnscaled(u32 size, u32 op, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
|
void ARM64FloatEmitter::EmitLoadStoreUnscaled(u32 size, u32 op, ARM64Reg Rt, ARM64Reg Rn, s32 imm)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !(imm < -256 || imm > 255), "%s received too large offset: %d", __func__,
|
ASSERT_MSG(DYNA_REC, !(imm < -256 || imm > 255), "received too large offset: {}", imm);
|
||||||
imm);
|
|
||||||
|
|
||||||
Write32((size << 30) | (0xF << 26) | (op << 22) | ((imm & 0x1FF) << 12) | (DecodeReg(Rn) << 5) |
|
Write32((size << 30) | (0xF << 26) | (op << 22) | ((imm & 0x1FF) << 12) | (DecodeReg(Rn) << 5) |
|
||||||
DecodeReg(Rt));
|
DecodeReg(Rt));
|
||||||
|
@ -2413,30 +2404,30 @@ void ARM64FloatEmitter::EncodeLoadStorePair(u32 size, bool load, IndexType type,
|
||||||
type_encode = 0b011;
|
type_encode = 0b011;
|
||||||
break;
|
break;
|
||||||
case IndexType::Unsigned:
|
case IndexType::Unsigned:
|
||||||
ASSERT_MSG(DYNA_REC, false, "%s doesn't support IndexType::Unsigned!", __func__);
|
ASSERT_MSG(DYNA_REC, false, "IndexType::Unsigned is unsupported!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 128)
|
if (size == 128)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !(imm & 0xF), "%s received invalid offset 0x%x!", __func__, imm);
|
ASSERT_MSG(DYNA_REC, !(imm & 0xF), "Invalid offset {:#x}! (size {})", imm, size);
|
||||||
opc = 2;
|
opc = 2;
|
||||||
imm >>= 4;
|
imm >>= 4;
|
||||||
}
|
}
|
||||||
else if (size == 64)
|
else if (size == 64)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !(imm & 0x7), "%s received invalid offset 0x%x!", __func__, imm);
|
ASSERT_MSG(DYNA_REC, !(imm & 0x7), "Invalid offset {:#x}! (size {})", imm, size);
|
||||||
opc = 1;
|
opc = 1;
|
||||||
imm >>= 3;
|
imm >>= 3;
|
||||||
}
|
}
|
||||||
else if (size == 32)
|
else if (size == 32)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !(imm & 0x3), "%s received invalid offset 0x%x!", __func__, imm);
|
ASSERT_MSG(DYNA_REC, !(imm & 0x3), "Invalid offset {:#x}! (size {})", imm, size);
|
||||||
opc = 0;
|
opc = 0;
|
||||||
imm >>= 2;
|
imm >>= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, imm >= -64 && imm < 64, "imm too large for load/store pair!");
|
ASSERT_MSG(DYNA_REC, imm >= -64 && imm < 64, "imm too large for load/store pair! {}", imm);
|
||||||
|
|
||||||
Write32((opc << 30) | (0b1011 << 26) | (type_encode << 23) | (load << 22) | ((imm & 0x7F) << 15) |
|
Write32((opc << 30) | (0b1011 << 26) | (type_encode << 23) | (load << 22) | ((imm & 0x7F) << 15) |
|
||||||
(DecodeReg(Rt2) << 10) | (DecodeReg(Rn) << 5) | DecodeReg(Rt));
|
(DecodeReg(Rt2) << 10) | (DecodeReg(Rn) << 5) | DecodeReg(Rt));
|
||||||
|
@ -2445,7 +2436,7 @@ void ARM64FloatEmitter::EncodeLoadStorePair(u32 size, bool load, IndexType type,
|
||||||
void ARM64FloatEmitter::EncodeLoadStoreRegisterOffset(u32 size, bool load, ARM64Reg Rt, ARM64Reg Rn,
|
void ARM64FloatEmitter::EncodeLoadStoreRegisterOffset(u32 size, bool load, ARM64Reg Rt, ARM64Reg Rn,
|
||||||
ArithOption Rm)
|
ArithOption Rm)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, Rm.IsExtended(), "%s must contain an extended reg as Rm!", __func__);
|
ASSERT_MSG(DYNA_REC, Rm.IsExtended(), "Must contain an extended reg as Rm!");
|
||||||
|
|
||||||
u32 encoded_size = 0;
|
u32 encoded_size = 0;
|
||||||
u32 encoded_op = 0;
|
u32 encoded_op = 0;
|
||||||
|
@ -2803,8 +2794,8 @@ void ARM64FloatEmitter::ST1(u8 size, ARM64Reg Rt, u8 index, ARM64Reg Rn, ARM64Re
|
||||||
// Loadstore multiple structure
|
// Loadstore multiple structure
|
||||||
void ARM64FloatEmitter::LD1(u8 size, u8 count, ARM64Reg Rt, ARM64Reg Rn)
|
void ARM64FloatEmitter::LD1(u8 size, u8 count, ARM64Reg Rt, ARM64Reg Rn)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !(count == 0 || count > 4), "%s must have a count of 1 to 4 registers!",
|
ASSERT_MSG(DYNA_REC, !(count == 0 || count > 4), "Must have a count of 1 to 4 registers! ({})",
|
||||||
__func__);
|
count);
|
||||||
u32 opcode = 0;
|
u32 opcode = 0;
|
||||||
if (count == 1)
|
if (count == 1)
|
||||||
opcode = 0b111;
|
opcode = 0b111;
|
||||||
|
@ -2819,9 +2810,9 @@ void ARM64FloatEmitter::LD1(u8 size, u8 count, ARM64Reg Rt, ARM64Reg Rn)
|
||||||
void ARM64FloatEmitter::LD1(u8 size, u8 count, IndexType type, ARM64Reg Rt, ARM64Reg Rn,
|
void ARM64FloatEmitter::LD1(u8 size, u8 count, IndexType type, ARM64Reg Rt, ARM64Reg Rn,
|
||||||
ARM64Reg Rm)
|
ARM64Reg Rm)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !(count == 0 || count > 4), "%s must have a count of 1 to 4 registers!",
|
ASSERT_MSG(DYNA_REC, !(count == 0 || count > 4), "Must have a count of 1 to 4 registers! ({})",
|
||||||
__func__);
|
count);
|
||||||
ASSERT_MSG(DYNA_REC, type == IndexType::Post, "%s only supports post indexing!", __func__);
|
ASSERT_MSG(DYNA_REC, type == IndexType::Post, "Only post indexing is supported!");
|
||||||
|
|
||||||
u32 opcode = 0;
|
u32 opcode = 0;
|
||||||
if (count == 1)
|
if (count == 1)
|
||||||
|
@ -2836,8 +2827,8 @@ void ARM64FloatEmitter::LD1(u8 size, u8 count, IndexType type, ARM64Reg Rt, ARM6
|
||||||
}
|
}
|
||||||
void ARM64FloatEmitter::ST1(u8 size, u8 count, ARM64Reg Rt, ARM64Reg Rn)
|
void ARM64FloatEmitter::ST1(u8 size, u8 count, ARM64Reg Rt, ARM64Reg Rn)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !(count == 0 || count > 4), "%s must have a count of 1 to 4 registers!",
|
ASSERT_MSG(DYNA_REC, !(count == 0 || count > 4), "Must have a count of 1 to 4 registers! ({})",
|
||||||
__func__);
|
count);
|
||||||
u32 opcode = 0;
|
u32 opcode = 0;
|
||||||
if (count == 1)
|
if (count == 1)
|
||||||
opcode = 0b111;
|
opcode = 0b111;
|
||||||
|
@ -2852,9 +2843,9 @@ void ARM64FloatEmitter::ST1(u8 size, u8 count, ARM64Reg Rt, ARM64Reg Rn)
|
||||||
void ARM64FloatEmitter::ST1(u8 size, u8 count, IndexType type, ARM64Reg Rt, ARM64Reg Rn,
|
void ARM64FloatEmitter::ST1(u8 size, u8 count, IndexType type, ARM64Reg Rt, ARM64Reg Rn,
|
||||||
ARM64Reg Rm)
|
ARM64Reg Rm)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !(count == 0 || count > 4), "%s must have a count of 1 to 4 registers!",
|
ASSERT_MSG(DYNA_REC, !(count == 0 || count > 4), "Must have a count of 1 to 4 registers! ({})",
|
||||||
__func__);
|
count);
|
||||||
ASSERT_MSG(DYNA_REC, type == IndexType::Post, "%s only supports post indexing!", __func__);
|
ASSERT_MSG(DYNA_REC, type == IndexType::Post, "Only post indexing is supporte!");
|
||||||
|
|
||||||
u32 opcode = 0;
|
u32 opcode = 0;
|
||||||
if (count == 1)
|
if (count == 1)
|
||||||
|
@ -2954,7 +2945,7 @@ void ARM64FloatEmitter::FRSQRTE(ARM64Reg Rd, ARM64Reg Rn)
|
||||||
// Scalar - 2 Source
|
// Scalar - 2 Source
|
||||||
void ARM64FloatEmitter::ADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
|
void ARM64FloatEmitter::ADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, IsDouble(Rd), "%s only supports double registers!", __func__);
|
ASSERT_MSG(DYNA_REC, IsDouble(Rd), "Only double registers are supported!");
|
||||||
EmitScalarThreeSame(0, 3, 0b10000, Rd, Rn, Rm);
|
EmitScalarThreeSame(0, 3, 0b10000, Rd, Rn, Rm);
|
||||||
}
|
}
|
||||||
void ARM64FloatEmitter::FADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
|
void ARM64FloatEmitter::FADD(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm)
|
||||||
|
@ -3292,9 +3283,9 @@ void ARM64FloatEmitter::INS(u8 size, ARM64Reg Rd, u8 index1, ARM64Reg Rn, u8 ind
|
||||||
void ARM64FloatEmitter::UMOV(u8 size, ARM64Reg Rd, ARM64Reg Rn, u8 index)
|
void ARM64FloatEmitter::UMOV(u8 size, ARM64Reg Rd, ARM64Reg Rn, u8 index)
|
||||||
{
|
{
|
||||||
bool b64Bit = Is64Bit(Rd);
|
bool b64Bit = Is64Bit(Rd);
|
||||||
ASSERT_MSG(DYNA_REC, Rd < ARM64Reg::SP, "%s destination must be a GPR!", __func__);
|
ASSERT_MSG(DYNA_REC, Rd < ARM64Reg::SP, "Destination must be a GPR!");
|
||||||
ASSERT_MSG(DYNA_REC, !(b64Bit && size != 64),
|
ASSERT_MSG(DYNA_REC, !(b64Bit && size != 64),
|
||||||
"%s must have a size of 64 when destination is 64bit!", __func__);
|
"Must have a size of 64 when destination is 64bit!");
|
||||||
u32 imm5 = 0;
|
u32 imm5 = 0;
|
||||||
|
|
||||||
if (size == 8)
|
if (size == 8)
|
||||||
|
@ -3323,8 +3314,8 @@ void ARM64FloatEmitter::UMOV(u8 size, ARM64Reg Rd, ARM64Reg Rn, u8 index)
|
||||||
void ARM64FloatEmitter::SMOV(u8 size, ARM64Reg Rd, ARM64Reg Rn, u8 index)
|
void ARM64FloatEmitter::SMOV(u8 size, ARM64Reg Rd, ARM64Reg Rn, u8 index)
|
||||||
{
|
{
|
||||||
bool b64Bit = Is64Bit(Rd);
|
bool b64Bit = Is64Bit(Rd);
|
||||||
ASSERT_MSG(DYNA_REC, Rd < ARM64Reg::SP, "%s destination must be a GPR!", __func__);
|
ASSERT_MSG(DYNA_REC, Rd < ARM64Reg::SP, "Destination must be a GPR!");
|
||||||
ASSERT_MSG(DYNA_REC, size != 64, "%s doesn't support 64bit destination. Use UMOV!", __func__);
|
ASSERT_MSG(DYNA_REC, size != 64, "SMOV doesn't support 64bit destination. Use UMOV!");
|
||||||
u32 imm5 = 0;
|
u32 imm5 = 0;
|
||||||
|
|
||||||
if (size == 8)
|
if (size == 8)
|
||||||
|
@ -3562,8 +3553,8 @@ void ARM64FloatEmitter::UXTL2(u8 src_size, ARM64Reg Rd, ARM64Reg Rn)
|
||||||
|
|
||||||
void ARM64FloatEmitter::SSHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, bool upper)
|
void ARM64FloatEmitter::SSHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, bool upper)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, shift < src_size, "%s shift amount must less than the element size!",
|
ASSERT_MSG(DYNA_REC, shift < src_size, "Shift amount must less than the element size! {} {}",
|
||||||
__func__);
|
shift, src_size);
|
||||||
u32 immh = 0;
|
u32 immh = 0;
|
||||||
u32 immb = shift & 0xFFF;
|
u32 immb = shift & 0xFFF;
|
||||||
|
|
||||||
|
@ -3585,8 +3576,8 @@ void ARM64FloatEmitter::SSHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift,
|
||||||
|
|
||||||
void ARM64FloatEmitter::USHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, bool upper)
|
void ARM64FloatEmitter::USHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, bool upper)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, shift < src_size, "%s shift amount must less than the element size!",
|
ASSERT_MSG(DYNA_REC, shift < src_size, "Shift amount must less than the element size! {} {}",
|
||||||
__func__);
|
shift, src_size);
|
||||||
u32 immh = 0;
|
u32 immh = 0;
|
||||||
u32 immb = shift & 0xFFF;
|
u32 immb = shift & 0xFFF;
|
||||||
|
|
||||||
|
@ -3608,8 +3599,8 @@ void ARM64FloatEmitter::USHLL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift,
|
||||||
|
|
||||||
void ARM64FloatEmitter::SHRN(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, bool upper)
|
void ARM64FloatEmitter::SHRN(u8 dest_size, ARM64Reg Rd, ARM64Reg Rn, u32 shift, bool upper)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, shift < dest_size, "%s shift amount must less than the element size!",
|
ASSERT_MSG(DYNA_REC, shift < dest_size, "Shift amount must less than the element size! {} {}",
|
||||||
__func__);
|
shift, dest_size);
|
||||||
u32 immh = 0;
|
u32 immh = 0;
|
||||||
u32 immb = shift & 0xFFF;
|
u32 immb = shift & 0xFFF;
|
||||||
|
|
||||||
|
@ -3642,7 +3633,8 @@ void ARM64FloatEmitter::UXTL(u8 src_size, ARM64Reg Rd, ARM64Reg Rn, bool upper)
|
||||||
// vector x indexed element
|
// vector x indexed element
|
||||||
void ARM64FloatEmitter::FMUL(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u8 index)
|
void ARM64FloatEmitter::FMUL(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u8 index)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, size == 32 || size == 64, "%s only supports 32bit or 64bit size!", __func__);
|
ASSERT_MSG(DYNA_REC, size == 32 || size == 64, "Only 32bit or 64bit sizes are supported! {}",
|
||||||
|
size);
|
||||||
|
|
||||||
bool L = false;
|
bool L = false;
|
||||||
bool H = false;
|
bool H = false;
|
||||||
|
@ -3661,7 +3653,8 @@ void ARM64FloatEmitter::FMUL(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u8
|
||||||
|
|
||||||
void ARM64FloatEmitter::FMLA(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u8 index)
|
void ARM64FloatEmitter::FMLA(u8 size, ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, u8 index)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, size == 32 || size == 64, "%s only supports 32bit or 64bit size!", __func__);
|
ASSERT_MSG(DYNA_REC, size == 32 || size == 64, "Only 32bit or 64bit sizes are supported! {}",
|
||||||
|
size);
|
||||||
|
|
||||||
bool L = false;
|
bool L = false;
|
||||||
bool H = false;
|
bool H = false;
|
||||||
|
@ -3687,14 +3680,14 @@ void ARM64FloatEmitter::MOVI(u8 size, ARM64Reg Rd, u64 imm, u8 shift)
|
||||||
u8 abcdefgh = imm & 0xFF;
|
u8 abcdefgh = imm & 0xFF;
|
||||||
if (size == 8)
|
if (size == 8)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, shift == 0, "%s(size8) doesn't support shift!", __func__);
|
ASSERT_MSG(DYNA_REC, shift == 0, "size8 doesn't support shift! ({})", shift);
|
||||||
ASSERT_MSG(DYNA_REC, !(imm & ~0xFFULL), "%s(size8) only supports 8bit values!", __func__);
|
ASSERT_MSG(DYNA_REC, !(imm & ~0xFFULL), "size8 only supports 8bit values! ({})", imm);
|
||||||
}
|
}
|
||||||
else if (size == 16)
|
else if (size == 16)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, shift == 0 || shift == 8, "%s(size16) only supports shift of {0, 8}!",
|
ASSERT_MSG(DYNA_REC, shift == 0 || shift == 8, "size16 only supports shift of 0 or 8! ({})",
|
||||||
__func__);
|
shift);
|
||||||
ASSERT_MSG(DYNA_REC, !(imm & ~0xFFULL), "%s(size16) only supports 8bit values!", __func__);
|
ASSERT_MSG(DYNA_REC, !(imm & ~0xFFULL), "size16 only supports 8bit values! ({})", imm);
|
||||||
|
|
||||||
if (shift == 8)
|
if (shift == 8)
|
||||||
cmode |= 2;
|
cmode |= 2;
|
||||||
|
@ -3702,9 +3695,9 @@ void ARM64FloatEmitter::MOVI(u8 size, ARM64Reg Rd, u64 imm, u8 shift)
|
||||||
else if (size == 32)
|
else if (size == 32)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, shift == 0 || shift == 8 || shift == 16 || shift == 24,
|
ASSERT_MSG(DYNA_REC, shift == 0 || shift == 8 || shift == 16 || shift == 24,
|
||||||
"%s(size32) only supports shift of {0, 8, 16, 24}!", __func__);
|
"size32 only supports shift of 0, 8, 16, or 24! ({})", shift);
|
||||||
// XXX: Implement support for MOVI - shifting ones variant
|
// XXX: Implement support for MOVI - shifting ones variant
|
||||||
ASSERT_MSG(DYNA_REC, !(imm & ~0xFFULL), "%s(size32) only supports 8bit values!", __func__);
|
ASSERT_MSG(DYNA_REC, !(imm & ~0xFFULL), "size32 only supports 8bit values! ({})", imm);
|
||||||
switch (shift)
|
switch (shift)
|
||||||
{
|
{
|
||||||
case 8:
|
case 8:
|
||||||
|
@ -3722,7 +3715,7 @@ void ARM64FloatEmitter::MOVI(u8 size, ARM64Reg Rd, u64 imm, u8 shift)
|
||||||
}
|
}
|
||||||
else // 64
|
else // 64
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, shift == 0, "%s(size64) doesn't support shift!", __func__);
|
ASSERT_MSG(DYNA_REC, shift == 0, "size64 doesn't support shift! ({})", shift);
|
||||||
|
|
||||||
op = 1;
|
op = 1;
|
||||||
cmode = 0xE;
|
cmode = 0xE;
|
||||||
|
@ -3730,7 +3723,8 @@ void ARM64FloatEmitter::MOVI(u8 size, ARM64Reg Rd, u64 imm, u8 shift)
|
||||||
for (int i = 0; i < 8; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
u8 tmp = (imm >> (i << 3)) & 0xFF;
|
u8 tmp = (imm >> (i << 3)) & 0xFF;
|
||||||
ASSERT_MSG(DYNA_REC, tmp == 0xFF || tmp == 0, "%s(size64) Invalid immediate!", __func__);
|
ASSERT_MSG(DYNA_REC, tmp == 0xFF || tmp == 0, "size64 Invalid immediate! ({} -> {})", imm,
|
||||||
|
tmp);
|
||||||
if (tmp == 0xFF)
|
if (tmp == 0xFF)
|
||||||
abcdefgh |= (1 << i);
|
abcdefgh |= (1 << i);
|
||||||
}
|
}
|
||||||
|
@ -3744,8 +3738,8 @@ void ARM64FloatEmitter::ORR_BIC(u8 size, ARM64Reg Rd, u8 imm, u8 shift, u8 op)
|
||||||
u8 cmode = 1;
|
u8 cmode = 1;
|
||||||
if (size == 16)
|
if (size == 16)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, shift == 0 || shift == 8, "%s(size16) only supports shift of {0, 8}!",
|
ASSERT_MSG(DYNA_REC, shift == 0 || shift == 8, "size16 only supports shift of 0 or 8! {}",
|
||||||
__func__);
|
shift);
|
||||||
|
|
||||||
if (shift == 8)
|
if (shift == 8)
|
||||||
cmode |= 2;
|
cmode |= 2;
|
||||||
|
@ -3753,7 +3747,7 @@ void ARM64FloatEmitter::ORR_BIC(u8 size, ARM64Reg Rd, u8 imm, u8 shift, u8 op)
|
||||||
else if (size == 32)
|
else if (size == 32)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, shift == 0 || shift == 8 || shift == 16 || shift == 24,
|
ASSERT_MSG(DYNA_REC, shift == 0 || shift == 8 || shift == 16 || shift == 24,
|
||||||
"%s(size32) only supports shift of {0, 8, 16, 24}!", __func__);
|
"size32 only supports shift of 0, 8, 16, or 24! ({})", shift);
|
||||||
// XXX: Implement support for MOVI - shifting ones variant
|
// XXX: Implement support for MOVI - shifting ones variant
|
||||||
switch (shift)
|
switch (shift)
|
||||||
{
|
{
|
||||||
|
@ -3772,7 +3766,7 @@ void ARM64FloatEmitter::ORR_BIC(u8 size, ARM64Reg Rd, u8 imm, u8 shift, u8 op)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, false, "%s only supports size of {16, 32}!", __func__);
|
ASSERT_MSG(DYNA_REC, false, "Only size of 16 or 32 is supported! ({})", size);
|
||||||
}
|
}
|
||||||
EncodeModImm(Q, op, cmode, 0, Rd, imm);
|
EncodeModImm(Q, op, cmode, 0, Rd, imm);
|
||||||
}
|
}
|
||||||
|
@ -3964,8 +3958,8 @@ void ARM64XEmitter::ANDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, scratch != ARM64Reg::INVALID_REG,
|
ASSERT_MSG(DYNA_REC, scratch != ARM64Reg::INVALID_REG,
|
||||||
"ANDI2R - failed to construct logical immediate value from %08x, need scratch",
|
"ANDI2R - failed to construct logical immediate value from {:#10x}, need scratch",
|
||||||
(u32)imm);
|
imm);
|
||||||
MOVI2R(scratch, imm);
|
MOVI2R(scratch, imm);
|
||||||
AND(Rd, Rn, scratch);
|
AND(Rd, Rn, scratch);
|
||||||
}
|
}
|
||||||
|
@ -3980,8 +3974,8 @@ void ARM64XEmitter::ORRI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, scratch != ARM64Reg::INVALID_REG,
|
ASSERT_MSG(DYNA_REC, scratch != ARM64Reg::INVALID_REG,
|
||||||
"ORRI2R - failed to construct logical immediate value from %08x, need scratch",
|
"ORRI2R - failed to construct logical immediate value from {:#10x}, need scratch",
|
||||||
(u32)imm);
|
imm);
|
||||||
MOVI2R(scratch, imm);
|
MOVI2R(scratch, imm);
|
||||||
ORR(Rd, Rn, scratch);
|
ORR(Rd, Rn, scratch);
|
||||||
}
|
}
|
||||||
|
@ -3996,8 +3990,8 @@ void ARM64XEmitter::EORI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, scratch != ARM64Reg::INVALID_REG,
|
ASSERT_MSG(DYNA_REC, scratch != ARM64Reg::INVALID_REG,
|
||||||
"EORI2R - failed to construct logical immediate value from %08x, need scratch",
|
"EORI2R - failed to construct logical immediate value from {:#10x}, need scratch",
|
||||||
(u32)imm);
|
imm);
|
||||||
MOVI2R(scratch, imm);
|
MOVI2R(scratch, imm);
|
||||||
EOR(Rd, Rn, scratch);
|
EOR(Rd, Rn, scratch);
|
||||||
}
|
}
|
||||||
|
@ -4012,8 +4006,8 @@ void ARM64XEmitter::ANDSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, scratch != ARM64Reg::INVALID_REG,
|
ASSERT_MSG(DYNA_REC, scratch != ARM64Reg::INVALID_REG,
|
||||||
"ANDSI2R - failed to construct logical immediate value from %08x, need scratch",
|
"ANDSI2R - failed to construct logical immediate value from {:#10x}, need scratch",
|
||||||
(u32)imm);
|
imm);
|
||||||
MOVI2R(scratch, imm);
|
MOVI2R(scratch, imm);
|
||||||
ANDS(Rd, Rn, scratch);
|
ANDS(Rd, Rn, scratch);
|
||||||
}
|
}
|
||||||
|
@ -4085,8 +4079,8 @@ void ARM64XEmitter::ADDI2R_internal(ARM64Reg Rd, ARM64Reg Rn, u64 imm, bool nega
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, has_scratch,
|
ASSERT_MSG(DYNA_REC, has_scratch,
|
||||||
"ADDI2R - failed to construct arithmetic immediate value from %08x, need scratch",
|
"ADDI2R - failed to construct arithmetic immediate value from {:#10x}, need scratch",
|
||||||
(u32)imm);
|
imm);
|
||||||
|
|
||||||
negative ^= MOVI2R2(scratch, imm, imm_neg);
|
negative ^= MOVI2R2(scratch, imm, imm_neg);
|
||||||
if (!negative)
|
if (!negative)
|
||||||
|
@ -4218,7 +4212,7 @@ void ARM64FloatEmitter::MOVI2F(ARM64Reg Rd, float value, ARM64Reg scratch, bool
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, scratch != ARM64Reg::INVALID_REG,
|
ASSERT_MSG(DYNA_REC, scratch != ARM64Reg::INVALID_REG,
|
||||||
"Failed to find a way to generate FP immediate %f without scratch", value);
|
"Failed to find a way to generate FP immediate {} without scratch", value);
|
||||||
if (negate)
|
if (negate)
|
||||||
value = -value;
|
value = -value;
|
||||||
|
|
||||||
|
|
|
@ -13,31 +13,33 @@
|
||||||
{ \
|
{ \
|
||||||
if (!(_a_)) \
|
if (!(_a_)) \
|
||||||
{ \
|
{ \
|
||||||
if (!PanicYesNo(_fmt_, ##__VA_ARGS__)) \
|
if (!PanicYesNoFmtAssert(_t_, \
|
||||||
|
"An error occurred.\n\n" _fmt_ "\n\n" \
|
||||||
|
" Condition: {}\n File: {}\n Line: {}\n Function: {}\n\n" \
|
||||||
|
"Ignore and continue?", \
|
||||||
|
##__VA_ARGS__, #_a_, __FILE__, __LINE__, __func__)) \
|
||||||
Crash(); \
|
Crash(); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define DEBUG_ASSERT_MSG(_t_, _a_, _msg_, ...) \
|
#define DEBUG_ASSERT_MSG(_t_, _a_, _fmt_, ...) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
if constexpr (Common::Log::MAX_LOGLEVEL >= Common::Log::LogLevel::LDEBUG) \
|
if constexpr (Common::Log::MAX_LOGLEVEL >= Common::Log::LogLevel::LDEBUG) \
|
||||||
{ \
|
ASSERT_MSG(_t_, _a_, _fmt_, ##__VA_ARGS__); \
|
||||||
if (!(_a_)) \
|
|
||||||
{ \
|
|
||||||
ERROR_LOG(_t_, _msg_, ##__VA_ARGS__); \
|
|
||||||
if (!PanicYesNo(_msg_, ##__VA_ARGS__)) \
|
|
||||||
Crash(); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define ASSERT(_a_) \
|
#define ASSERT(_a_) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
ASSERT_MSG(MASTER_LOG, _a_, \
|
if (!(_a_)) \
|
||||||
_trans("An error occurred.\n\n Line: %d\n File: %s\n\nIgnore and continue?"), \
|
{ \
|
||||||
__LINE__, __FILE__); \
|
if (!PanicYesNoFmt("An error occurred.\n\n" \
|
||||||
|
" Condition: {}\n File: {}\n Line: {}\n Function: {}\n\n" \
|
||||||
|
"Ignore and continue?", \
|
||||||
|
#_a_, __FILE__, __LINE__, __func__)) \
|
||||||
|
Crash(); \
|
||||||
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define DEBUG_ASSERT(_a_) \
|
#define DEBUG_ASSERT(_a_) \
|
||||||
|
|
|
@ -286,6 +286,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
target_link_libraries(common PUBLIC dl rt)
|
target_link_libraries(common PUBLIC dl rt)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
target_sources(common PUBLIC HRWrap.h HRWrap.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(USE_UPNP)
|
if(USE_UPNP)
|
||||||
target_link_libraries(common PRIVATE Miniupnpc::miniupnpc)
|
target_link_libraries(common PRIVATE Miniupnpc::miniupnpc)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/EnumMap.h"
|
#include "Common/EnumMap.h"
|
||||||
|
@ -332,8 +334,8 @@ private:
|
||||||
|
|
||||||
case MODE_VERIFY:
|
case MODE_VERIFY:
|
||||||
DEBUG_ASSERT_MSG(COMMON, !memcmp(data, *ptr, size),
|
DEBUG_ASSERT_MSG(COMMON, !memcmp(data, *ptr, size),
|
||||||
"Savestate verification failure: buf %p != %p (size %u).\n", data, *ptr,
|
"Savestate verification failure: buf {} != {} (size {}).\n", fmt::ptr(data),
|
||||||
size);
|
fmt::ptr(*ptr), size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#define CHECK_HEAP_INTEGRITY() \
|
#define CHECK_HEAP_INTEGRITY() \
|
||||||
{ \
|
{ \
|
||||||
if (!_CrtCheckMemory()) \
|
if (!_CrtCheckMemory()) \
|
||||||
PanicAlert("memory corruption detected. see log."); \
|
PanicAlertFmt("memory corruption detected. see log."); \
|
||||||
}
|
}
|
||||||
// If you want to see how much a pain in the ass singletons are, for example:
|
// If you want to see how much a pain in the ass singletons are, for example:
|
||||||
// {614} normal block at 0x030C5310, 188 bytes long.
|
// {614} normal block at 0x030C5310, 188 bytes long.
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright 2021 Dolphin Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "HRWrap.h"
|
||||||
|
|
||||||
|
#include <comdef.h>
|
||||||
|
#include "Common/StringUtil.h"
|
||||||
|
|
||||||
|
namespace Common
|
||||||
|
{
|
||||||
|
std::string GetHResultMessage(HRESULT hr)
|
||||||
|
{
|
||||||
|
// See https://stackoverflow.com/a/7008111
|
||||||
|
_com_error err(hr);
|
||||||
|
return TStrToUTF8(err.ErrorMessage());
|
||||||
|
}
|
||||||
|
} // namespace Common
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Copyright 2021 Dolphin Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <string>
|
||||||
|
#include <winerror.h>
|
||||||
|
|
||||||
|
namespace Common
|
||||||
|
{
|
||||||
|
std::string GetHResultMessage(HRESULT hr);
|
||||||
|
|
||||||
|
// Wrapper for HRESULT to be used with fmt. Note that we can't create a fmt::formatter directly
|
||||||
|
// for HRESULT as HRESULT is simply a typedef on long and not a distinct type.
|
||||||
|
struct HRWrap
|
||||||
|
{
|
||||||
|
constexpr explicit HRWrap(HRESULT hr) : m_hr(hr) {}
|
||||||
|
const HRESULT m_hr;
|
||||||
|
};
|
||||||
|
} // namespace Common
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct fmt::formatter<Common::HRWrap>
|
||||||
|
{
|
||||||
|
constexpr auto parse(fmt::format_parse_context& ctx) { return ctx.begin(); }
|
||||||
|
template <typename FormatContext>
|
||||||
|
auto format(const Common::HRWrap& hr, FormatContext& ctx)
|
||||||
|
{
|
||||||
|
return fmt::format_to(ctx.out(), "{} ({:#010x})", Common::GetHResultMessage(hr.m_hr),
|
||||||
|
static_cast<u32>(hr.m_hr));
|
||||||
|
}
|
||||||
|
};
|
|
@ -80,7 +80,7 @@ bool SavePNG(const std::string& path, const u8* input, ImageByteFormat format, u
|
||||||
byte_per_pixel = 4;
|
byte_per_pixel = 4;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ASSERT_MSG(FRAMEDUMP, false, "Invalid format %d", static_cast<int>(format));
|
ASSERT_MSG(FRAMEDUMP, false, "Invalid format {}", format);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,10 +106,14 @@ std::string GetStringT(const char* string)
|
||||||
return s_str_translator(string);
|
return s_str_translator(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ShowMessageAlert(std::string_view text, bool yes_no, MsgType style)
|
static bool ShowMessageAlert(std::string_view text, bool yes_no, Common::Log::LogType log_type,
|
||||||
|
MsgType style, const char* file, int line)
|
||||||
{
|
{
|
||||||
const char* caption = GetCaption(style);
|
const char* caption = GetCaption(style);
|
||||||
ERROR_LOG_FMT(MASTER_LOG, "{}: {}", caption, text);
|
// Directly call GenericLogFmt rather than using the normal log macros so that we can use the
|
||||||
|
// caller's line file and line number
|
||||||
|
Common::Log::GenericLogFmt<2>(Common::Log::LogLevel::LERROR, log_type, file, line,
|
||||||
|
FMT_STRING("{}: {}"), caption, text);
|
||||||
|
|
||||||
// Panic alerts.
|
// Panic alerts.
|
||||||
if (style == MsgType::Warning && s_abort_on_panic_alert)
|
if (style == MsgType::Warning && s_abort_on_panic_alert)
|
||||||
|
@ -127,27 +131,13 @@ static bool ShowMessageAlert(std::string_view text, bool yes_no, MsgType style)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the first stop for gui alerts where the log is updated and the
|
|
||||||
// correct window is shown, but only for legacy printf-style messages
|
|
||||||
bool MsgAlert(bool yes_no, MsgType style, const char* format, ...)
|
|
||||||
{
|
|
||||||
char buffer[2048];
|
|
||||||
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
CharArrayFromFormatV(buffer, sizeof(buffer) - 1, s_str_translator(format).c_str(), args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
return ShowMessageAlert(buffer, yes_no, style);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is the first stop for gui alerts where the log is updated and the
|
// This is the first stop for gui alerts where the log is updated and the
|
||||||
// correct window is shown, when using fmt
|
// correct window is shown, when using fmt
|
||||||
bool MsgAlertFmtImpl(bool yes_no, MsgType style, fmt::string_view format,
|
bool MsgAlertFmtImpl(bool yes_no, MsgType style, Common::Log::LogType log_type, const char* file,
|
||||||
const fmt::format_args& args)
|
int line, fmt::string_view format, const fmt::format_args& args)
|
||||||
{
|
{
|
||||||
const auto message = fmt::vformat(format, args);
|
const auto message = fmt::vformat(format, args);
|
||||||
|
|
||||||
return ShowMessageAlert(message, yes_no, style);
|
return ShowMessageAlert(message, yes_no, log_type, style, file, line);
|
||||||
}
|
}
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "Common/FormatUtil.h"
|
#include "Common/FormatUtil.h"
|
||||||
|
#include "Common/Logging/Log.h"
|
||||||
|
|
||||||
namespace Common
|
namespace Common
|
||||||
{
|
{
|
||||||
|
@ -30,22 +31,39 @@ void RegisterStringTranslator(StringTranslator translator);
|
||||||
|
|
||||||
std::string GetStringT(const char* string);
|
std::string GetStringT(const char* string);
|
||||||
|
|
||||||
bool MsgAlert(bool yes_no, MsgType style, const char* format, ...)
|
bool MsgAlertFmtImpl(bool yes_no, MsgType style, Common::Log::LogType log_type, const char* file,
|
||||||
#ifdef __GNUC__
|
int line, fmt::string_view format, const fmt::format_args& args);
|
||||||
__attribute__((format(printf, 3, 4)))
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
|
|
||||||
bool MsgAlertFmtImpl(bool yes_no, MsgType style, fmt::string_view format,
|
|
||||||
const fmt::format_args& args);
|
|
||||||
|
|
||||||
template <std::size_t NumFields, typename S, typename... Args>
|
template <std::size_t NumFields, typename S, typename... Args>
|
||||||
bool MsgAlertFmt(bool yes_no, MsgType style, const S& format, const Args&... args)
|
bool MsgAlertFmt(bool yes_no, MsgType style, Common::Log::LogType log_type, const char* file,
|
||||||
|
int line, const S& format, const Args&... args)
|
||||||
{
|
{
|
||||||
static_assert(NumFields == sizeof...(args),
|
static_assert(NumFields == sizeof...(args),
|
||||||
"Unexpected number of replacement fields in format string; did you pass too few or "
|
"Unexpected number of replacement fields in format string; did you pass too few or "
|
||||||
"too many arguments?");
|
"too many arguments?");
|
||||||
return MsgAlertFmtImpl(yes_no, style, format, fmt::make_args_checked<Args...>(format, args...));
|
static_assert(fmt::is_compile_string<S>::value);
|
||||||
|
return MsgAlertFmtImpl(yes_no, style, log_type, file, line, format,
|
||||||
|
fmt::make_args_checked<Args...>(format, args...));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t NumFields, bool has_non_positional_args, typename S, typename... Args>
|
||||||
|
bool MsgAlertFmtT(bool yes_no, MsgType style, Common::Log::LogType log_type, const char* file,
|
||||||
|
int line, const S& format, fmt::string_view translated_format,
|
||||||
|
const Args&... args)
|
||||||
|
{
|
||||||
|
static_assert(!has_non_positional_args,
|
||||||
|
"Translatable strings must use positional arguments (e.g. {0} instead of {})");
|
||||||
|
static_assert(NumFields == sizeof...(args),
|
||||||
|
"Unexpected number of replacement fields in format string; did you pass too few or "
|
||||||
|
"too many arguments?");
|
||||||
|
static_assert(fmt::is_compile_string<S>::value);
|
||||||
|
// It's only possible for us to compile-time check the English-language string.
|
||||||
|
// make_args_checked uses static_asserts to verify that a string is formattable with the given
|
||||||
|
// arguments. But it can't do that if the string varies at runtime, so we can't check
|
||||||
|
// translations. Still, verifying that the English string is correct will help ensure that
|
||||||
|
// translations use valid strings.
|
||||||
|
auto arg_list = fmt::make_args_checked<Args...>(format, args...);
|
||||||
|
return MsgAlertFmtImpl(yes_no, style, log_type, file, line, translated_format, arg_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetEnableAlert(bool enable);
|
void SetEnableAlert(bool enable);
|
||||||
|
@ -59,86 +77,50 @@ std::string FmtFormatT(const char* string, Args&&... args)
|
||||||
}
|
}
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
|
||||||
// Deprecated variants of the alert macros. See the fmt variants down below.
|
|
||||||
|
|
||||||
#define SuccessAlert(format, ...) \
|
|
||||||
Common::MsgAlert(false, Common::MsgType::Information, format, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
#define PanicAlert(format, ...) \
|
|
||||||
Common::MsgAlert(false, Common::MsgType::Warning, format, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
#define PanicYesNo(format, ...) \
|
|
||||||
Common::MsgAlert(true, Common::MsgType::Warning, format, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
#define AskYesNo(format, ...) \
|
|
||||||
Common::MsgAlert(true, Common::MsgType::Question, format, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
#define CriticalAlert(format, ...) \
|
|
||||||
Common::MsgAlert(false, Common::MsgType::Critical, format, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
// Use these macros (that do the same thing) if the message should be translated.
|
|
||||||
#define SuccessAlertT(format, ...) \
|
|
||||||
Common::MsgAlert(false, Common::MsgType::Information, format, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
#define PanicAlertT(format, ...) \
|
|
||||||
Common::MsgAlert(false, Common::MsgType::Warning, format, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
#define PanicYesNoT(format, ...) \
|
|
||||||
Common::MsgAlert(true, Common::MsgType::Warning, format, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
#define AskYesNoT(format, ...) \
|
|
||||||
Common::MsgAlert(true, Common::MsgType::Question, format, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
#define CriticalAlertT(format, ...) \
|
|
||||||
Common::MsgAlert(false, Common::MsgType::Critical, format, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
// Fmt-capable variants of the macros
|
// Fmt-capable variants of the macros
|
||||||
|
|
||||||
#define GenericAlertFmt(yes_no, style, format, ...) \
|
#define GenericAlertFmt(yes_no, style, log_type, format, ...) \
|
||||||
[&] { \
|
Common::MsgAlertFmt<Common::CountFmtReplacementFields(format)>( \
|
||||||
/* Use a macro-like name to avoid shadowing warnings */ \
|
yes_no, style, Common::Log::LogType::log_type, __FILE__, __LINE__, FMT_STRING(format), \
|
||||||
constexpr auto GENERIC_ALERT_FMT_N = Common::CountFmtReplacementFields(format); \
|
##__VA_ARGS__)
|
||||||
return Common::MsgAlertFmt<GENERIC_ALERT_FMT_N>(yes_no, style, FMT_STRING(format), \
|
|
||||||
##__VA_ARGS__); \
|
|
||||||
}()
|
|
||||||
|
|
||||||
#define GenericAlertFmtT(yes_no, style, format, ...) \
|
#define GenericAlertFmtT(yes_no, style, log_type, format, ...) \
|
||||||
[&] { \
|
Common::MsgAlertFmtT<Common::CountFmtReplacementFields(format), \
|
||||||
static_assert(!Common::ContainsNonPositionalArguments(format), \
|
Common::ContainsNonPositionalArguments(format)>( \
|
||||||
"Translatable strings must use positional arguments (e.g. {0} instead of {})"); \
|
yes_no, style, Common::Log::LogType::log_type, __FILE__, __LINE__, FMT_STRING(format), \
|
||||||
/* Use a macro-like name to avoid shadowing warnings */ \
|
Common::GetStringT(format), ##__VA_ARGS__)
|
||||||
constexpr auto GENERIC_ALERT_FMT_N = Common::CountFmtReplacementFields(format); \
|
|
||||||
return Common::MsgAlertFmt<GENERIC_ALERT_FMT_N>(yes_no, style, FMT_STRING(format), \
|
|
||||||
##__VA_ARGS__); \
|
|
||||||
}()
|
|
||||||
|
|
||||||
#define SuccessAlertFmt(format, ...) \
|
#define SuccessAlertFmt(format, ...) \
|
||||||
GenericAlertFmt(false, Common::MsgType::Information, format, ##__VA_ARGS__)
|
GenericAlertFmt(false, Common::MsgType::Information, MASTER_LOG, format, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define PanicAlertFmt(format, ...) \
|
#define PanicAlertFmt(format, ...) \
|
||||||
GenericAlertFmt(false, Common::MsgType::Warning, format, ##__VA_ARGS__)
|
GenericAlertFmt(false, Common::MsgType::Warning, MASTER_LOG, format, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define PanicYesNoFmt(format, ...) \
|
#define PanicYesNoFmt(format, ...) \
|
||||||
GenericAlertFmt(true, Common::MsgType::Warning, format, ##__VA_ARGS__)
|
GenericAlertFmt(true, Common::MsgType::Warning, MASTER_LOG, format, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define AskYesNoFmt(format, ...) \
|
#define AskYesNoFmt(format, ...) \
|
||||||
GenericAlertFmt(true, Common::MsgType::Question, format, ##__VA_ARGS__)
|
GenericAlertFmt(true, Common::MsgType::Question, MASTER_LOG, format, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define CriticalAlertFmt(format, ...) \
|
#define CriticalAlertFmt(format, ...) \
|
||||||
GenericAlertFmt(false, Common::MsgType::Critical, format, ##__VA_ARGS__)
|
GenericAlertFmt(false, Common::MsgType::Critical, MASTER_LOG, format, ##__VA_ARGS__)
|
||||||
|
|
||||||
// Use these macros (that do the same thing) if the message should be translated.
|
// Use these macros (that do the same thing) if the message should be translated.
|
||||||
#define SuccessAlertFmtT(format, ...) \
|
#define SuccessAlertFmtT(format, ...) \
|
||||||
GenericAlertFmtT(false, Common::MsgType::Information, format, ##__VA_ARGS__)
|
GenericAlertFmtT(false, Common::MsgType::Information, MASTER_LOG, format, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define PanicAlertFmtT(format, ...) \
|
#define PanicAlertFmtT(format, ...) \
|
||||||
GenericAlertFmtT(false, Common::MsgType::Warning, format, ##__VA_ARGS__)
|
GenericAlertFmtT(false, Common::MsgType::Warning, MASTER_LOG, format, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define PanicYesNoFmtT(format, ...) \
|
#define PanicYesNoFmtT(format, ...) \
|
||||||
GenericAlertFmtT(true, Common::MsgType::Warning, format, ##__VA_ARGS__)
|
GenericAlertFmtT(true, Common::MsgType::Warning, MASTER_LOG, format, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define AskYesNoFmtT(format, ...) \
|
#define AskYesNoFmtT(format, ...) \
|
||||||
GenericAlertFmtT(true, Common::MsgType::Question, format, ##__VA_ARGS__)
|
GenericAlertFmtT(true, Common::MsgType::Question, MASTER_LOG, format, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define CriticalAlertFmtT(format, ...) \
|
#define CriticalAlertFmtT(format, ...) \
|
||||||
GenericAlertFmtT(false, Common::MsgType::Critical, format, ##__VA_ARGS__)
|
GenericAlertFmtT(false, Common::MsgType::Critical, MASTER_LOG, format, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
// Variant that takes a log type, used by the assert macros
|
||||||
|
#define PanicYesNoFmtAssert(log_type, format, ...) \
|
||||||
|
GenericAlertFmt(true, Common::MsgType::Warning, log_type, format, ##__VA_ARGS__)
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include "Common/x64Emitter.h"
|
#include "Common/x64Emitter.h"
|
||||||
|
|
||||||
#include <cinttypes>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "Common/CPUDetect.h"
|
#include "Common/CPUDetect.h"
|
||||||
|
@ -310,7 +309,7 @@ void OpArg::WriteRest(XEmitter* emit, int extraBytes, X64Reg _operandReg,
|
||||||
s64 distance = (s64)offset - (s64)ripAddr;
|
s64 distance = (s64)offset - (s64)ripAddr;
|
||||||
ASSERT_MSG(DYNA_REC,
|
ASSERT_MSG(DYNA_REC,
|
||||||
(distance < 0x80000000LL && distance >= -0x80000000LL) || !warn_64bit_offset,
|
(distance < 0x80000000LL && distance >= -0x80000000LL) || !warn_64bit_offset,
|
||||||
"WriteRest: op out of range (0x%" PRIx64 " uses 0x%" PRIx64 ")", ripAddr, offset);
|
"WriteRest: op out of range ({:#x} uses {:#x})", ripAddr, offset);
|
||||||
s32 offs = (s32)distance;
|
s32 offs = (s32)distance;
|
||||||
emit->Write32((u32)offs);
|
emit->Write32((u32)offs);
|
||||||
return;
|
return;
|
||||||
|
@ -440,7 +439,7 @@ void XEmitter::JMP(const u8* addr, bool force5Bytes)
|
||||||
{
|
{
|
||||||
s64 distance = (s64)(fn - ((u64)code + 2));
|
s64 distance = (s64)(fn - ((u64)code + 2));
|
||||||
ASSERT_MSG(DYNA_REC, distance >= -0x80 && distance < 0x80,
|
ASSERT_MSG(DYNA_REC, distance >= -0x80 && distance < 0x80,
|
||||||
"Jump target too far away, needs force5Bytes = true");
|
"Jump target too far away ({}), needs force5Bytes = true", distance);
|
||||||
// 8 bits will do
|
// 8 bits will do
|
||||||
Write8(0xEB);
|
Write8(0xEB);
|
||||||
Write8((u8)(s8)distance);
|
Write8((u8)(s8)distance);
|
||||||
|
@ -450,7 +449,7 @@ void XEmitter::JMP(const u8* addr, bool force5Bytes)
|
||||||
s64 distance = (s64)(fn - ((u64)code + 5));
|
s64 distance = (s64)(fn - ((u64)code + 5));
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, distance >= -0x80000000LL && distance < 0x80000000LL,
|
ASSERT_MSG(DYNA_REC, distance >= -0x80000000LL && distance < 0x80000000LL,
|
||||||
"Jump target too far away, needs indirect register");
|
"Jump target too far away ({}), needs indirect register", distance);
|
||||||
Write8(0xE9);
|
Write8(0xE9);
|
||||||
Write32((u32)(s32)distance);
|
Write32((u32)(s32)distance);
|
||||||
}
|
}
|
||||||
|
@ -489,7 +488,7 @@ void XEmitter::CALL(const void* fnptr)
|
||||||
{
|
{
|
||||||
u64 distance = u64(fnptr) - (u64(code) + 5);
|
u64 distance = u64(fnptr) - (u64(code) + 5);
|
||||||
ASSERT_MSG(DYNA_REC, distance < 0x0000000080000000ULL || distance >= 0xFFFFFFFF80000000ULL,
|
ASSERT_MSG(DYNA_REC, distance < 0x0000000080000000ULL || distance >= 0xFFFFFFFF80000000ULL,
|
||||||
"CALL out of range (%p calls %p)", code, fnptr);
|
"CALL out of range ({} calls {})", fmt::ptr(code), fmt::ptr(fnptr));
|
||||||
Write8(0xE8);
|
Write8(0xE8);
|
||||||
Write32(u32(distance));
|
Write32(u32(distance));
|
||||||
}
|
}
|
||||||
|
@ -572,7 +571,7 @@ void XEmitter::J_CC(CCFlags conditionCode, const u8* addr)
|
||||||
{
|
{
|
||||||
distance = (s64)(fn - ((u64)code + 6));
|
distance = (s64)(fn - ((u64)code + 6));
|
||||||
ASSERT_MSG(DYNA_REC, distance >= -0x80000000LL && distance < 0x80000000LL,
|
ASSERT_MSG(DYNA_REC, distance >= -0x80000000LL && distance < 0x80000000LL,
|
||||||
"Jump target too far away, needs indirect register");
|
"Jump target too far away ({}), needs indirect register", distance);
|
||||||
Write8(0x0F);
|
Write8(0x0F);
|
||||||
Write8(0x80 + conditionCode);
|
Write8(0x80 + conditionCode);
|
||||||
Write32((u32)(s32)distance);
|
Write32((u32)(s32)distance);
|
||||||
|
@ -593,14 +592,14 @@ void XEmitter::SetJumpTarget(const FixupBranch& branch)
|
||||||
{
|
{
|
||||||
s64 distance = (s64)(code - branch.ptr);
|
s64 distance = (s64)(code - branch.ptr);
|
||||||
ASSERT_MSG(DYNA_REC, distance >= -0x80 && distance < 0x80,
|
ASSERT_MSG(DYNA_REC, distance >= -0x80 && distance < 0x80,
|
||||||
"Jump target too far away, needs force5Bytes = true");
|
"Jump target too far away ({}), needs force5Bytes = true", distance);
|
||||||
branch.ptr[-1] = (u8)(s8)distance;
|
branch.ptr[-1] = (u8)(s8)distance;
|
||||||
}
|
}
|
||||||
else if (branch.type == FixupBranch::Type::Branch32Bit)
|
else if (branch.type == FixupBranch::Type::Branch32Bit)
|
||||||
{
|
{
|
||||||
s64 distance = (s64)(code - branch.ptr);
|
s64 distance = (s64)(code - branch.ptr);
|
||||||
ASSERT_MSG(DYNA_REC, distance >= -0x80000000LL && distance < 0x80000000LL,
|
ASSERT_MSG(DYNA_REC, distance >= -0x80000000LL && distance < 0x80000000LL,
|
||||||
"Jump target too far away, needs indirect register");
|
"Jump target too far away ({}), needs indirect register", distance);
|
||||||
|
|
||||||
s32 valid_distance = static_cast<s32>(distance);
|
s32 valid_distance = static_cast<s32>(distance);
|
||||||
std::memcpy(&branch.ptr[-4], &valid_distance, sizeof(s32));
|
std::memcpy(&branch.ptr[-4], &valid_distance, sizeof(s32));
|
||||||
|
@ -1535,7 +1534,7 @@ void OpArg::WriteNormalOp(XEmitter* emit, bool toRM, NormalOp op, const OpArg& o
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, 0, "WriteNormalOp - Unhandled case %d %d", operand.scale, bits);
|
ASSERT_MSG(DYNA_REC, 0, "WriteNormalOp - Unhandled case {} {}", operand.scale, bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
// pass extension in REG of ModRM
|
// pass extension in REG of ModRM
|
||||||
|
|
|
@ -476,13 +476,14 @@ void DecryptARCode(std::vector<std::string> vCodes, std::vector<AREntry>* ops)
|
||||||
else if (!batchdecrypt(uCodes.data(), (u16)vCodes.size() << 1))
|
else if (!batchdecrypt(uCodes.data(), (u16)vCodes.size() << 1))
|
||||||
{
|
{
|
||||||
// Commented out since we just send the code anyways and hope for the best XD
|
// Commented out since we just send the code anyways and hope for the best XD
|
||||||
// PanicAlert("Action Replay Code Decryption Error:\nCRC Check Failed\n\n"
|
// PanicAlertFmt("Action Replay Code Decryption Error:\nCRC Check Failed\n\n"
|
||||||
// "First Code in Block(should be verification code):\n%s", vCodes[0].c_str());
|
// "First Code in Block (should be verification code):\n{}",
|
||||||
|
// vCodes[0]);
|
||||||
|
|
||||||
for (size_t i = 0; i < (vCodes.size() << 1); i += 2)
|
for (size_t i = 0; i < (vCodes.size() << 1); i += 2)
|
||||||
{
|
{
|
||||||
ops->emplace_back(uCodes[i], uCodes[i + 1]);
|
ops->emplace_back(uCodes[i], uCodes[i + 1]);
|
||||||
// PanicAlert("Decrypted AR Code without verification code:\n%08X %08X", uCodes[i],
|
// PanicAlertFmt("Decrypted AR Code without verification code:\n{:08X} {:08X}", uCodes[i],
|
||||||
// uCodes[i + 1]);
|
// uCodes[i + 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -492,7 +493,7 @@ void DecryptARCode(std::vector<std::string> vCodes, std::vector<AREntry>* ops)
|
||||||
for (size_t i = 2; i < (vCodes.size() << 1); i += 2)
|
for (size_t i = 2; i < (vCodes.size() << 1); i += 2)
|
||||||
{
|
{
|
||||||
ops->emplace_back(uCodes[i], uCodes[i + 1]);
|
ops->emplace_back(uCodes[i], uCodes[i + 1]);
|
||||||
// PanicAlert("Decrypted AR Code:\n%08X %08X", uCodes[i], uCodes[i+1]);
|
// PanicAlertFmt("Decrypted AR Code:\n{:08X} {:08X}", uCodes[i], uCodes[i+1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cinttypes>
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
|
@ -108,9 +108,9 @@ EventType* RegisterEvent(const std::string& name, TimedCallback callback)
|
||||||
// check for existing type with same name.
|
// check for existing type with same name.
|
||||||
// we want event type names to remain unique so that we can use them for serialization.
|
// we want event type names to remain unique so that we can use them for serialization.
|
||||||
ASSERT_MSG(POWERPC, s_event_types.find(name) == s_event_types.end(),
|
ASSERT_MSG(POWERPC, s_event_types.find(name) == s_event_types.end(),
|
||||||
"CoreTiming Event \"%s\" is already registered. Events should only be registered "
|
"CoreTiming Event \"{}\" is already registered. Events should only be registered "
|
||||||
"during Init to avoid breaking save states.",
|
"during Init to avoid breaking save states.",
|
||||||
name.c_str());
|
name);
|
||||||
|
|
||||||
auto info = s_event_types.emplace(name, EventType{callback, nullptr});
|
auto info = s_event_types.emplace(name, EventType{callback, nullptr});
|
||||||
EventType* event_type = &info.first->second;
|
EventType* event_type = &info.first->second;
|
||||||
|
@ -257,7 +257,7 @@ void ScheduleEvent(s64 cycles_into_future, EventType* event_type, u64 userdata,
|
||||||
{
|
{
|
||||||
from_cpu_thread = from == FromThread::CPU;
|
from_cpu_thread = from == FromThread::CPU;
|
||||||
ASSERT_MSG(POWERPC, from_cpu_thread == Core::IsCPUThread(),
|
ASSERT_MSG(POWERPC, from_cpu_thread == Core::IsCPUThread(),
|
||||||
"A \"%s\" event was scheduled from the wrong thread (%s)", event_type->name->c_str(),
|
"A \"{}\" event was scheduled from the wrong thread ({})", *event_type->name,
|
||||||
from_cpu_thread ? "CPU" : "non-CPU");
|
from_cpu_thread ? "CPU" : "non-CPU");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -300,7 +300,7 @@ u16 SDSP::ReadRegister(size_t reg) const
|
||||||
case DSP_REG_ACM1:
|
case DSP_REG_ACM1:
|
||||||
return r.ac[reg - DSP_REG_ACM0].m;
|
return r.ac[reg - DSP_REG_ACM0].m;
|
||||||
default:
|
default:
|
||||||
ASSERT_MSG(DSP_CORE, 0, "cannot happen");
|
ASSERT_MSG(DSPLLE, 0, "cannot happen");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -687,7 +687,7 @@ u16 Interpreter::OpReadRegister(int reg_)
|
||||||
case DSP_REG_ACM1:
|
case DSP_REG_ACM1:
|
||||||
return state.r.ac[reg - DSP_REG_ACM0].m;
|
return state.r.ac[reg - DSP_REG_ACM0].m;
|
||||||
default:
|
default:
|
||||||
ASSERT_MSG(DSP_INT, 0, "cannot happen");
|
ASSERT_MSG(DSPLLE, 0, "cannot happen");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,7 +153,7 @@ void DSPEmitter::FallBackToInterpreter(UDSPInstruction inst)
|
||||||
const auto interpreter_function = Interpreter::GetOp(inst);
|
const auto interpreter_function = Interpreter::GetOp(inst);
|
||||||
|
|
||||||
m_gpr.PushRegs();
|
m_gpr.PushRegs();
|
||||||
ASSERT_MSG(DSPLLE, interpreter_function != nullptr, "No function for %04x", inst);
|
ASSERT_MSG(DSPLLE, interpreter_function != nullptr, "No function for {:04x}", inst);
|
||||||
ABI_CallFunctionPC(FallbackThunk, &m_dsp_core.GetInterpreter(), inst);
|
ABI_CallFunctionPC(FallbackThunk, &m_dsp_core.GetInterpreter(), inst);
|
||||||
m_gpr.PopRegs();
|
m_gpr.PopRegs();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include "Core/DSP/Jit/x64/DSPJitRegCache.h"
|
#include "Core/DSP/Jit/x64/DSPJitRegCache.h"
|
||||||
|
|
||||||
#include <cinttypes>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
|
@ -298,21 +297,21 @@ void DSPJitRegCache::FlushRegs(DSPJitRegCache& cache, bool emit)
|
||||||
for (size_t i = 0; i < m_xregs.size(); i++)
|
for (size_t i = 0; i < m_xregs.size(); i++)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DSPLLE, m_xregs[i].guest_reg == cache.m_xregs[i].guest_reg,
|
ASSERT_MSG(DSPLLE, m_xregs[i].guest_reg == cache.m_xregs[i].guest_reg,
|
||||||
"cache and current xreg guest_reg mismatch for %zu", i);
|
"cache and current xreg guest_reg mismatch for {}", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < m_regs.size(); i++)
|
for (size_t i = 0; i < m_regs.size(); i++)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DSPLLE, m_regs[i].loc.IsImm() == cache.m_regs[i].loc.IsImm(),
|
ASSERT_MSG(DSPLLE, m_regs[i].loc.IsImm() == cache.m_regs[i].loc.IsImm(),
|
||||||
"cache and current reg loc mismatch for %zu", i);
|
"cache and current reg loc mismatch for {}", i);
|
||||||
ASSERT_MSG(DSPLLE, m_regs[i].loc.GetSimpleReg() == cache.m_regs[i].loc.GetSimpleReg(),
|
ASSERT_MSG(DSPLLE, m_regs[i].loc.GetSimpleReg() == cache.m_regs[i].loc.GetSimpleReg(),
|
||||||
"cache and current reg loc mismatch for %zu", i);
|
"cache and current reg loc mismatch for {}", i);
|
||||||
ASSERT_MSG(DSPLLE, m_regs[i].dirty || !cache.m_regs[i].dirty,
|
ASSERT_MSG(DSPLLE, m_regs[i].dirty || !cache.m_regs[i].dirty,
|
||||||
"cache and current reg dirty mismatch for %zu", i);
|
"cache and current reg dirty mismatch for {}", i);
|
||||||
ASSERT_MSG(DSPLLE, m_regs[i].used == cache.m_regs[i].used,
|
ASSERT_MSG(DSPLLE, m_regs[i].used == cache.m_regs[i].used,
|
||||||
"cache and current reg used mismatch for %zu", i);
|
"cache and current reg used mismatch for {}", i);
|
||||||
ASSERT_MSG(DSPLLE, m_regs[i].shift == cache.m_regs[i].shift,
|
ASSERT_MSG(DSPLLE, m_regs[i].shift == cache.m_regs[i].shift,
|
||||||
"cache and current reg shift mismatch for %zu", i);
|
"cache and current reg shift mismatch for {}", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_use_ctr = cache.m_use_ctr;
|
m_use_ctr = cache.m_use_ctr;
|
||||||
|
@ -326,7 +325,7 @@ void DSPJitRegCache::FlushMemBackedRegs()
|
||||||
|
|
||||||
for (size_t i = 0; i < m_regs.size(); i++)
|
for (size_t i = 0; i < m_regs.size(); i++)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DSPLLE, !m_regs[i].used, "register %u still in use", static_cast<u32>(i));
|
ASSERT_MSG(DSPLLE, !m_regs[i].used, "register {} still in use", static_cast<u32>(i));
|
||||||
|
|
||||||
if (m_regs[i].used)
|
if (m_regs[i].used)
|
||||||
{
|
{
|
||||||
|
@ -356,27 +355,27 @@ void DSPJitRegCache::FlushRegs()
|
||||||
MovToMemory(i);
|
MovToMemory(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_MSG(DSPLLE, !m_regs[i].loc.IsSimpleReg(), "register %zu is still a simple reg", i);
|
ASSERT_MSG(DSPLLE, !m_regs[i].loc.IsSimpleReg(), "register {} is still a simple reg", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_MSG(DSPLLE, m_xregs[RSP].guest_reg == DSP_REG_STATIC, "wrong xreg state for %d", RSP);
|
ASSERT_MSG(DSPLLE, m_xregs[RSP].guest_reg == DSP_REG_STATIC, "wrong xreg state for {}", RSP);
|
||||||
ASSERT_MSG(DSPLLE, m_xregs[RBX].guest_reg == DSP_REG_STATIC, "wrong xreg state for %d", RBX);
|
ASSERT_MSG(DSPLLE, m_xregs[RBX].guest_reg == DSP_REG_STATIC, "wrong xreg state for {}", RBX);
|
||||||
ASSERT_MSG(DSPLLE, m_xregs[RBP].guest_reg == DSP_REG_NONE, "wrong xreg state for %d", RBP);
|
ASSERT_MSG(DSPLLE, m_xregs[RBP].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", RBP);
|
||||||
ASSERT_MSG(DSPLLE, m_xregs[RSI].guest_reg == DSP_REG_NONE, "wrong xreg state for %d", RSI);
|
ASSERT_MSG(DSPLLE, m_xregs[RSI].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", RSI);
|
||||||
ASSERT_MSG(DSPLLE, m_xregs[RDI].guest_reg == DSP_REG_NONE, "wrong xreg state for %d", RDI);
|
ASSERT_MSG(DSPLLE, m_xregs[RDI].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", RDI);
|
||||||
#ifdef STATIC_REG_ACCS
|
#ifdef STATIC_REG_ACCS
|
||||||
ASSERT_MSG(DSPLLE, m_xregs[R8].guest_reg == DSP_REG_STATIC, "wrong xreg state for %d", R8);
|
ASSERT_MSG(DSPLLE, m_xregs[R8].guest_reg == DSP_REG_STATIC, "wrong xreg state for {}", R8);
|
||||||
ASSERT_MSG(DSPLLE, m_xregs[R9].guest_reg == DSP_REG_STATIC, "wrong xreg state for %d", R9);
|
ASSERT_MSG(DSPLLE, m_xregs[R9].guest_reg == DSP_REG_STATIC, "wrong xreg state for {}", R9);
|
||||||
#else
|
#else
|
||||||
ASSERT_MSG(DSPLLE, m_xregs[R8].guest_reg == DSP_REG_NONE, "wrong xreg state for %d", R8);
|
ASSERT_MSG(DSPLLE, m_xregs[R8].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", R8);
|
||||||
ASSERT_MSG(DSPLLE, m_xregs[R9].guest_reg == DSP_REG_NONE, "wrong xreg state for %d", R9);
|
ASSERT_MSG(DSPLLE, m_xregs[R9].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", R9);
|
||||||
#endif
|
#endif
|
||||||
ASSERT_MSG(DSPLLE, m_xregs[R10].guest_reg == DSP_REG_NONE, "wrong xreg state for %d", R10);
|
ASSERT_MSG(DSPLLE, m_xregs[R10].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", R10);
|
||||||
ASSERT_MSG(DSPLLE, m_xregs[R11].guest_reg == DSP_REG_NONE, "wrong xreg state for %d", R11);
|
ASSERT_MSG(DSPLLE, m_xregs[R11].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", R11);
|
||||||
ASSERT_MSG(DSPLLE, m_xregs[R12].guest_reg == DSP_REG_NONE, "wrong xreg state for %d", R12);
|
ASSERT_MSG(DSPLLE, m_xregs[R12].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", R12);
|
||||||
ASSERT_MSG(DSPLLE, m_xregs[R13].guest_reg == DSP_REG_NONE, "wrong xreg state for %d", R13);
|
ASSERT_MSG(DSPLLE, m_xregs[R13].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", R13);
|
||||||
ASSERT_MSG(DSPLLE, m_xregs[R14].guest_reg == DSP_REG_NONE, "wrong xreg state for %d", R14);
|
ASSERT_MSG(DSPLLE, m_xregs[R14].guest_reg == DSP_REG_NONE, "wrong xreg state for {}", R14);
|
||||||
ASSERT_MSG(DSPLLE, m_xregs[R15].guest_reg == DSP_REG_STATIC, "wrong xreg state for %d", R15);
|
ASSERT_MSG(DSPLLE, m_xregs[R15].guest_reg == DSP_REG_STATIC, "wrong xreg state for {}", R15);
|
||||||
|
|
||||||
m_use_ctr = 0;
|
m_use_ctr = 0;
|
||||||
}
|
}
|
||||||
|
@ -403,7 +402,7 @@ void DSPJitRegCache::SaveRegs()
|
||||||
MovToMemory(i);
|
MovToMemory(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_MSG(DSPLLE, !m_regs[i].loc.IsSimpleReg(), "register %zu is still a simple reg", i);
|
ASSERT_MSG(DSPLLE, !m_regs[i].loc.IsSimpleReg(), "register {} is still a simple reg", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,7 +417,7 @@ void DSPJitRegCache::PushRegs()
|
||||||
MovToMemory(i);
|
MovToMemory(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_MSG(DSPLLE, !m_regs[i].loc.IsSimpleReg(), "register %zu is still a simple reg", i);
|
ASSERT_MSG(DSPLLE, !m_regs[i].loc.IsSimpleReg(), "register {} is still a simple reg", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
int push_count = 0;
|
int push_count = 0;
|
||||||
|
@ -445,7 +444,7 @@ void DSPJitRegCache::PushRegs()
|
||||||
|
|
||||||
ASSERT_MSG(DSPLLE,
|
ASSERT_MSG(DSPLLE,
|
||||||
m_xregs[i].guest_reg == DSP_REG_NONE || m_xregs[i].guest_reg == DSP_REG_STATIC,
|
m_xregs[i].guest_reg == DSP_REG_NONE || m_xregs[i].guest_reg == DSP_REG_STATIC,
|
||||||
"register %zu is still used", i);
|
"register {} is still used", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,10 +485,10 @@ X64Reg DSPJitRegCache::MakeABICallSafe(X64Reg reg)
|
||||||
|
|
||||||
void DSPJitRegCache::MovToHostReg(size_t reg, X64Reg host_reg, bool load)
|
void DSPJitRegCache::MovToHostReg(size_t reg, X64Reg host_reg, bool load)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DSPLLE, reg < m_regs.size(), "bad register name %zu", reg);
|
ASSERT_MSG(DSPLLE, reg < m_regs.size(), "bad register name {}", reg);
|
||||||
ASSERT_MSG(DSPLLE, m_regs[reg].parentReg == DSP_REG_NONE, "register %zu is proxy for %d", reg,
|
ASSERT_MSG(DSPLLE, m_regs[reg].parentReg == DSP_REG_NONE, "register {} is proxy for {}", reg,
|
||||||
m_regs[reg].parentReg);
|
m_regs[reg].parentReg);
|
||||||
ASSERT_MSG(DSPLLE, !m_regs[reg].used, "moving to host reg in use guest reg %zu", reg);
|
ASSERT_MSG(DSPLLE, !m_regs[reg].used, "moving to host reg in use guest reg {}", reg);
|
||||||
X64Reg old_reg = m_regs[reg].loc.GetSimpleReg();
|
X64Reg old_reg = m_regs[reg].loc.GetSimpleReg();
|
||||||
if (old_reg == host_reg)
|
if (old_reg == host_reg)
|
||||||
{
|
{
|
||||||
|
@ -529,10 +528,10 @@ void DSPJitRegCache::MovToHostReg(size_t reg, X64Reg host_reg, bool load)
|
||||||
|
|
||||||
void DSPJitRegCache::MovToHostReg(size_t reg, bool load)
|
void DSPJitRegCache::MovToHostReg(size_t reg, bool load)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DSPLLE, reg < m_regs.size(), "bad register name %zu", reg);
|
ASSERT_MSG(DSPLLE, reg < m_regs.size(), "bad register name {}", reg);
|
||||||
ASSERT_MSG(DSPLLE, m_regs[reg].parentReg == DSP_REG_NONE, "register %zu is proxy for %d", reg,
|
ASSERT_MSG(DSPLLE, m_regs[reg].parentReg == DSP_REG_NONE, "register {} is proxy for {}", reg,
|
||||||
m_regs[reg].parentReg);
|
m_regs[reg].parentReg);
|
||||||
ASSERT_MSG(DSPLLE, !m_regs[reg].used, "moving to host reg in use guest reg %zu", reg);
|
ASSERT_MSG(DSPLLE, !m_regs[reg].used, "moving to host reg in use guest reg {}", reg);
|
||||||
|
|
||||||
if (m_regs[reg].loc.IsSimpleReg())
|
if (m_regs[reg].loc.IsSimpleReg())
|
||||||
{
|
{
|
||||||
|
@ -559,11 +558,11 @@ void DSPJitRegCache::MovToHostReg(size_t reg, bool load)
|
||||||
|
|
||||||
void DSPJitRegCache::RotateHostReg(size_t reg, int shift, bool emit)
|
void DSPJitRegCache::RotateHostReg(size_t reg, int shift, bool emit)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DSPLLE, reg < m_regs.size(), "bad register name %zu", reg);
|
ASSERT_MSG(DSPLLE, reg < m_regs.size(), "bad register name {}", reg);
|
||||||
ASSERT_MSG(DSPLLE, m_regs[reg].parentReg == DSP_REG_NONE, "register %zu is proxy for %d", reg,
|
ASSERT_MSG(DSPLLE, m_regs[reg].parentReg == DSP_REG_NONE, "register {} is proxy for {}", reg,
|
||||||
m_regs[reg].parentReg);
|
m_regs[reg].parentReg);
|
||||||
ASSERT_MSG(DSPLLE, m_regs[reg].loc.IsSimpleReg(), "register %zu is not a simple reg", reg);
|
ASSERT_MSG(DSPLLE, m_regs[reg].loc.IsSimpleReg(), "register {} is not a simple reg", reg);
|
||||||
ASSERT_MSG(DSPLLE, !m_regs[reg].used, "rotating in use guest reg %zu", reg);
|
ASSERT_MSG(DSPLLE, !m_regs[reg].used, "rotating in use guest reg {}", reg);
|
||||||
|
|
||||||
if (shift > m_regs[reg].shift && emit)
|
if (shift > m_regs[reg].shift && emit)
|
||||||
{
|
{
|
||||||
|
@ -600,10 +599,10 @@ void DSPJitRegCache::RotateHostReg(size_t reg, int shift, bool emit)
|
||||||
|
|
||||||
void DSPJitRegCache::MovToMemory(size_t reg)
|
void DSPJitRegCache::MovToMemory(size_t reg)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DSPLLE, reg < m_regs.size(), "bad register name %zu", reg);
|
ASSERT_MSG(DSPLLE, reg < m_regs.size(), "bad register name {}", reg);
|
||||||
ASSERT_MSG(DSPLLE, m_regs[reg].parentReg == DSP_REG_NONE, "register %zu is proxy for %d", reg,
|
ASSERT_MSG(DSPLLE, m_regs[reg].parentReg == DSP_REG_NONE, "register {} is proxy for {}", reg,
|
||||||
m_regs[reg].parentReg);
|
m_regs[reg].parentReg);
|
||||||
ASSERT_MSG(DSPLLE, !m_regs[reg].used, "moving to memory in use guest reg %zu", reg);
|
ASSERT_MSG(DSPLLE, !m_regs[reg].used, "moving to memory in use guest reg {}", reg);
|
||||||
|
|
||||||
if (m_regs[reg].used)
|
if (m_regs[reg].used)
|
||||||
{
|
{
|
||||||
|
@ -683,7 +682,7 @@ OpArg DSPJitRegCache::GetReg(int reg, bool load)
|
||||||
shift = 0;
|
shift = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_MSG(DSPLLE, !m_regs[real_reg].used, "register %d already in use", real_reg);
|
ASSERT_MSG(DSPLLE, !m_regs[real_reg].used, "register {} already in use", real_reg);
|
||||||
|
|
||||||
if (m_regs[real_reg].used)
|
if (m_regs[real_reg].used)
|
||||||
{
|
{
|
||||||
|
@ -694,7 +693,7 @@ OpArg DSPJitRegCache::GetReg(int reg, bool load)
|
||||||
MovToHostReg(real_reg, load);
|
MovToHostReg(real_reg, load);
|
||||||
|
|
||||||
// TODO: actually handle INVALID_REG
|
// TODO: actually handle INVALID_REG
|
||||||
ASSERT_MSG(DSPLLE, m_regs[real_reg].loc.IsSimpleReg(), "did not get host reg for %d", reg);
|
ASSERT_MSG(DSPLLE, m_regs[real_reg].loc.IsSimpleReg(), "did not get host reg for {}", reg);
|
||||||
|
|
||||||
RotateHostReg(real_reg, shift, load);
|
RotateHostReg(real_reg, shift, load);
|
||||||
const OpArg oparg = m_regs[real_reg].loc;
|
const OpArg oparg = m_regs[real_reg].loc;
|
||||||
|
@ -962,7 +961,7 @@ void DSPJitRegCache::SpillXReg(X64Reg reg)
|
||||||
if (m_xregs[reg].guest_reg <= DSP_REG_MAX_MEM_BACKED)
|
if (m_xregs[reg].guest_reg <= DSP_REG_MAX_MEM_BACKED)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DSPLLE, !m_regs[m_xregs[reg].guest_reg].used,
|
ASSERT_MSG(DSPLLE, !m_regs[m_xregs[reg].guest_reg].used,
|
||||||
"to be spilled host reg %x(guest reg %zx) still in use!", reg,
|
"to be spilled host reg {:#x} (guest reg {:#x}) still in use!", reg,
|
||||||
m_xregs[reg].guest_reg);
|
m_xregs[reg].guest_reg);
|
||||||
|
|
||||||
MovToMemory(m_xregs[reg].guest_reg);
|
MovToMemory(m_xregs[reg].guest_reg);
|
||||||
|
@ -970,7 +969,7 @@ void DSPJitRegCache::SpillXReg(X64Reg reg)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DSPLLE, m_xregs[reg].guest_reg == DSP_REG_NONE,
|
ASSERT_MSG(DSPLLE, m_xregs[reg].guest_reg == DSP_REG_NONE,
|
||||||
"to be spilled host reg %x still in use!", reg);
|
"to be spilled host reg {:#x} still in use!", reg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include "Core/HW/DVD/DVDMath.h"
|
#include "Core/HW/DVD/DVDMath.h"
|
||||||
|
|
||||||
#include <cinttypes>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
|
|
@ -123,7 +123,7 @@ void CEXIChannel::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUG_ASSERT_MSG(EXPANSIONINTERFACE, 0,
|
DEBUG_ASSERT_MSG(EXPANSIONINTERFACE, 0,
|
||||||
"EXI Imm: Unknown transfer type %i", m_control.RW);
|
"EXI Imm: Unknown transfer type {}", m_control.RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -139,7 +139,7 @@ void CEXIChannel::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUG_ASSERT_MSG(EXPANSIONINTERFACE, 0,
|
DEBUG_ASSERT_MSG(EXPANSIONINTERFACE, 0,
|
||||||
"EXI DMA: Unknown transfer type %i", m_control.RW);
|
"EXI DMA: Unknown transfer type {}", m_control.RW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,7 @@ CEXIMemoryCard::CEXIMemoryCard(const int index, bool gci_folder,
|
||||||
: m_card_index(index)
|
: m_card_index(index)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(EXPANSIONINTERFACE, static_cast<std::size_t>(index) < s_et_cmd_done.size(),
|
ASSERT_MSG(EXPANSIONINTERFACE, static_cast<std::size_t>(index) < s_et_cmd_done.size(),
|
||||||
"Trying to create invalid memory card index %d.", index);
|
"Trying to create invalid memory card index {}.", index);
|
||||||
|
|
||||||
// NOTE: When loading a save state, DMA completion callbacks (s_et_transfer_complete) and such
|
// NOTE: When loading a save state, DMA completion callbacks (s_et_transfer_complete) and such
|
||||||
// may have been restored, we need to anticipate those arriving.
|
// may have been restored, we need to anticipate those arriving.
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
#include "Core/HW/GCMemcard/GCIFile.h"
|
#include "Core/HW/GCMemcard/GCIFile.h"
|
||||||
|
|
||||||
#include <cinttypes>
|
|
||||||
|
|
||||||
#include "Common/ChunkFile.h"
|
#include "Common/ChunkFile.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/IOFile.h"
|
#include "Common/IOFile.h"
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include "Core/HW/GCMemcard/GCMemcard.h"
|
#include "Core/HW/GCMemcard/GCMemcard.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cinttypes>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cinttypes>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
|
@ -195,7 +195,7 @@ std::unique_ptr<ISIDevice> SIDevice_Create(const SIDevices device, const int por
|
||||||
#ifdef HAS_LIBMGBA
|
#ifdef HAS_LIBMGBA
|
||||||
return std::make_unique<CSIDevice_GBAEmu>(device, port_number);
|
return std::make_unique<CSIDevice_GBAEmu>(device, port_number);
|
||||||
#else
|
#else
|
||||||
PanicAlertT("Error: This build does not support emulated GBA controllers");
|
PanicAlertFmtT("Error: This build does not support emulated GBA controllers");
|
||||||
return std::make_unique<CSIDevice_Null>(device, port_number);
|
return std::make_unique<CSIDevice_Null>(device, port_number);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "Common/CommonFuncs.h"
|
#include "Common/CommonFuncs.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/DynamicLibrary.h"
|
#include "Common/DynamicLibrary.h"
|
||||||
|
#include "Common/HRWrap.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/ScopeGuard.h"
|
#include "Common/ScopeGuard.h"
|
||||||
#include "Common/Thread.h"
|
#include "Common/Thread.h"
|
||||||
|
@ -247,7 +248,7 @@ int IOWritePerSetOutputReport(HANDLE& dev_handle, const u8* buf, size_t len, DWO
|
||||||
// Some third-party adapters (DolphinBar) use this
|
// Some third-party adapters (DolphinBar) use this
|
||||||
// error code to signal the absence of a Wiimote
|
// error code to signal the absence of a Wiimote
|
||||||
// linked to the HID device.
|
// linked to the HID device.
|
||||||
WARN_LOG_FMT(WIIMOTE, "IOWrite[WWM_SET_OUTPUT_REPORT]: Error: {:08x}", err);
|
WARN_LOG_FMT(WIIMOTE, "IOWrite[WWM_SET_OUTPUT_REPORT]: Error: {}", Common::HRWrap(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +298,8 @@ int IOWritePerWriteFile(HANDLE& dev_handle, OVERLAPPED& hid_overlap_write,
|
||||||
// Pending is no error!
|
// Pending is no error!
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
WARN_LOG_FMT(WIIMOTE, "IOWrite[WWM_WRITE_FILE]: Error on WriteFile: {:08x}", error);
|
WARN_LOG_FMT(WIIMOTE, "IOWrite[WWM_WRITE_FILE]: Error on WriteFile: {}",
|
||||||
|
Common::HRWrap(error));
|
||||||
CancelIo(dev_handle);
|
CancelIo(dev_handle);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -771,7 +773,7 @@ int IORead(HANDLE& dev_handle, OVERLAPPED& hid_overlap_read, u8* buf, int index)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WARN_LOG_FMT(WIIMOTE, "ReadFile error {} on Wiimote {}.", read_err, index + 1);
|
WARN_LOG_FMT(WIIMOTE, "ReadFile on Wiimote {}: {}", index + 1, Common::HRWrap(read_err));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -955,8 +957,8 @@ bool AttachWiimote(HANDLE hRadio, const BLUETOOTH_RADIO_INFO& radio_info,
|
||||||
|
|
||||||
if (ERROR_SUCCESS != auth_result)
|
if (ERROR_SUCCESS != auth_result)
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(WIIMOTE, "AttachWiimote: BluetoothAuthenticateDeviceEx returned {:08x}",
|
ERROR_LOG_FMT(WIIMOTE, "AttachWiimote: BluetoothAuthenticateDeviceEx failed: {}",
|
||||||
auth_result);
|
Common::HRWrap(auth_result));
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD pcServices = 16;
|
DWORD pcServices = 16;
|
||||||
|
@ -967,8 +969,8 @@ bool AttachWiimote(HANDLE hRadio, const BLUETOOTH_RADIO_INFO& radio_info,
|
||||||
|
|
||||||
if (ERROR_SUCCESS != srv_result)
|
if (ERROR_SUCCESS != srv_result)
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(WIIMOTE, "AttachWiimote: BluetoothEnumerateInstalledServices returned {:08x}",
|
ERROR_LOG_FMT(WIIMOTE, "AttachWiimote: BluetoothEnumerateInstalledServices failed: {}",
|
||||||
srv_result);
|
Common::HRWrap(auth_result));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// Activate service
|
// Activate service
|
||||||
|
@ -979,7 +981,8 @@ bool AttachWiimote(HANDLE hRadio, const BLUETOOTH_RADIO_INFO& radio_info,
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(WIIMOTE, "AttachWiimote: BluetoothSetServiceState returned {:08x}", hr);
|
ERROR_LOG_FMT(WIIMOTE, "AttachWiimote: BluetoothSetServiceState failed: {}",
|
||||||
|
Common::HRWrap(hr));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include "Core/IOS/ES/ES.h"
|
#include "Core/IOS/ES/ES.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cinttypes>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cinttypes>
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -683,7 +682,7 @@ std::optional<IPCReply> Kernel::HandleIPCCommand(const Request& request)
|
||||||
ret = device->IOCtlV(IOCtlVRequest{request.address});
|
ret = device->IOCtlV(IOCtlVRequest{request.address});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ASSERT_MSG(IOS, false, "Unexpected command: %x", request.command);
|
ASSERT_MSG(IOS, false, "Unexpected command: {:#x}", request.command);
|
||||||
ret = IPCReply{IPC_EINVAL, 978_tbticks};
|
ret = IPCReply{IPC_EINVAL, 978_tbticks};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cinttypes>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
|
@ -178,7 +178,7 @@ std::optional<IPCReply> BluetoothEmuDevice::IOCtlV(const IOCtlVRequest& request)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
DEBUG_ASSERT_MSG(IOS_WIIMOTE, 0, "Unknown USB::IOCTLV_USBV0_BLKMSG: %x", ctrl.endpoint);
|
DEBUG_ASSERT_MSG(IOS_WIIMOTE, 0, "Unknown USB::IOCTLV_USBV0_BLKMSG: {:#x}", ctrl.endpoint);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,7 @@ std::optional<IPCReply> BluetoothEmuDevice::IOCtlV(const IOCtlVRequest& request)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_ASSERT_MSG(IOS_WIIMOTE, 0, "Unknown USB::IOCTLV_USBV0_INTRMSG: %x", ctrl.endpoint);
|
DEBUG_ASSERT_MSG(IOS_WIIMOTE, 0, "Unknown USB::IOCTLV_USBV0_INTRMSG: {:#x}", ctrl.endpoint);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1085,8 +1085,9 @@ void BluetoothEmuDevice::ExecuteHCICommandMessage(const USB::V0CtrlMessage& ctrl
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_ASSERT_MSG(IOS_WIIMOTE, 0, "Unknown USB_IOCTL_CTRLMSG: 0x%04X (ocf: 0x%x ogf 0x%x)",
|
DEBUG_ASSERT_MSG(IOS_WIIMOTE, 0,
|
||||||
msg.Opcode, ocf, ogf);
|
"Unknown USB_IOCTL_CTRLMSG: {:#06x} (ocf: {:#04x} ogf {:#04x})", msg.Opcode,
|
||||||
|
ocf, ogf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -610,7 +610,7 @@ void WiimoteDevice::ReceiveConfigurationReq(u8 ident, u8* data, u32 size)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DEBUG_ASSERT_MSG(IOS_WIIMOTE, 0, "Unknown Option: 0x%02x", options->type);
|
DEBUG_ASSERT_MSG(IOS_WIIMOTE, 0, "Unknown Option: {:#04x}", options->type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ V5IsoMessage::V5IsoMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
|
||||||
total_packet_size += packet_size;
|
total_packet_size += packet_size;
|
||||||
}
|
}
|
||||||
length = ioctlv.GetVector(2)->size;
|
length = ioctlv.GetVector(2)->size;
|
||||||
ASSERT_MSG(IOS_USB, length == total_packet_size, "Wrong buffer size (0x%x != 0x%x)", length,
|
ASSERT_MSG(IOS_USB, length == total_packet_size, "Wrong buffer size ({:#x} != {:#x})", length,
|
||||||
total_packet_size);
|
total_packet_size);
|
||||||
}
|
}
|
||||||
} // namespace USB
|
} // namespace USB
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include "Core/IOS/WFS/WFSSRV.h"
|
#include "Core/IOS/WFS/WFSSRV.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cinttypes>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ public:
|
||||||
Impl()
|
Impl()
|
||||||
{
|
{
|
||||||
const int ret = libusb_init(&m_context);
|
const int ret = libusb_init(&m_context);
|
||||||
ASSERT_MSG(IOS_USB, ret == LIBUSB_SUCCESS, "Failed to init libusb: %s", libusb_error_name(ret));
|
ASSERT_MSG(IOS_USB, ret == LIBUSB_SUCCESS, "Failed to init libusb: {}", libusb_error_name(ret));
|
||||||
if (ret != LIBUSB_SUCCESS)
|
if (ret != LIBUSB_SUCCESS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -328,7 +328,7 @@ void InstallExceptionHandler()
|
||||||
signal_stack.ss_size = SIGSTKSZ;
|
signal_stack.ss_size = SIGSTKSZ;
|
||||||
signal_stack.ss_flags = 0;
|
signal_stack.ss_flags = 0;
|
||||||
if (sigaltstack(&signal_stack, nullptr))
|
if (sigaltstack(&signal_stack, nullptr))
|
||||||
PanicAlert("sigaltstack failed");
|
PanicAlertFmt("sigaltstack failed");
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
sa.sa_handler = nullptr;
|
sa.sa_handler = nullptr;
|
||||||
sa.sa_sigaction = &sigsegv_handler;
|
sa.sa_sigaction = &sigsegv_handler;
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cinttypes>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include "Core/PowerPC/Interpreter/Interpreter.h"
|
#include "Core/PowerPC/Interpreter/Interpreter.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cinttypes>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
@ -340,7 +339,7 @@ void Interpreter::unknown_instruction(UGeckoInstruction inst)
|
||||||
i + 1, rGPR[i + 1], i + 2, rGPR[i + 2], i + 3, rGPR[i + 3]);
|
i + 1, rGPR[i + 1], i + 2, rGPR[i + 2], i + 3, rGPR[i + 3]);
|
||||||
}
|
}
|
||||||
ASSERT_MSG(POWERPC, 0,
|
ASSERT_MSG(POWERPC, 0,
|
||||||
"\nIntCPU: Unknown instruction %08x at PC = %08x last_PC = %08x LR = %08x\n",
|
"\nIntCPU: Unknown instruction {:08x} at PC = {:08x} last_PC = {:08x} LR = {:08x}\n",
|
||||||
inst.hex, PC, last_pc, LR);
|
inst.hex, PC, last_pc, LR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -341,7 +341,7 @@ void Interpreter::mtspr(UGeckoInstruction inst)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPR_WPAR:
|
case SPR_WPAR:
|
||||||
ASSERT_MSG(POWERPC, rGPR[inst.RD] == 0x0C008000, "Gather pipe @ %08x", PC);
|
ASSERT_MSG(POWERPC, rGPR[inst.RD] == 0x0C008000, "Gather pipe @ {:08x}", PC);
|
||||||
GPFifo::ResetGatherPipe();
|
GPFifo::ResetGatherPipe();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -1142,7 +1142,7 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
||||||
// it.
|
// it.
|
||||||
FixupBranch memException;
|
FixupBranch memException;
|
||||||
ASSERT_MSG(DYNA_REC, !(js.fastmemLoadStore && js.fixupExceptionHandler),
|
ASSERT_MSG(DYNA_REC, !(js.fastmemLoadStore && js.fixupExceptionHandler),
|
||||||
"Fastmem loadstores shouldn't have exception handler fixups (PC=%x)!",
|
"Fastmem loadstores shouldn't have exception handler fixups (PC={:x})!",
|
||||||
op.address);
|
op.address);
|
||||||
if (!js.fastmemLoadStore && !js.fixupExceptionHandler)
|
if (!js.fastmemLoadStore && !js.fixupExceptionHandler)
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,13 +15,13 @@ FPURegCache::FPURegCache(Jit64& jit) : RegCache{jit}
|
||||||
|
|
||||||
void FPURegCache::StoreRegister(preg_t preg, const OpArg& new_loc)
|
void FPURegCache::StoreRegister(preg_t preg, const OpArg& new_loc)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, m_regs[preg].IsBound(), "Unbound register - %zu", preg);
|
ASSERT_MSG(DYNA_REC, m_regs[preg].IsBound(), "Unbound register - {}", preg);
|
||||||
m_emitter->MOVAPD(new_loc, m_regs[preg].Location()->GetSimpleReg());
|
m_emitter->MOVAPD(new_loc, m_regs[preg].Location()->GetSimpleReg());
|
||||||
}
|
}
|
||||||
|
|
||||||
void FPURegCache::LoadRegister(preg_t preg, X64Reg new_loc)
|
void FPURegCache::LoadRegister(preg_t preg, X64Reg new_loc)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !m_regs[preg].IsDiscarded(), "Discarded register - %zu", preg);
|
ASSERT_MSG(DYNA_REC, !m_regs[preg].IsDiscarded(), "Discarded register - {}", preg);
|
||||||
m_emitter->MOVAPD(new_loc, m_regs[preg].Location().value());
|
m_emitter->MOVAPD(new_loc, m_regs[preg].Location().value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,13 @@ GPRRegCache::GPRRegCache(Jit64& jit) : RegCache{jit}
|
||||||
|
|
||||||
void GPRRegCache::StoreRegister(preg_t preg, const OpArg& new_loc)
|
void GPRRegCache::StoreRegister(preg_t preg, const OpArg& new_loc)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !m_regs[preg].IsDiscarded(), "Discarded register - %zu", preg);
|
ASSERT_MSG(DYNA_REC, !m_regs[preg].IsDiscarded(), "Discarded register - {}", preg);
|
||||||
m_emitter->MOV(32, new_loc, m_regs[preg].Location().value());
|
m_emitter->MOV(32, new_loc, m_regs[preg].Location().value());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPRRegCache::LoadRegister(preg_t preg, X64Reg new_loc)
|
void GPRRegCache::LoadRegister(preg_t preg, X64Reg new_loc)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !m_regs[preg].IsDiscarded(), "Discarded register - %zu", preg);
|
ASSERT_MSG(DYNA_REC, !m_regs[preg].IsDiscarded(), "Discarded register - {}", preg);
|
||||||
m_emitter->MOV(32, ::Gen::R(new_loc), m_regs[preg].Location().value());
|
m_emitter->MOV(32, ::Gen::R(new_loc), m_regs[preg].Location().value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include "Core/PowerPC/Jit64/RegCache/JitRegCache.h"
|
#include "Core/PowerPC/Jit64/RegCache/JitRegCache.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cinttypes>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
@ -389,9 +388,10 @@ void RegCache::Discard(BitSet32 pregs)
|
||||||
|
|
||||||
for (preg_t i : pregs)
|
for (preg_t i : pregs)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !m_regs[i].IsLocked(),
|
ASSERT_MSG(DYNA_REC, !m_regs[i].IsLocked(), "Someone forgot to unlock PPC reg {} (X64 reg {}).",
|
||||||
"Someone forgot to unlock PPC reg %zu (X64 reg %i).", i, RX(i));
|
i, RX(i));
|
||||||
ASSERT_MSG(DYNA_REC, !m_regs[i].IsRevertable(), "Register transaction is in progress!");
|
ASSERT_MSG(DYNA_REC, !m_regs[i].IsRevertable(), "Register transaction is in progress for {}!",
|
||||||
|
i);
|
||||||
|
|
||||||
if (m_regs[i].IsBound())
|
if (m_regs[i].IsBound())
|
||||||
{
|
{
|
||||||
|
@ -412,9 +412,10 @@ void RegCache::Flush(BitSet32 pregs)
|
||||||
|
|
||||||
for (preg_t i : pregs)
|
for (preg_t i : pregs)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !m_regs[i].IsLocked(),
|
ASSERT_MSG(DYNA_REC, !m_regs[i].IsLocked(), "Someone forgot to unlock PPC reg {} (X64 reg {}).",
|
||||||
"Someone forgot to unlock PPC reg %zu (X64 reg %i).", i, RX(i));
|
i, RX(i));
|
||||||
ASSERT_MSG(DYNA_REC, !m_regs[i].IsRevertable(), "Register transaction is in progress!");
|
ASSERT_MSG(DYNA_REC, !m_regs[i].IsRevertable(), "Register transaction is in progress for {}!",
|
||||||
|
i);
|
||||||
|
|
||||||
switch (m_regs[i].GetLocationType())
|
switch (m_regs[i].GetLocationType())
|
||||||
{
|
{
|
||||||
|
@ -439,7 +440,7 @@ void RegCache::Reset(BitSet32 pregs)
|
||||||
{
|
{
|
||||||
for (preg_t i : pregs)
|
for (preg_t i : pregs)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNAREC, !m_regs[i].IsAway(),
|
ASSERT_MSG(DYNA_REC, !m_regs[i].IsAway(),
|
||||||
"Attempted to reset a loaded register (did you mean to flush it?)");
|
"Attempted to reset a loaded register (did you mean to flush it?)");
|
||||||
m_regs[i].SetFlushed();
|
m_regs[i].SetFlushed();
|
||||||
}
|
}
|
||||||
|
@ -496,7 +497,7 @@ BitSet32 RegCache::RegistersInUse() const
|
||||||
|
|
||||||
void RegCache::FlushX(X64Reg reg)
|
void RegCache::FlushX(X64Reg reg)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, reg < m_xregs.size(), "Flushing non-existent reg %i", reg);
|
ASSERT_MSG(DYNA_REC, reg < m_xregs.size(), "Flushing non-existent reg {}", reg);
|
||||||
ASSERT(!m_xregs[reg].IsLocked());
|
ASSERT(!m_xregs[reg].IsLocked());
|
||||||
if (!m_xregs[reg].IsFree())
|
if (!m_xregs[reg].IsFree())
|
||||||
{
|
{
|
||||||
|
@ -520,7 +521,7 @@ void RegCache::BindToRegister(preg_t i, bool doLoad, bool makeDirty)
|
||||||
{
|
{
|
||||||
X64Reg xr = GetFreeXReg();
|
X64Reg xr = GetFreeXReg();
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, !m_xregs[xr].IsDirty(), "Xreg %i already dirty", xr);
|
ASSERT_MSG(DYNA_REC, !m_xregs[xr].IsDirty(), "Xreg {} already dirty", xr);
|
||||||
ASSERT_MSG(DYNA_REC, !m_xregs[xr].IsLocked(), "GetFreeXReg returned locked register");
|
ASSERT_MSG(DYNA_REC, !m_xregs[xr].IsLocked(), "GetFreeXReg returned locked register");
|
||||||
ASSERT_MSG(DYNA_REC, !m_regs[i].IsRevertable(), "Invalid transaction state");
|
ASSERT_MSG(DYNA_REC, !m_regs[i].IsRevertable(), "Invalid transaction state");
|
||||||
|
|
||||||
|
@ -537,7 +538,7 @@ void RegCache::BindToRegister(preg_t i, bool doLoad, bool makeDirty)
|
||||||
[xr](const auto& r) {
|
[xr](const auto& r) {
|
||||||
return r.Location().has_value() && r.Location()->IsSimpleReg(xr);
|
return r.Location().has_value() && r.Location()->IsSimpleReg(xr);
|
||||||
}),
|
}),
|
||||||
"Xreg %i already bound", xr);
|
"Xreg {} already bound", xr);
|
||||||
|
|
||||||
m_regs[i].SetBoundTo(xr);
|
m_regs[i].SetBoundTo(xr);
|
||||||
}
|
}
|
||||||
|
@ -549,13 +550,14 @@ void RegCache::BindToRegister(preg_t i, bool doLoad, bool makeDirty)
|
||||||
m_xregs[RX(i)].MakeDirty();
|
m_xregs[RX(i)].MakeDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_MSG(DYNA_REC, !m_xregs[RX(i)].IsLocked(), "WTF, this reg should have been flushed");
|
ASSERT_MSG(DYNA_REC, !m_xregs[RX(i)].IsLocked(),
|
||||||
|
"WTF, this reg ({} -> {}) should have been flushed", i, RX(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegCache::StoreFromRegister(preg_t i, FlushMode mode)
|
void RegCache::StoreFromRegister(preg_t i, FlushMode mode)
|
||||||
{
|
{
|
||||||
// When a transaction is in progress, allowing the store would overwrite the old value.
|
// When a transaction is in progress, allowing the store would overwrite the old value.
|
||||||
ASSERT_MSG(DYNA_REC, !m_regs[i].IsRevertable(), "Register transaction is in progress!");
|
ASSERT_MSG(DYNA_REC, !m_regs[i].IsRevertable(), "Register transaction on {} is in progress!", i);
|
||||||
|
|
||||||
bool doStore = false;
|
bool doStore = false;
|
||||||
|
|
||||||
|
@ -673,13 +675,13 @@ float RegCache::ScoreRegister(X64Reg xreg) const
|
||||||
|
|
||||||
const OpArg& RegCache::R(preg_t preg) const
|
const OpArg& RegCache::R(preg_t preg) const
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, !m_regs[preg].IsDiscarded(), "Discarded register - %zu", preg);
|
ASSERT_MSG(DYNA_REC, !m_regs[preg].IsDiscarded(), "Discarded register - {}", preg);
|
||||||
return m_regs[preg].Location().value();
|
return m_regs[preg].Location().value();
|
||||||
}
|
}
|
||||||
|
|
||||||
X64Reg RegCache::RX(preg_t preg) const
|
X64Reg RegCache::RX(preg_t preg) const
|
||||||
{
|
{
|
||||||
ASSERT_MSG(DYNA_REC, m_regs[preg].IsBound(), "Unbound register - %zu", preg);
|
ASSERT_MSG(DYNA_REC, m_regs[preg].IsBound(), "Unbound register - {}", preg);
|
||||||
return m_regs[preg].Location()->GetSimpleReg();
|
return m_regs[preg].Location()->GetSimpleReg();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cinttypes>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include "Core/PowerPC/Jit64Common/TrampolineCache.h"
|
#include "Core/PowerPC/Jit64Common/TrampolineCache.h"
|
||||||
|
|
||||||
#include <cinttypes>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
|
|
@ -715,7 +715,8 @@ void JitArm64::Jit(u32 em_address, bool clear_cache_and_retry_on_failure)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PanicAlertT("JIT failed to find code space after a cache clear. This should never happen. Please "
|
PanicAlertFmtT(
|
||||||
|
"JIT failed to find code space after a cache clear. This should never happen. Please "
|
||||||
"report this incident on the bug tracker. Dolphin will now exit.");
|
"report this incident on the bug tracker. Dolphin will now exit.");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include "Core/PowerPC/JitArm64/Jit.h"
|
#include "Core/PowerPC/JitArm64/Jit.h"
|
||||||
|
|
||||||
#include <cinttypes>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
|
@ -36,7 +36,7 @@ void Arm64RegCache::ResetRegisters(BitSet32 regs)
|
||||||
OpArg& reg = m_guest_registers[i];
|
OpArg& reg = m_guest_registers[i];
|
||||||
ARM64Reg host_reg = reg.GetReg();
|
ARM64Reg host_reg = reg.GetReg();
|
||||||
|
|
||||||
ASSERT_MSG(DYNAREC, host_reg == ARM64Reg::INVALID_REG,
|
ASSERT_MSG(DYNA_REC, host_reg == ARM64Reg::INVALID_REG,
|
||||||
"Attempted to reset a loaded register (did you mean to flush it?)");
|
"Attempted to reset a loaded register (did you mean to flush it?)");
|
||||||
reg.Flush();
|
reg.Flush();
|
||||||
}
|
}
|
||||||
|
@ -90,8 +90,7 @@ void Arm64RegCache::LockRegister(ARM64Reg host_reg)
|
||||||
{
|
{
|
||||||
auto reg = std::find(m_host_registers.begin(), m_host_registers.end(), host_reg);
|
auto reg = std::find(m_host_registers.begin(), m_host_registers.end(), host_reg);
|
||||||
ASSERT_MSG(DYNA_REC, reg != m_host_registers.end(),
|
ASSERT_MSG(DYNA_REC, reg != m_host_registers.end(),
|
||||||
"Don't try locking a register that isn't in the cache. Reg %d",
|
"Don't try locking a register that isn't in the cache. Reg {}", host_reg);
|
||||||
static_cast<int>(host_reg));
|
|
||||||
reg->Lock();
|
reg->Lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,8 +98,7 @@ void Arm64RegCache::UnlockRegister(ARM64Reg host_reg)
|
||||||
{
|
{
|
||||||
auto reg = std::find(m_host_registers.begin(), m_host_registers.end(), host_reg);
|
auto reg = std::find(m_host_registers.begin(), m_host_registers.end(), host_reg);
|
||||||
ASSERT_MSG(DYNA_REC, reg != m_host_registers.end(),
|
ASSERT_MSG(DYNA_REC, reg != m_host_registers.end(),
|
||||||
"Don't try unlocking a register that isn't in the cache. Reg %d",
|
"Don't try unlocking a register that isn't in the cache. Reg {}", host_reg);
|
||||||
static_cast<int>(host_reg));
|
|
||||||
reg->Unlock();
|
reg->Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ private:
|
||||||
m_emit->STR(IndexType::Unsigned, reg, ARM64Reg::X0, 0);
|
m_emit->STR(IndexType::Unsigned, reg, ARM64Reg::X0, 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ASSERT_MSG(DYNA_REC, false, "Unknown size %d passed to MMIOWriteCodeGenerator!", sbits);
|
ASSERT_MSG(DYNA_REC, false, "Unknown size {} passed to MMIOWriteCodeGenerator!", sbits);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ private:
|
||||||
m_emit->LDR(IndexType::Unsigned, m_dst_reg, ARM64Reg::X0, 0);
|
m_emit->LDR(IndexType::Unsigned, m_dst_reg, ARM64Reg::X0, 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ASSERT_MSG(DYNA_REC, false, "Unknown size %d passed to MMIOReadCodeGenerator!", sbits);
|
ASSERT_MSG(DYNA_REC, false, "Unknown size {} passed to MMIOReadCodeGenerator!", sbits);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include "Core/PowerPC/JitInterface.h"
|
#include "Core/PowerPC/JitInterface.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cinttypes>
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cinttypes>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -52,7 +51,7 @@ GekkoOPInfo* GetOpInfo(UGeckoInstruction inst)
|
||||||
case 63:
|
case 63:
|
||||||
return m_infoTable63[inst.SUBOP10];
|
return m_infoTable63[inst.SUBOP10];
|
||||||
default:
|
default:
|
||||||
ASSERT_MSG(POWERPC, 0, "GetOpInfo - invalid subtable op %08x @ %08x", inst.hex, PC);
|
ASSERT_MSG(POWERPC, 0, "GetOpInfo - invalid subtable op {:08x} @ {:08x}", inst.hex, PC);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +59,7 @@ GekkoOPInfo* GetOpInfo(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
if (info->type == OpType::Invalid)
|
if (info->type == OpType::Invalid)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(POWERPC, 0, "GetOpInfo - invalid op %08x @ %08x", inst.hex, PC);
|
ASSERT_MSG(POWERPC, 0, "GetOpInfo - invalid op {:08x} @ {:08x}", inst.hex, PC);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return m_infoTable[inst.OPCD];
|
return m_infoTable[inst.OPCD];
|
||||||
|
@ -85,7 +84,8 @@ Interpreter::Instruction GetInterpreterOp(UGeckoInstruction inst)
|
||||||
case 63:
|
case 63:
|
||||||
return Interpreter::m_op_table63[inst.SUBOP10];
|
return Interpreter::m_op_table63[inst.SUBOP10];
|
||||||
default:
|
default:
|
||||||
ASSERT_MSG(POWERPC, 0, "GetInterpreterOp - invalid subtable op %08x @ %08x", inst.hex, PC);
|
ASSERT_MSG(POWERPC, 0, "GetInterpreterOp - invalid subtable op {:08x} @ {:08x}", inst.hex,
|
||||||
|
PC);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ Interpreter::Instruction GetInterpreterOp(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
if (info->type == OpType::Invalid)
|
if (info->type == OpType::Invalid)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(POWERPC, 0, "GetInterpreterOp - invalid op %08x @ %08x", inst.hex, PC);
|
ASSERT_MSG(POWERPC, 0, "GetInterpreterOp - invalid op {:08x} @ {:08x}", inst.hex, PC);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return Interpreter::m_op_table[inst.OPCD];
|
return Interpreter::m_op_table[inst.OPCD];
|
||||||
|
|
|
@ -600,7 +600,7 @@ void CheckExternalExceptions()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_ASSERT_MSG(POWERPC, 0, "Unknown EXT interrupt: Exceptions == %08x", exceptions);
|
DEBUG_ASSERT_MSG(POWERPC, 0, "Unknown EXT interrupt: Exceptions == {:08x}", exceptions);
|
||||||
ERROR_LOG_FMT(POWERPC, "Unknown EXTERNAL INTERRUPT exception: Exceptions == {:08x}",
|
ERROR_LOG_FMT(POWERPC, "Unknown EXTERNAL INTERRUPT exception: Exceptions == {:08x}",
|
||||||
exceptions);
|
exceptions);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include "Core/WiiRoot.h"
|
#include "Core/WiiRoot.h"
|
||||||
|
|
||||||
#include <cinttypes>
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
|
@ -107,6 +107,7 @@
|
||||||
<ClInclude Include="Common\GL\GLUtil.h" />
|
<ClInclude Include="Common\GL\GLUtil.h" />
|
||||||
<ClInclude Include="Common\GL\GLX11Window.h" />
|
<ClInclude Include="Common\GL\GLX11Window.h" />
|
||||||
<ClInclude Include="Common\Hash.h" />
|
<ClInclude Include="Common\Hash.h" />
|
||||||
|
<ClInclude Include="Common\HRWrap.h" />
|
||||||
<ClInclude Include="Common\HttpRequest.h" />
|
<ClInclude Include="Common\HttpRequest.h" />
|
||||||
<ClInclude Include="Common\Image.h" />
|
<ClInclude Include="Common\Image.h" />
|
||||||
<ClInclude Include="Common\ImageC.h" />
|
<ClInclude Include="Common\ImageC.h" />
|
||||||
|
@ -707,6 +708,7 @@
|
||||||
<ClCompile Include="Common\GL\GLInterface\WGL.cpp" />
|
<ClCompile Include="Common\GL\GLInterface\WGL.cpp" />
|
||||||
<ClCompile Include="Common\GL\GLUtil.cpp" />
|
<ClCompile Include="Common\GL\GLUtil.cpp" />
|
||||||
<ClCompile Include="Common\Hash.cpp" />
|
<ClCompile Include="Common\Hash.cpp" />
|
||||||
|
<ClCompile Include="Common\HRWrap.cpp" />
|
||||||
<ClCompile Include="Common\HttpRequest.cpp" />
|
<ClCompile Include="Common\HttpRequest.cpp" />
|
||||||
<ClCompile Include="Common\Image.cpp" />
|
<ClCompile Include="Common\Image.cpp" />
|
||||||
<ClCompile Include="Common\ImageC.c">
|
<ClCompile Include="Common\ImageC.c">
|
||||||
|
|
|
@ -82,7 +82,7 @@ bool PlatformX11::Init()
|
||||||
m_display = XOpenDisplay(nullptr);
|
m_display = XOpenDisplay(nullptr);
|
||||||
if (!m_display)
|
if (!m_display)
|
||||||
{
|
{
|
||||||
PanicAlert("No X11 display found");
|
PanicAlertFmt("No X11 display found");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include "DolphinQt/WiiUpdate.h"
|
#include "DolphinQt/WiiUpdate.h"
|
||||||
|
|
||||||
#include <cinttypes>
|
|
||||||
#include <future>
|
#include <future>
|
||||||
|
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "InputCommon/ControllerInterface/DInput/DInput.h"
|
#include "InputCommon/ControllerInterface/DInput/DInput.h"
|
||||||
|
|
||||||
|
#include "Common/HRWrap.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
|
|
||||||
|
@ -37,13 +38,15 @@ std::string GetDeviceName(const LPDIRECTINPUTDEVICE8 device)
|
||||||
str.diph.dwHow = DIPH_DEVICE;
|
str.diph.dwHow = DIPH_DEVICE;
|
||||||
|
|
||||||
std::string result;
|
std::string result;
|
||||||
if (SUCCEEDED(device->GetProperty(DIPROP_PRODUCTNAME, &str.diph)))
|
HRESULT hr = device->GetProperty(DIPROP_PRODUCTNAME, &str.diph);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
result = StripSpaces(WStringToUTF8(str.wsz));
|
result = StripSpaces(WStringToUTF8(str.wsz));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(CONTROLLERINTERFACE, "GetProperty(DIPROP_PRODUCTNAME) failed.");
|
ERROR_LOG_FMT(CONTROLLERINTERFACE, "GetProperty(DIPROP_PRODUCTNAME) failed: {}",
|
||||||
|
Common::HRWrap(hr));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -52,12 +55,16 @@ std::string GetDeviceName(const LPDIRECTINPUTDEVICE8 device)
|
||||||
// Assumes hwnd had not changed from the previous call
|
// Assumes hwnd had not changed from the previous call
|
||||||
void PopulateDevices(HWND hwnd)
|
void PopulateDevices(HWND hwnd)
|
||||||
{
|
{
|
||||||
if (!s_idi8 && FAILED(DirectInput8Create(GetModuleHandle(nullptr), DIRECTINPUT_VERSION,
|
if (!s_idi8)
|
||||||
IID_IDirectInput8, (LPVOID*)&s_idi8, nullptr)))
|
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(CONTROLLERINTERFACE, "DirectInput8Create failed.");
|
HRESULT hr = DirectInput8Create(GetModuleHandle(nullptr), DIRECTINPUT_VERSION,
|
||||||
|
IID_IDirectInput8, (LPVOID*)&s_idi8, nullptr);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(CONTROLLERINTERFACE, "DirectInput8Create failed: {}", Common::HRWrap(hr));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Remove old (invalid) devices. No need to ever remove the KeyboardMouse device.
|
// Remove old (invalid) devices. No need to ever remove the KeyboardMouse device.
|
||||||
// Note that if we have 2+ DInput controllers, not fully repopulating devices
|
// Note that if we have 2+ DInput controllers, not fully repopulating devices
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "Common/HRWrap.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||||
#include "InputCommon/ControllerInterface/DInput/DInput.h"
|
#include "InputCommon/ControllerInterface/DInput/DInput.h"
|
||||||
|
@ -62,12 +63,14 @@ void InitJoystick(IDirectInput8* const idi8, HWND hwnd)
|
||||||
{
|
{
|
||||||
if (SUCCEEDED(js_device->SetDataFormat(&c_dfDIJoystick)))
|
if (SUCCEEDED(js_device->SetDataFormat(&c_dfDIJoystick)))
|
||||||
{
|
{
|
||||||
if (FAILED(js_device->SetCooperativeLevel(GetAncestor(hwnd, GA_ROOT),
|
HRESULT hr = js_device->SetCooperativeLevel(GetAncestor(hwnd, GA_ROOT),
|
||||||
DISCL_BACKGROUND | DISCL_EXCLUSIVE)))
|
DISCL_BACKGROUND | DISCL_EXCLUSIVE);
|
||||||
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
WARN_LOG_FMT(
|
WARN_LOG_FMT(CONTROLLERINTERFACE,
|
||||||
CONTROLLERINTERFACE,
|
"DInput: Failed to acquire device exclusively. Force feedback will be "
|
||||||
"DInput: Failed to acquire device exclusively. Force feedback will be unavailable.");
|
"unavailable. {}",
|
||||||
|
Common::HRWrap(hr));
|
||||||
// Fall back to non-exclusive mode, with no rumble
|
// Fall back to non-exclusive mode, with no rumble
|
||||||
if (FAILED(
|
if (FAILED(
|
||||||
js_device->SetCooperativeLevel(nullptr, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE)))
|
js_device->SetCooperativeLevel(nullptr, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE)))
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "Common/Flag.h"
|
#include "Common/Flag.h"
|
||||||
|
#include "Common/HRWrap.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/ScopeGuard.h"
|
#include "Common/ScopeGuard.h"
|
||||||
#include "Common/Thread.h"
|
#include "Common/Thread.h"
|
||||||
|
@ -61,9 +62,10 @@ void ciface::Win32::Init(void* hwnd)
|
||||||
HWND message_window = nullptr;
|
HWND message_window = nullptr;
|
||||||
Common::ScopeGuard promise_guard([&] { message_window_promise.set_value(message_window); });
|
Common::ScopeGuard promise_guard([&] { message_window_promise.set_value(message_window); });
|
||||||
|
|
||||||
if (FAILED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED)))
|
HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
||||||
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(CONTROLLERINTERFACE, "CoInitializeEx failed: {}", GetLastError());
|
ERROR_LOG_FMT(CONTROLLERINTERFACE, "CoInitializeEx failed: {}", Common::HRWrap(hr));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Common::ScopeGuard uninit([] { CoUninitialize(); });
|
Common::ScopeGuard uninit([] { CoUninitialize(); });
|
||||||
|
@ -77,12 +79,14 @@ void ciface::Win32::Init(void* hwnd)
|
||||||
ATOM window_class = RegisterClassEx(&window_class_info);
|
ATOM window_class = RegisterClassEx(&window_class_info);
|
||||||
if (!window_class)
|
if (!window_class)
|
||||||
{
|
{
|
||||||
NOTICE_LOG_FMT(CONTROLLERINTERFACE, "RegisterClassEx failed: {}", GetLastError());
|
NOTICE_LOG_FMT(CONTROLLERINTERFACE, "RegisterClassEx failed: {}",
|
||||||
|
Common::HRWrap(GetLastError()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Common::ScopeGuard unregister([&window_class] {
|
Common::ScopeGuard unregister([&window_class] {
|
||||||
if (!UnregisterClass(MAKEINTATOM(window_class), GetModuleHandle(nullptr)))
|
if (!UnregisterClass(MAKEINTATOM(window_class), GetModuleHandle(nullptr)))
|
||||||
ERROR_LOG_FMT(CONTROLLERINTERFACE, "UnregisterClass failed: {}", GetLastError());
|
ERROR_LOG_FMT(CONTROLLERINTERFACE, "UnregisterClass failed: {}",
|
||||||
|
Common::HRWrap(GetLastError()));
|
||||||
});
|
});
|
||||||
|
|
||||||
message_window = CreateWindowEx(0, L"Message", nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr,
|
message_window = CreateWindowEx(0, L"Message", nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr,
|
||||||
|
@ -90,12 +94,14 @@ void ciface::Win32::Init(void* hwnd)
|
||||||
promise_guard.Exit();
|
promise_guard.Exit();
|
||||||
if (!message_window)
|
if (!message_window)
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(CONTROLLERINTERFACE, "CreateWindowEx failed: {}", GetLastError());
|
ERROR_LOG_FMT(CONTROLLERINTERFACE, "CreateWindowEx failed: {}",
|
||||||
|
Common::HRWrap(GetLastError()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Common::ScopeGuard destroy([&] {
|
Common::ScopeGuard destroy([&] {
|
||||||
if (!DestroyWindow(message_window))
|
if (!DestroyWindow(message_window))
|
||||||
ERROR_LOG_FMT(CONTROLLERINTERFACE, "DestroyWindow failed: {}", GetLastError());
|
ERROR_LOG_FMT(CONTROLLERINTERFACE, "DestroyWindow failed: {}",
|
||||||
|
Common::HRWrap(GetLastError()));
|
||||||
});
|
});
|
||||||
|
|
||||||
std::array<RAWINPUTDEVICE, 2> devices;
|
std::array<RAWINPUTDEVICE, 2> devices;
|
||||||
|
|
|
@ -296,7 +296,7 @@ static void HotplugThreadFunc()
|
||||||
udev* const udev = udev_new();
|
udev* const udev = udev_new();
|
||||||
Common::ScopeGuard udev_guard([udev] { udev_unref(udev); });
|
Common::ScopeGuard udev_guard([udev] { udev_unref(udev); });
|
||||||
|
|
||||||
ASSERT_MSG(PAD, udev != nullptr, "Couldn't initialize libudev.");
|
ASSERT_MSG(CONTROLLERINTERFACE, udev != nullptr, "Couldn't initialize libudev.");
|
||||||
|
|
||||||
// Set up monitoring
|
// Set up monitoring
|
||||||
udev_monitor* const monitor = udev_monitor_new_from_netlink(udev, "udev");
|
udev_monitor* const monitor = udev_monitor_new_from_netlink(udev, "udev");
|
||||||
|
@ -366,7 +366,7 @@ static void StartHotplugThread()
|
||||||
}
|
}
|
||||||
|
|
||||||
s_wakeup_eventfd = eventfd(0, 0);
|
s_wakeup_eventfd = eventfd(0, 0);
|
||||||
ASSERT_MSG(PAD, s_wakeup_eventfd != -1, "Couldn't create eventfd.");
|
ASSERT_MSG(CONTROLLERINTERFACE, s_wakeup_eventfd != -1, "Couldn't create eventfd.");
|
||||||
s_hotplug_thread = std::thread(HotplugThreadFunc);
|
s_hotplug_thread = std::thread(HotplugThreadFunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,7 +406,7 @@ void PopulateDevices()
|
||||||
// this ever changes, hopefully udev will take care of this.
|
// this ever changes, hopefully udev will take care of this.
|
||||||
|
|
||||||
udev* const udev = udev_new();
|
udev* const udev = udev_new();
|
||||||
ASSERT_MSG(PAD, udev != nullptr, "Couldn't initialize libudev.");
|
ASSERT_MSG(CONTROLLERINTERFACE, udev != nullptr, "Couldn't initialize libudev.");
|
||||||
|
|
||||||
// List all input devices
|
// List all input devices
|
||||||
udev_enumerate* const enumerate = udev_enumerate_new(udev);
|
udev_enumerate* const enumerate = udev_enumerate_new(udev);
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cinttypes>
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
|
@ -66,7 +66,7 @@ bool Create(u32 adapter_index, bool enable_debug_layer)
|
||||||
HRESULT hr = dxgi_factory->EnumAdapters(adapter_index, adapter.GetAddressOf());
|
HRESULT hr = dxgi_factory->EnumAdapters(adapter_index, adapter.GetAddressOf());
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
WARN_LOG_FMT(VIDEO, "Adapter {} not found, using default", adapter_index);
|
WARN_LOG_FMT(VIDEO, "Adapter {} not found, using default: {}", adapter_index, DX11HRWrap(hr));
|
||||||
adapter = nullptr;
|
adapter = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ bool Create(u32 adapter_index, bool enable_debug_layer)
|
||||||
D3D11_SDK_VERSION, device.GetAddressOf(), &feature_level, context.GetAddressOf());
|
D3D11_SDK_VERSION, device.GetAddressOf(), &feature_level, context.GetAddressOf());
|
||||||
|
|
||||||
// Debugbreak on D3D error
|
// Debugbreak on D3D error
|
||||||
if (SUCCEEDED(hr) && SUCCEEDED(device.As(&s_debug)))
|
if (SUCCEEDED(hr) && SUCCEEDED(hr = device.As(&s_debug)))
|
||||||
{
|
{
|
||||||
ComPtr<ID3D11InfoQueue> info_queue;
|
ComPtr<ID3D11InfoQueue> info_queue;
|
||||||
if (SUCCEEDED(s_debug.As(&info_queue)))
|
if (SUCCEEDED(s_debug.As(&info_queue)))
|
||||||
|
@ -98,7 +98,7 @@ bool Create(u32 adapter_index, bool enable_debug_layer)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WARN_LOG_FMT(VIDEO, "Debug layer requested but not available.");
|
WARN_LOG_FMT(VIDEO, "Debug layer requested but not available: {}", DX11HRWrap(hr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +113,8 @@ bool Create(u32 adapter_index, bool enable_debug_layer)
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
PanicAlertFmtT(
|
PanicAlertFmtT(
|
||||||
"Failed to initialize Direct3D.\nMake sure your video card supports at least D3D 10.0");
|
"Failed to initialize Direct3D.\nMake sure your video card supports at least D3D 10.0\n{0}",
|
||||||
|
DX11HRWrap(hr));
|
||||||
dxgi_factory.Reset();
|
dxgi_factory.Reset();
|
||||||
D3DCommon::UnloadLibraries();
|
D3DCommon::UnloadLibraries();
|
||||||
s_d3d11_library.Close();
|
s_d3d11_library.Close();
|
||||||
|
@ -123,7 +124,9 @@ bool Create(u32 adapter_index, bool enable_debug_layer)
|
||||||
hr = device.As(&device1);
|
hr = device.As(&device1);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
WARN_LOG_FMT(VIDEO, "Missing Direct3D 11.1 support. Logical operations will not be supported.");
|
WARN_LOG_FMT(VIDEO,
|
||||||
|
"Missing Direct3D 11.1 support. Logical operations will not be supported.\n{}",
|
||||||
|
DX11HRWrap(hr));
|
||||||
}
|
}
|
||||||
|
|
||||||
stateman = std::make_unique<StateManager>();
|
stateman = std::make_unique<StateManager>();
|
||||||
|
|
|
@ -7,12 +7,12 @@
|
||||||
#include <d3d11_1.h>
|
#include <d3d11_1.h>
|
||||||
#include <d3dcompiler.h>
|
#include <d3dcompiler.h>
|
||||||
#include <dxgi1_5.h>
|
#include <dxgi1_5.h>
|
||||||
|
#include <fmt/format.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <wrl/client.h>
|
#include <wrl/client.h>
|
||||||
|
|
||||||
#include "Common/Common.h"
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/MsgHandler.h"
|
#include "Common/HRWrap.h"
|
||||||
|
|
||||||
namespace DX11
|
namespace DX11
|
||||||
{
|
{
|
||||||
|
@ -41,4 +41,32 @@ bool SupportsLogicOp(u32 adapter_index);
|
||||||
|
|
||||||
} // namespace D3D
|
} // namespace D3D
|
||||||
|
|
||||||
|
// Wrapper for HRESULT to be used with fmt. Note that we can't create a fmt::formatter directly
|
||||||
|
// for HRESULT as HRESULT is simply a typedef on long and not a distinct type.
|
||||||
|
// Unlike the version in Common, this variant also knows to call GetDeviceRemovedReason if needed.
|
||||||
|
struct DX11HRWrap
|
||||||
|
{
|
||||||
|
constexpr explicit DX11HRWrap(HRESULT hr) : m_hr(hr) {}
|
||||||
|
const HRESULT m_hr;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace DX11
|
} // namespace DX11
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct fmt::formatter<DX11::DX11HRWrap>
|
||||||
|
{
|
||||||
|
constexpr auto parse(fmt::format_parse_context& ctx) { return ctx.begin(); }
|
||||||
|
template <typename FormatContext>
|
||||||
|
auto format(const DX11::DX11HRWrap& hr, FormatContext& ctx)
|
||||||
|
{
|
||||||
|
if (hr.m_hr == DXGI_ERROR_DEVICE_REMOVED && DX11::D3D::device != nullptr)
|
||||||
|
{
|
||||||
|
return fmt::format_to(ctx.out(), "{}\nDevice removal reason: {}", Common::HRWrap(hr.m_hr),
|
||||||
|
Common::HRWrap(DX11::D3D::device->GetDeviceRemovedReason()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return fmt::format_to(ctx.out(), "{}", Common::HRWrap(hr.m_hr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -6,8 +6,10 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
#include "Common/Assert.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/MsgHandler.h"
|
#include "Common/MsgHandler.h"
|
||||||
|
|
||||||
#include "VideoBackends/D3D/D3DState.h"
|
#include "VideoBackends/D3D/D3DState.h"
|
||||||
#include "VideoBackends/D3DCommon/D3DCommon.h"
|
#include "VideoBackends/D3DCommon/D3DCommon.h"
|
||||||
|
|
||||||
|
@ -33,7 +35,7 @@ bool D3DBoundingBox::Initialize()
|
||||||
data.SysMemSlicePitch = 0;
|
data.SysMemSlicePitch = 0;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
hr = D3D::device->CreateBuffer(&desc, &data, &m_buffer);
|
hr = D3D::device->CreateBuffer(&desc, &data, &m_buffer);
|
||||||
CHECK(SUCCEEDED(hr), "Create BoundingBox Buffer.");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create BoundingBox Buffer: {}", DX11HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
D3DCommon::SetDebugObjectName(m_buffer.Get(), "BoundingBox Buffer");
|
D3DCommon::SetDebugObjectName(m_buffer.Get(), "BoundingBox Buffer");
|
||||||
|
@ -43,7 +45,8 @@ bool D3DBoundingBox::Initialize()
|
||||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||||
desc.BindFlags = 0;
|
desc.BindFlags = 0;
|
||||||
hr = D3D::device->CreateBuffer(&desc, nullptr, &m_staging_buffer);
|
hr = D3D::device->CreateBuffer(&desc, nullptr, &m_staging_buffer);
|
||||||
CHECK(SUCCEEDED(hr), "Create BoundingBox Staging Buffer.");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create BoundingBox Staging Buffer: {}",
|
||||||
|
DX11HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
D3DCommon::SetDebugObjectName(m_staging_buffer.Get(), "BoundingBox Staging Buffer");
|
D3DCommon::SetDebugObjectName(m_staging_buffer.Get(), "BoundingBox Staging Buffer");
|
||||||
|
@ -56,7 +59,7 @@ bool D3DBoundingBox::Initialize()
|
||||||
UAVdesc.Buffer.Flags = 0;
|
UAVdesc.Buffer.Flags = 0;
|
||||||
UAVdesc.Buffer.NumElements = NUM_BBOX_VALUES;
|
UAVdesc.Buffer.NumElements = NUM_BBOX_VALUES;
|
||||||
hr = D3D::device->CreateUnorderedAccessView(m_buffer.Get(), &UAVdesc, &m_uav);
|
hr = D3D::device->CreateUnorderedAccessView(m_buffer.Get(), &UAVdesc, &m_uav);
|
||||||
CHECK(SUCCEEDED(hr), "Create BoundingBox UAV.");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create BoundingBox UAV: {}", DX11HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
D3DCommon::SetDebugObjectName(m_uav.Get(), "BoundingBox UAV");
|
D3DCommon::SetDebugObjectName(m_uav.Get(), "BoundingBox UAV");
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
#include "Common/Assert.h"
|
||||||
#include "Common/EnumMap.h"
|
#include "Common/EnumMap.h"
|
||||||
|
|
||||||
#include "VideoBackends/D3D/D3DBase.h"
|
#include "VideoBackends/D3D/D3DBase.h"
|
||||||
|
@ -182,7 +183,7 @@ ID3D11InputLayout* D3DVertexFormat::GetInputLayout(const void* vs_bytecode, size
|
||||||
|
|
||||||
HRESULT hr = D3D::device->CreateInputLayout(m_elems.data(), m_num_elems, vs_bytecode,
|
HRESULT hr = D3D::device->CreateInputLayout(m_elems.data(), m_num_elems, vs_bytecode,
|
||||||
vs_bytecode_size, &layout);
|
vs_bytecode_size, &layout);
|
||||||
CHECK(SUCCEEDED(hr), "Failed to create input layout");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create input layout: {}", DX11HRWrap(hr));
|
||||||
|
|
||||||
// This method can be called from multiple threads, so ensure that only one thread sets the
|
// This method can be called from multiple threads, so ensure that only one thread sets the
|
||||||
// cached input layout pointer. If another thread beats this thread, use the existing layout.
|
// cached input layout pointer. If another thread beats this thread, use the existing layout.
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cinttypes>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
#include "Common/Assert.h"
|
||||||
#include "Common/BitSet.h"
|
#include "Common/BitSet.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
|
@ -348,7 +349,7 @@ ID3D11SamplerState* StateCache::Get(SamplerState state)
|
||||||
|
|
||||||
ComPtr<ID3D11SamplerState> res;
|
ComPtr<ID3D11SamplerState> res;
|
||||||
HRESULT hr = D3D::device->CreateSamplerState(&sampdc, res.GetAddressOf());
|
HRESULT hr = D3D::device->CreateSamplerState(&sampdc, res.GetAddressOf());
|
||||||
CHECK(SUCCEEDED(hr), "Creating D3D sampler state failed");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Creating D3D sampler state failed: {}", DX11HRWrap(hr));
|
||||||
return m_sampler.emplace(state, std::move(res)).first->second.Get();
|
return m_sampler.emplace(state, std::move(res)).first->second.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,7 +387,7 @@ ID3D11BlendState* StateCache::Get(BlendingState state)
|
||||||
{
|
{
|
||||||
return m_blend.emplace(state.hex, std::move(res)).first->second.Get();
|
return m_blend.emplace(state.hex, std::move(res)).first->second.Get();
|
||||||
}
|
}
|
||||||
WARN_LOG_FMT(VIDEO, "Creating D3D blend state failed with an error: {:08X}", hr);
|
WARN_LOG_FMT(VIDEO, "Creating D3D blend state failed with an error: {}", DX11HRWrap(hr));
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D11_BLEND_DESC desc = {};
|
D3D11_BLEND_DESC desc = {};
|
||||||
|
@ -425,7 +426,7 @@ ID3D11BlendState* StateCache::Get(BlendingState state)
|
||||||
|
|
||||||
ComPtr<ID3D11BlendState> res;
|
ComPtr<ID3D11BlendState> res;
|
||||||
HRESULT hr = D3D::device->CreateBlendState(&desc, res.GetAddressOf());
|
HRESULT hr = D3D::device->CreateBlendState(&desc, res.GetAddressOf());
|
||||||
CHECK(SUCCEEDED(hr), "Creating D3D blend state failed");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Creating D3D blend state failed: {}", DX11HRWrap(hr));
|
||||||
return m_blend.emplace(state.hex, std::move(res)).first->second.Get();
|
return m_blend.emplace(state.hex, std::move(res)).first->second.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,7 +447,7 @@ ID3D11RasterizerState* StateCache::Get(RasterizationState state)
|
||||||
|
|
||||||
ComPtr<ID3D11RasterizerState> res;
|
ComPtr<ID3D11RasterizerState> res;
|
||||||
HRESULT hr = D3D::device->CreateRasterizerState(&desc, res.GetAddressOf());
|
HRESULT hr = D3D::device->CreateRasterizerState(&desc, res.GetAddressOf());
|
||||||
CHECK(SUCCEEDED(hr), "Creating D3D rasterizer state failed");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Creating D3D rasterizer state failed: {}", DX11HRWrap(hr));
|
||||||
return m_raster.emplace(state.hex, std::move(res)).first->second.Get();
|
return m_raster.emplace(state.hex, std::move(res)).first->second.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,7 +489,7 @@ ID3D11DepthStencilState* StateCache::Get(DepthState state)
|
||||||
|
|
||||||
ComPtr<ID3D11DepthStencilState> res;
|
ComPtr<ID3D11DepthStencilState> res;
|
||||||
HRESULT hr = D3D::device->CreateDepthStencilState(&depthdc, res.GetAddressOf());
|
HRESULT hr = D3D::device->CreateDepthStencilState(&depthdc, res.GetAddressOf());
|
||||||
CHECK(SUCCEEDED(hr), "Creating D3D depth stencil state failed");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Creating D3D depth stencil state failed: {}", DX11HRWrap(hr));
|
||||||
return m_depth.emplace(state.hex, std::move(res)).first->second.Get();
|
return m_depth.emplace(state.hex, std::move(res)).first->second.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include "VideoBackends/D3D/D3DSwapChain.h"
|
#include "VideoBackends/D3D/D3DSwapChain.h"
|
||||||
|
|
||||||
|
#include "Common/Assert.h"
|
||||||
|
|
||||||
#include "VideoBackends/D3D/DXTexture.h"
|
#include "VideoBackends/D3D/DXTexture.h"
|
||||||
|
|
||||||
namespace DX11
|
namespace DX11
|
||||||
|
@ -29,7 +31,7 @@ bool SwapChain::CreateSwapChainBuffers()
|
||||||
{
|
{
|
||||||
ComPtr<ID3D11Texture2D> texture;
|
ComPtr<ID3D11Texture2D> texture;
|
||||||
HRESULT hr = m_swap_chain->GetBuffer(0, IID_PPV_ARGS(&texture));
|
HRESULT hr = m_swap_chain->GetBuffer(0, IID_PPV_ARGS(&texture));
|
||||||
CHECK(SUCCEEDED(hr), "Get swap chain buffer");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to get swap chain buffer: {}", DX11HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,8 @@ static ComPtr<ID3D11Buffer> AllocateConstantBuffer(u32 size)
|
||||||
D3D11_CPU_ACCESS_WRITE);
|
D3D11_CPU_ACCESS_WRITE);
|
||||||
ComPtr<ID3D11Buffer> cbuf;
|
ComPtr<ID3D11Buffer> cbuf;
|
||||||
const HRESULT hr = D3D::device->CreateBuffer(&cbdesc, nullptr, &cbuf);
|
const HRESULT hr = D3D::device->CreateBuffer(&cbdesc, nullptr, &cbuf);
|
||||||
CHECK(SUCCEEDED(hr), "shader constant buffer (size=%u)", cbsize);
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create shader constant buffer (size={}): {}", cbsize,
|
||||||
|
DX11HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -59,8 +60,8 @@ CreateTexelBufferView(ID3D11Buffer* buffer, TexelBufferFormat format, DXGI_FORMA
|
||||||
CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(buffer, srv_format, 0,
|
CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(buffer, srv_format, 0,
|
||||||
VertexManager::TEXEL_STREAM_BUFFER_SIZE /
|
VertexManager::TEXEL_STREAM_BUFFER_SIZE /
|
||||||
VertexManager::GetTexelBufferElementSize(format));
|
VertexManager::GetTexelBufferElementSize(format));
|
||||||
CHECK(SUCCEEDED(D3D::device->CreateShaderResourceView(buffer, &srv_desc, &srv)),
|
HRESULT hr = D3D::device->CreateShaderResourceView(buffer, &srv_desc, &srv);
|
||||||
"Create SRV for texel buffer");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create SRV for texel buffer: {}", DX11HRWrap(hr));
|
||||||
return srv;
|
return srv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,8 +80,8 @@ bool VertexManager::Initialize()
|
||||||
|
|
||||||
for (int i = 0; i < BUFFER_COUNT; i++)
|
for (int i = 0; i < BUFFER_COUNT; i++)
|
||||||
{
|
{
|
||||||
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&bufdesc, nullptr, &m_buffers[i])),
|
HRESULT hr = D3D::device->CreateBuffer(&bufdesc, nullptr, &m_buffers[i]);
|
||||||
"Failed to create buffer.");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create buffer: {}", DX11HRWrap(hr));
|
||||||
if (m_buffers[i])
|
if (m_buffers[i])
|
||||||
D3DCommon::SetDebugObjectName(m_buffers[i].Get(), "Buffer of VertexManager");
|
D3DCommon::SetDebugObjectName(m_buffers[i].Get(), "Buffer of VertexManager");
|
||||||
}
|
}
|
||||||
|
@ -93,8 +94,8 @@ bool VertexManager::Initialize()
|
||||||
|
|
||||||
CD3D11_BUFFER_DESC texel_buf_desc(TEXEL_STREAM_BUFFER_SIZE, D3D11_BIND_SHADER_RESOURCE,
|
CD3D11_BUFFER_DESC texel_buf_desc(TEXEL_STREAM_BUFFER_SIZE, D3D11_BIND_SHADER_RESOURCE,
|
||||||
D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
|
D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
|
||||||
CHECK(SUCCEEDED(D3D::device->CreateBuffer(&texel_buf_desc, nullptr, &m_texel_buffer)),
|
HRESULT hr = D3D::device->CreateBuffer(&texel_buf_desc, nullptr, &m_texel_buffer);
|
||||||
"Creating texel buffer failed");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Creating texel buffer failed: {}", DX11HRWrap(hr));
|
||||||
if (!m_texel_buffer)
|
if (!m_texel_buffer)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -132,7 +133,7 @@ bool VertexManager::MapTexelBuffer(u32 required_size, D3D11_MAPPED_SUBRESOURCE&
|
||||||
{
|
{
|
||||||
// Restart buffer.
|
// Restart buffer.
|
||||||
HRESULT hr = D3D::context->Map(m_texel_buffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &sr);
|
HRESULT hr = D3D::context->Map(m_texel_buffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &sr);
|
||||||
CHECK(SUCCEEDED(hr), "Map texel buffer");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to map texel buffer: {}", DX11HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -142,7 +143,7 @@ bool VertexManager::MapTexelBuffer(u32 required_size, D3D11_MAPPED_SUBRESOURCE&
|
||||||
{
|
{
|
||||||
// Don't overwrite the earlier-used space.
|
// Don't overwrite the earlier-used space.
|
||||||
HRESULT hr = D3D::context->Map(m_texel_buffer.Get(), 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &sr);
|
HRESULT hr = D3D::context->Map(m_texel_buffer.Get(), 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &sr);
|
||||||
CHECK(SUCCEEDED(hr), "Map texel buffer");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to map texel buffer: {}", DX11HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ std::unique_ptr<DXShader> DXShader::CreateFromBytecode(ShaderStage stage, Binary
|
||||||
{
|
{
|
||||||
ComPtr<ID3D11VertexShader> vs;
|
ComPtr<ID3D11VertexShader> vs;
|
||||||
HRESULT hr = D3D::device->CreateVertexShader(bytecode.data(), bytecode.size(), nullptr, &vs);
|
HRESULT hr = D3D::device->CreateVertexShader(bytecode.data(), bytecode.size(), nullptr, &vs);
|
||||||
CHECK(SUCCEEDED(hr), "Create vertex shader");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create vertex shader: {}", DX11HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ std::unique_ptr<DXShader> DXShader::CreateFromBytecode(ShaderStage stage, Binary
|
||||||
{
|
{
|
||||||
ComPtr<ID3D11GeometryShader> gs;
|
ComPtr<ID3D11GeometryShader> gs;
|
||||||
HRESULT hr = D3D::device->CreateGeometryShader(bytecode.data(), bytecode.size(), nullptr, &gs);
|
HRESULT hr = D3D::device->CreateGeometryShader(bytecode.data(), bytecode.size(), nullptr, &gs);
|
||||||
CHECK(SUCCEEDED(hr), "Create geometry shader");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create geometry shader: {}", DX11HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ std::unique_ptr<DXShader> DXShader::CreateFromBytecode(ShaderStage stage, Binary
|
||||||
{
|
{
|
||||||
ComPtr<ID3D11PixelShader> ps;
|
ComPtr<ID3D11PixelShader> ps;
|
||||||
HRESULT hr = D3D::device->CreatePixelShader(bytecode.data(), bytecode.size(), nullptr, &ps);
|
HRESULT hr = D3D::device->CreatePixelShader(bytecode.data(), bytecode.size(), nullptr, &ps);
|
||||||
CHECK(SUCCEEDED(hr), "Create pixel shader");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create pixel shader: {}", DX11HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ std::unique_ptr<DXShader> DXShader::CreateFromBytecode(ShaderStage stage, Binary
|
||||||
{
|
{
|
||||||
ComPtr<ID3D11ComputeShader> cs;
|
ComPtr<ID3D11ComputeShader> cs;
|
||||||
HRESULT hr = D3D::device->CreateComputeShader(bytecode.data(), bytecode.size(), nullptr, &cs);
|
HRESULT hr = D3D::device->CreateComputeShader(bytecode.data(), bytecode.size(), nullptr, &cs);
|
||||||
CHECK(SUCCEEDED(hr), "Create compute shader");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create compute shader: {}", DX11HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
|
|
@ -51,8 +51,8 @@ std::unique_ptr<DXTexture> DXTexture::Create(const TextureConfig& config, std::s
|
||||||
HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, d3d_texture.GetAddressOf());
|
HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, d3d_texture.GetAddressOf());
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
PanicAlertFmt("Failed to create {}x{}x{} D3D backing texture", config.width, config.height,
|
PanicAlertFmt("Failed to create {}x{}x{} D3D backing texture: {}", config.width, config.height,
|
||||||
config.layers);
|
config.layers, DX11HRWrap(hr));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,8 +98,8 @@ bool DXTexture::CreateSRV()
|
||||||
HRESULT hr = D3D::device->CreateShaderResourceView(m_texture.Get(), &desc, m_srv.GetAddressOf());
|
HRESULT hr = D3D::device->CreateShaderResourceView(m_texture.Get(), &desc, m_srv.GetAddressOf());
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
PanicAlertFmt("Failed to create {}x{}x{} D3D SRV", m_config.width, m_config.height,
|
PanicAlertFmt("Failed to create {}x{}x{} D3D SRV: {}", m_config.width, m_config.height,
|
||||||
m_config.layers);
|
m_config.layers, DX11HRWrap(hr));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,8 +115,8 @@ bool DXTexture::CreateUAV()
|
||||||
HRESULT hr = D3D::device->CreateUnorderedAccessView(m_texture.Get(), &desc, m_uav.GetAddressOf());
|
HRESULT hr = D3D::device->CreateUnorderedAccessView(m_texture.Get(), &desc, m_uav.GetAddressOf());
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
PanicAlertFmt("Failed to create {}x{}x{} D3D UAV", m_config.width, m_config.height,
|
PanicAlertFmt("Failed to create {}x{}x{} D3D UAV: {}", m_config.width, m_config.height,
|
||||||
m_config.layers);
|
m_config.layers, DX11HRWrap(hr));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ std::unique_ptr<DXStagingTexture> DXStagingTexture::Create(StagingTextureType ty
|
||||||
|
|
||||||
ComPtr<ID3D11Texture2D> texture;
|
ComPtr<ID3D11Texture2D> texture;
|
||||||
HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, texture.GetAddressOf());
|
HRESULT hr = D3D::device->CreateTexture2D(&desc, nullptr, texture.GetAddressOf());
|
||||||
CHECK(SUCCEEDED(hr), "Create staging texture");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create staging texture: {}", DX11HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -298,7 +298,7 @@ bool DXStagingTexture::Map()
|
||||||
|
|
||||||
D3D11_MAPPED_SUBRESOURCE sr;
|
D3D11_MAPPED_SUBRESOURCE sr;
|
||||||
HRESULT hr = D3D::context->Map(m_tex.Get(), 0, map_type, 0, &sr);
|
HRESULT hr = D3D::context->Map(m_tex.Get(), 0, map_type, 0, &sr);
|
||||||
CHECK(SUCCEEDED(hr), "Map readback texture");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to map readback texture: {}", DX11HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -363,7 +363,8 @@ std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(DXTexture* color_attachment
|
||||||
color_attachment->GetLayers());
|
color_attachment->GetLayers());
|
||||||
HRESULT hr = D3D::device->CreateRenderTargetView(color_attachment->GetD3DTexture(), &desc,
|
HRESULT hr = D3D::device->CreateRenderTargetView(color_attachment->GetD3DTexture(), &desc,
|
||||||
rtv.GetAddressOf());
|
rtv.GetAddressOf());
|
||||||
CHECK(SUCCEEDED(hr), "Create render target view for framebuffer");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create render target view for framebuffer: {}",
|
||||||
|
DX11HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -375,7 +376,8 @@ std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(DXTexture* color_attachment
|
||||||
desc.Format = integer_format;
|
desc.Format = integer_format;
|
||||||
hr = D3D::device->CreateRenderTargetView(color_attachment->GetD3DTexture(), &desc,
|
hr = D3D::device->CreateRenderTargetView(color_attachment->GetD3DTexture(), &desc,
|
||||||
integer_rtv.GetAddressOf());
|
integer_rtv.GetAddressOf());
|
||||||
CHECK(SUCCEEDED(hr), "Create integer render target view for framebuffer");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr),
|
||||||
|
"Failed to create integer render target view for framebuffer: {}", DX11HRWrap(hr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,7 +391,8 @@ std::unique_ptr<DXFramebuffer> DXFramebuffer::Create(DXTexture* color_attachment
|
||||||
depth_attachment->GetLayers(), 0);
|
depth_attachment->GetLayers(), 0);
|
||||||
HRESULT hr = D3D::device->CreateDepthStencilView(depth_attachment->GetD3DTexture(), &desc,
|
HRESULT hr = D3D::device->CreateDepthStencilView(depth_attachment->GetD3DTexture(), &desc,
|
||||||
dsv.GetAddressOf());
|
dsv.GetAddressOf());
|
||||||
CHECK(SUCCEEDED(hr), "Create depth stencil view for framebuffer");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create depth stencil view for framebuffer: {}",
|
||||||
|
DX11HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "VideoBackends/D3D12/D3D12BoundingBox.h"
|
#include "VideoBackends/D3D12/D3D12BoundingBox.h"
|
||||||
|
|
||||||
|
#include "Common/Assert.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
|
|
||||||
#include "VideoBackends/D3D12/D3D12Renderer.h"
|
#include "VideoBackends/D3D12/D3D12Renderer.h"
|
||||||
|
@ -41,7 +42,7 @@ std::vector<BBoxType> D3D12BoundingBox::Read(u32 index, u32 length)
|
||||||
static constexpr D3D12_RANGE read_range = {0, BUFFER_SIZE};
|
static constexpr D3D12_RANGE read_range = {0, BUFFER_SIZE};
|
||||||
void* mapped_pointer;
|
void* mapped_pointer;
|
||||||
HRESULT hr = m_readback_buffer->Map(0, &read_range, &mapped_pointer);
|
HRESULT hr = m_readback_buffer->Map(0, &read_range, &mapped_pointer);
|
||||||
CHECK(SUCCEEDED(hr), "Map bounding box CPU buffer");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Map bounding box CPU buffer failed: {}", DX12HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return values;
|
return values;
|
||||||
|
|
||||||
|
@ -102,7 +103,7 @@ bool D3D12BoundingBox::CreateBuffers()
|
||||||
HRESULT hr = g_dx_context->GetDevice()->CreateCommittedResource(
|
HRESULT hr = g_dx_context->GetDevice()->CreateCommittedResource(
|
||||||
&gpu_heap_properties, D3D12_HEAP_FLAG_NONE, &buffer_desc,
|
&gpu_heap_properties, D3D12_HEAP_FLAG_NONE, &buffer_desc,
|
||||||
D3D12_RESOURCE_STATE_UNORDERED_ACCESS, nullptr, IID_PPV_ARGS(&m_gpu_buffer));
|
D3D12_RESOURCE_STATE_UNORDERED_ACCESS, nullptr, IID_PPV_ARGS(&m_gpu_buffer));
|
||||||
CHECK(SUCCEEDED(hr), "Creating bounding box GPU buffer failed");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Creating bounding box GPU buffer failed: {}", DX12HRWrap(hr));
|
||||||
if (FAILED(hr) || !g_dx_context->GetDescriptorHeapManager().Allocate(&m_gpu_descriptor))
|
if (FAILED(hr) || !g_dx_context->GetDescriptorHeapManager().Allocate(&m_gpu_descriptor))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -115,7 +116,7 @@ bool D3D12BoundingBox::CreateBuffers()
|
||||||
hr = g_dx_context->GetDevice()->CreateCommittedResource(
|
hr = g_dx_context->GetDevice()->CreateCommittedResource(
|
||||||
&cpu_heap_properties, D3D12_HEAP_FLAG_NONE, &buffer_desc, D3D12_RESOURCE_STATE_COPY_DEST,
|
&cpu_heap_properties, D3D12_HEAP_FLAG_NONE, &buffer_desc, D3D12_RESOURCE_STATE_COPY_DEST,
|
||||||
nullptr, IID_PPV_ARGS(&m_readback_buffer));
|
nullptr, IID_PPV_ARGS(&m_readback_buffer));
|
||||||
CHECK(SUCCEEDED(hr), "Creating bounding box CPU buffer failed");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Creating bounding box CPU buffer failed: {}", DX12HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
|
|
||||||
#include "VideoBackends/D3D12/Common.h"
|
#include "VideoBackends/D3D12/Common.h"
|
||||||
#include "VideoBackends/D3D12/D3D12Renderer.h"
|
#include "VideoBackends/D3D12/D3D12Renderer.h"
|
||||||
#include "VideoBackends/D3D12/DX12Context.h"
|
#include "VideoBackends/D3D12/DX12Context.h"
|
||||||
|
@ -22,7 +23,7 @@ bool PerfQuery::Initialize()
|
||||||
{
|
{
|
||||||
constexpr D3D12_QUERY_HEAP_DESC desc = {D3D12_QUERY_HEAP_TYPE_OCCLUSION, PERF_QUERY_BUFFER_SIZE};
|
constexpr D3D12_QUERY_HEAP_DESC desc = {D3D12_QUERY_HEAP_TYPE_OCCLUSION, PERF_QUERY_BUFFER_SIZE};
|
||||||
HRESULT hr = g_dx_context->GetDevice()->CreateQueryHeap(&desc, IID_PPV_ARGS(&m_query_heap));
|
HRESULT hr = g_dx_context->GetDevice()->CreateQueryHeap(&desc, IID_PPV_ARGS(&m_query_heap));
|
||||||
CHECK(SUCCEEDED(hr), "Failed to create query heap");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create query heap: {}", DX12HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -40,7 +41,7 @@ bool PerfQuery::Initialize()
|
||||||
hr = g_dx_context->GetDevice()->CreateCommittedResource(
|
hr = g_dx_context->GetDevice()->CreateCommittedResource(
|
||||||
&heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc, D3D12_RESOURCE_STATE_COPY_DEST,
|
&heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc, D3D12_RESOURCE_STATE_COPY_DEST,
|
||||||
nullptr, IID_PPV_ARGS(&m_query_readback_buffer));
|
nullptr, IID_PPV_ARGS(&m_query_readback_buffer));
|
||||||
CHECK(SUCCEEDED(hr), "Failed to create query buffer");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create query buffer: {}", DX12HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -220,7 +221,7 @@ void PerfQuery::AccumulateQueriesFromBuffer(u32 query_count)
|
||||||
(m_query_readback_pos + query_count) * sizeof(PerfQueryDataType)};
|
(m_query_readback_pos + query_count) * sizeof(PerfQueryDataType)};
|
||||||
u8* mapped_ptr;
|
u8* mapped_ptr;
|
||||||
HRESULT hr = m_query_readback_buffer->Map(0, &read_range, reinterpret_cast<void**>(&mapped_ptr));
|
HRESULT hr = m_query_readback_buffer->Map(0, &read_range, reinterpret_cast<void**>(&mapped_ptr));
|
||||||
CHECK(SUCCEEDED(hr), "Failed to map query readback buffer");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to map query readback buffer: {}", DX12HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -46,13 +46,14 @@ bool StreamBuffer::AllocateBuffer(u32 size)
|
||||||
HRESULT hr = g_dx_context->GetDevice()->CreateCommittedResource(
|
HRESULT hr = g_dx_context->GetDevice()->CreateCommittedResource(
|
||||||
&heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc, D3D12_RESOURCE_STATE_GENERIC_READ,
|
&heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc, D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||||
nullptr, IID_PPV_ARGS(&m_buffer));
|
nullptr, IID_PPV_ARGS(&m_buffer));
|
||||||
CHECK(SUCCEEDED(hr), "Allocate buffer");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to allocate buffer of size {}: {}", size,
|
||||||
|
DX12HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
static const D3D12_RANGE read_range = {};
|
static const D3D12_RANGE read_range = {};
|
||||||
hr = m_buffer->Map(0, &read_range, reinterpret_cast<void**>(&m_host_pointer));
|
hr = m_buffer->Map(0, &read_range, reinterpret_cast<void**>(&m_host_pointer));
|
||||||
CHECK(SUCCEEDED(hr), "Map buffer");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to map buffer of size {}: {}", size, DX12HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include "VideoBackends/D3D12/D3D12SwapChain.h"
|
#include "VideoBackends/D3D12/D3D12SwapChain.h"
|
||||||
|
|
||||||
|
#include "Common/Assert.h"
|
||||||
|
|
||||||
#include "VideoBackends/D3D12/DX12Context.h"
|
#include "VideoBackends/D3D12/DX12Context.h"
|
||||||
#include "VideoBackends/D3D12/DX12Texture.h"
|
#include "VideoBackends/D3D12/DX12Texture.h"
|
||||||
|
|
||||||
|
@ -32,16 +34,17 @@ bool SwapChain::CreateSwapChainBuffers()
|
||||||
{
|
{
|
||||||
ComPtr<ID3D12Resource> resource;
|
ComPtr<ID3D12Resource> resource;
|
||||||
HRESULT hr = m_swap_chain->GetBuffer(i, IID_PPV_ARGS(&resource));
|
HRESULT hr = m_swap_chain->GetBuffer(i, IID_PPV_ARGS(&resource));
|
||||||
CHECK(SUCCEEDED(hr), "Get swap chain buffer");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to get swap chain buffer {}: {}", i, DX12HRWrap(hr));
|
||||||
|
|
||||||
BufferResources buffer;
|
BufferResources buffer;
|
||||||
buffer.texture = DXTexture::CreateAdopted(resource.Get());
|
buffer.texture = DXTexture::CreateAdopted(resource.Get());
|
||||||
CHECK(buffer.texture, "Create swap chain buffer texture");
|
ASSERT_MSG(VIDEO, buffer.texture != nullptr, "Failed to create swap chain buffer texture");
|
||||||
if (!buffer.texture)
|
if (!buffer.texture)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
buffer.framebuffer = DXFramebuffer::Create(buffer.texture.get(), nullptr);
|
buffer.framebuffer = DXFramebuffer::Create(buffer.texture.get(), nullptr);
|
||||||
CHECK(buffer.texture, "Create swap chain buffer framebuffer");
|
ASSERT_MSG(VIDEO, buffer.framebuffer != nullptr,
|
||||||
|
"Failed to create swap chain buffer framebuffer");
|
||||||
if (!buffer.framebuffer)
|
if (!buffer.framebuffer)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
#include "Common/DynamicLibrary.h"
|
#include "Common/DynamicLibrary.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
|
|
||||||
#include "VideoBackends/D3D12/Common.h"
|
#include "VideoBackends/D3D12/Common.h"
|
||||||
#include "VideoBackends/D3D12/D3D12StreamBuffer.h"
|
#include "VideoBackends/D3D12/D3D12StreamBuffer.h"
|
||||||
#include "VideoBackends/D3D12/DescriptorHeapManager.h"
|
#include "VideoBackends/D3D12/DescriptorHeapManager.h"
|
||||||
|
@ -151,7 +152,7 @@ bool DXContext::CreateDevice(u32 adapter_index, bool enable_debug_layer)
|
||||||
HRESULT hr = m_dxgi_factory->EnumAdapters(adapter_index, &adapter);
|
HRESULT hr = m_dxgi_factory->EnumAdapters(adapter_index, &adapter);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(VIDEO, "Adapter {} not found, using default", adapter_index);
|
ERROR_LOG_FMT(VIDEO, "Adapter {} not found, using default: {}", adapter_index, DX12HRWrap(hr));
|
||||||
adapter = nullptr;
|
adapter = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,14 +166,14 @@ bool DXContext::CreateDevice(u32 adapter_index, bool enable_debug_layer)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(VIDEO, "Debug layer requested but not available.");
|
ERROR_LOG_FMT(VIDEO, "Debug layer requested but not available: {}", DX12HRWrap(hr));
|
||||||
enable_debug_layer = false;
|
enable_debug_layer = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the actual device.
|
// Create the actual device.
|
||||||
hr = s_d3d12_create_device(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device));
|
hr = s_d3d12_create_device(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device));
|
||||||
CHECK(SUCCEEDED(hr), "Create D3D12 device");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create D3D12 device: {}", DX12HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -207,7 +208,7 @@ bool DXContext::CreateCommandQueue()
|
||||||
D3D12_COMMAND_QUEUE_PRIORITY_NORMAL,
|
D3D12_COMMAND_QUEUE_PRIORITY_NORMAL,
|
||||||
D3D12_COMMAND_QUEUE_FLAG_NONE};
|
D3D12_COMMAND_QUEUE_FLAG_NONE};
|
||||||
HRESULT hr = m_device->CreateCommandQueue(&queue_desc, IID_PPV_ARGS(&m_command_queue));
|
HRESULT hr = m_device->CreateCommandQueue(&queue_desc, IID_PPV_ARGS(&m_command_queue));
|
||||||
CHECK(SUCCEEDED(hr), "Create command queue");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create command queue: {}", DX12HRWrap(hr));
|
||||||
return SUCCEEDED(hr);
|
return SUCCEEDED(hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,12 +216,12 @@ bool DXContext::CreateFence()
|
||||||
{
|
{
|
||||||
HRESULT hr =
|
HRESULT hr =
|
||||||
m_device->CreateFence(m_completed_fence_value, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence));
|
m_device->CreateFence(m_completed_fence_value, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence));
|
||||||
CHECK(SUCCEEDED(hr), "Create fence");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create fence: {}", DX12HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_fence_event = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
m_fence_event = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||||
CHECK(m_fence_event != NULL, "Create fence event");
|
ASSERT_MSG(VIDEO, m_fence_event != NULL, "Failed to create fence event");
|
||||||
if (!m_fence_event)
|
if (!m_fence_event)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -302,14 +303,15 @@ static bool BuildRootSignature(ID3D12Device* device, ID3D12RootSignature** sig_p
|
||||||
&root_signature_blob, &root_signature_error_blob);
|
&root_signature_blob, &root_signature_error_blob);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
PanicAlertFmt("Failed to serialize root signature: {}",
|
PanicAlertFmt("Failed to serialize root signature: {}\n{}",
|
||||||
static_cast<const char*>(root_signature_error_blob->GetBufferPointer()));
|
static_cast<const char*>(root_signature_error_blob->GetBufferPointer()),
|
||||||
|
DX12HRWrap(hr));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = device->CreateRootSignature(0, root_signature_blob->GetBufferPointer(),
|
hr = device->CreateRootSignature(0, root_signature_blob->GetBufferPointer(),
|
||||||
root_signature_blob->GetBufferSize(), IID_PPV_ARGS(sig_ptr));
|
root_signature_blob->GetBufferSize(), IID_PPV_ARGS(sig_ptr));
|
||||||
CHECK(SUCCEEDED(hr), "Create root signature");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create root signature: {}", DX12HRWrap(hr));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,21 +418,21 @@ bool DXContext::CreateCommandLists()
|
||||||
CommandListResources& res = m_command_lists[i];
|
CommandListResources& res = m_command_lists[i];
|
||||||
HRESULT hr = m_device->CreateCommandAllocator(
|
HRESULT hr = m_device->CreateCommandAllocator(
|
||||||
D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(res.command_allocator.GetAddressOf()));
|
D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(res.command_allocator.GetAddressOf()));
|
||||||
CHECK(SUCCEEDED(hr), "Create command allocator");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create command allocator: {}", DX12HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
hr = m_device->CreateCommandList(1, D3D12_COMMAND_LIST_TYPE_DIRECT, res.command_allocator.Get(),
|
hr = m_device->CreateCommandList(1, D3D12_COMMAND_LIST_TYPE_DIRECT, res.command_allocator.Get(),
|
||||||
nullptr, IID_PPV_ARGS(res.command_list.GetAddressOf()));
|
nullptr, IID_PPV_ARGS(res.command_list.GetAddressOf()));
|
||||||
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create command list: {}", DX12HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
PanicAlertFmt("Failed to create command list.");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the command list, since the first thing we do is reset them.
|
// Close the command list, since the first thing we do is reset them.
|
||||||
hr = res.command_list->Close();
|
hr = res.command_list->Close();
|
||||||
CHECK(SUCCEEDED(hr), "Closing new command list failed");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Closing new command list failed: {}", DX12HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -472,14 +474,15 @@ void DXContext::ExecuteCommandList(bool wait_for_completion)
|
||||||
|
|
||||||
// Close and queue command list.
|
// Close and queue command list.
|
||||||
HRESULT hr = res.command_list->Close();
|
HRESULT hr = res.command_list->Close();
|
||||||
CHECK(SUCCEEDED(hr), "Close command list");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to close command list: {}", DX12HRWrap(hr));
|
||||||
const std::array<ID3D12CommandList*, 1> execute_lists{res.command_list.Get()};
|
const std::array<ID3D12CommandList*, 1> execute_lists{res.command_list.Get()};
|
||||||
m_command_queue->ExecuteCommandLists(static_cast<UINT>(execute_lists.size()),
|
m_command_queue->ExecuteCommandLists(static_cast<UINT>(execute_lists.size()),
|
||||||
execute_lists.data());
|
execute_lists.data());
|
||||||
|
|
||||||
// Update fence when GPU has completed.
|
// Update fence when GPU has completed.
|
||||||
hr = m_command_queue->Signal(m_fence.Get(), m_current_fence_value);
|
hr = m_command_queue->Signal(m_fence.Get(), m_current_fence_value);
|
||||||
CHECK(SUCCEEDED(hr), "Signal fence");
|
|
||||||
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to signal fence: {}", DX12HRWrap(hr));
|
||||||
|
|
||||||
MoveToNextCommandList();
|
MoveToNextCommandList();
|
||||||
if (wait_for_completion)
|
if (wait_for_completion)
|
||||||
|
@ -532,7 +535,7 @@ void DXContext::WaitForFence(u64 fence)
|
||||||
{
|
{
|
||||||
// Fall back to event.
|
// Fall back to event.
|
||||||
HRESULT hr = m_fence->SetEventOnCompletion(fence, m_fence_event);
|
HRESULT hr = m_fence->SetEventOnCompletion(fence, m_fence_event);
|
||||||
CHECK(SUCCEEDED(hr), "Set fence event on completion");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to set fence event on completion: {}", DX12HRWrap(hr));
|
||||||
WaitForSingleObject(m_fence_event, INFINITE);
|
WaitForSingleObject(m_fence_event, INFINITE);
|
||||||
m_completed_fence_value = m_fence->GetCompletedValue();
|
m_completed_fence_value = m_fence->GetCompletedValue();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Common/HRWrap.h"
|
||||||
|
|
||||||
#include "VideoBackends/D3D12/Common.h"
|
#include "VideoBackends/D3D12/Common.h"
|
||||||
#include "VideoBackends/D3D12/D3D12StreamBuffer.h"
|
#include "VideoBackends/D3D12/D3D12StreamBuffer.h"
|
||||||
#include "VideoBackends/D3D12/DescriptorAllocator.h"
|
#include "VideoBackends/D3D12/DescriptorAllocator.h"
|
||||||
|
@ -187,4 +189,34 @@ private:
|
||||||
|
|
||||||
extern std::unique_ptr<DXContext> g_dx_context;
|
extern std::unique_ptr<DXContext> g_dx_context;
|
||||||
|
|
||||||
|
// Wrapper for HRESULT to be used with fmt. Note that we can't create a fmt::formatter directly
|
||||||
|
// for HRESULT as HRESULT is simply a typedef on long and not a distinct type.
|
||||||
|
// Unlike the version in Common, this variant also knows to call GetDeviceRemovedReason if needed.
|
||||||
|
struct DX12HRWrap
|
||||||
|
{
|
||||||
|
constexpr explicit DX12HRWrap(HRESULT hr) : m_hr(hr) {}
|
||||||
|
const HRESULT m_hr;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace DX12
|
} // namespace DX12
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct fmt::formatter<DX12::DX12HRWrap>
|
||||||
|
{
|
||||||
|
constexpr auto parse(fmt::format_parse_context& ctx) { return ctx.begin(); }
|
||||||
|
template <typename FormatContext>
|
||||||
|
auto format(const DX12::DX12HRWrap& hr, FormatContext& ctx)
|
||||||
|
{
|
||||||
|
if (hr.m_hr == DXGI_ERROR_DEVICE_REMOVED && DX12::g_dx_context != nullptr &&
|
||||||
|
DX12::g_dx_context->GetDevice() != nullptr)
|
||||||
|
{
|
||||||
|
return fmt::format_to(
|
||||||
|
ctx.out(), "{}\nDevice removal reason: {}", Common::HRWrap(hr.m_hr),
|
||||||
|
Common::HRWrap(DX12::g_dx_context->GetDevice()->GetDeviceRemovedReason()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return fmt::format_to(ctx.out(), "{}", Common::HRWrap(hr.m_hr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -210,8 +210,8 @@ std::unique_ptr<DXPipeline> DXPipeline::Create(const AbstractPipelineConfig& con
|
||||||
HRESULT hr = g_dx_context->GetDevice()->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&pso));
|
HRESULT hr = g_dx_context->GetDevice()->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&pso));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
WARN_LOG_FMT(VIDEO, "CreateGraphicsPipelineState() {}failed with HRESULT {:08X}",
|
WARN_LOG_FMT(VIDEO, "CreateGraphicsPipelineState() {}failed: {}",
|
||||||
cache_data ? "with cache data " : "", hr);
|
cache_data ? "with cache data " : "", DX12HRWrap(hr));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ AbstractPipeline::CacheData DXPipeline::GetCacheData() const
|
||||||
HRESULT hr = m_pipeline->GetCachedBlob(&blob);
|
HRESULT hr = m_pipeline->GetCachedBlob(&blob);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
WARN_LOG_FMT(VIDEO, "ID3D12Pipeline::GetCachedBlob() failed with HRESULT {:08X}", hr);
|
WARN_LOG_FMT(VIDEO, "ID3D12Pipeline::GetCachedBlob() failed: {}", DX12HRWrap(hr));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "VideoBackends/D3D12/DX12Shader.h"
|
#include "VideoBackends/D3D12/DX12Shader.h"
|
||||||
|
|
||||||
|
#include "Common/Assert.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
|
|
||||||
#include "VideoBackends/D3D12/Common.h"
|
#include "VideoBackends/D3D12/Common.h"
|
||||||
|
@ -51,7 +52,7 @@ bool DXShader::CreateComputePipeline()
|
||||||
|
|
||||||
HRESULT hr = g_dx_context->GetDevice()->CreateComputePipelineState(
|
HRESULT hr = g_dx_context->GetDevice()->CreateComputePipelineState(
|
||||||
&desc, IID_PPV_ARGS(&m_compute_pipeline));
|
&desc, IID_PPV_ARGS(&m_compute_pipeline));
|
||||||
CHECK(SUCCEEDED(hr), "Creating compute pipeline failed");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Creating compute pipeline failed: {}", DX12HRWrap(hr));
|
||||||
|
|
||||||
if (m_compute_pipeline && !m_name.empty())
|
if (m_compute_pipeline && !m_name.empty())
|
||||||
m_compute_pipeline->SetName(m_name.c_str());
|
m_compute_pipeline->SetName(m_name.c_str());
|
||||||
|
|
|
@ -39,7 +39,7 @@ static ComPtr<ID3D12Resource> CreateTextureUploadBuffer(u32 buffer_size)
|
||||||
HRESULT hr = g_dx_context->GetDevice()->CreateCommittedResource(
|
HRESULT hr = g_dx_context->GetDevice()->CreateCommittedResource(
|
||||||
&heap_properties, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr,
|
&heap_properties, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr,
|
||||||
IID_PPV_ARGS(&resource));
|
IID_PPV_ARGS(&resource));
|
||||||
CHECK(SUCCEEDED(hr), "Create texture upload buffer");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create texture upload buffer: {}", DX12HRWrap(hr));
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ std::unique_ptr<DXTexture> DXTexture::Create(const TextureConfig& config, std::s
|
||||||
HRESULT hr = g_dx_context->GetDevice()->CreateCommittedResource(
|
HRESULT hr = g_dx_context->GetDevice()->CreateCommittedResource(
|
||||||
&heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc, resource_state,
|
&heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc, resource_state,
|
||||||
config.IsRenderTarget() ? &optimized_clear_value : nullptr, IID_PPV_ARGS(&resource));
|
config.IsRenderTarget() ? &optimized_clear_value : nullptr, IID_PPV_ARGS(&resource));
|
||||||
CHECK(SUCCEEDED(hr), "Create D3D12 texture resource");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create D3D12 texture resource: {}", DX12HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -230,9 +230,15 @@ void DXTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8*
|
||||||
{
|
{
|
||||||
const D3D12_RANGE read_range = {0, 0};
|
const D3D12_RANGE read_range = {0, 0};
|
||||||
staging_buffer = CreateTextureUploadBuffer(upload_size);
|
staging_buffer = CreateTextureUploadBuffer(upload_size);
|
||||||
if (!staging_buffer || FAILED(staging_buffer->Map(0, &read_range, &upload_buffer_ptr)))
|
if (!staging_buffer)
|
||||||
{
|
{
|
||||||
PanicAlertFmt("Failed to allocate/map temporary texture upload buffer");
|
PanicAlertFmt("Failed to allocate temporary texture upload buffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HRESULT hr = staging_buffer->Map(0, &read_range, &upload_buffer_ptr);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
PanicAlertFmt("Failed to map temporary texture upload buffer: {}", DX12HRWrap(hr));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,7 +604,7 @@ bool DXStagingTexture::Map()
|
||||||
|
|
||||||
const D3D12_RANGE read_range = {0u, m_type == StagingTextureType::Upload ? 0u : m_buffer_size};
|
const D3D12_RANGE read_range = {0u, m_type == StagingTextureType::Upload ? 0u : m_buffer_size};
|
||||||
HRESULT hr = m_resource->Map(0, &read_range, reinterpret_cast<void**>(&m_map_pointer));
|
HRESULT hr = m_resource->Map(0, &read_range, reinterpret_cast<void**>(&m_map_pointer));
|
||||||
CHECK(SUCCEEDED(hr), "Map resource failed");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Map resource failed: {}", DX12HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -663,7 +669,7 @@ std::unique_ptr<DXStagingTexture> DXStagingTexture::Create(StagingTextureType ty
|
||||||
&heap_properties, D3D12_HEAP_FLAG_NONE, &desc,
|
&heap_properties, D3D12_HEAP_FLAG_NONE, &desc,
|
||||||
is_upload ? D3D12_RESOURCE_STATE_GENERIC_READ : D3D12_RESOURCE_STATE_COPY_DEST, nullptr,
|
is_upload ? D3D12_RESOURCE_STATE_GENERIC_READ : D3D12_RESOURCE_STATE_COPY_DEST, nullptr,
|
||||||
IID_PPV_ARGS(&resource));
|
IID_PPV_ARGS(&resource));
|
||||||
CHECK(SUCCEEDED(hr), "Create staging texture resource");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create staging texture resource: {}", DX12HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include "VideoBackends/D3D12/DescriptorAllocator.h"
|
#include "VideoBackends/D3D12/DescriptorAllocator.h"
|
||||||
|
|
||||||
|
#include "Common/Assert.h"
|
||||||
|
|
||||||
#include "VideoBackends/D3D12/DX12Context.h"
|
#include "VideoBackends/D3D12/DX12Context.h"
|
||||||
|
|
||||||
namespace DX12
|
namespace DX12
|
||||||
|
@ -16,7 +18,8 @@ bool DescriptorAllocator::Create(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYP
|
||||||
const D3D12_DESCRIPTOR_HEAP_DESC desc = {type, static_cast<UINT>(num_descriptors),
|
const D3D12_DESCRIPTOR_HEAP_DESC desc = {type, static_cast<UINT>(num_descriptors),
|
||||||
D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE};
|
D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE};
|
||||||
HRESULT hr = device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_descriptor_heap));
|
HRESULT hr = device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_descriptor_heap));
|
||||||
CHECK(SUCCEEDED(hr), "Creating descriptor heap for linear allocator failed");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Creating descriptor heap for linear allocator failed: {}",
|
||||||
|
DX12HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ bool DescriptorHeapManager::Create(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_T
|
||||||
D3D12_DESCRIPTOR_HEAP_FLAG_NONE};
|
D3D12_DESCRIPTOR_HEAP_FLAG_NONE};
|
||||||
|
|
||||||
HRESULT hr = device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_descriptor_heap));
|
HRESULT hr = device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_descriptor_heap));
|
||||||
CHECK(SUCCEEDED(hr), "Create descriptor heap");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create descriptor heap: {}", DX12HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ bool SamplerHeapManager::Create(ID3D12Device* device, u32 num_descriptors)
|
||||||
{
|
{
|
||||||
const D3D12_DESCRIPTOR_HEAP_DESC desc = {D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, num_descriptors};
|
const D3D12_DESCRIPTOR_HEAP_DESC desc = {D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, num_descriptors};
|
||||||
HRESULT hr = device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_descriptor_heap));
|
HRESULT hr = device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_descriptor_heap));
|
||||||
CHECK(SUCCEEDED(hr), "Failed to create sampler descriptor heap");
|
ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Failed to create sampler descriptor heap: {}", DX12HRWrap(hr));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
#include "Common/DynamicLibrary.h"
|
#include "Common/DynamicLibrary.h"
|
||||||
|
#include "Common/HRWrap.h"
|
||||||
#include "Common/MsgHandler.h"
|
#include "Common/MsgHandler.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
|
|
||||||
|
@ -89,7 +90,7 @@ Microsoft::WRL::ComPtr<IDXGIFactory> CreateDXGIFactory(bool debug_device)
|
||||||
HRESULT hr = create_dxgi_factory(IID_PPV_ARGS(factory.ReleaseAndGetAddressOf()));
|
HRESULT hr = create_dxgi_factory(IID_PPV_ARGS(factory.ReleaseAndGetAddressOf()));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
PanicAlertFmt("CreateDXGIFactory() failed with HRESULT {:08X}", hr);
|
PanicAlertFmt("CreateDXGIFactory() failed: {}", Common::HRWrap(hr));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,6 @@
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
|
||||||
#define CHECK(cond, Message, ...) \
|
|
||||||
if (!(cond)) \
|
|
||||||
{ \
|
|
||||||
PanicAlert("%s failed in %s at line %d: " Message, __func__, __FILE__, __LINE__, \
|
|
||||||
##__VA_ARGS__); \
|
|
||||||
}
|
|
||||||
|
|
||||||
struct IDXGIFactory;
|
struct IDXGIFactory;
|
||||||
|
|
||||||
enum class AbstractTextureFormat : u32;
|
enum class AbstractTextureFormat : u32;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
#include "Common/FileUtil.h"
|
#include "Common/FileUtil.h"
|
||||||
|
#include "Common/HRWrap.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/MsgHandler.h"
|
#include "Common/MsgHandler.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
|
@ -118,8 +119,8 @@ std::optional<Shader::BinaryData> Shader::CompileShader(D3D_FEATURE_LEVEL featur
|
||||||
file << "Video Backend: " + g_video_backend->GetDisplayName();
|
file << "Video Backend: " + g_video_backend->GetDisplayName();
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
PanicAlertFmt("Failed to compile {}:\nDebug info ({}):\n{}", filename, target,
|
PanicAlertFmt("Failed to compile {}: {}\nDebug info ({}):\n{}", filename, Common::HRWrap(hr),
|
||||||
static_cast<const char*>(errors->GetBufferPointer()));
|
target, static_cast<const char*>(errors->GetBufferPointer()));
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,10 @@
|
||||||
|
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
#include "Common/CommonFuncs.h"
|
#include "Common/CommonFuncs.h"
|
||||||
|
#include "Common/HRWrap.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/MsgHandler.h"
|
#include "Common/MsgHandler.h"
|
||||||
|
|
||||||
#include "VideoCommon/VideoConfig.h"
|
#include "VideoCommon/VideoConfig.h"
|
||||||
|
|
||||||
static bool IsTearingSupported(IDXGIFactory2* dxgi_factory)
|
static bool IsTearingSupported(IDXGIFactory2* dxgi_factory)
|
||||||
|
@ -125,7 +127,7 @@ bool SwapChain::CreateSwapChain(bool stereo)
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
PanicAlertFmt("Failed to create swap chain with HRESULT {:08X}", hr);
|
PanicAlertFmt("Failed to create swap chain: {}", Common::HRWrap(hr));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +135,7 @@ bool SwapChain::CreateSwapChain(bool stereo)
|
||||||
hr = m_dxgi_factory->MakeWindowAssociation(static_cast<HWND>(m_wsi.render_surface),
|
hr = m_dxgi_factory->MakeWindowAssociation(static_cast<HWND>(m_wsi.render_surface),
|
||||||
DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER);
|
DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
WARN_LOG_FMT(VIDEO, "MakeWindowAssociation() failed with HRESULT {:08X}", hr);
|
WARN_LOG_FMT(VIDEO, "MakeWindowAssociation() failed: {}", Common::HRWrap(hr));
|
||||||
|
|
||||||
m_stereo = stereo;
|
m_stereo = stereo;
|
||||||
if (!CreateSwapChainBuffers())
|
if (!CreateSwapChainBuffers())
|
||||||
|
@ -166,7 +168,7 @@ bool SwapChain::ResizeSwapChain()
|
||||||
GetDXGIFormatForAbstractFormat(m_texture_format, false),
|
GetDXGIFormatForAbstractFormat(m_texture_format, false),
|
||||||
GetSwapChainFlags());
|
GetSwapChainFlags());
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
WARN_LOG_FMT(VIDEO, "ResizeBuffers() failed with HRESULT {:08X}", hr);
|
WARN_LOG_FMT(VIDEO, "ResizeBuffers() failed: {}", Common::HRWrap(hr));
|
||||||
|
|
||||||
DXGI_SWAP_CHAIN_DESC desc;
|
DXGI_SWAP_CHAIN_DESC desc;
|
||||||
if (SUCCEEDED(m_swap_chain->GetDesc(&desc)))
|
if (SUCCEEDED(m_swap_chain->GetDesc(&desc)))
|
||||||
|
@ -236,7 +238,7 @@ bool SwapChain::Present()
|
||||||
HRESULT hr = m_swap_chain->Present(static_cast<UINT>(g_ActiveConfig.bVSyncActive), present_flags);
|
HRESULT hr = m_swap_chain->Present(static_cast<UINT>(g_ActiveConfig.bVSyncActive), present_flags);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
WARN_LOG_FMT(VIDEO, "Swap chain present failed with HRESULT {:08X}", hr);
|
WARN_LOG_FMT(VIDEO, "Swap chain present failed: {}", Common::HRWrap(hr));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include "VideoBackends/OGL/OGLRender.h"
|
#include "VideoBackends/OGL/OGLRender.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cinttypes>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
|
@ -345,7 +345,7 @@ void RunGpuLoop()
|
||||||
|
|
||||||
ASSERT_MSG(COMMANDPROCESSOR,
|
ASSERT_MSG(COMMANDPROCESSOR,
|
||||||
(s32)fifo.CPReadWriteDistance.load(std::memory_order_relaxed) - 32 >= 0,
|
(s32)fifo.CPReadWriteDistance.load(std::memory_order_relaxed) - 32 >= 0,
|
||||||
"Negative fifo.CPReadWriteDistance = %i in FIFO Loop !\nThat can produce "
|
"Negative fifo.CPReadWriteDistance = {} in FIFO Loop !\nThat can produce "
|
||||||
"instability in the game. Please report it.",
|
"instability in the game. Please report it.",
|
||||||
fifo.CPReadWriteDistance.load(std::memory_order_relaxed) - 32);
|
fifo.CPReadWriteDistance.load(std::memory_order_relaxed) - 32);
|
||||||
|
|
||||||
|
|
|
@ -176,11 +176,11 @@ void VertexLoader::CompileVertexTranslator()
|
||||||
if (tc != VertexComponentFormat::NotPresent)
|
if (tc != VertexComponentFormat::NotPresent)
|
||||||
{
|
{
|
||||||
ASSERT_MSG(VIDEO, VertexComponentFormat::Direct <= tc && tc <= VertexComponentFormat::Index16,
|
ASSERT_MSG(VIDEO, VertexComponentFormat::Direct <= tc && tc <= VertexComponentFormat::Index16,
|
||||||
"Invalid texture coordinates!\n(tc = %d)", (u32)tc);
|
"Invalid texture coordinates!\n(tc = {})", tc);
|
||||||
ASSERT_MSG(VIDEO, ComponentFormat::UByte <= format && format <= ComponentFormat::Float,
|
ASSERT_MSG(VIDEO, ComponentFormat::UByte <= format && format <= ComponentFormat::Float,
|
||||||
"Invalid texture coordinates format!\n(format = %d)", (u32)format);
|
"Invalid texture coordinates format!\n(format = {})", format);
|
||||||
ASSERT_MSG(VIDEO, elements == TexComponentCount::S || elements == TexComponentCount::ST,
|
ASSERT_MSG(VIDEO, elements == TexComponentCount::S || elements == TexComponentCount::ST,
|
||||||
"Invalid number of texture coordinates elements!\n(elements = %d)", (u32)elements);
|
"Invalid number of texture coordinates elements!\n(elements = {})", elements);
|
||||||
|
|
||||||
WriteCall(VertexLoader_TextCoord::GetFunction(tc, format, elements));
|
WriteCall(VertexLoader_TextCoord::GetFunction(tc, format, elements));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include "VideoCommon/VertexLoaderBase.h"
|
#include "VideoCommon/VertexLoaderBase.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cinttypes>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright 2021 Dolphin Emulator Project
|
// Copyright 2021 Dolphin Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <cinttypes>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue