Skip to content

Commit

Permalink
Move Window and Gui calls to port game loop (#787)
Browse files Browse the repository at this point in the history
* Move gui draw calls to be called by ports

* move window manager start_frame logic to is_frame_ready

* call gfx_end_frame from fast3dwindow

* expose handle_events on fast3dwindow

* remove dropped frame handling from gfx_pc

* Add dedicated draw method to fast3d window to encapsulate all drawing logic as a LUS default
  • Loading branch information
Archez authored Jan 11, 2025
1 parent 440c7ad commit 7fc7376
Show file tree
Hide file tree
Showing 12 changed files with 86 additions and 46 deletions.
32 changes: 32 additions & 0 deletions src/graphic/Fast3D/Fast3dWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,38 @@ void Fast3dWindow::StartFrame() {
}

void Fast3dWindow::EndFrame() {
gfx_end_frame();
}

bool Fast3dWindow::IsFrameReady() {
return mWindowManagerApi->is_frame_ready();
}

bool Fast3dWindow::DrawAndRunGraphicsCommands(Gfx* commands, const std::unordered_map<Mtx*, MtxF>& mtxReplacements) {
std::shared_ptr<Window> wnd = Ship::Context::GetInstance()->GetWindow();

// Skip dropped frames
if (!wnd->IsFrameReady()) {
return false;
}

auto gui = wnd->GetGui();
// Setup of the backend frames and draw initial Window and GUI menus
gui->StartDraw();
// Setup game framebuffers to match available window space
gfx_start_frame();
// Execute the games gfx commands
gfx_run(commands, mtxReplacements);
// Renders the game frame buffer to the final window and finishes the GUI
gui->EndDraw();
// Finalize swap buffers
gfx_end_frame();

return true;
}

void Fast3dWindow::HandleEvents() {
mWindowManagerApi->handle_events();
}

void Fast3dWindow::SetCursorVisibility(bool visible) {
Expand Down
5 changes: 5 additions & 0 deletions src/graphic/Fast3D/Fast3dWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "public/bridge/gfxbridge.h"
#include "controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h"

union Gfx;

namespace Fast {
class Fast3dWindow : public Ship::Window {
public:
Expand All @@ -16,6 +18,8 @@ class Fast3dWindow : public Ship::Window {
void Close() override;
void StartFrame() override;
void EndFrame() override;
bool IsFrameReady() override;
void HandleEvents() override;
void SetCursorVisibility(bool visible) override;
uint32_t GetWidth() override;
uint32_t GetHeight() override;
Expand Down Expand Up @@ -46,6 +50,7 @@ class Fast3dWindow : public Ship::Window {
void SetTextureFilter(FilteringMode filteringMode);
void SetRendererUCode(UcodeHandlers ucode);
void EnableSRGBMode();
bool DrawAndRunGraphicsCommands(Gfx* commands, const std::unordered_map<Mtx*, MtxF>& mtxReplacements);

protected:
static bool KeyDown(int32_t scancode);
Expand Down
4 changes: 2 additions & 2 deletions src/graphic/Fast3D/gfx_dxgi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ static uint64_t qpc_to_100ns(uint64_t qpc) {
qpc % dxgi.qpc_freq * _100NANOSECONDS_IN_SECOND / dxgi.qpc_freq;
}

static bool gfx_dxgi_start_frame() {
static bool gfx_dxgi_is_frame_ready() {
DXGI_FRAME_STATISTICS stats;
if (dxgi.swap_chain->GetFrameStatistics(&stats) == S_OK &&
(stats.SyncRefreshCount != 0 || stats.SyncQPCTime.QuadPart != 0ULL)) {
Expand Down Expand Up @@ -1058,7 +1058,7 @@ extern "C" struct GfxWindowManagerAPI gfx_dxgi_api = { gfx_dxgi_init,
gfx_dxgi_is_mouse_captured,
gfx_dxgi_get_dimensions,
gfx_dxgi_handle_events,
gfx_dxgi_start_frame,
gfx_dxgi_is_frame_ready,
gfx_dxgi_swap_buffers_begin,
gfx_dxgi_swap_buffers_end,
gfx_dxgi_get_time,
Expand Down
4 changes: 1 addition & 3 deletions src/graphic/Fast3D/gfx_metal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,13 +234,11 @@ bool Metal_Init(SDL_Renderer* renderer) {

static void gfx_metal_setup_screen_framebuffer(uint32_t width, uint32_t height);

void Metal_SetupFrame(SDL_Renderer* renderer) {
void Metal_NewFrame(SDL_Renderer* renderer) {
int width, height;
SDL_GetRendererOutputSize(renderer, &width, &height);
gfx_metal_setup_screen_framebuffer(width, height);
}

void Metal_NewFrame(SDL_Renderer* renderer) {
MTL::RenderPassDescriptor* current_render_pass = mctx.framebuffers[0].render_pass_descriptor;
ImGui_ImplMetal_NewFrame(current_render_pass);
}
Expand Down
1 change: 0 additions & 1 deletion src/graphic/Fast3D/gfx_metal.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ ImTextureID gfx_metal_get_texture_by_id(int id);
bool Metal_IsSupported();

bool Metal_Init(SDL_Renderer* renderer);
void Metal_SetupFrame(SDL_Renderer* renderer);
void Metal_NewFrame(SDL_Renderer* renderer);
void Metal_SetupFloatingFrame();
void Metal_RenderDrawData(ImDrawData* draw_data);
Expand Down
31 changes: 12 additions & 19 deletions src/graphic/Fast3D/gfx_pc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,6 @@ static int game_framebuffer_msaa_resolved;

uint32_t gfx_msaa_level = 1;

static bool dropped_frame;

static const std::unordered_map<Mtx*, MtxF>* current_mtx_replacements;

static float buf_vbo[MAX_BUFFERED * (32 * 3)]; // 3 vertices in a triangle and 32 floats per vtx
Expand Down Expand Up @@ -4123,8 +4121,15 @@ struct GfxRenderingAPI* gfx_get_current_rendering_api() {
return gfx_rapi;
}

void gfx_start_frame() {
void gfx_handle_window_events() {
gfx_wapi->handle_events();
}

bool gfx_is_frame_ready() {
return gfx_wapi->is_frame_ready();
}

void gfx_start_frame() {
gfx_wapi->get_dimensions(&gfx_current_window_dimensions.width, &gfx_current_window_dimensions.height,
&gfx_current_window_position_x, &gfx_current_window_position_y);
if (gfx_current_dimensions.height == 0) {
Expand Down Expand Up @@ -4184,20 +4189,11 @@ void gfx_start_frame() {
GfxExecStack g_exec_stack = {};

void gfx_run(Gfx* commands, const std::unordered_map<Mtx*, MtxF>& mtx_replacements) {
Ship::Context::GetInstance()->GetWindow()->GetGui()->SetupRendererFrame();

gfx_sp_reset();

get_pixel_depth_pending.clear();
get_pixel_depth_cached.clear();

if (!gfx_wapi->start_frame()) {
dropped_frame = true;
Ship::Context::GetInstance()->GetWindow()->GetGui()->Draw();
return;
}
dropped_frame = false;

current_mtx_replacements = &mtx_replacements;

gfx_rapi->update_framebuffer_parameters(0, gfx_current_window_dimensions.width,
Expand Down Expand Up @@ -4261,16 +4257,13 @@ void gfx_run(Gfx* commands, const std::unordered_map<Mtx*, MtxF>& mtx_replacemen

assert(0 && "active framebuffer was never reset back to original");
}
Ship::Context::GetInstance()->GetWindow()->GetGui()->Draw();
gfx_rapi->end_frame();
gfx_wapi->swap_buffers_begin();
}

void gfx_end_frame() {
if (!dropped_frame) {
gfx_rapi->finish_render();
gfx_wapi->swap_buffers_end();
}
gfx_rapi->end_frame();
gfx_wapi->swap_buffers_begin();
gfx_rapi->finish_render();
gfx_wapi->swap_buffers_end();
}

void gfx_set_target_ucode(UcodeHandlers ucode) {
Expand Down
2 changes: 2 additions & 0 deletions src/graphic/Fast3D/gfx_pc.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ void gfx_start_frame();

// Since this function is "exposted" to the games, it needs to take a normal Gfx
void gfx_run(Gfx* commands, const std::unordered_map<Mtx*, MtxF>& mtx_replacements);
void gfx_handle_window_events();
bool gfx_is_frame_ready();
void gfx_end_frame();
void gfx_set_target_ucode(UcodeHandlers ucode);
void gfx_set_target_fps(int);
Expand Down
4 changes: 2 additions & 2 deletions src/graphic/Fast3D/gfx_sdl2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ static void gfx_sdl_handle_events() {
}
}

static bool gfx_sdl_start_frame() {
static bool gfx_sdl_is_frame_ready() {
return true;
}

Expand Down Expand Up @@ -709,7 +709,7 @@ struct GfxWindowManagerAPI gfx_sdl = { gfx_sdl_init,
gfx_sdl_is_mouse_captured,
gfx_sdl_get_dimensions,
gfx_sdl_handle_events,
gfx_sdl_start_frame,
gfx_sdl_is_frame_ready,
gfx_sdl_swap_buffers_begin,
gfx_sdl_swap_buffers_end,
gfx_sdl_get_time,
Expand Down
2 changes: 1 addition & 1 deletion src/graphic/Fast3D/gfx_window_manager_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct GfxWindowManagerAPI {
bool (*is_mouse_captured)();
void (*get_dimensions)(uint32_t* width, uint32_t* height, int32_t* posX, int32_t* posY);
void (*handle_events)();
bool (*start_frame)();
bool (*is_frame_ready)();
void (*swap_buffers_begin)();
void (*swap_buffers_end)();
double (*get_time)(); // For debug
Expand Down
2 changes: 2 additions & 0 deletions src/window/Window.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class Window {
virtual void Close() = 0;
virtual void StartFrame() = 0;
virtual void EndFrame() = 0;
virtual bool IsFrameReady() = 0;
virtual void HandleEvents() = 0;
virtual void SetCursorVisibility(bool visible) = 0;
virtual uint32_t GetWidth() = 0;
virtual uint32_t GetHeight() = 0;
Expand Down
40 changes: 24 additions & 16 deletions src/window/gui/Gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ void Gui::EndFrame() {
ImGui::EndFrame();
}

void Gui::DrawGame() {
void Gui::CalculateGameViewport() {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_ChildBorderSize, 0.0f);
Expand Down Expand Up @@ -617,10 +617,25 @@ void Gui::DrawGame() {
}
}

ImGui::End();
}

void Gui::DrawGame() {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_ChildBorderSize, 0.0f);
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBackground;

ImGui::Begin("Main Game", nullptr, flags);
ImGui::PopStyleVar(3);
ImGui::PopStyleColor();

GetGameOverlay()->Draw();

mainPos = ImGui::GetWindowPos();
size = ImGui::GetContentRegionAvail();
ImVec2 mainPos = ImGui::GetWindowPos();
ImVec2 size = ImGui::GetContentRegionAvail();
ImVec2 pos = ImVec2(0, 0);
if (CVarGetInteger(CVAR_LOW_RES_MODE, 0) == 1) { // N64 Mode takes priority
const float sw = size.y * 320.0f / 240.0f;
Expand Down Expand Up @@ -695,11 +710,16 @@ void Gui::CheckSaveCvars() {
}
}

void Gui::Draw() {
void Gui::StartDraw() {
// Initialize the frame.
StartFrame();
// Draw the gui menus
DrawMenu();
// Calculate the available space the game can render to
CalculateGameViewport();
}

void Gui::EndDraw() {
// Draw the game framebuffer into ImGui
DrawGame();
// End the frame
Expand All @@ -710,18 +730,6 @@ void Gui::Draw() {
CheckSaveCvars();
}

void Gui::SetupRendererFrame() {
switch (Context::GetInstance()->GetWindow()->GetWindowBackend()) {
#ifdef __APPLE__
case WindowBackend::FAST3D_SDL_METAL:
Metal_SetupFrame(mImpl.Metal.Renderer);
break;
#endif
default:
break;
}
}

ImTextureID Gui::GetTextureById(int32_t id) {
#ifdef ENABLE_DX11
if (Context::GetInstance()->GetWindow()->GetWindowBackend() == WindowBackend::FAST3D_DXGI_DX11) {
Expand Down
5 changes: 3 additions & 2 deletions src/window/gui/Gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ class Gui {
~Gui();

void Init(GuiWindowInitData windowImpl);
void Draw();
void StartDraw();
void EndDraw();
void HandleWindowEvents(WindowEvent event);
void SetupRendererFrame();
void SaveConsoleVariablesNextFrame();
bool SupportsViewports();
ImGuiID GetMainGameWindowID();
Expand Down Expand Up @@ -112,6 +112,7 @@ class Gui {
void DrawFloatingWindows();
void DrawMenu();
void DrawGame();
void CalculateGameViewport();

void ImGuiBackendNewFrame();
void ImGuiWMNewFrame();
Expand Down

0 comments on commit 7fc7376

Please sign in to comment.