mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-24 00:03:11 +01:00
Merge pull request #20489 from ZehMatt/code-overhaul
Remove TestPaint and remove benchmark code
This commit is contained in:
@@ -100,7 +100,8 @@ option(STATIC "Create a static build.")
|
||||
option(USE_MMAP "Use mmap to try loading rct2's data segment into memory.")
|
||||
|
||||
option(DISABLE_DISCORD_RPC "Disable Discord-RPC support." OFF)
|
||||
option(DISABLE_GOOGLE_BENCHMARK "Disable Google Benchmarks support." OFF)
|
||||
# Currently unused, disable by default.
|
||||
option(DISABLE_GOOGLE_BENCHMARK "Disable Google Benchmarks support." ON)
|
||||
option(DISABLE_HTTP "Disable HTTP support.")
|
||||
option(DISABLE_NETWORK "Disable multiplayer functionality. Mainly for testing.")
|
||||
option(DISABLE_TTF "Disable support for TTF provided by freetype2.")
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
C4549: 'operator': operator before comma has no effect; did you intend 'operator'?
|
||||
C4555: expression has no effect; expected expression with side-effect
|
||||
-->
|
||||
<PreprocessorDefinitions>BENCHMARK_STATIC_DEFINE;OPENGL_NO_LINK;_CRT_SECURE_NO_WARNINGS;SDL_MAIN_HANDLED;_WINSOCK_DEPRECATED_NO_WARNINGS;NOMINMAX;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>OPENGL_NO_LINK;_CRT_SECURE_NO_WARNINGS;SDL_MAIN_HANDLED;_WINSOCK_DEPRECATED_NO_WARNINGS;NOMINMAX;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="'$(Platform)'=='Win32' or '$(Platform)'=='x64'">__AVX2__;__SSE4_1__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>ENABLE_SCRIPTING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary Condition="'$(UseSharedLibs)'!='true'">MultiThreaded</RuntimeLibrary>
|
||||
@@ -86,7 +86,7 @@
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
|
||||
<AdditionalDependencies>benchmark.lib;brotlicommon-static.lib;brotlidec-static.lib;brotlienc-static.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>brotlicommon-static.lib;brotlidec-static.lib;brotlienc-static.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies Condition="'$(Breakpad)'=='true' and ('$(Platform)'=='Win32' or '$(Platform)'=='x64')">libbreakpadd.lib;libbreakpad_clientd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>bz2d.lib;discord-rpc.lib;flac.lib;freetyped.lib;libpng16d.lib;ogg.lib;speexdsp.lib;SDL2-staticd.lib;vorbis.lib;vorbisfile.lib;zip.lib;zlibd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
@@ -107,7 +107,7 @@
|
||||
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>benchmark.lib;brotlicommon-static.lib;brotlidec-static.lib;brotlienc-static.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>brotlicommon-static.lib;brotlidec-static.lib;brotlienc-static.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies Condition="'$(Breakpad)'=='true' and ('$(Platform)'=='Win32' or '$(Platform)'=='x64')">libbreakpad.lib;libbreakpad_client.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>bz2.lib;discord-rpc.lib;flac.lib;freetype.lib;libpng16.lib;ogg.lib;speexdsp.lib;SDL2-static.lib;vorbis.lib;vorbisfile.lib;zip.lib;zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
|
||||
@@ -250,19 +250,10 @@ void GameState::Tick()
|
||||
gDoSingleUpdate = false;
|
||||
}
|
||||
|
||||
void GameState::UpdateLogic(LogicTimings* timings)
|
||||
void GameState::UpdateLogic()
|
||||
{
|
||||
PROFILED_FUNCTION();
|
||||
|
||||
auto start_time = std::chrono::high_resolution_clock::now();
|
||||
|
||||
auto report_time = [timings, start_time](LogicTimePart part) {
|
||||
if (timings != nullptr)
|
||||
{
|
||||
timings->TimingInfo[part][timings->CurrentIdx] = std::chrono::high_resolution_clock::now() - start_time;
|
||||
}
|
||||
};
|
||||
|
||||
gInUpdateCode = true;
|
||||
|
||||
gScreenAge++;
|
||||
@@ -272,7 +263,6 @@ void GameState::UpdateLogic(LogicTimings* timings)
|
||||
GetContext()->GetReplayManager()->Update();
|
||||
|
||||
NetworkUpdate();
|
||||
report_time(LogicTimePart::NetworkUpdate);
|
||||
|
||||
if (NetworkGetMode() == NETWORK_MODE_SERVER)
|
||||
{
|
||||
@@ -316,51 +306,33 @@ void GameState::UpdateLogic(LogicTimings* timings)
|
||||
#endif
|
||||
|
||||
_date.Update();
|
||||
report_time(LogicTimePart::Date);
|
||||
|
||||
ScenarioUpdate();
|
||||
report_time(LogicTimePart::Scenario);
|
||||
ClimateUpdate();
|
||||
report_time(LogicTimePart::Climate);
|
||||
MapUpdateTiles();
|
||||
report_time(LogicTimePart::MapTiles);
|
||||
// Temporarily remove provisional paths to prevent peep from interacting with them
|
||||
MapRemoveProvisionalElements();
|
||||
report_time(LogicTimePart::MapStashProvisionalElements);
|
||||
MapUpdatePathWideFlags();
|
||||
report_time(LogicTimePart::MapPathWideFlags);
|
||||
PeepUpdateAll();
|
||||
report_time(LogicTimePart::Peep);
|
||||
MapRestoreProvisionalElements();
|
||||
report_time(LogicTimePart::MapRestoreProvisionalElements);
|
||||
VehicleUpdateAll();
|
||||
report_time(LogicTimePart::Vehicle);
|
||||
UpdateAllMiscEntities();
|
||||
report_time(LogicTimePart::Misc);
|
||||
Ride::UpdateAll();
|
||||
report_time(LogicTimePart::Ride);
|
||||
|
||||
if (!(gScreenFlags & SCREEN_FLAGS_EDITOR))
|
||||
{
|
||||
_park->Update(_date);
|
||||
}
|
||||
report_time(LogicTimePart::Park);
|
||||
|
||||
ResearchUpdate();
|
||||
report_time(LogicTimePart::Research);
|
||||
RideRatingsUpdateAll();
|
||||
report_time(LogicTimePart::RideRatings);
|
||||
RideMeasurementsUpdate();
|
||||
report_time(LogicTimePart::RideMeasurments);
|
||||
News::UpdateCurrentItem();
|
||||
report_time(LogicTimePart::News);
|
||||
|
||||
MapAnimationInvalidateAll();
|
||||
report_time(LogicTimePart::MapAnimation);
|
||||
VehicleSoundsUpdate();
|
||||
PeepUpdateCrowdNoise();
|
||||
ClimateUpdateSound();
|
||||
report_time(LogicTimePart::Sounds);
|
||||
EditorOpenWindowsForCurrentStep();
|
||||
|
||||
// Update windows
|
||||
@@ -373,11 +345,9 @@ void GameState::UpdateLogic(LogicTimings* timings)
|
||||
}
|
||||
|
||||
GameActions::ProcessQueue();
|
||||
report_time(LogicTimePart::GameActions);
|
||||
|
||||
NetworkProcessPending();
|
||||
NetworkFlush();
|
||||
report_time(LogicTimePart::NetworkFlush);
|
||||
|
||||
gCurrentTicks++;
|
||||
gSavedAge++;
|
||||
@@ -390,14 +360,8 @@ void GameState::UpdateLogic(LogicTimings* timings)
|
||||
{
|
||||
hookEngine.Call(HOOK_TYPE::INTERVAL_DAY, true);
|
||||
}
|
||||
report_time(LogicTimePart::Scripts);
|
||||
#endif
|
||||
|
||||
if (timings != nullptr)
|
||||
{
|
||||
timings->CurrentIdx = (timings->CurrentIdx + 1) % LOGIC_UPDATE_MEASUREMENTS_COUNT;
|
||||
}
|
||||
|
||||
gInUpdateCode = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,46 +21,6 @@ namespace OpenRCT2
|
||||
{
|
||||
class Park;
|
||||
|
||||
// Information regarding various pieces of logic update
|
||||
enum class LogicTimePart
|
||||
{
|
||||
NetworkUpdate,
|
||||
Date,
|
||||
Scenario,
|
||||
Climate,
|
||||
MapTiles,
|
||||
MapStashProvisionalElements,
|
||||
MapPathWideFlags,
|
||||
Peep,
|
||||
MapRestoreProvisionalElements,
|
||||
Vehicle,
|
||||
Misc,
|
||||
Ride,
|
||||
Park,
|
||||
Research,
|
||||
RideRatings,
|
||||
RideMeasurments,
|
||||
News,
|
||||
MapAnimation,
|
||||
Sounds,
|
||||
GameActions,
|
||||
NetworkFlush,
|
||||
Scripts,
|
||||
};
|
||||
|
||||
// ~6.5s at 40Hz
|
||||
constexpr size_t LOGIC_UPDATE_MEASUREMENTS_COUNT = 256;
|
||||
|
||||
// In order not to cause allocations, collect multiple samples into single pre-allocated struct
|
||||
using LogicTimingInfo = std::unordered_map<
|
||||
LogicTimePart, std::array<std::chrono::duration<double>, LOGIC_UPDATE_MEASUREMENTS_COUNT>>;
|
||||
|
||||
struct LogicTimings
|
||||
{
|
||||
LogicTimingInfo TimingInfo;
|
||||
size_t CurrentIdx{};
|
||||
};
|
||||
|
||||
/**
|
||||
* Class to update the state of the map and park.
|
||||
*/
|
||||
@@ -85,7 +45,7 @@ namespace OpenRCT2
|
||||
|
||||
void InitAll(const TileCoordsXY& mapSize);
|
||||
void Tick();
|
||||
void UpdateLogic(LogicTimings* timings = nullptr);
|
||||
void UpdateLogic();
|
||||
void SetDate(Date newDate);
|
||||
void ResetDate();
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Copyright (c) 2014-2023 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 "../interface/Screenshot.h"
|
||||
#include "CommandLine.hpp"
|
||||
|
||||
static exitcode_t HandleBenchGfx(CommandLineArgEnumerator* argEnumerator);
|
||||
|
||||
const CommandLineCommand CommandLine::BenchGfxCommands[]{
|
||||
// Main commands
|
||||
DefineCommand("", "<file> [iterations count]", nullptr, HandleBenchGfx), CommandTableEnd
|
||||
};
|
||||
|
||||
static exitcode_t HandleBenchGfx(CommandLineArgEnumerator* argEnumerator)
|
||||
{
|
||||
const char** argv = const_cast<const char**>(argEnumerator->GetArguments()) + argEnumerator->GetIndex();
|
||||
int32_t argc = argEnumerator->GetCount() - argEnumerator->GetIndex();
|
||||
int32_t result = CommandLineForGfxbench(argv, argc);
|
||||
if (result < 0)
|
||||
{
|
||||
return EXITCODE_FAIL;
|
||||
}
|
||||
return EXITCODE_OK;
|
||||
}
|
||||
@@ -1,235 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Copyright (c) 2014-2023 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/File.h"
|
||||
# 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(std::vector<RecordedPaintSession>& s)
|
||||
{
|
||||
for (size_t i = 0; i < s.size(); i++)
|
||||
{
|
||||
auto& entries = s[i].Entries;
|
||||
auto& quadrants = s[i].Session.Quadrants;
|
||||
for (size_t j = 0; j < entries.size(); j++)
|
||||
{
|
||||
if (entries[j].AsBasic()->NextQuadrantEntry == reinterpret_cast<PaintStruct*>(-1))
|
||||
{
|
||||
entries[j].AsBasic()->NextQuadrantEntry = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto nextQuadrantPs = reinterpret_cast<size_t>(entries[j].AsBasic()->NextQuadrantEntry) / sizeof(PaintEntry);
|
||||
entries[j].AsBasic()->NextQuadrantEntry = s[i].Entries[nextQuadrantPs].AsBasic();
|
||||
}
|
||||
}
|
||||
for (size_t j = 0; j < std::size(quadrants); j++)
|
||||
{
|
||||
if (quadrants[j] == reinterpret_cast<PaintStruct*>(-1))
|
||||
{
|
||||
quadrants[j] = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto ps = reinterpret_cast<size_t>(quadrants[j]) / sizeof(PaintEntry);
|
||||
quadrants[j] = entries[ps].AsBasic();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<RecordedPaintSession> extract_paint_session(std::string_view parkFileName)
|
||||
{
|
||||
gOpenRCT2Headless = true;
|
||||
auto context = OpenRCT2::CreateContext();
|
||||
std::vector<RecordedPaintSession> sessions;
|
||||
LOG_INFO("Starting...");
|
||||
if (context->Initialise())
|
||||
{
|
||||
DrawingEngineInit();
|
||||
if (!context->LoadParkFromFile(std::string(parkFileName)))
|
||||
{
|
||||
LOG_ERROR("Failed to load park!");
|
||||
return {};
|
||||
}
|
||||
|
||||
gIntroState = IntroState::None;
|
||||
gScreenFlags = SCREEN_FLAGS_PLAYING;
|
||||
|
||||
int32_t resolutionWidth = (gMapSize.x * COORDS_XY_STEP * 2);
|
||||
int32_t resolutionHeight = (gMapSize.y * COORDS_XY_STEP * 1);
|
||||
|
||||
resolutionWidth += 8;
|
||||
resolutionHeight += 128;
|
||||
|
||||
Viewport viewport;
|
||||
viewport.pos = { 0, 0 };
|
||||
viewport.width = resolutionWidth;
|
||||
viewport.height = resolutionHeight;
|
||||
viewport.view_width = viewport.width;
|
||||
viewport.view_height = viewport.height;
|
||||
viewport.var_11 = 0;
|
||||
viewport.flags = 0;
|
||||
|
||||
auto customXY = TileCoordsXY(gMapSize.x / 2, gMapSize.y / 2).ToCoordsXY().ToTileCentre();
|
||||
auto customXYZ = CoordsXYZ(customXY, TileElementHeight(customXY));
|
||||
auto screenXY = Translate3DTo2DWithZ(0, customXYZ);
|
||||
|
||||
viewport.viewPos = { screenXY.x - (viewport.view_width / 2), screenXY.y - (viewport.view_height / 2) };
|
||||
viewport.zoom = ZoomLevel{ 0 };
|
||||
gCurrentRotation = 0;
|
||||
|
||||
// Ensure sprites appear regardless of rotation
|
||||
ResetAllSpriteQuadrantPlacements();
|
||||
|
||||
DrawPixelInfo dpi;
|
||||
dpi.x = 0;
|
||||
dpi.y = 0;
|
||||
dpi.width = resolutionWidth;
|
||||
dpi.height = resolutionHeight;
|
||||
dpi.pitch = 0;
|
||||
dpi.bits = static_cast<uint8_t*>(malloc(dpi.width * dpi.height));
|
||||
|
||||
LOG_INFO("Obtaining sprite data...");
|
||||
ViewportRender(dpi, &viewport, { { 0, 0 }, { viewport.width, viewport.height } }, &sessions);
|
||||
|
||||
free(dpi.bits);
|
||||
DrawingEngineDispose();
|
||||
}
|
||||
LOG_INFO("Got %u paint sessions.", std::size(sessions));
|
||||
return sessions;
|
||||
}
|
||||
|
||||
// This function is based on BenchgfxRenderScreenshots
|
||||
static void BM_paint_session_arrange(benchmark::State& state, const std::vector<RecordedPaintSession> inputSessions)
|
||||
{
|
||||
auto 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.
|
||||
RecordedPaintSession* local_s = new RecordedPaintSession[std::size(sessions)];
|
||||
fixup_pointers(sessions);
|
||||
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();
|
||||
PaintSessionArrange(sessions[0].Session);
|
||||
benchmark::DoNotOptimize(sessions);
|
||||
}
|
||||
state.SetItemsProcessed(state.iterations() * std::size(sessions));
|
||||
delete[] local_s;
|
||||
}
|
||||
|
||||
static int command_line_for_bench_sprite_sort(int argc, const char** argv)
|
||||
{
|
||||
{
|
||||
// Register some basic "baseline" benchmark
|
||||
std::vector<RecordedPaintSession> sessions(1);
|
||||
for (auto& ps : sessions[0].Entries)
|
||||
{
|
||||
ps.AsBasic()->NextQuadrantEntry = reinterpret_cast<PaintStruct*>(-1);
|
||||
}
|
||||
for (auto& quad : sessions[0].Session.Quadrants)
|
||||
{
|
||||
quad = reinterpret_cast<PaintStruct*>(-1);
|
||||
}
|
||||
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 (File::Exists(argv[i]))
|
||||
{
|
||||
// Register benchmark for sv6 if valid
|
||||
std::vector<RecordedPaintSession> sessions = extract_paint_session(argv[i]);
|
||||
if (!sessions.empty())
|
||||
benchmark::RegisterBenchmark(argv[i], BM_paint_session_arrange, sessions);
|
||||
}
|
||||
else
|
||||
{
|
||||
argv_for_benchmark.push_back(const_cast<char*>(argv[i]));
|
||||
}
|
||||
}
|
||||
// Update argc with all the changes made
|
||||
argc = static_cast<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_cast<const char**>(argEnumerator->GetArguments()) + argEnumerator->GetIndex();
|
||||
int32_t argc = argEnumerator->GetCount() - argEnumerator->GetIndex();
|
||||
int32_t result = command_line_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
|
||||
};
|
||||
@@ -1,160 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Copyright (c) 2014-2023 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 "../GameState.h"
|
||||
# include "../OpenRCT2.h"
|
||||
# include "../core/File.h"
|
||||
# include "../platform/Platform.h"
|
||||
|
||||
# include <benchmark/benchmark.h>
|
||||
# include <cstdint>
|
||||
# include <iterator>
|
||||
# include <numeric>
|
||||
# include <vector>
|
||||
|
||||
using namespace OpenRCT2;
|
||||
|
||||
static void BM_update(benchmark::State& state, const std::string& filename)
|
||||
{
|
||||
std::unique_ptr<IContext> context(CreateContext());
|
||||
if (context->Initialise())
|
||||
{
|
||||
if (!filename.empty() && !context->LoadParkFromFile(filename))
|
||||
{
|
||||
state.SkipWithError("Failed to load file!");
|
||||
}
|
||||
|
||||
std::vector<LogicTimings> timings(1);
|
||||
timings.reserve(100);
|
||||
int currentTimingIdx = 0;
|
||||
for (auto _ : state)
|
||||
{
|
||||
if (timings[currentTimingIdx].CurrentIdx == (LOGIC_UPDATE_MEASUREMENTS_COUNT - 1))
|
||||
{
|
||||
timings.resize(timings.size() + 1);
|
||||
currentTimingIdx++;
|
||||
}
|
||||
LogicTimings* timingToUse = &timings[currentTimingIdx];
|
||||
context->GetGameState()->UpdateLogic(timingToUse);
|
||||
}
|
||||
state.SetItemsProcessed(state.iterations());
|
||||
auto accumulator = [timings](LogicTimePart part) -> double {
|
||||
std::chrono::duration<double> timesum;
|
||||
for (const auto& timing : timings)
|
||||
{
|
||||
timesum = std::accumulate(
|
||||
timing.TimingInfo.at(part).begin(), timing.TimingInfo.at(part).end(), std::chrono::duration<double>());
|
||||
}
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(timesum).count();
|
||||
};
|
||||
state.counters["NetworkUpdateAcc_ms"] = accumulator(LogicTimePart::NetworkUpdate);
|
||||
state.counters["DateAcc_ms"] = accumulator(LogicTimePart::Date);
|
||||
state.counters["ScenarioAcc_ms"] = accumulator(LogicTimePart::Scenario);
|
||||
state.counters["ClimateAcc_ms"] = accumulator(LogicTimePart::Climate);
|
||||
state.counters["MapTilesAcc_ms"] = accumulator(LogicTimePart::MapTiles);
|
||||
state.counters["MapStashProvisionalElementsAcc_ms"] = accumulator(LogicTimePart::MapStashProvisionalElements);
|
||||
state.counters["MapPathWideFlagsAcc_ms"] = accumulator(LogicTimePart::MapPathWideFlags);
|
||||
state.counters["PeepAcc_ms"] = accumulator(LogicTimePart::Peep);
|
||||
state.counters["MapRestoreProvisionalElementsAcc_ms"] = accumulator(LogicTimePart::MapRestoreProvisionalElements);
|
||||
state.counters["VehicleAcc_ms"] = accumulator(LogicTimePart::Vehicle);
|
||||
state.counters["MiscAcc_ms"] = accumulator(LogicTimePart::Misc);
|
||||
state.counters["RideAcc_ms"] = accumulator(LogicTimePart::Ride);
|
||||
state.counters["ParkAcc_ms"] = accumulator(LogicTimePart::Park);
|
||||
state.counters["ResearchAcc_ms"] = accumulator(LogicTimePart::Research);
|
||||
state.counters["RideRatingsAcc_ms"] = accumulator(LogicTimePart::RideRatings);
|
||||
state.counters["RideMeasurmentsAcc_ms"] = accumulator(LogicTimePart::RideMeasurments);
|
||||
state.counters["NewsAcc_ms"] = accumulator(LogicTimePart::News);
|
||||
state.counters["MapAnimationAcc_ms"] = accumulator(LogicTimePart::MapAnimation);
|
||||
state.counters["SoundsAcc_ms"] = accumulator(LogicTimePart::Sounds);
|
||||
state.counters["GameActionsAcc_ms"] = accumulator(LogicTimePart::GameActions);
|
||||
state.counters["NetworkFlushAcc_ms"] = accumulator(LogicTimePart::NetworkFlush);
|
||||
state.counters["ScriptsAcc_ms"] = accumulator(LogicTimePart::Scripts);
|
||||
}
|
||||
else
|
||||
{
|
||||
state.SkipWithError("Context initialization failed.");
|
||||
}
|
||||
}
|
||||
|
||||
static int CommandLineForBenchSpriteSort(int argc, const char* const* argv)
|
||||
{
|
||||
// Add a baseline test on an empty park
|
||||
benchmark::RegisterBenchmark("baseline", BM_update, std::string{});
|
||||
|
||||
// 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 (File::Exists(argv[i]))
|
||||
{
|
||||
// Register benchmark for sv6 if valid
|
||||
benchmark::RegisterBenchmark(argv[i], BM_update, argv[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
argv_for_benchmark.push_back(const_cast<char*>(argv[i]));
|
||||
}
|
||||
}
|
||||
// Update argc with all the changes made
|
||||
argc = static_cast<int>(argv_for_benchmark.size());
|
||||
::benchmark::Initialize(&argc, &argv_for_benchmark[0]);
|
||||
if (::benchmark::ReportUnrecognizedArguments(argc, &argv_for_benchmark[0]))
|
||||
return -1;
|
||||
|
||||
gOpenRCT2Headless = true;
|
||||
|
||||
::benchmark::RunSpecifiedBenchmarks();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static exitcode_t HandleBenchUpdate(CommandLineArgEnumerator* argEnumerator)
|
||||
{
|
||||
const char* const* argv = static_cast<const char* const*>(argEnumerator->GetArguments()) + argEnumerator->GetIndex();
|
||||
int32_t argc = argEnumerator->GetCount() - argEnumerator->GetIndex();
|
||||
int32_t result = CommandLineForBenchSpriteSort(argc, argv);
|
||||
if (result < 0)
|
||||
{
|
||||
return EXITCODE_FAIL;
|
||||
}
|
||||
return EXITCODE_OK;
|
||||
}
|
||||
|
||||
#else
|
||||
static exitcode_t HandleBenchUpdate(CommandLineArgEnumerator* argEnumerator)
|
||||
{
|
||||
LOG_ERROR("Sorry, Google benchmark not enabled in this build");
|
||||
return EXITCODE_FAIL;
|
||||
}
|
||||
#endif // USE_BENCHMARK
|
||||
|
||||
const CommandLineCommand CommandLine::BenchUpdateCommands[]{
|
||||
#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, HandleBenchUpdate),
|
||||
CommandTableEnd
|
||||
#else
|
||||
DefineCommand("", "*** SORRY NOT ENABLED IN THIS BUILD ***", nullptr, HandleBenchUpdate), CommandTableEnd
|
||||
#endif // USE_BENCHMARK
|
||||
};
|
||||
@@ -116,9 +116,6 @@ namespace CommandLine
|
||||
extern const CommandLineCommand RootCommands[];
|
||||
extern const CommandLineCommand ScreenshotCommands[];
|
||||
extern const CommandLineCommand SpriteCommands[];
|
||||
extern const CommandLineCommand BenchGfxCommands[];
|
||||
extern const CommandLineCommand BenchSpriteSortCommands[];
|
||||
extern const CommandLineCommand BenchUpdateCommands[];
|
||||
extern const CommandLineCommand SimulateCommands[];
|
||||
extern const CommandLineCommand ParkInfoCommands[];
|
||||
|
||||
|
||||
@@ -140,9 +140,6 @@ const CommandLineCommand CommandLine::RootCommands[]
|
||||
// Sub-commands
|
||||
DefineSubCommand("screenshot", CommandLine::ScreenshotCommands ),
|
||||
DefineSubCommand("sprite", CommandLine::SpriteCommands ),
|
||||
DefineSubCommand("benchgfx", CommandLine::BenchGfxCommands ),
|
||||
DefineSubCommand("benchspritesort", CommandLine::BenchSpriteSortCommands ),
|
||||
DefineSubCommand("benchsimulate", CommandLine::BenchUpdateCommands ),
|
||||
DefineSubCommand("simulate", CommandLine::SimulateCommands ),
|
||||
DefineSubCommand("parkinfo", CommandLine::ParkInfoCommands ),
|
||||
CommandTableEnd
|
||||
|
||||
@@ -391,129 +391,6 @@ void ScreenshotGiant()
|
||||
ReleaseDPI(dpi);
|
||||
}
|
||||
|
||||
// TODO: Move this at some point into a more appropriate place.
|
||||
template<typename FN> static inline double MeasureFunctionTime(const FN& fn)
|
||||
{
|
||||
const auto startTime = std::chrono::high_resolution_clock::now();
|
||||
fn();
|
||||
const auto endTime = std::chrono::high_resolution_clock::now();
|
||||
return std::chrono::duration<double>(endTime - startTime).count();
|
||||
}
|
||||
|
||||
static void BenchgfxRenderScreenshots(const char* inputPath, std::unique_ptr<IContext>& context, uint32_t iterationCount)
|
||||
{
|
||||
if (!context->LoadParkFromFile(inputPath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gIntroState = IntroState::None;
|
||||
gScreenFlags = SCREEN_FLAGS_PLAYING;
|
||||
|
||||
// Create Viewport and DPI for every rotation and zoom.
|
||||
// We iterate from the default zoom level to the max zoomed out zoom level, then run GetGiantViewport once for each
|
||||
// rotation.
|
||||
constexpr int32_t NUM_ROTATIONS = 4;
|
||||
constexpr auto NUM_ZOOM_LEVELS = static_cast<int8_t>(ZoomLevel::max());
|
||||
std::array<DrawPixelInfo, NUM_ROTATIONS * NUM_ZOOM_LEVELS> dpis;
|
||||
std::array<Viewport, NUM_ROTATIONS * NUM_ZOOM_LEVELS> viewports;
|
||||
|
||||
for (ZoomLevel zoom{ 0 }; zoom < ZoomLevel::max(); zoom++)
|
||||
{
|
||||
int32_t zoomIndex{ static_cast<int8_t>(zoom) };
|
||||
for (int32_t rotation = 0; rotation < NUM_ROTATIONS; rotation++)
|
||||
{
|
||||
auto& viewport = viewports[zoomIndex * NUM_ZOOM_LEVELS + rotation];
|
||||
auto& dpi = dpis[zoomIndex * NUM_ZOOM_LEVELS + rotation];
|
||||
viewport = GetGiantViewport(rotation, zoom);
|
||||
dpi = CreateDPI(viewport);
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t totalRenderCount = iterationCount * NUM_ROTATIONS * NUM_ZOOM_LEVELS;
|
||||
|
||||
try
|
||||
{
|
||||
double totalTime = 0.0;
|
||||
|
||||
std::array<double, NUM_ZOOM_LEVELS> zoomAverages;
|
||||
|
||||
// Render at every zoom.
|
||||
for (int32_t zoom = 0; zoom < NUM_ZOOM_LEVELS; zoom++)
|
||||
{
|
||||
double zoomLevelTime = 0.0;
|
||||
|
||||
// Render at every rotation.
|
||||
for (int32_t rotation = 0; rotation < NUM_ROTATIONS; rotation++)
|
||||
{
|
||||
// N iterations.
|
||||
for (uint32_t i = 0; i < iterationCount; i++)
|
||||
{
|
||||
auto& dpi = dpis[zoom * NUM_ZOOM_LEVELS + rotation];
|
||||
auto& viewport = viewports[zoom * NUM_ZOOM_LEVELS + rotation];
|
||||
double elapsed = MeasureFunctionTime([&viewport, &dpi]() { RenderViewport(nullptr, viewport, dpi); });
|
||||
totalTime += elapsed;
|
||||
zoomLevelTime += elapsed;
|
||||
}
|
||||
}
|
||||
|
||||
zoomAverages[zoom] = zoomLevelTime / static_cast<double>(NUM_ROTATIONS * iterationCount);
|
||||
}
|
||||
|
||||
const double average = totalTime / static_cast<double>(totalRenderCount);
|
||||
const auto engineStringId = DrawingEngineStringIds[EnumValue(DrawingEngine::Software)];
|
||||
const auto engineName = FormatStringID(engineStringId, nullptr);
|
||||
std::printf("Engine: %s\n", engineName.c_str());
|
||||
std::printf("Render Count: %u\n", totalRenderCount);
|
||||
for (ZoomLevel zoom{ 0 }; zoom < ZoomLevel::max(); zoom++)
|
||||
{
|
||||
int32_t zoomIndex{ static_cast<int8_t>(zoom) };
|
||||
const auto zoomAverage = zoomAverages[zoomIndex];
|
||||
std::printf("Zoom[%d] average: %.06fs, %.f FPS\n", zoomIndex, zoomAverage, 1.0 / zoomAverage);
|
||||
}
|
||||
std::printf("Total average: %.06fs, %.f FPS\n", average, 1.0 / average);
|
||||
std::printf("Time: %.05fs\n", totalTime);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
Console::Error::WriteLine("%s", e.what());
|
||||
}
|
||||
|
||||
for (auto& dpi : dpis)
|
||||
ReleaseDPI(dpi);
|
||||
}
|
||||
|
||||
int32_t CommandLineForGfxbench(const char** argv, int32_t argc)
|
||||
{
|
||||
if (argc != 1 && argc != 2)
|
||||
{
|
||||
printf("Usage: openrct2 benchgfx <file> [<iteration_count>]\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t iterationCount = 5;
|
||||
if (argc == 2)
|
||||
{
|
||||
iterationCount = atoi(argv[1]);
|
||||
}
|
||||
|
||||
const char* inputPath = argv[0];
|
||||
|
||||
gOpenRCT2Headless = true;
|
||||
|
||||
std::unique_ptr<IContext> context(CreateContext());
|
||||
if (context->Initialise())
|
||||
{
|
||||
DrawingEngineInit();
|
||||
|
||||
BenchgfxRenderScreenshots(inputPath, context, iterationCount);
|
||||
|
||||
DrawingEngineDispose();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ApplyOptions(const ScreenshotOptions* options, Viewport& viewport)
|
||||
{
|
||||
if (options->weather != WeatherType::Sunny && options->weather != WeatherType::Count)
|
||||
|
||||
@@ -59,6 +59,5 @@ std::string ScreenshotDumpPNG32bpp(int32_t width, int32_t height, const void* pi
|
||||
|
||||
void ScreenshotGiant();
|
||||
int32_t CommandLineForScreenshot(const char** argv, int32_t argc, ScreenshotOptions* options);
|
||||
int32_t CommandLineForGfxbench(const char** argv, int32_t argc);
|
||||
|
||||
void CaptureImage(const CaptureOptions& options);
|
||||
|
||||
@@ -806,8 +806,7 @@ void ViewportUpdateSmartFollowVehicle(WindowBase* window)
|
||||
* edi: dpi
|
||||
* ebp: bottom
|
||||
*/
|
||||
void ViewportRender(
|
||||
DrawPixelInfo& dpi, const Viewport* viewport, const ScreenRect& screenRect, std::vector<RecordedPaintSession>* sessions)
|
||||
void ViewportRender(DrawPixelInfo& dpi, const Viewport* viewport, const ScreenRect& screenRect)
|
||||
{
|
||||
auto [topLeft, bottomRight] = screenRect;
|
||||
|
||||
@@ -837,7 +836,7 @@ void ViewportRender(
|
||||
viewport->zoom.ApplyTo(std::min(bottomRight.y, viewport->height)),
|
||||
} + viewport->viewPos;
|
||||
|
||||
ViewportPaint(viewport, dpi, { topLeft, bottomRight }, sessions);
|
||||
ViewportPaint(viewport, dpi, { topLeft, bottomRight });
|
||||
|
||||
#ifdef DEBUG_SHOW_DIRTY_BOX
|
||||
// FIXME g_viewport_list doesn't exist anymore
|
||||
@@ -846,75 +845,11 @@ void ViewportRender(
|
||||
#endif
|
||||
}
|
||||
|
||||
static void RecordSession(
|
||||
const PaintSession& session, std::vector<RecordedPaintSession>* recorded_sessions, size_t record_index)
|
||||
{
|
||||
// Perform a deep copy of the paint session, use relative offsets.
|
||||
// This is done to extract the session for benchmark.
|
||||
// Place the copied session at provided record_index, so the caller can decide which columns/paint sessions to copy;
|
||||
// there is no column information embedded in the session itself.
|
||||
auto& recordedSession = recorded_sessions->at(record_index);
|
||||
recordedSession.Session = session;
|
||||
recordedSession.Entries.resize(session.PaintEntryChain.GetCount());
|
||||
|
||||
// Mind the offset needs to be calculated against the original `session`, not `session_copy`
|
||||
std::unordered_map<PaintStruct*, PaintStruct*> entryRemap;
|
||||
|
||||
// Copy all entries
|
||||
auto paintIndex = 0;
|
||||
auto chain = session.PaintEntryChain.Head;
|
||||
while (chain != nullptr)
|
||||
{
|
||||
for (size_t i = 0; i < chain->Count; i++)
|
||||
{
|
||||
auto& src = chain->PaintStructs[i];
|
||||
auto& dst = recordedSession.Entries[paintIndex++];
|
||||
dst = src;
|
||||
entryRemap[src.AsBasic()] = reinterpret_cast<PaintStruct*>(i * sizeof(PaintEntry));
|
||||
}
|
||||
chain = chain->Next;
|
||||
}
|
||||
entryRemap[nullptr] = reinterpret_cast<PaintStruct*>(-1);
|
||||
|
||||
// Remap all entries
|
||||
for (auto& ps : recordedSession.Entries)
|
||||
{
|
||||
auto& ptr = ps.AsBasic()->NextQuadrantEntry;
|
||||
auto it = entryRemap.find(ptr);
|
||||
if (it == entryRemap.end())
|
||||
{
|
||||
assert(false);
|
||||
ptr = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = it->second;
|
||||
}
|
||||
}
|
||||
for (auto& ptr : recordedSession.Session.Quadrants)
|
||||
{
|
||||
auto it = entryRemap.find(ptr);
|
||||
if (it == entryRemap.end())
|
||||
{
|
||||
assert(false);
|
||||
ptr = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = it->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ViewportFillColumn(PaintSession& session, std::vector<RecordedPaintSession>* recorded_sessions, size_t record_index)
|
||||
static void ViewportFillColumn(PaintSession& session)
|
||||
{
|
||||
PROFILED_FUNCTION();
|
||||
|
||||
PaintSessionGenerate(session);
|
||||
if (recorded_sessions != nullptr)
|
||||
{
|
||||
RecordSession(session, recorded_sessions, record_index);
|
||||
}
|
||||
PaintSessionArrange(session);
|
||||
}
|
||||
|
||||
@@ -959,9 +894,7 @@ static void ViewportPaintColumn(PaintSession& session)
|
||||
* edi: dpi
|
||||
* ebp: bottom
|
||||
*/
|
||||
void ViewportPaint(
|
||||
const Viewport* viewport, DrawPixelInfo& dpi, const ScreenRect& screenRect,
|
||||
std::vector<RecordedPaintSession>* recorded_sessions)
|
||||
void ViewportPaint(const Viewport* viewport, DrawPixelInfo& dpi, const ScreenRect& screenRect)
|
||||
{
|
||||
PROFILED_FUNCTION();
|
||||
|
||||
@@ -1019,17 +952,8 @@ void ViewportPaint(
|
||||
useParallelDrawing = true;
|
||||
}
|
||||
|
||||
// Create space to record sessions and keep track which index is being drawn
|
||||
size_t index = 0;
|
||||
if (recorded_sessions != nullptr)
|
||||
{
|
||||
auto columnSize = rightBorder - alignedX;
|
||||
auto columnCount = (columnSize + 31) / 32;
|
||||
recorded_sessions->resize(columnCount);
|
||||
}
|
||||
|
||||
// Generate and sort columns.
|
||||
for (x = alignedX; x < rightBorder; x += 32, index++)
|
||||
for (x = alignedX; x < rightBorder; x += 32)
|
||||
{
|
||||
PaintSession* session = PaintSessionAlloc(dpi1, viewFlags);
|
||||
_paintColumns.push_back(session);
|
||||
@@ -1055,12 +979,11 @@ void ViewportPaint(
|
||||
|
||||
if (useMultithreading)
|
||||
{
|
||||
_paintJobs->AddTask(
|
||||
[session, recorded_sessions, index]() -> void { ViewportFillColumn(*session, recorded_sessions, index); });
|
||||
_paintJobs->AddTask([session]() -> void { ViewportFillColumn(*session); });
|
||||
}
|
||||
else
|
||||
{
|
||||
ViewportFillColumn(*session, recorded_sessions, index);
|
||||
ViewportFillColumn(*session);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <vector>
|
||||
|
||||
struct PaintSession;
|
||||
struct RecordedPaintSession;
|
||||
struct PaintStruct;
|
||||
struct DrawPixelInfo;
|
||||
struct TileElement;
|
||||
@@ -140,12 +139,8 @@ void ViewportUpdateSmartFollowEntity(WindowBase* window);
|
||||
void ViewportUpdateSmartFollowGuest(WindowBase* window, const Guest* peep);
|
||||
void ViewportUpdateSmartFollowStaff(WindowBase* window, const Staff* peep);
|
||||
void ViewportUpdateSmartFollowVehicle(WindowBase* window);
|
||||
void ViewportRender(
|
||||
DrawPixelInfo& dpi, const Viewport* viewport, const ScreenRect& screenRect,
|
||||
std::vector<RecordedPaintSession>* sessions = nullptr);
|
||||
void ViewportPaint(
|
||||
const Viewport* viewport, DrawPixelInfo& dpi, const ScreenRect& screenRect,
|
||||
std::vector<RecordedPaintSession>* sessions = nullptr);
|
||||
void ViewportRender(DrawPixelInfo& dpi, const Viewport* viewport, const ScreenRect& screenRect);
|
||||
void ViewportPaint(const Viewport* viewport, DrawPixelInfo& dpi, const ScreenRect& screenRect);
|
||||
|
||||
CoordsXYZ ViewportAdjustForMapHeight(const ScreenCoordsXY& startCoords);
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
<Import Project="..\..\openrct2.common.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>__ENABLE_DISCORD__;USE_BENCHMARK;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>__ENABLE_DISCORD__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="'$(Breakpad)'=='true' and ('$(Platform)'=='Win32' or '$(Platform)'=='x64')">USE_BREAKPAD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="'$(Platform)'=='Win32' or '$(Platform)'=='x64'">USE_FRIBIDI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader Condition="'$(UsePCH)'=='true'">Use</PrecompiledHeader>
|
||||
@@ -690,9 +690,6 @@
|
||||
<ClCompile Include="audio\DummyAudioContext.cpp" />
|
||||
<ClCompile Include="Cheats.cpp" />
|
||||
<ClCompile Include="CommandLineSprite.cpp" />
|
||||
<ClCompile Include="command_line\BenchGfxCommmands.cpp" />
|
||||
<ClCompile Include="command_line\BenchSpriteSort.cpp" />
|
||||
<ClCompile Include="command_line/BenchUpdate.cpp" />
|
||||
<ClCompile Include="command_line\CommandLine.cpp" />
|
||||
<ClCompile Include="command_line\ConvertCommand.cpp" />
|
||||
<ClCompile Include="command_line\ParkInfoCommands.cpp" />
|
||||
|
||||
@@ -270,12 +270,6 @@ struct FootpathPaintInfo
|
||||
colour_t SupportColour = 255;
|
||||
};
|
||||
|
||||
struct RecordedPaintSession
|
||||
{
|
||||
PaintSessionCore Session;
|
||||
std::vector<PaintEntry> Entries;
|
||||
};
|
||||
|
||||
extern PaintSession gPaintSession;
|
||||
|
||||
// Globals for paint clipping
|
||||
|
||||
Reference in New Issue
Block a user