1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-23 15:52:55 +01:00

Refactor benchgfx

This commit is contained in:
Matt
2019-11-03 18:44:58 +01:00
parent 8dc5865e6f
commit d3103b6397

View File

@@ -320,6 +320,34 @@ static int32_t GetTallestVisibleTileTop(int32_t mapSize, int32_t rotation)
return minViewY - 256;
}
static rct_drawpixelinfo CreateDPI(const rct_viewport& viewport)
{
rct_drawpixelinfo dpi;
dpi.width = viewport.width;
dpi.height = viewport.height;
dpi.bits = new (std::nothrow) uint8_t[dpi.width * dpi.height];
if (dpi.bits == nullptr)
{
throw std::runtime_error("Giant screenshot failed, unable to allocate memory for image.");
}
if (viewport.flags & VIEWPORT_FLAG_TRANSPARENT_BACKGROUND)
{
std::memset(dpi.bits, PALETTE_INDEX_0, (size_t)dpi.width * dpi.height);
}
return dpi;
}
static void ReleaseDPI(rct_drawpixelinfo& dpi)
{
if (dpi.bits != nullptr)
delete[] dpi.bits;
dpi.bits = nullptr;
dpi.width = 0;
dpi.height = 0;
}
static rct_viewport GetGiantViewport(int32_t mapSize, int32_t rotation, int32_t zoom)
{
// Get the tile coordinates of each corner
@@ -349,25 +377,11 @@ static rct_viewport GetGiantViewport(int32_t mapSize, int32_t rotation, int32_t
return viewport;
}
static rct_drawpixelinfo RenderViewport(IDrawingEngine* drawingEngine, const rct_viewport& viewport)
static void RenderViewport(IDrawingEngine* drawingEngine, const rct_viewport& viewport, rct_drawpixelinfo& dpi)
{
// Ensure sprites appear regardless of rotation
reset_all_sprite_quadrant_placements();
rct_drawpixelinfo dpi;
dpi.width = viewport.width;
dpi.height = viewport.height;
dpi.bits = (uint8_t*)malloc((size_t)dpi.width * dpi.height);
if (dpi.bits == nullptr)
{
throw std::runtime_error("Giant screenshot failed, unable to allocate memory for image.");
}
if (viewport.flags & VIEWPORT_FLAG_TRANSPARENT_BACKGROUND)
{
std::memset(dpi.bits, PALETTE_INDEX_0, (size_t)dpi.width * dpi.height);
}
std::unique_ptr<X8DrawingEngine> tempDrawingEngine;
if (drawingEngine == nullptr)
{
@@ -376,12 +390,11 @@ static rct_drawpixelinfo RenderViewport(IDrawingEngine* drawingEngine, const rct
}
dpi.DrawingEngine = drawingEngine;
viewport_render(&dpi, &viewport, 0, 0, viewport.width, viewport.height);
return dpi;
}
void screenshot_giant()
{
rct_drawpixelinfo dpi;
rct_drawpixelinfo dpi{};
try
{
auto path = screenshot_get_next_path();
@@ -410,7 +423,9 @@ void screenshot_giant()
viewport.flags |= VIEWPORT_FLAG_TRANSPARENT_BACKGROUND;
}
dpi = RenderViewport(nullptr, viewport);
dpi = CreateDPI(viewport);
RenderViewport(nullptr, viewport, dpi);
auto renderedPalette = screenshot_get_rendered_palette();
WriteDpiToFile(path->c_str(), &dpi, renderedPalette);
@@ -424,7 +439,17 @@ void screenshot_giant()
log_error("%s", e.what());
context_show_error(STR_SCREENSHOT_FAILED, STR_NONE);
}
free(dpi.bits);
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 benchgfx_render_screenshots(const char* inputPath, std::unique_ptr<IContext>& context, uint32_t iterationCount)
@@ -437,33 +462,73 @@ static void benchgfx_render_screenshots(const char* inputPath, std::unique_ptr<I
gIntroState = INTRO_STATE_NONE;
gScreenFlags = SCREEN_FLAGS_PLAYING;
rct_drawpixelinfo dpi;
// Create Viewport and DPI for every rotation and zoom.
constexpr int32_t MAX_ROTATIONS = 4;
std::array<rct_drawpixelinfo, MAX_ROTATIONS * MAX_ZOOM_LEVEL> dpis;
std::array<rct_viewport, MAX_ROTATIONS * MAX_ZOOM_LEVEL> viewports;
for (int32_t zoom = 0; zoom < MAX_ZOOM_LEVEL; zoom++)
{
for (int32_t rotation = 0; rotation < MAX_ROTATIONS; rotation++)
{
auto& viewport = viewports[zoom * MAX_ZOOM_LEVEL + rotation];
auto& dpi = dpis[zoom * MAX_ZOOM_LEVEL + rotation];
viewport = GetGiantViewport(gMapSize, rotation, zoom);
dpi = CreateDPI(viewport);
}
}
const uint32_t totalRenderCount = iterationCount * MAX_ROTATIONS * MAX_ZOOM_LEVEL;
try
{
auto startTime = std::chrono::high_resolution_clock::now();
for (uint32_t i = 0; i < iterationCount; i++)
{
// Render at various zoom levels
auto viewport = GetGiantViewport(gMapSize, get_current_rotation(), 0);
viewport.zoom = i & 3;
dpi = RenderViewport(nullptr, viewport);
free(dpi.bits);
dpi.bits = nullptr;
}
auto endTime = std::chrono::high_resolution_clock::now();
std::chrono::duration<float> duration = endTime - startTime;
double totalTime = 0.0;
auto engineStringId = DrawingEngineStringIds[DRAWING_ENGINE_SOFTWARE];
auto engineName = format_string(engineStringId, nullptr);
std::printf(
"Rendering %u times with drawing engine %s took %.2f seconds.", iterationCount, engineName.c_str(),
duration.count());
std::array<double, MAX_ZOOM_LEVEL> zoomAverages;
// Render at every zoom.
for (int32_t zoom = 0; zoom < MAX_ZOOM_LEVEL; zoom++)
{
double zoomLevelTime = 0.0;
// Render at every rotation.
for (int32_t rotation = 0; rotation < MAX_ROTATIONS; rotation++)
{
// N iterations.
for (uint32_t i = 0; i < iterationCount; i++)
{
auto& dpi = dpis[zoom * MAX_ZOOM_LEVEL + rotation];
auto& viewport = viewports[zoom * MAX_ZOOM_LEVEL + rotation];
double elapsed = MeasureFunctionTime([&viewport, &dpi]() { RenderViewport(nullptr, viewport, dpi); });
totalTime += elapsed;
zoomLevelTime += elapsed;
}
}
zoomAverages[zoom] = zoomLevelTime / static_cast<double>(MAX_ROTATIONS * iterationCount);
}
const double average = totalTime / static_cast<double>(totalRenderCount);
const auto engineStringId = DrawingEngineStringIds[DRAWING_ENGINE_SOFTWARE];
const auto engineName = format_string(engineStringId, nullptr);
std::printf("Engine: %s\n", engineName.c_str());
std::printf("Render Count: %u\n", totalRenderCount);
for (int32_t zoom = 0; zoom < MAX_ZOOM_LEVEL; zoom++)
{
const auto zoomAverage = zoomAverages[zoom];
std::printf("Zoom[%d] average: %.06fs, %.f FPS\n", zoom, 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)
{
std::fprintf(stderr, "%s", e.what());
}
free(dpi.bits);
for (auto& dpi : dpis)
ReleaseDPI(dpi);
}
int32_t cmdline_for_gfxbench(const char** argv, int32_t argc)
@@ -475,7 +540,7 @@ int32_t cmdline_for_gfxbench(const char** argv, int32_t argc)
}
core_init();
int32_t iterationCount = 40;
int32_t iterationCount = 5;
if (argc == 2)
{
iterationCount = atoi(argv[1]);
@@ -677,7 +742,9 @@ int32_t cmdline_for_screenshot(const char** argv, int32_t argc, ScreenshotOption
ApplyOptions(options, viewport);
dpi = RenderViewport(nullptr, viewport);
dpi = CreateDPI(viewport);
RenderViewport(nullptr, viewport, dpi);
auto renderedPalette = screenshot_get_rendered_palette();
WriteDpiToFile(outputPath, &dpi, renderedPalette);
}
@@ -686,7 +753,8 @@ int32_t cmdline_for_screenshot(const char** argv, int32_t argc, ScreenshotOption
std::printf("%s\n", e.what());
exitCode = -1;
}
free(dpi.bits);
ReleaseDPI(dpi);
drawing_engine_dispose();
return exitCode;