Skip to content

Commit 7f2885e

Browse files
authored
Merge pull request #18810 from hrydgard/more-fixes
More fixes looking at crash reports
2 parents df3ace3 + a07a2e4 commit 7f2885e

15 files changed

+76
-66
lines changed

Common/GPU/OpenGL/GLMemory.cpp

+5-16
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ bool GLRBuffer::Unmap() {
6363
}
6464

6565
GLPushBuffer::GLPushBuffer(GLRenderManager *render, GLuint target, size_t size, const char *tag) : render_(render), size_(size), target_(target), tag_(tag) {
66-
bool res = AddBuffer();
67-
_assert_(res);
66+
AddBuffer();
6867
RegisterGPUMemoryManager(this);
6968
}
7069

@@ -103,7 +102,6 @@ void GLPushBuffer::Unmap() {
103102
void GLPushBuffer::Flush() {
104103
// Must be called from the render thread.
105104
_dbg_assert_(OnRenderThread());
106-
107105
if (buf_ >= buffers_.size()) {
108106
_dbg_assert_msg_(false, "buf_ somehow got out of sync: %d vs %d", (int)buf_, (int)buffers_.size());
109107
return;
@@ -138,17 +136,15 @@ void GLPushBuffer::Flush() {
138136
}
139137
}
140138

141-
bool GLPushBuffer::AddBuffer() {
139+
void GLPushBuffer::AddBuffer() {
142140
// INFO_LOG(G3D, "GLPushBuffer(%s): Allocating %d bytes", tag_, size_);
143141
BufInfo info;
144142
info.localMemory = (uint8_t *)AllocateAlignedMemory(size_, 16);
145-
if (!info.localMemory)
146-
return false;
143+
_assert_msg_(info.localMemory != 0, "GLPushBuffer alloc fail: %d (%s)", (int)size_, tag_);
147144
info.buffer = render_->CreateBuffer(target_, size_, GL_DYNAMIC_DRAW);
148145
info.size = size_;
149146
buf_ = buffers_.size();
150147
buffers_.push_back(info);
151-
return true;
152148
}
153149

154150
void GLPushBuffer::Destroy(bool onRenderThread) {
@@ -178,13 +174,7 @@ void GLPushBuffer::NextBuffer(size_t minSize) {
178174
while (size_ < minSize) {
179175
size_ <<= 1;
180176
}
181-
182-
bool res = AddBuffer();
183-
_assert_(res);
184-
if (!res) {
185-
// Let's try not to crash at least?
186-
buf_ = 0;
187-
}
177+
AddBuffer();
188178
}
189179

190180
// Now, move to the next buffer and map it.
@@ -219,8 +209,7 @@ void GLPushBuffer::Defragment() {
219209

220210
// Set some sane but very free limits. If there's another spike, we'll just allocate more anyway.
221211
size_ = std::min(std::max(newSize, (size_t)65536), (size_t)(512 * 1024 * 1024));
222-
bool res = AddBuffer();
223-
_assert_msg_(res, "AddBuffer failed");
212+
AddBuffer();
224213
}
225214

226215
size_t GLPushBuffer::GetTotalSize() const {

Common/GPU/OpenGL/GLMemory.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ class GLPushBuffer : public GPUMemoryManager {
169169
void UnmapDevice();
170170

171171
private:
172-
bool AddBuffer();
172+
void AddBuffer(); // asserts on failure
173173
void NextBuffer(size_t minSize);
174174
void Defragment();
175175

Common/GPU/Vulkan/VulkanContext.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,11 @@ VkResult VulkanContext::CreateDevice() {
697697
deviceFeatures_.enabled.standard.shaderCullDistance = deviceFeatures_.available.standard.shaderCullDistance;
698698
deviceFeatures_.enabled.standard.geometryShader = deviceFeatures_.available.standard.geometryShader;
699699
deviceFeatures_.enabled.standard.sampleRateShading = deviceFeatures_.available.standard.sampleRateShading;
700+
701+
#ifdef _DEBUG
702+
// For debugging! Although, it might hide problems, so turning it off. Can be useful to rule out classes of issues.
703+
// deviceFeatures_.enabled.standard.robustBufferAccess = deviceFeatures_.available.standard.robustBufferAccess;
704+
#endif
700705

701706
deviceFeatures_.enabled.multiview = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES };
702707
if (extensionsLookup_.KHR_multiview) {

Common/GPU/Vulkan/VulkanFrameData.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ void FrameData::Submit(VulkanContext *vulkan, FrameSubmitType type, FrameDataSha
201201
}
202202

203203
if (hasPresentCommands) {
204-
_dbg_assert_(type == FrameSubmitType::FinishFrame);
204+
_dbg_assert_(type != FrameSubmitType::Pending);
205205
VkResult res = vkEndCommandBuffer(presentCmd);
206206

207207
_assert_msg_(res == VK_SUCCESS, "vkEndCommandBuffer failed (present)! result=%s", VulkanResultToString(res));

Common/GPU/Vulkan/VulkanRenderManager.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,9 @@ void VulkanRenderManager::PollPresentTiming() {
585585
// Poll for information about completed frames.
586586
// NOTE: We seem to get the information pretty late! Like after 6 frames, which is quite weird.
587587
// Tested on POCO F4.
588-
if (vulkan_->Extensions().GOOGLE_display_timing) {
588+
// TODO: Getting validation errors that this should be called from the thread doing the presenting.
589+
// Probably a fair point. For now, we turn it off.
590+
if (measurePresentTime_ && vulkan_->Extensions().GOOGLE_display_timing) {
589591
uint32_t count = 0;
590592
vkGetPastPresentationTimingGOOGLE(vulkan_->GetDevice(), vulkan_->GetSwapchain(), &count, nullptr);
591593
if (count > 0) {

Common/GPU/Vulkan/thin3d_vulkan.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -1543,6 +1543,10 @@ std::vector<std::string> VKContext::GetFeatureList() const {
15431543
AddFeature(features, "shaderCullDistance", available.shaderCullDistance, enabled.shaderCullDistance);
15441544
AddFeature(features, "occlusionQueryPrecise", available.occlusionQueryPrecise, enabled.occlusionQueryPrecise);
15451545
AddFeature(features, "multiDrawIndirect", available.multiDrawIndirect, enabled.multiDrawIndirect);
1546+
AddFeature(features, "robustBufferAccess", available.robustBufferAccess, enabled.robustBufferAccess);
1547+
AddFeature(features, "fullDrawIndexUint32", available.fullDrawIndexUint32, enabled.fullDrawIndexUint32);
1548+
AddFeature(features, "fragmentStoresAndAtomics", available.fragmentStoresAndAtomics, enabled.fragmentStoresAndAtomics);
1549+
AddFeature(features, "shaderInt16", available.shaderInt16, enabled.shaderInt16);
15461550

15471551
AddFeature(features, "multiview", vulkan_->GetDeviceFeatures().available.multiview.multiview, vulkan_->GetDeviceFeatures().enabled.multiview.multiview);
15481552
AddFeature(features, "multiviewGeometryShader", vulkan_->GetDeviceFeatures().available.multiview.multiviewGeometryShader, vulkan_->GetDeviceFeatures().enabled.multiview.multiviewGeometryShader);

Core/HLE/Plugins.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,11 @@ static std::vector<PluginInfo> FindPlugins(const std::string &gameID, const std:
108108
std::set<std::string> matches;
109109

110110
std::string gameIni;
111-
if (ini.GetOrCreateSection("games")->Get(gameID.c_str(), &gameIni, "")) {
111+
112+
// TODO: Should just use getsection and fail the ini if not found, I guess.
113+
Section *games = ini.GetOrCreateSection("games");
114+
115+
if (games->Get(gameID.c_str(), &gameIni, "")) {
112116
if (!strcasecmp(gameIni.c_str(), "true")) {
113117
matches.insert("plugin.ini");
114118
} else if (!strcasecmp(gameIni.c_str(), "false")){
@@ -118,7 +122,7 @@ static std::vector<PluginInfo> FindPlugins(const std::string &gameID, const std:
118122
}
119123
}
120124

121-
if (ini.GetOrCreateSection("games")->Get("ALL", &gameIni, "")) {
125+
if (games->Get("ALL", &gameIni, "")) {
122126
if (!strcasecmp(gameIni.c_str(), "true")) {
123127
matches.insert("plugin.ini");
124128
} else if (!gameIni.empty()) {

GPU/Common/DrawEngineCommon.h

+1
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ class DrawEngineCommon {
194194
gpuStats.numDrawCalls += numDrawInds_;
195195
gpuStats.numVertexDecodes += numDrawVerts_;
196196
gpuStats.numVertsSubmitted += vertexCountInDrawCalls_;
197+
gpuStats.numVertsDecoded += numDecodedVerts_;
197198

198199
indexGen.Reset();
199200
numDecodedVerts_ = 0;

GPU/Common/PresentationCommon.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u
801801
if (usePostShader) {
802802
// When we render to temp framebuffers during post, we switch position, not UV.
803803
// The flipping here is only because D3D has a clip coordinate system that doesn't match their screen coordinate system.
804+
// The flipping here is only because D3D has a clip coordinate system that doesn't match their screen coordinate system.
804805
bool flipped = flags & OutputFlags::POSITION_FLIPPED;
805806
float y0 = flipped ? 1.0f : -1.0f;
806807
float y1 = flipped ? -1.0f : 1.0f;

GPU/GPU.h

+2
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ struct GPUStatistics {
8080
numDrawSyncs = 0;
8181
numListSyncs = 0;
8282
numVertsSubmitted = 0;
83+
numVertsDecoded = 0;
8384
numUncachedVertsDrawn = 0;
8485
numTextureInvalidations = 0;
8586
numTextureInvalidationsByFramebuffer = 0;
@@ -119,6 +120,7 @@ struct GPUStatistics {
119120
int numBBOXJumps;
120121
int numPlaneUpdates;
121122
int numVertsSubmitted;
123+
int numVertsDecoded;
122124
int numUncachedVertsDrawn;
123125
int numTextureInvalidations;
124126
int numTextureInvalidationsByFramebuffer;

GPU/GPUCommonHW.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1749,7 +1749,7 @@ size_t GPUCommonHW::FormatGPUStatsCommon(char *buffer, size_t size) {
17491749
return snprintf(buffer, size,
17501750
"DL processing time: %0.2f ms, %d drawsync, %d listsync\n"
17511751
"Draw: %d (%d dec, %d culled), flushes %d, clears %d, bbox jumps %d (%d updates)\n"
1752-
"Vertices: %d drawn: %d\n"
1752+
"Vertices: %d dec: %d drawn: %d\n"
17531753
"FBOs active: %d (evaluations: %d)\n"
17541754
"Textures: %d, dec: %d, invalidated: %d, hashed: %d kB\n"
17551755
"readbacks %d (%d non-block), upload %d (cached %d), depal %d\n"
@@ -1768,6 +1768,7 @@ size_t GPUCommonHW::FormatGPUStatsCommon(char *buffer, size_t size) {
17681768
gpuStats.numBBOXJumps,
17691769
gpuStats.numPlaneUpdates,
17701770
gpuStats.numVertsSubmitted,
1771+
gpuStats.numVertsDecoded,
17711772
gpuStats.numUncachedVertsDrawn,
17721773
(int)framebufferManager_->NumVFBs(),
17731774
gpuStats.numFramebufferEvaluations,

GPU/Vulkan/DrawEngineVulkan.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ void DrawEngineVulkan::DoFlush() {
224224
if (gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS) && !gstate.isModeClear() && gstate.isTextureMapEnabled()) {
225225
textureCache_->SetTexture();
226226
gstate_c.Clean(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS);
227+
// NOTE: After this is set, we MUST call ApplyTexture before returning.
227228
textureNeedsApply = true;
228229
} else if (gstate.getTextureAddress(0) == (gstate.getFrameBufRawAddress() | 0x04000000)) {
229230
// This catches the case of clearing a texture.

UI/EmuScreen.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -1326,7 +1326,7 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
13261326
// We only bind it in FramebufferManager::CopyDisplayToOutput (unless non-buffered)...
13271327
// We do, however, start the frame in other ways.
13281328

1329-
if ((g_Config.bSkipBufferEffects && !g_Config.bSoftwareRendering) || Core_IsStepping()) {
1329+
if ((skipBufferEffects && !g_Config.bSoftwareRendering) || Core_IsStepping()) {
13301330
// We need to clear here already so that drawing during the frame is done on a clean slate.
13311331
if (Core_IsStepping() && gpuStats.numFlips != 0) {
13321332
draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::KEEP, RPAction::CLEAR, RPAction::CLEAR }, "EmuScreen_BackBuffer");
@@ -1348,12 +1348,13 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
13481348
System_Notify(SystemNotification::KEEP_SCREEN_AWAKE);
13491349
} else if (!Core_ShouldRunBehind() && strcmp(screenManager()->topScreen()->tag(), "DevMenu") != 0) {
13501350
// Just to make sure.
1351-
if (PSP_IsInited() && !g_Config.bSkipBufferEffects) {
1351+
if (PSP_IsInited() && !skipBufferEffects) {
13521352
PSP_BeginHostFrame();
13531353
gpu->CopyDisplayToOutput(true);
13541354
PSP_EndHostFrame();
1355-
} else {
1356-
draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR, }, "EmuScreen_Stepping");
1355+
}
1356+
if (!framebufferBound && !gpu->PresentedThisFrame()) {
1357+
draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR, }, "EmuScreen_Behind");
13571358
}
13581359
// Need to make sure the UI texture is available, for "darken".
13591360
screenManager()->getUIContext()->BeginFrame();

UI/NativeApp.cpp

+18-17
Original file line numberDiff line numberDiff line change
@@ -1061,23 +1061,6 @@ void NativeFrame(GraphicsContext *graphicsContext) {
10611061
ProcessWheelRelease(NKCODE_EXT_MOUSEWHEEL_UP, startTime, false);
10621062
ProcessWheelRelease(NKCODE_EXT_MOUSEWHEEL_DOWN, startTime, false);
10631063

1064-
std::vector<PendingMessage> toProcess;
1065-
{
1066-
std::lock_guard<std::mutex> lock(pendingMutex);
1067-
toProcess = std::move(pendingMessages);
1068-
pendingMessages.clear();
1069-
}
1070-
1071-
for (const auto &item : toProcess) {
1072-
if (HandleGlobalMessage(item.message, item.value)) {
1073-
// TODO: Add a to-string thingy.
1074-
INFO_LOG(SYSTEM, "Handled global message: %d / %s", (int)item.message, item.value.c_str());
1075-
}
1076-
g_screenManager->sendMessage(item.message, item.value.c_str());
1077-
}
1078-
1079-
g_requestManager.ProcessRequests();
1080-
10811064
// it's ok to call this redundantly with DoFrame from EmuScreen
10821065
Achievements::Idle();
10831066

@@ -1104,6 +1087,24 @@ void NativeFrame(GraphicsContext *graphicsContext) {
11041087

11051088
g_screenManager->update();
11061089

1090+
// Do this after g_screenManager.update() so we can receive setting changes before rendering.
1091+
std::vector<PendingMessage> toProcess;
1092+
{
1093+
std::lock_guard<std::mutex> lock(pendingMutex);
1094+
toProcess = std::move(pendingMessages);
1095+
pendingMessages.clear();
1096+
}
1097+
1098+
for (const auto &item : toProcess) {
1099+
if (HandleGlobalMessage(item.message, item.value)) {
1100+
// TODO: Add a to-string thingy.
1101+
INFO_LOG(SYSTEM, "Handled global message: %d / %s", (int)item.message, item.value.c_str());
1102+
}
1103+
g_screenManager->sendMessage(item.message, item.value.c_str());
1104+
}
1105+
1106+
g_requestManager.ProcessRequests();
1107+
11071108
// Apply the UIContext bounds as a 2D transformation matrix.
11081109
// TODO: This should be moved into the draw context...
11091110
Matrix4x4 ortho = ComputeOrthoMatrix(g_display.dp_xres, g_display.dp_yres);

android/jni/app-android.cpp

+21-23
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,6 @@ enum class EmuThreadState {
115115
static std::thread emuThread;
116116
static std::atomic<int> emuThreadState((int)EmuThreadState::DISABLED);
117117

118-
void UpdateRunLoopAndroid(JNIEnv *env);
119-
120118
AndroidAudioState *g_audioState;
121119

122120
struct FrameCommand {
@@ -202,6 +200,8 @@ int utimensat(int fd, const char *path, const struct timespec times[2]) {
202200
}
203201
#endif
204202

203+
static void ProcessFrameCommands(JNIEnv *env);
204+
205205
void AndroidLogger::Log(const LogMessage &message) {
206206
int mode;
207207
switch (message.level) {
@@ -337,8 +337,22 @@ static void EmuThreadFunc() {
337337
// We just call the update/render loop here.
338338
emuThreadState = (int)EmuThreadState::RUNNING;
339339
while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) {
340-
UpdateRunLoopAndroid(env);
340+
{
341+
std::lock_guard<std::mutex> renderGuard(renderLock);
342+
NativeFrame(graphicsContext);
343+
}
344+
345+
std::lock_guard<std::mutex> guard(frameCommandLock);
346+
if (!nativeActivity) {
347+
ERROR_LOG(SYSTEM, "No activity, clearing commands");
348+
while (!frameCommands.empty())
349+
frameCommands.pop();
350+
return;
351+
}
352+
// Still under lock here.
353+
ProcessFrameCommands(env);
341354
}
355+
342356
INFO_LOG(SYSTEM, "QUIT_REQUESTED found, left EmuThreadFunc loop. Setting state to STOPPED.");
343357
emuThreadState = (int)EmuThreadState::STOPPED;
344358

@@ -371,8 +385,6 @@ static void EmuThreadJoin() {
371385
INFO_LOG(SYSTEM, "EmuThreadJoin - joined");
372386
}
373387

374-
static void ProcessFrameCommands(JNIEnv *env);
375-
376388
static void PushCommand(std::string cmd, std::string param) {
377389
std::lock_guard<std::mutex> guard(frameCommandLock);
378390
frameCommands.push(FrameCommand(cmd, param));
@@ -1162,23 +1174,6 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendRequestResult(JNIEn
11621174
}
11631175
}
11641176

1165-
void UpdateRunLoopAndroid(JNIEnv *env) {
1166-
{
1167-
std::lock_guard<std::mutex> renderGuard(renderLock);
1168-
NativeFrame(graphicsContext);
1169-
}
1170-
1171-
std::lock_guard<std::mutex> guard(frameCommandLock);
1172-
if (!nativeActivity) {
1173-
ERROR_LOG(SYSTEM, "No activity, clearing commands");
1174-
while (!frameCommands.empty())
1175-
frameCommands.pop();
1176-
return;
1177-
}
1178-
// Still under lock here.
1179-
ProcessFrameCommands(env);
1180-
}
1181-
11821177
extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayRender(JNIEnv *env, jobject obj) {
11831178
// This doesn't get called on the Vulkan path.
11841179
_assert_(useCPUThread);
@@ -1641,7 +1636,10 @@ static void VulkanEmuThread(ANativeWindow *wnd) {
16411636
std::lock_guard<std::mutex> renderGuard(renderLock);
16421637
NativeFrame(graphicsContext);
16431638
}
1644-
ProcessFrameCommands(env);
1639+
{
1640+
std::lock_guard<std::mutex> guard(frameCommandLock);
1641+
ProcessFrameCommands(env);
1642+
}
16451643
}
16461644
INFO_LOG(G3D, "Leaving Vulkan main loop.");
16471645
} else {

0 commit comments

Comments
 (0)