/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. // Description : Platform specific DXGL requirements implementation #ifndef __GLPLATFORM__ #define __GLPLATFORM__ namespace NCryOpenGL { enum ELogSeverity { eLS_Info, eLS_Warning, eLS_Error }; } #define CUSTOM_SCOPED_PROFILE(_Name) #if defined(OPENGL) #include "GLCryPlatform.hpp" #elif defined(WIN32) #include "../Standalone/GLWinPlatform.hpp" #elif defined(LINUX) #include "../Standalone/GLLinuxPlatform.hpp" #else #error "Platform is not supported" #endif #define DXGL_PROFILING 0 #if defined(AZ_COMPILER_MSVC) #define _DXGL_LOG_STRINGIFY_(x) #x #define _DXGL_LOG_STRINGIFY(x) _DXGL_LOG_STRINGIFY_(x) #define _DXGL_LOG_MSG(_TEXT, _FILE, _LINE, _FUNC) "DXGL: " _TEXT " : [@" _FUNC "] " _FILE "(" _LINE ")" #define DXGL_LOG_MSG(_TEXT) _DXGL_LOG_MSG(_TEXT, __FILE__, _DXGL_LOG_STRINGIFY(__LINE__), __FUNCSIG__) #else #define _DXGL_LOG_MSG(_TEXT, _FILE, _FUNC) "DXGL: " _TEXT " : [@" _FUNC "] " _FILE "(%d)" #define DXGL_LOG_MSG(_TEXT) _DXGL_LOG_MSG(_TEXT, __FILE__, "?") // GCC can't resolve __FUNCTION__ in the preprocessor #endif #if defined(_MSC_VER) #define DXGL_WARNING(_Format, ...) NCryOpenGL::LogMessage(NCryOpenGL::eLS_Warning, DXGL_LOG_MSG(_Format), __VA_ARGS__) #define DXGL_ERROR(_Format, ...) NCryOpenGL::LogMessage(NCryOpenGL::eLS_Error, DXGL_LOG_MSG(_Format), __VA_ARGS__) #define DXGL_INFO(_Format, ...) NCryOpenGL::LogMessage(NCryOpenGL::eLS_Info, DXGL_LOG_MSG(_Format), __VA_ARGS__) #else #define DXGL_WARNING(_Format, ...) NCryOpenGL::LogMessage(NCryOpenGL::eLS_Warning, DXGL_LOG_MSG(_Format), ##__VA_ARGS__, __LINE__) #define DXGL_ERROR(_Format, ...) NCryOpenGL::LogMessage(NCryOpenGL::eLS_Error, DXGL_LOG_MSG(_Format), ##__VA_ARGS__, __LINE__) #define DXGL_INFO(_Format, ...) NCryOpenGL::LogMessage(NCryOpenGL::eLS_Info, DXGL_LOG_MSG(_Format), ##__VA_ARGS__, __LINE__) #endif #define DXGL_NOT_IMPLEMENTED NCryOpenGL::BreakUnique(__FILE__, __LINE__, __func__); #define DXGL_TODO(_DESC) #define DXGL_ARRAY_SIZE(_Array) (sizeof(_Array) / sizeof(_Array[0])) #define _DXGL_QUOTE(X) #X #define DXGL_QUOTE(X) _DXGL_QUOTE(X) #define DXGL_CAT(_Left, _Right) _Left ## _Right #define _DXGL_IF_0(...) #define _DXGL_IF_1(...) __VA_ARGS__ #define DXGL_IF(_Condition) DXGL_CAT(_DXGL_IF_, _Condition) #define DXGL_DECLARE_PTR(_Qualifier, _TypeName) \ _Qualifier _TypeName; \ typedef _smart_ptr<_TypeName> _TypeName ## Ptr; #define DXGL_DECLARE_REF_COUNTED(_Qualifier, _TypeName) \ DXGL_DECLARE_PTR(_Qualifier, _TypeName) \ _Qualifier _TypeName: public NCryOpenGL::SRefCounted < _TypeName > namespace NCryOpenGL { template struct SRefCounted { uint32 m_uRefCnt; SRefCounted() : m_uRefCnt(0) { } void AddRef() { ++m_uRefCnt; } void Release() { if (--m_uRefCnt == 0) { delete static_cast(this); } } }; struct SSpinlockBitMaskWord { typedef LONG Word; enum { BIT_SIZE = sizeof(Word) * 8 }; volatile Word m_aMask; void Set(Word kNewValue) { Exchange(&m_aMask, kNewValue); } Word Get() const { return CompareExchange(const_cast(&m_aMask), 0, 0); } bool Set(uint32 uIndex, bool bFlag) { while (true) { Word kOld(m_aMask); Word uFlagMask(1 << uIndex); Word kNew(bFlag ? (kOld | uFlagMask) : (kOld & ~uFlagMask)); if (CompareExchange(&m_aMask, kNew, kOld) == kOld) { return (kOld & uFlagMask) != 0; } } } bool Get(uint32 uIndex) const { assert(uIndex <= BIT_SIZE); return ((m_aMask >> uIndex) & 1) != 0; } }; struct SUnsafeBitMaskWord { typedef uint32 Word; enum { BIT_SIZE = sizeof(Word) * 8 }; Word m_aMask; void Set(Word kNewValue) { m_aMask = kNewValue; } Word Get() const { return m_aMask; } bool Set(uint32 uIndex, bool bFlag) { assert(uIndex <= BIT_SIZE); Word uFlagMask(1 << uIndex); Word kOld(m_aMask); m_aMask = bFlag ? (kOld | uFlagMask) : (kOld & ~uFlagMask); return (kOld & uFlagMask) != 0; } bool Get(uint32 uIndex) const { assert(uIndex <= BIT_SIZE); return ((m_aMask >> uIndex) & 1) != 0; } }; template struct SBitMaskMultiWord { typedef BitMaskWord Word; Word m_akWords[uNumWords]; bool Set(uint32 uIndex, bool bFlag) { return m_akWords[uIndex / Word::BIT_SIZE].Set(uIndex % Word::BIT_SIZE, bFlag); } bool Get(uint32 uIndex) const { return m_akWords[uIndex / Word::BIT_SIZE].Get(uIndex % Word::BIT_SIZE); } }; template struct SBitMaskImpl { typedef SBitMaskMultiWord Type; typedef typename BitMaskWord::Word Word; static void Init(Type* pMask, bool bValue, Word kUsedMask) { memset(pMask->m_akWords, bValue ? (Word) ~0 : (Word)0, sizeof(Word) * (uNumWords - 1)); pMask->m_akWords[uNumWords - 1].m_aMask = bValue ? kUsedMask : (Word)0; } static void SetZero(Type* pMask) { for (uint32 uPosition = 0; uPosition < uNumWords; ++uPosition) { pMask->m_akWords[uPosition].Set((Word)0); } } static void SetOne(Type* pMask, Word kUsedMask) { for (uint32 uPosition = 0; uPosition < uNumWords - 1; ++uPosition) { pMask->m_akWords[uPosition].Set(~(Word)0); } pMask->m_akWords[uNumWords - 1].Set(kUsedMask); } static bool IsZero(Type* pMask, Word kUsedMask) { for (uint32 uPosition = 0; uPosition < uNumWords - 1; ++uPosition) { if (pMask->m_akWords[uPosition].Get() != (Word)0) { return false; } } return (pMask->m_akWords[uNumWords - 1].Get() & kUsedMask) == (Word)0; } static bool IsOne(Type* pMask, Word kUsedMask) { for (uint32 uPosition = 0; uPosition < uNumWords - 1; ++uPosition) { if (pMask->m_akWords[uPosition].Get() != ~(Word)0) { return false; } } return (pMask->m_akWords[uNumWords - 1].Get() & kUsedMask) == kUsedMask; } static void BitwiseOr(BitMaskWord* pResult, const BitMaskWord& kLeft, const BitMaskWord& kRight) { for (uint32 uIndex = 0; uIndex < uNumWords; ++uIndex) { pResult->m_akWords[uIndex].Set(kLeft.m_akWords[uIndex].Get() | kRight.m_akWords[uIndex].Get()); } } static void BitwiseAnd(BitMaskWord* pResult, const BitMaskWord& kLeft, const BitMaskWord& kRight) { for (uint32 uIndex = 0; uIndex < uNumWords; ++uIndex) { pResult->m_akWords[uIndex].Set(kLeft.m_akWords[uIndex].Get() & kRight.m_akWords[uIndex].Get()); } } static bool Equals(const BitMaskWord& kLeft, const BitMaskWord& kRight) { for (uint32 uIndex = 0; uIndex < uNumWords; ++uIndex) { if (kLeft.m_akWords[uIndex].Get() != kRight.m_akWords[uIndex].Get()) { return false; } } return true; } static void Copy(BitMaskWord* pDestination, const BitMaskWord& kSource) { for (uint32 uIndex = 0; uIndex < uNumWords; ++uIndex) { pDestination->m_akWords[uIndex].Set(kSource.m_akWords[uIndex].Get()); } } }; template struct SBitMaskImpl<1, BitMaskWord> { typedef BitMaskWord Type; typedef typename BitMaskWord::Word Word; static void Init(Type* pMask, bool bValue, Word kUsedMask) { pMask->m_aMask = bValue ? kUsedMask : (Word)0; } static void SetZero(Type* pMask) { pMask->Set((Word)0); } static void SetOne(Type* pMask, Word kUsedMask) { pMask->Set(kUsedMask); } static bool IsZero(const Type* pMask, Word kUsedMask) { return (pMask->Get() & kUsedMask) == (Word)0; } static bool IsOne(const Type* pMask, Word kUsedMask) { return (pMask->Get() & kUsedMask) == kUsedMask; } static void BitwiseOr(Type* pResult, const Type& kLeft, const Type& kRight) { pResult->Set(kLeft.Get() | kRight.Get()); } static void BitwiseAnd(Type* pResult, const Type& kLeft, const Type& kRight) { pResult->Set(kLeft.Get() & kRight.Get()); } static bool Equals(const Type& kLeft, const Type& kRight) { return kLeft.Get() == kRight.Get(); } static void Copy(Type* pDestination, const Type& kSource) { pDestination->Set(kSource.Get()); } }; template struct SBitMask : SBitMaskImpl<(uSize + BitMaskWord::BIT_SIZE - 1) / BitMaskWord::BIT_SIZE, BitMaskWord>::Type { typedef SBitMaskImpl<(uSize + BitMaskWord::BIT_SIZE - 1) / BitMaskWord::BIT_SIZE, BitMaskWord> Impl; typedef typename BitMaskWord::Word Word; enum { USED_MASK = ~(~(Word)0 << uSize % BitMaskWord::BIT_SIZE) }; // The following methods are not thread safe regardless of the BitMaskWord type SBitMask(bool bInitValue = false) { Impl::Init(this, bInitValue, (Word)USED_MASK); } SBitMask(const SBitMask& kOther) { Impl::Copy(this, kOther); } void SetZero() { return Impl::SetZero(this); } void SetOne() { return Impl::SetOne(this, (Word)USED_MASK); } bool IsZero() const { return Impl::IsZero(this, (Word)USED_MASK); } bool IsOne() const { return Impl::IsOne(this, (Word)USED_MASK); } SBitMask& operator|=(const SBitMask& kOther) { Impl::BitwiseOr(this, *this, kOther); return *this; } SBitMask& operator&=(const SBitMask& kOther) { Impl::BitwiseAnd(this, *this, kOther); return *this; } SBitMask operator|(const SBitMask& kOther) const { SBitMask kResult; Impl::BitwiseOr(&kResult, *this, kOther); return kResult; } SBitMask operator&(const SBitMask& kOther) const { SBitMask kResult; Impl::BitwiseAnd(&kResult, *this, kOther); return kResult; } bool operator==(const SBitMask& kOther) const { return Impl::Equals(*this, kOther); } bool operator!=(const SBitMask& kOther) const { return !Impl::Equals(*this, kOther); } SBitMask& operator=(const SBitMask& kOther) { Impl::Copy(this, kOther); return *this; } }; inline void* CreateTLS() { #if defined(WIN32) return alias_cast(TlsAlloc()); #elif AZ_LEGACY_CRYCOMMON_TRAIT_USE_PTHREADS pthread_key_t* pKey(new pthread_key_t()); pthread_key_create(pKey, NULL); return alias_cast(pKey); #else #error "Not implemented on this platform" #endif } inline void DestroyTLS(void* pTLSHandle) { #if defined(WIN32) TlsFree(alias_cast(pTLSHandle)); #elif AZ_LEGACY_CRYCOMMON_TRAIT_USE_PTHREADS pthread_key_t* pKey(alias_cast(pTLSHandle)); pthread_key_delete(*pKey); #else #error "Not implemented on this platform" #endif } inline void* GetTLSValue(void* pTLSHandle) { #if defined(WIN32) return TlsGetValue(alias_cast(pTLSHandle)); #elif AZ_LEGACY_CRYCOMMON_TRAIT_USE_PTHREADS return pthread_getspecific(*alias_cast(pTLSHandle)); #else #error "Not implemented on this platform" #endif } inline void SetTLSValue(void* pTLSHandle, void* pValue) { #if defined(WIN32) TlsSetValue(alias_cast(pTLSHandle), pValue); #elif AZ_LEGACY_CRYCOMMON_TRAIT_USE_PTHREADS pthread_setspecific(*alias_cast(pTLSHandle), pValue); #else #error "Not implemented on this platform" #endif } struct SList { typedef SLockFreeSingleLinkedListHeader TListHeader; typedef SLockFreeSingleLinkedListEntry TListEntry; SList() { CryInitializeSListHead(m_kHeader); } void Push(TListEntry& kEntry) { CryInterlockedPushEntrySList(m_kHeader, kEntry); } TListEntry* Pop() { return alias_cast(CryInterlockedPopEntrySList(m_kHeader)); } TListHeader m_kHeader; }; struct SScopedProfileLabel { const char* m_szName; SScopedProfileLabel(const char* szName) : m_szName(szName) { PushProfileLabel(m_szName); } ~SScopedProfileLabel() { PopProfileLabel(m_szName); } }; } #if DXGL_PROFILING #define DXGL_SCOPED_PROFILE(_Name) NCryOpenGL::SScopedProfileLabel kDXGLScopedProfileLabel(_Name); #else #define DXGL_SCOPED_PROFILE(_Name) #endif #endif //__GLPLATFORM__