mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-24 23:34:37 +01:00
Merge pull request #8458 from janisozaur/benchmark
Add sprite sorting benchmark
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
4C29DEB3218C6AE500E8707F /* RCT12.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C29DEB2218C6AE500E8707F /* RCT12.cpp */; };
|
||||
4C358E5221C445F700ADE6BC /* ReplayManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C358E5021C445F700ADE6BC /* ReplayManager.cpp */; };
|
||||
4C3B4236205914F7000C5BB7 /* InGameConsole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C3B4234205914F7000C5BB7 /* InGameConsole.cpp */; };
|
||||
4C724B2221F0AD790012ADD0 /* BenchSpriteSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C724B2121F0AD790012ADD0 /* BenchSpriteSort.cpp */; };
|
||||
4C93F1AD1F8CD9F000A9330D /* Input.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C93F1AC1F8CD9F000A9330D /* Input.cpp */; };
|
||||
4C93F1AF1F8CD9F600A9330D /* KeyboardShortcut.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C93F1AE1F8CD9F600A9330D /* KeyboardShortcut.cpp */; };
|
||||
4CB1375621C2E9F80029FCDA /* SimulateCommands.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CB1375521C2E9F80029FCDA /* SimulateCommands.cpp */; };
|
||||
@@ -643,6 +644,7 @@
|
||||
4C6AC20E1F9E1693004324AA /* Station.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Station.h; sourceTree = "<group>"; };
|
||||
4C6AC2101F9E1CB3004324AA /* CableLift.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CableLift.cpp; sourceTree = "<group>"; };
|
||||
4C6AC2111F9E1CB3004324AA /* CableLift.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CableLift.h; sourceTree = "<group>"; };
|
||||
4C724B2121F0AD790012ADD0 /* BenchSpriteSort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BenchSpriteSort.cpp; sourceTree = "<group>"; };
|
||||
4C7B53A21FFC15ED00A52E21 /* ObjectLimits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectLimits.h; sourceTree = "<group>"; };
|
||||
4C7B53A31FFC180400A52E21 /* ObjectList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectList.cpp; sourceTree = "<group>"; };
|
||||
4C7B53A41FFC180400A52E21 /* ObjectList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectList.h; sourceTree = "<group>"; };
|
||||
@@ -2411,6 +2413,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D48AFDB61EF78DBF0081C644 /* BenchGfxCommmands.cpp */,
|
||||
4C724B2121F0AD790012ADD0 /* BenchSpriteSort.cpp */,
|
||||
F76C83631EC4E7CC00FA49E2 /* CommandLine.cpp */,
|
||||
F76C83641EC4E7CC00FA49E2 /* CommandLine.hpp */,
|
||||
F76C83651EC4E7CC00FA49E2 /* ConvertCommand.cpp */,
|
||||
@@ -3647,6 +3650,7 @@
|
||||
C6D2BEE61F9BAACE008B557C /* TrackList.cpp in Sources */,
|
||||
C666EE701F37ACB10061AA04 /* LandRights.cpp in Sources */,
|
||||
93F6004D213DD7DD00EEB83E /* TerrainEdgeObject.cpp in Sources */,
|
||||
4C724B2221F0AD790012ADD0 /* BenchSpriteSort.cpp in Sources */,
|
||||
C666EE781F37ACB10061AA04 /* ServerList.cpp in Sources */,
|
||||
C654DF341F69C0430040F43D /* NewCampaign.cpp in Sources */,
|
||||
F76C887D1EC5324E00FA49E2 /* CursorData.cpp in Sources */,
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
- Feature: [#8259] Add say command to in-game console.
|
||||
- Feature: [#8374] Add replay system.
|
||||
- Feature: [#8377] Add option to adjust amount of autosaves to keep.
|
||||
- Feature: [#8458] Add sprite sorting benchmark.
|
||||
- Feature: [#8583] Add boosters to water coaster.
|
||||
- Change: [#7961] Add new object types: station, terrain surface, and terrain edge.
|
||||
- Change: [#8222] The climate setting has been moved from objective options to scenario options.
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
<AdditionalOptions>/utf-8 /std:c++17 /permissive- /Zc:externConstexpr</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>wininet.lib;imm32.lib;version.lib;winmm.lib;crypt32.lib;wldap32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>wininet.lib;imm32.lib;version.lib;winmm.lib;crypt32.lib;wldap32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalOptions>/OPT:NOLBR /ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@@ -76,7 +76,7 @@
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
|
||||
<AdditionalDependencies>bz2d.lib;discord-rpc.lib;freetyped.lib;jansson_d.lib;libcurl.lib;libeay32.lib;libpng16d.lib;libspeexdsp.lib;SDL2d.lib;ssleay32.lib;zip.lib;zlibd.lib;libbreakpadd.lib;libbreakpad_clientd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>bz2d.lib;discord-rpc.lib;freetyped.lib;jansson_d.lib;libcurl.lib;libeay32.lib;libpng16d.lib;libspeexdsp.lib;SDL2d.lib;ssleay32.lib;zip.lib;zlibd.lib;libbreakpadd.lib;libbreakpad_clientd.lib;benchmark.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
@@ -94,7 +94,7 @@
|
||||
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>bz2.lib;discord-rpc.lib;freetype.lib;jansson.lib;libcurl.lib;libeay32.lib;libpng16.lib;libspeexdsp.lib;SDL2.lib;ssleay32.lib;zip.lib;zlib.lib;libbreakpad.lib;libbreakpad_client.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>bz2.lib;discord-rpc.lib;freetype.lib;jansson.lib;libcurl.lib;libeay32.lib;libpng16.lib;libspeexdsp.lib;SDL2.lib;ssleay32.lib;zip.lib;zlib.lib;libbreakpad.lib;libbreakpad_client.lib;benchmark.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
|
||||
@@ -61,10 +61,10 @@
|
||||
<!-- 3rd party libraries / dependencies -->
|
||||
<PropertyGroup>
|
||||
<DependenciesCheckFile>$(RootDir).dependencies</DependenciesCheckFile>
|
||||
<LibsUrl Condition="'$(Platform)'=='Win32'">https://github.com/OpenRCT2/Dependencies/releases/download/v18/openrct2-libs-v18-x86-windows-static-winssl.zip</LibsUrl>
|
||||
<LibsSha1 Condition="'$(Platform)'=='Win32'">5266545ca3034f9718729c7841d0352ed866db39</LibsSha1>
|
||||
<LibsUrl Condition="'$(Platform)'=='x64'">https://github.com/OpenRCT2/Dependencies/releases/download/v18/openrct2-libs-v18-x64-windows-static-winssl.zip</LibsUrl>
|
||||
<LibsSha1 Condition="'$(Platform)'=='x64'">4a122221e000b26067c8a4d06d2f053f27fe3f39</LibsSha1>
|
||||
<LibsUrl Condition="'$(Platform)'=='Win32'">https://github.com/OpenRCT2/Dependencies/releases/download/v19/openrct2-libs-v19-x86-windows-static-winssl.zip</LibsUrl>
|
||||
<LibsSha1 Condition="'$(Platform)'=='Win32'">c0a49dfb7a0b4175c5b5003922f8a5c4b4589132</LibsSha1>
|
||||
<LibsUrl Condition="'$(Platform)'=='x64'">https://github.com/OpenRCT2/Dependencies/releases/download/v19/openrct2-libs-v19-x64-windows-static-winssl.zip</LibsUrl>
|
||||
<LibsSha1 Condition="'$(Platform)'=='x64'">623cb9199da328e55ee9c7f5e1135ceab43cc6b9</LibsSha1>
|
||||
<GtestVersion>2fe3bd994b3189899d93f1d5a881e725e046fdc2</GtestVersion>
|
||||
<GtestUrl>https://github.com/google/googletest/archive/$(GtestVersion).zip</GtestUrl>
|
||||
<GtestSha1>058b9df80244c03f1633cb06e9f70471a29ebb8e</GtestSha1>
|
||||
|
||||
@@ -47,6 +47,8 @@ if (NOT DISABLE_NETWORK)
|
||||
find_package(OpenSSL 1.0.0 REQUIRED)
|
||||
endif ()
|
||||
|
||||
find_package(benchmark)
|
||||
|
||||
if (NOT DISABLE_TTF)
|
||||
if (UNIX AND NOT APPLE AND NOT MSVC)
|
||||
PKG_CHECK_MODULES(FONTCONFIG REQUIRED fontconfig)
|
||||
@@ -73,6 +75,15 @@ project(${PROJECT} CXX)
|
||||
add_library(${PROJECT} ${OPENRCT2_CORE_SOURCES} ${OPENRCT2_CORE_MM_SOURCES} ${RCT2_SECTIONS})
|
||||
set_target_properties(${PROJECT} PROPERTIES PREFIX "")
|
||||
|
||||
if (benchmark_FOUND)
|
||||
message("Found Google benchmark, enabling support")
|
||||
set_target_properties(${PROJECT} PROPERTIES COMPILE_DEFINITIONS USE_BENCHMARK)
|
||||
target_link_libraries(${PROJECT} benchmark::benchmark)
|
||||
target_include_directories(${PROJECT} PRIVATE ${benchmark_INCLUDE_DIRS})
|
||||
else ()
|
||||
message("Google benchmark not found, disabling support")
|
||||
endif ()
|
||||
|
||||
# Libraries
|
||||
if (STATIC)
|
||||
target_link_libraries(${PROJECT} ${JANSSON_STATIC_LIBRARIES}
|
||||
|
||||
240
src/openrct2/cmdline/BenchSpriteSort.cpp
Normal file
240
src/openrct2/cmdline/BenchSpriteSort.cpp
Normal file
@@ -0,0 +1,240 @@
|
||||
/*****************************************************************************
|
||||
* Copyright (c) 2014-2019 OpenRCT2 developers
|
||||
*
|
||||
* For a complete list of all authors, please refer to contributors.md
|
||||
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "CommandLine.hpp"
|
||||
|
||||
#ifdef USE_BENCHMARK
|
||||
|
||||
# include "../Context.h"
|
||||
# include "../Game.h"
|
||||
# include "../Intro.h"
|
||||
# include "../OpenRCT2.h"
|
||||
# include "../audio/audio.h"
|
||||
# include "../core/Console.hpp"
|
||||
# include "../core/Imaging.h"
|
||||
# include "../drawing/Drawing.h"
|
||||
# include "../interface/Viewport.h"
|
||||
# include "../localisation/Localisation.h"
|
||||
# include "../paint/Paint.h"
|
||||
# include "../platform/platform.h"
|
||||
# include "../util/Util.h"
|
||||
# include "../world/Climate.h"
|
||||
# include "../world/Map.h"
|
||||
# include "../world/Park.h"
|
||||
# include "../world/Surface.h"
|
||||
|
||||
# include <benchmark/benchmark.h>
|
||||
# include <cstdint>
|
||||
# include <iterator>
|
||||
# include <vector>
|
||||
|
||||
static void fixup_pointers(paint_session* s, size_t paint_session_entries, size_t paint_struct_entries, size_t quadrant_entries)
|
||||
{
|
||||
for (size_t i = 0; i < paint_session_entries; i++)
|
||||
{
|
||||
for (size_t j = 0; j < paint_struct_entries; j++)
|
||||
{
|
||||
if (s[i].PaintStructs[j].basic.next_quadrant_ps == (paint_struct*)paint_struct_entries)
|
||||
{
|
||||
s[i].PaintStructs[j].basic.next_quadrant_ps = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
s[i].PaintStructs[j].basic.next_quadrant_ps = &s[i].PaintStructs
|
||||
[(uintptr_t)s[i].PaintStructs[j].basic.next_quadrant_ps]
|
||||
.basic;
|
||||
}
|
||||
}
|
||||
for (size_t j = 0; j < quadrant_entries; j++)
|
||||
{
|
||||
if (s[i].Quadrants[j] == (paint_struct*)quadrant_entries)
|
||||
{
|
||||
s[i].Quadrants[j] = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
s[i].Quadrants[j] = &s[i].PaintStructs[(size_t)s[i].Quadrants[j]].basic;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<paint_session> extract_paint_session(const std::string parkFileName)
|
||||
{
|
||||
core_init();
|
||||
gOpenRCT2Headless = true;
|
||||
auto context = OpenRCT2::CreateContext();
|
||||
std::vector<paint_session> sessions;
|
||||
log_info("Starting...");
|
||||
if (context->Initialise())
|
||||
{
|
||||
drawing_engine_init();
|
||||
if (!context->LoadParkFromFile(parkFileName))
|
||||
{
|
||||
log_error("Failed to load park!");
|
||||
return {};
|
||||
}
|
||||
|
||||
gIntroState = INTRO_STATE_NONE;
|
||||
gScreenFlags = SCREEN_FLAGS_PLAYING;
|
||||
|
||||
int32_t mapSize = gMapSize;
|
||||
int32_t resolutionWidth = (mapSize * 32 * 2);
|
||||
int32_t resolutionHeight = (mapSize * 32 * 1);
|
||||
|
||||
resolutionWidth += 8;
|
||||
resolutionHeight += 128;
|
||||
|
||||
rct_viewport viewport;
|
||||
viewport.x = 0;
|
||||
viewport.y = 0;
|
||||
viewport.width = resolutionWidth;
|
||||
viewport.height = resolutionHeight;
|
||||
viewport.view_width = viewport.width;
|
||||
viewport.view_height = viewport.height;
|
||||
viewport.var_11 = 0;
|
||||
viewport.flags = 0;
|
||||
|
||||
int32_t customX = (gMapSize / 2) * 32 + 16;
|
||||
int32_t customY = (gMapSize / 2) * 32 + 16;
|
||||
|
||||
int32_t x = 0, y = 0;
|
||||
int32_t z = tile_element_height(customX, customY) & 0xFFFF;
|
||||
x = customY - customX;
|
||||
y = ((customX + customY) / 2) - z;
|
||||
|
||||
viewport.view_x = x - ((viewport.view_width) / 2);
|
||||
viewport.view_y = y - ((viewport.view_height) / 2);
|
||||
viewport.zoom = 0;
|
||||
gCurrentRotation = 0;
|
||||
|
||||
// Ensure sprites appear regardless of rotation
|
||||
reset_all_sprite_quadrant_placements();
|
||||
|
||||
rct_drawpixelinfo dpi;
|
||||
dpi.x = 0;
|
||||
dpi.y = 0;
|
||||
dpi.width = resolutionWidth;
|
||||
dpi.height = resolutionHeight;
|
||||
dpi.pitch = 0;
|
||||
dpi.bits = (uint8_t*)malloc(dpi.width * dpi.height);
|
||||
|
||||
log_info("Obtaining sprite data...");
|
||||
viewport_render(&dpi, &viewport, 0, 0, viewport.width, viewport.height, &sessions);
|
||||
|
||||
free(dpi.bits);
|
||||
drawing_engine_dispose();
|
||||
}
|
||||
log_info("Got %u paint sessions.", std::size(sessions));
|
||||
return sessions;
|
||||
}
|
||||
|
||||
// This function is based on benchgfx_render_screenshots
|
||||
static void BM_paint_session_arrange(benchmark::State& state, const std::vector<paint_session> inputSessions)
|
||||
{
|
||||
std::vector<paint_session> sessions = inputSessions;
|
||||
// Fixing up the pointers continuously is wasteful. Fix it up once for `sessions` and store a copy.
|
||||
// Keep in mind we need bit-exact copy, as the lists use pointers.
|
||||
// Once sorted, just restore the copy with the original fixed-up version.
|
||||
paint_session* local_s = new paint_session[std::size(sessions)];
|
||||
fixup_pointers(&sessions[0], std::size(sessions), std::size(local_s->PaintStructs), std::size(local_s->Quadrants));
|
||||
std::copy_n(sessions.cbegin(), std::size(sessions), local_s);
|
||||
for (auto _ : state)
|
||||
{
|
||||
state.PauseTiming();
|
||||
std::copy_n(local_s, std::size(sessions), sessions.begin());
|
||||
state.ResumeTiming();
|
||||
paint_session_arrange(&sessions[0]);
|
||||
benchmark::DoNotOptimize(sessions);
|
||||
}
|
||||
state.SetItemsProcessed(state.iterations() * std::size(sessions));
|
||||
delete[] local_s;
|
||||
}
|
||||
|
||||
static int cmdline_for_bench_sprite_sort(int argc, const char** argv)
|
||||
{
|
||||
{
|
||||
// Register some basic "baseline" benchmark
|
||||
std::vector<paint_session> sessions(1);
|
||||
for (auto& ps : sessions[0].PaintStructs)
|
||||
{
|
||||
ps.basic.next_quadrant_ps = (paint_struct*)(std::size(sessions[0].PaintStructs));
|
||||
}
|
||||
for (auto& quad : sessions[0].Quadrants)
|
||||
{
|
||||
quad = (paint_struct*)(std::size(sessions[0].Quadrants));
|
||||
}
|
||||
benchmark::RegisterBenchmark("baseline", BM_paint_session_arrange, sessions);
|
||||
}
|
||||
|
||||
// Google benchmark does stuff to argv. It doesn't modify the pointees,
|
||||
// but it wants to reorder the pointers, so present a copy of them.
|
||||
std::vector<char*> argv_for_benchmark;
|
||||
|
||||
// argv[0] is expected to contain the binary name. It's only for logging purposes, don't bother.
|
||||
argv_for_benchmark.push_back(nullptr);
|
||||
|
||||
// Extract file names from argument list. If there is no such file, consider it benchmark option.
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
if (platform_file_exists(argv[i]))
|
||||
{
|
||||
// Register benchmark for sv6 if valid
|
||||
std::vector<paint_session> sessions = extract_paint_session(argv[i]);
|
||||
if (!sessions.empty())
|
||||
benchmark::RegisterBenchmark(argv[i], BM_paint_session_arrange, sessions);
|
||||
}
|
||||
else
|
||||
{
|
||||
argv_for_benchmark.push_back((char*)argv[i]);
|
||||
}
|
||||
}
|
||||
// Update argc with all the changes made
|
||||
argc = (int)argv_for_benchmark.size();
|
||||
::benchmark::Initialize(&argc, &argv_for_benchmark[0]);
|
||||
if (::benchmark::ReportUnrecognizedArguments(argc, &argv_for_benchmark[0]))
|
||||
return -1;
|
||||
::benchmark::RunSpecifiedBenchmarks();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static exitcode_t HandleBenchSpriteSort(CommandLineArgEnumerator* argEnumerator)
|
||||
{
|
||||
const char** argv = (const char**)argEnumerator->GetArguments() + argEnumerator->GetIndex();
|
||||
int32_t argc = argEnumerator->GetCount() - argEnumerator->GetIndex();
|
||||
int32_t result = cmdline_for_bench_sprite_sort(argc, argv);
|
||||
if (result < 0)
|
||||
{
|
||||
return EXITCODE_FAIL;
|
||||
}
|
||||
return EXITCODE_OK;
|
||||
}
|
||||
|
||||
#else
|
||||
static exitcode_t HandleBenchSpriteSort(CommandLineArgEnumerator* argEnumerator)
|
||||
{
|
||||
log_error("Sorry, Google benchmark not enabled in this build");
|
||||
return EXITCODE_FAIL;
|
||||
}
|
||||
#endif // USE_BENCHMARK
|
||||
|
||||
const CommandLineCommand CommandLine::BenchSpriteSortCommands[]{
|
||||
#ifdef USE_BENCHMARK
|
||||
DefineCommand(
|
||||
"",
|
||||
"[<file>]... [--benchmark_list_tests={true|false}] [--benchmark_filter=<regex>] [--benchmark_min_time=<min_time>] "
|
||||
"[--benchmark_repetitions=<num_repetitions>] [--benchmark_report_aggregates_only={true|false}] "
|
||||
"[--benchmark_format=<console|json|csv>] [--benchmark_out=<filename>] [--benchmark_out_format=<json|console|csv>] "
|
||||
"[--benchmark_color={auto|true|false}] [--benchmark_counters_tabular={true|false}] [--v=<verbosity>]",
|
||||
nullptr, HandleBenchSpriteSort),
|
||||
CommandTableEnd
|
||||
#else
|
||||
DefineCommand("", "*** SORRY NOT ENABLED IN THIS BUILD ***", nullptr, HandleBenchSpriteSort), CommandTableEnd
|
||||
#endif // USE_BENCHMARK
|
||||
};
|
||||
@@ -117,6 +117,7 @@ namespace CommandLine
|
||||
extern const CommandLineCommand ScreenshotCommands[];
|
||||
extern const CommandLineCommand SpriteCommands[];
|
||||
extern const CommandLineCommand BenchGfxCommands[];
|
||||
extern const CommandLineCommand BenchSpriteSortCommands[];
|
||||
extern const CommandLineCommand SimulateCommands[];
|
||||
|
||||
extern const CommandLineExample RootExamples[];
|
||||
|
||||
@@ -135,10 +135,11 @@ const CommandLineCommand CommandLine::RootCommands[]
|
||||
#endif
|
||||
|
||||
// Sub-commands
|
||||
DefineSubCommand("screenshot", CommandLine::ScreenshotCommands),
|
||||
DefineSubCommand("sprite", CommandLine::SpriteCommands ),
|
||||
DefineSubCommand("benchgfx", CommandLine::BenchGfxCommands ),
|
||||
DefineSubCommand("simulate", CommandLine::SimulateCommands ),
|
||||
DefineSubCommand("screenshot", CommandLine::ScreenshotCommands ),
|
||||
DefineSubCommand("sprite", CommandLine::SpriteCommands ),
|
||||
DefineSubCommand("benchgfx", CommandLine::BenchGfxCommands ),
|
||||
DefineSubCommand("benchspritesort", CommandLine::BenchSpriteSortCommands ),
|
||||
DefineSubCommand("simulate", CommandLine::SimulateCommands ),
|
||||
CommandTableEnd
|
||||
};
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ static int16_t _interactionMapX;
|
||||
static int16_t _interactionMapY;
|
||||
static uint16_t _unk9AC154;
|
||||
|
||||
static void viewport_paint_column(rct_drawpixelinfo* dpi, uint32_t viewFlags);
|
||||
static void viewport_paint_column(rct_drawpixelinfo* dpi, uint32_t viewFlags, std::vector<paint_session>* sessions);
|
||||
static void viewport_paint_weather_gloom(rct_drawpixelinfo* dpi);
|
||||
|
||||
/**
|
||||
@@ -791,7 +791,9 @@ void viewport_update_smart_vehicle_follow(rct_window* window)
|
||||
* edi: dpi
|
||||
* ebp: bottom
|
||||
*/
|
||||
void viewport_render(rct_drawpixelinfo* dpi, rct_viewport* viewport, int32_t left, int32_t top, int32_t right, int32_t bottom)
|
||||
void viewport_render(
|
||||
rct_drawpixelinfo* dpi, rct_viewport* viewport, int32_t left, int32_t top, int32_t right, int32_t bottom,
|
||||
std::vector<paint_session>* sessions)
|
||||
{
|
||||
if (right <= viewport->x)
|
||||
return;
|
||||
@@ -821,7 +823,7 @@ void viewport_render(rct_drawpixelinfo* dpi, rct_viewport* viewport, int32_t lef
|
||||
top += viewport->view_y;
|
||||
bottom += viewport->view_y;
|
||||
|
||||
viewport_paint(viewport, dpi, left, top, right, bottom);
|
||||
viewport_paint(viewport, dpi, left, top, right, bottom, sessions);
|
||||
|
||||
#ifdef DEBUG_SHOW_DIRTY_BOX
|
||||
if (viewport != g_viewport_list)
|
||||
@@ -842,7 +844,9 @@ void viewport_render(rct_drawpixelinfo* dpi, rct_viewport* viewport, int32_t lef
|
||||
* edi: dpi
|
||||
* ebp: bottom
|
||||
*/
|
||||
void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int16_t left, int16_t top, int16_t right, int16_t bottom)
|
||||
void viewport_paint(
|
||||
rct_viewport* viewport, rct_drawpixelinfo* dpi, int16_t left, int16_t top, int16_t right, int16_t bottom,
|
||||
std::vector<paint_session>* sessions)
|
||||
{
|
||||
uint32_t viewFlags = viewport->flags;
|
||||
uint16_t width = right - left;
|
||||
@@ -878,32 +882,37 @@ void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int16_t left
|
||||
int16_t rightBorder = dpi1.x + dpi1.width;
|
||||
|
||||
// Splits the area into 32 pixel columns and renders them
|
||||
for (x = floor2(dpi1.x, 32); x < rightBorder; x += 32)
|
||||
int16_t start_x = floor2(dpi1.x, 32);
|
||||
if (sessions != nullptr)
|
||||
{
|
||||
sessions->reserve((rightBorder - start_x) / 32);
|
||||
}
|
||||
for (int16_t columnx = start_x; columnx < rightBorder; columnx += 32)
|
||||
{
|
||||
rct_drawpixelinfo dpi2 = dpi1;
|
||||
if (x >= dpi2.x)
|
||||
if (columnx >= dpi2.x)
|
||||
{
|
||||
int16_t leftPitch = x - dpi2.x;
|
||||
int16_t leftPitch = columnx - dpi2.x;
|
||||
dpi2.width -= leftPitch;
|
||||
dpi2.bits += leftPitch >> dpi2.zoom_level;
|
||||
dpi2.pitch += leftPitch >> dpi2.zoom_level;
|
||||
dpi2.x = x;
|
||||
dpi2.x = columnx;
|
||||
}
|
||||
|
||||
int16_t paintRight = dpi2.x + dpi2.width;
|
||||
if (paintRight >= x + 32)
|
||||
if (paintRight >= columnx + 32)
|
||||
{
|
||||
int16_t rightPitch = paintRight - x - 32;
|
||||
int16_t rightPitch = paintRight - columnx - 32;
|
||||
paintRight -= rightPitch;
|
||||
dpi2.pitch += rightPitch >> dpi2.zoom_level;
|
||||
}
|
||||
dpi2.width = paintRight - dpi2.x;
|
||||
|
||||
viewport_paint_column(&dpi2, viewFlags);
|
||||
viewport_paint_column(&dpi2, viewFlags, sessions);
|
||||
}
|
||||
}
|
||||
|
||||
static void viewport_paint_column(rct_drawpixelinfo* dpi, uint32_t viewFlags)
|
||||
static void viewport_paint_column(rct_drawpixelinfo* dpi, uint32_t viewFlags, std::vector<paint_session>* sessions)
|
||||
{
|
||||
if (viewFlags
|
||||
& (VIEWPORT_FLAG_HIDE_VERTICAL | VIEWPORT_FLAG_HIDE_BASE | VIEWPORT_FLAG_UNDERGROUND_INSIDE | VIEWPORT_FLAG_CLIP_VIEW))
|
||||
@@ -918,6 +927,23 @@ static void viewport_paint_column(rct_drawpixelinfo* dpi, uint32_t viewFlags)
|
||||
|
||||
paint_session* session = paint_session_alloc(dpi, viewFlags);
|
||||
paint_session_generate(session);
|
||||
// Perform a deep copy of the paint session, use relative offsets.
|
||||
// This is done to extract the session for benchmark.
|
||||
if (sessions != nullptr)
|
||||
{
|
||||
sessions->push_back(*session);
|
||||
paint_session* session_copy = &sessions->at(sessions->size() - 1);
|
||||
|
||||
// Mind the offset needs to be calculated against the original `session`, not `session_copy`
|
||||
for (auto& ps : session_copy->PaintStructs)
|
||||
{
|
||||
ps.basic.next_quadrant_ps = (paint_struct*)(ps.basic.next_quadrant_ps ? int(ps.basic.next_quadrant_ps - &session->PaintStructs[0].basic) : std::size(session->PaintStructs));
|
||||
}
|
||||
for (auto& quad : session_copy->Quadrants)
|
||||
{
|
||||
quad = (paint_struct*)(quad ? int(quad - &session->PaintStructs[0].basic) : std::size(session->Quadrants));
|
||||
}
|
||||
}
|
||||
paint_session_arrange(session);
|
||||
paint_draw_structs(session);
|
||||
paint_session_free(session);
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include "../world/Location.hpp"
|
||||
#include "Window.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct paint_session;
|
||||
struct paint_struct;
|
||||
struct rct_drawpixelinfo;
|
||||
@@ -127,8 +129,12 @@ void viewport_update_smart_sprite_follow(rct_window* window);
|
||||
void viewport_update_smart_guest_follow(rct_window* window, rct_peep* peep);
|
||||
void viewport_update_smart_staff_follow(rct_window* window, rct_peep* peep);
|
||||
void viewport_update_smart_vehicle_follow(rct_window* window);
|
||||
void viewport_render(rct_drawpixelinfo* dpi, rct_viewport* viewport, int32_t left, int32_t top, int32_t right, int32_t bottom);
|
||||
void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int16_t left, int16_t top, int16_t right, int16_t bottom);
|
||||
void viewport_render(
|
||||
rct_drawpixelinfo* dpi, rct_viewport* viewport, int32_t left, int32_t top, int32_t right, int32_t bottom,
|
||||
std::vector<paint_session>* sessions = nullptr);
|
||||
void viewport_paint(
|
||||
rct_viewport* viewport, rct_drawpixelinfo* dpi, int16_t left, int16_t top, int16_t right, int16_t bottom,
|
||||
std::vector<paint_session>* sessions = nullptr);
|
||||
|
||||
void viewport_adjust_for_map_height(int16_t* x, int16_t* y, int16_t* z);
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<Import Project="..\..\openrct2.common.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>__ENABLE_DISCORD__;__ENABLE_LIGHTFX__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>__ENABLE_DISCORD__;__ENABLE_LIGHTFX__;USE_BENCHMARK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="'$(Breakpad)'=='true'">USE_BREAKPAD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
Reference in New Issue
Block a user