mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-02 15:32:52 +00:00
imgui: add layers system
Add video info layer to show fps. Press F10 to toggle it.
This commit is contained in:
parent
de08bbc75d
commit
60d8f41181
@ -561,12 +561,15 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
|
|||||||
src/video_core/renderdoc.h
|
src/video_core/renderdoc.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(IMGUI src/imgui_renderer/imgui_core.cpp
|
set(IMGUI src/imgui/imgui_layer.h
|
||||||
src/imgui_renderer/imgui_core.h
|
src/imgui/layer/video_info.cpp
|
||||||
src/imgui_renderer/imgui_impl_sdl3.cpp
|
src/imgui/layer/video_info.h
|
||||||
src/imgui_renderer/imgui_impl_sdl3.h
|
src/imgui/renderer/imgui_core.cpp
|
||||||
src/imgui_renderer/imgui_impl_vulkan.cpp
|
src/imgui/renderer/imgui_core.h
|
||||||
src/imgui_renderer/imgui_impl_vulkan.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
|
set(INPUT src/input/controller.cpp
|
||||||
|
17
src/imgui/imgui_layer.h
Normal file
17
src/imgui/imgui_layer.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ImGui
|
16
src/imgui/layer/video_info.cpp
Normal file
16
src/imgui/layer/video_info.cpp
Normal file
@ -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
src/imgui/layer/video_info.h
Normal file
23
src/imgui/layer/video_info.h
Normal file
@ -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
|
@ -4,6 +4,7 @@
|
|||||||
#include <SDL3/SDL_events.h>
|
#include <SDL3/SDL_events.h>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include "common/config.h"
|
#include "common/config.h"
|
||||||
|
#include "imgui/imgui_layer.h"
|
||||||
#include "imgui_core.h"
|
#include "imgui_core.h"
|
||||||
#include "imgui_impl_sdl3.h"
|
#include "imgui_impl_sdl3.h"
|
||||||
#include "imgui_impl_vulkan.h"
|
#include "imgui_impl_vulkan.h"
|
||||||
@ -14,22 +15,32 @@ static void CheckVkResult(const vk::Result err) {
|
|||||||
LOG_ERROR(ImGui, "Vulkan error {}", vk::to_string(err));
|
LOG_ERROR(ImGui, "Vulkan error {}", vk::to_string(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ImGui::Emulator {
|
static std::vector<ImGui::Layer*> layers;
|
||||||
|
|
||||||
|
// Update layers before rendering to allow layer changes to be applied during rendering.
|
||||||
|
// Using deque to keep the order of changes in case a Layer is removed then added again between
|
||||||
|
// frames.
|
||||||
|
static std::deque<std::pair<bool, ImGui::Layer*>> change_layers;
|
||||||
|
static std::mutex change_layers_mutex{};
|
||||||
|
|
||||||
|
namespace ImGui {
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
|
||||||
void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& window,
|
void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& window,
|
||||||
const u32 image_count, vk::Format surface_format,
|
const u32 image_count, vk::Format surface_format,
|
||||||
const vk::AllocationCallbacks* allocator) {
|
const vk::AllocationCallbacks* allocator) {
|
||||||
ImGui::CreateContext();
|
CreateContext();
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = GetIO();
|
||||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
|
||||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||||
io.DisplaySize = ImVec2((float)window.getWidth(), (float)window.getHeight());
|
io.DisplaySize = ImVec2((float)window.getWidth(), (float)window.getHeight());
|
||||||
ImGui::StyleColorsDark();
|
StyleColorsDark();
|
||||||
|
|
||||||
Sdl::Init(window.GetSdlWindow());
|
Sdl::Init(window.GetSdlWindow());
|
||||||
|
|
||||||
Vulkan::InitInfo vk_info{
|
const Vulkan::InitInfo vk_info{
|
||||||
.instance = instance.GetInstance(),
|
.instance = instance.GetInstance(),
|
||||||
.physical_device = instance.GetPhysicalDevice(),
|
.physical_device = instance.GetPhysicalDevice(),
|
||||||
.device = instance.GetDevice(),
|
.device = instance.GetDevice(),
|
||||||
@ -48,7 +59,6 @@ void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& w
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OnResize() {
|
void OnResize() {
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
|
||||||
Sdl::OnResize();
|
Sdl::OnResize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,11 +67,11 @@ void Shutdown(const vk::Device& device) {
|
|||||||
|
|
||||||
Vulkan::Shutdown();
|
Vulkan::Shutdown();
|
||||||
Sdl::Shutdown();
|
Sdl::Shutdown();
|
||||||
ImGui::DestroyContext();
|
DestroyContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProcessEvent(SDL_Event* event) {
|
bool ProcessEvent(SDL_Event* event) {
|
||||||
bool used = Sdl::ProcessEvent(event);
|
const bool used = Sdl::ProcessEvent(event);
|
||||||
if (!used) {
|
if (!used) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -70,34 +80,43 @@ bool ProcessEvent(SDL_Event* event) {
|
|||||||
case SDL_EVENT_MOUSE_WHEEL:
|
case SDL_EVENT_MOUSE_WHEEL:
|
||||||
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||||
case SDL_EVENT_MOUSE_BUTTON_UP:
|
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||||
return ImGui::GetIO().WantCaptureMouse;
|
return GetIO().WantCaptureMouse;
|
||||||
case SDL_EVENT_TEXT_INPUT:
|
case SDL_EVENT_TEXT_INPUT:
|
||||||
case SDL_EVENT_KEY_DOWN:
|
case SDL_EVENT_KEY_DOWN:
|
||||||
case SDL_EVENT_KEY_UP:
|
case SDL_EVENT_KEY_UP:
|
||||||
return ImGui::GetIO().WantCaptureKeyboard;
|
return GetIO().WantCaptureKeyboard;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewFrame() {
|
void NewFrame() {
|
||||||
|
{
|
||||||
|
std::scoped_lock lock{change_layers_mutex};
|
||||||
|
while (!change_layers.empty()) {
|
||||||
|
const auto [to_be_added, layer] = change_layers.front();
|
||||||
|
if (to_be_added) {
|
||||||
|
layers.push_back(layer);
|
||||||
|
} else {
|
||||||
|
const auto [begin, end] = std::ranges::remove(layers, layer);
|
||||||
|
layers.erase(begin, end);
|
||||||
|
}
|
||||||
|
change_layers.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Vulkan::NewFrame();
|
Vulkan::NewFrame();
|
||||||
Sdl::NewFrame();
|
Sdl::NewFrame();
|
||||||
const auto& io = ImGui::GetIO();
|
|
||||||
|
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
|
|
||||||
ImGui::ShowDemoWindow();
|
for (auto* layer : layers) {
|
||||||
if (ImGui::Begin("Frame timings")) {
|
layer->Draw();
|
||||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate,
|
|
||||||
io.Framerate);
|
|
||||||
ImGui::End();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Render(const vk::CommandBuffer& cmdbuf, ::Vulkan::Frame* frame) {
|
void Render(const vk::CommandBuffer& cmdbuf, ::Vulkan::Frame* frame) {
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
ImDrawData* draw_data = ImGui::GetDrawData();
|
ImDrawData* draw_data = GetDrawData();
|
||||||
if (draw_data->CmdListsCount == 0) {
|
if (draw_data->CmdListsCount == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -150,4 +169,16 @@ void Render(const vk::CommandBuffer& cmdbuf, ::Vulkan::Frame* frame) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ImGui::Emulator
|
} // namespace Core
|
||||||
|
|
||||||
|
void Layer::AddLayer(Layer* layer) {
|
||||||
|
std::scoped_lock lock{change_layers_mutex};
|
||||||
|
change_layers.emplace_back(true, layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Layer::RemoveLayer(Layer* layer) {
|
||||||
|
std::scoped_lock lock{change_layers_mutex};
|
||||||
|
change_layers.emplace_back(false, layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ImGui
|
@ -12,7 +12,7 @@ namespace Vulkan {
|
|||||||
struct Frame;
|
struct Frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ImGui::Emulator {
|
namespace ImGui::Core {
|
||||||
|
|
||||||
void Initialize(const Vulkan::Instance& instance, const Frontend::WindowSDL& window,
|
void Initialize(const Vulkan::Instance& instance, const Frontend::WindowSDL& window,
|
||||||
u32 image_count, vk::Format surface_format,
|
u32 image_count, vk::Format surface_format,
|
||||||
@ -28,4 +28,4 @@ void NewFrame();
|
|||||||
|
|
||||||
void Render(const vk::CommandBuffer& cmdbuf, Vulkan::Frame* frame);
|
void Render(const vk::CommandBuffer& cmdbuf, Vulkan::Frame* frame);
|
||||||
|
|
||||||
} // namespace ImGui::Emulator
|
} // namespace ImGui::Core
|
@ -15,7 +15,7 @@
|
|||||||
#ifndef WIN32_LEAN_AND_MEAN
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#endif
|
#endif
|
||||||
#include <windows.h>
|
#include <Windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace ImGui::Sdl {
|
namespace ImGui::Sdl {
|
@ -6,7 +6,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define VULKAN_HPP_NO_EXCEPTIONS
|
#define VULKAN_HPP_NO_EXCEPTIONS
|
||||||
#include <video_core/renderer_vulkan/vk_common.h>
|
#include "video_core/renderer_vulkan/vk_common.h"
|
||||||
|
|
||||||
struct ImDrawData;
|
struct ImDrawData;
|
||||||
|
|
@ -9,7 +9,7 @@
|
|||||||
#include "common/config.h"
|
#include "common/config.h"
|
||||||
#include "common/version.h"
|
#include "common/version.h"
|
||||||
#include "core/libraries/pad/pad.h"
|
#include "core/libraries/pad/pad.h"
|
||||||
#include "imgui_renderer/imgui_core.h"
|
#include "imgui/renderer/imgui_core.h"
|
||||||
#include "input/controller.h"
|
#include "input/controller.h"
|
||||||
#include "sdl_window.h"
|
#include "sdl_window.h"
|
||||||
#include "video_core/renderdoc.h"
|
#include "video_core/renderdoc.h"
|
||||||
@ -81,7 +81,7 @@ void WindowSDL::waitEvent() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::Emulator::ProcessEvent(&event)) {
|
if (ImGui::Core::ProcessEvent(&event)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ void WindowSDL::waitEvent() {
|
|||||||
|
|
||||||
void WindowSDL::onResize() {
|
void WindowSDL::onResize() {
|
||||||
SDL_GetWindowSizeInPixels(window, &width, &height);
|
SDL_GetWindowSizeInPixels(window, &width, &height);
|
||||||
ImGui::Emulator::OnResize();
|
ImGui::Core::OnResize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowSDL::onKeyPress(const SDL_Event* event) {
|
void WindowSDL::onKeyPress(const SDL_Event* event) {
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include "common/singleton.h"
|
#include "common/singleton.h"
|
||||||
#include "core/file_format/splash.h"
|
#include "core/file_format/splash.h"
|
||||||
#include "core/libraries/system/systemservice.h"
|
#include "core/libraries/system/systemservice.h"
|
||||||
#include "imgui_renderer/imgui_core.h"
|
#include "imgui/renderer/imgui_core.h"
|
||||||
#include "sdl_window.h"
|
#include "sdl_window.h"
|
||||||
#include "video_core/renderer_vulkan/renderer_vulkan.h"
|
#include "video_core/renderer_vulkan/renderer_vulkan.h"
|
||||||
#include "video_core/renderer_vulkan/vk_rasterizer.h"
|
#include "video_core/renderer_vulkan/vk_rasterizer.h"
|
||||||
@ -74,7 +74,7 @@ RendererVulkan::RendererVulkan(Frontend::WindowSDL& window_, AmdGpu::Liverpool*
|
|||||||
draw_scheduler{instance}, present_scheduler{instance}, flip_scheduler{instance},
|
draw_scheduler{instance}, present_scheduler{instance}, flip_scheduler{instance},
|
||||||
swapchain{instance, window},
|
swapchain{instance, window},
|
||||||
rasterizer{std::make_unique<Rasterizer>(instance, draw_scheduler, liverpool)},
|
rasterizer{std::make_unique<Rasterizer>(instance, draw_scheduler, liverpool)},
|
||||||
texture_cache{rasterizer->GetTextureCache()} {
|
texture_cache{rasterizer->GetTextureCache()}, video_info_ui{this} {
|
||||||
const u32 num_images = swapchain.GetImageCount();
|
const u32 num_images = swapchain.GetImageCount();
|
||||||
const vk::Device device = instance.GetDevice();
|
const vk::Device device = instance.GetDevice();
|
||||||
|
|
||||||
@ -87,10 +87,12 @@ RendererVulkan::RendererVulkan(Frontend::WindowSDL& window_, AmdGpu::Liverpool*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup ImGui
|
// Setup ImGui
|
||||||
ImGui::Emulator::Initialize(instance, window, num_images, swapchain.GetSurfaceFormat().format);
|
ImGui::Core::Initialize(instance, window, num_images, swapchain.GetSurfaceFormat().format);
|
||||||
|
ImGui::Layer::AddLayer(&video_info_ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
RendererVulkan::~RendererVulkan() {
|
RendererVulkan::~RendererVulkan() {
|
||||||
|
ImGui::Layer::RemoveLayer(&video_info_ui);
|
||||||
draw_scheduler.Finish();
|
draw_scheduler.Finish();
|
||||||
const vk::Device device = instance.GetDevice();
|
const vk::Device device = instance.GetDevice();
|
||||||
for (auto& frame : present_frames) {
|
for (auto& frame : present_frames) {
|
||||||
@ -98,7 +100,7 @@ RendererVulkan::~RendererVulkan() {
|
|||||||
device.destroyImageView(frame.image_view);
|
device.destroyImageView(frame.image_view);
|
||||||
device.destroyFence(frame.present_done);
|
device.destroyFence(frame.present_done);
|
||||||
}
|
}
|
||||||
ImGui::Emulator::Shutdown(device);
|
ImGui::Core::Shutdown(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererVulkan::RecreateFrame(Frame* frame, u32 width, u32 height) {
|
void RendererVulkan::RecreateFrame(Frame* frame, u32 width, u32 height) {
|
||||||
@ -259,7 +261,7 @@ Frame* RendererVulkan::PrepareFrameInternal(VideoCore::Image& image, bool is_eop
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RendererVulkan::Present(Frame* frame) {
|
void RendererVulkan::Present(Frame* frame) {
|
||||||
ImGui::Emulator::NewFrame();
|
ImGui::Core::NewFrame();
|
||||||
|
|
||||||
swapchain.AcquireNextImage();
|
swapchain.AcquireNextImage();
|
||||||
|
|
||||||
@ -324,7 +326,7 @@ void RendererVulkan::Present(Frame* frame) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
ImGui::Emulator::Render(cmdbuf, frame);
|
ImGui::Core::Render(cmdbuf, frame);
|
||||||
|
|
||||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eColorAttachmentOutput,
|
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eColorAttachmentOutput,
|
||||||
vk::PipelineStageFlagBits::eTransfer,
|
vk::PipelineStageFlagBits::eTransfer,
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
|
||||||
|
#include "imgui/layer/video_info.h"
|
||||||
#include "video_core/amdgpu/liverpool.h"
|
#include "video_core/amdgpu/liverpool.h"
|
||||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||||
@ -103,6 +105,8 @@ private:
|
|||||||
std::condition_variable_any frame_cv;
|
std::condition_variable_any frame_cv;
|
||||||
std::optional<VideoCore::Image> splash_img;
|
std::optional<VideoCore::Image> splash_img;
|
||||||
std::vector<VAddr> vo_buffers_addr;
|
std::vector<VAddr> vo_buffers_addr;
|
||||||
|
|
||||||
|
ImGui::Layers::VideoInfo video_info_ui;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
Loading…
Reference in New Issue
Block a user