[Vulkan] Better handling of device lost events (present fatal error dialog)
This commit is contained in:
@@ -117,7 +117,7 @@ void CommandProcessor::ClearCaches() {}
|
||||
void CommandProcessor::WorkerThreadMain() {
|
||||
context_->MakeCurrent();
|
||||
if (!SetupContext()) {
|
||||
xe::FatalError("Unable to setup command processor GL state");
|
||||
xe::FatalError("Unable to setup command processor internal state");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,18 +56,17 @@ X_STATUS GraphicsSystem::Setup(cpu::Processor* processor,
|
||||
assert_null(target_window->context());
|
||||
target_window_->set_context(provider_->CreateContext(target_window_));
|
||||
|
||||
// Setup the GL context the command processor will do all its drawing in.
|
||||
// Setup the context the command processor will do all its drawing in.
|
||||
// It's shared with the display context so that we can resolve
|
||||
// framebuffers
|
||||
// from it.
|
||||
// framebuffers from it.
|
||||
processor_context = provider()->CreateOffscreenContext();
|
||||
});
|
||||
if (!processor_context) {
|
||||
xe::FatalError(
|
||||
"Unable to initialize GL context. Xenia requires OpenGL 4.5. Ensure "
|
||||
"you have the latest drivers for your GPU and that it supports "
|
||||
"OpenGL "
|
||||
"4.5. See http://xenia.jp/faq/ for more information.");
|
||||
"Unable to initialize graphics context. Xenia requires OpenGL 4.5 or "
|
||||
"Vulkan support. Ensure you have the latest drivers for your GPU and "
|
||||
"that it supports OpenGL or Vulkan. See http://xenia.jp/faq/ for "
|
||||
"more information.");
|
||||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
@@ -86,6 +85,10 @@ X_STATUS GraphicsSystem::Setup(cpu::Processor* processor,
|
||||
target_window->on_painting.AddListener(
|
||||
[this](xe::ui::UIEvent* e) { Swap(e); });
|
||||
|
||||
// Watch for context lost events.
|
||||
target_window->on_context_lost.AddListener(
|
||||
[this](xe::ui::UIEvent* e) { Reset(); });
|
||||
|
||||
// Let the processor know we want register access callbacks.
|
||||
memory_->AddVirtualMappedRange(
|
||||
0x7FC80000, 0xFFFF0000, 0x0000FFFF, this,
|
||||
@@ -123,17 +126,29 @@ X_STATUS GraphicsSystem::Setup(cpu::Processor* processor,
|
||||
}
|
||||
|
||||
void GraphicsSystem::Shutdown() {
|
||||
EndTracing();
|
||||
if (command_processor_) {
|
||||
EndTracing();
|
||||
}
|
||||
|
||||
vsync_worker_running_ = false;
|
||||
vsync_worker_thread_->Wait(0, 0, 0, nullptr);
|
||||
vsync_worker_thread_.reset();
|
||||
if (command_processor_) {
|
||||
command_processor_->Shutdown();
|
||||
// TODO(benvanik): remove mapped range.
|
||||
command_processor_.reset();
|
||||
}
|
||||
|
||||
command_processor_->Shutdown();
|
||||
if (vsync_worker_thread_) {
|
||||
vsync_worker_running_ = false;
|
||||
vsync_worker_thread_->Wait(0, 0, 0, nullptr);
|
||||
vsync_worker_thread_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(benvanik): remove mapped range.
|
||||
void GraphicsSystem::Reset() {
|
||||
// TODO(DrChat): Reset the system.
|
||||
XELOGI("Context lost; Reset invoked");
|
||||
Shutdown();
|
||||
|
||||
command_processor_.reset();
|
||||
xe::FatalError("Graphics device lost (probably due to an internal error)");
|
||||
}
|
||||
|
||||
uint32_t GraphicsSystem::ReadRegisterThunk(void* ppc_context,
|
||||
|
||||
@@ -45,6 +45,7 @@ class GraphicsSystem {
|
||||
kernel::KernelState* kernel_state,
|
||||
ui::Window* target_window);
|
||||
virtual void Shutdown();
|
||||
virtual void Reset();
|
||||
|
||||
virtual std::unique_ptr<xe::ui::RawImage> Capture() { return nullptr; }
|
||||
|
||||
|
||||
@@ -314,8 +314,7 @@ TextureCache::Texture* TextureCache::AllocateTexture(
|
||||
VkResult status = vmaCreateImage(mem_allocator_, &image_info, &vma_reqs,
|
||||
&image, &alloc, &vma_info);
|
||||
if (status != VK_SUCCESS) {
|
||||
// Crap.
|
||||
assert_always();
|
||||
// Allocation failed.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -332,10 +331,12 @@ TextureCache::Texture* TextureCache::AllocateTexture(
|
||||
}
|
||||
|
||||
bool TextureCache::FreeTexture(Texture* texture) {
|
||||
if (texture->in_flight_fence &&
|
||||
vkGetFenceStatus(*device_, texture->in_flight_fence) != VK_SUCCESS) {
|
||||
// Texture still in flight.
|
||||
return false;
|
||||
if (texture->in_flight_fence) {
|
||||
VkResult status = vkGetFenceStatus(*device_, texture->in_flight_fence);
|
||||
if (status != VK_SUCCESS && status != VK_ERROR_DEVICE_LOST) {
|
||||
// Texture still in flight.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (texture->framebuffer) {
|
||||
@@ -1421,7 +1422,6 @@ bool TextureCache::SetupTextureBinding(VkCommandBuffer command_buffer,
|
||||
|
||||
auto texture = Demand(texture_info, command_buffer, completion_fence);
|
||||
auto sampler = Demand(sampler_info);
|
||||
// assert_true(texture != nullptr && sampler != nullptr);
|
||||
if (texture == nullptr || sampler == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -537,8 +537,6 @@ void VulkanCommandProcessor::PerformSwap(uint32_t frontbuffer_ptr,
|
||||
submit_info.pSignalSemaphores = nullptr;
|
||||
|
||||
status = vkQueueSubmit(queue_, 1, &submit_info, current_batch_fence_);
|
||||
CheckResult(status, "vkQueueSubmit");
|
||||
|
||||
if (device_->is_renderdoc_attached() && capturing_) {
|
||||
device_->EndRenderDocFrameCapture();
|
||||
capturing_ = false;
|
||||
|
||||
@@ -260,8 +260,15 @@ void VulkanGraphicsSystem::Swap(xe::ui::UIEvent* e) {
|
||||
if (!command_processor_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for pending swap.
|
||||
auto& swap_state = command_processor_->swap_state();
|
||||
if (display_context_->WasLost()) {
|
||||
// We're crashing. Cheese it.
|
||||
swap_state.pending = false;
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(swap_state.mutex);
|
||||
if (!swap_state.pending) {
|
||||
|
||||
Reference in New Issue
Block a user