diff --git a/scripts/check_regression_tests.py b/scripts/check_regression_tests.py index 725ec7746..f26e1fd93 100644 --- a/scripts/check_regression_tests.py +++ b/scripts/check_regression_tests.py @@ -82,10 +82,8 @@ def check_regression_test(baselinedir, testdir, name): write("".format(imguri1, imguri2)) write("") num_diff += 1 - if (num_diff >= 3): - return False - return True + return (num_diff > 0) def check_regression_tests(baselinedir, testdir): diff --git a/scripts/run_regression_tests.py b/scripts/run_regression_tests.py index ec7ec7341..332aff033 100644 --- a/scripts/run_regression_tests.py +++ b/scripts/run_regression_tests.py @@ -15,13 +15,14 @@ def is_game_path(path): return extension in ["cue", "chd"] -def run_regression_test(runner, destdir, dump_interval, frames, gamepath): +def run_regression_test(runner, destdir, dump_interval, frames, renderer, gamepath): args = [runner, "-renderer", "software", - "-log", "verbose", + "-log", "error", "-dumpdir", destdir, "-dumpinterval", str(dump_interval), "-frames", str(frames), + "-renderer", ("Software" if renderer is None else renderer), "--", gamepath ] @@ -29,7 +30,7 @@ def run_regression_test(runner, destdir, dump_interval, frames, gamepath): subprocess.run(args) -def run_regression_tests(runner, gamedir, destdir, dump_interval, frames, parallel=1): +def run_regression_tests(runner, gamedir, destdir, dump_interval, frames, parallel, renderer): paths = glob.glob(gamedir + "/*.*", recursive=True) gamepaths = list(filter(is_game_path, paths)) @@ -44,9 +45,9 @@ def run_regression_tests(runner, gamedir, destdir, dump_interval, frames, parall run_regression_test(runner, destdir, dump_interval, frames, game) else: print("Processing %u games on %u processors" % (len(gamepaths), parallel)) - func = partial(run_regression_test, runner, destdir, dump_interval, frames) + func = partial(run_regression_test, runner, destdir, dump_interval, frames, renderer) pool = multiprocessing.Pool(parallel) - pool.map(func, gamepaths) + pool.map(func, gamepaths, chunksize=1) pool.close() @@ -60,11 +61,12 @@ if __name__ == "__main__": parser.add_argument("-destdir", action="store", required=True, help="Base directory to dump frames to") parser.add_argument("-dumpinterval", action="store", type=int, default=600, help="Interval to dump frames at") parser.add_argument("-frames", action="store", type=int, default=36000, help="Number of frames to run") - parser.add_argument("-parallel", action="store", type=int, default=1, help="Number of proceeses to run") + parser.add_argument("-parallel", action="store", type=int, default=1, help="Number of processes to run") + parser.add_argument("-renderer", action="store", type=str, help="Renderer to use") args = parser.parse_args() - if not run_regression_tests(args.runner, os.path.realpath(args.gamedir), os.path.realpath(args.destdir), args.dumpinterval, args.frames, args.parallel): + if not run_regression_tests(args.runner, os.path.realpath(args.gamedir), os.path.realpath(args.destdir), args.dumpinterval, args.frames, args.parallel, args.renderer): sys.exit(1) else: sys.exit(0) diff --git a/src/duckstation-regtest/CMakeLists.txt b/src/duckstation-regtest/CMakeLists.txt index b03b6a5b7..5555e0918 100644 --- a/src/duckstation-regtest/CMakeLists.txt +++ b/src/duckstation-regtest/CMakeLists.txt @@ -1,6 +1,4 @@ add_executable(duckstation-regtest - regtest_host_display.cpp - regtest_host_display.h regtest_host.cpp ) diff --git a/src/duckstation-regtest/duckstation-regtest.vcxproj b/src/duckstation-regtest/duckstation-regtest.vcxproj index 2eeb8f4bf..a6418adf8 100644 --- a/src/duckstation-regtest/duckstation-regtest.vcxproj +++ b/src/duckstation-regtest/duckstation-regtest.vcxproj @@ -5,12 +5,8 @@ {3029310E-4211-4C87-801A-72E130A648EF} - - - - {ee054e08-3799-4a59-a422-18259c105ffd} diff --git a/src/duckstation-regtest/duckstation-regtest.vcxproj.filters b/src/duckstation-regtest/duckstation-regtest.vcxproj.filters index 83f206b77..9ead085b9 100644 --- a/src/duckstation-regtest/duckstation-regtest.vcxproj.filters +++ b/src/duckstation-regtest/duckstation-regtest.vcxproj.filters @@ -2,9 +2,5 @@ - - - - \ No newline at end of file diff --git a/src/duckstation-regtest/regtest_host.cpp b/src/duckstation-regtest/regtest_host.cpp index 37584d9dd..916aff5e8 100644 --- a/src/duckstation-regtest/regtest_host.cpp +++ b/src/duckstation-regtest/regtest_host.cpp @@ -8,21 +8,21 @@ #include "common/memory_settings_interface.h" #include "common/path.h" #include "common/string_util.h" +#include "core/common_host.h" +#include "core/game_list.h" #include "core/host.h" -#include "core/host_display.h" #include "core/host_settings.h" #include "core/system.h" -#include "frontend-common/common_host.h" -#include "frontend-common/game_list.h" -#include "frontend-common/input_manager.h" -#include "regtest_host_display.h" #include "scmversion/scmversion.h" +#include "util/host_display.h" +#include "util/imgui_manager.h" +#include "util/input_manager.h" #include #include Log_SetChannel(RegTestHost); #ifdef WITH_CHEEVOS -#include "frontend-common/achievements.h" +#include "core/achievements_private.h" #endif namespace RegTestHost { @@ -43,7 +43,6 @@ static u32 s_frames_to_run = 60 * 60; static u32 s_frame_dump_interval = 0; static std::string s_dump_base_directory; static std::string s_dump_game_directory; -static GPURenderer s_renderer_to_use = GPURenderer::Software; bool RegTestHost::SetFolders() { @@ -289,12 +288,37 @@ void Host::SetFullscreen(bool enabled) bool Host::AcquireHostDisplay(RenderAPI api) { - g_host_display = std::make_unique(); + WindowInfo wi; + wi.SetSurfaceless(); + + g_host_display = Host::CreateDisplayForAPI(api); + if (g_host_display && !g_host_display->CreateDevice(wi, false)) + { + Log_ErrorPrintf("Failed to create host display."); + g_host_display.reset(); + return false; + } + + if (!g_host_display->MakeCurrent() || !g_host_display->SetupDevice() || !ImGuiManager::Initialize() || + !CommonHost::CreateHostDisplayResources()) + { + Log_ErrorPrintf("Failed to setup host display."); + ImGuiManager::Shutdown(); + CommonHost::ReleaseHostDisplayResources(); + g_host_display.reset(); + return false; + } + return true; } void Host::ReleaseHostDisplay() { + if (!g_host_display) + return; + + CommonHost::ReleaseHostDisplayResources(); + ImGuiManager::Shutdown(); g_host_display.reset(); } @@ -306,6 +330,9 @@ void Host::RenderDisplay(bool skip_present) std::string dump_filename(RegTestHost::GetFrameDumpFilename(frame)); g_host_display->WriteDisplayTextureToFile(std::move(dump_filename)); } + + g_host_display->Render(true); + ImGuiManager::NewFrame(); } void Host::InvalidateDisplay() diff --git a/src/duckstation-regtest/regtest_host_display.cpp b/src/duckstation-regtest/regtest_host_display.cpp deleted file mode 100644 index 6383c22f2..000000000 --- a/src/duckstation-regtest/regtest_host_display.cpp +++ /dev/null @@ -1,255 +0,0 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin -// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) - -#include "regtest_host_display.h" -#include "common/align.h" -#include "common/assert.h" -#include "common/file_system.h" -#include "common/image.h" -#include "common/log.h" -#include "common/string_util.h" -#include -#include -Log_SetChannel(RegTestHostDisplay); - -RegTestHostDisplay::RegTestHostDisplay() = default; - -RegTestHostDisplay::~RegTestHostDisplay() = default; - -RenderAPI RegTestHostDisplay::GetRenderAPI() const -{ - return RenderAPI::None; -} - -void* RegTestHostDisplay::GetDevice() const -{ - return nullptr; -} - -void* RegTestHostDisplay::GetContext() const -{ - return nullptr; -} - -bool RegTestHostDisplay::HasDevice() const -{ - return true; -} - -bool RegTestHostDisplay::HasSurface() const -{ - return true; -} - -bool RegTestHostDisplay::CreateDevice(const WindowInfo& wi, bool vsync) -{ - m_window_info = wi; - return true; -} - -bool RegTestHostDisplay::SetupDevice() -{ - return true; -} - -bool RegTestHostDisplay::MakeCurrent() -{ - return true; -} - -bool RegTestHostDisplay::DoneCurrent() -{ - return true; -} - -void RegTestHostDisplay::DestroySurface() {} - -bool RegTestHostDisplay::CreateResources() -{ - return true; -} - -void RegTestHostDisplay::DestroyResources() {} - -HostDisplay::AdapterAndModeList RegTestHostDisplay::GetAdapterAndModeList() -{ - return {}; -} - -bool RegTestHostDisplay::CreateImGuiContext() -{ - return true; -} - -void RegTestHostDisplay::DestroyImGuiContext() -{ - // noop -} - -bool RegTestHostDisplay::UpdateImGuiFontTexture() -{ - // noop - return true; -} - -bool RegTestHostDisplay::ChangeWindow(const WindowInfo& wi) -{ - m_window_info = wi; - return true; -} - -void RegTestHostDisplay::ResizeWindow(s32 new_window_width, s32 new_window_height) -{ - m_window_info.surface_width = new_window_width; - m_window_info.surface_height = new_window_height; -} - -bool RegTestHostDisplay::SupportsFullscreen() const -{ - return false; -} - -bool RegTestHostDisplay::IsFullscreen() -{ - return false; -} - -bool RegTestHostDisplay::SetFullscreen(bool fullscreen, u32 width, u32 height, float refresh_rate) -{ - return false; -} - -bool RegTestHostDisplay::SetPostProcessingChain(const std::string_view& config) -{ - return false; -} - -std::unique_ptr RegTestHostDisplay::CreateTexture(u32 width, u32 height, u32 layers, u32 levels, - u32 samples, GPUTexture::Format format, const void* data, - u32 data_stride, bool dynamic /* = false */) -{ - std::unique_ptr tex = std::make_unique(); - if (!tex->Create(width, height, layers, levels, samples, format)) - return {}; - - if (data && !tex->Upload(0, 0, width, height, data, data_stride)) - return {}; - - return tex; -} - -bool RegTestHostDisplay::BeginTextureUpdate(GPUTexture* texture, u32 width, u32 height, void** out_buffer, - u32* out_pitch) -{ - return static_cast(texture)->BeginUpload(width, height, out_buffer, out_pitch); -} - -void RegTestHostDisplay::EndTextureUpdate(GPUTexture* texture, u32 x, u32 y, u32 width, u32 height) -{ - static_cast(texture)->EndUpload(x, y, width, height); -} - -bool RegTestHostDisplay::UpdateTexture(GPUTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data, - u32 data_stride) -{ - return static_cast(texture)->Upload(x, y, width, height, data, data_stride); -} - -bool RegTestHostDisplay::DownloadTexture(GPUTexture* texture, u32 x, u32 y, u32 width, u32 height, void* out_data, - u32 out_data_stride) -{ - return static_cast(texture)->Download(x, y, width, height, out_data, out_data_stride); -} - -bool RegTestHostDisplay::SupportsTextureFormat(GPUTexture::Format format) const -{ - return (format == GPUTexture::Format::RGBA8); -} - -void RegTestHostDisplay::SetVSync(bool enabled) -{ - Log_DevPrintf("Ignoring SetVSync(%u)", BoolToUInt32(enabled)); -} - -bool RegTestHostDisplay::Render(bool skip_present) -{ - return true; -} - -bool RegTestHostDisplay::RenderScreenshot(u32 width, u32 height, const Common::Rectangle& draw_rect, - std::vector* out_pixels, u32* out_stride, GPUTexture::Format* out_format) -{ - return false; -} - -RegTestTexture::RegTestTexture() = default; - -RegTestTexture::~RegTestTexture() = default; - -bool RegTestTexture::IsValid() const -{ - return !m_frame_buffer.empty(); -} - -bool RegTestTexture::Create(u32 width, u32 height, u32 layers, u32 levels, u32 samples, GPUTexture::Format format) -{ - if (width == 0 || height == 0 || layers != 1 || levels != 1 || samples != 1 || format == GPUTexture::Format::Unknown) - return false; - - m_width = static_cast(width); - m_height = static_cast(height); - m_layers = static_cast(layers); - m_levels = static_cast(levels); - m_samples = static_cast(samples); - m_format = format; - - m_frame_buffer_pitch = width * GPUTexture::GetPixelSize(format); - m_frame_buffer.resize(m_frame_buffer_pitch * height); - return true; -} - -bool RegTestTexture::Upload(u32 x, u32 y, u32 width, u32 height, const void* data, u32 data_stride) -{ - if ((static_cast(x) + width) > m_width || (static_cast(y) + height) > m_height) - return false; - - const u32 ps = GetPixelSize(m_format); - const u32 copy_size = width * ps; - StringUtil::StrideMemCpy(&m_frame_buffer[y * m_frame_buffer_pitch + x * ps], m_frame_buffer_pitch, data, data_stride, - copy_size, height); - return true; -} - -bool RegTestTexture::Download(u32 x, u32 y, u32 width, u32 height, void* data, u32 data_stride) const -{ - if ((static_cast(x) + width) > m_width || (static_cast(y) + height) > m_height) - return false; - - const u32 ps = GetPixelSize(m_format); - const u32 copy_size = width * ps; - StringUtil::StrideMemCpy(data, data_stride, &m_frame_buffer[y * m_frame_buffer_pitch + x * ps], m_frame_buffer_pitch, - copy_size, height); - return true; -} - -bool RegTestTexture::BeginUpload(u32 width, u32 height, void** out_buffer, u32* out_pitch) -{ - if (width > m_width || height > m_height) - return false; - - const u32 pitch = GetPixelSize(m_format) * width; - m_staging_buffer.resize(pitch * height); - *out_buffer = m_staging_buffer.data(); - *out_pitch = pitch; - return true; -} - -void RegTestTexture::EndUpload(u32 x, u32 y, u32 width, u32 height) -{ - Assert((static_cast(x) + width) <= m_width && (static_cast(y) + height) <= m_height); - - const u32 ps = GetPixelSize(m_format); - const u32 pitch = ps * width; - StringUtil::StrideMemCpy(&m_frame_buffer[y * m_frame_buffer_pitch + x * ps], m_frame_buffer_pitch, - m_staging_buffer.data(), pitch, pitch, height); -} diff --git a/src/duckstation-regtest/regtest_host_display.h b/src/duckstation-regtest/regtest_host_display.h deleted file mode 100644 index 505fcc05e..000000000 --- a/src/duckstation-regtest/regtest_host_display.h +++ /dev/null @@ -1,89 +0,0 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin -// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) - -#pragma once -#include "core/host_display.h" -#include - -class RegTestHostDisplay final : public HostDisplay -{ -public: - RegTestHostDisplay(); - ~RegTestHostDisplay(); - - RenderAPI GetRenderAPI() const override; - void* GetDevice() const override; - void* GetContext() const override; - - bool HasDevice() const override; - bool HasSurface() const override; - - bool CreateDevice(const WindowInfo& wi, bool vsync) override; - bool SetupDevice() override; - - bool MakeCurrent() override; - bool DoneCurrent() override; - - bool ChangeWindow(const WindowInfo& wi) override; - void ResizeWindow(s32 new_window_width, s32 new_window_height) override; - bool SupportsFullscreen() const override; - bool IsFullscreen() override; - bool SetFullscreen(bool fullscreen, u32 width, u32 height, float refresh_rate) override; - void DestroySurface() override; - - bool SetPostProcessingChain(const std::string_view& config) override; - - bool CreateResources() override; - void DestroyResources() override; - - AdapterAndModeList GetAdapterAndModeList() override; - bool CreateImGuiContext() override; - void DestroyImGuiContext() override; - bool UpdateImGuiFontTexture() override; - - std::unique_ptr CreateTexture(u32 width, u32 height, u32 layers, u32 levels, u32 samples, - GPUTexture::Format format, const void* data, u32 data_stride, - bool dynamic = false) override; - bool BeginTextureUpdate(GPUTexture* texture, u32 width, u32 height, void** out_buffer, u32* out_pitch) override; - void EndTextureUpdate(GPUTexture* texture, u32 x, u32 y, u32 width, u32 height) override; - bool UpdateTexture(GPUTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data, u32 data_stride) override; - bool DownloadTexture(GPUTexture* texture, u32 x, u32 y, u32 width, u32 height, void* out_data, - u32 out_data_stride) override; - - void SetVSync(bool enabled) override; - - bool Render(bool skip_present) override; - bool RenderScreenshot(u32 width, u32 height, const Common::Rectangle& draw_rect, std::vector* out_pixels, - u32* out_stride, GPUTexture::Format* out_format) override; - - bool SupportsTextureFormat(GPUTexture::Format format) const override; - -private: - -}; - -class RegTestTexture : public GPUTexture -{ -public: - RegTestTexture(); - ~RegTestTexture() override; - - ALWAYS_INLINE const std::vector& GetPixels() const { return m_frame_buffer; } - ALWAYS_INLINE u32 GetPitch() const { return m_frame_buffer_pitch; } - - bool IsValid() const override; - - bool Create(u32 width, u32 height, u32 layers, u32 levels, u32 samples, GPUTexture::Format format); - - bool Upload(u32 x, u32 y, u32 width, u32 height, const void* data, u32 data_stride); - bool Download(u32 x, u32 y, u32 width, u32 height, void* data, u32 data_stride) const; - - bool BeginUpload(u32 width, u32 height, void** out_buffer, u32* out_pitch); - void EndUpload(u32 x, u32 y, u32 width, u32 height); - -private: - std::vector m_frame_buffer; - std::vector m_staging_buffer; - GPUTexture::Format m_frame_buffer_format = GPUTexture::Format::Unknown; - u32 m_frame_buffer_pitch = 0; -};