mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
graphics: address performance regression with Image Resize (#504)
## Link to GitHub Issue, if one exists Regressed by #401 ## Description of change Two things from testing SDVX Live2D - 1. ColorFill is almost always too expensive and will lead to drops 1. Scale factor of 0.5 causes GPU to sync and causes drops (ARGB/XRGB doesn't matter, linear filtering doesn't matter) 1 is fixed by removing ColorFill calls on every frame - instead only do this once when the user changes the duplicate option (on the next frame) 2 is fixed by updating the UI (limit the slider) though people can ctrl+click to override these slider limits. The warning label will be kept with slightly reworded text. ## Testing tested in sdvx eg final (sudden death) - on my RTX 4070, my FPS is rock solid 120 fps even with image resize on now.
This commit is contained in:
@@ -81,18 +81,7 @@ namespace cfg {
|
||||
|
||||
load_bool_value(doc, root + "enable_screen_resize", this->enable_screen_resize);
|
||||
if (this->enable_screen_resize) {
|
||||
if (avs::game::is_model("KFC")) {
|
||||
log_warning(
|
||||
"ScreenResize",
|
||||
"Image Resize feature enabled for SDVX; enabling this is known to significantly "
|
||||
"lower framerate for songs with Live2D!");
|
||||
deferredlogs::defer_error_messages({
|
||||
"Image Resize + SDVX Live2D performance warning",
|
||||
" Enabling Image Resize feature is known to have significant impact",
|
||||
" on Live2D performance; you should disable it"});
|
||||
} else {
|
||||
log_misc("ScreenResize", "enabled by config file");
|
||||
}
|
||||
log_misc("ScreenResize", "enabled by config file");
|
||||
}
|
||||
|
||||
load_bool_value(doc, root + "enable_linear_filter", this->enable_linear_filter);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
@@ -51,6 +52,9 @@ namespace cfg {
|
||||
bool enable_linear_filter = true;
|
||||
fullscreen_setting scene_settings[4];
|
||||
|
||||
// state
|
||||
std::atomic<bool> need_surface_clean = false;
|
||||
|
||||
// windowed mode sizing
|
||||
// Windows terminology:
|
||||
// window = rectangle including the frame
|
||||
|
||||
@@ -742,14 +742,12 @@ void SurfaceHook(IDirect3DDevice9 *pReal) {
|
||||
const int w = param.BackBufferWidth;
|
||||
const int h = param.BackBufferHeight;
|
||||
|
||||
if (cfg::SCREENRESIZE->enable_screen_resize) {
|
||||
RECT rect {
|
||||
0,
|
||||
0,
|
||||
(LONG)topSurface_width,
|
||||
(LONG)topSurface_height,
|
||||
};
|
||||
pReal->ColorFill(topSurface, &rect, D3DCOLOR_XRGB(0, 0, 0));
|
||||
// this code used to clear the surface using ColorFill on every call, but
|
||||
// this turned out to be very expensive, leading to major frame drops in
|
||||
// SDVX Live2D scenario
|
||||
if (cfg::SCREENRESIZE->need_surface_clean) {
|
||||
pReal->ColorFill(topSurface, nullptr, D3DCOLOR_XRGB(0, 0, 0));
|
||||
cfg::SCREENRESIZE->need_surface_clean = false;
|
||||
}
|
||||
|
||||
D3DLOCKED_RECT rect;
|
||||
|
||||
@@ -103,12 +103,16 @@ namespace overlay::windows {
|
||||
|
||||
if (avs::game::is_model("KFC")) {
|
||||
ImGui::TextColored(ImVec4(1, 0.5f, 0.5f, 1.f),
|
||||
"Warning: Enabling Image Resize will significantly\n"
|
||||
"lower framerate for songs with Live2D!");
|
||||
"Warning: Enabling Image Resize uses more GPU\n"
|
||||
"resources and may significantly lower framerate\n"
|
||||
"for songs with Live2D! Results may vary, use at\n"
|
||||
"your own risk.");
|
||||
} else {
|
||||
ImGui::TextColored(ImVec4(1, 0.5f, 0.5f, 1.f),
|
||||
"Warning: Some games are known to have significant\n"
|
||||
"performance issues when Image Resize is enabled.");
|
||||
"Warning: Enabling Image Resize uses more GPU\n"
|
||||
"resources and may significantly lower framerate\n"
|
||||
"in some situations! Results may vary, use at\n"
|
||||
"your own risk.");
|
||||
}
|
||||
|
||||
// enable checkbox
|
||||
@@ -152,22 +156,27 @@ namespace overlay::windows {
|
||||
// aspect ratio
|
||||
ImGui::Checkbox("Keep Aspect Ratio", &scene.keep_aspect_ratio);
|
||||
if (scene.keep_aspect_ratio) {
|
||||
if (ImGui::SliderFloat("Scale", &scene.scale_x, 0.5f, 2.5f)) {
|
||||
|
||||
// we want to avoid zooming out below 0.6 as it will cause StretchRect calls to
|
||||
// go on a slow sync path with the GPU, leading to frame drops in some situations
|
||||
// (e.g., SDVX Live2D)
|
||||
|
||||
if (ImGui::SliderFloat("Scale", &scene.scale_x, 0.6f, 2.5f)) {
|
||||
scene.scale_y = scene.scale_x;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::HelpMarker("Hint: ctrl + click on the slider to type in a numeric value.");
|
||||
} else {
|
||||
ImGui::SliderFloat("Width Scale", &scene.scale_x, 0.5f, 2.5f);
|
||||
ImGui::SliderFloat("Width Scale", &scene.scale_x, 0.6f, 2.5f);
|
||||
ImGui::SameLine();
|
||||
ImGui::HelpMarker("Hint: ctrl + click on the slider to type in a numeric value.");
|
||||
ImGui::SliderFloat("Height Scale", &scene.scale_y, 0.5f, 2.5f);
|
||||
ImGui::SliderFloat("Height Scale", &scene.scale_y, 0.6f, 2.5f);
|
||||
ImGui::SameLine();
|
||||
ImGui::HelpMarker("Hint: ctrl + click on the slider to type in a numeric value.");
|
||||
}
|
||||
|
||||
static const char* dupe_items[] = { "None", "Copy Left", "Copy Right" };
|
||||
ImGui::Combo(
|
||||
const bool duplicate_changed = ImGui::Combo(
|
||||
"Duplicate",
|
||||
reinterpret_cast<int *>(&scene.duplicate),
|
||||
dupe_items,
|
||||
@@ -178,6 +187,11 @@ namespace overlay::windows {
|
||||
"wrap-around effect when an offset is set.");
|
||||
|
||||
ImGui::EndDisabled();
|
||||
|
||||
// tell d3d9 device to clear surface to get rid of ghost image
|
||||
if (duplicate_changed) {
|
||||
cfg::SCREENRESIZE->need_surface_clean = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenResize::build_windowed_config() {
|
||||
|
||||
Reference in New Issue
Block a user