Misc: Simplify assertion macros

This commit is contained in:
Stenzek 2023-12-22 20:30:31 +10:00 committed by Connor McLaughlin
parent 20e75b4057
commit dc859ca0a6
40 changed files with 123 additions and 204 deletions

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
@ -17,8 +17,6 @@
#include "common/Pcsx2Defs.h"
#include <string>
#ifndef __pxFUNCTION__
#if defined(__GNUG__)
#define __pxFUNCTION__ __PRETTY_FUNCTION__
@ -27,132 +25,39 @@
#endif
#endif
// ----------------------------------------------------------------------------------------
// pxAssert / pxAssertDev
// ----------------------------------------------------------------------------------------
// Standard "nothrow" assertions. All assertions act as valid conditional statements that
// return the result of the specified conditional; useful for handling failed assertions in
// a "graceful" fashion when utilizing the "ignore" feature of assertion debugging.
// These macros are mostly intended for "pseudo-weak" assumptions within code, most often for
// testing threaded user interface code (threading of the UI is a prime example since often
// even very robust assertions can fail in very rare conditions, due to the complex variety
// of ways the user can invoke UI events).
// pxAssertRel - assertion check even in Release builds.
// pxFailRel - aborts program even in Release builds.
//
// All macros return TRUE if the assertion succeeds, or FALSE if the assertion failed
// (thus matching the condition of the assertion itself).
//
// pxAssertDev is an assertion tool for Devel builds, intended for sanity checking and/or
// bounds checking variables in areas which are not performance critical. Another common
// use is for checking thread affinity on utility functions.
//
// Credits: These macros are based on a combination of wxASSERT, MSVCRT's assert and the
// ATL's Assertion/Assumption macros. the best of all worlds!
// --------------------------------------------------------------------------------------
// pxAssume / pxAssumeDev / pxFail / pxFailDev
// --------------------------------------------------------------------------------------
// Assumptions are hints to the compiler that the condition will always be true,
// the condition should never fail under any circumstance in release builds
// or else you might get incorrect compiler generated code.
//
// Performance: All assumption/fail types optimize into __assume()/likely() directives in
// Release builds (non-dev varieties optimize as such in Devel builds as well).
// __assume(0) is a special form of __assume() which tells the compiler that the code path
// is not reachable and will cause undefined results if it is reachable...
//
// Having pxFail and pxFailDev translate into __assume statements is very dangerous, since
// it can lead to the compiler optimizing out code and leading to crashes in dev/release
// builds. To have code optimized, explicitly use pxAssume(false) or pxAssumeDev(false,msg);
// pxAssertRel ->
// Special release-mode assertion. Limited use since stack traces in release mode builds
// (especially with LTCG) are highly suspect. But when troubleshooting crashes that only
// rear ugly heads in optimized builds, this is one of the few tools we have.
// pxAssert[Msg] - assertion check only in Debug/Devel builds, noop in Release.
// pxAssume[Msg] - assertion check in Debug/Devel builds, optimization hint in Release builds.
// pxFail - aborts program only in Debug/Devel builds, noop in Release.
extern void pxOnAssertFail(const char* file, int line, const char* func, const char* msg);
#define pxAssertRel(cond, msg) ((likely(cond)) || (pxOnAssertFail(__FILE__, __LINE__, __pxFUNCTION__, msg), false))
#define pxAssumeRel(cond, msg) ((void)((!likely(cond)) && (pxOnAssertFail(__FILE__, __LINE__, __pxFUNCTION__, msg), false)))
#define pxFailRel(msg) pxAssertRel(false, msg)
#define pxAssertRel(cond, msg) do { if (!(cond)) [[unlikely]] { pxOnAssertFail(__FILE__, __LINE__, __pxFUNCTION__, msg); } } while(0)
#define pxFailRel(msg) pxOnAssertFail(__FILE__, __LINE__, __pxFUNCTION__, msg)
#if defined(PCSX2_DEBUG)
#if defined(PCSX2_DEBUG) || defined(PCSX2_DEVBUILD)
#define pxAssertMsg(cond, msg) pxAssertRel(cond, msg)
#define pxAssertDev(cond, msg) pxAssertMsg(cond, msg)
#define pxAssumeMsg(cond, msg) pxAssumeRel(cond, msg)
#define pxAssumeDev(cond, msg) pxAssumeRel(cond, msg)
#define pxFail(msg) pxAssertMsg(false, msg)
#define pxFailDev(msg) pxAssertDev(false, msg)
#elif defined(PCSX2_DEVBUILD)
// Devel builds now will give you a release-mode assertion dialog window if any of the
// following macro's 'cond' field is false.
// Note: Only use pxAssume/Msg/Dev if you know what you're doing, __assume is supposed
// to be used as an optimization hint, yet many devs have been using psAssume
// thinking its the same as an assertion.
// __assume(0) is also very dangerous because it is a special case of __assume() which
// tells the compiler that the code path is not reachable, and it can cause unpredictable
// results if the code path can be reached.
// i.e. if (1) { __assume(0); something(); }
// In the above example, something() may never be called.
// __assume(0)'s real use is in optimizing stuff such as "default:" cases on a switch
// statement. See jNO_DEFAULT
#define pxAssertMsg(cond, msg) pxAssertRel(cond, msg)
#define pxAssertDev(cond, msg) pxAssertRel(cond, msg)
#define pxAssumeMsg(cond, msg) pxAssumeRel(cond, msg) //(__assume(cond))
#define pxAssumeDev(cond, msg) pxAssumeRel(cond, msg)
#define pxFail(msg) pxAssertDev(false, msg)
#define pxFailDev(msg) pxAssertDev(false, msg)
#define pxAssumeMsg(cond, msg) pxAssertRel(cond, msg)
#define pxFail(msg) pxFailRel(msg)
#else
// Release Builds just use __assume as an optimization, and return the conditional
// as a result (which is optimized to nil if unused).
#define pxAssertMsg(cond, msg) (likely(cond))
#define pxAssertDev(cond, msg) (likely(cond))
#define pxAssumeMsg(cond, msg) __assume(cond)
#define pxAssumeDev(cond, msg) __assume(cond)
#define pxFail(msg) \
do \
{ \
} while (0)
#define pxFailDev(msg) \
do \
{ \
} while (0)
#define pxAssertMsg(cond, msg) ((void)0)
#define pxAssumeMsg(cond, msg) ASSUME(cond)
#define pxFail(msg) ((void)0)
#endif
#define pxAssert(cond) pxAssertMsg(cond, #cond)
#define pxAssume(cond) pxAssumeMsg(cond, #cond)
#define pxAssertRelease(cond, msg)
// --------------------------------------------------------------------------------------
// jNO_DEFAULT -- disables the default case in a switch, which improves switch optimization
// under MSVC.
// --------------------------------------------------------------------------------------
// How it Works: pxAssumeDev turns into an __assume(0) under msvc compilers, which when specified
// in the 'default:' case of a switch tells the compiler that the case is unreachable, so
// that it will not generate any code, LUTs, or conditionals to handle it.
//
// * In debug/devel builds the default case will cause an assertion.
//
#ifndef jNO_DEFAULT
// jNO_DEFAULT -- disables the default case in a switch, which improves switch optimization.
#define jNO_DEFAULT \
default: \
{ \
pxAssumeDev(0, "Incorrect usage of jNO_DEFAULT detected (default case is not unreachable!)"); \
pxAssumeMsg(false, "Incorrect usage of jNO_DEFAULT detected (default case is not unreachable!)"); \
break; \
}
#endif

