Skip to content

Commit

Permalink
Merge pull request #18754 from hrydgard/more-beta-fixes
Browse files Browse the repository at this point in the history
More beta fixes
  • Loading branch information
hrydgard committed Jan 24, 2024
2 parents 2a7f3c5 + 0d2e5c3 commit 138890a
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 17 deletions.
5 changes: 2 additions & 3 deletions Common/GPU/Vulkan/VulkanQueueRunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1703,9 +1703,8 @@ void VulkanQueueRunner::PerformBlit(const VKRStep &step, VkCommandBuffer cmd) {

// We can't copy only depth or only stencil unfortunately.
if (step.blit.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
_dbg_assert_(src->depth.image != VK_NULL_HANDLE);
_dbg_assert_(dst->depth.image != VK_NULL_HANDLE);

_assert_(src->depth.image != VK_NULL_HANDLE);
_assert_(dst->depth.image != VK_NULL_HANDLE);
SetupTransitionToTransferSrc(src->depth, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, &recordBarrier_);
SetupTransitionToTransferDst(dst->depth, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, &recordBarrier_);
}
Expand Down
30 changes: 23 additions & 7 deletions Common/GPU/Vulkan/VulkanRenderManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,9 @@ void VulkanRenderManager::StartThreads() {

// Called from main thread.
void VulkanRenderManager::StopThreads() {
// Not sure this is a sensible check - should be ok even if not.
// _dbg_assert_(steps_.empty());

if (useRenderThread_) {
_dbg_assert_(renderThread_.joinable());
// Tell the render thread to quit when it's done.
Expand Down Expand Up @@ -400,7 +403,6 @@ void VulkanRenderManager::StopThreads() {

INFO_LOG(G3D, "Vulkan compiler thread joined. Now wait for any straggling compile tasks.");
CreateMultiPipelinesTask::WaitForAll();
_dbg_assert_(steps_.empty());
}

void VulkanRenderManager::DestroyBackbuffers() {
Expand All @@ -413,6 +415,15 @@ void VulkanRenderManager::DestroyBackbuffers() {
VulkanRenderManager::~VulkanRenderManager() {
INFO_LOG(G3D, "VulkanRenderManager destructor");

{
std::unique_lock<std::mutex> lock(compileMutex_);
_assert_(compileQueue_.empty());
}

if (useRenderThread_) {
_dbg_assert_(!renderThread_.joinable());
}

_dbg_assert_(!runCompileThread_); // StopThread should already have been called from DestroyBackbuffers.

vulkan_->WaitUntilQueueIdle();
Expand All @@ -433,9 +444,6 @@ void VulkanRenderManager::CompileThreadFunc() {
std::vector<CompileQueueEntry> toCompile;
{
std::unique_lock<std::mutex> lock(compileMutex_);
// TODO: Should this be while?
// It may be beneficial also to unlock and wait a little bit to see if we get some more shaders
// so we can do a better job of thread-sorting them.
if (compileQueue_.empty() && runCompileThread_) {
compileCond_.wait(lock);
}
Expand Down Expand Up @@ -490,6 +498,9 @@ void VulkanRenderManager::CompileThreadFunc() {
// Hold off just a bit before we check again, to allow bunches of pipelines to collect.
sleep_ms(1);
}

std::unique_lock<std::mutex> lock(compileMutex_);
_assert_(compileQueue_.empty());
}

void VulkanRenderManager::RenderThreadFunc() {
Expand Down Expand Up @@ -522,9 +533,8 @@ void VulkanRenderManager::RenderThreadFunc() {
}

// Wait for the device to be done with everything, before tearing stuff down.
// TODO: Do we need this?
// TODO: Do we really need this? It's probably a good idea, though.
vkDeviceWaitIdle(vulkan_->GetDevice());

VLOG("PULL: Quitting");
}

Expand Down Expand Up @@ -956,6 +966,7 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR
step->render.numReads = 0;
step->render.finalColorLayout = !fb ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED;
step->render.finalDepthStencilLayout = !fb ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED;
// pipelineFlags, renderArea and renderPassType get filled in when we finalize the step. Do not read from them before that.
step->tag = tag;
steps_.push_back(step);

Expand Down Expand Up @@ -1282,8 +1293,13 @@ void VulkanRenderManager::BlitFramebuffer(VKRFramebuffer *src, VkRect2D srcRect,

EndCurRenderStep();

VKRStep *step = new VKRStep{ VKRStepType::BLIT };
// Sanity check. Added an assert to try to gather more info.
if (aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
_assert_msg_(src->depth.image != VK_NULL_HANDLE, "%s", src->Tag());
_assert_msg_(dst->depth.image != VK_NULL_HANDLE, "%s", dst->Tag());
}

VKRStep *step = new VKRStep{ VKRStepType::BLIT };
step->blit.aspectMask = aspectMask;
step->blit.src = src;
step->blit.srcRect = srcRect;
Expand Down
4 changes: 4 additions & 0 deletions Common/Thread/Promise.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,13 @@ class Promise {
// A promise should have been fulfilled before it's destroyed.
_assert_(ready_);
_assert_(!rx_);
sentinel_ = 0xeeeeeeee;
}

// Returns T if the data is ready, nullptr if it's not.
// Obviously, can only be used if T is nullable, otherwise it won't compile.
T Poll() {
_assert_(sentinel_ == 0xffc0ffee);
std::lock_guard<std::mutex> guard(readyMutex_);
if (ready_) {
return data_;
Expand All @@ -103,6 +105,7 @@ class Promise {
}

T BlockUntilReady() {
_assert_(sentinel_ == 0xffc0ffee);
std::lock_guard<std::mutex> guard(readyMutex_);
if (ready_) {
return data_;
Expand All @@ -128,4 +131,5 @@ class Promise {
bool ready_ = false;
std::mutex readyMutex_;
Mailbox<T> *rx_ = nullptr;
uint32_t sentinel_ = 0xffc0ffee;
};
2 changes: 1 addition & 1 deletion GPU/Vulkan/GPU_Vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ GPU_Vulkan::~GPU_Vulkan() {

SaveCache(shaderCachePath_);

// Super important to delete pipeline manager FIRST, before clearing shaders, so we wait for all pending pipelines to finish compiling.
// StopThreads should have ensured that no pipelines are queued to compile at this point. So we can tear it down.
delete pipelineManager_;
pipelineManager_ = nullptr;

Expand Down
2 changes: 1 addition & 1 deletion UI/DebugOverlay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ Invalid / Unknown (%d)
}
if (checkingISO) {
tips += "* (waiting for CRC...)\n";
} else if (!isoOK) {
} else if (!isoOK) { // TODO: Should check that it actually is an ISO and not a homebrew
tips += "* Verify and possibly re-dump your ISO\n (CRC not recognized)\n";
}
if (!tips.empty()) {
Expand Down
15 changes: 10 additions & 5 deletions UI/EmuScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1306,6 +1306,8 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {

bool skipBufferEffects = g_Config.bSkipBufferEffects;

bool framebufferBound = false;

if (mode & ScreenRenderMode::FIRST) {
// Actually, always gonna be first when it exists (?)

Expand All @@ -1327,6 +1329,7 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
draw->SetViewport(viewport);
draw->SetScissorRect(0, 0, g_display.pixel_xres, g_display.pixel_yres);
skipBufferEffects = true;
framebufferBound = true;
}
draw->SetTargetSize(g_display.pixel_xres, g_display.pixel_yres);
}
Expand Down Expand Up @@ -1387,7 +1390,6 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
Core_UpdateDebugStats((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::DEBUG_STATS || g_Config.bLogFrameDrops);

bool blockedExecution = Achievements::IsBlockingExecution();
bool rebind = false;
uint32_t clearColor = 0;
if (!blockedExecution) {
PSP_BeginHostFrame();
Expand All @@ -1411,11 +1413,13 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
bool dangerousSettings = !Reporting::IsSupported();
clearColor = dangerousSettings ? 0xFF900050 : 0xFF900000;
draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR, clearColor }, "EmuScreen_RuntimeError");
framebufferBound = true;
// The info is drawn later in renderUI
} else {
// If we're stepping, it's convenient not to clear the screen entirely, so we copy display to output.
// This won't work in non-buffered, but that's fine.
draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR, clearColor }, "EmuScreen_Stepping");
framebufferBound = true;
// Just to make sure.
if (PSP_IsInited()) {
gpu->CopyDisplayToOutput(true);
Expand All @@ -1427,7 +1431,7 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
// Didn't actually reach the end of the frame, ran out of the blockTicks cycles.
// In this case we need to bind and wipe the backbuffer, at least.
// It's possible we never ended up outputted anything - make sure we have the backbuffer cleared
rebind = true;
// So, we don't set framebufferBound here.
break;
}

Expand All @@ -1437,8 +1441,11 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
Achievements::FrameUpdate();
}

if (gpu->PresentedThisFrame()) {
framebufferBound = true;
}

if (gpu && !gpu->PresentedThisFrame() && !skipBufferEffects) {
if (!framebufferBound) {
draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, RPAction::CLEAR, clearColor }, "EmuScreen_NoFrame");
draw->SetViewport(viewport);
draw->SetScissorRect(0, 0, g_display.pixel_xres, g_display.pixel_yres);
Expand All @@ -1460,8 +1467,6 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
checkPowerDown();

if (hasVisibleUI()) {
// In most cases, this should already be bound and a no-op.
draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::KEEP, RPAction::CLEAR, RPAction::CLEAR }, "EmuScreen_UI");
draw->SetViewport(viewport);
cardboardDisableButton_->SetVisibility(g_Config.bEnableCardboardVR ? UI::V_VISIBLE : UI::V_GONE);
screenManager()->getUIContext()->BeginFrame();
Expand Down

0 comments on commit 138890a

Please sign in to comment.