From 99b34c7b455af37157293a8cf5dd7a2037c480c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 7 Dec 2017 17:02:00 +0100 Subject: [PATCH 1/3] Use glslang to translate GLSL 1.x postshaders to GLSL 3.0 or later to appease strict GL Core drivers. Should fix #10362 Fixed small bugs, now tested and working on mac. Add spirv-cross to cmake build --- CMakeLists.txt | 2 +- GPU/Common/ShaderTranslation.cpp | 21 +++++++++++++++ GPU/GLES/FramebufferManagerGLES.cpp | 41 ++++++++++++++++++++++++++++- UI/DevScreens.cpp | 3 +++ Windows/GPU/WindowsGLContext.cpp | 3 +++ ext/native/base/PCMain.cpp | 4 +++ ext/native/base/QtMain.cpp | 4 +++ 7 files changed, 76 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 16fe1ef6acaf..927aa9bb7170 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1638,7 +1638,7 @@ endif() set(CoreExtraLibs ${CoreExtraLibs} armips) -set(GlslangLibs glslang OGLCompiler OSDependent SPIRV SPVRemapper) +set(GlslangLibs glslang OGLCompiler OSDependent SPIRV SPVRemapper spirv-cross-glsl) target_link_libraries(${CoreLibName} Common native kirk cityhash sfmt19937 xbrz xxhash ${GlslangLibs} ${CoreExtraLibs} ${OPENGL_LIBRARIES} ${X11_LIBRARIES} ${CMAKE_DL_LIBS}) diff --git a/GPU/Common/ShaderTranslation.cpp b/GPU/Common/ShaderTranslation.cpp index 0f6c3b2b3b2c..d1a7e9b802e5 100644 --- a/GPU/Common/ShaderTranslation.cpp +++ b/GPU/Common/ShaderTranslation.cpp @@ -32,6 +32,7 @@ #include "ShaderTranslation.h" #include "ext/glslang/SPIRV/GlslangToSpv.h" #include "thin3d/thin3d.h" +#include "gfx_es2/gpu_features.h" #if !defined(ANDROID) #include "ext/SPIRV-Cross/spirv.hpp" @@ -196,6 +197,9 @@ bool TranslateShader(std::string *dest, ShaderLanguage destLang, TranslatedShade bool result = ConvertToVulkanGLSL(dest, destMetadata, src, stage, errorMessage); return result; } + if (errorMessage) { + *errorMessage = ""; + } #if defined(ANDROID) return false; @@ -307,6 +311,23 @@ bool TranslateShader(std::string *dest, ShaderLanguage destLang, TranslatedShade *dest = glsl.compile(); return true; } + case GLSL_300: + { + spirv_cross::CompilerGLSL glsl(std::move(spirv)); + // The SPIR-V is now parsed, and we can perform reflection on it. + spirv_cross::ShaderResources resources = glsl.get_shader_resources(); + // Set some options. + spirv_cross::CompilerGLSL::Options options; + if (gl_extensions.ver[0] >= 4) { + options.version = 400; + } else { + options.version = 300; + } + glsl.set_options(options); + // Compile to GLSL, ready to give to GL driver. + *dest = glsl.compile(); + return true; + } default: return false; } diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 4324cb17ac48..2b0aa7991db8 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -25,6 +25,7 @@ #include "thin3d/thin3d.h" #include "base/timeutil.h" +#include "file/vfs.h" #include "math/lin/matrix4x4.h" #include "Common/ColorConv.h" @@ -37,6 +38,7 @@ #include "GPU/GPUState.h" #include "GPU/Common/PostShader.h" +#include "GPU/Common/ShaderTranslation.h" #include "GPU/Common/TextureDecoder.h" #include "GPU/Common/FramebufferCommon.h" #include "GPU/Debugger/Stepping.h" @@ -122,7 +124,44 @@ void FramebufferManagerGLES::CompilePostShader() { if (shaderInfo) { std::string errorString; postShaderAtOutputResolution_ = shaderInfo->outputResolution; - postShaderProgram_ = glsl_create(shaderInfo->vertexShaderFile.c_str(), shaderInfo->fragmentShaderFile.c_str(), &errorString); + + size_t sz; + char *vs = (char *)VFSReadFile(shaderInfo->vertexShaderFile.c_str(), &sz); + if (!vs) + return; + char *fs = (char *)VFSReadFile(shaderInfo->fragmentShaderFile.c_str(), &sz); + if (!fs) { + free(vs); + return; + } + + std::string vshader; + std::string fshader; + bool translationFailed = false; + if (gl_extensions.IsCoreContext) { + // Gonna have to upconvert the shaders. + std::string errorMessage; + if (!TranslateShader(&vshader, GLSL_300, nullptr, vs, GLSL_140, Draw::ShaderStage::VERTEX, &errorMessage)) { + translationFailed = true; + ELOG("Failed to translate post-vshader: %s", errorMessage.c_str()); + } + if (!TranslateShader(&fshader, GLSL_300, nullptr, fs, GLSL_140, Draw::ShaderStage::FRAGMENT, &errorMessage)) { + translationFailed = true; + ELOG("Failed to translate post-fshader: %s", errorMessage.c_str()); + } + } else { + vshader = vs; + fshader = fs; + } + + if (!translationFailed) { + postShaderProgram_ = glsl_create_source(vshader.c_str(), fshader.c_str(), &errorString); + } else { + ERROR_LOG(FRAMEBUF, "Failed to translate post shader!"); + } + free(vs); + free(fs); + if (!postShaderProgram_) { // DO NOT turn this into a report, as it will pollute our logs with all kinds of // user shader experiments. diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index d69db27b3fe6..bf007ce07f83 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -396,6 +396,9 @@ void SystemInfoScreen::CreateViews() { } #endif #endif + if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) { + deviceSpecs->Add(new InfoItem("Core Context", gl_extensions.IsCoreContext ? "Yes" : "No")); + } deviceSpecs->Add(new ItemHeader("OS Information")); deviceSpecs->Add(new InfoItem("Memory Page Size", StringFromFormat("%d bytes", GetMemoryProtectPageSize()))); deviceSpecs->Add(new InfoItem("RW/RX exclusive: ", PlatformIsWXExclusive() ? "Yes" : "No")); diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index 363d6d928bd6..54486671d130 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -28,6 +28,7 @@ #include "util/text/utf8.h" #include "i18n/i18n.h" #include "UI/OnScreenDisplay.h" +#include "ext/glslang/glslang/Public/ShaderLang.h" #include "Windows/W32Util/Misc.h" #include "Windows/GPU/WindowsGLContext.h" @@ -151,6 +152,7 @@ void DebugCallbackARB(GLenum source, GLenum type, GLuint id, GLenum severity, } bool WindowsGLContext::Init(HINSTANCE hInst, HWND window, std::string *error_message) { + glslang::InitializeProcess(); *error_message = "ok"; hWnd = window; GLuint PixelFormat; @@ -398,6 +400,7 @@ void WindowsGLContext::Shutdown() { hDC = NULL; } hWnd = NULL; + glslang::FinalizeProcess(); } void WindowsGLContext::Resize() { diff --git a/ext/native/base/PCMain.cpp b/ext/native/base/PCMain.cpp index 9bf98b097823..128e045d4c5e 100644 --- a/ext/native/base/PCMain.cpp +++ b/ext/native/base/PCMain.cpp @@ -32,6 +32,7 @@ SDLJoystick *joystick = NULL; #include "base/display.h" #include "base/logging.h" #include "base/timeutil.h" +#include "ext/glslang/glslang/Public/ShaderLang.h" #include "gfx/gl_common.h" #include "gfx_es2/gpu_features.h" #include "input/input_state.h" @@ -687,6 +688,8 @@ int main(int argc, char *argv[]) { printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); + glslang::InitializeProcess(); + GraphicsContext *graphicsContext = new GLDummyGraphicsContext(); NativeInitGraphics(graphicsContext); @@ -939,6 +942,7 @@ int main(int argc, char *argv[]) { graphicsContext->Shutdown(); NativeShutdown(); delete graphicsContext; + glslang::FinalizeProcess(); // Faster exit, thanks to the OS. Remove this if you want to debug shutdown // The speed difference is only really noticable on Linux. On Windows you do notice it though #ifndef MOBILE_DEVICE diff --git a/ext/native/base/QtMain.cpp b/ext/native/base/QtMain.cpp index 06a050291a7f..3030f64354e1 100644 --- a/ext/native/base/QtMain.cpp +++ b/ext/native/base/QtMain.cpp @@ -13,6 +13,8 @@ #include #include +#include "ext/glslang/glslang/Public/ShaderLang.h" + #if QT_VERSION > QT_VERSION_CHECK(5, 0, 0) #include #ifdef QT_HAS_SYSTEMINFO @@ -428,6 +430,7 @@ Q_DECL_EXPORT #endif int main(int argc, char *argv[]) { + glslang::InitializeProcess(); #if defined(Q_OS_LINUX) QApplication::setAttribute(Qt::AA_X11InitThreads, true); #endif @@ -467,6 +470,7 @@ int main(int argc, char *argv[]) SDL_CloseAudio(); #endif NativeShutdown(); + glslang::FinalizeProcess(); return ret; } From b895f944ffdb98cb0b504c6d22999e17a0f057c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 7 Dec 2017 22:33:41 +0100 Subject: [PATCH 2/3] SPIRV-Cross should build on Android now, so remove another platform check. --- GPU/Common/ShaderTranslation.cpp | 13 ++----------- ext/CMakeLists.txt | 1 + 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/GPU/Common/ShaderTranslation.cpp b/GPU/Common/ShaderTranslation.cpp index d1a7e9b802e5..4bc34908be9a 100644 --- a/GPU/Common/ShaderTranslation.cpp +++ b/GPU/Common/ShaderTranslation.cpp @@ -34,7 +34,6 @@ #include "thin3d/thin3d.h" #include "gfx_es2/gpu_features.h" -#if !defined(ANDROID) #include "ext/SPIRV-Cross/spirv.hpp" #include "ext/SPIRV-Cross/spirv_common.hpp" #include "ext/SPIRV-Cross/spirv_cross.hpp" @@ -42,11 +41,9 @@ #ifdef _WIN32 #include "ext/SPIRV-Cross/spirv_hlsl.hpp" #endif -#endif extern void init_resources(TBuiltInResource &Resources); -#if !defined(ANDROID) static EShLanguage GetLanguage(const Draw::ShaderStage stage) { switch (stage) { case Draw::ShaderStage::VERTEX: return EShLangVertex; @@ -58,16 +55,15 @@ static EShLanguage GetLanguage(const Draw::ShaderStage stage) { default: return EShLangVertex; } } -#endif void ShaderTranslationInit() { // TODO: We have TLS issues on UWP -#if !PPSSPP_PLATFORM(UWP) && !defined(ANDROID) +#if !PPSSPP_PLATFORM(UWP) glslang::InitializeProcess(); #endif } void ShaderTranslationShutdown() { -#if !PPSSPP_PLATFORM(UWP) && !defined(ANDROID) +#if !PPSSPP_PLATFORM(UWP) glslang::FinalizeProcess(); #endif } @@ -201,10 +197,6 @@ bool TranslateShader(std::string *dest, ShaderLanguage destLang, TranslatedShade *errorMessage = ""; } -#if defined(ANDROID) - return false; -#else - #if PPSSPP_PLATFORM(UWP) return false; #endif @@ -331,5 +323,4 @@ bool TranslateShader(std::string *dest, ShaderLanguage destLang, TranslatedShade default: return false; } -#endif } diff --git a/ext/CMakeLists.txt b/ext/CMakeLists.txt index c616be29d219..f506eb6787b4 100644 --- a/ext/CMakeLists.txt +++ b/ext/CMakeLists.txt @@ -6,6 +6,7 @@ if(NOT USING_GLES2) endif() set(ENABLE_GLSLANG_BINARIES OFF CACHE BOOL "let's not build binaries we don't need" FORCE) +set(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS ON CACHE BOOL "let's not use exceptions" FORCE) add_subdirectory(glslang) add_subdirectory(snappy) From 58fd674bbf8017f9fbcd2cf1b6aadb454d2378d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 8 Dec 2017 10:25:01 +0100 Subject: [PATCH 3/3] Try to fix build with the old Android build system too... --- android/jni/Android.mk | 6 ++++++ android/jni/Locals.mk | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 252d8cffae3f..69ecc0b24dc9 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -144,10 +144,16 @@ VULKAN_FILES := \ $(SRC)/GPU/Vulkan/VulkanUtil.cpp #endif +SPIRV_CROSS_FILES := \ + $(SRC)/ext/SPIRV-Cross/spirv_cfg.cpp \ + $(SRC)/ext/SPIRV-Cross/spirv_cross.cpp \ + $(SRC)/ext/SPIRV-Cross/spirv_glsl.cpp + EXEC_AND_LIB_FILES := \ $(ARCH_FILES) \ $(EGL_FILES) \ $(VULKAN_FILES) \ + $(SPIRV_CROSS_FILES) \ TestRunner.cpp \ $(SRC)/Core/MIPS/MIPS.cpp.arm \ $(SRC)/Core/MIPS/MIPSAnalyst.cpp \ diff --git a/android/jni/Locals.mk b/android/jni/Locals.mk index 6e91bffb0212..92ed005928d6 100644 --- a/android/jni/Locals.mk +++ b/android/jni/Locals.mk @@ -1,7 +1,7 @@ # These are definitions for LOCAL_ variables for PPSSPP. # They are shared between ppsspp_jni (lib for Android app) and ppsspp_headless. -LOCAL_CFLAGS := -DUSE_FFMPEG -DUSING_GLES2 -DMOBILE_DEVICE -O3 -fsigned-char -Wall -Wno-multichar -Wno-unused-variable -fno-strict-aliasing -D__STDC_CONSTANT_MACROS -Wno-format +LOCAL_CFLAGS := -DUSE_FFMPEG -DUSING_GLES2 -DMOBILE_DEVICE -O3 -fsigned-char -Wall -Wno-multichar -Wno-unused-variable -fno-strict-aliasing -D__STDC_CONSTANT_MACROS -Wno-format -DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS # yes, it's really CPPFLAGS for C++ # deprecated-register is generated by Android default code and causes noise. LOCAL_CPPFLAGS := -fno-exceptions -std=gnu++11 -fno-rtti -Wno-reorder -Wno-format -Wno-deprecated-register