Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor benchgfx #10191

Merged
merged 1 commit into from Nov 8, 2019
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -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++)
double totalTime = 0.0;

std::array<double, MAX_ZOOM_LEVEL> zoomAverages;

// Render at every zoom.
for (int32_t zoom = 0; zoom < MAX_ZOOM_LEVEL; zoom++)
{
// 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;
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);
}
auto endTime = std::chrono::high_resolution_clock::now();
std::chrono::duration<float> duration = endTime - startTime;

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());
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;
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.