project(usd)
-if (NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
- if (WIN32)
- message(FATAL_ERROR "Compiler does not support 64-bit builds. "
- "If you are using Visual Studio, make sure you are in the "
- "x64 command prompt and have specified the Win64 cmake "
- "generator (e.g., -G \"Visual Studio 15 2017 Win64\")")
- else()
- message(FATAL_ERROR "Compiler does not support 64-bit builds.")
- endif()
-endif()
-
list(APPEND CMAKE_MODULE_PATH
${PROJECT_SOURCE_DIR}/cmake/defaults
${PROJECT_SOURCE_DIR}/cmake/modules
Arch_ObtainCacheLineSize()
{
#if defined(ARCH_OS_LINUX)
+#if defined(ARCH_BITS_64)
return sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
+#else
+ return 64;
+#endif
#elif defined(ARCH_OS_DARWIN)
size_t cacheLineSize = 0;
size_t cacheLineSizeSize = sizeof(cacheLineSize);
#if defined(__x86_64__) || defined(__aarch64__) || defined(_M_X64)
#define ARCH_BITS_64
#else
-#error "Unsupported architecture. x86_64 or ARM64 required."
+#define ARCH_BITS_32
#endif
//
double
Arch_ComputeNanosecondsPerTick()
{
-#if defined(ARCH_CPU_ARM)
+#if defined(ARCH_CPU_ARM) && defined(ARCH_BITS_64)
uint64_t counter_hz;
__asm __volatile("mrs %0, CNTFRQ_EL0" : "=&r" (counter_hz));
Arch_NanosecondsPerTick = double(1e9) / double(counter_hz);
#include <iterator>
#include <numeric>
+#ifdef ARCH_BITS_32
+#include <chrono>
+#include <thread>
+#endif // ARCH_BITS_32
+
PXR_NAMESPACE_OPEN_SCOPE
/// Return the current time in system-dependent units.
// On Intel we'll use the rdtsc instruction.
return __rdtsc();
#elif defined (ARCH_CPU_ARM)
+#ifdef ARCH_BITS_64
uint64_t result;
__asm __volatile("mrs %0, CNTVCT_EL0" : "=&r" (result));
return result;
+#else
+ auto epoch = std::chrono::steady_clock::now().time_since_epoch();
+ auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
+ return static_cast<uint64_t>(duration.count());
+#endif // ARCH_BITS_64s
#else
#error Unknown architecture.
#endif
ArchGetStartTickTime()
{
uint64_t t;
-#if defined (ARCH_OS_DARWIN)
+#if defined (ARCH_OS_DARWIN) || defined (ARCH_BITS_32)
return ArchGetTickTime();
#elif defined (ARCH_CPU_ARM)
std::atomic_signal_fence(std::memory_order_seq_cst);
ArchGetStopTickTime()
{
uint64_t t;
-#if defined (ARCH_OS_DARWIN)
+#if defined (ARCH_OS_DARWIN) || defined (ARCH_BITS_32)
return ArchGetTickTime();
#elif defined (ARCH_CPU_ARM)
std::atomic_signal_fence(std::memory_order_seq_cst);
#include "pxr/base/arch/attributes.h"
#include "pxr/base/arch/debugger.h"
+#include "pxr/base/arch/defines.h"
#include "pxr/base/arch/hash.h"
#include "pxr/base/arch/inttypes.h"
#include "pxr/base/arch/mallocHook.h"
};
#if !defined(ARCH_OS_WINDOWS)
+#ifdef ARCH_BITS_64
static_assert(sizeof(Tf_MallocBlockInfo) == 16,
"Unexpected size for Tf_MallocBlockInfo");
+#else
+static_assert(sizeof(Tf_MallocBlockInfo) == 8,
+ "Unexpected size for Tf_MallocBlockInfo");
+#endif // ARCH_BITS_64
#endif
/*
#include "pxr/pxr.h"
#include "pxr/base/arch/pragmas.h"
+#include "pxr/base/arch/defines.h"
#include <cstdint>
#include <type_traits>
+#include <limits>
#include <utility>
PXR_NAMESPACE_OPEN_SCOPE
+#ifdef ARCH_BITS_32
+// If we are on a 32 bit architecture, we just store 32bits and a pointer with 32 bits
+// Taken from: https://github.com/autodesk-forks/USD/blob/adsk/collab/port-python-wasm/pxr/base/tf/pointerAndBits.h
+/// \class TfPointerAndBits
+///
+/// This class stores a T * and a small integer in the space of a T *. The
+/// number of bits possible to store depends on the alignment of T. The
+/// number of distinct values representable by the bits and the maximal value
+/// are exposed via the compile time constants \a NumBitsValues and \a
+/// MaxValue, respectively.
+///
+/// The bits may be set and retrieved as any integral type. The pointer value
+/// and the bits value may be set and retrieved independently.
+///
+template <class T>
+class TfPointerAndBits
+{
+public:
+ /// Constructor. Pointer is initialized to null, bits are initialized to
+ /// zero.
+ constexpr TfPointerAndBits() noexcept : _ptr(0), _bits(0) {
+ }
+
+ /// Constructor. Set the pointer to \a p, and the bits to \a bits.
+ constexpr explicit TfPointerAndBits(T *p, uintptr_t bits = 0) noexcept
+ : _ptr(p), _bits(bits)
+ {
+ }
+
+ constexpr uintptr_t GetMaxValue() const {
+ return std::numeric_limits<uint32_t>::max();
+ }
+
+ constexpr uintptr_t GetNumBitsValues() const {
+ return 32;
+ }
+
+ /// Assignment. Leaves bits unmodified.
+ TfPointerAndBits &operator=(T *ptr) noexcept {
+ _SetPtr(ptr);
+ return *this;
+ }
+
+ /// Indirection.
+ constexpr T *operator->() const noexcept {
+ return _GetPtr();
+ }
+
+ /// Dereference.
+ constexpr T &operator *() const noexcept {
+ return *_GetPtr();
+ }
+
+ /// Retrieve the stored bits as the integral type \a Integral.
+ template <class Integral>
+ constexpr Integral BitsAs() const noexcept {
+ return static_cast<Integral>(_bits);
+ }
+
+ /// Set the stored bits. No static range checking is performed.
+ template <class Integral>
+ void SetBits(Integral val) noexcept {
+ _SetBits(static_cast<int32_t>(val));
+ }
+
+ /// Set the pointer value to \a ptr.
+ void Set(T *ptr) noexcept {
+ _SetPtr(ptr);
+ }
+
+ /// Set the pointer value to \a ptr and the bits to \a val.
+ template <class Integral>
+ void Set(T *ptr, Integral val) noexcept {
+ _ptr = ptr;
+ _bits = static_cast<int32_t>(val);
+ }
+
+ /// Retrieve the pointer.
+ constexpr T *Get() const noexcept {
+ return _GetPtr();
+ }
+
+ /// Retrieve the raw underlying value. This can be useful for doing literal
+ /// equality checks between two instances. The only guarantees are that
+ /// this has the same bit pattern as the pointer value if the bits are 0,
+ /// and will compare equal to another instance when both have identical
+ /// pointer and bits values.
+ constexpr uintptr_t GetLiteral() const noexcept {
+ return (static_cast<uint64_t>(_bits) << 32) | reinterpret_cast<uint64_t>(_ptr);
+ }
+
+ /// Swap this PointerAndBits with \a other.
+ void Swap(TfPointerAndBits &other) noexcept {
+ ::std::swap(_ptr, other._ptr);
+ ::std::swap(_bits, other._bits);
+ }
+
+private:
+ constexpr uintptr_t _GetBitMask() const noexcept {
+ return GetMaxValue();
+ }
+
+ // Retrieve the held pointer value.
+ constexpr T *_GetPtr() const noexcept {
+ return _ptr;
+ }
+
+ // Set the held pointer value.
+ void _SetPtr(T *p) noexcept {
+ _ptr = p;
+ }
+
+ // Retrieve the held bits value.
+ constexpr uint32_t _GetBits() const noexcept {
+ return _bits;
+ }
+
+ // Set the held bits value.
+ void _SetBits(uint32_t bits) noexcept {
+ _bits = bits;
+ }
+
+ // Single pointer member stores pointer value and bits.
+ T *_ptr;
+ uint32_t _bits;
+};
+#else
// Return true if \p val is a power of two.
constexpr bool Tf_IsPow2(uintptr_t val) {
return val && !(val & (val - 1));
// Single pointer member stores pointer value and bits.
T *_ptrAndBits;
};
+#endif
PXR_NAMESPACE_CLOSE_SCOPE
//
#include "pxr/pxr.h"
#include "pxr/base/tf/smallVector.h"
+#include "pxr/base/arch/defines.h"
PXR_NAMESPACE_OPEN_SCOPE
+#ifndef ARCH_BITS_32
static_assert(
sizeof(TfSmallVector<int, 1>) == 16,
"Expecting sizeof(TfSmallVector<int, N = 1>) to be 16 bytes.");
+#else
+static_assert(
+ sizeof(TfSmallVector<int, 1>) == 12,
+ "Expecting sizeof(TfSmallVector<int, N = 1>) to be 12 bytes.");
+#endif
static_assert(
sizeof(TfSmallVector<int, 2>) == 16,
sizeof(TfSmallVector<double, 2>) == 24,
"Expecting sizeof(TfSmallVector<double, N = 2>) to be 24 bytes.");
+#ifndef ARCH_BITS_32
static_assert(
TfSmallVectorBase::ComputeSerendipitousLocalCapacity<char>() == 8,
"Expecting 8 bytes of local capacity.");
+#else
+static_assert(
+ TfSmallVectorBase::ComputeSerendipitousLocalCapacity<char>() == 4,
+ "Expecting 4 bytes of local capacity.");
+#endif
PXR_NAMESPACE_CLOSE_SCOPE
#include "pxr/pxr.h"
#include "pxr/usd/ndr/api.h"
#include "pxr/base/tf/token.h"
+#include "pxr/base/arch/defines.h"
#include <memory>
#include <string>
#include <unordered_set>
#include <vector>
+#ifdef ARCH_BITS_32
+#include <boost/functional/hash.hpp>
+#endif // ARCH_BITS_32
+
PXR_NAMESPACE_OPEN_SCOPE
class NdrNode;
NDR_API
std::size_t GetHash() const
{
- return (static_cast<std::size_t>(_major) << 32) +
- static_cast<std::size_t>(_minor);
+ #ifdef ARCH_BITS_32
+ size_t h = 0;
+ boost::hash_combine(h, _major);
+ boost::hash_combine(h, _minor);
+ return h;
+ #else
+ return (static_cast<std::size_t>(_major) << 32) +
+ static_cast<std::size_t>(_minor);
+ #endif // ARCH_BITS_32
}
/// Return true iff the version is valid.
struct Sdf_PathPropTag;
// These are validated below.
-static constexpr size_t Sdf_SizeofPrimPathNode = sizeof(void *) * 3;
-static constexpr size_t Sdf_SizeofPropPathNode = sizeof(void *) * 3;
+static constexpr size_t Sdf_SizeofPrimPathNode = sizeof(TfToken) + 2 * sizeof(unsigned int) + sizeof(void*);
+static constexpr size_t Sdf_SizeofPropPathNode = sizeof(TfToken) + 2 * sizeof(unsigned int) + sizeof(void*);
using Sdf_PathPrimPartPool = Sdf_Pool<
Sdf_PathPrimTag, Sdf_SizeofPrimPathNode, /*regionBits=*/8>;
// Size of path nodes is important, so we want the compiler to tell us if it
// changes.
-static_assert(sizeof(Sdf_PrimPathNode) == 3 * sizeof(void *), "");
-static_assert(sizeof(Sdf_PrimPropertyPathNode) == 3 * sizeof(void *), "");
+static_assert(sizeof(Sdf_PrimPathNode) == sizeof(TfToken) + 2 * sizeof(unsigned int) + sizeof(void*), "");
+static_assert(sizeof(Sdf_PrimPropertyPathNode) == sizeof(TfToken) + 2 * sizeof(unsigned int) + sizeof(void*), "");
struct Sdf_PathNodePrivateAccess
{
#include "pxr/base/tf/exception.h"
#include "pxr/base/tf/stringUtils.h"
+#include "pxr/base/arch/defines.h"
+
#include <algorithm>
#include <sstream>
#include <vector>
// Static assertion on PrimData size. We want to be warned when its size
// changes.
+#ifndef ARCH_BITS_32
static_assert(sizeof(Usd_PrimData) == 64,
"Expected sizeof(Usd_PrimData) == 64");
+#else
+static_assert(sizeof(Usd_PrimData) == 48,
+ "Expected sizeof(Usd_PrimData) == 48");
+#endif
// Usd_PrimData need to be always initialized with a valid type info pointer
static const UsdPrimTypeInfo *_GetEmptyPrimTypeInfo()