Skip to content

Commit ccaf244

Browse files
authored
Merge pull request #18793 from hrydgard/render-pass-cleanup
Fix GE framedump playback on Vulkan
2 parents d7e5928 + 8b99c9f commit ccaf244

8 files changed

+35
-19
lines changed

Common/GPU/Vulkan/VulkanFrameData.cpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ VkCommandBuffer FrameData::GetInitCmd(VulkanContext *vulkan) {
169169
return initCmd;
170170
}
171171

172-
void FrameData::SubmitPending(VulkanContext *vulkan, FrameSubmitType type, FrameDataShared &sharedData) {
172+
void FrameData::Submit(VulkanContext *vulkan, FrameSubmitType type, FrameDataShared &sharedData) {
173173
VkCommandBuffer cmdBufs[3];
174174
int numCmdBufs = 0;
175175

@@ -200,14 +200,16 @@ void FrameData::SubmitPending(VulkanContext *vulkan, FrameSubmitType type, Frame
200200
hasMainCommands = false;
201201
}
202202

203-
if (hasPresentCommands && type != FrameSubmitType::Pending) {
203+
if (hasPresentCommands) {
204+
_dbg_assert_(type == FrameSubmitType::FinishFrame);
204205
VkResult res = vkEndCommandBuffer(presentCmd);
206+
205207
_assert_msg_(res == VK_SUCCESS, "vkEndCommandBuffer failed (present)! result=%s", VulkanResultToString(res));
206208

207209
cmdBufs[numCmdBufs++] = presentCmd;
208210
hasPresentCommands = false;
209211

210-
if (type == FrameSubmitType::Present) {
212+
if (type == FrameSubmitType::FinishFrame) {
211213
fenceToTrigger = fence;
212214
}
213215
}
@@ -219,15 +221,15 @@ void FrameData::SubmitPending(VulkanContext *vulkan, FrameSubmitType type, Frame
219221

220222
VkSubmitInfo submit_info{ VK_STRUCTURE_TYPE_SUBMIT_INFO };
221223
VkPipelineStageFlags waitStage[1]{ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
222-
if (type == FrameSubmitType::Present && !skipSwap) {
224+
if (type == FrameSubmitType::FinishFrame && !skipSwap) {
223225
_dbg_assert_(hasAcquired);
224226
submit_info.waitSemaphoreCount = 1;
225227
submit_info.pWaitSemaphores = &acquireSemaphore;
226228
submit_info.pWaitDstStageMask = waitStage;
227229
}
228230
submit_info.commandBufferCount = (uint32_t)numCmdBufs;
229231
submit_info.pCommandBuffers = cmdBufs;
230-
if (type == FrameSubmitType::Present && !skipSwap) {
232+
if (type == FrameSubmitType::FinishFrame && !skipSwap) {
231233
submit_info.signalSemaphoreCount = 1;
232234
submit_info.pSignalSemaphores = &renderingCompleteSemaphore;
233235
}

Common/GPU/Vulkan/VulkanFrameData.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ struct FrameDataShared {
6565
enum class FrameSubmitType {
6666
Pending,
6767
Sync,
68-
Present,
68+
FinishFrame,
6969
};
7070

7171
// Per-frame data, round-robin so we can overlap submission with execution of the previous frame.
@@ -121,8 +121,8 @@ struct FrameData {
121121
// Generally called from the main thread, unlike most of the rest.
122122
VkCommandBuffer GetInitCmd(VulkanContext *vulkan);
123123

124-
// This will only submit if we are actually recording init commands.
125-
void SubmitPending(VulkanContext *vulkan, FrameSubmitType type, FrameDataShared &shared);
124+
// Submits pending command buffers.
125+
void Submit(VulkanContext *vulkan, FrameSubmitType type, FrameDataShared &shared);
126126

127127
private:
128128
// Metadata for logging etc

Common/GPU/Vulkan/VulkanQueueRunner.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ void VulkanQueueRunner::RunSteps(std::vector<VKRStep *> &steps, int curFrame, Fr
369369
if (emitLabels) {
370370
vkCmdEndDebugUtilsLabelEXT(cmd);
371371
}
372-
frameData.SubmitPending(vulkan_, FrameSubmitType::Pending, frameDataShared);
372+
frameData.Submit(vulkan_, FrameSubmitType::Pending, frameDataShared);
373373

374374
// When stepping in the GE debugger, we can end up here multiple times in a "frame".
375375
// So only acquire once.

Common/GPU/Vulkan/VulkanRenderManager.cpp

+9-3
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,11 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR
952952
EndCurRenderStep();
953953
}
954954

955+
// Sanity check that we don't have binds to the backbuffer before binds to other buffers. It must always be bound last.
956+
if (steps_.size() >= 1 && steps_.back()->stepType == VKRStepType::RENDER && steps_.back()->render.framebuffer == nullptr && fb != nullptr) {
957+
_dbg_assert_(false);
958+
}
959+
955960
// Older Mali drivers have issues with depth and stencil don't match load/clear/etc.
956961
// TODO: Determine which versions and do this only where necessary.
957962
u32 lateClearMask = 0;
@@ -1383,6 +1388,7 @@ void VulkanRenderManager::Finish() {
13831388
EndCurRenderStep();
13841389

13851390
// Let's do just a bit of cleanup on render commands now.
1391+
// TODO: Should look into removing this.
13861392
for (auto &step : steps_) {
13871393
if (step->stepType == VKRStepType::RENDER) {
13881394
CleanupRenderCommands(&step->commands);
@@ -1469,7 +1475,7 @@ void VulkanRenderManager::Run(VKRRenderThreadTask &task) {
14691475
if (!frameTimeHistory_[frameData.frameId].firstSubmit) {
14701476
frameTimeHistory_[frameData.frameId].firstSubmit = time_now_d();
14711477
}
1472-
frameData.SubmitPending(vulkan_, FrameSubmitType::Pending, frameDataShared_);
1478+
frameData.Submit(vulkan_, FrameSubmitType::Pending, frameDataShared_);
14731479

14741480
// Flush descriptors.
14751481
double descStart = time_now_d();
@@ -1506,12 +1512,12 @@ void VulkanRenderManager::Run(VKRRenderThreadTask &task) {
15061512

15071513
switch (task.runType) {
15081514
case VKRRunType::SUBMIT:
1509-
frameData.SubmitPending(vulkan_, FrameSubmitType::Present, frameDataShared_);
1515+
frameData.Submit(vulkan_, FrameSubmitType::FinishFrame, frameDataShared_);
15101516
break;
15111517

15121518
case VKRRunType::SYNC:
15131519
// The submit will trigger the readbackFence, and also do the wait for it.
1514-
frameData.SubmitPending(vulkan_, FrameSubmitType::Sync, frameDataShared_);
1520+
frameData.Submit(vulkan_, FrameSubmitType::Sync, frameDataShared_);
15151521

15161522
if (useRenderThread_) {
15171523
std::unique_lock<std::mutex> lock(syncMutex_);

GPU/Common/FramebufferManagerCommon.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -1547,6 +1547,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput(bool reallyDirty) {
15471547
// No framebuffer to display! Clear to black.
15481548
if (useBufferedRendering_) {
15491549
draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }, "CopyDisplayToOutput");
1550+
presentation_->NotifyPresent();
15501551
}
15511552
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE);
15521553
return;

GPU/Common/PresentationCommon.h

+4
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ class PresentationCommon {
104104
bool PresentedThisFrame() const {
105105
return presentedThisFrame_;
106106
}
107+
void NotifyPresent() {
108+
// Something else did the present, skipping PresentationCommon.
109+
presentedThisFrame_ = true;
110+
}
107111

108112
void DeviceLost();
109113
void DeviceRestore(Draw::DrawContext *draw);

GPU/Debugger/Playback.cpp

+8-5
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ class DumpExecute {
308308
void Memcpy(u32 ptr, u32 sz);
309309
void Texture(int level, u32 ptr, u32 sz);
310310
void Framebuf(int level, u32 ptr, u32 sz);
311-
void Display(u32 ptr, u32 sz);
311+
void Display(u32 ptr, u32 sz, bool allowFlip);
312312
void EdramTrans(u32 ptr, u32 sz);
313313

314314
u32 execMemcpyDest = 0;
@@ -616,7 +616,7 @@ void DumpExecute::Framebuf(int level, u32 ptr, u32 sz) {
616616
}
617617
}
618618

619-
void DumpExecute::Display(u32 ptr, u32 sz) {
619+
void DumpExecute::Display(u32 ptr, u32 sz, bool allowFlip) {
620620
struct DisplayBufData {
621621
PSPPointer<u8> topaddr;
622622
int linesize, pixelFormat;
@@ -628,7 +628,9 @@ void DumpExecute::Display(u32 ptr, u32 sz) {
628628
SyncStall();
629629

630630
__DisplaySetFramebuf(disp->topaddr.ptr, disp->linesize, disp->pixelFormat, 1);
631-
__DisplaySetFramebuf(disp->topaddr.ptr, disp->linesize, disp->pixelFormat, 0);
631+
if (allowFlip) {
632+
__DisplaySetFramebuf(disp->topaddr.ptr, disp->linesize, disp->pixelFormat, 0);
633+
}
632634
}
633635

634636
void DumpExecute::EdramTrans(u32 ptr, u32 sz) {
@@ -657,7 +659,8 @@ bool DumpExecute::Run() {
657659
if (gpu)
658660
gpu->SetAddrTranslation(0x400);
659661

660-
for (const Command &cmd : commands_) {
662+
for (size_t i = 0; i < commands_.size(); i++) {
663+
const Command &cmd = commands_[i];
661664
switch (cmd.type) {
662665
case CommandType::INIT:
663666
Init(cmd.ptr, cmd.sz);
@@ -726,7 +729,7 @@ bool DumpExecute::Run() {
726729
break;
727730

728731
case CommandType::DISPLAY:
729-
Display(cmd.ptr, cmd.sz);
732+
Display(cmd.ptr, cmd.sz, i == commands_.size() - 1);
730733
break;
731734

732735
default:

UI/EmuScreen.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1342,13 +1342,13 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
13421342
if (mode & ScreenRenderMode::TOP) {
13431343
System_Notify(SystemNotification::KEEP_SCREEN_AWAKE);
13441344
} else if (!Core_ShouldRunBehind() && strcmp(screenManager()->topScreen()->tag(), "DevMenu") != 0) {
1345-
// Not on top. Let's not execute, only draw the image.
1346-
draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR, }, "EmuScreen_Stepping");
13471345
// Just to make sure.
13481346
if (PSP_IsInited() && !g_Config.bSkipBufferEffects) {
13491347
PSP_BeginHostFrame();
13501348
gpu->CopyDisplayToOutput(true);
13511349
PSP_EndHostFrame();
1350+
} else {
1351+
draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR, }, "EmuScreen_Stepping");
13521352
}
13531353
// Need to make sure the UI texture is available, for "darken".
13541354
screenManager()->getUIContext()->BeginFrame();

0 commit comments

Comments
 (0)