diff --git a/Source/engine/render/blit_impl.hpp b/Source/engine/render/blit_impl.hpp index f352b5a19fd9..5d6bb8e72c9b 100644 --- a/Source/engine/render/blit_impl.hpp +++ b/Source/engine/render/blit_impl.hpp @@ -10,12 +10,6 @@ namespace devilution { -#if __cpp_lib_execution >= 201902L -#define DEVILUTIONX_BLIT_EXECUTION_POLICY std::execution::unseq, -#else -#define DEVILUTIONX_BLIT_EXECUTION_POLICY -#endif - DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitFillDirect(uint8_t *dst, unsigned length, uint8_t color) { DVL_ASSUME(length != 0); @@ -48,7 +42,7 @@ DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitFillWithMap(uint8_t *dst, unsigned DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitPixelsWithMap(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, unsigned length, const uint8_t *DVL_RESTRICT colorMap) { DVL_ASSUME(length != 0); - std::transform(DEVILUTIONX_BLIT_EXECUTION_POLICY src, src + length, dst, [colorMap](uint8_t srcColor) { return colorMap[srcColor]; }); + std::transform(DVL_EXECUTION_UNSEQ src, src + length, dst, [colorMap](uint8_t srcColor) { return colorMap[srcColor]; }); } struct BlitWithMap { @@ -67,7 +61,7 @@ struct BlitWithMap { DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitFillBlended(uint8_t *dst, unsigned length, uint8_t color) { DVL_ASSUME(length != 0); - std::for_each(DEVILUTIONX_BLIT_EXECUTION_POLICY dst, dst + length, [tbl = paletteTransparencyLookup[color]](uint8_t &dstColor) { + std::for_each(DVL_EXECUTION_UNSEQ dst, dst + length, [tbl = paletteTransparencyLookup[color]](uint8_t &dstColor) { dstColor = tbl[dstColor]; }); } @@ -75,7 +69,7 @@ DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitFillBlended(uint8_t *dst, unsigned DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitPixelsBlended(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, unsigned length) { DVL_ASSUME(length != 0); - std::transform(DEVILUTIONX_BLIT_EXECUTION_POLICY src, src + length, dst, dst, [pal = paletteTransparencyLookup](uint8_t srcColor, uint8_t dstColor) { + std::transform(DVL_EXECUTION_UNSEQ src, src + length, dst, dst, [pal = paletteTransparencyLookup](uint8_t srcColor, uint8_t dstColor) { return pal[srcColor][dstColor]; }); } @@ -94,7 +88,7 @@ struct BlitBlended { DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void BlitPixelsBlendedWithMap(uint8_t *DVL_RESTRICT dst, const uint8_t *DVL_RESTRICT src, unsigned length, const uint8_t *DVL_RESTRICT colorMap) { DVL_ASSUME(length != 0); - std::transform(DEVILUTIONX_BLIT_EXECUTION_POLICY src, src + length, dst, dst, [colorMap, pal = paletteTransparencyLookup](uint8_t srcColor, uint8_t dstColor) { + std::transform(DVL_EXECUTION_UNSEQ src, src + length, dst, dst, [colorMap, pal = paletteTransparencyLookup](uint8_t srcColor, uint8_t dstColor) { return pal[dstColor][colorMap[srcColor]]; }); } diff --git a/Source/engine/render/dun_render.cpp b/Source/engine/render/dun_render.cpp index 2fda02f407da..be9e0dee83d2 100644 --- a/Source/engine/render/dun_render.cpp +++ b/Source/engine/render/dun_render.cpp @@ -14,14 +14,12 @@ #include -#include #include #include +#include #include "engine/render/blit_impl.hpp" #include "levels/dun_tile.hpp" -#include "lighting.h" -#include "options.h" #include "utils/attributes.h" #ifdef DEBUG_STR #include "engine/render/text_render.hpp" @@ -282,16 +280,6 @@ DVL_ALWAYS_INLINE Clip CalculateClip(int_fast16_t x, int_fast16_t y, int_fast16_ return clip; } -DVL_ALWAYS_INLINE bool IsFullyDark(const uint8_t *DVL_RESTRICT tbl) -{ - return tbl == FullyDarkLightTable; -} - -DVL_ALWAYS_INLINE bool IsFullyLit(const uint8_t *DVL_RESTRICT tbl) -{ - return tbl == FullyLitLightTable; -} - template DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderSquareFull(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl) { @@ -906,7 +894,7 @@ DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderRightTrapezoid(uint8_t *DVL_RESTR } template -DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTileType(TileType tile, uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, Clip clip) +void RenderTileType(TileType tile, uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, Clip clip) { switch (tile) { case TileType::Square: @@ -997,7 +985,7 @@ DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderRightTrapezoidOrTransparentSquare } template -DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTileDispatch(TileType tile, uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, Clip clip) +void RenderTileDispatch(TileType tile, uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, const uint8_t *DVL_RESTRICT src, const uint8_t *DVL_RESTRICT tbl, Clip clip) { if (IsFullyDark(tbl)) { RenderTileType(tile, dst, dstPitch, src, tbl, clip); @@ -1009,7 +997,7 @@ DVL_ALWAYS_INLINE DVL_ATTRIBUTE_HOT void RenderTileDispatch(TileType tile, uint8 } // Blit with left and vertical clipping. -void RenderBlackTileClipLeftAndVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, int sx, DiamondClipY clipY) +void RenderSingleColorTileClipLeftAndVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, int sx, DiamondClipY clipY, uint8_t color) { dst += XStep * (LowerHeight - clipY.lowerBottom - 1); // Lower triangle (drawn bottom to top): @@ -1018,9 +1006,9 @@ void RenderBlackTileClipLeftAndVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstP const auto w = 2 * XStep * i; const auto curX = sx + TILE_WIDTH / 2 - XStep * i; if (curX >= 0) { - memset(dst, 0, w); + memset(dst, color, w); } else if (-curX <= w) { - memset(dst - curX, 0, w + curX); + memset(dst - curX, color, w + curX); } } dst += 2 * XStep + XStep * clipY.upperBottom; @@ -1030,9 +1018,9 @@ void RenderBlackTileClipLeftAndVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstP const auto w = 2 * XStep * (TriangleUpperHeight - i); const auto curX = sx + TILE_WIDTH / 2 - XStep * (TriangleUpperHeight - i); if (curX >= 0) { - memset(dst, 0, w); + memset(dst, color, w); } else if (-curX <= w) { - memset(dst - curX, 0, w + curX); + memset(dst - curX, color, w + curX); } else { break; } @@ -1040,7 +1028,7 @@ void RenderBlackTileClipLeftAndVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstP } // Blit with right and vertical clipping. -void RenderBlackTileClipRightAndVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, int_fast16_t maxWidth, DiamondClipY clipY) +void RenderSingleColorTileClipRightAndVertical(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, int_fast16_t maxWidth, DiamondClipY clipY, uint8_t color) { dst += XStep * (LowerHeight - clipY.lowerBottom - 1); // Lower triangle (drawn bottom to top): @@ -1050,7 +1038,7 @@ void RenderBlackTileClipRightAndVertical(uint8_t *DVL_RESTRICT dst, uint16_t dst const auto endX = TILE_WIDTH / 2 + XStep * i; const auto skip = endX > maxWidth ? endX - maxWidth : 0; if (width > skip) - memset(dst, 0, width - skip); + memset(dst, color, width - skip); } dst += 2 * XStep + XStep * clipY.upperBottom; // Upper triangle (drawn bottom to top): @@ -1066,35 +1054,35 @@ void RenderBlackTileClipRightAndVertical(uint8_t *DVL_RESTRICT dst, uint16_t dst } // Blit with vertical clipping only. -void RenderBlackTileClipY(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, DiamondClipY clipY) +void RenderSingleColorTileClipY(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, DiamondClipY clipY, uint8_t color) { dst += XStep * (LowerHeight - clipY.lowerBottom - 1); // Lower triangle (drawn bottom to top): const auto lowerMax = LowerHeight - clipY.lowerTop; for (auto i = 1 + clipY.lowerBottom; i <= lowerMax; ++i, dst -= dstPitch + XStep) { - memset(dst, 0, 2 * XStep * i); + memset(dst, color, 2 * XStep * i); } dst += 2 * XStep + XStep * clipY.upperBottom; // Upper triangle (drawn bottom to top): const auto upperMax = TriangleUpperHeight - clipY.upperTop; for (auto i = 1 + clipY.upperBottom; i <= upperMax; ++i, dst -= dstPitch - XStep) { - memset(dst, 0, TILE_WIDTH - 2 * XStep * i); + memset(dst, color, TILE_WIDTH - 2 * XStep * i); } } -// Blit a black tile without clipping (must be fully in bounds). -void RenderBlackTileFull(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch) +// Blit a single color tile without clipping (must be fully in bounds). +void RenderSingleColorTileFull(uint8_t *DVL_RESTRICT dst, uint16_t dstPitch, uint8_t color) { dst += XStep * (LowerHeight - 1); // Tile is fully in bounds, can use constant loop boundaries. // Lower triangle (drawn bottom to top): for (unsigned i = 1; i <= LowerHeight; ++i, dst -= dstPitch + XStep) { - memset(dst, 0, 2 * XStep * i); + memset(dst, color, 2 * XStep * i); } dst += 2 * XStep; // Upper triangle (drawn bottom to to top): for (unsigned i = 1; i <= TriangleUpperHeight; ++i, dst -= dstPitch - XStep) { - memset(dst, 0, TILE_WIDTH - 2 * XStep * i); + memset(dst, color, TILE_WIDTH - 2 * XStep * i); } } @@ -1189,7 +1177,16 @@ void RenderTile(const Surface &out, Point position, #endif } -void world_draw_black_tile(const Surface &out, int sx, int sy) +void BlitFloorTileToBuffer(LevelCelBlock levelCelBlock, const uint8_t *tbl, uint8_t *out) +{ + const TileType tile = levelCelBlock.type(); + const auto *pFrameTable = reinterpret_cast(pDungeonCels.get()); + const auto *src = reinterpret_cast(&pDungeonCels[SDL_SwapLE32(pFrameTable[levelCelBlock.frame()])]); + const Clip clip { .top = 0, .bottom = 0, .left = 0, .right = 0, .width = Width, .height = GetTileHeight(tile) }; + RenderTileDispatch(tile, out, DunFrameWidth, src, tbl, clip); +} + +void RenderSingleColorTile(const Surface &out, int sx, int sy, uint8_t color) { #ifdef DEBUG_RENDER_OFFSET_X sx += DEBUG_RENDER_OFFSET_X; @@ -1205,16 +1202,75 @@ void world_draw_black_tile(const Surface &out, int sx, int sy) uint8_t *dst = out.at(sx, static_cast(sy - clip.bottom)); if (clip.width == TILE_WIDTH) { if (clip.height == TriangleHeight) { - RenderBlackTileFull(dst, out.pitch()); + RenderSingleColorTileFull(dst, out.pitch(), color); } else { - RenderBlackTileClipY(dst, out.pitch(), clipY); + RenderSingleColorTileClipY(dst, out.pitch(), clipY, color); } } else { if (clip.right == 0) { - RenderBlackTileClipLeftAndVertical(dst, out.pitch(), sx, clipY); + RenderSingleColorTileClipLeftAndVertical(dst, out.pitch(), sx, clipY, color); } else { - RenderBlackTileClipRightAndVertical(dst, out.pitch(), clip.width, clipY); + RenderSingleColorTileClipRightAndVertical(dst, out.pitch(), clip.width, clipY, color); + } + } +} + +void RenderOpaqueTile(const Surface &out, Point position, LevelCelBlock levelCelBlock, const uint8_t *tbl) +{ + const TileType tile = levelCelBlock.type(); + const Clip clip = CalculateClip(position.x, position.y, Width, GetTileHeight(tile), out); + if (clip.width <= 0 || clip.height <= 0) return; + const auto *pFrameTable = reinterpret_cast(pDungeonCels.get()); + const auto *src = reinterpret_cast(&pDungeonCels[SDL_SwapLE32(pFrameTable[levelCelBlock.frame()])]); + uint8_t *dst = out.at(static_cast(position.x + clip.left), static_cast(position.y - clip.bottom)); + const uint16_t dstPitch = out.pitch(); + RenderTileDispatch(tile, dst, dstPitch, src, tbl, clip); +} + +void RenderFullyLitOpaqueTile(TileType tile, const Surface &out, Point position, const uint8_t *DVL_RESTRICT src) +{ + const Clip clip = CalculateClip(position.x, position.y, Width, GetTileHeight(tile), out); + if (clip.width <= 0 || clip.height <= 0) return; + uint8_t *dst = out.at(static_cast(position.x + clip.left), static_cast(position.y - clip.bottom)); + const uint16_t dstPitch = out.pitch(); + RenderTileType(tile, dst, dstPitch, src, nullptr, clip); +} + +void DunTileApplyTrans(LevelCelBlock levelCelBlock, uint8_t *dst, const uint8_t *tbl) +{ + const TileType tile = levelCelBlock.type(); + const auto *pFrameTable = reinterpret_cast(pDungeonCels.get()); + const auto *src = reinterpret_cast(&pDungeonCels[SDL_SwapLE32(pFrameTable[levelCelBlock.frame()])]); + + switch (tile) { + case TileType::Square: + BlitPixelsWithMap(dst, src, Width * Height, tbl); + break; + case TileType::TransparentSquare: + for (size_t i = 0; i < Height; ++i) { + uint_fast8_t drawWidth = Width; + while (drawWidth > 0) { + auto v = static_cast(*src++); + *dst++ = v; + if (v > 0) { + BlitPixelsWithMap(dst, src, v, tbl); + src += v; + dst += v; + } else { + v = static_cast(-v); + } + drawWidth -= v; + } } + break; + case TileType::LeftTriangle: + case TileType::RightTriangle: + BlitPixelsWithMap(dst, src, 544, tbl); + break; + case TileType::LeftTrapezoid: + case TileType::RightTrapezoid: + BlitPixelsWithMap(dst, src, 800, tbl); + break; } } diff --git a/Source/engine/render/dun_render.hpp b/Source/engine/render/dun_render.hpp index 684c83220949..43545539b342 100644 --- a/Source/engine/render/dun_render.hpp +++ b/Source/engine/render/dun_render.hpp @@ -7,11 +7,10 @@ #include -#include - #include "engine/point.hpp" #include "engine/surface.hpp" #include "levels/dun_tile.hpp" +#include "lighting.h" // #define DUN_RENDER_STATS #ifdef DUN_RENDER_STATS @@ -175,11 +174,37 @@ void RenderTile(const Surface &out, Point position, LevelCelBlock levelCelBlock, MaskType maskType, const uint8_t *tbl); /** - * @brief Render a black 64x31 tile ◆ + * @brief Render a single color 64x31 tile ◆ * @param out Target buffer * @param sx Target buffer coordinate (left corner of the tile) * @param sy Target buffer coordinate (bottom corner of the tile) + * @param color Color index + */ +void RenderSingleColorTile(const Surface &out, int sx, int sy, uint8_t color = 0); + +inline bool IsFullyDark(const uint8_t *DVL_RESTRICT tbl) +{ + return tbl == FullyDarkLightTable; +} + +inline bool IsFullyLit(const uint8_t *DVL_RESTRICT tbl) +{ + return tbl == FullyLitLightTable; +} + +/** + * @brief Renders a tile without masking. + */ +void RenderOpaqueTile(const Surface &out, Point position, LevelCelBlock levelCelBlock, const uint8_t *tbl); + +/** + * @brief Renders a tile without masking and without lighting. + */ +void RenderFullyLitOpaqueTile(TileType tile, const Surface &out, Point position, const uint8_t *DVL_RESTRICT src); + +/** + * @brief Writes a tile with the color swaps from `tbl` to `dst`. */ -void world_draw_black_tile(const Surface &out, int sx, int sy); +void DunTileApplyTrans(LevelCelBlock levelCelBlock, uint8_t *DVL_RESTRICT dst, const uint8_t *tbl); } // namespace devilution diff --git a/Source/engine/render/scrollrt.cpp b/Source/engine/render/scrollrt.cpp index 32680101db96..7a620350c4f7 100644 --- a/Source/engine/render/scrollrt.cpp +++ b/Source/engine/render/scrollrt.cpp @@ -5,6 +5,8 @@ */ #include "engine/render/scrollrt.h" +#include +#include #include #include @@ -19,6 +21,7 @@ #include "doom.h" #include "engine/backbuffer_state.hpp" #include "engine/dx.h" +#include "engine/point.hpp" #include "engine/render/clx_render.hpp" #include "engine/render/dun_render.hpp" #include "engine/render/text_render.hpp" @@ -29,6 +32,7 @@ #include "hwcursor.hpp" #include "init.h" #include "inv.h" +#include "levels/dun_tile.hpp" #include "lighting.h" #include "lua/lua.hpp" #include "minitext.h" @@ -48,9 +52,7 @@ #include "stores.h" #include "towners.h" #include "utils/attributes.h" -#include "utils/bitset2d.hpp" #include "utils/display.h" -#include "utils/endian.hpp" #include "utils/log.hpp" #include "utils/str_cat.hpp" @@ -563,39 +565,6 @@ void DrawCell(const Surface &out, Point tilePosition, Point targetBufferPosition } } -/** - * @brief Render a floor tile. - * @param out Target buffer - * @param tilePosition dPiece coordinates - * @param targetBufferPosition Target buffer coordinate - */ -void DrawFloorTile(const Surface &out, Point tilePosition, Point targetBufferPosition) -{ - const int lightTableIndex = dLight[tilePosition.x][tilePosition.y]; - - const uint8_t *tbl = LightTables[lightTableIndex].data(); -#ifdef _DEBUG - if (DebugPath && MyPlayer->IsPositionInPath(tilePosition)) - tbl = GetPauseTRN(); -#endif - - const uint16_t levelPieceId = dPiece[tilePosition.x][tilePosition.y]; - { - const LevelCelBlock levelCelBlock { DPieceMicros[levelPieceId].mt[0] }; - if (levelCelBlock.hasValue()) { - RenderTile(out, targetBufferPosition, - levelCelBlock, MaskType::Solid, tbl); - } - } - { - const LevelCelBlock levelCelBlock { DPieceMicros[levelPieceId].mt[1] }; - if (levelCelBlock.hasValue()) { - RenderTile(out, targetBufferPosition + Displacement { TILE_WIDTH / 2, 0 }, - levelCelBlock, MaskType::Solid, tbl); - } - } -} - /** * @brief Draw item for a given tile * @param out Output buffer @@ -823,8 +792,73 @@ void DrawDungeon(const Surface &out, Point tilePosition, Point targetBufferPosit } } +constexpr int MinFloorTileToBakeLight = 2; +constexpr size_t FloorTilesBufferSize = 1024; +struct FloorTilesBufferEntry { + PointOf targetBufferPosition; + uint32_t id; + + FloorTilesBufferEntry(PointOf position, + uint16_t levelCelBlock, + uint8_t lightTableIndex) + : targetBufferPosition(position) + , id((levelCelBlock << 8) | lightTableIndex) + { + } + + [[nodiscard]] LevelCelBlock levelCelBlock() const { return { static_cast(id >> 8) }; } + [[nodiscard]] uint8_t lightTableIndex() const { return static_cast(id); } +}; + +void DrawIdenticalFloorTiles(const Surface &out, FloorTilesBufferEntry *begin, FloorTilesBufferEntry *end) +{ + if (begin == end) return; + const LevelCelBlock levelCelBlock = begin->levelCelBlock(); + const uint8_t lightTableIndex = begin->lightTableIndex(); + const uint8_t *lightTable = +#ifdef _DEBUG + lightTableIndex == NumLightingLevels + 1 + ? GetPauseTRN() + : +#endif + LightTables[lightTableIndex].data(); + if (end - begin < MinFloorTileToBakeLight || IsFullyDark(lightTable) || IsFullyLit(lightTable)) { + for (FloorTilesBufferEntry *it = begin; it != end; ++it) { + RenderOpaqueTile(out, it->targetBufferPosition, levelCelBlock, lightTable); + } + } else { + uint8_t bakedLightTile[DunFrameHeight * DunFrameWidth]; + DunTileApplyTrans(levelCelBlock, bakedLightTile, lightTable); + const TileType type = levelCelBlock.type(); + for (FloorTilesBufferEntry *it = begin; it != end; ++it) { + RenderFullyLitOpaqueTile(type, out, it->targetBufferPosition, bakedLightTile); + } + } +} + +void DrawFloorBuffer(const Surface &out, + StaticVector &buffer) +{ + if (buffer.empty()) return; + std::stable_sort(buffer.begin(), buffer.end(), [](const FloorTilesBufferEntry &a, const FloorTilesBufferEntry &b) { + return a.id < b.id; + }); + uint32_t prevId = buffer[0].id; + size_t prevBegin = 0; + for (size_t i = 1; i < buffer.size(); ++i) { + const uint32_t id = buffer[i].id; + if (prevId != id) { + DrawIdenticalFloorTiles(out, buffer.begin() + prevBegin, buffer.begin() + i); + prevId = id; + prevBegin = i; + } + } + DrawIdenticalFloorTiles(out, buffer.begin() + prevBegin, buffer.end()); + buffer.clear(); +} + /** - * @brief Render a row of tiles + * @brief Renders the floor tiles * @param out Buffer to render to * @param tilePosition dPiece coordinates * @param targetBufferPosition Target buffer coordinates @@ -833,33 +867,50 @@ void DrawDungeon(const Surface &out, Point tilePosition, Point targetBufferPosit */ void DrawFloor(const Surface &out, Point tilePosition, Point targetBufferPosition, int rows, int columns) { + StaticVector buffer; + PointOf position = targetBufferPosition; for (int i = 0; i < rows; i++) { - for (int j = 0; j < columns; j++) { - if (InDungeonBounds(tilePosition)) { - if (!TileHasAny(tilePosition, TileProperties::Solid)) - DrawFloorTile(out, tilePosition, targetBufferPosition); - } else { - world_draw_black_tile(out, targetBufferPosition.x, targetBufferPosition.y); + for (int j = 0; j < columns; ++j) { + if (!InDungeonBounds(tilePosition)) { + RenderSingleColorTile(out, position.x, position.y); + } else if (!TileHasAny(tilePosition, TileProperties::Solid)) { + const uint16_t levelPieceId = dPiece[tilePosition.x][tilePosition.y]; + const uint8_t lightTableIndex = +#ifdef _DEBUG + DebugPath && MyPlayer->IsPositionInPath(tilePosition) + ? NumLightingLevels + 1 + : +#endif + dLight[tilePosition.x][tilePosition.y]; + if (buffer.size() + 2 >= FloorTilesBufferSize) DrawFloorBuffer(out, buffer); + if (const uint16_t pieceId = DPieceMicros[levelPieceId].mt[0].data; pieceId != 0) { + buffer.emplace_back(position, pieceId, lightTableIndex); + } + if (const uint16_t pieceId = DPieceMicros[levelPieceId].mt[1].data; pieceId != 0) { + buffer.emplace_back(position + Displacement { TILE_WIDTH / 2, 0 }, pieceId, lightTableIndex); + } } tilePosition += Direction::East; - targetBufferPosition.x += TILE_WIDTH; + position.x += TILE_WIDTH; } + // Return to start of row tilePosition += Displacement(Direction::West) * columns; - targetBufferPosition.x -= columns * TILE_WIDTH; + position.x -= columns * TILE_WIDTH; // Jump to next row - targetBufferPosition.y += TILE_HEIGHT / 2; + position.y += TILE_HEIGHT / 2; if ((i & 1) != 0) { tilePosition.x++; columns--; - targetBufferPosition.x += TILE_WIDTH / 2; + position.x += TILE_WIDTH / 2; } else { tilePosition.y++; columns++; - targetBufferPosition.x -= TILE_WIDTH / 2; + position.x -= TILE_WIDTH / 2; } } + DrawFloorBuffer(out, buffer); } [[nodiscard]] DVL_ALWAYS_INLINE bool IsWall(Point position) @@ -987,7 +1038,7 @@ void Zoom(const Surface &out) Displacement tileOffset; Displacement tileShift; -int tileColums; +int tileColumns; int tileRows; void CalcFirstTilePosition(Point &position, Displacement &offset) @@ -1048,7 +1099,7 @@ void DrawGame(const Surface &fullOut, Point position, Displacement offset) ? fullOut.subregionY(0, gnViewportHeight) : fullOut.subregionY(0, (gnViewportHeight + 1) / 2); - int columns = tileColums; + int columns = tileColumns; int rows = tileRows; // Skip rendering parts covered by the panels @@ -1511,7 +1562,7 @@ void CalcViewportGeometry() const int viewportHeight = GetViewportHeight() / zoomFactor; const Point renderStart = startPosition - Displacement { TILE_WIDTH / 2, TILE_HEIGHT / 2 }; tileRows = (viewportHeight - renderStart.y + TILE_HEIGHT / 2 - 1) / (TILE_HEIGHT / 2); - tileColums = (screenWidth - renderStart.x + TILE_WIDTH - 1) / TILE_WIDTH; + tileColumns = (screenWidth - renderStart.x + TILE_WIDTH - 1) / TILE_WIDTH; } Point GetScreenPosition(Point tile) diff --git a/Source/utils/attributes.h b/Source/utils/attributes.h index 2f40a9bcb6e6..d91b05a6c8ae 100644 --- a/Source/utils/attributes.h +++ b/Source/utils/attributes.h @@ -102,3 +102,9 @@ #else #define DVL_UNREACHABLE() #endif + +#if __cpp_lib_execution >= 201902L +#define DVL_EXECUTION_UNSEQ std::execution::unseq, +#else +#define DVL_EXECUTION_UNSEQ +#endif