Merge pull request #19561 from hrydgard/more-misc-fixes
Some checks are pending
Build / build-windows (ARM64) (push) Waiting to run
Build / build-windows (x64) (push) Waiting to run
Build / build-uwp (push) Waiting to run
Build / test-windows (push) Blocked by required conditions
Build / build (./b.sh --headless --unittest --fat --no-png --no-sdl2, clang, clang++, test, macos, macos-latest) (push) Waiting to run
Build / build (./b.sh --headless --unittest, clang, clang++, test, clang-normal, ubuntu-latest) (push) Waiting to run
Build / build (./b.sh --headless --unittest, gcc, g++, gcc-normal, ubuntu-latest) (push) Waiting to run
Build / build (./b.sh --ios, clang, clang++, ios, ios, macos-latest) (push) Waiting to run
Build / build (./b.sh --libretro_android ppsspp_libretro, clang, clang++, android, android-libretro, ubuntu-latest) (push) Waiting to run
Build / build (./b.sh --qt, gcc, g++, qt, qt, ubuntu-latest) (push) Waiting to run
Build / build (cd android && ./ab.sh -j2 APP_ABI=arm64-v8a OPENXR=1, clang, clang++, android, android-vr, ubuntu-latest) (push) Waiting to run
Build / build (cd android && ./ab.sh -j2 APP_ABI=arm64-v8a UNITTEST=1 HEADLESS=1, clang, clang++, android, android-arm64, ubuntu-latest) (push) Waiting to run
Build / build (cd android && ./ab.sh -j2 APP_ABI=armeabi-v7a UNITTEST=1 HEADLESS=1, clang, clang++, android, android-arm32, ubuntu-latest) (push) Waiting to run
Build / build (cd android && ./ab.sh -j2 APP_ABI=x86_64 UNITTEST=1 HEADLESS=1, clang, clang++, android, android-x86_64, ubuntu-latest) (push) Waiting to run
Build / build (make -C libretro -f Makefile -j2, clang, clang++, libretro, clang-libretro, ubuntu-latest) (push) Waiting to run
Build / build (make -C libretro -f Makefile -j2, gcc, g++, libretro, gcc-libretro, ubuntu-latest) (push) Waiting to run
Build / test (macos-latest) (push) Blocked by required conditions
Build / test (ubuntu-latest) (push) Blocked by required conditions
Build / build_test_headless_alpine (push) Waiting to run
Generate Docker Layer / build (push) Waiting to run

Simplify reporting code (removing two threads), other minor fixes
This commit is contained in:
Henrik Rydgård 2024-10-28 17:47:02 +01:00 committed by GitHub
commit ffb3e61ca6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 89 additions and 188 deletions

View File

@ -290,22 +290,26 @@ VFSOpenFile *ZipFileReader::OpenFileForRead(VFSFileReference *vfsReference, size
}
void ZipFileReader::Rewind(VFSOpenFile *vfsOpenFile) {
ZipFileReaderOpenFile *openFile = (ZipFileReaderOpenFile *)vfsOpenFile;
// Close and re-open.
zip_fclose(openFile->zf);
openFile->zf = zip_fopen_index(zip_file_, openFile->reference->zi, 0);
ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)vfsOpenFile;
_assert_(file);
_dbg_assert_(file->zf != nullptr);
zip_fseek(file->zf, 0, SEEK_SET);
}
size_t ZipFileReader::Read(VFSOpenFile *vfsOpenFile, void *buffer, size_t length) {
ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)vfsOpenFile;
_assert_(file);
_dbg_assert_(file->zf != nullptr);
return zip_fread(file->zf, buffer, length);
}
void ZipFileReader::CloseFile(VFSOpenFile *vfsOpenFile) {
ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)vfsOpenFile;
_assert_(file);
_dbg_assert_(file->zf != nullptr);
zip_fclose(file->zf);
file->zf = nullptr;
vfsOpenFile = nullptr;
lock_.unlock();
delete file;
}

View File

