From 5a3d229d042310a6b85b2570aed18b6c33e844ba Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 Jun 2017 12:15:59 -0700 Subject: [PATCH 01/23] Headless: Add support for SDL. --- CMakeLists.txt | 4 +- headless/Headless.cpp | 6 +- headless/SDLHeadlessHost.cpp | 202 +++++++++++++++++++++++++++++++++++ headless/SDLHeadlessHost.h | 48 +++++++++ 4 files changed, 257 insertions(+), 3 deletions(-) create mode 100644 headless/SDLHeadlessHost.cpp create mode 100644 headless/SDLHeadlessHost.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c827b4f93d..4f4674d1da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1771,7 +1771,9 @@ if(HEADLESS) headless/Headless.cpp headless/StubHost.h headless/Compare.cpp - headless/Compare.h) + headless/Compare.h + headless/SDLHeadlessHost.cpp + headless/SDLHeadlessHost.h) target_link_libraries(PPSSPPHeadless ${COCOA_LIBRARY} ${LinkCommon}) setup_target_project(PPSSPPHeadless headless) diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 19a7f42a61..ef3ead4188 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -24,8 +24,10 @@ #include "Compare.h" #include "StubHost.h" -#ifdef _WIN32 +#if defined(_WIN32) #include "WindowsHeadlessHost.h" +#elif defined(SDL) +#include "SDLHeadlessHost.h" #endif // https://github.com/richq/android-ndk-profiler @@ -199,7 +201,7 @@ int main(int argc, const char* argv[]) { PROFILE_INIT(); -#ifdef _DEBUG +#if defined(_DEBUG) && defined(_MSC_VER) _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif diff --git a/headless/SDLHeadlessHost.cpp b/headless/SDLHeadlessHost.cpp new file mode 100644 index 0000000000..8bf7ba8015 --- /dev/null +++ b/headless/SDLHeadlessHost.cpp @@ -0,0 +1,202 @@ +// Copyright (c) 2017- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include +#include +#include "gfx/gl_lost_manager.h" + +#include "SDLHeadlessHost.h" +#include "Compare.h" + +#include "Common/FileUtil.h" +#include "Common/GraphicsContext.h" + +#include "Core/CoreParameter.h" +#include "Core/System.h" +#include "GPU/Common/GPUDebugInterface.h" +#include "GPU/GPUState.h" + +#include "base/logging.h" +#include "gfx/gl_common.h" +#include "gfx_es2/gpu_features.h" +#include "file/vfs.h" +#include "file/zip_read.h" + +const bool WINDOW_VISIBLE = false; +const int WINDOW_WIDTH = 480; +const int WINDOW_HEIGHT = 272; + +SDL_Window *CreateHiddenWindow() { + Uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS; + if (!WINDOW_VISIBLE) { + flags |= SDL_WINDOW_HIDDEN; + } + return SDL_CreateWindow("PPSSPPHeadless", 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, flags); +} + +class GLDummyGraphicsContext : public DummyGraphicsContext { +public: + GLDummyGraphicsContext() { + CheckGLExtensions(); + draw_ = Draw::T3DCreateGLContext(); + } + ~GLDummyGraphicsContext() { delete draw_; } + + Draw::DrawContext *GetDrawContext() override { + return draw_; + } + +private: + Draw::DrawContext *draw_; +}; + +void SDLHeadlessHost::LoadNativeAssets() { + VFSRegister("", new DirectoryAssetReader("assets/")); + VFSRegister("", new DirectoryAssetReader("")); + VFSRegister("", new DirectoryAssetReader("../")); +} + +void SDLHeadlessHost::SendDebugOutput(const std::string &output) { + fwrite(output.data(), sizeof(char), output.length(), stdout); + OutputDebugStringUTF8(output.c_str()); +} + +void SDLHeadlessHost::SendOrCollectDebugOutput(const std::string &data) { + if (PSP_CoreParameter().printfEmuLog) + SendDebugOutput(data); + else if (PSP_CoreParameter().collectEmuLog) + *PSP_CoreParameter().collectEmuLog += data; + else + DEBUG_LOG(COMMON, "%s", data.c_str()); +} + +void SDLHeadlessHost::SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h) { + // Only if we're actually comparing. + if (comparisonScreenshot.empty()) { + return; + } + + // We ignore the current framebuffer parameters and just grab the full screen. + const static u32 FRAME_STRIDE = 512; + const static u32 FRAME_WIDTH = 480; + const static u32 FRAME_HEIGHT = 272; + + GPUDebugBuffer buffer; + gpuDebug->GetCurrentFramebuffer(buffer, GPU_DBG_FRAMEBUF_RENDER); + const std::vector pixels = TranslateDebugBufferToCompare(&buffer, 512, 272); + + std::string error; + double errors = CompareScreenshot(pixels, FRAME_STRIDE, FRAME_WIDTH, FRAME_HEIGHT, comparisonScreenshot, error); + if (errors < 0) + SendOrCollectDebugOutput(error); + + if (errors > 0) { + char temp[256]; + snprintf(temp, 256, "Screenshot error: %f%%\n", errors * 100.0f); + SendOrCollectDebugOutput(temp); + } + + if (errors > 0 && !teamCityMode) { + // Lazy, just read in the original header to output the failed screenshot. + u8 header[14 + 40] = {0}; + FILE *bmp = File::OpenCFile(comparisonScreenshot, "rb"); + if (bmp) { + fread(&header, sizeof(header), 1, bmp); + fclose(bmp); + } + + FILE *saved = File::OpenCFile("__testfailure.bmp", "wb"); + if (saved) { + fwrite(&header, sizeof(header), 1, saved); + fwrite(pixels.data(), sizeof(u32), FRAME_STRIDE * FRAME_HEIGHT, saved); + fclose(saved); + + SendOrCollectDebugOutput("Actual output written to: __testfailure.bmp\n"); + } + } +} + +void SDLHeadlessHost::SetComparisonScreenshot(const std::string &filename) { + comparisonScreenshot = filename; +} + +bool SDLHeadlessHost::InitGraphics(std::string *error_message, GraphicsContext **ctx) { + // TODO + //SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetSwapInterval(1); + + screen_ = CreateHiddenWindow(); + glContext_ = SDL_GL_CreateContext(screen_); + +#ifndef USING_GLES2 + // Some core profile drivers elide certain extensions from GL_EXTENSIONS/etc. + // glewExperimental allows us to force GLEW to search for the pointers anyway. + if (gl_extensions.IsCoreContext) + glewExperimental = true; + if (GLEW_OK != glewInit()) { + printf("Failed to initialize glew!\n"); + return false; + } + // Unfortunately, glew will generate an invalid enum error, ignore. + if (gl_extensions.IsCoreContext) + glGetError(); + + if (GLEW_VERSION_2_0) { + printf("OpenGL 2.0 or higher.\n"); + } else { + printf("Sorry, this program requires OpenGL 2.0.\n"); + return false; + } +#endif + + gl_lost_manager_init(); + + GraphicsContext *graphicsContext = new GLDummyGraphicsContext(); + *ctx = graphicsContext; + gfx_ = graphicsContext; + + LoadNativeAssets(); + + return true; +} + +void SDLHeadlessHost::ShutdownGraphics() { + gfx_->Shutdown(); + delete gfx_; + gfx_ = nullptr; + + SDL_GL_DeleteContext(glContext_); + glContext_ = nullptr; + SDL_DestroyWindow(screen_); + screen_ = nullptr; + + gl_lost_manager_shutdown(); +} + +void SDLHeadlessHost::SwapBuffers() { + gfx_->SwapBuffers(); + SDL_GL_SwapWindow(screen_); +} diff --git a/headless/SDLHeadlessHost.h b/headless/SDLHeadlessHost.h new file mode 100644 index 0000000000..72bfd7630a --- /dev/null +++ b/headless/SDLHeadlessHost.h @@ -0,0 +1,48 @@ +// Copyright (c) 2017- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include "StubHost.h" + +#undef HEADLESSHOST_CLASS +#define HEADLESSHOST_CLASS SDLHeadlessHost + +struct SDL_Window; +typedef void *SDL_GLContext; + +class SDLHeadlessHost : public HeadlessHost +{ +public: + virtual bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override; + virtual void ShutdownGraphics() override; + + virtual void SwapBuffers() override; + + virtual void SendDebugOutput(const std::string &output) override; + virtual void SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h) override; + virtual void SetComparisonScreenshot(const std::string &filename) override; + +protected: + void LoadNativeAssets(); + void SendOrCollectDebugOutput(const std::string &output); + + SDL_Window *screen_; + SDL_GLContext glContext_; + GraphicsContext *gfx_; + std::string comparisonScreenshot; +}; From 72e0a24724f56fe1c50a72768e055ba026decde3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 20 Sep 2017 08:30:34 -0700 Subject: [PATCH 02/23] GPU: Reset shader state on shader reset. Was ending up with lastFSID being -1, but being used. Seen in gpu/commands/blend test. --- GPU/D3D11/ShaderManagerD3D11.cpp | 11 ++++++----- GPU/Directx9/ShaderManagerDX9.cpp | 9 +++------ GPU/GLES/ShaderManagerGLES.cpp | 5 +---- GPU/GPUCommon.cpp | 6 +++--- GPU/Vulkan/ShaderManagerVulkan.cpp | 14 +++++++------- 5 files changed, 20 insertions(+), 25 deletions(-) diff --git a/GPU/D3D11/ShaderManagerD3D11.cpp b/GPU/D3D11/ShaderManagerD3D11.cpp index 9199242740..1da09dab62 100644 --- a/GPU/D3D11/ShaderManagerD3D11.cpp +++ b/GPU/D3D11/ShaderManagerD3D11.cpp @@ -124,8 +124,9 @@ void ShaderManagerD3D11::Clear() { } fsCache_.clear(); vsCache_.clear(); - lastFSID_.clear(); - lastVSID_.clear(); + lastFSID_.set_invalid(); + lastVSID_.set_invalid(); + gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE); } void ShaderManagerD3D11::ClearShaders() { @@ -135,11 +136,11 @@ void ShaderManagerD3D11::ClearShaders() { } void ShaderManagerD3D11::DirtyLastShader() { - lastFSID_.clear(); - lastVSID_.clear(); + lastFSID_.set_invalid(); + lastVSID_.set_invalid(); lastVShader_ = nullptr; lastFShader_ = nullptr; - gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE|DIRTY_FRAGMENTSHADER_STATE); + gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE); } uint64_t ShaderManagerD3D11::UpdateUniforms() { diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index 05da5bba0b..78988911cc 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -510,9 +510,6 @@ void ShaderManagerDX9::Clear() { } fsCache_.clear(); vsCache_.clear(); - gstate_c.Dirty(DIRTY_ALL_UNIFORMS); - lastFSID_.clear(); - lastVSID_.clear(); DirtyShader(); } @@ -523,11 +520,11 @@ void ShaderManagerDX9::ClearCache(bool deleteThem) { void ShaderManagerDX9::DirtyShader() { // Forget the last shader ID - lastFSID_.clear(); - lastVSID_.clear(); + lastFSID_.set_invalid(); + lastVSID_.set_invalid(); lastVShader_ = nullptr; lastPShader_ = nullptr; - gstate_c.Dirty(DIRTY_ALL_UNIFORMS); + gstate_c.Dirty(DIRTY_ALL_UNIFORMS | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE); } void ShaderManagerDX9::DirtyLastShader() { // disables vertex arrays diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index c6ebda7579..33b4b46d99 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -764,9 +764,6 @@ void ShaderManagerGLES::Clear() { linkedShaderCache_.clear(); fsCache_.Clear(); vsCache_.Clear(); - gstate_c.Dirty(DIRTY_ALL_UNIFORMS); - lastFSID_.set_invalid(); - lastVSID_.set_invalid(); DirtyShader(); } @@ -780,7 +777,7 @@ void ShaderManagerGLES::DirtyShader() { lastFSID_.set_invalid(); lastVSID_.set_invalid(); DirtyLastShader(); - gstate_c.Dirty(DIRTY_ALL_UNIFORMS); + gstate_c.Dirty(DIRTY_ALL_UNIFORMS | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE); shaderSwitchDirtyUniforms_ = 0; } diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index c7add7fc2b..36dded6568 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -49,7 +49,7 @@ const CommonCommandTableEntry commonCommandTable[] = { // Changes that dirty the framebuffer { GE_CMD_FRAMEBUFPTR, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS }, { GE_CMD_FRAMEBUFWIDTH, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE }, - { GE_CMD_FRAMEBUFPIXFORMAT, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_FRAGMENTSHADER_STATE}, + { GE_CMD_FRAMEBUFPIXFORMAT, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_FRAGMENTSHADER_STATE }, { GE_CMD_ZBUFPTR, FLAG_FLUSHBEFOREONCHANGE }, { GE_CMD_ZBUFWIDTH, FLAG_FLUSHBEFOREONCHANGE }, @@ -1789,7 +1789,7 @@ void GPUCommon::Execute_BoneMtxNum(u32 op, u32 diff) { } } - const int numPlusCount = (op & 0x7F) + i; + const unsigned int numPlusCount = (op & 0x7F) + i; for (unsigned int num = op & 0x7F; num < numPlusCount; num += 12) { gstate_c.Dirty(DIRTY_BONEMATRIX0 << (num / 12)); } @@ -1801,7 +1801,7 @@ void GPUCommon::Execute_BoneMtxNum(u32 op, u32 diff) { } } - const int numPlusCount = (op & 0x7F) + i; + const unsigned int numPlusCount = (op & 0x7F) + i; for (unsigned int num = op & 0x7F; num < numPlusCount; num += 12) { gstate_c.deferredVertTypeDirty |= DIRTY_BONEMATRIX0 << (num / 12); } diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index fc2d3cae86..c5a70db8f4 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -185,22 +185,22 @@ void ShaderManagerVulkan::Clear() { }); fsCache_.Clear(); vsCache_.Clear(); - lastFSID_.clear(); - lastVSID_.clear(); + lastFSID_.set_invalid(); + lastVSID_.set_invalid(); + gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE); } void ShaderManagerVulkan::ClearShaders() { Clear(); DirtyShader(); - gstate_c.Dirty(DIRTY_ALL_UNIFORMS); + gstate_c.Dirty(DIRTY_ALL_UNIFORMS | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE); } void ShaderManagerVulkan::DirtyShader() { // Forget the last shader ID - lastFSID_.clear(); - lastVSID_.clear(); - lastVShader_ = nullptr; - lastFShader_ = nullptr; + lastFSID_.set_invalid(); + lastVSID_.set_invalid(); + DirtyLastShader(); } void ShaderManagerVulkan::DirtyLastShader() { // disables vertex arrays From 7db9dfb50b3b43ead5667c824f7790d334748347 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 20 Sep 2017 08:58:42 -0700 Subject: [PATCH 03/23] Headless: Reduce some duplication. We can share the screenshot code for SDL. --- CMakeLists.txt | 1 + android/jni/Android.mk | 1 + headless/Headless.vcxproj | 8 +++ headless/Headless.vcxproj.filters | 12 ++++- headless/SDLHeadlessHost.cpp | 71 ++----------------------- headless/SDLHeadlessHost.h | 18 +++---- headless/StubHost.cpp | 88 +++++++++++++++++++++++++++++++ headless/StubHost.h | 10 +++- headless/WindowsHeadlessHost.cpp | 69 +----------------------- headless/WindowsHeadlessHost.h | 16 +++--- 10 files changed, 138 insertions(+), 156 deletions(-) create mode 100644 headless/StubHost.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f4674d1da..558517394e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1769,6 +1769,7 @@ set(NativeAssets if(HEADLESS) add_executable(PPSSPPHeadless headless/Headless.cpp + headless/StubHost.cpp headless/StubHost.h headless/Compare.cpp headless/Compare.h diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 775f4100c6..8cd5ba7603 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -444,6 +444,7 @@ ifeq ($(HEADLESS),1) LOCAL_MODULE := ppsspp_headless LOCAL_SRC_FILES := \ $(SRC)/headless/Headless.cpp \ + $(SRC)/headless/StubHost.cpp \ $(SRC)/headless/Compare.cpp include $(BUILD_EXECUTABLE) diff --git a/headless/Headless.vcxproj b/headless/Headless.vcxproj index 17d3f2fee8..4018293068 100644 --- a/headless/Headless.vcxproj +++ b/headless/Headless.vcxproj @@ -237,6 +237,13 @@ NotUsing NotUsing + + true + true + true + true + + @@ -268,6 +275,7 @@ + diff --git a/headless/Headless.vcxproj.filters b/headless/Headless.vcxproj.filters index 3f7bc674de..962db7ee84 100644 --- a/headless/Headless.vcxproj.filters +++ b/headless/Headless.vcxproj.filters @@ -22,6 +22,10 @@ Windows + + + Other Platforms + @@ -33,10 +37,16 @@ Windows + + Other Platforms + {28215e85-3e11-4a8a-8b4d-3e355b85a542} + + {d34ba935-dcca-4f21-a869-5d0b3bba7478} + - + \ No newline at end of file diff --git a/headless/SDLHeadlessHost.cpp b/headless/SDLHeadlessHost.cpp index 8bf7ba8015..42ad38c949 100644 --- a/headless/SDLHeadlessHost.cpp +++ b/headless/SDLHeadlessHost.cpp @@ -15,12 +15,13 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#ifdef SDL + #include #include #include "gfx/gl_lost_manager.h" -#include "SDLHeadlessHost.h" -#include "Compare.h" +#include "headless/SDLHeadlessHost.h" #include "Common/FileUtil.h" #include "Common/GraphicsContext.h" @@ -70,70 +71,6 @@ void SDLHeadlessHost::LoadNativeAssets() { VFSRegister("", new DirectoryAssetReader("../")); } -void SDLHeadlessHost::SendDebugOutput(const std::string &output) { - fwrite(output.data(), sizeof(char), output.length(), stdout); - OutputDebugStringUTF8(output.c_str()); -} - -void SDLHeadlessHost::SendOrCollectDebugOutput(const std::string &data) { - if (PSP_CoreParameter().printfEmuLog) - SendDebugOutput(data); - else if (PSP_CoreParameter().collectEmuLog) - *PSP_CoreParameter().collectEmuLog += data; - else - DEBUG_LOG(COMMON, "%s", data.c_str()); -} - -void SDLHeadlessHost::SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h) { - // Only if we're actually comparing. - if (comparisonScreenshot.empty()) { - return; - } - - // We ignore the current framebuffer parameters and just grab the full screen. - const static u32 FRAME_STRIDE = 512; - const static u32 FRAME_WIDTH = 480; - const static u32 FRAME_HEIGHT = 272; - - GPUDebugBuffer buffer; - gpuDebug->GetCurrentFramebuffer(buffer, GPU_DBG_FRAMEBUF_RENDER); - const std::vector pixels = TranslateDebugBufferToCompare(&buffer, 512, 272); - - std::string error; - double errors = CompareScreenshot(pixels, FRAME_STRIDE, FRAME_WIDTH, FRAME_HEIGHT, comparisonScreenshot, error); - if (errors < 0) - SendOrCollectDebugOutput(error); - - if (errors > 0) { - char temp[256]; - snprintf(temp, 256, "Screenshot error: %f%%\n", errors * 100.0f); - SendOrCollectDebugOutput(temp); - } - - if (errors > 0 && !teamCityMode) { - // Lazy, just read in the original header to output the failed screenshot. - u8 header[14 + 40] = {0}; - FILE *bmp = File::OpenCFile(comparisonScreenshot, "rb"); - if (bmp) { - fread(&header, sizeof(header), 1, bmp); - fclose(bmp); - } - - FILE *saved = File::OpenCFile("__testfailure.bmp", "wb"); - if (saved) { - fwrite(&header, sizeof(header), 1, saved); - fwrite(pixels.data(), sizeof(u32), FRAME_STRIDE * FRAME_HEIGHT, saved); - fclose(saved); - - SendOrCollectDebugOutput("Actual output written to: __testfailure.bmp\n"); - } - } -} - -void SDLHeadlessHost::SetComparisonScreenshot(const std::string &filename) { - comparisonScreenshot = filename; -} - bool SDLHeadlessHost::InitGraphics(std::string *error_message, GraphicsContext **ctx) { // TODO //SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); @@ -200,3 +137,5 @@ void SDLHeadlessHost::SwapBuffers() { gfx_->SwapBuffers(); SDL_GL_SwapWindow(screen_); } + +#endif diff --git a/headless/SDLHeadlessHost.h b/headless/SDLHeadlessHost.h index 72bfd7630a..9f50c8931f 100644 --- a/headless/SDLHeadlessHost.h +++ b/headless/SDLHeadlessHost.h @@ -17,7 +17,9 @@ #pragma once -#include "StubHost.h" +#ifdef SDL + +#include "headless/StubHost.h" #undef HEADLESSHOST_CLASS #define HEADLESSHOST_CLASS SDLHeadlessHost @@ -28,21 +30,17 @@ typedef void *SDL_GLContext; class SDLHeadlessHost : public HeadlessHost { public: - virtual bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override; - virtual void ShutdownGraphics() override; + bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override; + void ShutdownGraphics() override; - virtual void SwapBuffers() override; - - virtual void SendDebugOutput(const std::string &output) override; - virtual void SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h) override; - virtual void SetComparisonScreenshot(const std::string &filename) override; + void SwapBuffers() override; protected: void LoadNativeAssets(); - void SendOrCollectDebugOutput(const std::string &output); SDL_Window *screen_; SDL_GLContext glContext_; GraphicsContext *gfx_; - std::string comparisonScreenshot; }; + +#endif diff --git a/headless/StubHost.cpp b/headless/StubHost.cpp new file mode 100644 index 0000000000..82698770da --- /dev/null +++ b/headless/StubHost.cpp @@ -0,0 +1,88 @@ +// Copyright (c) 2017- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include "Common/FileUtil.h" +#include "Core/CoreParameter.h" +#include "Core/System.h" +#include "GPU/Common/GPUDebugInterface.h" +#include "headless/Compare.h" +#include "headless/StubHost.h" + +void HeadlessHost::SendOrCollectDebugOutput(const std::string &data) +{ + if (PSP_CoreParameter().printfEmuLog) + SendDebugOutput(data); + else if (PSP_CoreParameter().collectEmuLog) + *PSP_CoreParameter().collectEmuLog += data; + else + DEBUG_LOG(COMMON, "%s", data.c_str()); +} + +void HeadlessHost::SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h) +{ + if (!gfx_) { + return; + } + + // Only if we're actually comparing. + if (comparisonScreenshot_.empty()) { + return; + } + + // We ignore the current framebuffer parameters and just grab the full screen. + const static u32 FRAME_STRIDE = 512; + const static u32 FRAME_WIDTH = 480; + const static u32 FRAME_HEIGHT = 272; + + GPUDebugBuffer buffer; + gpuDebug->GetCurrentFramebuffer(buffer, GPU_DBG_FRAMEBUF_RENDER); + const std::vector pixels = TranslateDebugBufferToCompare(&buffer, 512, 272); + + std::string error; + double errors = CompareScreenshot(pixels, FRAME_STRIDE, FRAME_WIDTH, FRAME_HEIGHT, comparisonScreenshot_, error); + if (errors < 0) + SendOrCollectDebugOutput(error); + + if (errors > 0) + { + char temp[256]; + snprintf(temp, sizeof(temp), "Screenshot error: %f%%\n", errors * 100.0f); + SendOrCollectDebugOutput(temp); + } + + if (errors > 0 && !teamCityMode) + { + // Lazy, just read in the original header to output the failed screenshot. + u8 header[14 + 40] = {0}; + FILE *bmp = File::OpenCFile(comparisonScreenshot_, "rb"); + if (bmp) + { + fread(&header, sizeof(header), 1, bmp); + fclose(bmp); + } + + FILE *saved = File::OpenCFile("__testfailure.bmp", "wb"); + if (saved) + { + fwrite(&header, sizeof(header), 1, saved); + fwrite(pixels.data(), sizeof(u32), FRAME_STRIDE * FRAME_HEIGHT, saved); + fclose(saved); + + SendOrCollectDebugOutput("Actual output written to: __testfailure.bmp\n"); + } + } +} diff --git a/headless/StubHost.h b/headless/StubHost.h index 0a4be899c5..d6498e2b0f 100644 --- a/headless/StubHost.h +++ b/headless/StubHost.h @@ -64,13 +64,21 @@ public: debugOutputBuffer_.clear(); } } - virtual void SetComparisonScreenshot(const std::string &filename) {} + virtual void SetComparisonScreenshot(const std::string &filename) { + comparisonScreenshot_ = filename; + } + + void SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h) override; // Unique for HeadlessHost virtual void SwapBuffers() {} protected: + void SendOrCollectDebugOutput(const std::string &output); + + std::string comparisonScreenshot_; std::string debugOutputBuffer_; GPUCore gpuCore_; + GraphicsContext *gfx_ = nullptr; }; diff --git a/headless/WindowsHeadlessHost.cpp b/headless/WindowsHeadlessHost.cpp index 4ad37bd219..490ae92e8e 100644 --- a/headless/WindowsHeadlessHost.cpp +++ b/headless/WindowsHeadlessHost.cpp @@ -17,8 +17,7 @@ #include -#include "WindowsHeadlessHost.h" -#include "Compare.h" +#include "headless/WindowsHeadlessHost.h" #include "Common/FileUtil.h" #include "Common/CommonWindows.h" @@ -78,72 +77,6 @@ void WindowsHeadlessHost::SendDebugOutput(const std::string &output) OutputDebugStringUTF8(output.c_str()); } -void WindowsHeadlessHost::SendOrCollectDebugOutput(const std::string &data) -{ - if (PSP_CoreParameter().printfEmuLog) - SendDebugOutput(data); - else if (PSP_CoreParameter().collectEmuLog) - *PSP_CoreParameter().collectEmuLog += data; - else - DEBUG_LOG(COMMON, "%s", data.c_str()); -} - -void WindowsHeadlessHost::SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h) -{ - // Only if we're actually comparing. - if (comparisonScreenshot.empty()) { - return; - } - - // We ignore the current framebuffer parameters and just grab the full screen. - const static u32 FRAME_STRIDE = 512; - const static u32 FRAME_WIDTH = 480; - const static u32 FRAME_HEIGHT = 272; - - GPUDebugBuffer buffer; - gpuDebug->GetCurrentFramebuffer(buffer, GPU_DBG_FRAMEBUF_RENDER); - const std::vector pixels = TranslateDebugBufferToCompare(&buffer, 512, 272); - - std::string error; - double errors = CompareScreenshot(pixels, FRAME_STRIDE, FRAME_WIDTH, FRAME_HEIGHT, comparisonScreenshot, error); - if (errors < 0) - SendOrCollectDebugOutput(error); - - if (errors > 0) - { - char temp[256]; - sprintf_s(temp, "Screenshot error: %f%%\n", errors * 100.0f); - SendOrCollectDebugOutput(temp); - } - - if (errors > 0 && !teamCityMode) - { - // Lazy, just read in the original header to output the failed screenshot. - u8 header[14 + 40] = {0}; - FILE *bmp = File::OpenCFile(comparisonScreenshot, "rb"); - if (bmp) - { - fread(&header, sizeof(header), 1, bmp); - fclose(bmp); - } - - FILE *saved = File::OpenCFile("__testfailure.bmp", "wb"); - if (saved) - { - fwrite(&header, sizeof(header), 1, saved); - fwrite(pixels.data(), sizeof(u32), FRAME_STRIDE * FRAME_HEIGHT, saved); - fclose(saved); - - SendOrCollectDebugOutput("Actual output written to: __testfailure.bmp\n"); - } - } -} - -void WindowsHeadlessHost::SetComparisonScreenshot(const std::string &filename) -{ - comparisonScreenshot = filename; -} - bool WindowsHeadlessHost::InitGraphics(std::string *error_message, GraphicsContext **ctx) { hWnd = CreateHiddenWindow(); diff --git a/headless/WindowsHeadlessHost.h b/headless/WindowsHeadlessHost.h index 088e7935da..8a361ef41f 100644 --- a/headless/WindowsHeadlessHost.h +++ b/headless/WindowsHeadlessHost.h @@ -17,7 +17,7 @@ #pragma once -#include "StubHost.h" +#include "headless/StubHost.h" #undef HEADLESSHOST_CLASS #define HEADLESSHOST_CLASS WindowsHeadlessHost @@ -28,22 +28,18 @@ class WindowsHeadlessHost : public HeadlessHost { public: - virtual bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override; - virtual void ShutdownGraphics() override; + bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override; + void ShutdownGraphics() override; - virtual void SwapBuffers() override; + void SwapBuffers() override; - virtual void SendDebugOutput(const std::string &output) override; - virtual void SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h) override; - virtual void SetComparisonScreenshot(const std::string &filename) override; + void SendDebugOutput(const std::string &output) override; protected: void LoadNativeAssets(); - void SendOrCollectDebugOutput(const std::string &output); HWND hWnd; HDC hDC; HGLRC hRC; GraphicsContext *gfx_; - std::string comparisonScreenshot; -}; \ No newline at end of file +}; From 40f663664b71c3b74dde769e8a49ac7d3984387f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 20 Sep 2017 10:49:32 -0700 Subject: [PATCH 04/23] Headless: Oops, call SDL_Init(). --- headless/SDLHeadlessHost.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/headless/SDLHeadlessHost.cpp b/headless/SDLHeadlessHost.cpp index 42ad38c949..8e0e1ab082 100644 --- a/headless/SDLHeadlessHost.cpp +++ b/headless/SDLHeadlessHost.cpp @@ -72,6 +72,8 @@ void SDLHeadlessHost::LoadNativeAssets() { } bool SDLHeadlessHost::InitGraphics(std::string *error_message, GraphicsContext **ctx) { + SDL_Init(SDL_INIT_VIDEO); + // TODO //SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); From e754cca28872e0d0a564b8ee9cfbf505ee85e6e0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 20 Sep 2017 12:22:01 -0700 Subject: [PATCH 05/23] GLES: Add OpenGL 3.x core profile support. Need to define #version everywhere and avoid varying/etc. --- GPU/GLES/FramebufferManagerGLES.cpp | 15 ++++++++++++- GPU/GLES/StencilBufferGLES.cpp | 33 +++++++++++++++++------------ ext/native/gfx_es2/gpu_features.cpp | 28 ++++++++++++++++++++++++ ext/native/gfx_es2/gpu_features.h | 3 +++ ext/native/thin3d/thin3d.cpp | 21 +++++++++++++++++- ext/native/thin3d/thin3d_gl.cpp | 15 ++++++------- 6 files changed, 92 insertions(+), 23 deletions(-) diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 6fad8a9ee9..e51aad78a6 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -49,6 +49,12 @@ // #define DEBUG_READ_PIXELS 1 static const char tex_fs[] = + "#if __VERSION__ >= 130\n" + "#define varying in\n" + "#define texture2D texture\n" + "#define gl_FragColor fragColor0\n" + "out vec4 fragColor0;\n" + "#endif\n" #ifdef USING_GLES2 "precision mediump float;\n" #endif @@ -59,6 +65,10 @@ static const char tex_fs[] = "}\n"; static const char basic_vs[] = + "#if __VERSION__ >= 130\n" + "#define attribute in\n" + "#define varying out\n" + "#endif\n" "attribute vec4 a_position;\n" "attribute vec2 a_texcoord0;\n" "varying vec2 v_texcoord0;\n" @@ -87,7 +97,10 @@ void FramebufferManagerGLES::DisableState() { void FramebufferManagerGLES::CompileDraw2DProgram() { if (!draw2dprogram_) { std::string errorString; - draw2dprogram_ = glsl_create_source(basic_vs, tex_fs, &errorString); + static std::string vs_code, fs_code; + vs_code = ApplyGLSLPrelude(basic_vs, GL_VERTEX_SHADER); + fs_code = ApplyGLSLPrelude(tex_fs, GL_FRAGMENT_SHADER); + draw2dprogram_ = glsl_create_source(vs_code.c_str(), fs_code.c_str(), &errorString); if (!draw2dprogram_) { ERROR_LOG_REPORT(G3D, "Failed to compile draw2dprogram! This shouldn't happen.\n%s", errorString.c_str()); } else { diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index c431a51757..d570214917 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -22,11 +22,16 @@ #include "GPU/GLES/ShaderManagerGLES.h" #include "GPU/GLES/TextureCacheGLES.h" -static const char *gles_prefix = -"#version 100\n" -"precision highp float;\n"; - static const char *stencil_fs = +"#ifdef GL_ES\n" +"precision highp float;\n" +"#endif\n" +"#if __VERSION__ >= 130\n" +"#define varying in\n" +"#define texture2D texture\n" +"#define gl_FragColor fragColor0\n" +"out vec4 fragColor0;\n" +"#endif\n" "varying vec2 v_texcoord0;\n" "uniform float u_stencilValue;\n" "uniform sampler2D tex;\n" @@ -39,6 +44,13 @@ static const char *stencil_fs = "}\n"; static const char *stencil_vs = +"#ifdef GL_ES\n" +"precision highp float;\n" +"#endif\n" +"#if __VERSION__ >= 130\n" +"#define attribute in\n" +"#define varying out\n" +"#endif\n" "attribute vec4 a_position;\n" "attribute vec2 a_texcoord0;\n" "varying vec2 v_texcoord0;\n" @@ -47,14 +59,6 @@ static const char *stencil_vs = " gl_Position = a_position;\n" "}\n"; -std::string GLSLES100PrefixProgram(std::string code) { - if (gl_extensions.IsGLES) { - return std::string(gles_prefix) + code; - } else { - return code; - } -} - static u8 StencilBits5551(const u8 *ptr8, u32 numPixels) { const u32 *ptr = (const u32 *)ptr8; @@ -152,7 +156,10 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe if (!stencilUploadProgram_) { std::string errorString; - stencilUploadProgram_ = glsl_create_source(GLSLES100PrefixProgram(stencil_vs).c_str(), GLSLES100PrefixProgram(stencil_fs).c_str(), &errorString); + static std::string vs_code, fs_code; + vs_code = ApplyGLSLPrelude(stencil_vs, GL_VERTEX_SHADER); + fs_code = ApplyGLSLPrelude(stencil_fs, GL_FRAGMENT_SHADER); + stencilUploadProgram_ = glsl_create_source(vs_code.c_str(), fs_code.c_str(), &errorString); if (!stencilUploadProgram_) { ERROR_LOG_REPORT(G3D, "Failed to compile stencilUploadProgram! This shouldn't happen.\n%s", errorString.c_str()); } else { diff --git a/ext/native/gfx_es2/gpu_features.cpp b/ext/native/gfx_es2/gpu_features.cpp index a97a0f39f4..a3ef8af9ac 100644 --- a/ext/native/gfx_es2/gpu_features.cpp +++ b/ext/native/gfx_es2/gpu_features.cpp @@ -444,3 +444,31 @@ void SetGLCoreContext(bool flag) { // For convenience, it'll get reset later. gl_extensions.IsCoreContext = useCoreContext; } + +static const char *glsl_fragment_prelude = +"#ifdef GL_ES\n" +"precision mediump float;\n" +"#endif\n"; + +std::string ApplyGLSLPrelude(const std::string &source, uint32_t stage) { + std::string temp; + std::string version = ""; + if (!gl_extensions.IsGLES && gl_extensions.IsCoreContext) { + // We need to add a corresponding #version. Apple drives fail without an exact match. + if (gl_extensions.VersionGEThan(3, 3)) { + version = StringFromFormat("#version %d%d0\n", gl_extensions.ver[0], gl_extensions.ver[1]); + } else if (gl_extensions.VersionGEThan(3, 2)) { + version = "#version 150\n"; + } else if (gl_extensions.VersionGEThan(3, 1)) { + version = "#version 140\n"; + } else { + version = "#version 130\n"; + } + } + if (stage == GL_FRAGMENT_SHADER) { + temp = version + glsl_fragment_prelude + source; + } else if (stage == GL_VERTEX_SHADER) { + temp = version + source; + } + return temp; +} diff --git a/ext/native/gfx_es2/gpu_features.h b/ext/native/gfx_es2/gpu_features.h index d8ea0de803..3bc237c3f0 100644 --- a/ext/native/gfx_es2/gpu_features.h +++ b/ext/native/gfx_es2/gpu_features.h @@ -4,6 +4,7 @@ #pragma once +#include #include "base/NativeApp.h" enum { @@ -110,3 +111,5 @@ extern std::string g_all_egl_extensions; void CheckGLExtensions(); void SetGLCoreContext(bool flag); + +std::string ApplyGLSLPrelude(const std::string &source, uint32_t stage); diff --git a/ext/native/thin3d/thin3d.cpp b/ext/native/thin3d/thin3d.cpp index b04626760e..46ddbf3c53 100644 --- a/ext/native/thin3d/thin3d.cpp +++ b/ext/native/thin3d/thin3d.cpp @@ -69,6 +69,12 @@ static const std::vector fsTexCol = { "#ifdef GL_ES\n" "precision lowp float;\n" "#endif\n" + "#if __VERSION__ >= 130\n" + "#define varying in\n" + "#define texture2D texture\n" + "#define gl_FragColor fragColor0\n" + "out vec4 fragColor0;\n" + "#endif\n" "varying vec4 oColor0;\n" "varying vec2 oTexCoord0;\n" "uniform sampler2D Sampler0;\n" @@ -107,6 +113,11 @@ static const std::vector fsCol = { "#ifdef GL_ES\n" "precision lowp float;\n" "#endif\n" + "#if __VERSION__ >= 130\n" + "#define varying in\n" + "#define gl_FragColor fragColor0\n" + "out vec4 fragColor0;\n" + "#endif\n" "varying vec4 oColor0;\n" "void main() { gl_FragColor = oColor0; }\n" }, @@ -136,6 +147,10 @@ static const std::vector fsCol = { static const std::vector vsCol = { { ShaderLanguage::GLSL_ES_200, + "#if __VERSION__ >= 130\n" + "#define attribute in\n" + "#define varying out\n" + "#endif\n" "attribute vec3 Position;\n" "attribute vec4 Color0;\n" "varying vec4 oColor0;\n" @@ -193,6 +208,10 @@ const UniformBufferDesc vsColBufDesc { sizeof(VsColUB), { static const std::vector vsTexCol = { { ShaderLanguage::GLSL_ES_200, + "#if __VERSION__ >= 130\n" + "#define attribute in\n" + "#define varying out\n" + "#endif\n" "attribute vec3 Position;\n" "attribute vec4 Color0;\n" "attribute vec2 TexCoord0;\n" @@ -285,4 +304,4 @@ DrawContext::~DrawContext() { } } -} // namespace Draw \ No newline at end of file +} // namespace Draw diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 2d4e6d968d..440fffe5a8 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -163,11 +163,6 @@ static const unsigned short primToGL[] = { class OpenGLBuffer; -static const char *glsl_fragment_prelude = -"#ifdef GL_ES\n" -"precision mediump float;\n" -"#endif\n"; - class OpenGLBlendState : public BlendState { public: bool enabled; @@ -332,9 +327,9 @@ bool OpenGLShaderModule::Compile(ShaderLanguage language, const uint8_t *data, s language_ = language; std::string temp; - // Add the prelude on automatically for fragment shaders. - if (glstage_ == GL_FRAGMENT_SHADER) { - temp = std::string(glsl_fragment_prelude) + source_; + // Add the prelude on automatically. + if (glstage_ == GL_FRAGMENT_SHADER || glstage_ == GL_VERTEX_SHADER) { + temp = ApplyGLSLPrelude(source_, glstage_); source_ = temp.c_str(); } @@ -1047,6 +1042,10 @@ bool OpenGLPipeline::LinkShaders() { glBindAttribLocation(program_, SEM_NORMAL, "Normal"); glBindAttribLocation(program_, SEM_TANGENT, "Tangent"); glBindAttribLocation(program_, SEM_BINORMAL, "Binormal"); + + if (gl_extensions.VersionGEThan(3, 3, 0)) { + glBindFragDataLocation(program_, 0, "fragColor0"); + } glLinkProgram(program_); GLint linkStatus = GL_FALSE; From 1802d7a45ea192cc2477d6637a6e13bc85352f9d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 20 Sep 2017 12:23:11 -0700 Subject: [PATCH 06/23] GLSL: Set extension flags for elided core exts. So that we know we have them, i.e. on Apple. --- ext/native/gfx_es2/gpu_features.cpp | 43 ++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/ext/native/gfx_es2/gpu_features.cpp b/ext/native/gfx_es2/gpu_features.cpp index a3ef8af9ac..aa96d648ca 100644 --- a/ext/native/gfx_es2/gpu_features.cpp +++ b/ext/native/gfx_es2/gpu_features.cpp @@ -394,7 +394,7 @@ void CheckGLExtensions() { #endif // This is probably a waste of time, implementations lie. - if (gl_extensions.IsGLES || strstr(extString, "GL_ARB_ES2_compatibility")) { + if (gl_extensions.IsGLES || strstr(extString, "GL_ARB_ES2_compatibility") || gl_extensions.VersionGEThan(4, 1)) { const GLint precisions[6] = { GL_LOW_FLOAT, GL_MEDIUM_FLOAT, GL_HIGH_FLOAT, GL_LOW_INT, GL_MEDIUM_INT, GL_HIGH_INT @@ -419,6 +419,47 @@ void CheckGLExtensions() { gl_extensions.ARB_vertex_array_object = true; gl_extensions.ARB_framebuffer_object = true; } + + // Add any extensions that are included in core. May be elided. + if (!gl_extensions.IsGLES) { + if (gl_extensions.VersionGEThan(3, 0)) { + gl_extensions.ARB_texture_float = true; + } + if (gl_extensions.VersionGEThan(3, 1)) { + gl_extensions.ARB_draw_instanced = true; + // ARB_uniform_buffer_object = true; + } + if (gl_extensions.VersionGEThan(3, 2)) { + // ARB_depth_clamp = true; + } + if (gl_extensions.VersionGEThan(3, 3)) { + gl_extensions.ARB_blend_func_extended = true; + // ARB_explicit_attrib_location = true; + } + if (gl_extensions.VersionGEThan(4, 0)) { + // ARB_gpu_shader5 = true; + } + if (gl_extensions.VersionGEThan(4, 1)) { + // ARB_get_program_binary = true; + // ARB_separate_shader_objects = true; + // ARB_shader_precision = true; + // ARB_viewport_array = true; + } + if (gl_extensions.VersionGEThan(4, 2)) { + // ARB_texture_storage = true; + } + if (gl_extensions.VersionGEThan(4, 3)) { + gl_extensions.ARB_copy_image = true; + // ARB_explicit_uniform_location = true; + // ARB_stencil_texturing = true; + // ARB_texture_view = true; + // ARB_vertex_attrib_binding = true; + } + if (gl_extensions.VersionGEThan(4, 4)) { + // ARB_buffer_storage = true; + } + } + #ifdef __APPLE__ if (!gl_extensions.IsGLES && !gl_extensions.IsCoreContext) { // Apple doesn't allow OpenGL 3.x+ in compatibility contexts. From bd63fdd8eda00dc23cda8c52ea84072542e1ec0a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 20 Sep 2017 19:38:24 -0700 Subject: [PATCH 07/23] GLES: Android buildfix. Shouldn't need this, actually. --- ext/native/thin3d/thin3d_gl.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 440fffe5a8..12c6b0d6b2 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -1042,10 +1042,6 @@ bool OpenGLPipeline::LinkShaders() { glBindAttribLocation(program_, SEM_NORMAL, "Normal"); glBindAttribLocation(program_, SEM_TANGENT, "Tangent"); glBindAttribLocation(program_, SEM_BINORMAL, "Binormal"); - - if (gl_extensions.VersionGEThan(3, 3, 0)) { - glBindFragDataLocation(program_, 0, "fragColor0"); - } glLinkProgram(program_); GLint linkStatus = GL_FALSE; From 5784b5142807551abaaf5d1220d7d27032c41234 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 21 Sep 2017 20:20:17 -0700 Subject: [PATCH 08/23] GLES: Allow hwtess for GL 3.1 w/o shader4. gl_InstanceID was added to core in 3.1, so we don't need gpu_shader4. --- GPU/GLES/GPU_GLES.cpp | 2 +- UI/GameSettingsScreen.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 6a514a7b6a..a36450a494 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -299,7 +299,7 @@ void GPU_GLES::CheckGPUFeatures() { features |= GPU_SUPPORTS_ANISOTROPY; bool canUseInstanceID = gl_extensions.EXT_draw_instanced || gl_extensions.ARB_draw_instanced; - bool canDefInstanceID = gl_extensions.IsGLES || gl_extensions.EXT_gpu_shader4; + bool canDefInstanceID = gl_extensions.IsGLES || gl_extensions.EXT_gpu_shader4 || gl_extensions.VersionGEThan(3, 1); bool instanceRendering = gl_extensions.GLES3 || (canUseInstanceID && canDefInstanceID); features |= GPU_SUPPORTS_INSTANCE_RENDERING; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index c8754c61a5..d30aebb853 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -94,7 +94,7 @@ bool CheckSupportInstancedTessellationGLES() { bool vertexTexture = maxVertexTextureImageUnits >= 3; // At least 3 for hardware tessellation bool canUseInstanceID = gl_extensions.EXT_draw_instanced || gl_extensions.ARB_draw_instanced; - bool canDefInstanceID = gl_extensions.IsGLES || gl_extensions.EXT_gpu_shader4; + bool canDefInstanceID = gl_extensions.IsGLES || gl_extensions.EXT_gpu_shader4 || gl_extensions.VersionGEThan(3, 1); bool instanceRendering = gl_extensions.GLES3 || (canUseInstanceID && canDefInstanceID); bool textureFloat = gl_extensions.ARB_texture_float || gl_extensions.OES_texture_float; From 5686939e2cadfdc642baad8d8f6239f3b352ead1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 23 Sep 2017 21:27:17 +0900 Subject: [PATCH 09/23] Update lang submodule --- assets/lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/lang b/assets/lang index 7b31a30fd0..c31a1d3096 160000 --- a/assets/lang +++ b/assets/lang @@ -1 +1 @@ -Subproject commit 7b31a30fd0bbe23b683396e3a8709a8618524341 +Subproject commit c31a1d309631acbe0f2d583f390f163e18befe5d From d96232be7227981e33e9637f7269b5e74160863b Mon Sep 17 00:00:00 2001 From: LunaMoo Date: Sat, 23 Sep 2017 15:37:10 +0200 Subject: [PATCH 10/23] Finish making extra psp keys mappable. --- Common/KeyMap.h | 44 ++++++++++++++++++++++---------------------- Core/HLE/sceCtrl.h | 2 +- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Common/KeyMap.h b/Common/KeyMap.h index 334b5a53f9..369b12fc89 100644 --- a/Common/KeyMap.h +++ b/Common/KeyMap.h @@ -29,28 +29,28 @@ #define KEYMAP_ERROR_UNKNOWN_KEY 0 enum { - VIRTKEY_FIRST = 0x10000, - VIRTKEY_AXIS_X_MIN = 0x10000, - VIRTKEY_AXIS_Y_MIN = 0x10001, - VIRTKEY_AXIS_X_MAX = 0x10002, - VIRTKEY_AXIS_Y_MAX = 0x10003, - VIRTKEY_RAPID_FIRE = 0x10004, - VIRTKEY_UNTHROTTLE = 0x10005, - VIRTKEY_PAUSE = 0x10006, - VIRTKEY_SPEED_TOGGLE = 0x10007, - VIRTKEY_AXIS_RIGHT_X_MIN = 0x10008, - VIRTKEY_AXIS_RIGHT_Y_MIN = 0x10009, - VIRTKEY_AXIS_RIGHT_X_MAX = 0x1000a, - VIRTKEY_AXIS_RIGHT_Y_MAX = 0x1000b, - VIRTKEY_REWIND = 0x1000c, - VIRTKEY_SAVE_STATE = 0x1000d, - VIRTKEY_LOAD_STATE = 0x1000e, - VIRTKEY_NEXT_SLOT = 0x1000f, - VIRTKEY_TOGGLE_FULLSCREEN = 0x10010, - VIRTKEY_ANALOG_LIGHTLY = 0x10011, - VIRTKEY_AXIS_SWAP = 0x10012, - VIRTKEY_DEVMENU = 0x10013, - VIRTKEY_FRAME_ADVANCE = 0x10014, + VIRTKEY_FIRST = 0x40000001, + VIRTKEY_AXIS_X_MIN = 0x40000001, + VIRTKEY_AXIS_Y_MIN = 0x40000002, + VIRTKEY_AXIS_X_MAX = 0x40000003, + VIRTKEY_AXIS_Y_MAX = 0x40000004, + VIRTKEY_RAPID_FIRE = 0x40000005, + VIRTKEY_UNTHROTTLE = 0x40000006, + VIRTKEY_PAUSE = 0x40000007, + VIRTKEY_SPEED_TOGGLE = 0x40000008, + VIRTKEY_AXIS_RIGHT_X_MIN = 0x40000009, + VIRTKEY_AXIS_RIGHT_Y_MIN = 0x4000000a, + VIRTKEY_AXIS_RIGHT_X_MAX = 0x4000000b, + VIRTKEY_AXIS_RIGHT_Y_MAX = 0x4000000c, + VIRTKEY_REWIND = 0x4000000d, + VIRTKEY_SAVE_STATE = 0x4000000e, + VIRTKEY_LOAD_STATE = 0x4000000f, + VIRTKEY_NEXT_SLOT = 0x40000010, + VIRTKEY_TOGGLE_FULLSCREEN = 0x40000011, + VIRTKEY_ANALOG_LIGHTLY = 0x40000012, + VIRTKEY_AXIS_SWAP = 0x40000013, + VIRTKEY_DEVMENU = 0x40000014, + VIRTKEY_FRAME_ADVANCE = 0x40000015, VIRTKEY_LAST, VIRTKEY_COUNT = VIRTKEY_LAST - VIRTKEY_FIRST }; diff --git a/Core/HLE/sceCtrl.h b/Core/HLE/sceCtrl.h index 524240ebf6..12e5969643 100644 --- a/Core/HLE/sceCtrl.h +++ b/Core/HLE/sceCtrl.h @@ -58,7 +58,7 @@ const int CTRL_STICK_RIGHT = 1; #define CTRL_MASK_DPAD (CTRL_UP | CTRL_DOWN | CTRL_LEFT | CTRL_RIGHT) #define CTRL_MASK_ACTION (CTRL_SQUARE | CTRL_TRIANGLE | CTRL_CIRCLE | CTRL_CROSS) #define CTRL_MASK_TRIGGER (CTRL_LTRIGGER | CTRL_RTRIGGER) -#define CTRL_MASK_USER (CTRL_MASK_DPAD | CTRL_MASK_ACTION | CTRL_START | CTRL_SELECT | CTRL_MASK_TRIGGER | CTRL_HOME | CTRL_HOLD) +#define CTRL_MASK_USER (CTRL_MASK_DPAD | CTRL_MASK_ACTION | CTRL_START | CTRL_SELECT | CTRL_MASK_TRIGGER | CTRL_HOME | CTRL_HOLD | CTRL_WLAN | CTRL_REMOTE_HOLD | CTRL_VOL_UP | CTRL_VOL_DOWN | CTRL_SCREEN | CTRL_NOTE) void __CtrlInit(); void __CtrlDoState(PointerWrap &p); From 271a3bb7d3d3ccd9ad847b492bcfdc2980b8ce74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 27 Sep 2017 10:29:36 +0200 Subject: [PATCH 11/23] Fix the build on the buildbot by avoiding fancy new Java features. Fixes #9979 --- .../src/org/ppsspp/ppsspp/NativeActivity.java | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index 0894885dd2..39adc3b0b2 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -1200,26 +1200,20 @@ public abstract class NativeActivity extends Activity implements SurfaceHolder.C NativeApp.sendMessage("permission_granted", "storage"); } } else if (command.equals("gps_command")) { - switch (params) { - case "open": - if(!askForPermissions(permissionsForLocation, REQUEST_CODE_LOCATION_PERMISSION)) { - mLocationHelper.startLocationUpdates(); - } - break; - case "close": - mLocationHelper.stopLocationUpdates(); - break; + if (params.equals("open")) { + if (!askForPermissions(permissionsForLocation, REQUEST_CODE_LOCATION_PERMISSION)) { + mLocationHelper.startLocationUpdates(); + } + } else if (params.equals("close")) { + mLocationHelper.stopLocationUpdates(); } } else if (command.equals("camera_command")) { - switch (params) { - case "startVideo": - if(!askForPermissions(permissionsForCamera, REQUEST_CODE_CAMERA_PERMISSION)) { - mCameraHelper.startCamera(); - } - break; - case "stopVideo": - mCameraHelper.stopCamera(); - break; + if (params.equals("startVideo")) { + if (!askForPermissions(permissionsForCamera, REQUEST_CODE_CAMERA_PERMISSION)) { + mCameraHelper.startCamera(); + } + } else if (params.equals("stopVideo")) { + mCameraHelper.stopCamera(); } } return false; From 9b9f382b0b0e8513aaaa7300fd9736723143596f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 27 Sep 2017 13:25:48 +0200 Subject: [PATCH 12/23] Don't default to coldbird adhoc server, it doesn't run anymore (?) --- Core/Config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 4f1ffa9850..e71562640a 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -738,7 +738,7 @@ static ConfigSetting systemParamSettings[] = { ReportedConfigSetting("PSPModel", &g_Config.iPSPModel, &DefaultPSPModel, true, true), ReportedConfigSetting("PSPFirmwareVersion", &g_Config.iFirmwareVersion, PSP_DEFAULT_FIRMWARE, true, true), ConfigSetting("NickName", &g_Config.sNickName, "PPSSPP", true, true), - ConfigSetting("proAdhocServer", &g_Config.proAdhocServer, "coldbird.net", true, true), + ConfigSetting("proAdhocServer", &g_Config.proAdhocServer, "", true, true), ConfigSetting("MacAddress", &g_Config.sMACAddress, "", true, true), ConfigSetting("PortOffset", &g_Config.iPortOffset, 0, true, true), ReportedConfigSetting("Language", &g_Config.iLanguage, &DefaultSystemParamLanguage, true, true), From ebaa8051a40eed146d01d1cbabeb248a1274761e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 28 Sep 2017 19:33:07 +0200 Subject: [PATCH 13/23] Remove unnecessary ifdef. Thanks Bracket-. See #9548 comments. --- ext/native/base/PCMain.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/ext/native/base/PCMain.cpp b/ext/native/base/PCMain.cpp index 362b5ff7e1..27926428bc 100644 --- a/ext/native/base/PCMain.cpp +++ b/ext/native/base/PCMain.cpp @@ -711,7 +711,6 @@ int main(int argc, char *argv[]) { dp_yres = (float)pixel_yres * dpi_scale; NativeResized(); -#if defined(PPSSPP) // Set variable here in case fullscreen was toggled by hotkey g_Config.bFullScreen = fullscreen; @@ -721,7 +720,6 @@ int main(int argc, char *argv[]) { } else if (lastUIState != UISTATE_INGAME || !fullscreen) { SDL_ShowCursor(SDL_ENABLE); } - #endif break; } From 4de75235ff0fc2c3e031672630c6b876e8795600 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 28 Sep 2017 20:27:31 +0200 Subject: [PATCH 14/23] Oops, forgot this one. --- ext/native/base/PCMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/native/base/PCMain.cpp b/ext/native/base/PCMain.cpp index 27926428bc..6a252325d7 100644 --- a/ext/native/base/PCMain.cpp +++ b/ext/native/base/PCMain.cpp @@ -858,7 +858,7 @@ int main(int argc, char *argv[]) { UpdateRunLoop(); if (g_QuitRequested) break; -#if defined(PPSSPP) && !defined(MOBILE_DEVICE) +#if !defined(MOBILE_DEVICE) if (lastUIState != GetUIState()) { lastUIState = GetUIState(); if (lastUIState == UISTATE_INGAME && g_Config.bFullScreen && !g_Config.bShowTouchControls) From 1b6c5c4832d562ca5de2e830fbe6cbfa5ceae558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 29 Sep 2017 20:51:59 +0200 Subject: [PATCH 15/23] Fix typo causing Y axis in joystick tester not to be mirrored correctly if backwards. Should fix #9300 --- UI/ControlMappingScreen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index 50023fcab1..509efee5bc 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -438,7 +438,7 @@ public: JoystickHistoryView(int xAxis, int xDevice, int xDir, int yAxis, int yDevice, int yDir, UI::LayoutParams *layoutParams = nullptr) : UI::InertView(layoutParams), xAxis_(xAxis), xDevice_(xDevice), xDir_(xDir), - yAxis_(yAxis), yDevice_(yDevice), yDir_(xDir), + yAxis_(yAxis), yDevice_(yDevice), yDir_(yDir), curX_(0.0f), curY_(0.0f), maxCount_(500) {} void Draw(UIContext &dc) override; From c9dc36a418bdba3f4fe7e2753be96b409ca11b46 Mon Sep 17 00:00:00 2001 From: orbea Date: Fri, 29 Sep 2017 17:33:06 -0700 Subject: [PATCH 16/23] Add Horipad One config. --- assets/gamecontrollerdb.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/gamecontrollerdb.txt b/assets/gamecontrollerdb.txt index e50c1485bc..84e589cd0d 100644 --- a/assets/gamecontrollerdb.txt +++ b/assets/gamecontrollerdb.txt @@ -155,6 +155,7 @@ bd1200000000000015d0000000000000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,b 05000000102800000900000000010000,8Bitdo SFC30 GamePad,platform:Linux,x:b4,a:b1,b:b0,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1, 03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,leftx:a0,lefty:a1, 030000000d0f00000d00000000010000,hori,platform:Linux,a:b0,b:b6,y:b2,x:b1,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,start:b9,guide:b10,back:b8,leftshoulder:b3,rightshoulder:b7,leftx:b4,lefty:b5, +030000000d0f00006700000001010000,HORIPAD ONE,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2, 03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5, 03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,platform:Linux,a:b0,b:b1,y:b2,x:b3,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7, 03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),platform:Linux,a:b3,b:b4,y:b1,x:b0,start:b7,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5, From fef709bd344fb0de6f43ed28fae8a6eb2da97318 Mon Sep 17 00:00:00 2001 From: Bracket- Date: Sun, 1 Oct 2017 16:29:57 -0400 Subject: [PATCH 17/23] gamecontrollerdb.txt: Add 8Bitdo NES30 Pro mappings for Linux --- assets/gamecontrollerdb.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/assets/gamecontrollerdb.txt b/assets/gamecontrollerdb.txt index 84e589cd0d..d0be78b895 100644 --- a/assets/gamecontrollerdb.txt +++ b/assets/gamecontrollerdb.txt @@ -182,3 +182,5 @@ bd1200000000000015d0000000000000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,b 050000004c050000cc09000000810000,Wireless Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4, 030000004c0500006802000011810000,Sony PLAYSTATION(R)3 Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4, 050000004c0500006802000000810000,PLAYSTATION(R)3 Controller,platform:Linux,x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4, +03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5, +05000000c82d00002038000000010000,8Bitdo NES30 Pro,platform:Linux,a:b1,b:b0,x:b4,y:b3,back:b10,guide:b2,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4, From 6ab39ba47529a241540ad92b9926da4a0fb75e52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 1 Oct 2017 22:59:21 +0200 Subject: [PATCH 18/23] Reorder SDL init a bit, allowing us to read the fullscreen option early enough to fix #9086 --- ext/native/base/PCMain.cpp | 55 +++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/ext/native/base/PCMain.cpp b/ext/native/base/PCMain.cpp index 6a252325d7..dc734a5048 100644 --- a/ext/native/base/PCMain.cpp +++ b/ext/native/base/PCMain.cpp @@ -558,10 +558,40 @@ int main(int argc, char *argv[]) { dp_xres = (float)pixel_xres * dpi_scale; dp_yres = (float)pixel_yres * dpi_scale; +#ifdef _MSC_VER + // VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\")); + TCHAR path[MAX_PATH]; + SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path); + PathAppend(path, (app_name + "\\").c_str()); +#else + // Mac / Linux + char path[2048]; + const char *the_path = getenv("HOME"); + if (!the_path) { + struct passwd* pwd = getpwuid(getuid()); + if (pwd) + the_path = pwd->pw_dir; + } + strcpy(path, the_path); + if (path[strlen(path)-1] != '/') + strcat(path, "/"); +#endif + +#ifdef _WIN32 + NativeInit(remain_argc, (const char **)remain_argv, path, "D:\\", nullptr); +#else + NativeInit(remain_argc, (const char **)remain_argv, path, "/tmp", nullptr); +#endif + + // Use the setting from the config when initing the window. + if (g_Config.bFullScreen) + mode |= SDL_WINDOW_FULLSCREEN_DESKTOP; + g_Screen = SDL_CreateWindow(app_name_nice.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(getDisplayNumber()),\ SDL_WINDOWPOS_UNDEFINED, pixel_xres, pixel_yres, mode); if (g_Screen == NULL) { + NativeShutdown(); fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError()); SDL_Quit(); return 2; @@ -569,6 +599,7 @@ int main(int argc, char *argv[]) { SDL_GLContext glContext = SDL_GL_CreateContext(g_Screen); if (glContext == NULL) { + NativeShutdown(); fprintf(stderr, "SDL_GL_CreateContext failed: %s\n", SDL_GetError()); SDL_Quit(); return 2; @@ -606,30 +637,6 @@ int main(int argc, char *argv[]) { } #endif -#ifdef _MSC_VER - // VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\")); - TCHAR path[MAX_PATH]; - SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path); - PathAppend(path, (app_name + "\\").c_str()); -#else - // Mac / Linux - char path[2048]; - const char *the_path = getenv("HOME"); - if (!the_path) { - struct passwd* pwd = getpwuid(getuid()); - if (pwd) - the_path = pwd->pw_dir; - } - strcpy(path, the_path); - if (path[strlen(path)-1] != '/') - strcat(path, "/"); -#endif - -#ifdef _WIN32 - NativeInit(remain_argc, (const char **)remain_argv, path, "D:\\", nullptr); -#else - NativeInit(remain_argc, (const char **)remain_argv, path, "/tmp", nullptr); -#endif pixel_in_dps_x = (float)pixel_xres / dp_xres; pixel_in_dps_y = (float)pixel_yres / dp_yres; From 356b25e3cea0124519e15a8bbf164d0bc3b52ded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 2 Oct 2017 14:08:35 +0200 Subject: [PATCH 19/23] Vulkan: If there are no GPUs available, fail properly instead of asserting. Seen on an obscure x86-64 android device when running 32-bit binaries --- Common/Vulkan/VulkanContext.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Common/Vulkan/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp index b1a0064045..248ec0b643 100644 --- a/Common/Vulkan/VulkanContext.cpp +++ b/Common/Vulkan/VulkanContext.cpp @@ -123,11 +123,20 @@ VkResult VulkanContext::CreateInstance(const char *app_name, int app_ver, uint32 uint32_t gpu_count = 1; res = vkEnumeratePhysicalDevices(instance_, &gpu_count, nullptr); + if (gpu_count <= 0) { + ELOG("Vulkan driver found but no supported GPU is available"); + init_error_ = "No Vulkan physical devices found"; + vkDestroyInstance(instance_, nullptr); + instance_ = nullptr; + return VK_ERROR_INITIALIZATION_FAILED; + } + assert(gpu_count > 0); physical_devices_.resize(gpu_count); res = vkEnumeratePhysicalDevices(instance_, &gpu_count, physical_devices_.data()); if (res != VK_SUCCESS) { init_error_ = "Failed to enumerate physical devices"; + vkDestroyInstance(instance_, nullptr); return res; } From ac0052c6af92a37698095969cb52cd7bce8d1e0c Mon Sep 17 00:00:00 2001 From: Neil Munday Date: Tue, 3 Oct 2017 22:08:29 +0100 Subject: [PATCH 20/23] Added default control pad mapping for control pads not found in SDL's game controller database file. --- SDL/SDLJoystick.cpp | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/SDL/SDLJoystick.cpp b/SDL/SDLJoystick.cpp index b02e23fc97..72254a1534 100644 --- a/SDL/SDLJoystick.cpp +++ b/SDL/SDLJoystick.cpp @@ -50,22 +50,36 @@ void SDLJoystick::setUpControllers() { } void SDLJoystick::setUpController(int deviceIndex) { - if (SDL_IsGameController(deviceIndex)) { - SDL_GameController *controller = SDL_GameControllerOpen(deviceIndex); - if (controller) { - if (SDL_GameControllerGetAttached(controller)) { - controllers.push_back(controller); - controllerDeviceMap[SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(controller))] = deviceIndex; - cout << "found control pad: " << SDL_GameControllerName(controller) << ", loading mapping: "; - auto mapping = SDL_GameControllerMapping(controller); - if (mapping == NULL) { - cout << "FAILED" << endl; - } else { - cout << "SUCCESS, mapping is:" << endl << mapping << endl; - } + if (!SDL_IsGameController(deviceIndex)) { + cout << "Control pad device " << deviceIndex << " not supported by SDL game controller database, attempting to create default mapping..." << endl; + int cbGUID = 33; + char pszGUID[cbGUID]; + SDL_Joystick* joystick = SDL_JoystickOpen(deviceIndex); + SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), pszGUID, cbGUID); + // create default mapping - this is the PS3 dual shock mapping + std::string mapping = string(pszGUID) + "," + string(SDL_JoystickName(joystick)) + ",x:b3,a:b0,b:b1,y:b2,back:b8,guide:b10,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:a5,leftstick:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4"; + if (SDL_GameControllerAddMapping(mapping.c_str()) == 1){ + cout << "Added default mapping ok" << endl; + } else { + cout << "Failed to add default mapping" << endl; + } + SDL_JoystickClose(joystick); + } + SDL_GameController *controller = SDL_GameControllerOpen(deviceIndex); + if (controller) { + if (SDL_GameControllerGetAttached(controller)) { + controllers.push_back(controller); + controllerDeviceMap[SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(controller))] = deviceIndex; + cout << "found control pad: " << SDL_GameControllerName(controller) << ", loading mapping: "; + auto mapping = SDL_GameControllerMapping(controller); + if (mapping == NULL) { + //cout << "FAILED" << endl; + cout << "Could not find mapping in SDL2 controller database" << endl; } else { - SDL_GameControllerClose(controller); + cout << "SUCCESS, mapping is:" << endl << mapping << endl; } + } else { + SDL_GameControllerClose(controller); } } } From 709a86a154e2412bc4b811ed604f026ca2721b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 4 Oct 2017 10:33:41 +0200 Subject: [PATCH 21/23] Fix savestates from before 1.4.2-420. Fixes #9998. Unfortunately this also breaks states between 420 and 468, so please save normally before upgrading if you were using one of those. --- Core/HLE/sceKernel.cpp | 4 +++- Core/HLE/sceUsbGps.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 5b6e9a341d..1db8b5d60d 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -263,7 +263,6 @@ void __KernelDoState(PointerWrap &p) __UmdDoState(p); __UtilityDoState(p); __UsbDoState(p); - __UsbGpsDoState(p); __VaudioDoState(p); __HeapDoState(p); @@ -272,6 +271,9 @@ void __KernelDoState(PointerWrap &p) __sceAudiocodecDoState(p); __VideoPmpDoState(p); __AACDoState(p); + __UsbGpsDoState(p); + + // IMPORTANT! Add new sections last! } { diff --git a/Core/HLE/sceUsbGps.cpp b/Core/HLE/sceUsbGps.cpp index 2bca912ec9..4213e7abd1 100644 --- a/Core/HLE/sceUsbGps.cpp +++ b/Core/HLE/sceUsbGps.cpp @@ -36,7 +36,7 @@ void __UsbGpsInit() { } void __UsbGpsDoState(PointerWrap &p) { - auto s = p.Section("sceUsbGps", 1, 4); + auto s = p.Section("sceUsbGps", 0, 1); if (!s) return; From 8826c031a67ed09cf519228ca8c2eda19a46ce85 Mon Sep 17 00:00:00 2001 From: LunaMoo Date: Wed, 4 Oct 2017 17:16:21 +0200 Subject: [PATCH 22/23] Add ini-only "Savedata Upgrade" setting. --- Core/Config.cpp | 1 + Core/Config.h | 1 + Core/Dialog/SavedataParam.cpp | 6 ++++++ 3 files changed, 8 insertions(+) diff --git a/Core/Config.cpp b/Core/Config.cpp index e71562640a..e4adbd12ff 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -754,6 +754,7 @@ static ConfigSetting systemParamSettings[] = { #endif ConfigSetting("WlanPowerSave", &g_Config.bWlanPowerSave, (bool) PSP_SYSTEMPARAM_WLAN_POWERSAVE_OFF, true, true), ReportedConfigSetting("EncryptSave", &g_Config.bEncryptSave, true, true, true), + ConfigSetting("SavedataUpgrade", &g_Config.bSavedataUpgrade, false, true, false), ConfigSetting(false), }; diff --git a/Core/Config.h b/Core/Config.h index d776b0478e..37dd1373fe 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -420,6 +420,7 @@ public: int iButtonPreference; int iLockParentalLevel; bool bEncryptSave; + bool bSavedataUpgrade; // Networking bool bEnableWlan; diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 457747e305..0640eca06b 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -647,6 +647,12 @@ void SavedataParam::LoadCryptedSave(SceUtilitySavedataParam *param, u8 *data, u8 } else { WARN_LOG_REPORT(SCEUTILITY, "Savedata loading with detected hashmode %d instead of file's %d", decryptMode, prevCryptMode); } + if (g_Config.bSavedataUpgrade) { + decryptMode = prevCryptMode; + I18NCategory *di = GetI18NCategory("Dialog"); + host->NotifyUserMessage(di->T("When you save, it will not work on outdated PSP Firmware anymore"), 6.0f); + host->NotifyUserMessage(di->T("Old savedata detected"), 6.0f); + } } } From 3757070fe27d48690448d61ccb52231f9d2dab9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 9 Oct 2017 12:17:54 +0200 Subject: [PATCH 23/23] Extra safety when switching GPU backends, fix possible Vulkan shutdown issue. Should help #10005 --- Common/Vulkan/VulkanMemory.cpp | 1 + GPU/Vulkan/TextureCacheVulkan.cpp | 17 +++++++++++------ UI/GameSettingsScreen.cpp | 3 +++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Common/Vulkan/VulkanMemory.cpp b/Common/Vulkan/VulkanMemory.cpp index da2f7f899b..c6db161c8a 100644 --- a/Common/Vulkan/VulkanMemory.cpp +++ b/Common/Vulkan/VulkanMemory.cpp @@ -143,6 +143,7 @@ void VulkanDeviceAllocator::Destroy() { } } + assert(slab.deviceMemory); vulkan_->Delete().QueueDeleteDeviceMemory(slab.deviceMemory); } slabs_.clear(); diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index e23324966e..11e930399d 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -135,13 +135,16 @@ TextureCacheVulkan::TextureCacheVulkan(Draw::DrawContext *draw, VulkanContext *v TextureCacheVulkan::~TextureCacheVulkan() { Clear(true); - allocator_->Destroy(); - // We have to delete on queue, so this can free its queued deletions. - vulkan_->Delete().QueueCallback([](void *ptr) { - auto allocator = static_cast(ptr); - delete allocator; - }, allocator_); + if (allocator_) { + allocator_->Destroy(); + + // We have to delete on queue, so this can free its queued deletions. + vulkan_->Delete().QueueCallback([](void *ptr) { + auto allocator = static_cast(ptr); + delete allocator; + }, allocator_); + } } void TextureCacheVulkan::SetFramebufferManager(FramebufferManagerVulkan *fbManager) { @@ -171,6 +174,8 @@ void TextureCacheVulkan::DeviceLost() { void TextureCacheVulkan::DeviceRestore(VulkanContext *vulkan) { vulkan_ = vulkan; + assert(!allocator_); + allocator_ = new VulkanDeviceAllocator(vulkan_, TEXCACHE_MIN_SLAB_SIZE, TEXCACHE_MAX_SLAB_SIZE); samplerCache_.DeviceRestore(vulkan); } diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index d30aebb853..5baed5463e 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1083,6 +1083,9 @@ void GameSettingsScreen::CallbackRenderingBackend(bool yes) { // If the user ends up deciding not to restart, set the config back to the current backend // so it doesn't get switched by accident. if (yes) { + // Extra save here to make sure the choice really gets saved even if there are shutdown bugs in + // the GPU backend code. + g_Config.Save(); System_SendMessage("graphics_restart", ""); } else { g_Config.iGPUBackend = (int)GetGPUBackend();