You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
4.4 KiB
137 lines
4.4 KiB
#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 (!HaveMainData()) { |
|
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
|
|
|