#include #include #include #include "run_furmark.h" #include "sates.h" #include #include extern void frSceneInit(); extern void frRender(); extern void frExit(); extern void frRamSceneInit(); extern void frRamRender(); extern void frRamExit(); extern void GPUPTSceneInit(); extern void GPUPTRender(); extern void GPUPTExit(); extern void BHRTSceneInit(); extern void BHRTRender(); extern void BHRTExit(); extern void CPURTSceneinit(); extern void CPURTRender(); extern void CPURTExit(); extern void CPURBSceneinit(); extern void CPURBRender(); extern void CPURBExit(); AppState state = STATE_MENU; namespace { std::thread g_thread; std::atomic g_stop{ false }; std::atomic g_running{ false }; std::atomic g_fps{ 0.0f }; std::atomic g_which{ -1 }; EGLDisplay s_dpy = EGL_NO_DISPLAY; EGLContext s_ctx = EGL_NO_CONTEXT; EGLSurface s_surf = EGL_NO_SURFACE; bool eglUp() { s_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (s_dpy == EGL_NO_DISPLAY) return false; if (!eglInitialize(s_dpy, nullptr, nullptr)) return false; if (!eglBindAPI(EGL_OPENGL_API)) return false; const EGLint cfgAttr[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 24, EGL_STENCIL_SIZE, 8, EGL_NONE }; EGLConfig cfg; EGLint n = 0; if (!eglChooseConfig(s_dpy, cfgAttr, &cfg, 1, &n) || n == 0) return false; const EGLint ctxAttr[] = { EGL_CONTEXT_MAJOR_VERSION, 4, EGL_CONTEXT_MINOR_VERSION, 3, EGL_NONE }; s_ctx = eglCreateContext(s_dpy, cfg, EGL_NO_CONTEXT, ctxAttr); if (s_ctx == EGL_NO_CONTEXT) return false; s_surf = EGL_NO_SURFACE; if (eglMakeCurrent(s_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, s_ctx) != EGL_TRUE) return false; return true; } void eglDown() { if (s_dpy) { eglMakeCurrent(s_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (s_ctx) eglDestroyContext(s_dpy, s_ctx); if (s_surf != EGL_NO_SURFACE) eglDestroySurface(s_dpy, s_surf); eglTerminate(s_dpy); } s_ctx = EGL_NO_CONTEXT; s_surf = EGL_NO_SURFACE; s_dpy = EGL_NO_DISPLAY; eglReleaseThread(); } void sceneInit(int which) { switch (which) { case 0: frSceneInit(); break; case 1: frRamSceneInit(); break; case 2: GPUPTSceneInit(); break; case 3: BHRTSceneInit(); break; case 4: CPURTSceneinit(); break; case 5: CPURBSceneinit(); break; } } void sceneRender(int which) { switch (which) { case 0: frRender(); break; case 1: frRamRender(); break; case 2: GPUPTRender(); break; case 3: BHRTRender(); break; case 4: CPURTRender(); break; case 5: CPURBRender(); break; } } void sceneExit(int which) { switch (which) { case 0: frExit(); break; case 1: frRamExit(); break; case 2: GPUPTExit(); break; case 3: BHRTExit(); break; case 4: CPURTExit(); break; case 5: CPURBExit(); break; } } void worker(int which) { g_which.store(which); g_fps.store(0.0f); if (!eglUp()) { eglDown(); g_which.store(-1); g_running.store(false); return; } gladLoadGLLoader((GLADloadproc)eglGetProcAddress); GLuint fbo = 0, rbColor = 0, rbDepth = 0; glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glGenRenderbuffers(1, &rbColor); glBindRenderbuffer(GL_RENDERBUFFER, rbColor); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1280, 720); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbColor); glGenRenderbuffers(1, &rbDepth); glBindRenderbuffer(GL_RENDERBUFFER, rbDepth); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 1280, 720); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbDepth); glViewport(0, 0, 1280, 720); sceneInit(which); const u64 frameNs = 16666666ULL; u64 fpsT0 = armGetSystemTick(); int fpsFrames = 0; while (!g_stop.load()) { u64 t0 = armGetSystemTick(); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glViewport(0, 0, 1280, 720); sceneRender(which); GLsync fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); glFlush(); while (!g_stop.load()) { GLenum r = glClientWaitSync(fence, 0, 0); if (r != GL_TIMEOUT_EXPIRED) break; svcSleepThread(500000ULL); } glDeleteSync(fence); u64 dt = armTicksToNs(armGetSystemTick() - t0); if (dt < frameNs) svcSleepThread(frameNs - dt); fpsFrames++; u64 elapsed = armTicksToNs(armGetSystemTick() - fpsT0); if (elapsed >= 500000000ULL) { g_fps.store((float)((double)fpsFrames * 1.0e9 / (double)elapsed)); fpsFrames = 0; fpsT0 = armGetSystemTick(); } } sceneExit(which); glDeleteFramebuffers(1, &fbo); glDeleteRenderbuffers(1, &rbColor); glDeleteRenderbuffers(1, &rbDepth); eglDown(); g_fps.store(0.0f); g_which.store(-1); g_running.store(false); } } // namespace extern "C" void run_furmark_start(int which) { if (g_running.load()) return; if (g_thread.joinable()) g_thread.join(); g_stop.store(false); g_running.store(true); appletSetAutoSleepDisabled(true); g_thread = std::thread(worker, which); } extern "C" void run_furmark_stop(void) { g_stop.store(true); if (g_thread.joinable()) g_thread.join(); g_running.store(false); appletSetAutoSleepDisabled(false); } extern "C" int run_furmark_running(void) { return g_running.load() ? 1 : 0; } extern "C" float bhrt_cpu_fps(void); extern "C" float run_furmark_fps(void) { return g_fps.load(); } extern "C" float run_furmark_cpu_fps(void) { return (g_running.load() && g_which.load() == 3) ? bhrt_cpu_fps() : 0.0f; }