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;
lockfree::spsc::Queue<CompilingProgram*, preallocatedProgramsSize - 1> programQueue;
std::atomic_bool running;
std::atomic_flag hasWork = ATOMIC_FLAG_INIT;
std::atomic_bool hasWork;
std::thread thread;
};

View file

@ -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()) {}
}

View file

@ -429,54 +429,38 @@ void RendererGL::drawVertices(PICA::PrimType primType, std::span<const Vertex> 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<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};
// 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();
}

View file

@ -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

View file

@ -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

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_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<GLADloadproc>(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;
}