View File

@ -58,7 +58,7 @@ void Console_SetStdout(FILE* fp)
// threaded mutex lock, which are only valid after C++ initialization has finished.
void Console_SetActiveHandler(const IConsoleWriter& writer, FILE* flushfp)
{
pxAssertDev(
pxAssertMsg(
(writer.WriteRaw != NULL) && (writer.DoWriteLn != NULL) &&
(writer.Newline != NULL) && (writer.SetTitle != NULL) &&
(writer.DoSetColor != NULL),

View File

@ -189,7 +189,7 @@ static __ri uint LinuxProt(const PageProtectionMode& mode)
void* HostSys::Mmap(void* base, size_t size, const PageProtectionMode& mode)
{
pxAssertDev((size & (__pagesize - 1)) == 0, "Size is page aligned");
pxAssertMsg((size & (__pagesize - 1)) == 0, "Size is page aligned");
if (mode.IsNone())
return nullptr;
@ -217,7 +217,7 @@ void HostSys::Munmap(void* base, size_t size)
void HostSys::MemProtect(void* baseaddr, size_t size, const PageProtectionMode& mode)
{
pxAssertDev((size & (__pagesize - 1)) == 0, "Size is page aligned");
pxAssertMsg((size & (__pagesize - 1)) == 0, "Size is page aligned");
const u32 lnxmode = LinuxProt(mode);

View File

@ -66,10 +66,6 @@ static constexpr unsigned int __pagemask = __pagesize - 1;
#define __noinline __declspec(noinline)
#define __noreturn __declspec(noreturn)
// Don't know if there are Visual C++ equivalents of these.
#define likely(x) (!!(x))
#define unlikely(x) (!!(x))
#else
// --------------------------------------------------------------------------------------
@ -99,8 +95,6 @@ static constexpr unsigned int __pagemask = __pagesize - 1;
#ifndef __noreturn
#define __noreturn __attribute__((noreturn))
#endif
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#endif
// --------------------------------------------------------------------------------------
@ -131,6 +125,18 @@ static constexpr unsigned int __pagemask = __pagesize - 1;
#endif
#endif
// __assume, potentially enables optimization.
#ifdef _MSC_VER
#define ASSUME(x) __assume(x)
#else
#define ASSUME(x) \
do \
{ \
if (!(x)) \
__builtin_unreachable(); \
} while (0)
#endif
//////////////////////////////////////////////////////////////////////////////////////////
// Safe deallocation macros -- checks pointer validity (non-null) when needed, and sets
// pointer to null after deallocation.

View File

@ -113,7 +113,7 @@ bool Threading::WorkSema::WaitForEmpty()
if (m_state.compare_exchange_weak(value, value | STATE_FLAG_WAITING_EMPTY, std::memory_order_acquire))
break;
}
pxAssertDev(!(value & STATE_FLAG_WAITING_EMPTY), "Multiple threads attempted to wait for empty (not currently supported)");
pxAssertMsg(!(value & STATE_FLAG_WAITING_EMPTY), "Multiple threads attempted to wait for empty (not currently supported)");
m_empty_sema.Wait();
return !IsDead(m_state.load(std::memory_order_relaxed));
}
@ -131,7 +131,7 @@ bool Threading::WorkSema::WaitForEmptyWithSpin()
waited += ShortSpin();
value = m_state.load(std::memory_order_acquire);
}
pxAssertDev(!(value & STATE_FLAG_WAITING_EMPTY), "Multiple threads attempted to wait for empty (not currently supported)");
pxAssertMsg(!(value & STATE_FLAG_WAITING_EMPTY), "Multiple threads attempted to wait for empty (not currently supported)");
m_empty_sema.Wait();
return !IsDead(m_state.load(std::memory_order_relaxed));
}

View File

@ -38,7 +38,7 @@ struct TraceLogDescriptor
const char* GetShortName() const
{
pxAssumeDev(Name, "Tracelog descriptors require a valid name!");
pxAssumeMsg(Name, "Tracelog descriptors require a valid name!");
return ShortName ? ShortName : Name;
}
};
@ -84,7 +84,7 @@ protected:
public:
BaseTraceLogSource(const TraceLogDescriptor* desc)
{
pxAssumeDev(desc, "Trace logs must have a valid (non-NULL) descriptor.");
pxAssumeMsg(desc, "Trace logs must have a valid (non-NULL) descriptor.");
Enabled = false;
m_Descriptor = desc;
}