@ -67,7 +67,7 @@ void ReportMessage(const char *message, ...) {
return;
const int MESSAGE_BUFFER_SIZE = 65536;
char temp[MESSAGE_BUFFER_SIZE];
char *temp = new char [MESSAGE_BUFFER_SIZE];
va_list args;
va_start(args, message);
@ -76,6 +76,8 @@ void ReportMessage(const char *message, ...) {
va_end(args);
messageCallback(message, temp);
delete[] temp;
}
void ReportMessageFormatted(const char *message, const char *formatted) {

View File

@ -9,7 +9,8 @@
namespace http {
Request::Request(RequestMethod method, const std::string &url, std::string_view name, bool *cancelled, ProgressBarMode mode) : method_(method), url_(url), name_(name), progress_(cancelled), progressBarMode_(mode) {
Request::Request(RequestMethod method, const std::string &url, std::string_view name, bool *cancelled, ProgressBarMode mode)
: method_(method), url_(url), name_(name), progress_(cancelled), progressBarMode_(mode) {
INFO_LOG(Log::HTTP, "HTTP %s request: %s (%.*s)", RequestMethodToString(method), url.c_str(), (int)name.size(), name.data());
progress_.callback = [=](int64_t bytes, int64_t contentLength, bool done) {

View File

@ -71,6 +71,7 @@ void Shutdown()
#endif
}
// NOTE: Due to the nature of getaddrinfo, this can block indefinitely. Not good.
bool DNSResolve(const std::string &host, const std::string &service, addrinfo **res, std::string &error, DNSType type) {
#if PPSSPP_PLATFORM(SWITCH)
// Force IPv4 lookups.

View File

@ -164,7 +164,8 @@ bool ElfReader::LoadRelocations(const Elf32_Rel *rels, int numRelocs) {
// It appears the PSP takes any relocation that is not a HI16.
if (t_type != R_MIPS_LO16) {
if (t_type != R_MIPS_16) {
// Let's play it safe for now and skip. We've only seen this type.
// Let's play it safe for now and skip. We've only seen this type.
// These exists in some popular games like Assassin's Creed: Bloodlines and GTA: VCS: (https://report.ppsspp.org/logs/kind/1187)
ERROR_LOG_REPORT(Log::Loader, "ELF relocation HI16/%d pair (instead of LO16) at %08x / %08x", t_type, addr, corrLoAddr);
continue;
} else {

View File

@ -91,8 +91,8 @@ bool JitBlock::ContainsAddress(u32 em_address) const {
}
bool JitBlockCache::IsFull() const {
// -10 to safely leave space for some proxy blocks, which we don't check before we allocate (not ideal, but should work).
return num_blocks_ >= MAX_NUM_BLOCKS - 10;
// Subtract some amount to safely leave space for some proxy blocks, which we don't check before we allocate (not ideal, but should be enough).
return num_blocks_ >= MAX_NUM_BLOCKS - 512;
}
void JitBlockCache::Init() {
@ -218,7 +218,6 @@ void JitBlockCache::ProxyBlock(u32 rootAddress, u32 startAddress, u32 size, cons
void JitBlockCache::AddBlockMap(int block_num) {
const JitBlock &b = blocks_[block_num];
// Convert the logical address to a physical address for the block map
// Yeah, this'll work fine for PSP too I think.
u32 pAddr = b.originalAddress & 0x1FFFFFFF;
block_map_[std::make_pair(pAddr + 4 * b.originalSize, pAddr)] = block_num;
}

View File

@ -227,7 +227,8 @@ private:
std::pair<u32, u32> blockMemRanges_[3];
enum {
MAX_NUM_BLOCKS = 65536*2
// Where does this number come from?
MAX_NUM_BLOCKS = 65536 * 4
};
};

View File

@ -101,7 +101,7 @@ namespace MIPSInt
int func = (op >> 16) & 0x1F;
// Let's only report this once per run to be safe from impacting perf.
static bool reportedAlignment = false;
static bool loggedAlignment = false;
// It appears that a cache line is 0x40 (64) bytes, loops in games
// issue the cache instruction at that interval.
@ -120,9 +120,10 @@ namespace MIPSInt
int size = 0x40 + (addr & 0x3F);
MIPSComp::jit->InvalidateCacheAt(alignedAddr, size);
// Using a bool to avoid locking/etc. in case it's slow.
if (!reportedAlignment && (addr & 0x3F) != 0) {
WARN_LOG_REPORT(Log::JIT, "Unaligned icache invalidation of %08x (%08x + %d) at PC=%08x", addr, R(rs), imm, PC);
reportedAlignment = true;
if (!loggedAlignment && (addr & 0x3F) != 0) {
// These are seen exclusively in Lego games, and are really no big deal. Reporting removed.
WARN_LOG(Log::JIT, "Unaligned icache invalidation of %08x (%08x + %d) at PC=%08x", addr, R(rs), imm, PC);
loggedAlignment = true;
}
if (alignedAddr <= PC + 4 && alignedAddr + size >= PC - 4) {
// This is probably rare so we don't use a static bool.

View File

@ -68,9 +68,6 @@ namespace Reporting
// Internal limiter on number of requests per instance.
static u32 spamProtectionCount = 0;
// Temporarily stores a reference to the hostname.
static std::string lastHostname;
// Keeps track of whether a harmful setting was ever used.
static bool everUnsupported = false;
// Support is cached here to avoid checking it on every single request.
@ -84,22 +81,13 @@ namespace Reporting
static int lastModuleVersion;
static uint32_t lastModuleCrc;
static std::mutex pendingMessageLock;
static std::condition_variable pendingMessageCond;
static std::deque<int> pendingMessages;
static bool pendingMessagesDone = false;
static std::thread messageThread;
static std::thread compatThread;
enum class RequestType
{
enum class RequestType {
NONE,
MESSAGE,
COMPAT,
};
struct Payload
{
struct Payload {
RequestType type;
std::string string1;
std::string string2;
@ -107,8 +95,6 @@ namespace Reporting
int int2;
int int3;
};
static Payload payloadBuffer[PAYLOAD_BUFFER_SIZE];
static int payloadBufferPos = 0;
static std::mutex crcLock;
static std::condition_variable crcCond;
@ -240,10 +226,9 @@ namespace Reporting
}
// Returns the full host (e.g. report.ppsspp.org:80.)
std::string ServerHost()
{
std::string ServerHost() {
if (g_Config.sReportHost.compare("default") == 0)
return "";
return "report.ppsspp.org";
return g_Config.sReportHost;
}
@ -267,20 +252,18 @@ namespace Reporting
}
// Returns only the hostname part (e.g. "report.ppsspp.org".)
static const char *ServerHostname()
{
static std::string ServerHostname() {
if (!IsEnabled())
return NULL;
return "";
std::string host = ServerHost();
size_t length = ServerHostnameLength();
// This means there's no port number - it's already the hostname.
if (length == host.npos)
lastHostname = host;
return host;
else
lastHostname = host.substr(0, length);
return lastHostname.c_str();
return host.substr(0, length);
}
// Returns only the port part (e.g. 80) as an int.
@ -306,36 +289,15 @@ namespace Reporting
return ++spamProtectionCount >= SPAM_LIMIT;
}
bool SendReportRequest(const char *uri, const std::string &data, const std::string &mimeType, Buffer *output = NULL)
{
http::Client http;
net::RequestProgress progress(&pendingMessagesDone);
Buffer theVoid = Buffer::Void();
http.SetUserAgent(StringFromFormat("PPSSPP/%s", PPSSPP_GIT_VERSION));
if (output == nullptr)
output = &theVoid;
const char *serverHost = ServerHostname();
if (!serverHost)
return false;
if (http.Resolve(serverHost, ServerPort())) {
int result = -1;
if (http.Connect()) {
result = http.POST(http::RequestParams(uri), data, mimeType, output, &progress);
http.Disconnect();
}
return result >= 200 && result < 300;
} else {
return false;
}
static void SendReportRequest(const char *uri, const std::string &data, const std::string &mimeType, std::function<void(http::Request &)> callback) {
char url[1024];
std::string hostname = ServerHostname();
int port = ServerPort();
snprintf(url, sizeof(url), "http://%s:%d%s", hostname.c_str(), port, uri);
g_DownloadManager.AsyncPostWithCallback(url, data, mimeType, http::ProgressBarMode::NONE, callback);
}
std::string StripTrailingNull(const std::string &str)
{
std::string StripTrailingNull(const std::string &str) {
size_t pos = str.find_first_of('\0');
if (pos != str.npos)
return str.substr(0, pos);
@ -385,14 +347,12 @@ namespace Reporting
bool MessageAllowed();
void SendReportMessage(const char *message, const char *formatted);
void Init()
{
void Init() {
// New game, clean slate.
spamProtectionCount = 0;
ResetCounts();
everUnsupported = false;
currentSupported = IsSupported();
pendingMessagesDone = false;
Reporting::SetupCallbacks(&MessageAllowed, &SendReportMessage);
lastModuleName.clear();
@ -400,24 +360,14 @@ namespace Reporting
lastModuleCrc = 0;
}
void Shutdown()
{
pendingMessageLock.lock();
pendingMessagesDone = true;
pendingMessageCond.notify_one();
pendingMessageLock.unlock();
if (compatThread.joinable())
compatThread.join();
if (messageThread.joinable())
messageThread.join();
void Shutdown() {
PurgeCRC();
// Just so it can be enabled in the menu again.
Init();
}
void DoState(PointerWrap &p)
{
void DoState(PointerWrap &p) {
const int LATEST_VERSION = 1;
auto s = p.Section("Reporting", 0, LATEST_VERSION);
if (!s || s < LATEST_VERSION) {
@ -429,8 +379,7 @@ namespace Reporting
Do(p, everUnsupported);
}
void UpdateConfig()
{
void UpdateConfig() {
currentSupported = IsSupported();
if (!currentSupported && PSP_IsInited())
everUnsupported = true;
@ -514,13 +463,7 @@ namespace Reporting
}
}
int Process(int pos)
{
SetCurrentThreadName("Report");
AndroidJNIThreadContext jniContext; // destructor detaches
Payload &payload = payloadBuffer[pos];
int Process(const Payload &payload) {
Buffer output;
MultipartFormDataEncoder postdata;
@ -529,21 +472,18 @@ namespace Reporting
AddConfigInfo(postdata);
AddGameplayInfo(postdata);
switch (payload.type)
{
switch (payload.type) {
case RequestType::MESSAGE:
// TODO: Add CRC?
postdata.Add("message", payload.string1);
postdata.Add("value", payload.string2);
// We tend to get corrupted data, this acts as a very primitive verification check.
postdata.Add("verify", payload.string1 + payload.string2);
payload.string1.clear();
payload.string2.clear();
postdata.Finish();
serverWorking = true;
if (!SendReportRequest("/report/message", postdata.ToString(), postdata.GetMimeType()))
serverWorking = false;
SendReportRequest("/report/message", postdata.ToString(), postdata.GetMimeType(), [=](http::Request &req) {
serverWorking = !req.Failed();
});
break;
case RequestType::COMPAT:
@ -556,31 +496,28 @@ namespace Reporting
postdata.Add("crc", StringFromFormat("%08x", RetrieveCRCUnlessPowerSaving(PSP_CoreParameter().fileToStart)));
postdata.Add("suggestions", payload.string1 != "perfect" && payload.string1 != "playable" ? "1" : "0");
AddScreenshotData(postdata, Path(payload.string2));
payload.string1.clear();
payload.string2.clear();
postdata.Finish();
serverWorking = true;
if (!SendReportRequest("/report/compat", postdata.ToString(), postdata.GetMimeType(), &output)) {
serverWorking = false;
} else {
std::string result;
output.TakeAll(&result);
SendReportRequest("/report/compat", postdata.ToString(), postdata.GetMimeType(), [=](http::Request &req) {
if (req.Failed()) {
serverWorking = false;
return;
}
serverWorking = true;
std::string result;
req.buffer().TakeAll(&result);
lastCompatResult.clear();
if (result.empty() || result[0] == '0')
serverWorking = false;
else if (result[0] != '1')
SplitString(result, '\n', lastCompatResult);
}
});
break;
case RequestType::NONE:
break;
}
payload.type = RequestType::NONE;
return 0;
}
@ -643,56 +580,12 @@ namespace Reporting
g_Config.sReportHost = "default";
}
ReportStatus GetStatus()
{
ReportStatus GetStatus() {
if (!serverWorking)
return ReportStatus::FAILING;
for (int pos = 0; pos < PAYLOAD_BUFFER_SIZE; ++pos)
{
if (payloadBuffer[pos].type != RequestType::NONE)
return ReportStatus::BUSY;
}
return ReportStatus::WORKING;
}
int NextFreePos()
{
int start = payloadBufferPos % PAYLOAD_BUFFER_SIZE;
do
{
int pos = payloadBufferPos++ % PAYLOAD_BUFFER_SIZE;
if (payloadBuffer[pos].type == RequestType::NONE)
return pos;
}
while (payloadBufferPos != start);
return -1;
}
int ProcessPending() {
SetCurrentThreadName("Report");
std::unique_lock<std::mutex> guard(pendingMessageLock);
while (!pendingMessagesDone) {
while (!pendingMessages.empty() && !pendingMessagesDone) {
int pos = pendingMessages.front();
pendingMessages.pop_front();
guard.unlock();
Process(pos);
guard.lock();
}
if (pendingMessagesDone) {
break;
}
pendingMessageCond.wait(guard);
}
return 0;
}
bool MessageAllowed() {
if (!IsEnabled() || CheckSpamLimited())
return false;
@ -700,33 +593,20 @@ namespace Reporting
}
void SendReportMessage(const char *message, const char *formatted) {
int pos = NextFreePos();
if (pos == -1)
return;
// MessageAllowed is checked first.
Payload &payload = payloadBuffer[pos];
Payload payload{};
payload.type = RequestType::MESSAGE;
payload.string1 = message;
payload.string2 = formatted;
std::lock_guard<std::mutex> guard(pendingMessageLock);
pendingMessages.push_back(pos);
pendingMessageCond.notify_one();
if (!messageThread.joinable()) {
messageThread = std::thread(ProcessPending);
}
Process(payload);
}
void ReportCompatibility(const char *compat, int graphics, int speed, int gameplay, const std::string &screenshotFilename)
{
void ReportCompatibility(const char *compat, int graphics, int speed, int gameplay, const std::string &screenshotFilename) {
if (!IsEnabled())
return;
int pos = NextFreePos();
if (pos == -1)
return;
Payload &payload = payloadBuffer[pos];
Payload payload{};
payload.type = RequestType::COMPAT;
payload.string1 = compat;
payload.string2 = screenshotFilename;
@ -734,9 +614,7 @@ namespace Reporting
payload.int2 = speed;
payload.int3 = gameplay;
if (compatThread.joinable())
compatThread.join();
compatThread = std::thread(Process, pos);
Process(payload);
}
std::vector<std::string> CompatibilitySuggestions() {

View File

@ -1523,7 +1523,7 @@ Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, G
return tex;
}
void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, int srcStride, GEBufferFormat srcPixelFormat) {
bool FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, int srcStride, GEBufferFormat srcPixelFormat) {
textureCache_->ForgetLastTexture();
shaderManager_->DirtyLastShader();
@ -1531,7 +1531,7 @@ void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, int
float v0 = 0.0f, v1 = 1.0f;
Draw::Texture *pixelsTex = MakePixelTexture(srcPixels, srcPixelFormat, srcStride, 512, 272);
if (!pixelsTex)
return;
return false;
int uvRotation = useBufferedRendering_ ? g_Config.iInternalScreenRotation : ROTATION_LOCKED_HORIZONTAL;
OutputFlags flags = g_Config.iDisplayFilter == SCALE_LINEAR ? OutputFlags::LINEAR : OutputFlags::NEAREST;
@ -1552,6 +1552,8 @@ void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, int
DiscardFramebufferCopy();
currentRenderVfb_ = nullptr;
return true;
}
void FramebufferManagerCommon::SetViewport2D(int x, int y, int w, int h) {
@ -1633,8 +1635,14 @@ void FramebufferManagerCommon::CopyDisplayToOutput(bool reallyDirty) {
if (!vfb) {
if (Memory::IsValidAddress(fbaddr)) {
// The game is displaying something directly from RAM. In GTA, it's decoded video.
DrawFramebufferToOutput(Memory::GetPointerUnchecked(fbaddr), displayStride_, displayFormat_);
// This effectively calls presentation_->NotifyPresent();
// If successful, this effectively calls presentation_->NotifyPresent();
if (!DrawFramebufferToOutput(Memory::GetPointerUnchecked(fbaddr), displayStride_, displayFormat_)) {
if (useBufferedRendering_) {
// Bind and clear the backbuffer. This should be the first time during the frame that it's bound.
draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }, "CopyDisplayToOutput_DrawError");
}
presentation_->NotifyPresent();
}
return;
} else {
DEBUG_LOG(Log::FrameBuf, "Found no FBO to display! displayFBPtr = %08x", fbaddr);

View File

@ -356,7 +356,7 @@ public:
void ReadFramebufferToMemory(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel, Draw::ReadbackMode mode);
void DownloadFramebufferForClut(u32 fb_address, u32 loadBytes);
void DrawFramebufferToOutput(const u8 *srcPixels, int srcStride, GEBufferFormat srcPixelFormat);
bool DrawFramebufferToOutput(const u8 *srcPixels, int srcStride, GEBufferFormat srcPixelFormat);
void DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, RasterChannel channel, const char *tag);

View File

@ -1349,8 +1349,7 @@ void GPUCommon::FlushImm() {
}
void GPUCommon::Execute_Unknown(u32 op, u32 diff) {
if ((op & 0xFFFFFF) != 0)
WARN_LOG_REPORT_ONCE(unknowncmd, Log::G3D, "Unknown GE command : %08x ", op);
// Do nothing. We used to report here, but we're confident we have them all so no need to report unknown.
}
void GPUCommon::FastLoadBoneMatrix(u32 target) {

View File

@ -535,6 +535,7 @@ void GPUCommonHW::CopyDisplayToOutput(bool reallyDirty) {
shaderManager_->DirtyLastShader();
// after this, render pass is active.
framebufferManager_->CopyDisplayToOutput(reallyDirty);
gstate_c.Dirty(DIRTY_TEXTURE_IMAGE);

View File

@ -9,6 +9,7 @@ public:
GPUCommonHW(GraphicsContext *gfxCtx, Draw::DrawContext *draw);
~GPUCommonHW();
// This can fail, and if so no render pass is active.
void CopyDisplayToOutput(bool reallyDirty) override;
void DoState(PointerWrap &p) override;
void DeviceLost() override;

View File

@ -1397,7 +1397,9 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
}
Draw::BackendState state = draw->GetCurrentBackendState();
_assert_msg_(!state.valid || state.passes >= 1, "skipB: %d sw: %d mode: %d back: %d tag: %s", (int)skipBufferEffects, (int)g_Config.bSoftwareRendering, (int)mode, (int)g_Config.iGPUBackend, screenManager()->topScreen()->tag());
if (state.valid) {
_assert_msg_(state.passes >= 1, "skipB: %d sw: %d mode: %d back: %d tag: %s", (int)skipBufferEffects, (int)g_Config.bSoftwareRendering, (int)mode, (int)g_Config.iGPUBackend, screenManager()->topScreen()->tag());
}
// Need to make sure the UI texture is available, for "darken".
screenManager()->getUIContext()->BeginFrame();
@ -1523,8 +1525,10 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
Draw::BackendState state = draw->GetCurrentBackendState();
// We allow if !state.valid, that means it's not the Vulkan backend.
_assert_msg_(!state.valid || state.passes >= 1, "skipB: %d sw: %d mode: %d back: %d bound: %d", (int)skipBufferEffects, (int)g_Config.bSoftwareRendering, (int)mode, (int)g_Config.iGPUBackend, (int)framebufferBound);
// State.valid just states whether the passes parameter has a meaningful value.
if (state.valid) {
_assert_msg_(state.passes >= 1, "skipB: %d sw: %d mode: %d back: %d bound: %d", (int)skipBufferEffects, (int)g_Config.bSoftwareRendering, (int)mode, (int)g_Config.iGPUBackend, (int)framebufferBound);
}
screenManager()->getUIContext()->BeginFrame();

View File

@ -168,7 +168,7 @@ ReportScreen::ReportScreen(const Path &gamePath) // unused gamePath, after remo
ScreenRenderFlags ReportScreen::render(ScreenRenderMode mode) {
_dbg_assert_(mode & ScreenRenderMode::FIRST);
_dbg_assert_(mode & ScreenRenderMode::TOP);
// _dbg_assert_(mode & ScreenRenderMode::TOP);
if (mode & ScreenRenderMode::TOP) {
// We do this after render because we need it to be within the frame (so the screenshot works).