Skip to content

Commit

Permalink
Dear ImGui Implementation (shadps4-emu#598)
Browse files Browse the repository at this point in the history
* added imgui as dependency

* imgui renderer/basic input implementation

* imgui: add layers system

Add video info layer to show fps. Press F10 to toggle it.

* imgui: add custom imgui config

* imgui: gamepad capture, stopping propagation

* imgui: changed config & log file path to use portable dir

* videoout: render blank frame when video output is closed

required to render imgui even when game has no video output

- fixed merge compile-error
  • Loading branch information
viniciuslrangel authored Sep 8, 2024
1 parent f1becb2 commit 035cb3e
Show file tree
Hide file tree
Showing 23 changed files with 2,386 additions and 8 deletions.
5 changes: 5 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,8 @@
[submodule "externals/half"]
path = externals/half
url = https://github.com/ROCm/half.git
[submodule "externals/dear_imgui"]
path = externals/dear_imgui
url = https://github.com/shadps4-emu/ext-imgui.git
shallow = true
branch = docking
19 changes: 18 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,18 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
src/video_core/renderdoc.h
)

set(IMGUI src/imgui/imgui_config.h
src/imgui/imgui_layer.h
src/imgui/layer/video_info.cpp
src/imgui/layer/video_info.h
src/imgui/renderer/imgui_core.cpp
src/imgui/renderer/imgui_core.h
src/imgui/renderer/imgui_impl_sdl3.cpp
src/imgui/renderer/imgui_impl_sdl3.h
src/imgui/renderer/imgui_impl_vulkan.cpp
src/imgui/renderer/imgui_impl_vulkan.h
)

set(INPUT src/input/controller.cpp
src/input/controller.h
)
Expand Down Expand Up @@ -617,6 +629,7 @@ endif()
if (ENABLE_QT_GUI)
qt_add_executable(shadps4
${AUDIO_CORE}
${IMGUI}
${INPUT}
${QT_GUI}
${COMMON}
Expand All @@ -629,6 +642,7 @@ if (ENABLE_QT_GUI)
else()
add_executable(shadps4
${AUDIO_CORE}
${IMGUI}
${INPUT}
${COMMON}
${CORE}
Expand All @@ -645,9 +659,12 @@ endif()

create_target_directory_groups(shadps4)

target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg)
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui)
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::SPIRV glslang::glslang SDL3::SDL3)

target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h")

if (APPLE)
option(USE_SYSTEM_VULKAN_LOADER "Enables using the system Vulkan loader instead of directly linking with MoltenVK. Useful for loading validation layers." OFF)
if (USE_SYSTEM_VULKAN_LOADER)
Expand Down
11 changes: 11 additions & 0 deletions externals/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,17 @@ if (APPLE)
endif()
endif()

# Dear ImGui
add_library(Dear_ImGui
dear_imgui/imgui.cpp
dear_imgui/imgui_demo.cpp
dear_imgui/imgui_draw.cpp
dear_imgui/imgui_internal.h
dear_imgui/imgui_tables.cpp
dear_imgui/imgui_widgets.cpp
)
target_include_directories(Dear_ImGui INTERFACE dear_imgui/)

# Tracy
option(TRACY_ENABLE "" ON)
option(TRACY_NO_CRASH_HANDLER "" ON) # Otherwise texture cache exceptions will be treaten as a crash
Expand Down
1 change: 1 addition & 0 deletions externals/dear_imgui
Submodule dear_imgui added at 636cd4
5 changes: 5 additions & 0 deletions src/common/assert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ void assert_fail_impl() {
Crash();
throw std::runtime_error("Unreachable code");
}