View File

@ -30,7 +30,7 @@ public:
__forceinline void operator()(const xRegisterSSE& to, const ModSibBase& from) const
{
bool isReallyAligned = ((from.Displacement & 0x0f) == 0) && from.Index.IsEmpty() && from.Base.IsEmpty();
pxAssertDev(isReallyAligned, "Alignment check failed on SSE indirect load.");
pxAssertMsg(isReallyAligned, "Alignment check failed on SSE indirect load.");
xOpWrite0F(Prefix, Opcode, to, from);
}

View File

@ -201,7 +201,7 @@ namespace x86Emitter
if (slideForward)
{
pxAssertDev(displacement8 >= 0, "Used slideForward on a backward jump; nothing to slide!");
pxAssertMsg(displacement8 >= 0, "Used slideForward on a backward jump; nothing to slide!");
}
if (is_s8(displacement8))
@ -213,7 +213,7 @@ namespace x86Emitter
sptr distance = (sptr)target - (sptr)xGetPtr();
// This assert won't physically happen on x86 targets
pxAssertDev(distance >= -0x80000000LL && distance < 0x80000000LL, "Jump target is too far away, needs an indirect register");
pxAssertMsg(distance >= -0x80000000LL && distance < 0x80000000LL, "Jump target is too far away, needs an indirect register");
*bah = (s32)distance;
}
@ -229,7 +229,7 @@ namespace x86Emitter
xForwardJumpBase::xForwardJumpBase(uint opsize, JccComparisonType cctype)
{
pxAssert(opsize == 1 || opsize == 4);
pxAssertDev(cctype != Jcc_Unknown, "Invalid ForwardJump conditional type.");
pxAssertMsg(cctype != Jcc_Unknown, "Invalid ForwardJump conditional type.");
BasePtr = (s8*)xGetPtr() +
((opsize == 1) ? 2 : // j8's are always 2 bytes.
@ -253,12 +253,12 @@ namespace x86Emitter
void xForwardJumpBase::_setTarget(uint opsize) const
{
pxAssertDev(BasePtr != NULL, "");
pxAssertMsg(BasePtr != NULL, "");
sptr displacement = (sptr)xGetPtr() - (sptr)BasePtr;
if (opsize == 1)
{
pxAssertDev(is_s8(displacement), "Emitter Error: Invalid short jump displacement.");
pxAssertMsg(is_s8(displacement), "Emitter Error: Invalid short jump displacement.");
BasePtr[-1] = (s8)displacement;
}
else

View File

@ -151,7 +151,7 @@ namespace x86Emitter
// CMOVcc
// --------------------------------------------------------------------------------------
#define ccSane() pxAssertDev(ccType >= 0 && ccType <= 0x0f, "Invalid comparison type specifier.")
#define ccSane() pxAssertMsg(ccType >= 0 && ccType <= 0x0f, "Invalid comparison type specifier.")
// Macro useful for trapping unwanted use of EBP.
//#define EbpAssert() pxAssert( to != ebp )

View File

@ -317,7 +317,7 @@ const xRegister32
}
else
{
pxAssertDev(displacement == (s32)displacement, "SIB target is too far away, needs an indirect register");
pxAssertMsg(displacement == (s32)displacement, "SIB target is too far away, needs an indirect register");
ModRM(0, regfield, ModRm_UseSib);
SibSB(0, Sib_EIZ, Sib_UseDisp32);
}
@ -357,7 +357,7 @@ const xRegister32
{
// 3 bits also on x86_64 (so max is 8)
// We might need to mask it on x86_64
pxAssertDev(regfield < 8, "Invalid x86 register identifier.");
pxAssertMsg(regfield < 8, "Invalid x86 register identifier.");
int displacement_size = (info.Displacement == 0) ? 0 :
((info.IsByteSizeDisp()) ? 1 : 2);
@ -714,7 +714,7 @@ const xRegister32
Factor++;
else
{
pxAssertDev(Index.IsEmpty(), "x86Emitter: Only one scaled index register is allowed in an address modifier.");
pxAssertMsg(Index.IsEmpty(), "x86Emitter: Only one scaled index register is allowed in an address modifier.");
Index = src;
Factor = 2;
}
@ -724,7 +724,7 @@ const xRegister32
else if (Index.IsEmpty())
Index = src;
else
pxAssumeDev(false, "x86Emitter: address modifiers cannot have more than two index registers."); // oops, only 2 regs allowed per ModRm!
pxAssumeMsg(false, "x86Emitter: address modifiers cannot have more than two index registers."); // oops, only 2 regs allowed per ModRm!
return *this;
}
@ -749,7 +749,7 @@ const xRegister32
Factor += src.Factor;
}
else
pxAssumeDev(false, "x86Emitter: address modifiers cannot have more than two index registers."); // oops, only 2 regs allowed per ModRm!
pxAssumeMsg(false, "x86Emitter: address modifiers cannot have more than two index registers."); // oops, only 2 regs allowed per ModRm!
return *this;
}
@ -836,7 +836,7 @@ const xRegister32
break;
case 3: // becomes [reg*2+reg]
pxAssertDev(Base.IsEmpty(), "Cannot scale an Index register by 3 when Base is not empty!");
pxAssertMsg(Base.IsEmpty(), "Cannot scale an Index register by 3 when Base is not empty!");
Base = Index;
Scale = 1;
break;
@ -846,24 +846,24 @@ const xRegister32
break;
case 5: // becomes [reg*4+reg]
pxAssertDev(Base.IsEmpty(), "Cannot scale an Index register by 5 when Base is not empty!");
pxAssertMsg(Base.IsEmpty(), "Cannot scale an Index register by 5 when Base is not empty!");
Base = Index;
Scale = 2;
break;
case 6: // invalid!
pxAssumeDev(false, "x86 asm cannot scale a register by 6.");
pxAssumeMsg(false, "x86 asm cannot scale a register by 6.");
break;
case 7: // so invalid!
pxAssumeDev(false, "x86 asm cannot scale a register by 7.");
pxAssumeMsg(false, "x86 asm cannot scale a register by 7.");
break;
case 8:
Scale = 3;
break;
case 9: // becomes [reg*8+reg]
pxAssertDev(Base.IsEmpty(), "Cannot scale an Index register by 9 when Base is not empty!");
pxAssertMsg(Base.IsEmpty(), "Cannot scale an Index register by 9 when Base is not empty!");
Base = Index;
Scale = 3;
break;

