mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-22 05:45:38 +00:00
RegTest: Drop HostDisplay and add HW support
This commit is contained in:
parent
a00a4391ca
commit
910abd1eac
|
@ -82,10 +82,8 @@ def check_regression_test(baselinedir, testdir, name):
|
||||||
write("<tr><td><img src=\"{}\" /></td><td><img src=\"{}\" /></td></tr>".format(imguri1, imguri2))
|
write("<tr><td><img src=\"{}\" /></td><td><img src=\"{}\" /></td></tr>".format(imguri1, imguri2))
|
||||||
write("</table>")
|
write("</table>")
|
||||||
num_diff += 1
|
num_diff += 1
|
||||||
if (num_diff >= 3):
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
return (num_diff > 0)
|
||||||
|
|
||||||
|
|
||||||
def check_regression_tests(baselinedir, testdir):
|
def check_regression_tests(baselinedir, testdir):
|
||||||
|
|
|
@ -15,13 +15,14 @@ def is_game_path(path):
|
||||||
return extension in ["cue", "chd"]
|
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,
|
args = [runner,
|
||||||
"-renderer", "software",
|
"-renderer", "software",
|
||||||
"-log", "verbose",
|
"-log", "error",
|
||||||
"-dumpdir", destdir,
|
"-dumpdir", destdir,
|
||||||
"-dumpinterval", str(dump_interval),
|
"-dumpinterval", str(dump_interval),
|
||||||
"-frames", str(frames),
|
"-frames", str(frames),
|
||||||
|
"-renderer", ("Software" if renderer is None else renderer),
|
||||||
"--", gamepath
|
"--", gamepath
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -29,7 +30,7 @@ def run_regression_test(runner, destdir, dump_interval, frames, gamepath):
|
||||||
subprocess.run(args)
|
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)
|
paths = glob.glob(gamedir + "/*.*", recursive=True)
|
||||||
gamepaths = list(filter(is_game_path, paths))
|
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)
|
run_regression_test(runner, destdir, dump_interval, frames, game)
|
||||||
else:
|
else:
|
||||||
print("Processing %u games on %u processors" % (len(gamepaths), parallel))
|
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 = multiprocessing.Pool(parallel)
|
||||||
pool.map(func, gamepaths)
|
pool.map(func, gamepaths, chunksize=1)
|
||||||
pool.close()
|
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("-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("-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("-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()
|
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)
|
sys.exit(1)
|
||||||
else:
|
else:
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
add_executable(duckstation-regtest
|
add_executable(duckstation-regtest
|
||||||
regtest_host_display.cpp
|
|
||||||
regtest_host_display.h
|
|
||||||
regtest_host.cpp
|
regtest_host.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,8 @@
|
||||||
<ProjectGuid>{3029310E-4211-4C87-801A-72E130A648EF}</ProjectGuid>
|
<ProjectGuid>{3029310E-4211-4C87-801A-72E130A648EF}</ProjectGuid>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="regtest_host_display.cpp" />
|
|
||||||
<ClCompile Include="regtest_host.cpp" />
|
<ClCompile Include="regtest_host.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="regtest_host_display.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\common\common.vcxproj">
|
<ProjectReference Include="..\common\common.vcxproj">
|
||||||
<Project>{ee054e08-3799-4a59-a422-18259c105ffd}</Project>
|
<Project>{ee054e08-3799-4a59-a422-18259c105ffd}</Project>
|
||||||
|
|
|
@ -2,9 +2,5 @@
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="regtest_host.cpp" />
|
<ClCompile Include="regtest_host.cpp" />
|
||||||
<ClCompile Include="regtest_host_display.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="regtest_host_display.h" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -8,21 +8,21 @@
|
||||||
#include "common/memory_settings_interface.h"
|
#include "common/memory_settings_interface.h"
|
||||||
#include "common/path.h"
|
#include "common/path.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
|
#include "core/common_host.h"
|
||||||
|
#include "core/game_list.h"
|
||||||
#include "core/host.h"
|
#include "core/host.h"
|
||||||
#include "core/host_display.h"
|
|
||||||
#include "core/host_settings.h"
|
#include "core/host_settings.h"
|
||||||
#include "core/system.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 "scmversion/scmversion.h"
|
||||||
|
#include "util/host_display.h"
|
||||||
|
#include "util/imgui_manager.h"
|
||||||
|
#include "util/input_manager.h"
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
Log_SetChannel(RegTestHost);
|
Log_SetChannel(RegTestHost);
|
||||||
|
|
||||||
#ifdef WITH_CHEEVOS
|
#ifdef WITH_CHEEVOS
|
||||||
#include "frontend-common/achievements.h"
|
#include "core/achievements_private.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace RegTestHost {
|
namespace RegTestHost {
|
||||||
|
@ -43,7 +43,6 @@ static u32 s_frames_to_run = 60 * 60;
|
||||||
static u32 s_frame_dump_interval = 0;
|
static u32 s_frame_dump_interval = 0;
|
||||||
static std::string s_dump_base_directory;
|
static std::string s_dump_base_directory;
|
||||||
static std::string s_dump_game_directory;
|
static std::string s_dump_game_directory;
|
||||||
static GPURenderer s_renderer_to_use = GPURenderer::Software;
|
|
||||||
|
|
||||||
bool RegTestHost::SetFolders()
|
bool RegTestHost::SetFolders()
|
||||||
{
|
{
|
||||||
|
@ -289,12 +288,37 @@ void Host::SetFullscreen(bool enabled)
|
||||||
|
|
||||||
bool Host::AcquireHostDisplay(RenderAPI api)
|
bool Host::AcquireHostDisplay(RenderAPI api)
|
||||||
{
|
{
|
||||||
g_host_display = std::make_unique<RegTestHostDisplay>();
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::ReleaseHostDisplay()
|
void Host::ReleaseHostDisplay()
|
||||||
{
|
{
|
||||||
|
if (!g_host_display)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CommonHost::ReleaseHostDisplayResources();
|
||||||
|
ImGuiManager::Shutdown();
|
||||||
g_host_display.reset();
|
g_host_display.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,6 +330,9 @@ void Host::RenderDisplay(bool skip_present)
|
||||||
std::string dump_filename(RegTestHost::GetFrameDumpFilename(frame));
|
std::string dump_filename(RegTestHost::GetFrameDumpFilename(frame));
|
||||||
g_host_display->WriteDisplayTextureToFile(std::move(dump_filename));
|
g_host_display->WriteDisplayTextureToFile(std::move(dump_filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_host_display->Render(true);
|
||||||
|
ImGuiManager::NewFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::InvalidateDisplay()
|
void Host::InvalidateDisplay()
|
||||||
|
|
|
@ -1,255 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
|
||||||
// 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 <array>
|
|
||||||
#include <tuple>
|
|
||||||
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<GPUTexture> 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<RegTestTexture> tex = std::make_unique<RegTestTexture>();
|
|
||||||
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<RegTestTexture*>(texture)->BeginUpload(width, height, out_buffer, out_pitch);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegTestHostDisplay::EndTextureUpdate(GPUTexture* texture, u32 x, u32 y, u32 width, u32 height)
|
|
||||||
{
|
|
||||||
static_cast<RegTestTexture*>(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<RegTestTexture*>(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<const RegTestTexture*>(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<s32>& draw_rect,
|
|
||||||
std::vector<u32>* 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<u16>(width);
|
|
||||||
m_height = static_cast<u16>(height);
|
|
||||||
m_layers = static_cast<u8>(layers);
|
|
||||||
m_levels = static_cast<u8>(levels);
|
|
||||||
m_samples = static_cast<u8>(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<u64>(x) + width) > m_width || (static_cast<u64>(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<u64>(x) + width) > m_width || (static_cast<u64>(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<u64>(x) + width) <= m_width && (static_cast<u64>(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);
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
|
||||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "core/host_display.h"
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
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<GPUTexture> 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<s32>& draw_rect, std::vector<u32>* 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<u32>& 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<u32> m_frame_buffer;
|
|
||||||
std::vector<u32> m_staging_buffer;
|
|
||||||
GPUTexture::Format m_frame_buffer_format = GPUTexture::Format::Unknown;
|
|
||||||
u32 m_frame_buffer_pitch = 0;
|
|
||||||
};
|
|
Loading…
Reference in a new issue