Fix message asserts on Android. Add more of them to check things in Vulkan code.

This commit is contained in:
Henrik Rydgård 2017-11-20 11:57:54 +01:00
parent 7ab403e320
commit 27a60f5e58
9 changed files with 55 additions and 83 deletions

View File

@ -17,6 +17,9 @@
#pragma once
#include <cassert>
#include <cstdio>
#include "MsgHandler.h"
#define NOTICE_LEVEL 1 // VERY important information that is NOT errors. Like startup and debugprintfs from the game itself.
@ -26,11 +29,6 @@
#define DEBUG_LEVEL 5 // Detailed debugging - might make things slow.
#define VERBOSE_LEVEL 6 // Noisy debugging - sometimes needed but usually unimportant.
#if !defined(_WIN32)
#include <signal.h>
#endif
#include <cstdio>
namespace LogTypes {
@ -113,13 +111,13 @@ bool GenericLogEnabled(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type);
if (!(_a_)) {\
ERROR_LOG(_t_, "Error...\n\n Line: %d\n File: %s\n\nIgnore and continue?", \
__LINE__, __FILE__); \
if (!PanicYesNo("*** Assertion (see log)***\n")) {Crash();} \
if (!PanicYesNo("*** Assertion ***\n")) { assert(false); } \
}
#define _dbg_assert_msg_(_t_, _a_, ...)\
if (!(_a_)) {\
printf(__VA_ARGS__); \
ERROR_LOG(_t_, __VA_ARGS__); \
if (!PanicYesNo(__VA_ARGS__)) {Crash();} \
if (!PanicYesNo(__VA_ARGS__)) { assert(false);} \
}
#define _dbg_update_() ; //Host_UpdateLogDisplay();
@ -132,16 +130,10 @@ bool GenericLogEnabled(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type);
#endif // dbg_assert
#endif // MAX_LOGLEVEL DEBUG
#define _assert_(_a_) _dbg_assert_(SYSTEM, _a_)
#define _assert_(_a_) \
_dbg_assert_(SYSTEM, _a_)
#ifdef _MSC_VER
#define _assert_msg_(_t_, _a_, _fmt_, ...) \
if (!(_a_)) {\
if (!PanicYesNo(_fmt_, __VA_ARGS__)) {Crash();} \
#define _assert_msg_(_t_, _a_, ...) \
if (!(_a_) && !PanicYesNo(__VA_ARGS__)) { \
assert(false); \
}
#else // not win32
#define _assert_msg_(_t_, _a_, _fmt_, ...) \
if (!(_a_)) {\
if (!PanicYesNo(_fmt_, ##__VA_ARGS__)) {Crash();} \
}
#endif // WIN32

View File

@ -15,31 +15,20 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <string>
#include "ppsspp_config.h"
#include "Common.h" // Local
#include "Common.h"
#include "StringUtils.h"
#include "base/logging.h"
#include "util/text/utf8.h"
#include <string>
bool MsgHandler(const char* caption, const char* text, bool yes_no, int Style);
bool MsgHandler(const char *caption, const char *text, bool yes_no, int Style);
static bool AlertEnabled = true;
// enable/disable the alert handler
void SetEnableAlert(bool enable)
{
AlertEnabled = enable;
}
// This is the first stop for gui alerts where the log is updated and the
// correct window is shown
bool MsgAlert(bool yes_no, int Style, const char* format, ...)
{
bool MsgAlert(bool yes_no, int Style, const char* format, ...) {
// Read message and write it to the log
char buffer[2048];
static const char *captions[] = {
"Information",
"Question",
@ -48,22 +37,15 @@ bool MsgAlert(bool yes_no, int Style, const char* format, ...)
};
const char *caption = captions[Style];
va_list args;
va_start(args, format);
CharArrayFromFormatV(buffer, sizeof(buffer)-1, format, args);
va_end(args);
// Safe android logging
#if PPSSPP_PLATFORM(ANDROID)
ELOG("%s: %s", caption, buffer);
#endif
// Normal logging
// Normal logging (will also log to Android log)
ERROR_LOG(SYSTEM, "%s: %s", caption, buffer);
// Don't ignore questions, especially AskYesNo, PanicYesNo could be ignored
if (AlertEnabled || Style == QUESTION || Style == CRITICAL)
if (Style == QUESTION || Style == CRITICAL)
return MsgHandler(caption, buffer, yes_no, Style);
return true;
}
@ -72,22 +54,22 @@ bool MsgAlert(bool yes_no, int Style, const char* format, ...)
#endif
// Default non library dependent panic alert
bool MsgHandler(const char* caption, const char* text, bool yes_no, int Style)
{
bool MsgHandler(const char* caption, const char* text, bool yes_no, int Style) {
#if defined(USING_WIN_UI)
int STYLE = MB_ICONINFORMATION;
if (Style == QUESTION) STYLE = MB_ICONQUESTION;
if (Style == WARNING) STYLE = MB_ICONWARNING;
int msgBoxStyle = MB_ICONINFORMATION;
if (Style == QUESTION) msgBoxStyle = MB_ICONQUESTION;
if (Style == WARNING) msgBoxStyle = MB_ICONWARNING;
std::wstring wtext = ConvertUTF8ToWString(text);
std::wstring wtext = ConvertUTF8ToWString(text) + L"\n\nTry to continue?";
std::wstring wcaption = ConvertUTF8ToWString(caption);
return IDYES == MessageBox(0, wtext.c_str(), wcaption.c_str(), STYLE | (yes_no ? MB_YESNO : MB_OK));
OutputDebugString(wtext.c_str());
return IDYES == MessageBox(0, wtext.c_str(), wcaption.c_str(), msgBoxStyle | (yes_no ? MB_YESNO : MB_OK));
#elif PPSSPP_PLATFORM(UWP)
OutputDebugStringUTF8(text);
return true;
return false;
#else
printf("%s\n", text);
return true;
// Will use android-log if available, printf if not.
ELOG("%s", text);
return false;
#endif
}

View File

@ -30,18 +30,8 @@ extern bool MsgAlert(bool yes_no, int Style, const char* format, ...)
__attribute__((format(printf, 3, 4)))
#endif
;
void SetEnableAlert(bool enable);
#ifndef GEKKO
#if defined(_WIN32) && !defined(__MINGW32__)
#define PanicAlert(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__)
#define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__)
#else
#define PanicAlert(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__)
#define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__)
#endif
#else
// GEKKO
#define PanicAlert(format, ...) ;
#define PanicYesNo(format, ...) ;
#endif
#define PanicAlert(...) MsgAlert(false, WARNING, __VA_ARGS__)
// Used only for asserts.
#define PanicYesNo(...) MsgAlert(true, CRITICAL, __VA_ARGS__)

View File

@ -225,6 +225,7 @@ bool VulkanContext::InitObjects() {
}
if (!InitSwapchain()) {
// Destroy queue?
return false;
}
return true;
@ -821,8 +822,8 @@ bool VulkanContext::InitSwapchain() {
}
res = vkCreateSwapchainKHR(device_, &swap_chain_info, NULL, &swapchain_);
assert(res == VK_SUCCESS);
if (res != VK_SUCCESS) {
ELOG("vkCreateSwapchainKHR failed!");
return false;
}

View File

@ -44,6 +44,7 @@ bool VulkanPushBuffer::AddBuffer() {
VkResult res = vkCreateBuffer(device_, &b, nullptr, &info.buffer);
if (VK_SUCCESS != res) {
ELOG("vkCreateBuffer failed! result=%d", (int)res);
return false;
}
@ -60,10 +61,15 @@ bool VulkanPushBuffer::AddBuffer() {
res = vkAllocateMemory(device_, &alloc, nullptr, &info.deviceMemory);
if (VK_SUCCESS != res) {
ELOG("vkAllocateMemory failed! result=%d", (int)res);
vkDestroyBuffer(device_, info.buffer, nullptr);
return false;
}
res = vkBindBufferMemory(device_, info.buffer, info.deviceMemory, 0);
if (VK_SUCCESS != res) {
ELOG("vkBindBufferMemory failed! result=%d", (int)res);
vkFreeMemory(device_, info.deviceMemory, nullptr);
vkDestroyBuffer(device_, info.buffer, nullptr);
return false;
}

View File

@ -191,7 +191,6 @@ void D3D9Context::Resize() {
HRESULT hr = device_->Reset(&presentParams_);
if (FAILED(hr)) {
// Had to remove DXGetErrorStringA calls here because dxerr.lib is deprecated and will not link with VS 2015.
ERROR_LOG_REPORT(G3D, "Unable to reset D3D device");
PanicAlert("Unable to reset D3D9 device");
}
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, 0, 0, nullptr);

View File

@ -44,6 +44,7 @@
#include "Core/System.h"
#include "Common/CPUDetect.h"
#include "Common/GraphicsContext.h"
#include "Common/Log.h"
#include "Common/GL/GLInterfaceBase.h"
#include "Common/Vulkan/VulkanLoader.h"
#include "Common/Vulkan/VulkanContext.h"

View File

@ -938,7 +938,10 @@ void VulkanQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataForm
const size_t srcPixelSize = DataFormatSizeInBytes(srcFormat);
VkResult res = vkMapMemory(vulkan_->GetDevice(), readbackMemory_, 0, width * height * srcPixelSize, 0, &mappedData);
assert(res == VK_SUCCESS);
if (res != VK_SUCCESS) {
ELOG("CopyReadbackBuffer: vkMapMemory failed! result=%d", (int)res);
return;
}
if (srcFormat == Draw::DataFormat::R8G8B8A8_UNORM) {
ConvertFromRGBA8888(pixels, (const uint8_t *)mappedData, pixelStride, width, width, height, destFormat);
} else if (srcFormat == Draw::DataFormat::B8G8R8A8_UNORM) {
@ -955,6 +958,7 @@ void VulkanQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataForm
ConvertToD32F(pixels, (const uint8_t *)mappedData, pixelStride, width, width, height, srcFormat);
} else {
// TODO: Maybe a depth conversion or something?
ELOG("CopyReadbackBuffer: Unknown format");
assert(false);
}
vkUnmapMemory(vulkan_->GetDevice(), readbackMemory_);

View File

@ -137,8 +137,8 @@ void VulkanRenderManager::CreateBackbuffers() {
VkImage *swapchainImages = new VkImage[swapchainImageCount_];
res = vkGetSwapchainImagesKHR(vulkan_->GetDevice(), vulkan_->GetSwapchain(), &swapchainImageCount_, swapchainImages);
assert(res == VK_SUCCESS);
if (res != VK_SUCCESS) {
ELOG("vkGetSwapchainImagesKHR failed");
delete[] swapchainImages;
return;
}
@ -729,20 +729,17 @@ void VulkanRenderManager::BeginSubmitFrame(int frame) {
// Now, I wonder if we should do this early in the frame or late? Right now we do it early, which should be fine.
VkResult res = vkAcquireNextImageKHR(vulkan_->GetDevice(), vulkan_->GetSwapchain(), UINT64_MAX, acquireSemaphore_, (VkFence)VK_NULL_HANDLE, &frameData.curSwapchainImage);
if (res == VK_SUBOPTIMAL_KHR) {
// Hopefully the resize will happen shortly. Ignore.
// Hopefully the resize will happen shortly. Ignore - one frame might look bad or something.
} else if (res == VK_ERROR_OUT_OF_DATE_KHR) {
frameData.skipSwap = true;
} else {
assert(res == VK_SUCCESS);
_assert_msg_(G3D, res == VK_SUCCESS, "vkAcquireNextImageKHR failed! result=%d", (int)res);
}
// TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
// return codes
VkCommandBufferBeginInfo begin{ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
begin.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
res = vkBeginCommandBuffer(frameData.mainCmd, &begin);
assert(res == VK_SUCCESS);
_assert_msg_(G3D, res == VK_SUCCESS, "vkBeginCommandBuffer failed! result=%d", (int)res);
queueRunner_.SetBackbuffer(framebuffers_[frameData.curSwapchainImage], swapchainImages_[frameData.curSwapchainImage].image);
@ -754,11 +751,11 @@ void VulkanRenderManager::Submit(int frame, bool triggerFence) {
FrameData &frameData = frameData_[frame];
if (frameData.hasInitCommands) {
VkResult res = vkEndCommandBuffer(frameData.initCmd);
assert(res == VK_SUCCESS);
_assert_msg_(G3D, res == VK_SUCCESS, "vkEndCommandBuffer failed (init)! result=%d", (int)res);
}
VkResult res = vkEndCommandBuffer(frameData.mainCmd);
assert(res == VK_SUCCESS);
_assert_msg_(G3D, res == VK_SUCCESS, "vkEndCommandBuffer failed (main)! result=%d", (int)res);
VkCommandBuffer cmdBufs[2];
int numCmdBufs = 0;
@ -775,7 +772,7 @@ void VulkanRenderManager::Submit(int frame, bool triggerFence) {
if (res == VK_ERROR_DEVICE_LOST) {
_assert_msg_(G3D, false, "Lost the Vulkan device!");
} else {
assert(res == VK_SUCCESS);
_assert_msg_(G3D, res == VK_SUCCESS, "vkQueueSubmit failed! result=%d", (int)res);
}
numCmdBufs = 0;
}
@ -798,7 +795,7 @@ void VulkanRenderManager::Submit(int frame, bool triggerFence) {
if (res == VK_ERROR_DEVICE_LOST) {
_assert_msg_(G3D, false, "Lost the Vulkan device!");
} else {
assert(res == VK_SUCCESS);
_assert_msg_(G3D, res == VK_SUCCESS, "vkQueueSubmit failed! result=%d", (int)res);
}
// When !triggerFence, we notify after syncing with Vulkan.
@ -830,7 +827,7 @@ void VulkanRenderManager::EndSubmitFrame(int frame) {
if (res == VK_ERROR_OUT_OF_DATE_KHR) {
// ignore, it'll be fine. this happens sometimes during resizes, and we do make sure to recreate the swap chain.
} else {
assert(res == VK_SUCCESS);
_assert_msg_(G3D, res == VK_SUCCESS, "vkQueuePresentKHR failed! result=%d", (int)res);
}
} else {
frameData.skipSwap = false;