View File

@ -188,7 +188,7 @@ namespace x86Emitter
public:
uint GetOperandSize() const
{
pxAssertDev(_operandSize != 0, "Attempted to use operand size of uninitialized or void object");
pxAssertMsg(_operandSize != 0, "Attempted to use operand size of uninitialized or void object");
return _operandSize;
}
@ -384,7 +384,7 @@ namespace x86Emitter
explicit xRegister16(const xRegisterInt& other)
: _parent(2, other.Id)
{
pxAssertDev(other.canMapIDTo(2), "Mapping h registers to higher registers can produce unexpected values");
pxAssertMsg(other.canMapIDTo(2), "Mapping h registers to higher registers can produce unexpected values");
}
bool operator==(const xRegister16& src) const { return this->Id == src.Id; }
@ -404,7 +404,7 @@ namespace x86Emitter
explicit xRegister32(const xRegisterInt& other)
: _parent(4, other.Id)
{
pxAssertDev(other.canMapIDTo(4), "Mapping h registers to higher registers can produce unexpected values");
pxAssertMsg(other.canMapIDTo(4), "Mapping h registers to higher registers can produce unexpected values");
}
static const inline xRegister32& GetInstance(uint id);
@ -426,7 +426,7 @@ namespace x86Emitter
explicit xRegister64(const xRegisterInt& other)
: _parent(8, other.Id)
{
pxAssertDev(other.canMapIDTo(8), "Mapping h registers to higher registers can produce unexpected values");
pxAssertMsg(other.canMapIDTo(8), "Mapping h registers to higher registers can produce unexpected values");
}
static const inline xRegister64& GetInstance(uint id);

View File

@ -63,7 +63,7 @@ static OutputIsoFile blockDumpFile;
// relying on DEP exceptions -- and a little more reliable too.
static void CheckNullCDVD()
{
pxAssertDev(CDVD != NULL, "Invalid CDVD object state (null pointer exception)");
pxAssertMsg(CDVD, "Invalid CDVD object state (null pointer exception)");
}
//////////////////////////////////////////////////////////////////////////////////////////

View File

@ -49,7 +49,7 @@ int InputIsoFile::ReadSync(u8* dst, uint lsn)
if (lsn >= m_blocks)
{
std::string msg(fmt::format("isoFile error: Block index is past the end of file! ({} >= {}).", lsn, m_blocks));
pxAssertDev(false, msg.c_str());
pxAssertMsg(false, msg.c_str());
Console.Error(msg.c_str());
return -1;
}

View File

@ -415,7 +415,7 @@ void UpdateVSyncRate(bool force)
else
total_scanlines = SCANLINES_TOTAL_NTSC_NI;
Console.Error("PCSX2-Counters: Unknown video mode detected");
pxAssertDev(false, "Unknown video mode detected via SetGsCrt");
pxAssertMsg(false, "Unknown video mode detected via SetGsCrt");
}
const bool video_mode_initialized = gsVideoMode != GS_VideoMode::Uninitialized;

View File

@ -191,7 +191,7 @@ namespace Sessions
{
ResetEvent(icmpEvent);
//Prep buffer for reasing
int count = IcmpParseReplies(icmpResponseBuffer.get(), icmpResponseBufferLen);
[[maybe_unused]] int count = IcmpParseReplies(icmpResponseBuffer.get(), icmpResponseBufferLen);
pxAssert(count == 1);
ICMP_ECHO_REPLY* pingRet = (ICMP_ECHO_REPLY*)icmpResponseBuffer.get();

View File

@ -316,7 +316,7 @@ static __fi int ChannelNumber(u32 addr)
case D9_CHCR: return 9;
default:
{
pxFailDev("Invalid DMA channel number");
pxFail("Invalid DMA channel number");
return 51; // some value
}
}

