From 3678523266dd2c2ab565fc646c73615bd1e55d8b Mon Sep 17 00:00:00 2001 From: offtkp Date: Fri, 9 Aug 2024 02:16:38 +0300 Subject: [PATCH] Apply requested changes --- include/renderer_gl/async_compiler.hpp | 2 +- src/core/renderer_gl/async_compiler.cpp | 15 ++--- src/core/renderer_gl/renderer_gl.cpp | 78 ++++++++++--------------- src/hydra_core.cpp | 10 ++++ src/jni_driver.cpp | 11 ---- src/panda_sdl/frontend_sdl.cpp | 26 +++++---- 6 files changed, 63 insertions(+), 79 deletions(-) diff --git a/include/renderer_gl/async_compiler.hpp b/include/renderer_gl/async_compiler.hpp index b57ce972..6635cb9e 100644 --- a/include/renderer_gl/async_compiler.hpp +++ b/include/renderer_gl/async_compiler.hpp @@ -45,6 +45,6 @@ struct AsyncCompilerThread { std::array preallocatedPrograms; lockfree::spsc::Queue programQueue; std::atomic_bool running; - std::atomic_flag hasWork = ATOMIC_FLAG_INIT; + std::atomic_bool hasWork; std::thread thread; }; \ No newline at end of file diff --git a/src/core/renderer_gl/async_compiler.cpp b/src/core/renderer_gl/async_compiler.cpp index 95631c78..7e58a9e1 100644 --- a/src/core/renderer_gl/async_compiler.cpp +++ b/src/core/renderer_gl/async_compiler.cpp @@ -30,7 +30,7 @@ AsyncCompilerThread::AsyncCompilerThread(PICA::ShaderGen::FragmentGenerator& fra fragShader.free(); } - hasWork.clear(); + hasWork.store(false); std::this_thread::yield(); } @@ -57,19 +57,16 @@ void AsyncCompilerThread::PushFragmentConfig(const PICA::FragmentConfig& config, if (!pushed) { Helpers::warn("AsyncCompilerThread: Queue full, spinning"); - } else { - return; - } - while (!pushed) { - pushed = programQueue.Push(newProgram); + while (!pushed) { + pushed = programQueue.Push(newProgram); + } } } void AsyncCompilerThread::Finish() { - hasWork.test_and_set(); + hasWork.store(true); // Wait for the compiler thread to finish any outstanding work - while (hasWork.test_and_set()) { - } + while (hasWork.load()) {} } \ No newline at end of file diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 8945f6e9..d0fc3385 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -429,54 +429,38 @@ void RendererGL::drawVertices(PICA::PrimType primType, std::span v OpenGL::Triangle, }; - bool usingUbershader; - switch (shaderMode) { - case ShaderMode::Ubershader: { - const bool lightsEnabled = (regs[InternalRegs::LightingEnable] & 1) != 0; - const uint lightCount = (regs[InternalRegs::LightNumber] & 0x7) + 1; + if (shaderMode == ShaderMode::Ubershader) { + const bool lightsEnabled = (regs[InternalRegs::LightingEnable] & 1) != 0; + const uint lightCount = (regs[InternalRegs::LightNumber] & 0x7) + 1; - // Emulating lights in the ubershader is incredibly slow, so we've got an option to render draws using moret han N lights via shadergen - // This way we generate fewer shaders overall than with full shadergen, but don't tank performance - if (emulatorConfig->forceShadergenForLights && lightsEnabled && lightCount >= emulatorConfig->lightShadergenThreshold) { - usingUbershader = false; - } else { - usingUbershader = true; - } - break; + // Emulating lights in the ubershader is incredibly slow, so we've got an option to render draws using moret han N lights via shadergen + // This way we generate fewer shaders overall than with full shadergen, but don't tank performance + if (emulatorConfig->forceShadergenForLights && lightsEnabled && lightCount >= emulatorConfig->lightShadergenThreshold) { + OpenGL::Program& program = getSpecializedShader(); + gl.useProgram(program); + } else { + gl.useProgram(triangleProgram); } - - case ShaderMode::Specialized: { - usingUbershader = false; - break; - } - - case ShaderMode::Hybrid: { - PICA::FragmentConfig fsConfig(regs); // TODO: introduce code duplication to make sure this constructor/lookup isn't done too many times - auto cachedProgram = shaderCache.find(fsConfig); - if (cachedProgram == shaderCache.end()) { - CachedProgram& program = shaderCache[fsConfig]; - program.compiling.store(true); - asyncCompiler->PushFragmentConfig(fsConfig, &program); - usingUbershader = true; - } else if (cachedProgram->second.compiling.load(std::memory_order_relaxed)) { - usingUbershader = true; - } else { - usingUbershader = false; - } - break; - } - - default: { - Helpers::panic("Invalid shader mode"); - break; - } - } - - if (usingUbershader) { - gl.useProgram(triangleProgram); - } else { + } else if (shaderMode == ShaderMode::Specialized) { OpenGL::Program& program = getSpecializedShader(); gl.useProgram(program); + } else if (shaderMode == ShaderMode::Hybrid) { + PICA::FragmentConfig fsConfig(regs); + auto cachedProgram = shaderCache.find(fsConfig); + + if (cachedProgram == shaderCache.end()) { + CachedProgram& program = shaderCache[fsConfig]; + program.compiling.store(true); + asyncCompiler->PushFragmentConfig(fsConfig, &program); + gl.useProgram(triangleProgram); + } else if (cachedProgram->second.compiling.load(std::memory_order_relaxed)) { + gl.useProgram(triangleProgram); + } else { + OpenGL::Program& program = getSpecializedShader(); + gl.useProgram(program); + } + } else { + Helpers::panic("Invalid shader mode"); } const auto primitiveTopology = primTypes[static_cast(primType)]; @@ -504,7 +488,7 @@ void RendererGL::drawVertices(PICA::PrimType primType, std::span v static constexpr std::array depthModes = {GL_NEVER, GL_ALWAYS, GL_EQUAL, GL_NOTEQUAL, GL_LESS, GL_LEQUAL, GL_GREATER, GL_GEQUAL}; // Update ubershader uniforms - if (usingUbershader) { + if (gl.currentProgram == triangleProgram.handle()) { const float depthScale = f24::fromRaw(regs[PICA::InternalRegs::DepthScale] & 0xffffff).toFloat32(); const float depthOffset = f24::fromRaw(regs[PICA::InternalRegs::DepthOffset] & 0xffffff).toFloat32(); const bool depthMapEnable = regs[PICA::InternalRegs::DepthmapEnable] & 1; @@ -890,7 +874,7 @@ OpenGL::Program& RendererGL::getSpecializedShader() { OpenGL::Program& program = programEntry.program; if (!program.exists()) { - if (shaderMode == ShaderMode::Hybrid) { + if (shaderMode == ShaderMode::Hybrid) [[unlikely]] { Helpers::panic("Compiling shaders in main thread, this should never happen"); } @@ -1032,7 +1016,7 @@ void RendererGL::screenshot(const std::string& name) { } void RendererGL::clearShaderCache() { - if (asyncCompiler && shaderMode == ShaderMode::Hybrid) { + if (asyncCompiler != nullptr && shaderMode == ShaderMode::Hybrid) { // May contain objects that are still in use, so we need to clear them first asyncCompiler->Finish(); } diff --git a/src/hydra_core.cpp b/src/hydra_core.cpp index acbf30a8..0abd3987 100644 --- a/src/hydra_core.cpp +++ b/src/hydra_core.cpp @@ -162,3 +162,13 @@ HC_API const char* getInfo(hydra::InfoType type) { default: return nullptr; } } + +namespace AsyncCompiler { + void* createContext(void* mainContext) { + return nullptr; + } + + void makeCurrent(void* mainContext, void* context) {} + + void destroyContext(void* context) {} +} // namespace AsyncCompiler diff --git a/src/jni_driver.cpp b/src/jni_driver.cpp index 306c8ba6..bdd34470 100644 --- a/src/jni_driver.cpp +++ b/src/jni_driver.cpp @@ -140,14 +140,3 @@ int AndroidUtils::openDocument(const char* path, const char* perms) { return (int)result; } - -namespace AsyncCompiler { - void* createContext(void* mainContext) { - throwException(jniEnv(), "AsyncCompiler not supported on Android, how did you manage to enable this?"); - return nullptr; - } - - void makeCurrent(void* mainContext, void* context) {} - - void destroyContext(void* context) {} -} // namespace AsyncCompiler diff --git a/src/panda_sdl/frontend_sdl.cpp b/src/panda_sdl/frontend_sdl.cpp index 59d06541..2e806fe2 100644 --- a/src/panda_sdl/frontend_sdl.cpp +++ b/src/panda_sdl/frontend_sdl.cpp @@ -35,7 +35,11 @@ FrontendSDL::FrontendSDL() : keyboardMappings(InputMappings::defaultKeyboardMapp SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, config.rendererType == RendererType::Software ? 3 : 4); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, config.rendererType == RendererType::Software ? 3 : 1); - SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1); + + if (config.shaderMode == ShaderMode::Hybrid) { + SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1); + } + window = SDL_CreateWindow("Alber", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 400, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); if (window == nullptr) { @@ -47,6 +51,16 @@ FrontendSDL::FrontendSDL() : keyboardMappings(InputMappings::defaultKeyboardMapp Helpers::panic("OpenGL context creation failed: %s", SDL_GetError()); } + if (config.shaderMode == ShaderMode::Hybrid) { + // As per the wiki you should check the value after creating the context + // as it can differ from the requested value + int sharingEnabled; + SDL_GL_GetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, &sharingEnabled); + if (!sharingEnabled) { + Helpers::panic("OpenGL context sharing not enabled"); + } + } + if (!gladLoadGLLoader(reinterpret_cast(SDL_GL_GetProcAddress))) { Helpers::panic("OpenGL init failed"); } @@ -350,23 +364,13 @@ namespace AsyncCompiler { // SDL_GL_CreateContext also makes it the current context so we need to switch back after creation SDL_GLContext currentContext = SDL_GL_GetCurrentContext(); - SDL_GLContext glContext = SDL_GL_CreateContext(sdlWindow); if (glContext == nullptr) { Helpers::panic("OpenGL context creation failed: %s", SDL_GetError()); } - // As per the wiki you should check the value after creating the context - // as it can differ from the requested value - int sharingEnabled; - SDL_GL_GetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, &sharingEnabled); - if (!sharingEnabled) { - Helpers::panic("OpenGL context sharing not enabled"); - } - SDL_GL_MakeCurrent(sdlWindow, currentContext); - return glContext; }