mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-07 14:45:41 +12:00
Apply requested changes
This commit is contained in:
parent
9a852475c5
commit
3678523266
6 changed files with 63 additions and 79 deletions
|
@ -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;
|
||||
};
|
|
@ -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()) {}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue