forked from diasurgical/DevilutionX
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdun_render_benchmark.cpp
More file actions
137 lines (119 loc) · 4.39 KB
/
dun_render_benchmark.cpp
File metadata and controls
137 lines (119 loc) · 4.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <cstddef>
#include <span>
#include <ankerl/unordered_dense.h>
#include <benchmark/benchmark.h>
#include "diablo.h"
#include "engine/assets.hpp"
#include "engine/clx_sprite.hpp"
#include "engine/displacement.hpp"
#include "engine/load_file.hpp"
#include "engine/render/dun_render.hpp"
#include "engine/surface.hpp"
#include "levels/dun_tile.hpp"
#include "levels/gendung.h"
#include "lighting.h"
#include "options.h"
#include "utils/log.hpp"
#include "utils/sdl_wrap.h"
namespace devilution {
namespace {
SDLSurfaceUniquePtr SdlSurface;
ankerl::unordered_dense::map<TileType, std::vector<LevelCelBlock>> Tiles;
void InitOnce()
{
[[maybe_unused]] static const bool GlobalInitDone = []() {
LoadCoreArchives();
LoadGameArchives();
if (!HaveSpawn() && !HaveDiabdat()) {
LogError("This benchmark needs spawn.mpq or diabdat.mpq");
exit(1);
}
leveltype = DTYPE_CATHEDRAL;
pDungeonCels = LoadFileInMem("levels\\l1data\\l1.cel");
SetDungeonMicros();
MakeLightTable();
SdlSurface = SDLWrap::CreateRGBSurfaceWithFormat(
/*flags=*/0, /*width=*/640, /*height=*/480, /*depth=*/8, SDL_PIXELFORMAT_INDEX8);
if (SdlSurface == nullptr) {
LogError("Failed to create SDL Surface: {}", SDL_GetError());
exit(1);
}
for (size_t i = 0; i < 700; ++i) {
for (size_t j = 0; j < 10; ++j) {
if (const LevelCelBlock levelCelBlock = DPieceMicros[i].mt[j]; levelCelBlock.hasValue()) {
if ((j == 0 || j == 1) && levelCelBlock.type() == TileType::TransparentSquare) {
// This could actually be re-encoded foliage, which is a triangle followed by TransparentSquare.
// Simply skip it.
continue;
}
Tiles[levelCelBlock.type()].push_back(levelCelBlock);
}
}
}
return true;
}();
}
void RunForTileMaskLight(benchmark::State &state, TileType tileType, MaskType maskType, const uint8_t *lightTable)
{
Surface out = Surface(SdlSurface.get());
Lightmap lightmap(nullptr, {}, 1, nullptr, 0);
size_t numItemsProcessed = 0;
const std::span<const LevelCelBlock> tiles = Tiles[tileType];
for (auto _ : state) {
for (const LevelCelBlock &levelCelBlock : tiles) {
RenderTile(out, lightmap, Point { 320, 240 }, levelCelBlock, maskType, lightTable);
uint8_t color = out[Point { 310, 200 }];
benchmark::DoNotOptimize(color);
}
numItemsProcessed += tiles.size();
}
state.SetItemsProcessed(numItemsProcessed);
}
using GetLightTableFn = const uint8_t *();
const uint8_t *FullyLit() { return FullyLitLightTable; }
const uint8_t *FullyDark() { return FullyDarkLightTable; }
const uint8_t *PartiallyLit() { return LightTables[5].data(); }
template <TileType TileT, MaskType MaskT, GetLightTableFn GetLightTableFnT>
void Render(benchmark::State &state)
{
InitOnce();
RunForTileMaskLight(state, TileT, MaskT, GetLightTableFnT());
}
// Define aliases in order to have shorter benchmark names.
constexpr auto LeftTriangle = TileType::LeftTriangle;
constexpr auto RightTriangle = TileType::RightTriangle;
constexpr auto TransparentSquare = TileType::TransparentSquare;
constexpr auto Square = TileType::Square;
constexpr auto LeftTrapezoid = TileType::LeftTrapezoid;
constexpr auto RightTrapezoid = TileType::RightTrapezoid;
constexpr auto Transparent = MaskType::Transparent;
constexpr auto Solid = MaskType::Solid;
#define DEFINE_FOR_TILE_AND_MASK_TYPE(TILE_TYPE, MASK_TYPE) \
BENCHMARK_TEMPLATE(Render, TILE_TYPE, MASK_TYPE, FullyLit); \
BENCHMARK_TEMPLATE(Render, TILE_TYPE, MASK_TYPE, FullyDark); \
BENCHMARK_TEMPLATE(Render, TILE_TYPE, MASK_TYPE, PartiallyLit);
#define DEFINE_FOR_TILE_TYPE(TILE_TYPE) \
DEFINE_FOR_TILE_AND_MASK_TYPE(TILE_TYPE, Solid) \
DEFINE_FOR_TILE_AND_MASK_TYPE(TILE_TYPE, Transparent)
DEFINE_FOR_TILE_TYPE(LeftTriangle)
DEFINE_FOR_TILE_TYPE(RightTriangle)
DEFINE_FOR_TILE_TYPE(TransparentSquare)
DEFINE_FOR_TILE_TYPE(Square)
DEFINE_FOR_TILE_TYPE(LeftTrapezoid)
DEFINE_FOR_TILE_TYPE(RightTrapezoid)
void BM_RenderBlackTile(benchmark::State &state)
{
InitOnce();
Surface out = Surface(SdlSurface.get());
size_t numItemsProcessed = 0;
for (auto _ : state) {
world_draw_black_tile(out, 320, 240);
uint8_t color = out[Point { 310, 200 }];
benchmark::DoNotOptimize(color);
++numItemsProcessed;
}
state.SetItemsProcessed(numItemsProcessed);
}
BENCHMARK(BM_RenderBlackTile);
} // namespace
} // namespace devilution