From 5d708d22a0172c1d4f5c4ec5edda347dd315efd9 Mon Sep 17 00:00:00 2001 From: assiduous Date: Mon, 1 Feb 2021 19:53:52 -0800 Subject: MathLib: added stream insreters for vector types --- Common/interface/BasicMath.hpp | 62 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'Common/interface') diff --git a/Common/interface/BasicMath.hpp b/Common/interface/BasicMath.hpp index 05a168fc..9b882a46 100644 --- a/Common/interface/BasicMath.hpp +++ b/Common/interface/BasicMath.hpp @@ -50,6 +50,7 @@ #include #include +#include #include "HashUtils.hpp" @@ -2189,6 +2190,67 @@ inline Uint32 BitInterleave16(Uint16 _x, Uint16 _y) return x | (y << 1u); } +/// Returns the least-signficant bit and clears it in the input argument +template +typename std::enable_if::value, T>::type ExtractLSB(T& bits) +{ + if (bits == T{0}) + return 0; + + const T bit = bits & ~(bits - T{1}); + bits &= ~bit; + + return bit; +} + +/// Returns the enum value representing the least-signficant bit and clears it in the input argument +template +typename std::enable_if::value, T>::type ExtractLSB(T& bits) +{ + return static_cast(ExtractLSB(reinterpret_cast::type&>(bits))); +} + + +inline std::ostream& operator<<(std::ostream& os, const float4& vec) +{ + return os << "float4(" << vec.x << ", " << vec.y << ", " << vec.z << ", " << vec.w << ')'; +} +inline std::ostream& operator<<(std::ostream& os, const float3& vec) +{ + return os << "float3(" << vec.x << ", " << vec.y << ", " << vec.z << ')'; +} +inline std::ostream& operator<<(std::ostream& os, const float2& vec) +{ + return os << "float2(" << vec.x << ", " << vec.y << ')'; +} + +inline std::ostream& operator<<(std::ostream& os, const int4& vec) +{ + return os << "int4(" << vec.x << ", " << vec.y << ", " << vec.z << ", " << vec.w << ')'; +} +inline std::ostream& operator<<(std::ostream& os, const int3& vec) +{ + return os << "int3(" << vec.x << ", " << vec.y << ", " << vec.z << ')'; +} +inline std::ostream& operator<<(std::ostream& os, const int2& vec) +{ + return os << "int2(" << vec.x << ", " << vec.y << ')'; +} + + +inline std::ostream& operator<<(std::ostream& os, const uint4& vec) +{ + return os << "uint4(" << vec.x << ", " << vec.y << ", " << vec.z << ", " << vec.w << ')'; +} +inline std::ostream& operator<<(std::ostream& os, const uint3& vec) +{ + return os << "uint3(" << vec.x << ", " << vec.y << ", " << vec.z << ')'; +} +inline std::ostream& operator<<(std::ostream& os, const uint2& vec) +{ + return os << "uint2(" << vec.x << ", " << vec.y << ')'; +} + } // namespace Diligent -- cgit v1.2.3 From 1b12c2195f219844f186f20b98b5210944b38f65 Mon Sep 17 00:00:00 2001 From: assiduous Date: Sun, 7 Feb 2021 16:18:59 -0800 Subject: Some improvement to ThreadingTools::Signal --- Common/interface/ThreadSignal.hpp | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) (limited to 'Common/interface') diff --git a/Common/interface/ThreadSignal.hpp b/Common/interface/ThreadSignal.hpp index d6d12a8f..657d0b6d 100644 --- a/Common/interface/ThreadSignal.hpp +++ b/Common/interface/ThreadSignal.hpp @@ -41,8 +41,8 @@ class Signal public: Signal() { - m_SignaledValue = 0; - m_NumThreadsAwaken = 0; + m_SignaledValue.store(0); + m_NumThreadsAwaken.store(0); } // http://en.cppreference.com/w/cpp/thread/condition_variable @@ -58,8 +58,8 @@ public: // std::condition_variable works only with std::unique_lock std::lock_guard Lock{m_Mutex}; VERIFY(SignalValue != 0, "Signal value must not be 0"); - VERIFY(m_SignaledValue == 0 && m_NumThreadsAwaken == 0, "Not all threads have been awaken since the signal was triggered last time, or the signal has not been reset"); - m_SignaledValue = SignalValue; + VERIFY(m_SignaledValue.load() == 0 && m_NumThreadsAwaken.load() == 0, "Not all threads have been awaken since the signal was triggered last time, or the signal has not been reset"); + m_SignaledValue.store(SignalValue); } // Unlocking is done before notifying, to avoid waking up the waiting // thread only to block again (see notify_one for details) @@ -87,22 +87,23 @@ public: std::unique_lock Lock(m_Mutex); // It is safe to check m_SignaledValue since we are holding // the mutex - if (m_SignaledValue == 0) + if (m_SignaledValue.load() == 0) { - m_CondVar.wait(Lock, [&] { return m_SignaledValue != 0; }); + m_CondVar.wait(Lock, [&] { return m_SignaledValue.load() != 0; }); } - int SignaledValue = m_SignaledValue; - // Count the number of threads awaken while holding the mutex - ++m_NumThreadsAwaken; + auto SignaledValue = m_SignaledValue.load(); + // Update the number of threads awaken while holding the mutex + const auto NumThreadsAwaken = m_NumThreadsAwaken.fetch_add(1) + 1; + // fetch_add returns the original value immediately preceding the addition. if (AutoReset) { VERIFY(NumThreadsWaiting > 0, "Number of waiting threads must not be 0 when auto resetting the signal"); // Reset the signal while holding the mutex. If Trigger() is executed by another // thread, it will wait until we release the mutex - if (m_NumThreadsAwaken == NumThreadsWaiting) + if (NumThreadsAwaken == NumThreadsWaiting) { - m_SignaledValue = 0; - m_NumThreadsAwaken = 0; + m_SignaledValue.store(0); + m_NumThreadsAwaken.store(0); } } return SignaledValue; @@ -111,17 +112,17 @@ public: void Reset() { std::lock_guard Lock{m_Mutex}; - m_SignaledValue = 0; - m_NumThreadsAwaken = 0; + m_SignaledValue.store(0); + m_NumThreadsAwaken.store(0); } - bool IsTriggered() const { return m_SignaledValue != 0; } + bool IsTriggered() const { return m_SignaledValue.load() != 0; } private: std::mutex m_Mutex; std::condition_variable m_CondVar; - std::atomic_int m_SignaledValue; - std::atomic_int m_NumThreadsAwaken; + std::atomic_int m_SignaledValue{0}; + std::atomic_int m_NumThreadsAwaken{0}; Signal(const Signal&) = delete; Signal& operator=(const Signal&) = delete; -- cgit v1.2.3