View File

@ -74,7 +74,7 @@ void WriteFIFO_VIF0(const mem128_t* value)
vif0ch.qwc += 1;
if (vif0.irqoffset.value != 0 && vif0.vifstalled.enabled)
DevCon.Warning("Offset on VIF0 FIFO start!");
bool ret = VIF0transfer((u32*)value, 4);
[[maybe_unused]] bool ret = VIF0transfer((u32*)value, 4);
if (vif0.cmd)
{
@ -86,7 +86,7 @@ void WriteFIFO_VIF0(const mem128_t* value)
vif0Regs.stat.VPS = VPS_IDLE;
}
pxAssertDev(ret, "vif stall code not implemented");
pxAssertMsg(ret, "vif stall code not implemented");
}
void WriteFIFO_VIF1(const mem128_t* value)
@ -106,7 +106,7 @@ void WriteFIFO_VIF1(const mem128_t* value)
DevCon.Warning("Offset on VIF1 FIFO start!");
}
bool ret = VIF1transfer((u32*)value, 4);
[[maybe_unused]] bool ret = VIF1transfer((u32*)value, 4);
if (vif1.cmd)
{
@ -126,7 +126,7 @@ void WriteFIFO_VIF1(const mem128_t* value)
gifUnit.Execute(false, true);
}
pxAssertDev(ret, "vif stall code not implemented");
pxAssertMsg(ret, "vif stall code not implemented");
}
void WriteFIFO_GIF(const mem128_t* value)

View File