void assert_fail_debug_msg(const char* msg) {
LOG_CRITICAL(Debug, "Assertion Failed!\n{}", msg);
assert_fail_impl();
}
1 change: 1 addition & 0 deletions src/common/logging/filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
CLS(Render) \
SUB(Render, Vulkan) \
SUB(Render, Recompiler) \
CLS(ImGui) \
CLS(Input) \
CLS(Tty) \
CLS(Loader)
Expand Down
1 change: 1 addition & 0 deletions src/common/logging/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ enum class Class : u8 {
Render, ///< Video Core
Render_Vulkan, ///< Vulkan backend
Render_Recompiler, ///< Shader recompiler
ImGui, ///< ImGui
Loader, ///< ROM loader
Input, ///< Input emulation
Tty, ///< Debug output from emu
Expand Down
18 changes: 13 additions & 5 deletions src/core/libraries/videoout/driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,6 @@ int VideoOutDriver::UnregisterBuffers(VideoOutPort* port, s32 attributeIndex) {
}

std::chrono::microseconds VideoOutDriver::Flip(const Request& req) {
if (!req) {
return std::chrono::microseconds{0};
}

const auto start = std::chrono::high_resolution_clock::now();

// Whatever the game is rendering show splash if it is active
Expand Down Expand Up @@ -207,6 +203,11 @@ std::chrono::microseconds VideoOutDriver::Flip(const Request& req) {
return std::chrono::duration_cast<std::chrono::microseconds>(end - start);
}

void VideoOutDriver::DrawBlankFrame() {
const auto empty_frame = renderer->PrepareBlankFrame(false);
renderer->Present(empty_frame);
}

bool VideoOutDriver::SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg,
bool is_eop /*= false*/) {
{
Expand Down Expand Up @@ -283,7 +284,14 @@ void VideoOutDriver::PresentThread(std::stop_token token) {
auto& vblank_status = main_port.vblank_status;
if (vblank_status.count % (main_port.flip_rate + 1) == 0) {
const auto request = receive_request();
delay = Flip(request);
if (!request) {
delay = std::chrono::microseconds{0};
if (!main_port.is_open) {
DrawBlankFrame();
}
} else {
delay = Flip(request);
}
FRAME_END;
}

Expand Down
1 change: 1 addition & 0 deletions src/core/libraries/videoout/driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class VideoOutDriver {
};

std::chrono::microseconds Flip(const Request& req);
void DrawBlankFrame(); // Used when there is no flip request to keep ImGui up to date
void SubmitFlipInternal(VideoOutPort* port, s32 index, s64 flip_arg, bool is_eop = false);
void PresentThread(std::stop_token token);

Expand Down
29 changes: 29 additions & 0 deletions src/imgui/imgui_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

// WARNING: All includes from this file must be relative to allow Dear_ImGui project to compile
// without having this project include paths.

#include <cstdint>

extern void assert_fail_debug_msg(const char* msg);

#define ImDrawIdx std::uint32_t

#define IM_STRINGIZE(x) IM_STRINGIZE2(x)
#define IM_STRINGIZE2(x) #x
#define IM_ASSERT(_EXPR) \
([&]() { \
if (!(_EXPR)) [[unlikely]] { \
assert_fail_debug_msg(#_EXPR " at " __FILE__ ":" IM_STRINGIZE(__LINE__)); \
} \
}())

#define IMGUI_USE_WCHAR32
#define IMGUI_ENABLE_STB_TRUETYPE
#define IMGUI_DEFINE_MATH_OPERATORS

#define IM_VEC2_CLASS_EXTRA \
constexpr ImVec2(float _v) : x(_v), y(_v) {}
21 changes: 21 additions & 0 deletions src/imgui/imgui_layer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

namespace ImGui {

class Layer {
public:
virtual ~Layer() = default;
static void AddLayer(Layer* layer);
static void RemoveLayer(Layer* layer);

virtual void Draw() = 0;

virtual bool ShouldGrabGamepad() {
return false;
}
};

} // namespace ImGui
16 changes: 16 additions & 0 deletions src/imgui/layer/video_info.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include <imgui.h>
#include "video_info.h"

void ImGui::Layers::VideoInfo::Draw() {
const ImGuiIO& io = GetIO();

m_show = IsKeyPressed(ImGuiKey_F10, false) ^ m_show;

if (m_show && Begin("Video Info")) {
Text("Frame time: %.3f ms (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
End();
}
}
23 changes: 23 additions & 0 deletions src/imgui/layer/video_info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "imgui/imgui_layer.h"

namespace Vulkan {
class RendererVulkan;
}
namespace ImGui::Layers {

class VideoInfo : public Layer {
bool m_show = false;
::Vulkan::RendererVulkan* renderer{};

public:
explicit VideoInfo(::Vulkan::RendererVulkan* renderer) : renderer(renderer) {}

void Draw() override;
};

} // namespace ImGui::Layers
Loading

0 comments on commit 035cb3e

Please sign in to comment.