From 0b90eea56be798acd361584b13938d3e0d5af02c Mon Sep 17 00:00:00 2001 From: Vladislav Belov Date: Mon, 21 Sep 2026 00:47:11 +0200 Subject: [PATCH] Replaces is_pow2 by std::has_single_bit --- source/graphics/TerrainTextureManager.cpp | 6 ++--- source/graphics/TextureConverter.cpp | 4 ++-- source/graphics/TextureManager.cpp | 4 ++-- source/lib/bits.h | 23 +++++-------------- source/lib/file/io/io.h | 7 +++--- source/lib/sysdep/smbios.cpp | 5 ++-- source/lib/tests/test_bits.h | 9 -------- source/lib/tex/tex.cpp | 3 ++- source/renderer/SkyManager.cpp | 4 ++-- source/renderer/VertexArray.cpp | 5 ++-- .../backend/vulkan/DeviceCommandContext.cpp | 3 ++- 11 files changed, 29 insertions(+), 44 deletions(-) diff --git a/source/graphics/TerrainTextureManager.cpp b/source/graphics/TerrainTextureManager.cpp index 2c3f532b09..0b387d177e 100644 --- a/source/graphics/TerrainTextureManager.cpp +++ b/source/graphics/TerrainTextureManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2025 Wildfire Games. +/* Copyright (C) 2026 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -23,7 +23,6 @@ #include "graphics/TerrainTextureEntry.h" #include "lib/alignment.h" #include "lib/allocators/shared_ptr.h" -#include "lib/bits.h" #include "lib/debug.h" #include "lib/file/vfs/vfs.h" #include "lib/file/vfs/vfs_util.h" @@ -41,6 +40,7 @@ #include "renderer/backend/Sampler.h" #include +#include #include #include #include @@ -232,7 +232,7 @@ CTerrainTextureManager::LoadAlphaMap(const VfsPath& alphaMapType) // const size_t tileWidth = 2 + base + 2; // 2 pixel border (avoids bilinear filtering artifacts) const size_t totalWidth = round_up_to_pow2(tileWidth * NUM_ALPHA_MAPS); - const size_t totalHeight = base; ENSURE(is_pow2(totalHeight)); + const size_t totalHeight = base; ENSURE(std::has_single_bit(totalHeight)); std::shared_ptr data; AllocateAligned(data, totalWidth * totalHeight, maxSectorSize); // for each tile on row diff --git a/source/graphics/TextureConverter.cpp b/source/graphics/TextureConverter.cpp index a2fe918174..66e0633809 100644 --- a/source/graphics/TextureConverter.cpp +++ b/source/graphics/TextureConverter.cpp @@ -21,7 +21,6 @@ #include "lib/alignment.h" #include "lib/allocators/shared_ptr.h" -#include "lib/bits.h" #include "lib/debug.h" #include "lib/path.h" #include "lib/regex.h" @@ -40,6 +39,7 @@ #include "ps/XMB/XMBStorage.h" #include "ps/XML/Xeromyces.h" +#include #include #include @@ -343,7 +343,7 @@ bool CTextureConverter::ConvertTexture(const CTexturePtr& texture, const VfsPath return false; } - if (!is_pow2(tex.m_Width) || !is_pow2(tex.m_Height)) + if (!std::has_single_bit(tex.m_Width) || !std::has_single_bit(tex.m_Height)) { LOGERROR("Texture to convert \"%s\" should have width and height be power of two: %zux%zu", src.string8(), tex.m_Width, tex.m_Height); diff --git a/source/graphics/TextureManager.cpp b/source/graphics/TextureManager.cpp index 86ab0bd9f0..208665b90d 100644 --- a/source/graphics/TextureManager.cpp +++ b/source/graphics/TextureManager.cpp @@ -22,7 +22,6 @@ #include "graphics/Color.h" #include "graphics/SColor.h" #include "graphics/TextureConverter.h" -#include "lib/bits.h" #include "lib/debug.h" #include "lib/hash.h" #include "lib/path.h" @@ -43,6 +42,7 @@ #include #include +#include #include #include #include @@ -498,7 +498,7 @@ public: return; } - if (!is_pow2(textureData.m_Width) || !is_pow2(textureData.m_Height)) + if (!std::has_single_bit(textureData.m_Width) || !std::has_single_bit(textureData.m_Height)) { LOGERROR("Texture should have width and height be power of two; \"%s\" %zux%zu", texture->m_Properties.m_Path.string8(), textureData.m_Width, textureData.m_Height); diff --git a/source/lib/bits.h b/source/lib/bits.h index 69f3908fea..aef6203cd0 100644 --- a/source/lib/bits.h +++ b/source/lib/bits.h @@ -31,9 +31,11 @@ #include "lib/debug.h" #include "lib/status.h" +#include #include #include #include +#include /** * value of bit number \. @@ -128,21 +130,6 @@ inline T SetBitsTo(T num, size_t lo_idx, size_t hi_idx, size_t value) return result; } -/** - * @return whether the given number is a power of two. - **/ -template -inline bool is_pow2(T n) -{ - // 0 would pass the test below but isn't a POT. - if(n == 0) - return false; - return (n & (n-1)) == 0; -} - -// as above; intended for use in static_assert -#define IS_POW2(n) (((n) != 0) && ((n) & ((n)-1)) == 0) - template inline T LeastSignificantBit(T x) { @@ -235,7 +222,8 @@ inline T round_down_to_pow2(T x) template inline T round_up(T n, T multiple) { - ASSERT(is_pow2(multiple)); + ASSERT(multiple > 0); + ASSERT(std::has_single_bit(static_cast>(multiple))); const T result = (n + multiple-1) & ~(multiple-1); ASSERT(n <= result && result < n+multiple); return result; @@ -244,7 +232,8 @@ inline T round_up(T n, T multiple) template inline T round_down(T n, T multiple) { - ASSERT(is_pow2(multiple)); + ASSERT(multiple > 0); + ASSERT(std::has_single_bit(static_cast>(multiple))); const T result = n & ~(multiple-1); ASSERT(result <= n && n < result+multiple); return result; diff --git a/source/lib/file/io/io.h b/source/lib/file/io/io.h index 46f5a4e9ed..d0e71e5a29 100644 --- a/source/lib/file/io/io.h +++ b/source/lib/file/io/io.h @@ -44,6 +44,7 @@ #include "lib/types.h" #include +#include #include #include #include @@ -73,7 +74,7 @@ using BufferPtr = std::unique_ptr; // never reused (avoids displacing other items). static inline io::BufferPtr Allocate(size_t size, size_t alignment = maxSectorSize) { - ENSURE(is_pow2(alignment)); + ENSURE(std::has_single_bit(alignment)); alignment = std::max(alignment, allocationAlignment); u8* p = static_cast(rtl_AllocateAligned(round_up(size, alignment), alignment)); @@ -141,12 +142,12 @@ struct Parameters void Validate(const Operation& op) const { - ENSURE(is_pow2(alignment)); ENSURE(alignment > 0); + ENSURE(std::has_single_bit(static_cast(alignment))); if(blockSize != 0) { - ENSURE(is_pow2(blockSize)); + ENSURE(std::has_single_bit(blockSize)); ENSURE(g_PageSize <= blockSize); // (don't bother checking an upper bound) } diff --git a/source/lib/sysdep/smbios.cpp b/source/lib/sysdep/smbios.cpp index 0a27dd4ceb..ce009f390a 100644 --- a/source/lib/sysdep/smbios.cpp +++ b/source/lib/sysdep/smbios.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2025 Wildfire Games. +/* Copyright (C) 2026 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -44,6 +44,7 @@ # include "lib/sysdep/os/win/wutil.h" #endif +#include #include #include #include @@ -492,7 +493,7 @@ std::string StringFromEnum(Enum /*field*/) #define ENUM(enumerator, VALUE)\ if(field.value == VALUE) /* single bit flag or matching enumerator */\ return #enumerator;\ - if(!is_pow2(VALUE)) /* these aren't bit flags */\ + if(!std::has_single_bit(static_cast(VALUE))) /* these aren't bit flags */\ {\ allowFlags = false;\ string.clear();\ diff --git a/source/lib/tests/test_bits.h b/source/lib/tests/test_bits.h index 0e974c7ceb..8a1e8207aa 100644 --- a/source/lib/tests/test_bits.h +++ b/source/lib/tests/test_bits.h @@ -85,15 +85,6 @@ public: EQUALS(bits(0xA5A5A5A5A5A5A5A5ull, 32, 63), 0xA5A5A5A5ull); } - void test_is_pow2() - { - EQUALS(is_pow2(0u), false); - EQUALS(is_pow2(~0u), false); - EQUALS(is_pow2(0x80000001), false); - EQUALS(is_pow2(1), true); - EQUALS(is_pow2(1u << 31), true); - } - void test_ceil_log2() { EQUALS(ceil_log2(3u), 2u); diff --git a/source/lib/tex/tex.cpp b/source/lib/tex/tex.cpp index 45e09568e0..e0aad3aff3 100644 --- a/source/lib/tex/tex.cpp +++ b/source/lib/tex/tex.cpp @@ -33,6 +33,7 @@ #include "lib/tex/tex_codec.h" #include +#include #include #include @@ -253,7 +254,7 @@ static Status add_mipmaps(Tex* t, size_t w, size_t h, size_t bpp, void* newData, // this code assumes the image is of POT dimension; we don't // go to the trouble of implementing image scaling because // the only place this is used (backend textures) requires POT anyway. - if(!is_pow2(w) || !is_pow2(h)) + if(!std::has_single_bit(w) || !std::has_single_bit(h)) WARN_RETURN(ERR::TEX_INVALID_SIZE); t->m_Flags |= TEX_MIPMAPS; // must come before tex_img_size! const size_t mipmap_size = t->img_size(); diff --git a/source/renderer/SkyManager.cpp b/source/renderer/SkyManager.cpp index 22896bf75b..bd7ee4fba1 100644 --- a/source/renderer/SkyManager.cpp +++ b/source/renderer/SkyManager.cpp @@ -25,7 +25,6 @@ #include "graphics/ShaderTechnique.h" #include "graphics/ShaderTechniquePtr.h" #include "graphics/TextureManager.h" -#include "lib/bits.h" #include "lib/code_generation.h" #include "lib/file/file_system.h" #include "lib/file/vfs/vfs.h" @@ -54,6 +53,7 @@ #include #include +#include #include #include #include @@ -130,7 +130,7 @@ void SkyManager::LoadAndUploadSkyTexturesIfNeeded( return; } - if (!is_pow2(textures[i].m_Width) || !is_pow2(textures[i].m_Height)) + if (!std::has_single_bit(textures[i].m_Width) || !std::has_single_bit(textures[i].m_Height)) { LOGERROR("Error creating sky cubemap '%s', cube textures should have power of 2 sizes.", m_SkySet.ToUTF8().c_str()); return; diff --git a/source/renderer/VertexArray.cpp b/source/renderer/VertexArray.cpp index 391e678090..2c1730d453 100644 --- a/source/renderer/VertexArray.cpp +++ b/source/renderer/VertexArray.cpp @@ -18,7 +18,6 @@ #include "precompiled.h" #include "lib/alignment.h" -#include "lib/bits.h" #include "lib/sysdep/rtl.h" #include "ps/CLogger.h" #include "renderer/Renderer.h" @@ -26,6 +25,8 @@ #include "renderer/VertexBuffer.h" #include "renderer/VertexBufferManager.h" +#include + class CVector3D; class CVector4D; struct SColor4ub; @@ -104,7 +105,7 @@ void VertexArray::SetNumberOfVertices(const size_t numberOfVertices) void VertexArray::SetMinimumAttributeAlignment(const uint32_t minimumAttributeAlignment) { - ENSURE(minimumAttributeAlignment >= 4 || is_pow2(minimumAttributeAlignment)); + ENSURE(minimumAttributeAlignment >= 4 || std::has_single_bit(minimumAttributeAlignment)); if (minimumAttributeAlignment == m_MinimumAttributeAlignment) return; diff --git a/source/renderer/backend/vulkan/DeviceCommandContext.cpp b/source/renderer/backend/vulkan/DeviceCommandContext.cpp index 017dbc5ed7..6eab401ded 100644 --- a/source/renderer/backend/vulkan/DeviceCommandContext.cpp +++ b/source/renderer/backend/vulkan/DeviceCommandContext.cpp @@ -46,6 +46,7 @@ #include "renderer/backend/vulkan/Utilities.h" #include +#include #include #include #include @@ -275,7 +276,7 @@ uint32_t CDeviceCommandContext::CUploadRing::ScheduleUpload( const uint32_t alignment) { ENSURE(data.size() > 0); - ENSURE(is_pow2(alignment)); + ENSURE(std::has_single_bit(alignment)); m_BlockOffset = (m_BlockOffset + alignment - 1) & ~(alignment - 1);