@ -51,10 +51,12 @@ bool D3D12DescriptorHeapManager::Create(
void D3D12DescriptorHeapManager::Destroy()
{
#ifdef PCSX2_DEVBUILD
for (BitSetType& bs : m_free_slots)
{
pxAssert(bs.all());
pxAssertMsg(bs.all(), "Not all descriptors were freed");
}
#endif
m_shader_visible = false;
m_num_descriptors = 0;

View File

@ -407,7 +407,7 @@ ID3D12GraphicsCommandList4* GSDevice12::GetInitCommandList()
CommandListResources& res = m_command_lists[m_current_command_list];
if (!res.init_command_list_used)
{
HRESULT hr = res.command_allocators[0]->Reset();
[[maybe_unused]] HRESULT hr = res.command_allocators[0]->Reset();
pxAssertMsg(SUCCEEDED(hr), "Reset init command allocator failed");
res.command_lists[0]->Reset(res.command_allocators[0].get(), nullptr);

View File

@ -1298,7 +1298,7 @@ GSDevice::PresentResult GSDeviceMTL::BeginPresent(bool frame_skip)
void GSDeviceMTL::EndPresent()
{ @autoreleasepool {
pxAssertDev(m_current_render.encoder && m_current_render_cmdbuf, "BeginPresent cmdbuf was destroyed");
pxAssertMsg(m_current_render.encoder && m_current_render_cmdbuf, "BeginPresent cmdbuf was destroyed");
ImGui::Render();
RenderImGui(ImGui::GetDrawData());
EndRenderPass();
@ -2165,7 +2165,7 @@ void GSDeviceMTL::RenderHW(GSHWDrawConfig& config)
if (!rt && !config.ds)
{
// If we were rendering depth-only and depth gets cleared by the above check, that turns into rendering nothing, which should be a no-op
pxAssertDev(0, "RenderHW was given a completely useless draw call!");
pxAssertMsg(0, "RenderHW was given a completely useless draw call!");
[m_current_render.encoder insertDebugSignpost:@"Skipped no-color no-depth draw"];
if (primid_tex)
Recycle(primid_tex);

View File

@ -204,9 +204,9 @@ bool SaveStateBase::gifPathFreeze(u32 path)
{
Gif_Path& gifPath = gifUnit.gifPath[path];
pxAssertDev(!gifPath.readAmount, "Gif Path readAmount should be 0!");
pxAssertDev(!gifPath.gsPack.readAmount, "GS Pack readAmount should be 0!");
pxAssertDev(!gifPath.GetPendingGSPackets(), "MTVU GS Pack Queue should be 0!");
pxAssertMsg(!gifPath.readAmount, "Gif Path readAmount should be 0!");
pxAssertMsg(!gifPath.gsPack.readAmount, "GS Pack readAmount should be 0!");
pxAssertMsg(!gifPath.GetPendingGSPackets(), "MTVU GS Pack Queue should be 0!");
if (!gifPath.isMTVU())
{ // FixMe: savestate freeze bug (Gust games) with MTVU enabled

View File

@ -324,7 +324,7 @@ struct Gif_Path
break; // Enough free front space
mtgsReadWait(); // Let MTGS run to free up buffer space
}
pxAssertDev(curSize + size <= buffSize, "Gif Path Buffer Overflow!");
pxAssertMsg(curSize + size <= buffSize, "Gif Path Buffer Overflow!");
memcpy(&buffer[curSize], pMem, size);
curSize += size;
}

View File

@ -146,7 +146,7 @@ __ri bool hwMFIFOWrite(u32 addr, const u128* data, uint qwc)
else
{
SPR_LOG( "Scratchpad/MFIFO: invalid base physical address: 0x%08x", dmacRegs.rbor.ADDR );
pxFailDev( fmt::format( "Scratchpad/MFIFO: Invalid base physical address: 0x{:08x}", u32(dmacRegs.rbor.ADDR)).c_str() );
pxFail( fmt::format( "Scratchpad/MFIFO: Invalid base physical address: 0x{:08x}", u32(dmacRegs.rbor.ADDR)).c_str() );
return false;
}

View File

@ -167,7 +167,9 @@ void IPU_Fifo_Output::read(void *value, uint size)
void ReadFIFO_IPUout(mem128_t* out)
{
if (!pxAssertDev( ipuRegs.ctrl.OFC > 0, "Attempted read from IPUout's FIFO, but the FIFO is empty!" )) return;
pxAssertMsg(ipuRegs.ctrl.OFC > 0, "Attempted read from IPUout's FIFO, but the FIFO is empty!");
if (ipuRegs.ctrl.OFC == 0) [[unlikely]]
return;
ipu_fifo.out.read(out, 1);
// Games should always check the fifo before reading from it -- so if the FIFO has no data

View File

@ -2330,10 +2330,12 @@ void ImGuiFullscreen::OpenBackgroundProgressDialog(const char* str_id, std::stri
std::unique_lock<std::mutex> lock(s_background_progress_lock);
#ifdef PCSX2_DEVBUILD
for (const BackgroundProgressDialogData& data : s_background_progress_dialogs)
{
pxAssert(data.id != id);
pxAssertMsg(data.id != id, "Duplicate background progress dialog open");
}
#endif
BackgroundProgressDialogData data;
data.id = id;

View File

@ -612,7 +612,8 @@ void MTGS::MainLoop()
// If isMTVU, then this implies this function is being called from the MTVU thread...
void MTGS::WaitGS(bool syncRegs, bool weakWait, bool isMTVU)
{
if (!pxAssertDev(IsOpen(), "MTGS Warning! WaitGS issued on a closed thread."))
pxAssertMsg(IsOpen(), "MTGS Warning! WaitGS issued on a closed thread.");
if (!IsOpen()) [[unlikely]]
return;
Gif_Path& path = gifUnit.gifPath[GIF_PATH_1];
@ -745,7 +746,7 @@ void MTGS::GenericStall(uint size)
if (somedone > 0x80)
{
pxAssertDev(s_SignalRingEnable == 0, "MTGS Thread Synchronization Error");
pxAssertMsg(s_SignalRingEnable == 0, "MTGS Thread Synchronization Error");
s_SignalRingPosition.store(somedone, std::memory_order_release);
//Console.WriteLn( Color_Blue, "(EEcore Sleep) PrepDataPacker \tringpos=0x%06x, writepos=0x%06x, signalpos=0x%06x", readpos, writepos, m_SignalRingPosition );
@ -767,7 +768,7 @@ void MTGS::GenericStall(uint size)
break;
}
pxAssertDev(s_SignalRingPosition <= 0, "MTGS Thread Synchronization Error");
pxAssertMsg(s_SignalRingPosition <= 0, "MTGS Thread Synchronization Error");
}
else
{
@ -1075,7 +1076,7 @@ void Gif_AddCompletedGSPacket(GS_Packet& gsPack, GIF_PATH path)
}
else
{
pxAssertDev(!gsPack.readAmount, "Gif Unit - gsPack.readAmount only valid for MTVU path 1!");
pxAssertMsg(!gsPack.readAmount, "Gif Unit - gsPack.readAmount only valid for MTVU path 1!");
gifUnit.gifPath[path].readAmount.fetch_add(gsPack.size);
MTGS::SendSimpleGSPacket(MTGS::Command::GSPacket, gsPack.offset, gsPack.size, path);
}

View File

@ -230,7 +230,7 @@ uint FileMcd_GetMtapSlot(uint slot)
{
case 0:
case 1:
pxFailDev("Invalid parameter in call to GetMtapSlot -- specified slot is one of the base slots, not a Multitap slot.");
pxFail("Invalid parameter in call to GetMtapSlot -- specified slot is one of the base slots, not a Multitap slot.");
break;
case 2:
@ -452,7 +452,8 @@ void FileMemoryCard::GetSizeInfo(uint slot, McdSizeInfo& outways)
outways.EraseBlockSizeInSectors = 16; // 0x0010
outways.Xor = 18; // 0x12, XOR 02 00 00 10
if (pxAssert(m_file[slot]))
pxAssert(m_file[slot]);
if (m_file[slot])
outways.McdSizeInSectors = static_cast<u32>(FileSystem::FSize64(m_file[slot])) / (outways.SectorSize + outways.EraseBlockSizeInSectors);
else
outways.McdSizeInSectors = 0x4000;

View File

@ -131,7 +131,7 @@ bool SaveStateBase::FreezeTag(const char* src)
return false;
char tagspace[32];
pxAssertDev(std::strlen(src) < (sizeof(tagspace) - 1), "Tag name exceeds the allowed length");
pxAssertMsg(std::strlen(src) < (sizeof(tagspace) - 1), "Tag name exceeds the allowed length");
std::memset(tagspace, 0, sizeof(tagspace));
StringUtil::Strlcpy(tagspace, src, sizeof(tagspace));

View File

@ -4025,13 +4025,13 @@ static void VU0regsMI_XTOP(_VURegsNum* VUregsn) { _vuRegsXTOP(&VU0, VUregsn); }
void VU0unknown()
{
pxFailDev("Unknown VU micromode opcode called");
pxFail("Unknown VU micromode opcode called");
CPU_LOG("Unknown VU micromode opcode called");
}
static void VU0regsunknown(_VURegsNum* VUregsn)
{
pxFailDev("Unknown VU micromode opcode called");
pxFail("Unknown VU micromode opcode called");
CPU_LOG("Unknown VU micromode opcode called");
}
@ -4391,13 +4391,13 @@ static void VU1regsMI_XTOP(_VURegsNum* VUregsn) { _vuRegsXTOP(&VU1, VUregsn); }
static void VU1unknown()
{
pxFailDev("Unknown VU micromode opcode called");
pxFail("Unknown VU micromode opcode called");
CPU_LOG("Unknown VU micromode opcode called");
}
static void VU1regsunknown(_VURegsNum* VUregsn)
{
pxFailDev("Unknown VU micromode opcode called");
pxFail("Unknown VU micromode opcode called");
CPU_LOG("Unknown VU micromode opcode called");
}

View File

@ -60,6 +60,7 @@ void vif1TransferToMemory()
const u32 size = std::min(vif1.GSLastDownloadSize, (u32)vif1ch.qwc);
//const u128* pMemEnd = vif1.GSLastDownloadSize + pMem;
#ifdef PCSX2_DEVBUILD
if (size)
{
// Checking if any crazy game does a partial
@ -71,6 +72,7 @@ void vif1TransferToMemory()
pxAssert(p2.isDone() || !p2.gifTag.isValid);
pxAssert(p3.isDone() || !p3.gifTag.isValid);
}
#endif
MTGS::InitAndReadFIFO(reinterpret_cast<u8*>(pMem), size);
// pMem += size;

View File

@ -299,7 +299,7 @@ bool IsBIOSAvailable(const std::string& full_path)
//
bool LoadBIOS()
{
pxAssertDev(eeMem->ROM != NULL, "PS2 system memory has not been initialized yet.");
pxAssertMsg(eeMem->ROM, "PS2 system memory has not been initialized yet.");
std::string path = EmuConfig.FullpathToBios();
if (path.empty() || !FileSystem::FileExists(path.c_str()))

View File

@ -591,57 +591,57 @@ static void TAKES_R128 vtlbUnmappedPWriteLg(u32 addr, r128 data) { vtlb_BusError
static mem8_t vtlbDefaultPhyRead8(u32 addr)
{
pxFailDev(fmt::format("(VTLB) Attempted read8 from unmapped physical address @ 0x{:08X}.", addr).c_str());
pxFail(fmt::format("(VTLB) Attempted read8 from unmapped physical address @ 0x{:08X}.", addr).c_str());
return 0;
}
static mem16_t vtlbDefaultPhyRead16(u32 addr)
{
pxFailDev(fmt::format("(VTLB) Attempted read16 from unmapped physical address @ 0x{:08X}.", addr).c_str());
pxFail(fmt::format("(VTLB) Attempted read16 from unmapped physical address @ 0x{:08X}.", addr).c_str());
return 0;
}
static mem32_t vtlbDefaultPhyRead32(u32 addr)
{
pxFailDev(fmt::format("(VTLB) Attempted read32 from unmapped physical address @ 0x{:08X}.", addr).c_str());
pxFail(fmt::format("(VTLB) Attempted read32 from unmapped physical address @ 0x{:08X}.", addr).c_str());
return 0;
}
static mem64_t vtlbDefaultPhyRead64(u32 addr)
{
pxFailDev(fmt::format("(VTLB) Attempted read64 from unmapped physical address @ 0x{:08X}.", addr).c_str());
pxFail(fmt::format("(VTLB) Attempted read64 from unmapped physical address @ 0x{:08X}.", addr).c_str());
return 0;
}
static RETURNS_R128 vtlbDefaultPhyRead128(u32 addr)
{
pxFailDev(fmt::format("(VTLB) Attempted read128 from unmapped physical address @ 0x{:08X}.", addr).c_str());
pxFail(fmt::format("(VTLB) Attempted read128 from unmapped physical address @ 0x{:08X}.", addr).c_str());
return r128_zero();
}
static void vtlbDefaultPhyWrite8(u32 addr, mem8_t data)
{
pxFailDev(fmt::format("(VTLB) Attempted write8 to unmapped physical address @ 0x{:08X}.", addr).c_str());
pxFail(fmt::format("(VTLB) Attempted write8 to unmapped physical address @ 0x{:08X}.", addr).c_str());
}
static void vtlbDefaultPhyWrite16(u32 addr, mem16_t data)
{
pxFailDev(fmt::format("(VTLB) Attempted write16 to unmapped physical address @ 0x{:08X}.", addr).c_str());
pxFail(fmt::format("(VTLB) Attempted write16 to unmapped physical address @ 0x{:08X}.", addr).c_str());
}
static void vtlbDefaultPhyWrite32(u32 addr, mem32_t data)
{
pxFailDev(fmt::format("(VTLB) Attempted write32 to unmapped physical address @ 0x{:08X}.", addr).c_str());
pxFail(fmt::format("(VTLB) Attempted write32 to unmapped physical address @ 0x{:08X}.", addr).c_str());
}
static void vtlbDefaultPhyWrite64(u32 addr, mem64_t data)
{
pxFailDev(fmt::format("(VTLB) Attempted write64 to unmapped physical address @ 0x{:08X}.", addr).c_str());
pxFail(fmt::format("(VTLB) Attempted write64 to unmapped physical address @ 0x{:08X}.", addr).c_str());
}
static void TAKES_R128 vtlbDefaultPhyWrite128(u32 addr, r128 data)
{
pxFailDev(fmt::format("(VTLB) Attempted write128 to unmapped physical address @ 0x{:08X}.", addr).c_str());
pxFail(fmt::format("(VTLB) Attempted write128 to unmapped physical address @ 0x{:08X}.", addr).c_str());
}
// ===========================================================================================
@ -677,7 +677,7 @@ __ri void vtlb_ReassignHandler(vtlbHandler rv,
vtlbHandler vtlb_NewHandler()
{
pxAssertDev(vtlbHandlerCount < VTLB_HANDLER_ITEMS, "VTLB handler count overflow!");
pxAssertMsg(vtlbHandlerCount < VTLB_HANDLER_ITEMS, "VTLB handler count overflow!");
return vtlbHandlerCount++;
}

View File

@ -1063,10 +1063,10 @@ static __fi u32 psxRecClearMem(u32 pc)
blockidx = 0;
while (BASEBLOCKEX* pexblock = recBlocks[blockidx++])
{
if (pc >= pexblock->startpc && pc < pexblock->startpc + pexblock->size * 4)
if (pc >= pexblock->startpc && pc < pexblock->startpc + pexblock->size * 4) [[unlikely]]
{
DevCon.Error("[IOP] Impossible block clearing failure");
pxFailDev("[IOP] Impossible block clearing failure");
pxFail("[IOP] Impossible block clearing failure");
}
}

View File

@ -2345,7 +2345,7 @@ void rpsxpropCP2_basic(EEINST* prev, EEINST* pinst)
break;
default:
pxFailDev("iop invalid opcode in const propagation (rpsxpropCP2/BASIC)");
pxFail("iop invalid opcode in const propagation (rpsxpropCP2/BASIC)");
break;
}
}

View File

@ -227,7 +227,7 @@ int _allocX86reg(int type, int reg, int mode)
{
if (type == X86TYPE_GPR || type == X86TYPE_PSX)
{
pxAssertDev(reg >= 0 && reg < 34, "Register index out of bounds.");
pxAssertMsg(reg >= 0 && reg < 34, "Register index out of bounds.");
}
int hostXMMreg = (type == X86TYPE_GPR) ? _checkXMMreg(XMMTYPE_GPRREG, reg, 0) : -1;

View File

@ -438,7 +438,7 @@ static const void* _DynGen_DispatcherEvent()
static const void* _DynGen_EnterRecompiledCode()
{
pxAssertDev(DispatcherReg != NULL, "Dynamically generated dispatchers are required prior to generating EnterRecompiledCode!");
pxAssertMsg(DispatcherReg, "Dynamically generated dispatchers are required prior to generating EnterRecompiledCode!");
u8* retval = xGetAlignedCallTarget();
@ -798,12 +798,10 @@ void recClear(u32 addr, u32 size)
if (s_pCurBlock == PC_GETBLOCK(pexblock->startpc))
continue;
u32 blockend = pexblock->startpc + pexblock->size * 4;
if ((pexblock->startpc >= addr && pexblock->startpc < addr + size * 4) || (pexblock->startpc < addr && blockend > addr))
if ((pexblock->startpc >= addr && pexblock->startpc < addr + size * 4) || (pexblock->startpc < addr && blockend > addr)) [[unlikely]]
{
if (!IsDevBuild)
Console.Error("[EE] Impossible block clearing failure");
else
pxFailDev("[EE] Impossible block clearing failure");
pxFail("[EE] Impossible block clearing failure");
}
}

View File

@ -51,7 +51,7 @@ void mVUsetupRange(microVU& mVU, s32 pc, bool isStartPC)
if (pc > (s64)mVU.microMemSize)
{
Console.Error("microVU%d: PC outside of VU memory PC=0x%04x", mVU.index, pc);
pxFailDev("microVU: PC out of VU memory");
pxFail("microVU: PC out of VU memory");
}
// The PC handling will prewrap the PC so we need to set the end PC to the end of the micro memory, but only if it wraps, no more.

View File

@ -309,7 +309,7 @@ protected:
}
}
int x = findFreeRegRec(0);
pxAssertDev(x >= 0, "microVU register allocation failure!");
pxAssertMsg(x >= 0, "microVU register allocation failure!");
return x;
}
@ -341,7 +341,7 @@ protected:
}
}
int x = findFreeGPRRec(0);
pxAssertDev(x >= 0, "microVU register allocation failure!");
pxAssertMsg(x >= 0, "microVU register allocation failure!");
return x;
}

View File

@ -295,7 +295,7 @@ static void mVUEBit()
static inline u32 branchAddr(const mV)
{
pxAssumeDev(islowerOP, "MicroVU: Expected Lower OP code for valid branch addr.");
pxAssumeMsg(islowerOP, "MicroVU: Expected Lower OP code for valid branch addr.");
return ((((iPC + 2) + (_Imm11_ * 2)) & mVU.progMemMask) * 4);
}

View File

@ -87,7 +87,7 @@ __fi void VifUnpackSSE_Dynarec::SetMasks(int cS) const
void VifUnpackSSE_Dynarec::doMaskWrite(const xRegisterSSE& regX) const
{
pxAssertDev(regX.Id <= 1, "Reg Overflow! XMM2 thru XMM6 are reserved for masking.");
pxAssertMsg(regX.Id <= 1, "Reg Overflow! XMM2 thru XMM6 are reserved for masking.");
const int cc = std::min(vCL, 3);
u32 m0 = (vB.mask >> (cc * 8)) & 0xff; //The actual mask example 0xE4 (protect, col, row, clear)