add null gpu notice (#3768)

This commit is contained in:
Vinicius Rangel
2025-11-02 14:55:43 -03:00
committed by GitHub
parent caccc05fb2
commit a4c3c665fe
7 changed files with 160 additions and 51 deletions

View File

@@ -617,6 +617,7 @@ set(COMPANION_LIBS src/core/libraries/companion/companion_httpd.cpp
)
set(DEV_TOOLS src/core/devtools/layer.cpp
src/core/devtools/layer.h
src/core/devtools/layer_extra.cpp
src/core/devtools/options.cpp
src/core/devtools/options.h
src/core/devtools/gcn/gcn_context_regs.cpp

View File

@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "layer.h"
@@ -460,12 +460,12 @@ void L::Draw() {
}
void L::TextCentered(const std::string& text) {
float window_width = ImGui::GetWindowSize().x;
float text_width = ImGui::CalcTextSize(text.c_str()).x;
float window_width = GetWindowSize().x;
float text_width = CalcTextSize(text.c_str()).x;
float text_indentation = (window_width - text_width) * 0.5f;
ImGui::SameLine(text_indentation);
ImGui::Text("%s", text.c_str());
SameLine(text_indentation);
Text("%s", text.c_str());
}
namespace Overlay {

View File

@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -9,18 +9,20 @@
namespace Core::Devtools {
class Layer final : public ImGui::Layer {
static void DrawMenuBar();
static void DrawAdvanced();
static void DrawSimple();
public:
static void SetupSettings();
void Draw() override;
void TextCentered(const std::string& text);
// Must be inside a window
static void DrawNullGpuNotice();
private:
static void DrawMenuBar();
static void DrawAdvanced();
static void DrawSimple();
static void TextCentered(const std::string& text);
};
} // namespace Core::Devtools

View File

@@ -0,0 +1,95 @@
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "layer.h"
#include "imgui/imgui_std.h"
#include <imgui.h>
#include <imgui_internal.h>
#include <cmath>
#include <numbers>
namespace Core::Devtools {
void Layer::DrawNullGpuNotice() {
auto* window = ImGui::GetCurrentWindow();
if (window->SkipItems) {
return;
}
constexpr std::string_view mainNotice = "Null GPU is enabled";
constexpr std::string_view detailsNotice =
"Disable the nullGpu config to show the game display";
auto displaySize = window->Size;
ImVec2 targetSize = displaySize * 0.7f;
float minFontSize = 1.0f;
float maxFontSize = 200.0f;
float optimalFontSize = minFontSize;
static auto lastSize = ImVec2(-1, -1);
static float lastFontSize = -1.0f;
auto* font = ImGui::GetIO().Fonts->Fonts[IMGUI_FONT_TEXT_BIG];
if (lastSize != targetSize) {
while (maxFontSize - minFontSize > 0.1f) {
float testFontSize = (minFontSize + maxFontSize) / 2.0f;
ImVec2 textSize = font->CalcTextSizeA(testFontSize, FLT_MAX, 0.0f, &mainNotice.front(),
&mainNotice.back() + 1);
if (textSize.x <= targetSize.x && textSize.y <= targetSize.y) {
optimalFontSize = testFontSize;
minFontSize = testFontSize;
} else {
maxFontSize = testFontSize;
}
}
lastSize = targetSize;
lastFontSize = optimalFontSize;
} else {
optimalFontSize = lastFontSize;
}
ImVec2 textSize = font->CalcTextSizeA(optimalFontSize, FLT_MAX, 0.0f, &mainNotice.front(),
&mainNotice.back() + 1);
ImVec2 textPos = (displaySize - textSize) * 0.5f + window->Pos;
const float scale = optimalFontSize / font->FontSize;
double timeAnim = -std::numbers::pi * ImGui::GetTime();
int i = 0;
for (auto ch : mainNotice) {
double colorTime = sin(timeAnim + i * std::numbers::pi / 6.0) / 2.0 + 0.5;
int color = (int)(200 * colorTime) + 55;
double posTime = sin(timeAnim + i * std::numbers::pi / 15.0) / 2.0 + 0.5;
auto pos = textPos;
pos.y += 10.0 * (posTime < 0.5 ? std::pow(2.0, 20.0 * posTime - 10.0) / 2.0
: (2.0 - std::pow(2.0, -20.0 * posTime + 10.0)) / 2.0);
window->DrawList->AddText(font, optimalFontSize, pos, IM_COL32(color, color, color, 255),
&ch, &ch + 1);
textPos.x += font->FindGlyph(ch)->AdvanceX * scale;
i++;
}
font = ImGui::GetIO().Fonts->Fonts[IMGUI_FONT_TEXT];
textPos.y += textSize.y + 1.0;
optimalFontSize *= 0.2;
textSize = font->CalcTextSizeA(optimalFontSize, FLT_MAX, 0.0f, &detailsNotice.front(),
&detailsNotice.back() + 1);
textPos.x = window->Pos.x + (window->Size.x - textSize.x) * 0.5f;
window->DrawList->AddText(font, optimalFontSize, textPos, IM_COL32(200, 200, 200, 255),
&detailsNotice.front(), &detailsNotice.back() + 1);
}
} // namespace Core::Devtools

View File

@@ -3,6 +3,8 @@
#pragma once
#include "common/types.h"
#include <cmath>
#include <imgui.h>
@@ -12,6 +14,7 @@
#define IMGUI_FONT_TEXT 0
#define IMGUI_FONT_MONO 1
#define IMGUI_FONT_TEXT_BIG 2
namespace ImGui {

View File

@@ -76,10 +76,15 @@ void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& w
font_cfg.OversampleV = 1;
io.FontDefault = io.Fonts->AddFontFromMemoryCompressedTTF(
imgui_font_notosansjp_regular_compressed_data,
imgui_font_notosansjp_regular_compressed_size, 16.0f, &font_cfg, ranges.Data);
imgui_font_notosansjp_regular_compressed_size, 32.0f, &font_cfg, ranges.Data);
io.Fonts->AddFontFromMemoryCompressedTTF(imgui_font_proggyvector_regular_compressed_data,
imgui_font_proggyvector_regular_compressed_size,
16.0f);
32.0f);
io.Fonts->AddFontFromMemoryCompressedTTF(imgui_font_notosansjp_regular_compressed_data,
imgui_font_notosansjp_regular_compressed_size, 128.0f,
&font_cfg, ranges.Data);
io.FontGlobalScale = 0.5f;
StyleColorsDark();
@@ -110,7 +115,7 @@ void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& w
dock_id = ImHashStr(label);
if (const auto dpi = SDL_GetWindowDisplayScale(window.GetSDLWindow()); dpi > 0.0f) {
GetIO().FontGlobalScale = dpi;
GetIO().FontGlobalScale *= dpi;
}
std::at_quick_exit([] { SaveIniSettingsToDisk(GetIO().IniFilename); });

View File

@@ -539,45 +539,48 @@ void Presenter::Present(Frame* frame, bool is_reusing_frame) {
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
ImGui::SetNextWindowDockID(dockId, ImGuiCond_Once);
ImGui::Begin("Display##game_display", nullptr, ImGuiWindowFlags_NoNav);
if (ImGui::Begin("Display##game_display", nullptr, ImGuiWindowFlags_NoNav)) {
auto game_texture = frame->imgui_texture;
auto game_width = frame->width;
auto game_height = frame->height;
auto game_texture = frame->imgui_texture;
auto game_width = frame->width;
auto game_height = frame->height;
if (Libraries::SystemService::IsSplashVisible()) { // draw splash
if (!splash_img.has_value()) {
splash_img.emplace();
auto splash_path = Common::ElfInfo::Instance().GetSplashPath();
if (!splash_path.empty()) {
splash_img = ImGui::RefCountedTexture::DecodePngFile(splash_path);
if (Libraries::SystemService::IsSplashVisible()) { // draw splash
if (!splash_img.has_value()) {
splash_img.emplace();
auto splash_path = Common::ElfInfo::Instance().GetSplashPath();
if (!splash_path.empty()) {
splash_img = ImGui::RefCountedTexture::DecodePngFile(splash_path);
}
}
if (auto& splash_image = this->splash_img.value()) {
auto [im_id, width, height] = splash_image.GetTexture();
game_texture = im_id;
game_width = width;
game_height = height;
}
}
if (auto& splash_image = this->splash_img.value()) {
auto [im_id, width, height] = splash_image.GetTexture();
game_texture = im_id;
game_width = width;
game_height = height;
ImVec2 contentArea = ImGui::GetContentRegionAvail();
SetExpectedGameSize((s32)contentArea.x, (s32)contentArea.y);
const auto imgRect =
FitImage(game_width, game_height, (s32)contentArea.x, (s32)contentArea.y);
ImVec2 offset{
static_cast<float>(imgRect.offset.x),
static_cast<float>(imgRect.offset.y),
};
ImVec2 size{
static_cast<float>(imgRect.extent.width),
static_cast<float>(imgRect.extent.height),
};
ImGui::SetCursorPos(ImGui::GetCursorStartPos() + offset);
ImGui::Image(game_texture, size);
if (Config::nullGpu()) {
Core::Devtools::Layer::DrawNullGpuNotice();
}
}
ImVec2 contentArea = ImGui::GetContentRegionAvail();
SetExpectedGameSize((s32)contentArea.x, (s32)contentArea.y);
const auto imgRect =
FitImage(game_width, game_height, (s32)contentArea.x, (s32)contentArea.y);
ImVec2 offset{
static_cast<float>(imgRect.offset.x),
static_cast<float>(imgRect.offset.y),
};
ImVec2 size{
static_cast<float>(imgRect.extent.width),
static_cast<float>(imgRect.extent.height),
};
ImGui::SetCursorPos(ImGui::GetCursorStartPos() + offset);
ImGui::Image(game_texture, size);
ImGui::End();
ImGui::PopStyleVar(3);
ImGui::PopStyleColor();