Apply requested changes

This commit is contained in:
offtkp 2024-08-09 02:16:38 +03:00
parent 9a852475c5
commit 3678523266
6 changed files with 63 additions and 79 deletions

View file

@ -45,6 +45,6 @@ struct AsyncCompilerThread {
std::array<CompilingProgram*, preallocatedProgramsSize> preallocatedPrograms; std::array<CompilingProgram*, preallocatedProgramsSize> preallocatedPrograms;
lockfree::spsc::Queue<CompilingProgram*, preallocatedProgramsSize - 1> programQueue; lockfree::spsc::Queue<CompilingProgram*, preallocatedProgramsSize - 1> programQueue;
std::atomic_bool running; std::atomic_bool running;
std::atomic_flag hasWork = ATOMIC_FLAG_INIT; std::atomic_bool hasWork;
std::thread thread; std::thread thread;
}; };

View file

@ -30,7 +30,7 @@ AsyncCompilerThread::AsyncCompilerThread(PICA::ShaderGen::FragmentGenerator& fra
fragShader.free(); fragShader.free();
} }
hasWork.clear(); hasWork.store(false);
std::this_thread::yield(); std::this_thread::yield();
} }
@ -57,19 +57,16 @@ void AsyncCompilerThread::PushFragmentConfig(const PICA::FragmentConfig& config,
if (!pushed) { if (!pushed) {
Helpers::warn("AsyncCompilerThread: Queue full, spinning"); Helpers::warn("AsyncCompilerThread: Queue full, spinning");
} else {
return;
}
while (!pushed) { while (!pushed) {
pushed = programQueue.Push(newProgram); pushed = programQueue.Push(newProgram);
}
} }
} }
void AsyncCompilerThread::Finish() { void AsyncCompilerThread::Finish() {
hasWork.test_and_set(); hasWork.store(true);
// Wait for the compiler thread to finish any outstanding work // Wait for the compiler thread to finish any outstanding work
while (hasWork.test_and_set()) { while (hasWork.load()) {}
}
} }

View file

@ -429,54 +429,38 @@ void RendererGL::drawVertices(PICA::PrimType primType, std::span<const Vertex> v
OpenGL::Triangle, OpenGL::Triangle,
}; };
bool usingUbershader; if (shaderMode == ShaderMode::Ubershader) {
switch (shaderMode) { const bool lightsEnabled = (regs[InternalRegs::LightingEnable] & 1) != 0;
case ShaderMode::Ubershader: { const uint lightCount = (regs[InternalRegs::LightNumber] & 0x7) + 1;
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 // 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 // This way we generate fewer shaders overall than with full shadergen, but don't tank performance
if (emulatorConfig->forceShadergenForLights && lightsEnabled && lightCount >= emulatorConfig->lightShadergenThreshold) { if (emulatorConfig->forceShadergenForLights && lightsEnabled && lightCount >= emulatorConfig->lightShadergenThreshold) {
usingUbershader = false; OpenGL::Program& program = getSpecializedShader();
} else { gl.useProgram(program);
usingUbershader = true; } else {
} gl.useProgram(triangleProgram);
break;
} }
} else if (shaderMode == ShaderMode::Specialized) {
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 {
OpenGL::Program& program = getSpecializedShader(); OpenGL::Program& program = getSpecializedShader();
gl.useProgram(program); 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<usize>(primType)]; const auto primitiveTopology = primTypes[static_cast<usize>(primType)];
@ -504,7 +488,7 @@ void RendererGL::drawVertices(PICA::PrimType primType, std::span<const Vertex> v
static constexpr std::array<GLenum, 8> depthModes = {GL_NEVER, GL_ALWAYS, GL_EQUAL, GL_NOTEQUAL, GL_LESS, GL_LEQUAL, GL_GREATER, GL_GEQUAL}; static constexpr std::array<GLenum, 8> depthModes = {GL_NEVER, GL_ALWAYS, GL_EQUAL, GL_NOTEQUAL, GL_LESS, GL_LEQUAL, GL_GREATER, GL_GEQUAL};
// Update ubershader uniforms // Update ubershader uniforms
if (usingUbershader) { if (gl.currentProgram == triangleProgram.handle()) {
const float depthScale = f24::fromRaw(regs[PICA::InternalRegs::DepthScale] & 0xffffff).toFloat32(); const float depthScale = f24::fromRaw(regs[PICA::InternalRegs::DepthScale] & 0xffffff).toFloat32();
const float depthOffset = f24::fromRaw(regs[PICA::InternalRegs::DepthOffset] & 0xffffff).toFloat32(); const float depthOffset = f24::fromRaw(regs[PICA::InternalRegs::DepthOffset] & 0xffffff).toFloat32();
const bool depthMapEnable = regs[PICA::InternalRegs::DepthmapEnable] & 1; const bool depthMapEnable = regs[PICA::InternalRegs::DepthmapEnable] & 1;
@ -890,7 +874,7 @@ OpenGL::Program& RendererGL::getSpecializedShader() {
OpenGL::Program& program = programEntry.program; OpenGL::Program& program = programEntry.program;
if (!program.exists()) { if (!program.exists()) {
if (shaderMode == ShaderMode::Hybrid) { if (shaderMode == ShaderMode::Hybrid) [[unlikely]] {
Helpers::panic("Compiling shaders in main thread, this should never happen"); 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() { 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 // May contain objects that are still in use, so we need to clear them first
asyncCompiler->Finish(); asyncCompiler->Finish();
} }

View file

@ -162,3 +162,13 @@ HC_API const char* getInfo(hydra::InfoType type) {
default: return nullptr; default: return nullptr;
} }
} }
namespace AsyncCompiler {
void* createContext(void* mainContext) {
return nullptr;
}
void makeCurrent(void* mainContext, void* context) {}
void destroyContext(void* context) {}
} // namespace AsyncCompiler

View file

@ -140,14 +140,3 @@ int AndroidUtils::openDocument(const char* path, const char* perms) {
return (int)result; 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

View file

@ -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_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_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_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); window = SDL_CreateWindow("Alber", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 400, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (window == nullptr) { if (window == nullptr) {
@ -47,6 +51,16 @@ FrontendSDL::FrontendSDL() : keyboardMappings(InputMappings::defaultKeyboardMapp
Helpers::panic("OpenGL context creation failed: %s", SDL_GetError()); 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<GLADloadproc>(SDL_GL_GetProcAddress))) { if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(SDL_GL_GetProcAddress))) {
Helpers::panic("OpenGL init failed"); 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_GL_CreateContext also makes it the current context so we need to switch back after creation
SDL_GLContext currentContext = SDL_GL_GetCurrentContext(); SDL_GLContext currentContext = SDL_GL_GetCurrentContext();
SDL_GLContext glContext = SDL_GL_CreateContext(sdlWindow); SDL_GLContext glContext = SDL_GL_CreateContext(sdlWindow);
if (glContext == nullptr) { if (glContext == nullptr) {
Helpers::panic("OpenGL context creation failed: %s", SDL_GetError()); 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); SDL_GL_MakeCurrent(sdlWindow, currentContext);
return glContext; return glContext;
} }