mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-15 02:29:51 +01:00
Merge branch 'master' into TemporaryHackishBranch
# Conflicts: # Core/Compatibility.h
This commit is contained in:
commit
0e83fc8d58
46 files changed
+327
-130
No files matched your search
+48
-5
@@ -20,7 +20,12 @@
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
|
||||
#include "MsgHandler.h"
|
||||
#include "CommonFuncs.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
#define NOTICE_LEVEL 1 // VERY important information that is NOT errors. Like startup and debugprintfs from the game itself.
|
||||
#define ERROR_LEVEL 2 // Important errors.
|
||||
@@ -106,19 +111,42 @@ bool GenericLogEnabled(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type);
|
||||
#define DEBUG_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LDEBUG, __VA_ARGS__) } while (false)
|
||||
#define VERBOSE_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LVERBOSE, __VA_ARGS__) } while (false)
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
// Tricky macro to get the basename, that also works if *built* on Win32.
|
||||
#define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : (__builtin_strrchr(__FILE__, '\\') ? __builtin_strrchr(__FILE__, '\\') + 1 : __FILE__))
|
||||
void AndroidAssertLog(const char *func, const char *file, int line, const char *condition, const char *fmt, ...);
|
||||
|
||||
#endif
|
||||
|
||||
#if MAX_LOGLEVEL >= DEBUG_LEVEL
|
||||
#define _dbg_assert_(_t_, _a_) \
|
||||
if (!(_a_)) {\
|
||||
ERROR_LOG(_t_, "Error...\n\n Line: %d\n File: %s\n\nIgnore and continue?", \
|
||||
__LINE__, __FILE__); \
|
||||
if (!PanicYesNo("*** Assertion ***\n")) { assert(false); } \
|
||||
if (!PanicYesNo("*** Assertion ***\n")) { Crash(); } \
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
#define _dbg_assert_msg_(_t_, _a_, ...)\
|
||||
if (!(_a_)) {\
|
||||
printf(__VA_ARGS__); \
|
||||
ERROR_LOG(_t_, __VA_ARGS__); \
|
||||
if (!PanicYesNo(__VA_ARGS__)) { assert(false);} \
|
||||
if (!PanicYesNo(__VA_ARGS__)) AndroidAssertLog(__FUNCTION__, __FILENAME__, __LINE__, #_a_, __VA_ARGS__); \
|
||||
}
|
||||
|
||||
#else // __ANDROID__
|
||||
|
||||
#define _dbg_assert_msg_(_t_, _a_, ...)\
|
||||
if (!(_a_)) {\
|
||||
printf(__VA_ARGS__); \
|
||||
ERROR_LOG(_t_, __VA_ARGS__); \
|
||||
if (!PanicYesNo(__VA_ARGS__)) { Crash();} \
|
||||
}
|
||||
|
||||
#endif // __ANDROID__
|
||||
|
||||
#define _dbg_update_() ; //Host_UpdateLogDisplay();
|
||||
|
||||
#else // not debug
|
||||
@@ -131,9 +159,24 @@ bool GenericLogEnabled(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type);
|
||||
#endif // MAX_LOGLEVEL DEBUG
|
||||
|
||||
#define _assert_(_a_) \
|
||||
_dbg_assert_(SYSTEM, _a_)
|
||||
if (!(_a_)) {\
|
||||
ERROR_LOG(SYSTEM, "Error...\n\n Line: %d\n File: %s\n\nIgnore and continue?", \
|
||||
__LINE__, __FILE__); \
|
||||
if (!PanicYesNo("*** Assertion ***\n")) { Crash(); } \
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
#define _assert_msg_(_t_, _a_, ...) \
|
||||
if (!(_a_) && !PanicYesNo(__VA_ARGS__)) { \
|
||||
assert(false); \
|
||||
AndroidAssertLog(__FUNCTION__, __FILENAME__, __LINE__, #_a_, __VA_ARGS__); \
|
||||
}
|
||||
|
||||
#else // __ANDROID__
|
||||
|
||||
#define _assert_msg_(_t_, _a_, ...) \
|
||||
if (!(_a_) && !PanicYesNo(__VA_ARGS__)) { \
|
||||
Crash(); \
|
||||
}
|
||||
|
||||
#endif // __ANDROID__
|
||||
@@ -57,6 +57,21 @@ bool GenericLogEnabled(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
#define LOG_BUF_SIZE 1024
|
||||
|
||||
void AndroidAssertLog(const char *func, const char *file, int line, const char *condition, const char *fmt, ...) {
|
||||
char buf[LOG_BUF_SIZE];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
__android_log_assert(condition, "PPSSPP", "%s:%d (%s): [%s] %s", file, line, func, condition, buf);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
LogManager *LogManager::logManager_ = NULL;
|
||||
|
||||
struct LogNameTableEntry {
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ enum MSG_TYPE {
|
||||
CRITICAL
|
||||
};
|
||||
|
||||
extern bool MsgAlert(bool yes_no, int Style, const char* format, ...)
|
||||
bool MsgAlert(bool yes_no, int Style, const char* format, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 3, 4)))
|
||||
#endif
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
// Additionally, Common/Vulkan/* , including this file, are also licensed
|
||||
// under the public domain.
|
||||
|
||||
#include "Common/Log.h"
|
||||
#include "Common/Vulkan/VulkanMemory.h"
|
||||
|
||||
VulkanPushBuffer::VulkanPushBuffer(VulkanContext *vulkan, size_t size) : device_(vulkan->GetDevice()), buf_(0), offset_(0), size_(size), writePtr_(nullptr) {
|
||||
@@ -44,7 +45,7 @@ bool VulkanPushBuffer::AddBuffer() {
|
||||
|
||||
VkResult res = vkCreateBuffer(device_, &b, nullptr, &info.buffer);
|
||||
if (VK_SUCCESS != res) {
|
||||
ELOG("vkCreateBuffer failed! result=%d", (int)res);
|
||||
_assert_msg_(G3D, false, "vkCreateBuffer failed! result=%d", (int)res);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -61,7 +62,7 @@ bool VulkanPushBuffer::AddBuffer() {
|
||||
|
||||
res = vkAllocateMemory(device_, &alloc, nullptr, &info.deviceMemory);
|
||||
if (VK_SUCCESS != res) {
|
||||
ELOG("vkAllocateMemory failed! result=%d", (int)res);
|
||||
_assert_msg_(G3D, false, "vkAllocateMemory failed! size=%d result=%d", (int)reqs.size, (int)res);
|
||||
vkDestroyBuffer(device_, info.buffer, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) {
|
||||
CheckSetting(iniFile, gameID, "RequireBufferedRendering", &flags_.RequireBufferedRendering);
|
||||
CheckSetting(iniFile, gameID, "RequireBlockTransfer", &flags_.RequireBlockTransfer);
|
||||
CheckSetting(iniFile, gameID, "DisableReadbacks", &flags_.DisableReadbacks);
|
||||
CheckSetting(iniFile, gameID, "DisableAccurateDepth", &flags_.DisableAccurateDepth);
|
||||
}
|
||||
|
||||
void Compatibility::CheckSetting(IniFile &iniFile, const std::string &gameID, const char *option, bool *flag) {
|
||||
|
||||
@@ -65,6 +65,7 @@ struct CompatFlags {
|
||||
bool FlushAtStall;
|
||||
bool Force04Download;
|
||||
bool GuardBand;
|
||||
bool DisableAccurateDepth;
|
||||
};
|
||||
|
||||
class IniFile;
|
||||
|
||||
@@ -550,6 +550,7 @@ static ConfigSetting graphicsSettings[] = {
|
||||
ReportedConfigSetting("FragmentTestCache", &g_Config.bFragmentTestCache, true, true, true),
|
||||
|
||||
ConfigSetting("GfxDebugOutput", &g_Config.bGfxDebugOutput, false, false, false),
|
||||
ConfigSetting("GfxDebugSplitSubmit", &g_Config.bGfxDebugSplitSubmit, false, false, false),
|
||||
ConfigSetting("LogFrameDrops", &g_Config.bLogFrameDrops, false, true, false),
|
||||
|
||||
ConfigSetting(false),
|
||||
|
||||
@@ -223,6 +223,7 @@ public:
|
||||
bool bHardwareTessellation;
|
||||
std::string sPostShaderName; // Off for off.
|
||||
bool bGfxDebugOutput;
|
||||
bool bGfxDebugSplitSubmit;
|
||||
|
||||
// Sound
|
||||
bool bEnableSound;
|
||||
|
||||
@@ -697,7 +697,6 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
|
||||
maxz += fullDepthRange;
|
||||
}
|
||||
}
|
||||
|
||||
// Okay. So, in our shader, -1 will map to minz, and +1 will map to maxz.
|
||||
float halfActualZRange = (maxz - minz) * (1.0f / 2.0f);
|
||||
float zScale = halfActualZRange < std::numeric_limits<float>::epsilon() ? 1.0f : vpZScale / halfActualZRange;
|
||||
|
||||
@@ -400,7 +400,7 @@ void SoftwareTransform(
|
||||
int scissorY2 = gstate.getScissorY2() + 1;
|
||||
reallyAClear = IsReallyAClear(transformed, maxIndex, scissorX2, scissorY2);
|
||||
}
|
||||
if (reallyAClear && gl_extensions.gpuVendor != GPU_VENDOR_POWERVR) {
|
||||
if (reallyAClear && gl_extensions.gpuVendor != GPU_VENDOR_IMGTEC) {
|
||||
// If alpha is not allowed to be separate, it must match for both depth/stencil and color. Vulkan requires this.
|
||||
bool alphaMatchesColor = gstate.isClearModeColorMask() == gstate.isClearModeAlphaMask();
|
||||
bool depthMatchesStencil = gstate.isClearModeAlphaMask() == gstate.isClearModeDepthMask();
|
||||
|
||||
@@ -225,8 +225,8 @@ void TextureCacheCommon::UpdateSamplingParams(TexCacheEntry &entry, SamplerCache
|
||||
key.lodBias = (int)(lodBias * 256.0f);
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_ANISOTROPY) && g_Config.iAnisotropyLevel > 0) {
|
||||
key.aniso = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GE_TEXLEVEL_MODE_CONST:
|
||||
case GE_TEXLEVEL_MODE_UNKNOWN:
|
||||
key.maxLevel = (int)(lodBias * 256.0f);
|
||||
|
||||
@@ -206,7 +206,11 @@ void GPU_D3D11::CheckGPUFeatures() {
|
||||
|
||||
features |= GPU_SUPPORTS_BLEND_MINMAX;
|
||||
features |= GPU_PREFER_CPU_DOWNLOAD;
|
||||
features |= GPU_SUPPORTS_ACCURATE_DEPTH; // Breaks text in PaRappa for some reason.
|
||||
|
||||
// Accurate depth is required on AMD so we ignore the compat flag to disable it on those. See #9545
|
||||
if (!PSP_CoreParameter().compat.flags().DisableAccurateDepth || draw_->GetDeviceCaps().vendor == Draw::GPUVendor::VENDOR_AMD) {
|
||||
features |= GPU_SUPPORTS_ACCURATE_DEPTH; // Breaks text in PaRappa for some reason.
|
||||
}
|
||||
|
||||
#ifndef _M_ARM
|
||||
// TODO: Do proper feature detection
|
||||
|
||||
@@ -187,7 +187,11 @@ void GPU_DX9::CheckGPUFeatures() {
|
||||
features |= GPU_SUPPORTS_BLEND_MINMAX;
|
||||
features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL;
|
||||
features |= GPU_PREFER_CPU_DOWNLOAD;
|
||||
features |= GPU_SUPPORTS_ACCURATE_DEPTH;
|
||||
|
||||
// Accurate depth is required on AMD so we ignore the compat flag to disable it on those. See #9545
|
||||
if (!PSP_CoreParameter().compat.flags().DisableAccurateDepth || draw_->GetDeviceCaps().vendor == Draw::GPUVendor::VENDOR_AMD) {
|
||||
features |= GPU_SUPPORTS_ACCURATE_DEPTH;
|
||||
}
|
||||
|
||||
D3DCAPS9 caps;
|
||||
ZeroMemory(&caps, sizeof(caps));
|
||||
|
||||
@@ -244,7 +244,7 @@ bool GenerateFragmentShader(const ShaderID &id, char *buffer, uint64_t *uniformM
|
||||
if (enableAlphaTest && !alphaTestAgainstZero) {
|
||||
if (bitwiseOps) {
|
||||
WRITE(p, "int roundAndScaleTo255i(in float x) { return int(floor(x * 255.0 + 0.5)); }\n");
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) {
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) {
|
||||
WRITE(p, "float roundTo255thf(in mediump float x) { mediump float y = x + (0.5/255.0); return y - fract(y * 255.0) * (1.0 / 255.0); }\n");
|
||||
} else {
|
||||
WRITE(p, "float roundAndScaleTo255f(in float x) { return floor(x * 255.0 + 0.5); }\n");
|
||||
@@ -253,7 +253,7 @@ bool GenerateFragmentShader(const ShaderID &id, char *buffer, uint64_t *uniformM
|
||||
if (enableColorTest && !colorTestAgainstZero) {
|
||||
if (bitwiseOps) {
|
||||
WRITE(p, "ivec3 roundAndScaleTo255iv(in vec3 x) { return ivec3(floor(x * 255.0 + 0.5)); }\n");
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) {
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) {
|
||||
WRITE(p, "vec3 roundTo255thv(in vec3 x) { vec3 y = x + (0.5/255.0); return y - fract(y * 255.0) * (1.0 / 255.0); }\n");
|
||||
} else {
|
||||
WRITE(p, "vec3 roundAndScaleTo255v(in vec3 x) { return floor(x * 255.0 + 0.5); }\n");
|
||||
@@ -437,7 +437,7 @@ bool GenerateFragmentShader(const ShaderID &id, char *buffer, uint64_t *uniformM
|
||||
if (alphaTestFuncs[alphaTestFunc][0] != '#') {
|
||||
if (bitwiseOps) {
|
||||
WRITE(p, " if ((roundAndScaleTo255i(v.a) & u_alphacolormask.a) %s int(u_alphacolorref.a)) discard;\n", alphaTestFuncs[alphaTestFunc]);
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) {
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) {
|
||||
// Work around bad PVR driver problem where equality check + discard just doesn't work.
|
||||
if (alphaTestFunc != GE_COMP_NOTEQUAL) {
|
||||
WRITE(p, " if (roundTo255thf(v.a) %s u_alphacolorref.a) discard;\n", alphaTestFuncs[alphaTestFunc]);
|
||||
@@ -486,7 +486,7 @@ bool GenerateFragmentShader(const ShaderID &id, char *buffer, uint64_t *uniformM
|
||||
const char *maskedFragColor = "ivec3(v_scaled.r & u_alphacolormask.r, v_scaled.g & u_alphacolormask.g, v_scaled.b & u_alphacolormask.b)";
|
||||
const char *maskedColorRef = "ivec3(int(u_alphacolorref.r) & u_alphacolormask.r, int(u_alphacolorref.g) & u_alphacolormask.g, int(u_alphacolorref.b) & u_alphacolormask.b)";
|
||||
WRITE(p, " if (%s %s %s) discard;\n", maskedFragColor, colorTestFuncs[colorTestFunc], maskedColorRef);
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) {
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) {
|
||||
WRITE(p, " if (roundTo255thv(v.rgb) %s u_alphacolorref.rgb) discard;\n", colorTestFuncs[colorTestFunc]);
|
||||
} else {
|
||||
WRITE(p, " if (roundAndScaleTo255v(v.rgb) %s u_alphacolorref.rgb) discard;\n", colorTestFuncs[colorTestFunc]);
|
||||
|
||||
@@ -285,7 +285,7 @@ static void SetColorUniform3Alpha(int uniform, u32 color, u8 alpha) {
|
||||
|
||||
// This passes colors unscaled (e.g. 0 - 255 not 0 - 1.)
|
||||
static void SetColorUniform3Alpha255(int uniform, u32 color, u8 alpha) {
|
||||
if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) {
|
||||
if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) {
|
||||
const float col[4] = {
|
||||
(float)((color & 0xFF) >> 0) * (1.0f / 255.0f),
|
||||
(float)((color & 0xFF00) >> 8) * (1.0f / 255.0f),
|
||||
|
||||
@@ -473,7 +473,7 @@ VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView
|
||||
descAlloc.descriptorSetCount = 1;
|
||||
VkResult result = vkAllocateDescriptorSets(vulkan_->GetDevice(), &descAlloc, &desc);
|
||||
// Even in release mode, this is bad.
|
||||
_assert_msg_(G3D, result == VK_SUCCESS, "Ran out of descriptor space in pool. sz=%d", (int)frame->descSets.size());
|
||||
_assert_msg_(G3D, result == VK_SUCCESS, "Ran out of descriptor space in pool. sz=%d res=%d", (int)frame->descSets.size(), (int)result);
|
||||
|
||||
// We just don't write to the slots we don't care about.
|
||||
// We need 8 now that we support secondary texture bindings.
|
||||
@@ -1041,8 +1041,6 @@ DrawEngineVulkan::TessellationDataTransferVulkan::~TessellationDataTransferVulka
|
||||
void DrawEngineVulkan::TessellationDataTransferVulkan::PrepareBuffers(float *&pos, float *&tex, float *&col, int &posStride, int &texStride, int &colStride, int size, bool hasColor, bool hasTexCoords) {
|
||||
colStride = 4;
|
||||
|
||||
assert(size > 0);
|
||||
|
||||
// TODO: This SHOULD work without padding but I can't get it to work on nvidia, so had
|
||||
// to expand to vec4. Driver bug?
|
||||
struct TessData {
|
||||
@@ -1064,6 +1062,5 @@ void DrawEngineVulkan::TessellationDataTransferVulkan::PrepareBuffers(float *&po
|
||||
}
|
||||
|
||||
void DrawEngineVulkan::TessellationDataTransferVulkan::SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) {
|
||||
assert(pos);
|
||||
// Nothing to do here!
|
||||
}
|
||||
+18
-13
@@ -176,6 +176,24 @@ GPU_Vulkan::~GPU_Vulkan() {
|
||||
|
||||
void GPU_Vulkan::CheckGPUFeatures() {
|
||||
uint32_t features = 0;
|
||||
|
||||
// Accurate depth is required on AMD so we ignore the compat flag to disable it on those. See #9545
|
||||
if (!PSP_CoreParameter().compat.flags().DisableAccurateDepth || vulkan_->GetPhysicalDeviceProperties().vendorID == VULKAN_VENDOR_AMD) {
|
||||
features |= GPU_SUPPORTS_ACCURATE_DEPTH;
|
||||
}
|
||||
|
||||
// Mandatory features on Vulkan, which may be checked in "centralized" code
|
||||
features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL;
|
||||
features |= GPU_SUPPORTS_FBO;
|
||||
features |= GPU_SUPPORTS_BLEND_MINMAX;
|
||||
features |= GPU_SUPPORTS_ANY_COPY_IMAGE;
|
||||
features |= GPU_SUPPORTS_OES_TEXTURE_NPOT;
|
||||
features |= GPU_SUPPORTS_LARGE_VIEWPORTS;
|
||||
features |= GPU_SUPPORTS_16BIT_FORMATS;
|
||||
features |= GPU_SUPPORTS_INSTANCE_RENDERING;
|
||||
features |= GPU_SUPPORTS_VERTEX_TEXTURE_FETCH;
|
||||
features |= GPU_SUPPORTS_TEXTURE_FLOAT;
|
||||
|
||||
if (vulkan_->GetFeaturesEnabled().wideLines) {
|
||||
features |= GPU_SUPPORTS_WIDE_LINES;
|
||||
}
|
||||
@@ -220,19 +238,6 @@ void GPU_Vulkan::CheckGPUFeatures() {
|
||||
else if (PSP_CoreParameter().compat.flags().VertexDepthRounding) {
|
||||
features |= GPU_ROUND_DEPTH_TO_16BIT;
|
||||
}
|
||||
|
||||
// Mandatory features on Vulkan, which may be checked in "centralized" code
|
||||
features |= GPU_SUPPORTS_ACCURATE_DEPTH;
|
||||
features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL;
|
||||
features |= GPU_SUPPORTS_FBO;
|
||||
features |= GPU_SUPPORTS_BLEND_MINMAX;
|
||||
features |= GPU_SUPPORTS_ANY_COPY_IMAGE;
|
||||
features |= GPU_SUPPORTS_OES_TEXTURE_NPOT;
|
||||
features |= GPU_SUPPORTS_LARGE_VIEWPORTS;
|
||||
features |= GPU_SUPPORTS_16BIT_FORMATS;
|
||||
features |= GPU_SUPPORTS_INSTANCE_RENDERING;
|
||||
features |= GPU_SUPPORTS_VERTEX_TEXTURE_FETCH;
|
||||
features |= GPU_SUPPORTS_TEXTURE_FLOAT;
|
||||
gstate_c.featureFlags = features;
|
||||
}
|
||||
|
||||
|
||||
@@ -278,6 +278,7 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip
|
||||
VkPipeline pipeline;
|
||||
VkResult result = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipe, nullptr, &pipeline);
|
||||
if (result != VK_SUCCESS) {
|
||||
_assert_msg_(G3D, false, "Failed creating graphics pipeline! result='%s'", VulkanResultToString(result));
|
||||
ERROR_LOG(G3D, "Failed creating graphics pipeline! result='%s'", VulkanResultToString(result));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
+2
-2
@@ -527,7 +527,7 @@ void GameBrowser::Refresh() {
|
||||
}
|
||||
} else {
|
||||
std::vector<FileInfo> fileInfo;
|
||||
path_.GetListing(fileInfo, "iso:cso:pbp:elf:prx:");
|
||||
path_.GetListing(fileInfo, "iso:cso:pbp:elf:prx:ppdmp:");
|
||||
for (size_t i = 0; i < fileInfo.size(); i++) {
|
||||
bool isGame = !fileInfo[i].isDirectory;
|
||||
bool isSaveData = false;
|
||||
@@ -973,7 +973,7 @@ bool MainScreen::UseVerticalLayout() const {
|
||||
|
||||
UI::EventReturn MainScreen::OnLoadFile(UI::EventParams &e) {
|
||||
#if defined(USING_QT_UI)
|
||||
QString fileName = QFileDialog::getOpenFileName(NULL, "Load ROM", g_Config.currentDirectory.c_str(), "PSP ROMs (*.iso *.cso *.pbp *.elf *.zip)");
|
||||
QString fileName = QFileDialog::getOpenFileName(NULL, "Load ROM", g_Config.currentDirectory.c_str(), "PSP ROMs (*.iso *.cso *.pbp *.elf *.zip *.ppdmp)");
|
||||
if (QFile::exists(fileName)) {
|
||||
QDir newPath;
|
||||
g_Config.currentDirectory = newPath.filePath(fileName).toStdString();
|
||||
|
||||
+30
-11
@@ -43,6 +43,7 @@
|
||||
#endif
|
||||
|
||||
#include "base/display.h"
|
||||
#include "base/timeutil.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/NativeApp.h"
|
||||
#include "file/vfs.h"
|
||||
@@ -394,6 +395,8 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
|
||||
const char *fileToLog = 0;
|
||||
const char *stateToLoad = 0;
|
||||
|
||||
bool gotBootFilename = false;
|
||||
|
||||
// Parse command line
|
||||
LogTypes::LOG_LEVELS logLevel = LogTypes::LINFO;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
@@ -435,18 +438,34 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (boot_filename.empty()) {
|
||||
ILOG("Boot filename found in args: %s", argv[i]);
|
||||
boot_filename = argv[i];
|
||||
#ifdef _WIN32
|
||||
boot_filename = ReplaceAll(boot_filename, "\\", "/");
|
||||
#endif
|
||||
skipLogo = true;
|
||||
// This parameter should be a boot filename. Only accept it if we
|
||||
// don't already have one.
|
||||
if (!gotBootFilename) {
|
||||
gotBootFilename = true;
|
||||
ILOG("Boot filename found in args: '%s'", argv[i]);
|
||||
|
||||
std::unique_ptr<FileLoader> fileLoader(ConstructFileLoader(boot_filename));
|
||||
if (!fileLoader->Exists()) {
|
||||
fprintf(stderr, "File not found: %s\n", boot_filename.c_str());
|
||||
exit(1);
|
||||
bool okToLoad = true;
|
||||
if (System_GetPropertyBool(SYSPROP_SUPPORTS_PERMISSIONS)) {
|
||||
PermissionStatus status = System_GetPermissionStatus(SYSTEM_PERMISSION_STORAGE);
|
||||
if (status != PERMISSION_STATUS_GRANTED) {
|
||||
ELOG("Storage permission not granted. Launching without argument.");
|
||||
okToLoad = false;
|
||||
} else {
|
||||
ILOG("Storage permission granted.");
|
||||
}
|
||||
}
|
||||
if (okToLoad) {
|
||||
boot_filename = argv[i];
|
||||
#ifdef _WIN32
|
||||
boot_filename = ReplaceAll(boot_filename, "\\", "/");
|
||||
#endif
|
||||
skipLogo = true;
|
||||
|
||||
std::unique_ptr<FileLoader> fileLoader(ConstructFileLoader(boot_filename));
|
||||
if (!fileLoader->Exists()) {
|
||||
fprintf(stderr, "File not found: %s\n", boot_filename.c_str());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Can only boot one file");
|
||||
|
||||
@@ -212,7 +212,9 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m
|
||||
return false;
|
||||
}
|
||||
|
||||
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan);
|
||||
bool splitSubmit = g_Config.bGfxDebugSplitSubmit;
|
||||
|
||||
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan, splitSubmit);
|
||||
bool success = draw_->CreatePresets();
|
||||
assert(success); // Doesn't fail, we include the compiler.
|
||||
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
|
||||
|
||||
@@ -369,7 +369,7 @@ namespace MainWindow {
|
||||
}
|
||||
|
||||
void BrowseAndBoot(std::string defaultPath, bool browseDirectory) {
|
||||
static std::wstring filter = L"All supported file types (*.iso *.cso *.pbp *.elf *.prx *.zip)|*.pbp;*.elf;*.iso;*.cso;*.prx;*.zip|PSP ROMs (*.iso *.cso *.pbp *.elf *.prx)|*.pbp;*.elf;*.iso;*.cso;*.prx|Homebrew/Demos installers (*.zip)|*.zip|All files (*.*)|*.*||";
|
||||
static std::wstring filter = L"All supported file types (*.iso *.cso *.pbp *.elf *.prx *.zip *.ppdmp)|*.pbp;*.elf;*.iso;*.cso;*.prx;*.zip;*.ppdmp|PSP ROMs (*.iso *.cso *.pbp *.elf *.prx)|*.pbp;*.elf;*.iso;*.cso;*.prx|Homebrew/Demos installers (*.zip)|*.zip|All files (*.*)|*.*||";
|
||||
for (int i = 0; i < (int)filter.length(); i++) {
|
||||
if (filter[i] == '|')
|
||||
filter[i] = '\0';
|
||||
|
||||
@@ -332,7 +332,7 @@ bool AndroidVulkanContext::Init(ANativeWindow *wnd, int desiredBackbufferSizeX,
|
||||
|
||||
bool success = true;
|
||||
if (g_Vulkan->InitObjects()) {
|
||||
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan);
|
||||
draw_ = Draw::T3DCreateVulkanContext(g_Vulkan, g_Config.bGfxDebugSplitSubmit);
|
||||
success = draw_->CreatePresets(); // Doesn't fail, we ship the compiler.
|
||||
assert(success);
|
||||
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
|
||||
@@ -600,6 +600,9 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init
|
||||
|
||||
setCurrentThreadName("androidInit");
|
||||
|
||||
// Makes sure we get early permission grants.
|
||||
ProcessFrameCommands(env);
|
||||
|
||||
ILOG("NativeApp.init() -- begin");
|
||||
PROFILE_INIT();
|
||||
|
||||
|
||||
@@ -197,6 +197,8 @@ public abstract class NativeActivity extends Activity implements SurfaceHolder.C
|
||||
// Let's start out granted if it was granted already.
|
||||
if (this.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
|
||||
NativeApp.sendMessage("permission_granted", "storage");
|
||||
} else {
|
||||
NativeApp.sendMessage("permission_denied", "storage");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,10 +26,8 @@ public class TextRenderer {
|
||||
}
|
||||
}
|
||||
private static Point measure(String string, double textSize) {
|
||||
Rect bound = new Rect();
|
||||
p.setTextSize((float)textSize);
|
||||
p.getTextBounds(string, 0, string.length(), bound);
|
||||
int w = bound.width();
|
||||
int w = (int)p.measureText(string);
|
||||
int h = (int)(p.descent() - p.ascent() + 2.0f);
|
||||
// Round width up to even already here to avoid annoyances from odd-width 16-bit textures which
|
||||
// OpenGL does not like - each line must be 4-byte aligned
|
||||
|
||||
@@ -401,3 +401,19 @@ ULJS00394 = true
|
||||
ULJS19068 = true
|
||||
NPJH50518 = true
|
||||
# TODO: Will add some games in the future
|
||||
|
||||
[DisableAccurateDepth]
|
||||
# Midnight Club: LA Remix
|
||||
ULUS10383 = true
|
||||
ULES01144 = true
|
||||
ULJS00180 = true
|
||||
ULJS00267 = true
|
||||
ULJM05904 = true
|
||||
NPJH50440 = true
|
||||
# Midnight Club 3 : DUB edition
|
||||
ULUS10021 = true
|
||||
ULES00108 = true
|
||||
|
||||
# Shadow of Destiny (#9545)
|
||||
ULUS10459 = true
|
||||
NPJH50036 = true
|
||||
+1
-1
@@ -5,7 +5,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.0.0'
|
||||
classpath 'com.android.tools.build:gradle:3.0.1'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ void OutputDebugStringUTF8(const char *p);
|
||||
#define ILOG(...) __android_log_print(ANDROID_LOG_INFO, APP_NAME, __VA_ARGS__);
|
||||
#define WLOG(...) __android_log_print(ANDROID_LOG_WARN, APP_NAME, __VA_ARGS__);
|
||||
#define ELOG(...) __android_log_print(ANDROID_LOG_ERROR, APP_NAME, __VA_ARGS__);
|
||||
#define FLOG(...) { __android_log_print(ANDROID_LOG_ERROR, APP_NAME, __VA_ARGS__); Crash(); }
|
||||
#define FLOG(...) __android_log_print(ANDROID_LOG_FATAL, APP_NAME, __VA_ARGS__);
|
||||
|
||||
#define MessageBox(a, b, c, d) __android_log_print(ANDROID_LOG_INFO, APP_NAME, "%s %s", (b), (c));
|
||||
|
||||
|
||||
@@ -74,6 +74,18 @@ protected:
|
||||
virtual void ClearCache() = 0;
|
||||
void WrapString(std::string &out, const char *str, float maxWidth);
|
||||
|
||||
struct CacheKey {
|
||||
bool operator < (const CacheKey &other) const {
|
||||
if (fontHash < other.fontHash)
|
||||
return true;
|
||||
if (fontHash > other.fontHash)
|
||||
return false;
|
||||
return text < other.text;
|
||||
}
|
||||
std::string text;
|
||||
uint32_t fontHash;
|
||||
};
|
||||
|
||||
int frameCount_;
|
||||
float fontScaleX_;
|
||||
float fontScaleY_;
|
||||
|
||||
@@ -80,11 +80,9 @@ std::string TextDrawerAndroid::NormalizeString(std::string str) {
|
||||
}
|
||||
|
||||
void TextDrawerAndroid::MeasureString(const char *str, size_t len, float *w, float *h) {
|
||||
uint32_t stringHash = hash::Adler32((const uint8_t *)str, len);
|
||||
uint32_t entryHash = stringHash ^ fontHash_;
|
||||
|
||||
CacheKey key{ std::string(str, len), fontHash_ };
|
||||
TextMeasureEntry *entry;
|
||||
auto iter = sizeCache_.find(entryHash);
|
||||
auto iter = sizeCache_.find(key);
|
||||
if (iter != sizeCache_.end()) {
|
||||
entry = iter->second.get();
|
||||
} else {
|
||||
@@ -103,7 +101,7 @@ void TextDrawerAndroid::MeasureString(const char *str, size_t len, float *w, flo
|
||||
entry = new TextMeasureEntry();
|
||||
entry->width = (size >> 16);
|
||||
entry->height = (size & 0xFFFF);
|
||||
sizeCache_[entryHash] = std::unique_ptr<TextMeasureEntry>(entry);
|
||||
sizeCache_[key] = std::unique_ptr<TextMeasureEntry>(entry);
|
||||
}
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
*w = entry->width * fontScaleX_ * dpiScale_;
|
||||
@@ -130,11 +128,10 @@ void TextDrawerAndroid::MeasureStringRect(const char *str, size_t len, const Bou
|
||||
float total_w = 0.0f;
|
||||
float total_h = 0.0f;
|
||||
for (size_t i = 0; i < lines.size(); i++) {
|
||||
uint32_t stringHash = hash::Adler32((const uint8_t *)&lines[i][0], lines[i].length());
|
||||
uint32_t entryHash = stringHash ^ fontHash_;
|
||||
CacheKey key{ lines[i], fontHash_ };
|
||||
|
||||
TextMeasureEntry *entry;
|
||||
auto iter = sizeCache_.find(entryHash);
|
||||
auto iter = sizeCache_.find(key);
|
||||
if (iter != sizeCache_.end()) {
|
||||
entry = iter->second.get();
|
||||
} else {
|
||||
@@ -147,7 +144,7 @@ void TextDrawerAndroid::MeasureStringRect(const char *str, size_t len, const Bou
|
||||
entry = new TextMeasureEntry();
|
||||
entry->width = sizecx;
|
||||
entry->height = sizecy;
|
||||
sizeCache_[entryHash] = std::unique_ptr<TextMeasureEntry>(entry);
|
||||
sizeCache_[key] = std::unique_ptr<TextMeasureEntry>(entry);
|
||||
}
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
|
||||
@@ -166,14 +163,12 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x,
|
||||
if (text.empty())
|
||||
return;
|
||||
|
||||
uint32_t stringHash = hash::Adler32((const uint8_t *)text.data(), text.size());
|
||||
uint32_t entryHash = stringHash ^ fontHash_ ^ (align << 24);
|
||||
|
||||
CacheKey key{ std::string(str), fontHash_ };
|
||||
target.Flush(true);
|
||||
|
||||
TextStringEntry *entry;
|
||||
|
||||
auto iter = cache_.find(entryHash);
|
||||
auto iter = cache_.find(key);
|
||||
if (iter != cache_.end()) {
|
||||
entry = iter->second.get();
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
@@ -223,7 +218,7 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x,
|
||||
desc.initData.push_back((uint8_t *)bitmapData);
|
||||
entry->texture = draw_->CreateTexture(desc);
|
||||
delete[] bitmapData;
|
||||
cache_[entryHash] = std::unique_ptr<TextStringEntry>(entry);
|
||||
cache_[key] = std::unique_ptr<TextStringEntry>(entry);
|
||||
draw_->BindTexture(0, entry->texture);
|
||||
}
|
||||
float w = entry->bmWidth * fontScaleX_ * dpiScale_;
|
||||
|
||||
@@ -44,9 +44,8 @@ private:
|
||||
|
||||
std::map<uint32_t, AndroidFontEntry> fontMap_;
|
||||
|
||||
// The key is the CityHash of the string xor the fontHash_.
|
||||
std::map<uint32_t, std::unique_ptr<TextStringEntry>> cache_;
|
||||
std::map<uint32_t, std::unique_ptr<TextMeasureEntry>> sizeCache_;
|
||||
std::map<CacheKey, std::unique_ptr<TextStringEntry>> cache_;
|
||||
std::map<CacheKey, std::unique_ptr<TextMeasureEntry>> sizeCache_;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -119,11 +119,10 @@ void TextDrawerWin32::SetFont(uint32_t fontHandle) {
|
||||
}
|
||||
|
||||
void TextDrawerWin32::MeasureString(const char *str, size_t len, float *w, float *h) {
|
||||
uint32_t stringHash = hash::Adler32((const uint8_t *)str, len);
|
||||
uint32_t entryHash = stringHash ^ fontHash_;
|
||||
|
||||
CacheKey key{ std::string(str, len), fontHash_ };
|
||||
|
||||
TextMeasureEntry *entry;
|
||||
auto iter = sizeCache_.find(entryHash);
|
||||
auto iter = sizeCache_.find(key);
|
||||
if (iter != sizeCache_.end()) {
|
||||
entry = iter->second.get();
|
||||
} else {
|
||||
@@ -139,7 +138,7 @@ void TextDrawerWin32::MeasureString(const char *str, size_t len, float *w, float
|
||||
entry = new TextMeasureEntry();
|
||||
entry->width = size.cx;
|
||||
entry->height = size.cy;
|
||||
sizeCache_[entryHash] = std::unique_ptr<TextMeasureEntry>(entry);
|
||||
sizeCache_[key] = std::unique_ptr<TextMeasureEntry>(entry);
|
||||
}
|
||||
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
@@ -164,11 +163,10 @@ void TextDrawerWin32::MeasureStringRect(const char *str, size_t len, const Bound
|
||||
float total_w = 0.0f;
|
||||
float total_h = 0.0f;
|
||||
for (size_t i = 0; i < lines.size(); i++) {
|
||||
uint32_t stringHash = hash::Adler32((const uint8_t *)&lines[i][0], lines[i].length());
|
||||
uint32_t entryHash = stringHash ^ fontHash_;
|
||||
CacheKey key{ lines[i], fontHash_ };
|
||||
|
||||
TextMeasureEntry *entry;
|
||||
auto iter = sizeCache_.find(entryHash);
|
||||
auto iter = sizeCache_.find(key);
|
||||
if (iter != sizeCache_.end()) {
|
||||
entry = iter->second.get();
|
||||
} else {
|
||||
@@ -179,7 +177,7 @@ void TextDrawerWin32::MeasureStringRect(const char *str, size_t len, const Bound
|
||||
entry = new TextMeasureEntry();
|
||||
entry->width = size.cx;
|
||||
entry->height = size.cy;
|
||||
sizeCache_[entryHash] = std::unique_ptr<TextMeasureEntry>(entry);
|
||||
sizeCache_[key] = std::unique_ptr<TextMeasureEntry>(entry);
|
||||
}
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
|
||||
@@ -197,14 +195,13 @@ void TextDrawerWin32::DrawString(DrawBuffer &target, const char *str, float x, f
|
||||
if (!strlen(str))
|
||||
return;
|
||||
|
||||
uint32_t stringHash = hash::Adler32((const uint8_t *)str, strlen(str));
|
||||
uint32_t entryHash = stringHash ^ fontHash_ ^ (align << 24);
|
||||
CacheKey key{ std::string(str), fontHash_ };
|
||||
|
||||
target.Flush(true);
|
||||
|
||||
TextStringEntry *entry;
|
||||
|
||||
auto iter = cache_.find(entryHash);
|
||||
auto iter = cache_.find(key);
|
||||
if (iter != cache_.end()) {
|
||||
entry = iter->second.get();
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
@@ -304,7 +301,7 @@ void TextDrawerWin32::DrawString(DrawBuffer &target, const char *str, float x, f
|
||||
delete[] bitmapData16;
|
||||
if (bitmapData32)
|
||||
delete[] bitmapData32;
|
||||
cache_[entryHash] = std::unique_ptr<TextStringEntry>(entry);
|
||||
cache_[key] = std::unique_ptr<TextStringEntry>(entry);
|
||||
}
|
||||
|
||||
draw_->BindTexture(0, entry->texture);
|
||||
|
||||
@@ -36,9 +36,8 @@ protected:
|
||||
std::map<uint32_t, std::unique_ptr<TextDrawerFontContext>> fontMap_;
|
||||
|
||||
uint32_t fontHash_;
|
||||
// The key is the CityHash of the string xor the fontHash_.
|
||||
std::map<uint32_t, std::unique_ptr<TextStringEntry>> cache_;
|
||||
std::map<uint32_t, std::unique_ptr<TextMeasureEntry>> sizeCache_;
|
||||
std::map<CacheKey, std::unique_ptr<TextStringEntry>> cache_;
|
||||
std::map<CacheKey, std::unique_ptr<TextMeasureEntry>> sizeCache_;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -64,7 +64,7 @@ void ProcessGPUFeatures() {
|
||||
gl_extensions.bugs |= BUG_FBO_UNUSABLE;
|
||||
}
|
||||
|
||||
if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) {
|
||||
if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) {
|
||||
if (!strcmp(gl_extensions.model, "PowerVR SGX 543") ||
|
||||
!strcmp(gl_extensions.model, "PowerVR SGX 540") ||
|
||||
!strcmp(gl_extensions.model, "PowerVR SGX 530") ||
|
||||
@@ -120,9 +120,9 @@ void CheckGLExtensions() {
|
||||
} else if (vendor == "ARM") {
|
||||
gl_extensions.gpuVendor = GPU_VENDOR_ARM;
|
||||
} else if (vendor == "Imagination Technologies") {
|
||||
gl_extensions.gpuVendor = GPU_VENDOR_POWERVR;
|
||||
gl_extensions.gpuVendor = GPU_VENDOR_IMGTEC;
|
||||
} else if (vendor == "Qualcomm") {
|
||||
gl_extensions.gpuVendor = GPU_VENDOR_ADRENO;
|
||||
gl_extensions.gpuVendor = GPU_VENDOR_QUALCOMM;
|
||||
} else if (vendor == "Broadcom") {
|
||||
gl_extensions.gpuVendor = GPU_VENDOR_BROADCOM;
|
||||
// Just for reference: Galaxy Y has renderer == "VideoCore IV HW"
|
||||
|
||||
@@ -12,8 +12,8 @@ enum {
|
||||
GPU_VENDOR_AMD = 2,
|
||||
GPU_VENDOR_INTEL = 3,
|
||||
GPU_VENDOR_ARM = 4, // Mali
|
||||
GPU_VENDOR_POWERVR = 5,
|
||||
GPU_VENDOR_ADRENO = 6,
|
||||
GPU_VENDOR_IMGTEC = 5,
|
||||
GPU_VENDOR_QUALCOMM = 6,
|
||||
GPU_VENDOR_BROADCOM = 7,
|
||||
GPU_VENDOR_UNKNOWN = 0,
|
||||
};
|
||||
|
||||
@@ -765,19 +765,19 @@ void VulkanRenderManager::Submit(int frame, bool triggerFence) {
|
||||
if (frameData.hasInitCommands) {
|
||||
cmdBufs[numCmdBufs++] = frameData.initCmd;
|
||||
frameData.hasInitCommands = false;
|
||||
}
|
||||
if (false) {
|
||||
// Send the init commands off separately. Used this once to confirm that the cause of a device loss was in the init cmdbuf.
|
||||
VkSubmitInfo submit_info{ VK_STRUCTURE_TYPE_SUBMIT_INFO };
|
||||
submit_info.commandBufferCount = (uint32_t)numCmdBufs;
|
||||
submit_info.pCommandBuffers = cmdBufs;
|
||||
res = vkQueueSubmit(vulkan_->GetGraphicsQueue(), 1, &submit_info, VK_NULL_HANDLE);
|
||||
if (res == VK_ERROR_DEVICE_LOST) {
|
||||
_assert_msg_(G3D, false, "Lost the Vulkan device!");
|
||||
} else {
|
||||
_assert_msg_(G3D, res == VK_SUCCESS, "vkQueueSubmit failed! result=%d", (int)res);
|
||||
if (splitSubmit_) {
|
||||
// Send the init commands off separately. Used this once to confirm that the cause of a device loss was in the init cmdbuf.
|
||||
VkSubmitInfo submit_info{ VK_STRUCTURE_TYPE_SUBMIT_INFO };
|
||||
submit_info.commandBufferCount = (uint32_t)numCmdBufs;
|
||||
submit_info.pCommandBuffers = cmdBufs;
|
||||
res = vkQueueSubmit(vulkan_->GetGraphicsQueue(), 1, &submit_info, VK_NULL_HANDLE);
|
||||
if (res == VK_ERROR_DEVICE_LOST) {
|
||||
_assert_msg_(G3D, false, "Lost the Vulkan device!");
|
||||
} else {
|
||||
_assert_msg_(G3D, res == VK_SUCCESS, "vkQueueSubmit failed (init)! result=%d", (int)res);
|
||||
}
|
||||
numCmdBufs = 0;
|
||||
}
|
||||
numCmdBufs = 0;
|
||||
}
|
||||
cmdBufs[numCmdBufs++] = frameData.mainCmd;
|
||||
|
||||
@@ -798,7 +798,7 @@ void VulkanRenderManager::Submit(int frame, bool triggerFence) {
|
||||
if (res == VK_ERROR_DEVICE_LOST) {
|
||||
_assert_msg_(G3D, false, "Lost the Vulkan device!");
|
||||
} else {
|
||||
_assert_msg_(G3D, res == VK_SUCCESS, "vkQueueSubmit failed! result=%d", (int)res);
|
||||
_assert_msg_(G3D, res == VK_SUCCESS, "vkQueueSubmit failed (main, split=%d)! result=%d", (int)splitSubmit_, (int)res);
|
||||
}
|
||||
|
||||
// When !triggerFence, we notify after syncing with Vulkan.
|
||||
@@ -826,8 +826,8 @@ void VulkanRenderManager::EndSubmitFrame(int frame) {
|
||||
present.waitSemaphoreCount = 1;
|
||||
|
||||
VkResult res = vkQueuePresentKHR(vulkan_->GetGraphicsQueue(), &present);
|
||||
// TODO: Deal with VK_SUBOPTIMAL_WSI ?
|
||||
if (res == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||
// TODO: Deal with VK_SUBOPTIMAL_KHR ?
|
||||
if (res == VK_ERROR_OUT_OF_DATE_KHR || res == VK_SUBOPTIMAL_KHR) {
|
||||
// ignore, it'll be fine. this happens sometimes during resizes, and we do make sure to recreate the swap chain.
|
||||
} else {
|
||||
_assert_msg_(G3D, res == VK_SUCCESS, "vkQueuePresentKHR failed! result=%d", (int)res);
|
||||
|
||||
@@ -208,6 +208,10 @@ public:
|
||||
return !framebuffers_.empty();
|
||||
}
|
||||
|
||||
void SetSplitSubmit(bool split) {
|
||||
splitSubmit_ = split;
|
||||
}
|
||||
|
||||
private:
|
||||
bool InitBackbufferFramebuffers(int width, int height);
|
||||
bool InitDepthStencilBuffer(VkCommandBuffer cmd); // Used for non-buffered rendering.
|
||||
@@ -259,6 +263,7 @@ private:
|
||||
bool insideFrame_ = false;
|
||||
VKRStep *curRenderStep_ = nullptr;
|
||||
std::vector<VKRStep *> steps_;
|
||||
bool splitSubmit_ = false;
|
||||
|
||||
// Execution time state
|
||||
bool run_ = true;
|
||||
|
||||
@@ -250,6 +250,17 @@ enum InfoField {
|
||||
DRIVER,
|
||||
};
|
||||
|
||||
enum class GPUVendor {
|
||||
VENDOR_UNKNOWN,
|
||||
VENDOR_NVIDIA,
|
||||
VENDOR_INTEL,
|
||||
VENDOR_AMD,
|
||||
VENDOR_ARM, // Mali
|
||||
VENDOR_QUALCOMM,
|
||||
VENDOR_IMGTEC, // PowerVR
|
||||
VENDOR_BROADCOM, // Raspberry
|
||||
};
|
||||
|
||||
enum class NativeObject {
|
||||
CONTEXT,
|
||||
CONTEXT_EX,
|
||||
@@ -483,6 +494,7 @@ struct PipelineDesc {
|
||||
};
|
||||
|
||||
struct DeviceCaps {
|
||||
GPUVendor vendor;
|
||||
DataFormat preferredDepthBufferFormat;
|
||||
DataFormat preferredShadowMapFormatLow;
|
||||
DataFormat preferredShadowMapFormatHigh;
|
||||
@@ -653,7 +665,7 @@ DrawContext *T3DCreateDX9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapt
|
||||
DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd);
|
||||
#endif
|
||||
|
||||
DrawContext *T3DCreateVulkanContext(VulkanContext *context);
|
||||
DrawContext *T3DCreateVulkanContext(VulkanContext *context, bool split);
|
||||
|
||||
// UBs for the preset shaders
|
||||
|
||||
|
||||
@@ -221,6 +221,7 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de
|
||||
caps_.framebufferDepthBlitSupported = false;
|
||||
caps_.framebufferDepthCopySupported = true;
|
||||
|
||||
|
||||
D3D11_FEATURE_DATA_D3D11_OPTIONS options{};
|
||||
HRESULT result = device_->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, sizeof(options));
|
||||
if (SUCCEEDED(result)) {
|
||||
@@ -241,6 +242,16 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
adapter->GetDesc(&desc);
|
||||
adapterDesc_ = ConvertWStringToUTF8(desc.Description);
|
||||
switch (desc.VendorId) {
|
||||
case 0x10DE: caps_.vendor = GPUVendor::VENDOR_NVIDIA; break;
|
||||
case 0x1002:
|
||||
case 0x1022: caps_.vendor = GPUVendor::VENDOR_AMD; break;
|
||||
case 0x163C:
|
||||
case 0x8086:
|
||||
case 0x8087: caps_.vendor = GPUVendor::VENDOR_INTEL; break;
|
||||
default:
|
||||
caps_.vendor = GPUVendor::VENDOR_UNKNOWN;
|
||||
}
|
||||
adapter->Release();
|
||||
}
|
||||
dxgiDevice->Release();
|
||||
|
||||
@@ -588,11 +588,23 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID
|
||||
if (FAILED(d3d->GetAdapterIdentifier(adapterId, 0, &identifier_))) {
|
||||
ELOG("Failed to get adapter identifier: %d", adapterId);
|
||||
}
|
||||
switch (identifier_.VendorId) {
|
||||
case 0x10DE: caps_.vendor = GPUVendor::VENDOR_NVIDIA; break;
|
||||
case 0x1002:
|
||||
case 0x1022: caps_.vendor = GPUVendor::VENDOR_AMD; break;
|
||||
case 0x163C:
|
||||
case 0x8086:
|
||||
case 0x8087: caps_.vendor = GPUVendor::VENDOR_INTEL; break;
|
||||
default:
|
||||
caps_.vendor = GPUVendor::VENDOR_UNKNOWN;
|
||||
}
|
||||
|
||||
if (!FAILED(device->GetDeviceCaps(&d3dCaps_))) {
|
||||
sprintf(shadeLangVersion_, "PS: %04x VS: %04x", d3dCaps_.PixelShaderVersion & 0xFFFF, d3dCaps_.VertexShaderVersion & 0xFFFF);
|
||||
} else {
|
||||
strcpy(shadeLangVersion_, "N/A");
|
||||
}
|
||||
|
||||
caps_.multiViewport = false;
|
||||
caps_.anisoSupported = true;
|
||||
caps_.depthRangeMinusOneToOne = false;
|
||||
|
||||
@@ -490,7 +490,12 @@ public:
|
||||
}
|
||||
|
||||
void SetScissorRect(int left, int top, int width, int height) override {
|
||||
glScissor(left, targetHeight_ - (top + height), width, height);
|
||||
int y = top;
|
||||
if (!curFB_) {
|
||||
// We render "upside down" to the backbuffer since GL is silly.
|
||||
y = targetHeight_ - (top + height);
|
||||
}
|
||||
glstate.scissorRect.set(left, y, width, height);
|
||||
}
|
||||
|
||||
void SetViewports(int count, Viewport *viewports) override {
|
||||
@@ -540,15 +545,15 @@ public:
|
||||
}
|
||||
case VENDORSTRING: return (const char *)glGetString(GL_VENDOR);
|
||||
case VENDOR:
|
||||
switch (gl_extensions.gpuVendor) {
|
||||
case GPU_VENDOR_AMD: return "VENDOR_AMD";
|
||||
case GPU_VENDOR_POWERVR: return "VENDOR_POWERVR";
|
||||
case GPU_VENDOR_NVIDIA: return "VENDOR_NVIDIA";
|
||||
case GPU_VENDOR_INTEL: return "VENDOR_INTEL";
|
||||
case GPU_VENDOR_ADRENO: return "VENDOR_ADRENO";
|
||||
case GPU_VENDOR_ARM: return "VENDOR_ARM";
|
||||
case GPU_VENDOR_BROADCOM: return "VENDOR_BROADCOM";
|
||||
case GPU_VENDOR_UNKNOWN:
|
||||
switch (caps_.vendor) {
|
||||
case GPUVendor::VENDOR_AMD: return "VENDOR_AMD";
|
||||
case GPUVendor::VENDOR_IMGTEC: return "VENDOR_POWERVR";
|
||||
case GPUVendor::VENDOR_NVIDIA: return "VENDOR_NVIDIA";
|
||||
case GPUVendor::VENDOR_INTEL: return "VENDOR_INTEL";
|
||||
case GPUVendor::VENDOR_QUALCOMM: return "VENDOR_ADRENO";
|
||||
case GPUVendor::VENDOR_ARM: return "VENDOR_ARM";
|
||||
case GPUVendor::VENDOR_BROADCOM: return "VENDOR_BROADCOM";
|
||||
case GPUVendor::VENDOR_UNKNOWN:
|
||||
default:
|
||||
return "VENDOR_UNKNOWN";
|
||||
}
|
||||
@@ -584,6 +589,7 @@ private:
|
||||
int curVBufferOffsets_[4]{};
|
||||
OpenGLBuffer *curIBuffer_ = nullptr;
|
||||
int curIBufferOffset_ = 0;
|
||||
OpenGLFramebuffer *curFB_;
|
||||
|
||||
// Framebuffer state
|
||||
GLuint currentDrawHandle_ = 0;
|
||||
@@ -603,6 +609,20 @@ OpenGLContext::OpenGLContext() {
|
||||
}
|
||||
caps_.framebufferBlitSupported = gl_extensions.NV_framebuffer_blit || gl_extensions.ARB_framebuffer_object;
|
||||
caps_.framebufferDepthBlitSupported = caps_.framebufferBlitSupported;
|
||||
|
||||
switch (gl_extensions.gpuVendor) {
|
||||
case GPU_VENDOR_AMD: caps_.vendor = GPUVendor::VENDOR_AMD; break;
|
||||
case GPU_VENDOR_NVIDIA: caps_.vendor = GPUVendor::VENDOR_NVIDIA; break;
|
||||
case GPU_VENDOR_ARM: caps_.vendor = GPUVendor::VENDOR_ARM; break;
|
||||
case GPU_VENDOR_QUALCOMM: caps_.vendor = GPUVendor::VENDOR_QUALCOMM; break;
|
||||
case GPU_VENDOR_BROADCOM: caps_.vendor = GPUVendor::VENDOR_BROADCOM; break;
|
||||
case GPU_VENDOR_INTEL: caps_.vendor = GPUVendor::VENDOR_INTEL; break;
|
||||
case GPU_VENDOR_IMGTEC: caps_.vendor = GPUVendor::VENDOR_IMGTEC; break;
|
||||
case GPU_VENDOR_UNKNOWN:
|
||||
default:
|
||||
caps_.vendor = GPUVendor::VENDOR_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
OpenGLContext::~OpenGLContext() {
|
||||
@@ -929,7 +949,7 @@ bool OpenGLContext::CopyFramebufferToMemorySync(Framebuffer *src, int channelBit
|
||||
}
|
||||
// Apply the correct alignment.
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, alignment);
|
||||
if (!gl_extensions.IsGLES || (gl_extensions.GLES3 && gl_extensions.gpuVendor != GPU_VENDOR_NVIDIA)) {
|
||||
if (!gl_extensions.IsGLES || (gl_extensions.GLES3 && caps_.vendor != GPUVendor::VENDOR_NVIDIA)) {
|
||||
// Some drivers seem to require we specify this. See #8254.
|
||||
glPixelStorei(GL_PACK_ROW_LENGTH, pixelStride);
|
||||
}
|
||||
@@ -1680,6 +1700,7 @@ void OpenGLContext::fbo_unbind() {
|
||||
|
||||
void OpenGLContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp) {
|
||||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
curFB_ = (OpenGLFramebuffer *)fbo;
|
||||
if (fbo) {
|
||||
OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo;
|
||||
// Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "Common/Vulkan/SPIRVDisasm.h"
|
||||
#include "Core/Config.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/display.h"
|
||||
@@ -348,7 +349,7 @@ class VKFramebuffer;
|
||||
|
||||
class VKContext : public DrawContext {
|
||||
public:
|
||||
VKContext(VulkanContext *vulkan);
|
||||
VKContext(VulkanContext *vulkan, bool splitSubmit);
|
||||
virtual ~VKContext();
|
||||
|
||||
const DeviceCaps &GetDeviceCaps() const override {
|
||||
@@ -674,7 +675,7 @@ bool VKTexture::Create(VkCommandBuffer cmd, const TextureDesc &desc) {
|
||||
return true;
|
||||
}
|
||||
|
||||
VKContext::VKContext(VulkanContext *vulkan)
|
||||
VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit)
|
||||
: vulkan_(vulkan), caps_{}, renderManager_(vulkan) {
|
||||
caps_.anisoSupported = vulkan->GetFeaturesAvailable().samplerAnisotropy != 0;
|
||||
caps_.geometryShaderSupported = vulkan->GetFeaturesAvailable().geometryShader != 0;
|
||||
@@ -687,6 +688,17 @@ VKContext::VKContext(VulkanContext *vulkan)
|
||||
caps_.framebufferDepthCopySupported = true; // Will pretty much always be the case.
|
||||
caps_.preferredDepthBufferFormat = DataFormat::D24_S8; // TODO: Ask vulkan.
|
||||
|
||||
switch (vulkan->GetPhysicalDeviceProperties().vendorID) {
|
||||
case VULKAN_VENDOR_AMD: caps_.vendor = GPUVendor::VENDOR_AMD; break;
|
||||
case VULKAN_VENDOR_ARM: caps_.vendor = GPUVendor::VENDOR_ARM; break;
|
||||
case VULKAN_VENDOR_IMGTEC: caps_.vendor = GPUVendor::VENDOR_IMGTEC; break;
|
||||
case VULKAN_VENDOR_NVIDIA: caps_.vendor = GPUVendor::VENDOR_NVIDIA; break;
|
||||
case VULKAN_VENDOR_QUALCOMM: caps_.vendor = GPUVendor::VENDOR_QUALCOMM; break;
|
||||
case VULKAN_VENDOR_INTEL: caps_.vendor = GPUVendor::VENDOR_INTEL; break;
|
||||
default:
|
||||
caps_.vendor = GPUVendor::VENDOR_UNKNOWN;
|
||||
}
|
||||
|
||||
device_ = vulkan->GetDevice();
|
||||
|
||||
queue_ = vulkan->GetGraphicsQueue();
|
||||
@@ -744,6 +756,8 @@ VKContext::VKContext(VulkanContext *vulkan)
|
||||
assert(VK_SUCCESS == res);
|
||||
|
||||
pipelineCache_ = vulkan_->CreatePipelineCache();
|
||||
|
||||
renderManager_.SetSplitSubmit(splitSubmit);
|
||||
}
|
||||
|
||||
VKContext::~VKContext() {
|
||||
@@ -1177,8 +1191,8 @@ void VKContext::Clear(int clearMask, uint32_t colorval, float depthVal, int sten
|
||||
renderManager_.Clear(colorval, depthVal, stencilVal, mask);
|
||||
}
|
||||
|
||||
DrawContext *T3DCreateVulkanContext(VulkanContext *vulkan) {
|
||||
return new VKContext(vulkan);
|
||||
DrawContext *T3DCreateVulkanContext(VulkanContext *vulkan, bool split) {
|
||||
return new VKContext(vulkan, split);
|
||||
}
|
||||
|
||||
void AddFeature(std::vector<std::string> &features, const char *name, VkBool32 available, VkBool32 enabled) {
|
||||
|
||||
@@ -172,7 +172,10 @@ void UIContext::DrawTextRect(const char *str, const Bounds &bounds, uint32_t col
|
||||
Draw()->DrawTextRect(fontStyle_->atlasFont, str, bounds.x, bounds.y, bounds.w, bounds.h, color, align);
|
||||
} else {
|
||||
textDrawer_->SetFontScale(fontScaleX_, fontScaleY_);
|
||||
textDrawer_->DrawStringRect(*Draw(), str, bounds, color, align);
|
||||
Bounds rounded = bounds;
|
||||
rounded.x = floorf(rounded.x);
|
||||
rounded.y = floorf(rounded.y);
|
||||
textDrawer_->DrawStringRect(*Draw(), str, rounded, color, align);
|
||||
RebindTexture();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -638,6 +638,7 @@ void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
|
||||
edit_ = new TextEdit(temp, "", new LinearLayoutParams(10.0f));
|
||||
edit_->SetMaxLen(16);
|
||||
edit_->SetTextColor(dc.theme->popupStyle.fgColor);
|
||||
edit_->SetTextAlign(FLAG_DYNAMIC_ASCII);
|
||||
edit_->OnTextChange.Handle(this, &SliderPopupScreen::OnTextChange);
|
||||
changing_ = false;
|
||||
lin->Add(edit_);
|
||||
@@ -668,6 +669,7 @@ void SliderFloatPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
|
||||
edit_ = new TextEdit(temp, "", new LinearLayoutParams(10.0f));
|
||||
edit_->SetMaxLen(16);
|
||||
edit_->SetTextColor(dc.theme->popupStyle.fgColor);
|
||||
edit_->SetTextAlign(FLAG_DYNAMIC_ASCII);
|
||||
edit_->OnTextChange.Handle(this, &SliderFloatPopupScreen::OnTextChange);
|
||||
changing_ = false;
|
||||
lin->Add(edit_);
|
||||
|
||||
@@ -791,12 +791,12 @@ void TextEdit::Draw(UIContext &dc) {
|
||||
dc.DrawTextRect(placeholderText_.c_str(), bounds_, c, ALIGN_CENTER);
|
||||
}
|
||||
} else {
|
||||
dc.DrawTextRect(text_.c_str(), textBounds, textColor, ALIGN_VCENTER | ALIGN_LEFT);
|
||||
dc.DrawTextRect(text_.c_str(), textBounds, textColor, ALIGN_VCENTER | ALIGN_LEFT | align_);
|
||||
}
|
||||
|
||||
if (HasFocus()) {
|
||||
// Hack to find the caret position. Might want to find a better way...
|
||||
dc.MeasureTextCount(dc.theme->uiFont, 1.0f, 1.0f, text_.c_str(), caret_, &w, &h, ALIGN_VCENTER | ALIGN_LEFT);
|
||||
dc.MeasureTextCount(dc.theme->uiFont, 1.0f, 1.0f, text_.c_str(), caret_, &w, &h, ALIGN_VCENTER | ALIGN_LEFT | align_);
|
||||
float caretX = w - scrollPos_;
|
||||
if (caretX > bounds_.w) {
|
||||
scrollPos_ += caretX - bounds_.w;
|
||||
@@ -811,7 +811,7 @@ void TextEdit::Draw(UIContext &dc) {
|
||||
}
|
||||
|
||||
void TextEdit::GetContentDimensions(const UIContext &dc, float &w, float &h) const {
|
||||
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, text_.size() ? text_.c_str() : "Wj", &w, &h);
|
||||
dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, text_.size() ? text_.c_str() : "Wj", &w, &h, align_);
|
||||
w += 2;
|
||||
h += 2;
|
||||
}
|
||||
@@ -1115,7 +1115,7 @@ void Slider::Draw(UIContext &dc) {
|
||||
else
|
||||
sprintf(temp, "%i", *value_);
|
||||
dc.SetFontStyle(dc.theme->uiFont);
|
||||
dc.DrawText(temp, bounds_.x2() - 22, bounds_.centerY(), dc.theme->popupStyle.fgColor, ALIGN_CENTER);
|
||||
dc.DrawText(temp, bounds_.x2() - 22, bounds_.centerY(), dc.theme->popupStyle.fgColor, ALIGN_CENTER | FLAG_DYNAMIC_ASCII);
|
||||
}
|
||||
|
||||
void Slider::Update() {
|
||||
|
||||
@@ -784,6 +784,7 @@ public:
|
||||
void SetTextColor(uint32_t color) { textColor_ = color; hasTextColor_ = true; }
|
||||
const std::string &GetText() const { return text_; }
|
||||
void SetMaxLen(size_t maxLen) { maxLen_ = maxLen; }
|
||||
void SetTextAlign(int align) { align_ = align; } // Only really useful for setting FLAG_DYNAMIC_ASCII
|
||||
|
||||
void GetContentDimensions(const UIContext &dc, float &w, float &h) const override;
|
||||
void Draw(UIContext &dc) override;
|
||||
@@ -805,6 +806,7 @@ private:
|
||||
int scrollPos_ = 0;
|
||||
size_t maxLen_;
|
||||
bool ctrlDown_ = false; // TODO: Make some global mechanism for this.
|
||||
int align_ = 0;
|
||||
// TODO: Selections
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user