Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
+525
View File
@@ -0,0 +1,525 @@
/*
* 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 : shadow volume AABB functionality for overlap testings
#ifndef CRYINCLUDE_CRYCOMMON_AABBSV_H
#define CRYINCLUDE_CRYCOMMON_AABBSV_H
#pragma once
#include "Cry_Geo.h"
struct Shadowvolume
{
uint32 sideamount;
uint32 nplanes;
Plane oplanes[10];
};
namespace NAABB_SV
{
//***************************************************************************************
//***************************************************************************************
//*** Calculate a ShadowVolume using an AABB and a point-light ***
//***************************************************************************************
//*** The planes of the AABB facing away from the point-light are the far-planes ***
//*** of the ShadowVolume. There can be 3-6 far-planes. ***
//***************************************************************************************
void AABB_ReceiverShadowVolume(const Vec3& PointLight, const AABB& Occluder, Shadowvolume& sv);
//***************************************************************************************
//***************************************************************************************
//*** Calculate a ShadowVolume using an AABB and a point-light ***
//***************************************************************************************
//*** The planes of the AABB facing the point-light are the near-planes of the ***
//*** the ShadowVolume. There can be 1-3 near-planes. ***
//*** The far-plane is defined by lightrange. ***
//***************************************************************************************
void AABB_ShadowVolume(const Vec3& PointLight, const AABB& Occluder, Shadowvolume& sv, f32 lightrange);
//***************************************************************************************
//*** this is the "fast" version to check if an AABB is overlapping a shadowvolume ***
//***************************************************************************************
bool Is_AABB_In_ShadowVolume(const Shadowvolume& sv, const AABB& Receiver);
//***************************************************************************************
//*** this is the "hierarchical" check ***
//***************************************************************************************
char Is_AABB_In_ShadowVolume_hierarchical(const Shadowvolume& sv, const AABB& Receiver);
}
inline void NAABB_SV::AABB_ReceiverShadowVolume(const Vec3& PointLight, const AABB& Occluder, Shadowvolume& sv)
{
sv.sideamount = 0;
sv.nplanes = 0;
//------------------------------------------------------------------------------
//-- check if PointLight is in front of any occluder plane or inside occluder --
//------------------------------------------------------------------------------
uint32 front = 0;
if (PointLight.x < Occluder.min.x)
{
front |= 0x01;
}
if (PointLight.x > Occluder.max.x)
{
front |= 0x02;
}
if (PointLight.y < Occluder.min.y)
{
front |= 0x04;
}
if (PointLight.y > Occluder.max.y)
{
front |= 0x08;
}
if (PointLight.z < Occluder.min.z)
{
front |= 0x10;
}
if (PointLight.z > Occluder.max.z)
{
front |= 0x20;
}
sv.sideamount = BoxSides[(front << 3) + 7];
uint32 back = front ^ 0x3f;
if (back & 0x01)
{
sv.oplanes[sv.nplanes].SetPlane(Vec3(-1, +0, +0), Occluder.min);
sv.nplanes++;
}
if (back & 0x02)
{
sv.oplanes[sv.nplanes].SetPlane(Vec3(+1, +0, +0), Occluder.max);
sv.nplanes++;
}
if (back & 0x04)
{
sv.oplanes[sv.nplanes].SetPlane(Vec3(+0, -1, +0), Occluder.min);
sv.nplanes++;
}
if (back & 0x08)
{
sv.oplanes[sv.nplanes].SetPlane(Vec3(+0, +1, +0), Occluder.max);
sv.nplanes++;
}
if (back & 0x10)
{
sv.oplanes[sv.nplanes].SetPlane(Vec3(+0, +0, -1), Occluder.min);
sv.nplanes++;
}
if (back & 0x20)
{
sv.oplanes[sv.nplanes].SetPlane(Vec3(+0, +0, +1), Occluder.max);
sv.nplanes++;
}
if (front == 0)
{
return; //light is inside occluder
}
//all 8 vertices of a AABB
Vec3 o[8] =
{
Vec3(Occluder.min.x, Occluder.min.y, Occluder.min.z),
Vec3(Occluder.max.x, Occluder.min.y, Occluder.min.z),
Vec3(Occluder.min.x, Occluder.max.y, Occluder.min.z),
Vec3(Occluder.max.x, Occluder.max.y, Occluder.min.z),
Vec3(Occluder.min.x, Occluder.min.y, Occluder.max.z),
Vec3(Occluder.max.x, Occluder.min.y, Occluder.max.z),
Vec3(Occluder.min.x, Occluder.max.y, Occluder.max.z),
Vec3(Occluder.max.x, Occluder.max.y, Occluder.max.z)
};
//---------------------------------------------------------------------
//--- find the silhouette-vertices of the occluder-AABB ---
//---------------------------------------------------------------------
uint32 p0 = BoxSides[(front << 3) + 0];
uint32 p1 = BoxSides[(front << 3) + 1];
uint32 p2 = BoxSides[(front << 3) + 2];
uint32 p3 = BoxSides[(front << 3) + 3];
uint32 p4 = BoxSides[(front << 3) + 4];
uint32 p5 = BoxSides[(front << 3) + 5];
float a;
if (sv.sideamount == 4)
{
//sv.oplanes[sv.nplanes+0] = Plane::CreatePlane( o[p0],o[p1], PointLight );
//sv.oplanes[sv.nplanes+1] = Plane::CreatePlane( o[p1],o[p2], PointLight );
//sv.oplanes[sv.nplanes+2] = Plane::CreatePlane( o[p2],o[p3], PointLight );
//sv.oplanes[sv.nplanes+3] = Plane::CreatePlane( o[p3],o[p0], PointLight );
sv.sideamount = 0;
a = (o[p1] - o[p0]) | (o[p0] - PointLight);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p0], o[p1], PointLight);
sv.sideamount++;
}
a = (o[p2] - o[p1]) | (o[p1] - PointLight);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p1], o[p2], PointLight);
sv.sideamount++;
}
a = (o[p3] - o[p2]) | (o[p2] - PointLight);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p2], o[p3], PointLight);
sv.sideamount++;
}
a = (o[p0] - o[p3]) | (o[p3] - PointLight);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p3], o[p0], PointLight);
sv.sideamount++;
}
}
if (sv.sideamount == 6)
{
//sv.oplanes[sv.nplanes+0] = Plane::CreatePlane( o[p0],o[p1], PointLight );
//sv.oplanes[sv.nplanes+1] = Plane::CreatePlane( o[p1],o[p2], PointLight );
//sv.oplanes[sv.nplanes+2] = Plane::CreatePlane( o[p2],o[p3], PointLight );
//sv.oplanes[sv.nplanes+3] = Plane::CreatePlane( o[p3],o[p4], PointLight );
//sv.oplanes[sv.nplanes+4] = Plane::CreatePlane( o[p4],o[p5], PointLight );
//sv.oplanes[sv.nplanes+5] = Plane::CreatePlane( o[p5],o[p0], PointLight );
sv.sideamount = 0;
a = (o[p1] - o[p0]) | (o[p0] - PointLight);
assert(sv.nplanes + sv.sideamount < 10);
PREFAST_ASSUME(sv.nplanes + sv.sideamount < 10);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p0], o[p1], PointLight);
sv.sideamount++;
}
a = (o[p2] - o[p1]) | (o[p1] - PointLight);
assert(sv.nplanes + sv.sideamount < 10);
PREFAST_ASSUME(sv.nplanes + sv.sideamount < 10);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p1], o[p2], PointLight);
sv.sideamount++;
}
a = (o[p3] - o[p2]) | (o[p2] - PointLight);
assert(sv.nplanes + sv.sideamount < 10);
PREFAST_ASSUME(sv.nplanes + sv.sideamount < 10);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p2], o[p3], PointLight);
sv.sideamount++;
}
a = (o[p4] - o[p3]) | (o[p3] - PointLight);
assert(sv.nplanes + sv.sideamount < 10);
PREFAST_ASSUME(sv.nplanes + sv.sideamount < 10);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p3], o[p4], PointLight);
sv.sideamount++;
}
a = (o[p5] - o[p4]) | (o[p4] - PointLight);
assert(sv.nplanes + sv.sideamount < 10);
PREFAST_ASSUME(sv.nplanes + sv.sideamount < 10);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p4], o[p5], PointLight);
sv.sideamount++;
}
a = (o[p0] - o[p5]) | (o[p5] - PointLight);
assert(sv.nplanes + sv.sideamount < 10);
PREFAST_ASSUME(sv.nplanes + sv.sideamount < 10);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p5], o[p0], PointLight);
sv.sideamount++;
}
}
}
inline void NAABB_SV::AABB_ShadowVolume(const Vec3& PointLight, const AABB& Occluder, Shadowvolume& sv, f32 lightrange)
{
sv.sideamount = 0;
sv.nplanes = 0;
//------------------------------------------------------------------------------
//-- check if PointLight is in front of any occluder plane or inside occluder --
//------------------------------------------------------------------------------
uint32 front = 0;
if (PointLight.x < Occluder.min.x)
{
front |= 0x01;
}
if (PointLight.x > Occluder.max.x)
{
front |= 0x02;
}
if (PointLight.y < Occluder.min.y)
{
front |= 0x04;
}
if (PointLight.y > Occluder.max.y)
{
front |= 0x08;
}
if (PointLight.z < Occluder.min.z)
{
front |= 0x10;
}
if (PointLight.z > Occluder.max.z)
{
front |= 0x20;
}
if (front == 0)
{
return; //light is inside occluder
}
sv.sideamount = BoxSides[(front << 3) + 7];
if (front & 0x01)
{
sv.oplanes[sv.nplanes].SetPlane(Vec3(-1, +0, +0), Occluder.min);
sv.nplanes++;
}
if (front & 0x02)
{
sv.oplanes[sv.nplanes].SetPlane(Vec3(+1, +0, +0), Occluder.max);
sv.nplanes++;
}
if (front & 0x04)
{
sv.oplanes[sv.nplanes].SetPlane(Vec3(+0, -1, +0), Occluder.min);
sv.nplanes++;
}
if (front & 0x08)
{
sv.oplanes[sv.nplanes].SetPlane(Vec3(+0, +1, +0), Occluder.max);
sv.nplanes++;
}
if (front & 0x10)
{
sv.oplanes[sv.nplanes].SetPlane(Vec3(+0, +0, -1), Occluder.min);
sv.nplanes++;
}
if (front & 0x20)
{
sv.oplanes[sv.nplanes].SetPlane(Vec3(+0, +0, +1), Occluder.max);
sv.nplanes++;
}
//all 8 vertices of a AABB
Vec3 o[8] =
{
Vec3(Occluder.min.x, Occluder.min.y, Occluder.min.z),
Vec3(Occluder.max.x, Occluder.min.y, Occluder.min.z),
Vec3(Occluder.min.x, Occluder.max.y, Occluder.min.z),
Vec3(Occluder.max.x, Occluder.max.y, Occluder.min.z),
Vec3(Occluder.min.x, Occluder.min.y, Occluder.max.z),
Vec3(Occluder.max.x, Occluder.min.y, Occluder.max.z),
Vec3(Occluder.min.x, Occluder.max.y, Occluder.max.z),
Vec3(Occluder.max.x, Occluder.max.y, Occluder.max.z)
};
//---------------------------------------------------------------------
//--- find the silhouette-vertices of the occluder-AABB ---
//---------------------------------------------------------------------
uint32 p0 = BoxSides[(front << 3) + 0];
uint32 p1 = BoxSides[(front << 3) + 1];
uint32 p2 = BoxSides[(front << 3) + 2];
uint32 p3 = BoxSides[(front << 3) + 3];
uint32 p4 = BoxSides[(front << 3) + 4];
uint32 p5 = BoxSides[(front << 3) + 5];
//the new center-position in world-space
Vec3 MiddleOfOccluder = (Occluder.max + Occluder.min) * 0.5f;
sv.oplanes[sv.nplanes] = Plane::CreatePlane((MiddleOfOccluder - PointLight).GetNormalized(), (MiddleOfOccluder - PointLight).GetNormalized() * lightrange + PointLight);
sv.nplanes++;
float a;
if (sv.sideamount == 4)
{
sv.sideamount = 0;
a = (o[p1] - o[p0]) | (o[p0] - PointLight);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p0], o[p1], PointLight);
sv.sideamount++;
}
a = (o[p2] - o[p1]) | (o[p1] - PointLight);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p1], o[p2], PointLight);
sv.sideamount++;
}
a = (o[p3] - o[p2]) | (o[p2] - PointLight);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p2], o[p3], PointLight);
sv.sideamount++;
}
a = (o[p0] - o[p3]) | (o[p3] - PointLight);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p3], o[p0], PointLight);
sv.sideamount++;
}
}
if (sv.sideamount == 6)
{
sv.sideamount = 0;
a = (o[p1] - o[p0]) | (o[p0] - PointLight);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p0], o[p1], PointLight);
sv.sideamount++;
}
a = (o[p2] - o[p1]) | (o[p1] - PointLight);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p1], o[p2], PointLight);
sv.sideamount++;
}
a = (o[p3] - o[p2]) | (o[p2] - PointLight);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p2], o[p3], PointLight);
sv.sideamount++;
}
a = (o[p4] - o[p3]) | (o[p3] - PointLight);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p3], o[p4], PointLight);
sv.sideamount++;
}
a = (o[p5] - o[p4]) | (o[p4] - PointLight);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p4], o[p5], PointLight);
sv.sideamount++;
}
a = (o[p0] - o[p5]) | (o[p5] - PointLight);
if (a)
{
sv.oplanes[sv.nplanes + sv.sideamount] = Plane::CreatePlane(o[p5], o[p0], PointLight);
sv.sideamount++;
}
}
}
inline bool NAABB_SV::Is_AABB_In_ShadowVolume(const Shadowvolume& sv, const AABB& Receiver)
{
uint32 pa = sv.sideamount + sv.nplanes;
f32 d;
const Vec3* pAABB = &Receiver.min;
union f32_u
{
float floatVal;
uint32 uintVal;
};
//------------------------------------------------------------------------------
//---- check if receiver-AABB is in front of any of these planes ------
//------------------------------------------------------------------------------
for (uint32 x = 0; x < pa; x++)
{
d = sv.oplanes[x].d;
//avoid breaking strict aliasing rules
f32_u ux;
ux.floatVal = sv.oplanes[x].n.x;
f32_u uy;
uy.floatVal = sv.oplanes[x].n.y;
f32_u uz;
uz.floatVal = sv.oplanes[x].n.z;
const uint32 bitX = ux.uintVal >> 31;
const uint32 bitY = uy.uintVal >> 31;
const uint32 bitZ = uz.uintVal >> 31;
d += sv.oplanes[x].n.x * pAABB[bitX].x;
d += sv.oplanes[x].n.y * pAABB[bitY].y;
d += sv.oplanes[x].n.z * pAABB[bitZ].z;
if (d > 0)
{
return CULL_EXCLUSION;
}
}
return CULL_OVERLAP;
}
inline char NAABB_SV::Is_AABB_In_ShadowVolume_hierarchical(const Shadowvolume& sv, const AABB& Receiver)
{
uint32 pa = sv.sideamount + sv.nplanes;
const Vec3* pAABB = &Receiver.min;
f32 dot1, dot2;
uint32 notOverlap = 0x80000000; // will be reset to 0 if there's at least one overlapping
union f32_u
{
float floatVal;
uint32 uintVal;
};
//------------------------------------------------------------------------------
//---- check if receiver-AABB is in front of any of these planes ------
//------------------------------------------------------------------------------
for (uint32 x = 0; x < pa; x++)
{
dot1 = dot2 = sv.oplanes[x].d;
//avoid breaking strict aliasing rules
f32_u ux;
ux.floatVal = sv.oplanes[x].n.x;
f32_u uy;
uy.floatVal = sv.oplanes[x].n.y;
f32_u uz;
uz.floatVal = sv.oplanes[x].n.z;
const uint32 bitX = ux.uintVal >> 31;
const uint32 bitY = uy.uintVal >> 31;
const uint32 bitZ = uz.uintVal >> 31;
dot1 += sv.oplanes[x].n.x * pAABB[0 + bitX].x;
dot2 += sv.oplanes[x].n.x * pAABB[1 - bitX].x;
dot1 += sv.oplanes[x].n.y * pAABB[0 + bitY].y;
dot2 += sv.oplanes[x].n.y * pAABB[1 - bitY].y;
dot1 += sv.oplanes[x].n.z * pAABB[0 + bitZ].z;
dot2 += sv.oplanes[x].n.z * pAABB[1 - bitZ].z;
PREFAST_SUPPRESS_WARNING(6001) f32_u d;
d.floatVal = dot1;
if (!(d.uintVal & 0x80000000))
{
return CULL_EXCLUSION;
}
PREFAST_SUPPRESS_WARNING(6001) f32_u d2;
d2.floatVal = dot2;
notOverlap &= d2.uintVal;
}
if (notOverlap)
{
return CULL_INCLUSION;
}
return CULL_OVERLAP;
}
#endif // CRYINCLUDE_CRYCOMMON_AABBSV_H
+74
View File
@@ -0,0 +1,74 @@
/*
* 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.
*
*/
#ifndef CRYINCLUDE_CRYCOMMON_ALGORITHM_H
#define CRYINCLUDE_CRYCOMMON_ALGORITHM_H
#pragma once
//short hand for using stl algorithms. same syntax (from users perspective) of c++17 range library. Only the shorthand algorithms from range library(N4128) though.
//Not all algorithms are covered. Add any as you need them. It would be a fair amount of work to add them all, so I'm just adding them as needed.
//Note Android doesn't have non member cbegin and cend yet.
#include <algorithm>
#include <numeric>
#include <iterator>
namespace std17
{
template<typename Container, typename Callable>
void for_each(const Container& con, Callable callable)
{
std::for_each(begin(con), end(con), callable);
}
template<typename Container, typename UnaryPredicate>
bool any_of(const Container& con, UnaryPredicate pred)
{
return std::any_of(begin(con), end(con), pred);
}
template<typename Container, typename UnaryPredicate>
bool all_of(const Container& con, UnaryPredicate pred)
{
return std::all_of(begin(con), end(con), pred);
}
template<typename Container, typename UnaryPredicate>
bool none_of(const Container& con, UnaryPredicate pred)
{
return std::none_of(begin(con), end(con), pred);
}
template<typename Container, typename UnaryPredicate>
typename Container::iterator find_if(Container& con, UnaryPredicate pred)
{
return std::find_if(begin(con), end(con), pred);
}
template <typename Container, typename T>
T accumulate(const Container& con, T init)
{
return std::accumulate(begin(con), end(con), init);
}
template <typename Container, typename T, class BinaryOperation>
T accumulate(const Container& con, T init, BinaryOperation binary_op)
{
return std::accumulate(begin(con), end(con), init, binary_op);
}
template <typename Container, typename UnaryPredicate>
auto count_if(const Container&con, UnaryPredicate pred)->decltype(std::count_if(begin(con), end(con), pred))
{
return std::count_if(begin(con), end(con), pred);
}
}
#endif // CRYINCLUDE_CRYCOMMON_ALGORITHM_H
+75
View File
@@ -0,0 +1,75 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYCOMMON_ALLOCATOR_H
#define CRYINCLUDE_CRYCOMMON_ALLOCATOR_H
#pragma once
#include "CryMemoryAllocator.h"
////////////////////////////////////////////////////////////////////////
// Allocator default implementation
struct StdAllocator
{
// Class-specific alloc/free/size functions. Use aligned versions only when necessary.
template<class T>
static void* Allocate(T*& p)
{
return p = NeedAlign<T>() ?
(T*)CryModuleMemalign(sizeof(T), alignof(T)) :
(T*)CryModuleMalloc(sizeof(T));
}
template<class T>
static void Deallocate(T* p)
{
if (NeedAlign<T>())
{
CryModuleMemalignFree(p);
}
else
{
CryModuleFree(p);
}
}
template<class T>
static size_t GetMemSize(const T* p)
{
return NeedAlign<T>() ?
sizeof(T) + alignof(T) :
sizeof(T);
}
template<typename T>
void GetMemoryUsage(ICrySizer* pSizer) const { /*nothing*/}
protected:
template<class T>
static bool NeedAlign()
{ PREFAST_SUPPRESS_WARNING(6326); return alignof(T) > _ALIGNMENT; }
};
// Handy delete template function, for any allocator.
template<class TAlloc, class T>
void Delete(TAlloc& alloc, T* ptr)
{
if (ptr)
{
ptr->~T();
alloc.Deallocate(ptr);
}
}
#endif // CRYINCLUDE_CRYCOMMON_ALLOCATOR_H
+220
View File
@@ -0,0 +1,220 @@
/*
* 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 : Specific to Android declarations, inline functions etc.
#ifndef CRYINCLUDE_CRYCOMMON_ANDROIDSPECIFIC_H
#define CRYINCLUDE_CRYCOMMON_ANDROIDSPECIFIC_H
#pragma once
#if defined(__arm__) || defined(__aarch64__)
#define _CPU_ARM
#endif
#if defined(__aarch64__)
#define PLATFORM_64BIT
#endif
#if defined(__ARM_NEON__)
#define _CPU_NEON
#endif
#ifndef MOBILE
#define MOBILE
#endif
#if (defined(__clang__) && NDK_REV_MAJOR >= 14) || (defined(_CPU_ARM) && defined(PLATFORM_64BIT))
// The version of clang that NDK r14+ ships with is seemingly generating different (for better or worse) code for the atomic operations
// used in the LocklessLinkedList. In either case, this is causing deadlocks in the job system and crashes from memory stomps in
// the bucket allocator. By defining INTERLOCKED_COMPARE_EXCHANGE_128_NOT_SUPPORTED it will disable the Cry job system as well as
// change the implementation of the LocklessLinkedList to use a mutex in it's operations instead, essentially use the same behaviour
// as iOS. While not ideal to use this as a band-aid on the problem, it does fix it with a negligible performance impact.
//
// Additionally, arm64 processors do not provide a cmpxchg16b (or equivalent) instruction required for _InterlockedCompareExchange128
#define INTERLOCKED_COMPARE_EXCHANGE_128_NOT_SUPPORTED
#endif
// Force all allocations to be aligned to TARGET_DEFAULT_ALIGN.
// This is because malloc on Android 32 bit returns memory that is not aligned
// to what some structs/classes need.
#define CRY_FORCE_MALLOC_NEW_ALIGN
#define DEBUG_BREAK raise(SIGTRAP)
#define RC_EXECUTABLE "rc"
#define USE_CRT 1
#define SIZEOF_PTR 4
//////////////////////////////////////////////////////////////////////////
// Standard includes.
//////////////////////////////////////////////////////////////////////////
#include <malloc.h>
#include <stdint.h>
#include <fcntl.h>
#include <float.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <time.h>
#include <ctype.h>
#include <sys/socket.h>
#include <errno.h>
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Define platform independent types.
//////////////////////////////////////////////////////////////////////////
#include "BaseTypes.h"
typedef signed long long INT64;
typedef double real;
typedef uint32 DWORD;
typedef DWORD* LPDWORD;
#if defined(PLATFORM_64BIT)
typedef uint64 DWORD_PTR;
#else
typedef DWORD DWORD_PTR;
#endif
typedef intptr_t INT_PTR, *PINT_PTR;
typedef uintptr_t UINT_PTR, * PUINT_PTR;
typedef char* LPSTR, * PSTR;
typedef uint64 __uint64;
typedef int64 INT64;
typedef uint64 UINT64;
typedef long LONG_PTR, * PLONG_PTR, * PLONG;
typedef unsigned long ULONG_PTR, * PULONG_PTR;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef void* HWND;
typedef UINT_PTR WPARAM;
typedef LONG_PTR LPARAM;
typedef LONG_PTR LRESULT;
#define PLARGE_INTEGER LARGE_INTEGER *
typedef const char* LPCSTR, * PCSTR;
typedef long long LONGLONG;
typedef ULONG_PTR SIZE_T;
typedef unsigned char byte;
#define ILINE __forceinline
#define _A_RDONLY (0x01)
#define _A_SUBDIR (0x10)
//////////////////////////////////////////////////////////////////////////
// Win32 FileAttributes.
//////////////////////////////////////////////////////////////////////////
#define FILE_ATTRIBUTE_READONLY 0x00000001
#define FILE_ATTRIBUTE_HIDDEN 0x00000002
#define FILE_ATTRIBUTE_SYSTEM 0x00000004
#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
#define FILE_ATTRIBUTE_DEVICE 0x00000040
#define FILE_ATTRIBUTE_NORMAL 0x00000080
#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
#define FILE_ATTRIBUTE_COMPRESSED 0x00000800
#define FILE_ATTRIBUTE_OFFLINE 0x00001000
#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
#define FILE_ATTRIBUTE_ENCRYPTED 0x00004000
#define INVALID_FILE_ATTRIBUTES (-1)
#define DEFINE_ALIGNED_DATA(type, name, alignment) \
type __attribute__ ((aligned(alignment))) name;
#define DEFINE_ALIGNED_DATA_STATIC(type, name, alignment) \
static type __attribute__ ((aligned(alignment))) name;
#define DEFINE_ALIGNED_DATA_CONST(type, name, alignment) \
const type __attribute__ ((aligned(alignment))) name;
#include "LinuxSpecific.h"
// these functions do not exist int the wchar.h header
#undef wscasecomp
#undef wscasencomp
extern int wcsicmp (const wchar_t* s1, const wchar_t* s2);
extern int wcsnicmp (const wchar_t* s1, const wchar_t* s2, size_t count);
// these are not defined in android-19 and prior
#undef wcsnlen
extern size_t wcsnlen(const wchar_t* str, size_t maxLen);
#undef stpcpy
extern char* stpcpy(char* dest, const char* str);
// end android-19
#define TARGET_DEFAULT_ALIGN (16U)
#ifdef _RELEASE
#define __debugbreak()
#else
#define __debugbreak() __builtin_trap()
#endif
// there is no __finite in android, only variants of isfinite
#undef __finite
#if NDK_REV_MAJOR >= 16
#define __finite isfinite
#else
#define __finite __isfinite
#endif
#define S_IWRITE S_IWUSR
#define ILINE __forceinline
#define _A_RDONLY (0x01)
#define _A_SUBDIR (0x10)
#define _A_HIDDEN (0x02)
#include <android/api-level.h>
#if __ANDROID_API__ == 19
// The following were apparently introduced in API 21, however in earlier versions of the
// platform specific headers they were defines. In the move to unified headers, the follwoing
// defines were removed from stat.h
#ifndef stat64
#define stat64 stat
#endif
#ifndef fstat64
#define fstat64 fstat
#endif
#ifndef lstat64
#define lstat64 lstat
#endif
#endif // __ANDROID_API__ == 19
// std::stoull deosn't exist on android, so we need to define it
namespace std
{
inline unsigned long long stoull(const std::string& str, size_t* idx = 0, int base = 10)
{
const char* start = str.c_str();
char* end = nullptr;
unsigned long long result = strtoull(start, &end, base);
if (idx)
{
*idx = end - start;
}
return result;
}
}
#endif // CRYINCLUDE_CRYCOMMON_ANDROIDSPECIFIC_H
+554
View File
@@ -0,0 +1,554 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYCOMMON_ANIMKEY_H
#define CRYINCLUDE_CRYCOMMON_ANIMKEY_H
#pragma once
#include <IConsole.h> // <> required for Interfuscator
#include <ISystem.h>
#include <Cry_Color.h>
#include <AzCore/Math/Color.h>
#include <AzCore/Component/EntityId.h>
enum EAnimKeyFlags
{
AKEY_SELECTED = 0x01, //! This key is selected in track view.
AKEY_SORT_MARKER = 0x02 //! Internal use to locate a key after a sort.
};
//! Interface to animation key.
//! Not real interface though...
//! No virtuals for optimization reason.
struct IKey
{
float time;
int flags;
// compare keys.
bool operator<(const IKey& key) const { return time < key.time; }
bool operator==(const IKey& key) const { return time == key.time; }
bool operator>(const IKey& key) const { return time > key.time; }
bool operator<=(const IKey& key) const { return time <= key.time; }
bool operator>=(const IKey& key) const { return time >= key.time; }
bool operator!=(const IKey& key) const { return time != key.time; }
IKey()
: time(0)
, flags(0) {};
virtual ~IKey() = default;
};
/** I2DBezierKey used in float tracks.
Its x component actually represents kinda time-warping curve.
*/
struct I2DBezierKey
: public IKey
{
Vec2 value;
};
/** ITcbKey used in all TCB tracks.
*/
struct ITcbKey
: public IKey
{
// Values.
float fval[4];
// Key controls.
float tens; //!< Key tension value.
float cont; //!< Key continuity value.
float bias; //!< Key bias value.
float easeto; //!< Key ease to value.
float easefrom; //!< Key ease from value.
//! Protect from direct instantiation of this class.
//! Only derived classes can be created,
ITcbKey()
{
fval[0] = 0;
fval[1] = 0;
fval[2] = 0;
fval[3] = 0;
tens = 0, cont = 0, bias = 0, easeto = 0, easefrom = 0;
};
void SetFloat(float val) { fval[0] = val; };
void SetVec3(const Vec3& val)
{
fval[0] = val.x;
fval[1] = val.y;
fval[2] = val.z;
};
void SetQuat(const Quat& val)
{
fval[0] = val.v.x;
fval[1] = val.v.y;
fval[2] = val.v.z;
fval[3] = val.w;
};
ILINE void SetValue(float val) { SetFloat(val); }
ILINE void SetValue(const Vec3& val) { SetVec3(val); }
ILINE void SetValue(const Quat& val) { SetQuat(val); }
float GetFloat() const { return *((float*)fval); };
Vec3 GetVec3() const
{
Vec3 vec;
vec.x = fval[0];
vec.y = fval[1];
vec.z = fval[2];
return vec;
};
Quat GetQuat() const
{
Quat quat;
quat.v.x = fval[0];
quat.v.y = fval[1];
quat.v.z = fval[2];
quat.w = fval[3];
return quat;
};
ILINE void GetValue(float& val) { val = GetFloat(); };
ILINE void GetValue(Vec3& val) { val = GetVec3(); };
ILINE void GetValue(Quat& val) { val = GetQuat(); };
};
struct IEventKey
: public IKey
{
AZStd::string event;
AZStd::string eventValue;
AZStd::string animation;
AZStd::string target;
union
{
float value;
float duration;
};
bool bNoTriggerInScrubbing;
IEventKey()
{
duration = 0;
bNoTriggerInScrubbing = false;
}
};
/** ISelectKey used in Camera selection track or Scene node.
*/
struct ISelectKey
: public IKey
{
AZStd::string szSelection; //!< Node name.
AZ::EntityId cameraAzEntityId; // will be Invalid for legacy Cameras
float fDuration;
float fBlendTime;
ISelectKey()
{
fDuration = 0;
fBlendTime = 0;
}
};
/** ISequenceKey used in sequence track.
*/
struct ISequenceKey
: public IKey
{
AZStd::string szSelection; //!@deprecated : use sequenceEntityId to identify sequences
AZ::EntityId sequenceEntityId;
float fDuration;
float fStartTime;
float fEndTime;
bool bOverrideTimes;
bool bDoNotStop;
ISequenceKey()
{
fDuration = 0;
fStartTime = 0;
fEndTime = 0;
bOverrideTimes = false;
bDoNotStop = false; // default crysis behaviour
}
};
/** ISoundKey used in sound track.
*/
struct ISoundKey
: public IKey
{
ISoundKey()
: fDuration(0.0f)
{
customColor.x = Col_TrackviewDefault.r;
customColor.y = Col_TrackviewDefault.g;
customColor.z = Col_TrackviewDefault.b;
}
AZStd::string sStartTrigger;
AZStd::string sStopTrigger;
float fDuration;
Vec3 customColor;
};
/** ITimeRangeKey used in time ranges animation track.
*/
#define ANIMKEY_TIME_RANGE_END_TIME_UNSET .0f
struct ITimeRangeKey
: public IKey
{
float m_duration; //!< Duration in seconds of this animation.
float m_startTime; //!< Start time of this animation (Offset from beginning of animation).
float m_endTime; //!< End time of this animation (can be smaller than the duration).
float m_speed; //!< Speed multiplier for this key.
bool m_bLoop; //!< True if time is looping
ITimeRangeKey()
{
m_duration = 0.0f;
m_endTime = ANIMKEY_TIME_RANGE_END_TIME_UNSET;
m_startTime = 0.0f;
m_speed = 1.0f;
m_bLoop = false;
}
float GetValidEndTime() const
{
float endTime = m_endTime;
if (endTime == ANIMKEY_TIME_RANGE_END_TIME_UNSET || (!m_bLoop && endTime > m_duration))
{
endTime = m_duration;
}
return endTime;
}
float GetValidSpeed() const
{
float speed = m_speed;
if (speed <= 0.0f)
{
speed = 1.0f;
}
return speed;
}
float GetActualDuration() const
{
return (GetValidEndTime() - m_startTime) / GetValidSpeed();
}
// Return true if the input time falls in range of the start/end time for this key.
bool IsInRange(float sequenceTime) const
{
return sequenceTime >= time && sequenceTime <= (time + GetActualDuration());
}
};
/** ICharacterKey used in Character animation track.
*/
struct ICharacterKey
: public ITimeRangeKey
{
AZStd::string m_animation; //!< Name of character animation.
bool m_bBlendGap; //!< True if gap to next animation should be blended
bool m_bInPlace; // Play animation in place (Do not move root).
ICharacterKey()
: ITimeRangeKey()
{
m_bLoop = false;
m_bBlendGap = false;
m_bInPlace = false;
}
};
/** IExprKey used in expression animation track.
*/
struct IExprKey
: public IKey
{
IExprKey()
{
pszName[0] = 0;
fAmp = 1.0f;
fBlendIn = 0.5f;
fHold = 1.0f;
fBlendOut = 0.5f;
}
char pszName[128]; //!< Name of morph-target
float fAmp;
float fBlendIn;
float fHold;
float fBlendOut;
};
/** IConsoleKey used in Console track, triggers console commands and variables.
*/
struct IConsoleKey
: public IKey
{
AZStd::string command;
};
struct ILookAtKey
: public IKey
{
AZStd::string szSelection; //!< Node name.
float fDuration;
AZStd::string lookPose;
float smoothTime;
ILookAtKey()
{
fDuration = 0;
smoothTime = 0.2f;
}
};
//! Discrete (non-interpolated) float key.
struct IDiscreteFloatKey
: public IKey
{
float m_fValue;
void SetValue(float fValue)
{
m_fValue = fValue;
}
IDiscreteFloatKey()
{
m_fValue = -1.0f;
}
};
//! A key for the capture track.
struct ICaptureKey
: public IKey
{
friend class AnimSerializer;
enum CaptureBufferType
{
Color = 0,
ColorWithAlpha,
NumCaptureBufferTypes // keep this last
};
enum CaptureFileFormat
{
Jpg = 0,
Tga,
Tif,
NumCaptureFileFormats // keep this last
};
float duration;
float timeStep;
AZStd::string folder;
bool once;
AZStd::string prefix;
CaptureBufferType captureBufferIndex;
const char* GetFormat() const
{ return format.c_str(); }
void FormatJPG()
{ format = "jpg"; }
void FormatTIF()
{ format = "tif"; }
void FormatTGA()
{ format = "tga"; }
void FormatHDR()
{
// deprecated
if (gEnv->pLog)
{
gEnv->pLog->LogWarning("'hdr' capture format is deprecated.");
}
format = "hdr";
}
void FormatBMP()
{
// deprecated
if (gEnv->pLog)
{
gEnv->pLog->LogWarning("'bmp' capture format is deprecated.");
}
format = "bmp";
}
ICaptureKey()
: IKey()
, duration(0)
, timeStep(0.033f)
, once(false)
, captureBufferIndex(Color)
{
FormatTGA();
ICVar* pCaptureFolderCVar = gEnv->pConsole->GetCVar("capture_folder");
if (pCaptureFolderCVar != NULL && pCaptureFolderCVar->GetString())
{
folder = pCaptureFolderCVar->GetString();
}
ICVar* pCaptureFilePrefixCVar = gEnv->pConsole->GetCVar("capture_file_prefix");
if (pCaptureFilePrefixCVar != NULL && pCaptureFilePrefixCVar->GetString())
{
prefix = pCaptureFilePrefixCVar->GetString();
}
ICVar* pCaptureFileFormatCVar = gEnv->pConsole->GetCVar("capture_file_format");
if (pCaptureFileFormatCVar != NULL)
{
format = pCaptureFileFormatCVar->GetString();
}
}
ICaptureKey(const ICaptureKey& other)
: IKey(other)
, folder(other.folder)
, prefix(other.prefix)
, duration(other.duration)
, timeStep(other.timeStep)
, once(other.once)
, format(other.format)
, captureBufferIndex(other.captureBufferIndex)
{
}
private:
AZStd::string format;
};
//! Boolean key.
struct IBoolKey
: public IKey
{
IBoolKey() {};
};
//! Comment Key.
struct ICommentKey
: public IKey
{
enum ETextAlign : int
{
eTA_Left = 0,
eTA_Center = BIT(1),
eTA_Right = BIT(2)
};
//-----------------------------------------------------------------------------
//!
ICommentKey()
: m_duration(1.f)
, m_size(1.f)
, m_align(eTA_Left)
, m_strFont("default")
, m_color(1.f, 1.f, 1.f, 1.f)
{
}
//-----------------------------------------------------------------------------
//!
ICommentKey(const ICommentKey& other)
: IKey(other)
, m_strComment(other.m_strComment)
, m_strFont(other.m_strFont)
{
m_duration = other.m_duration;
m_color = other.m_color;
m_size = other.m_size;
m_align = other.m_align;
}
AZStd::string m_strComment;
float m_duration;
AZStd::string m_strFont;
AZ::Color m_color;
float m_size;
ETextAlign m_align;
};
//-----------------------------------------------------------------------------
//!
struct IScreenFaderKey
: public IKey
{
//-----------------------------------------------------------------------------
//!
enum EFadeType : int
{
eFT_FadeIn = 0, eFT_FadeOut = 1
};
enum EFadeChangeType : int
{
eFCT_Linear = 0, eFCT_Square = 1, eFCT_CubicSquare = 2, eFCT_SquareRoot = 3, eFCT_Sin = 4
};
//-----------------------------------------------------------------------------
//!
IScreenFaderKey()
: IKey()
, m_fadeTime(2.f)
, m_bUseCurColor(true)
, m_fadeType(eFT_FadeOut)
, m_fadeChangeType(eFCT_Linear)
{
m_fadeColor = AZ::Color(.0f, .0f, .0f, 1.0f);
}
//-----------------------------------------------------------------------------
//!
IScreenFaderKey(const IScreenFaderKey& other)
: IKey(other)
, m_fadeTime(other.m_fadeTime)
, m_bUseCurColor(other.m_bUseCurColor)
, m_fadeType(other.m_fadeType)
, m_fadeChangeType(other.m_fadeChangeType)
{
m_fadeColor = other.m_fadeColor;
m_strTexture = other.m_strTexture;
}
//-----------------------------------------------------------------------------
//!
float m_fadeTime;
AZ::Color m_fadeColor;
AZStd::string m_strTexture;
bool m_bUseCurColor;
EFadeType m_fadeType;
EFadeChangeType m_fadeChangeType;
};
namespace AZ
{
AZ_TYPE_INFO_SPECIALIZE(IKey, "{680BD51E-C106-4BBF-9A6F-CD551E00519F}");
AZ_TYPE_INFO_SPECIALIZE(IBoolKey, "{DBF8044F-6E64-403D-807D-F3152F640703}");
AZ_TYPE_INFO_SPECIALIZE(ICaptureKey, "{93AA8D63-6B1E-4D33-8CC3-C82147BB95CB}");
AZ_TYPE_INFO_SPECIALIZE(ICharacterKey, "{6D1FB9E2-128C-4B33-84FF-4F696C1F7D53}");
AZ_TYPE_INFO_SPECIALIZE(ICommentKey, "{99C2234E-A4DD-45D1-90C3-D5AFC54FA47F}");
AZ_TYPE_INFO_SPECIALIZE(IConsoleKey, "{8C0DCB9B-297D-4AF4-A0D1-F5160E6900E8}");
AZ_TYPE_INFO_SPECIALIZE(IDiscreteFloatKey, "{469A2B90-E019-4147-A53F-2EB42E179596}");
AZ_TYPE_INFO_SPECIALIZE(IEventKey, "{F09533AA-9780-494D-9E5C-8CB98266AC5E}");
AZ_TYPE_INFO_SPECIALIZE(ILookAtKey, "{6F4CED0E-D83A-40E2-B7BF-038D82BC0374}");
AZ_TYPE_INFO_SPECIALIZE(IScreenFaderKey, "{FA15E27D-603F-4829-925A-E36D75C93964}");
AZ_TYPE_INFO_SPECIALIZE(ISelectKey, "{FCEADCF5-042E-473B-845F-0778F087B6DC}");
AZ_TYPE_INFO_SPECIALIZE(ISequenceKey, "{B55294AD-F14E-43AC-B6B5-AC27B377FE00}");
AZ_TYPE_INFO_SPECIALIZE(ISoundKey, "{452E50CF-B7D0-42D5-A86A-B295682674BB}");
AZ_TYPE_INFO_SPECIALIZE(ITimeRangeKey, "{17807C95-C7A1-481B-AD94-C54D83928D0B}");
}
#endif // CRYINCLUDE_CRYCOMMON_ANIMKEY_H
+173
View File
@@ -0,0 +1,173 @@
/*
* 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.
#ifndef __animtime_h__
#define __animtime_h__
#include <IXml.h>
#include <AzCore/Casting/numeric_cast.h>
#include <Serialization/IArchive.h>
struct SAnimTime
{
static const uint numTicksPerSecond = 6000;
// List of possible frame rates (dividers of 6000). Most commonly used ones first.
enum EFrameRate
{
// Common
eFrameRate_30fps, eFrameRate_60fps, eFrameRate_120fps,
// Possible
eFrameRate_10fps, eFrameRate_12fps, eFrameRate_15fps, eFrameRate_24fps,
eFrameRate_25fps, eFrameRate_40fps, eFrameRate_48fps, eFrameRate_50fps,
eFrameRate_75fps, eFrameRate_80fps, eFrameRate_100fps, eFrameRate_125fps,
eFrameRate_150fps, eFrameRate_200fps, eFrameRate_240fps, eFrameRate_250fps,
eFrameRate_300fps, eFrameRate_375fps, eFrameRate_400fps, eFrameRate_500fps,
eFrameRate_600fps, eFrameRate_750fps, eFrameRate_1000fps, eFrameRate_1200fps,
eFrameRate_1500fps, eFrameRate_2000fps, eFrameRate_3000fps, eFrameRate_6000fps,
eFrameRate_Num
};
SAnimTime()
: m_ticks(0) {}
explicit SAnimTime(int32 ticks)
: m_ticks(ticks) {}
explicit SAnimTime(float time)
: m_ticks(aznumeric_caster(std::lround(static_cast<double>(time) * numTicksPerSecond))) {}
static uint GetFrameRateValue(EFrameRate frameRate)
{
const uint frameRateValues[eFrameRate_Num] =
{
// Common
30, 60, 120,
// Possible
10, 12, 15, 24, 25, 40, 48, 50, 75, 80, 100, 125,
150, 200, 240, 250, 300, 375, 400, 500, 600, 750,
1000, 1200, 1500, 2000, 3000, 6000
};
return frameRateValues[frameRate];
}
static const char* GetFrameRateName(EFrameRate frameRate)
{
const char* frameRateNames[eFrameRate_Num] =
{
// Common
"30 fps", "60 fps", "120 fps",
// Possible
"10 fps", "12 fps", "15 fps", "24 fps",
"25 fps", "40 fps", "48 fps", "50 fps",
"75 fps", "80 fps", "100 fps", "125 fps",
"150 fps", "200 fps", "240 fps", "250 fps",
"300 fps", "375 fps", "400 fps", "500 fps",
"600 fps", "750 fps", "1000 fps", "1200 fps",
"1500 fps", "2000 fps", "3000 fps", "6000 fps"
};
return frameRateNames[frameRate];
}
float ToFloat() const { return static_cast<float>(m_ticks) / numTicksPerSecond; }
void Serialize(Serialization::IArchive& ar)
{
ar(m_ticks, "ticks", "Ticks");
}
// Helper to serialize from ticks or old float time
void Serialize(XmlNodeRef keyNode, bool bLoading, const char* pName, const char* pLegacyName)
{
if (bLoading)
{
int32 ticks;
if (!keyNode->getAttr(pName, ticks))
{
// Backwards compatibility
float time = 0.0f;
keyNode->getAttr(pLegacyName, time);
*this = SAnimTime(time);
}
else
{
m_ticks = ticks;
}
}
else if (m_ticks > 0)
{
keyNode->setAttr(pName, m_ticks);
}
}
int32 GetTicks() const { return m_ticks; }
static SAnimTime Min() { SAnimTime minTime; minTime.m_ticks = std::numeric_limits<int32>::lowest(); return minTime; }
static SAnimTime Max() { SAnimTime maxTime; maxTime.m_ticks = (std::numeric_limits<int32>::max)(); return maxTime; }
SAnimTime operator-() const { return SAnimTime(-m_ticks); }
SAnimTime operator-(SAnimTime r) const { SAnimTime temp = *this; temp.m_ticks -= r.m_ticks; return temp; }
SAnimTime operator+(SAnimTime r) const { SAnimTime temp = *this; temp.m_ticks += r.m_ticks; return temp; }
SAnimTime operator*(SAnimTime r) const { SAnimTime temp = *this; temp.m_ticks *= r.m_ticks; return temp; }
SAnimTime operator/(SAnimTime r) const { SAnimTime temp; temp.m_ticks = static_cast<int32>((static_cast<int64>(m_ticks) * numTicksPerSecond) / r.m_ticks); return temp; }
SAnimTime operator%(SAnimTime r) const { SAnimTime temp = *this; temp.m_ticks %= r.m_ticks; return temp; }
SAnimTime operator*(float r) const { SAnimTime temp; temp.m_ticks = aznumeric_caster(std::lround(static_cast<double>(m_ticks) * r)); return temp; }
SAnimTime operator/(float r) const { SAnimTime temp; temp.m_ticks = aznumeric_caster(std::lround(static_cast<double>(m_ticks) / r)); return temp; }
SAnimTime& operator+=(SAnimTime r) { *this = *this + r; return *this; }
SAnimTime& operator-=(SAnimTime r) { *this = *this - r; return *this; }
SAnimTime& operator*=(SAnimTime r) { *this = *this * r; return *this; }
SAnimTime& operator/=(SAnimTime r) { *this = *this / r; return *this; }
SAnimTime& operator%=(SAnimTime r) { *this = *this % r; return *this; }
SAnimTime& operator*=(float r) { *this = *this * r; return *this; }
SAnimTime& operator/=(float r) { *this = *this / r; return *this; }
bool operator<(SAnimTime r) const { return m_ticks < r.m_ticks; }
bool operator<=(SAnimTime r) const { return m_ticks <= r.m_ticks; }
bool operator>(SAnimTime r) const { return m_ticks > r.m_ticks; }
bool operator>=(SAnimTime r) const { return m_ticks >= r.m_ticks; }
bool operator==(SAnimTime r) const { return m_ticks == r.m_ticks; }
bool operator!=(SAnimTime r) const { return m_ticks != r.m_ticks; }
// Snap to nearest multiple of given frame rate
SAnimTime SnapToNearest(const EFrameRate frameRate)
{
const int sign = sgn(m_ticks);
const int32 absTicks = abs(m_ticks);
const int framesMod = numTicksPerSecond / GetFrameRateValue(frameRate);
const int32 remainder = absTicks % framesMod;
const bool bNextMultiple = remainder >= (framesMod / 2);
return SAnimTime(sign * ((absTicks - remainder) + (bNextMultiple ? framesMod : 0)));
}
private:
int32 m_ticks;
friend bool Serialize(Serialization::IArchive& ar, SAnimTime& animTime, const char* name, const char* label);
};
inline bool Serialize(Serialization::IArchive& ar, SAnimTime& animTime, const char* name, const char* label)
{
return ar(animTime.m_ticks, name, label);
}
inline SAnimTime abs(SAnimTime time)
{
return (time >= SAnimTime(0)) ? time : -time;
}
#endif
+597
View File
@@ -0,0 +1,597 @@
/*
* 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 : Apple specific declarations common amongst its products
#ifndef CRYINCLUDE_CRYCOMMON_APPLESPECIFIC_H
#define CRYINCLUDE_CRYCOMMON_APPLESPECIFIC_H
#pragma once
#if defined(__clang__)
#pragma diagnostic ignore "-W#pragma-messages"
#endif
#define DEBUG_BREAK __builtin_trap()
#define RC_EXECUTABLE "rc"
//////////////////////////////////////////////////////////////////////////
// Standard includes.
//////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <ctype.h>
#include <limits.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <malloc/malloc.h>
#include <Availability.h>
// Atomic operations , guaranteed to work across all apple platforms
#include <libkern/OSAtomic.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string>
//////////////////////////////////////////////////////////////////////////
#define FP16_MESH
#define BOOST_DISABLE_WIN32
#ifndef __COUNTER__
#define __COUNTER__ __LINE__
#endif
#ifdef __FUNC__
#undef __FUNC__
#endif
#define __FUNC__ __func__
typedef void* LPVOID;
#define VOID void
#define PVOID void*
typedef unsigned int UINT;
typedef char CHAR;
typedef float FLOAT;
#define PHYSICS_EXPORTS
// MSVC compiler-specific keywords
#define __forceinline inline
#define _inline inline
#define __cdecl
#define _cdecl
#define __stdcall
#define _stdcall
#define __fastcall
#define _fastcall
#define IN
#define OUT
#define MAP_ANONYMOUS MAP_ANON
//////////////////////////////////////////////////////////////////////////
// Define platform independent types.
//////////////////////////////////////////////////////////////////////////
#include "BaseTypes.h"
typedef double real;
typedef uint32 DWORD;
typedef DWORD* LPDWORD;
typedef uint64 DWORD_PTR;
typedef intptr_t INT_PTR, * PINT_PTR;
typedef uintptr_t UINT_PTR, * PUINT_PTR;
typedef char* LPSTR, * PSTR;
typedef char TCHAR;
typedef uint64 __uint64;
#if !defined(__clang__)
typedef int64 __int64;
#endif
typedef int64 INT64;
typedef uint64 UINT64;
typedef long LONG_PTR, * PLONG_PTR, * PLONG;
typedef unsigned long ULONG_PTR, * PULONG_PTR;
typedef uint8 BYTE;
typedef uint16 WORD;
typedef void* HWND;
typedef UINT_PTR WPARAM;
typedef LONG_PTR LPARAM;
typedef LONG_PTR LRESULT;
#define PLARGE_INTEGER LARGE_INTEGER *
typedef const char* LPCSTR, * PCSTR;
typedef long long LONGLONG;
typedef ULONG_PTR SIZE_T;
typedef uint8 byte;
#define ILINE __forceinline
#ifndef MAXUINT
#define MAXUINT ((uint) ~((uint)0))
#endif
#ifndef MAXINT
#define MAXINT ((int)(MAXUINT >> 1))
#endif
#ifndef _CVTBUFSIZE
#define _CVTBUFSIZE (309+40) /* # of digits in max. dp value + slop */
#endif
#ifndef STDMETHODCALLTYPE_DEFINED
#define STDMETHODCALLTYPE_DEFINED
#define STDMETHODCALLTYPE
#endif
#define _ALIGN(num) __attribute__ ((aligned(num)))
#define _PACK __attribute__ ((packed))
// Safe memory freeing
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if (p) { delete (p); (p) = NULL; } \
}
#endif
#ifndef SAFE_DELETE_ARRAY
#define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p); (p) = NULL; } \
}
#endif
#ifndef SAFE_RELEASE
#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p) = NULL; } \
}
#endif
#ifndef SAFE_RELEASE_FORCE
#define SAFE_RELEASE_FORCE(p) { if (p) { (p)->ReleaseForce(); (p) = NULL; } \
}
#endif
#define MAKEWORD(a, b) ((WORD)(((BYTE)((DWORD_PTR)(a) & 0xff)) | ((WORD)((BYTE)((DWORD_PTR)(b) & 0xff))) << 8))
#define MAKELONG(a, b) ((LONG)(((WORD)((DWORD_PTR)(a) & 0xffff)) | ((DWORD)((WORD)((DWORD_PTR)(b) & 0xffff))) << 16))
#define LOWORD(l) ((WORD)((DWORD_PTR)(l) & 0xffff))
#define HIWORD(l) ((WORD)((DWORD_PTR)(l) >> 16))
#define LOBYTE(w) ((BYTE)((DWORD_PTR)(w) & 0xff))
#define HIBYTE(w) ((BYTE)((DWORD_PTR)(w) >> 8))
#define CALLBACK
#define WINAPI
#ifndef __cplusplus
#ifndef _WCHAR_T_DEFINED
typedef unsigned short wchar_t;
#define TCHAR wchar_t;
#define _WCHAR_T_DEFINED
#endif
#endif
typedef wchar_t WCHAR; // wc, 16-bit UNICODE character
typedef WCHAR* PWCHAR;
typedef WCHAR* LPWCH, * PWCH;
typedef const WCHAR* LPCWCH, * PCWCH;
typedef WCHAR* NWPSTR;
typedef WCHAR* LPWSTR, * PWSTR;
typedef WCHAR* LPUWSTR, * PUWSTR;
typedef const WCHAR* LPCWSTR, * PCWSTR;
typedef const WCHAR* LPCUWSTR, * PCUWSTR;
#ifdef UNICODE
typedef LPCWSTR LPCTSTR;
typedef LPWSTR LPTSTR;
#else
typedef LPCSTR LPCTSTR;
typedef LPSTR LPTSTR;
#endif
typedef DWORD COLORREF;
#define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))
#define GetRValue(rgb) (LOBYTE(rgb))
#define GetGValue(rgb) (LOBYTE(((WORD)(rgb)) >> 8))
#define GetBValue(rgb) (LOBYTE((rgb)>>16))
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
#define FILE_ATTRIBUTE_NORMAL 0x00000080
// Conflit with OBJC defined bool type.
#if defined(IOS)
typedef bool BOOL;
#else
typedef signed char BOOL;
#endif
typedef int32_t LONG;
typedef unsigned int ULONG;
typedef int HRESULT;
//typedef int32 __int32;
typedef uint32 __uint32;
typedef int64 __int64;
typedef uint64 __uint64;
#define TRUE 1
#define FALSE 0
#ifndef MAX_PATH
#define MAX_PATH PATH_MAX
#endif
#ifndef _MAX_PATH
#define _MAX_PATH MAX_PATH
#endif
#define _PTRDIFF_T_DEFINED 1
#define _A_RDONLY (0x01) /* Read only file */
#define _A_HIDDEN (0x02) /* Hidden file */
#define _A_SUBDIR (0x10) /* Subdirectory */
//////////////////////////////////////////////////////////////////////////
// Win32 FileAttributes.
//////////////////////////////////////////////////////////////////////////
#define FILE_ATTRIBUTE_READONLY 0x00000001
#define FILE_ATTRIBUTE_HIDDEN 0x00000002
#define FILE_ATTRIBUTE_SYSTEM 0x00000004
#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
#define FILE_ATTRIBUTE_DEVICE 0x00000040
#define FILE_ATTRIBUTE_NORMAL 0x00000080
#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
#define FILE_ATTRIBUTE_COMPRESSED 0x00000800
#define FILE_ATTRIBUTE_OFFLINE 0x00001000
#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
#define FILE_ATTRIBUTE_ENCRYPTED 0x00004000
#define INVALID_FILE_ATTRIBUTES (-1)
#define DEFINE_ALIGNED_DATA(type, name, alignment) \
type __attribute__ ((aligned(alignment))) name;
#define DEFINE_ALIGNED_DATA_STATIC(type, name, alignment) \
static type __attribute__ ((aligned(alignment))) name;
#define DEFINE_ALIGNED_DATA_CONST(type, name, alignment) \
const type __attribute__ ((aligned(alignment))) name;
#define BST_UNCHECKED 0x0000
#ifndef HRESULT_VALUES_DEFINED
#define HRESULT_VALUES_DEFINED
enum
{
E_OUTOFMEMORY = 0x8007000E,
E_FAIL = 0x80004005,
E_ABORT = 0x80004004,
E_INVALIDARG = 0x80070057,
E_NOINTERFACE = 0x80004002,
E_NOTIMPL = 0x80004001,
E_UNEXPECTED = 0x8000FFFF
};
#endif
#define ERROR_SUCCESS 0L
enum
{
IDOK = 1,
IDCANCEL = 2,
IDABORT = 3,
IDRETRY = 4,
IDIGNORE = 5,
IDYES = 6,
IDNO = 7,
IDTRYAGAIN = 10,
IDCONTINUE = 11
};
#define ES_MULTILINE 0x0004L
#define ES_AUTOVSCROLL 0x0040L
#define ES_AUTOHSCROLL 0x0080L
#define ES_WANTRETURN 0x1000L
#define LB_ERR (-1)
#define LB_ADDSTRING 0x0180
#define LB_GETCOUNT 0x018B
#define LB_SETTOPINDEX 0x0197
#define MB_OK 0x00000000L
#define MB_OKCANCEL 0x00000001L
#define MB_ABORTRETRYIGNORE 0x00000002L
#define MB_YESNOCANCEL 0x00000003L
#define MB_YESNO 0x00000004L
#define MB_RETRYCANCEL 0x00000005L
#define MB_CANCELTRYCONTINUE 0x00000006L
#define MB_ICONQUESTION 0x00000020L
#define MB_ICONEXCLAMATION 0x00000030L
#define MB_ICONERROR 0x00000010L
#define MB_ICONWARNING 0x00000030L
#define MB_ICONINFORMATION 0x00000040L
#define MB_SETFOREGROUND 0x00010000L
#define MB_APPLMODAL 0x00000000L
#define MF_STRING 0x00000000L
#define MK_LBUTTON 0x0001
#define MK_RBUTTON 0x0002
#define MK_SHIFT 0x0004
#define MK_CONTROL 0x0008
#define MK_MBUTTON 0x0010
#define MK_ALT ( 0x20 )
#define SM_MOUSEPRESENT 0x00000000L
#define SM_CMOUSEBUTTONS 43
#define USER_TIMER_MINIMUM 0x0000000A
#define VK_TAB 0x09
#define VK_SHIFT 0x10
#define VK_MENU 0x12
#define VK_ESCAPE 0x1B
#define VK_SPACE 0x20
#define VK_DELETE 0x2E
#define VK_NUMPAD1 0x61
#define VK_NUMPAD2 0x62
#define VK_NUMPAD3 0x63
#define VK_NUMPAD4 0x64
#define VK_OEM_COMMA 0xBC // ',' any country
#define VK_OEM_PERIOD 0xBE // '.' any country
#define VK_OEM_3 0xC0 // '`~' for US
#define VK_OEM_4 0xDB // '[{' for US
#define VK_OEM_6 0xDD // ']}' for US
#define WAIT_TIMEOUT 258L // dderror
#define WM_MOVE 0x0003
#define WM_USER 0x0400
#define WHEEL_DELTA 120
#define WS_CHILD 0x40000000L
#define WS_VISIBLE 0x10000000L
#define CB_ERR (-1)
// function renaming
#define _finite std::isfinite
#define _snprintf snprintf
//#define _isnan isnan
#define stricmp strcasecmp
#define _stricmp strcasecmp
#define strnicmp strncasecmp
#define _strnicmp strncasecmp
#define wcsicmp wcscasecmp
#define wcsnicmp wcsncasecmp
//#define memcpy_s(dest,bytes,src,n) memcpy(dest,src,n)
#define _isnan ISNAN
#define _wtof(str) wcstod(str, 0)
#define TARGET_DEFAULT_ALIGN (0x8U)
#define _msize malloc_size
struct _OVERLAPPED;
typedef void (* LPOVERLAPPED_COMPLETION_ROUTINE)(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, struct _OVERLAPPED* lpOverlapped);
typedef struct _OVERLAPPED
{
void* pCaller;//this is orginally reserved for internal purpose, we store the Caller pointer here
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine; ////this is orginally ULONG_PTR InternalHigh and reserved for internal purpose
union
{
struct
{
DWORD Offset;
DWORD OffsetHigh;
};
PVOID Pointer;
};
DWORD dwNumberOfBytesTransfered; //additional member temporary speciying the number of bytes to be read
/*HANDLE*/ void* hEvent;
} OVERLAPPED, * LPOVERLAPPED;
typedef struct _SECURITY_ATTRIBUTES
{
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInheritHandle;
} SECURITY_ATTRIBUTES, * PSECURITY_ATTRIBUTES, * LPSECURITY_ATTRIBUTES;
#ifdef __cplusplus
#define __min(_S, _T) min(_S, _T)
#define __max(_S, _T) max(_S, _T)
typedef enum
{
INVALID_HANDLE_VALUE = -1l
}INVALID_HANDLE_VALUE_ENUM;
//for compatibility reason we got to create a class which actually contains an int rather than a void* and make sure it does not get mistreated
template <class T, T U>
//U is default type for invalid handle value, T the encapsulated handle type to be used instead of void* (as under windows and never linux)
class CHandle
{
public:
typedef T HandleType;
typedef void* PointerType; //for compatibility reason to encapsulate a void* as an int
static const HandleType sciInvalidHandleValue = U;
CHandle(const CHandle<T, U>& cHandle)
: m_Value(cHandle.m_Value){}
CHandle(const HandleType cHandle = U)
: m_Value(cHandle){}
CHandle(const PointerType cpHandle)
: m_Value(reinterpret_cast<HandleType>(cpHandle)){}
CHandle(INVALID_HANDLE_VALUE_ENUM)
: m_Value(U){} //to be able to use a common value for all InvalidHandle - types
#if defined(PLATFORM_64BIT)
//treat __null tyope also as invalid handle type
CHandle(long)
: m_Value(U){} //to be able to use a common value for all InvalidHandle - types
#endif
operator HandleType(){
return m_Value;
}
bool operator!() const{return m_Value == sciInvalidHandleValue; }
const CHandle& operator =(const CHandle& crHandle){m_Value = crHandle.m_Value; return *this; }
const CHandle& operator =(const PointerType cpHandle){m_Value = (HandleType) reinterpret_cast<UINT_PTR>(cpHandle); return *this; }
const bool operator ==(const CHandle& crHandle) const{return m_Value == crHandle.m_Value; }
const bool operator ==(const HandleType cHandle) const{return m_Value == cHandle; }
const bool operator ==(const PointerType cpHandle) const{return m_Value == reinterpret_cast<HandleType>(cpHandle); }
const bool operator !=(const HandleType cHandle) const{return m_Value != cHandle; }
const bool operator !=(const CHandle& crHandle) const{return m_Value != crHandle.m_Value; }
const bool operator !=(const PointerType cpHandle) const{return m_Value != reinterpret_cast<HandleType>(cpHandle); }
const bool operator < (const CHandle& crHandle) const{return m_Value < crHandle.m_Value; }
HandleType Handle() const{return m_Value; }
private:
HandleType m_Value; //the actual value, remember that file descriptors are ints under linux
typedef void ReferenceType;//for compatibility reason to encapsulate a void* as an int
//forbid these function which would actually not work on an int
PointerType operator->();
PointerType operator->() const;
ReferenceType operator*();
ReferenceType operator*() const;
operator PointerType();
};
typedef CHandle<int, (int) - 1l> HANDLE;
typedef HANDLE EVENT_HANDLE;
typedef HANDLE THREAD_HANDLE;
typedef HANDLE HKEY;
typedef HANDLE HDC;
typedef HANDLE HBITMAP;
typedef HANDLE HMENU;
#endif //__cplusplus
inline char* _fullpath(char* absPath, const char* relPath, size_t maxLength)
{
char path[PATH_MAX];
if (realpath(relPath, path) == NULL)
{
return NULL;
}
const size_t len = std::min(strlen(path), maxLength - 1);
memcpy(absPath, path, len);
absPath[len] = 0;
return absPath;
}
typedef union _LARGE_INTEGER
{
struct
{
DWORD LowPart;
LONG HighPart;
};
struct
{
DWORD LowPart;
LONG HighPart;
} u;
long long QuadPart;
} LARGE_INTEGER;
extern bool QueryPerformanceCounter(LARGE_INTEGER*);
extern bool QueryPerformanceFrequency(LARGE_INTEGER* frequency);
inline int64 CryGetTicks()
{
LARGE_INTEGER counter;
QueryPerformanceCounter(&counter);
return counter.QuadPart;
}
inline int64 CryGetTicksPerSec()
{
LARGE_INTEGER li;
QueryPerformanceFrequency(&li);
return li.QuadPart;
}
/*
inline uint32 GetTickCount()
{
LARGE_INTEGER count, freq;
QueryPerformanceCounter(&count);
QueryPerformanceFrequency(&freq);
return uint32(count.QuadPart * 1000 / freq.QuadPart);
}
*/
#ifdef _RELEASE
#define __debugbreak()
#else
#define __debugbreak() ::raise(SIGTRAP)
#endif
#define __assume(x)
#define _flushall sync
inline int closesocket(int s)
{
return ::close(s);
}
inline int WSAGetLastError()
{
return errno;
}
//we take the definition of the pthread_t type directly from the pthread file
#define THREADID_NULL 0
template <typename T, size_t N>
char (*RtlpNumberOf( T (&)[N] ))[N];
#define RTL_NUMBER_OF_V2(A) (sizeof(*RtlpNumberOf(A)))
#define ARRAYSIZE(A) RTL_NUMBER_OF_V2(A)
#undef SUCCEEDED
#define SUCCEEDED(x) ((x) >= 0)
#undef FAILED
#define FAILED(x) (!(SUCCEEDED(x)))
#endif // CRYINCLUDE_CRYCOMMON_APPLESPECIFIC_H
+197
View File
@@ -0,0 +1,197 @@
/*
* 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.
*
*/
// Description : Contains portable definition of structs and enums to match
// those in DXGIFormat.h in the DirectX SDK
#pragma once
#include <AzCore/PlatformDef.h>
#if defined(AZ_PLATFORM_WINDOWS) && !defined(OPENGL)
#include <dxgiformat.h>
// For non-windows platforms need to define the formats so that the ImageExtension
// class used by the editor can have access to these
#elif AZ_TRAIT_OS_PLATFORM_APPLE || defined(OPENGL) || defined(AZ_PLATFORM_LINUX) || defined(AZ_PLATFORM_ANDROID)
#define DXGI_FORMAT_DEFINED 1
typedef enum DXGI_FORMAT
{
DXGI_FORMAT_UNKNOWN = 0,
DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
DXGI_FORMAT_R32G32B32A32_UINT = 3,
DXGI_FORMAT_R32G32B32A32_SINT = 4,
DXGI_FORMAT_R32G32B32_TYPELESS = 5,
DXGI_FORMAT_R32G32B32_FLOAT = 6,
DXGI_FORMAT_R32G32B32_UINT = 7,
DXGI_FORMAT_R32G32B32_SINT = 8,
DXGI_FORMAT_R16G16B16A16_TYPELESS = 9,
DXGI_FORMAT_R16G16B16A16_FLOAT = 10,
DXGI_FORMAT_R16G16B16A16_UNORM = 11,
DXGI_FORMAT_R16G16B16A16_UINT = 12,
DXGI_FORMAT_R16G16B16A16_SNORM = 13,
DXGI_FORMAT_R16G16B16A16_SINT = 14,
DXGI_FORMAT_R32G32_TYPELESS = 15,
DXGI_FORMAT_R32G32_FLOAT = 16,
DXGI_FORMAT_R32G32_UINT = 17,
DXGI_FORMAT_R32G32_SINT = 18,
DXGI_FORMAT_R32G8X24_TYPELESS = 19,
DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20,
DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
DXGI_FORMAT_R10G10B10A2_UNORM = 24,
DXGI_FORMAT_R10G10B10A2_UINT = 25,
DXGI_FORMAT_R11G11B10_FLOAT = 26,
DXGI_FORMAT_R8G8B8A8_TYPELESS = 27,
DXGI_FORMAT_R8G8B8A8_UNORM = 28,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
DXGI_FORMAT_R8G8B8A8_UINT = 30,
DXGI_FORMAT_R8G8B8A8_SNORM = 31,
DXGI_FORMAT_R8G8B8A8_SINT = 32,
DXGI_FORMAT_R16G16_TYPELESS = 33,
DXGI_FORMAT_R16G16_FLOAT = 34,
DXGI_FORMAT_R16G16_UNORM = 35,
DXGI_FORMAT_R16G16_UINT = 36,
DXGI_FORMAT_R16G16_SNORM = 37,
DXGI_FORMAT_R16G16_SINT = 38,
DXGI_FORMAT_R32_TYPELESS = 39,
DXGI_FORMAT_D32_FLOAT = 40,
DXGI_FORMAT_R32_FLOAT = 41,
DXGI_FORMAT_R32_UINT = 42,
DXGI_FORMAT_R32_SINT = 43,
DXGI_FORMAT_R24G8_TYPELESS = 44,
DXGI_FORMAT_D24_UNORM_S8_UINT = 45,
DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46,
DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47,
DXGI_FORMAT_R8G8_TYPELESS = 48,
DXGI_FORMAT_R8G8_UNORM = 49,
DXGI_FORMAT_R8G8_UINT = 50,
DXGI_FORMAT_R8G8_SNORM = 51,
DXGI_FORMAT_R8G8_SINT = 52,
DXGI_FORMAT_R16_TYPELESS = 53,
DXGI_FORMAT_R16_FLOAT = 54,
DXGI_FORMAT_D16_UNORM = 55,
DXGI_FORMAT_R16_UNORM = 56,
DXGI_FORMAT_R16_UINT = 57,
DXGI_FORMAT_R16_SNORM = 58,
DXGI_FORMAT_R16_SINT = 59,
DXGI_FORMAT_R8_TYPELESS = 60,
DXGI_FORMAT_R8_UNORM = 61,
DXGI_FORMAT_R8_UINT = 62,
DXGI_FORMAT_R8_SNORM = 63,
DXGI_FORMAT_R8_SINT = 64,
DXGI_FORMAT_A8_UNORM = 65,
DXGI_FORMAT_R1_UNORM = 66,
DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
DXGI_FORMAT_BC1_TYPELESS = 70,
DXGI_FORMAT_BC1_UNORM = 71,
DXGI_FORMAT_BC1_UNORM_SRGB = 72,
DXGI_FORMAT_BC2_TYPELESS = 73,
DXGI_FORMAT_BC2_UNORM = 74,
DXGI_FORMAT_BC2_UNORM_SRGB = 75,
DXGI_FORMAT_BC3_TYPELESS = 76,
DXGI_FORMAT_BC3_UNORM = 77,
DXGI_FORMAT_BC3_UNORM_SRGB = 78,
DXGI_FORMAT_BC4_TYPELESS = 79,
DXGI_FORMAT_BC4_UNORM = 80,
DXGI_FORMAT_BC4_SNORM = 81,
DXGI_FORMAT_BC5_TYPELESS = 82,
DXGI_FORMAT_BC5_UNORM = 83,
DXGI_FORMAT_BC5_SNORM = 84,
DXGI_FORMAT_B5G6R5_UNORM = 85,
DXGI_FORMAT_B5G5R5A1_UNORM = 86,
DXGI_FORMAT_B8G8R8A8_UNORM = 87,
DXGI_FORMAT_B8G8R8X8_UNORM = 88,
DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89,
DXGI_FORMAT_B8G8R8A8_TYPELESS = 90,
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91,
DXGI_FORMAT_B8G8R8X8_TYPELESS = 92,
DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93,
DXGI_FORMAT_BC6H_TYPELESS = 94,
DXGI_FORMAT_BC6H_UF16 = 95,
DXGI_FORMAT_BC6H_SF16 = 96,
DXGI_FORMAT_BC7_TYPELESS = 97,
DXGI_FORMAT_BC7_UNORM = 98,
DXGI_FORMAT_BC7_UNORM_SRGB = 99,
DXGI_FORMAT_EAC_R11_TYPELESS = 200,
DXGI_FORMAT_EAC_R11_UNORM = 201,
DXGI_FORMAT_EAC_R11_SNORM = 202,
DXGI_FORMAT_EAC_RG11_TYPELESS = 203,
DXGI_FORMAT_EAC_RG11_UNORM = 204,
DXGI_FORMAT_EAC_RG11_SNORM = 205,
DXGI_FORMAT_ETC2_TYPELESS = 206,
DXGI_FORMAT_ETC2_UNORM = 207,
DXGI_FORMAT_ETC2_UNORM_SRGB = 208,
DXGI_FORMAT_ETC2A_TYPELESS = 209,
DXGI_FORMAT_ETC2A_UNORM = 210,
DXGI_FORMAT_ETC2A_UNORM_SRGB = 211,
DXGI_FORMAT_PVRTC2_TYPELESS = 250,
DXGI_FORMAT_PVRTC2_UNORM = 251,
DXGI_FORMAT_PVRTC2_UNORM_SRGB = 252,
DXGI_FORMAT_PVRTC4_TYPELESS = 253,
DXGI_FORMAT_PVRTC4_UNORM = 254,
DXGI_FORMAT_PVRTC4_UNORM_SRGB = 255,
DXGI_FORMAT_ASTC_4x4_TYPELESS = 260,
DXGI_FORMAT_ASTC_4x4_UNORM = 261,
DXGI_FORMAT_ASTC_4x4_UNORM_SRGB = 262,
DXGI_FORMAT_ASTC_5x4_TYPELESS = 263,
DXGI_FORMAT_ASTC_5x4_UNORM = 264,
DXGI_FORMAT_ASTC_5x4_UNORM_SRGB = 265,
DXGI_FORMAT_ASTC_5x5_TYPELESS = 266,
DXGI_FORMAT_ASTC_5x5_UNORM = 267,
DXGI_FORMAT_ASTC_5x5_UNORM_SRGB = 268,
DXGI_FORMAT_ASTC_6x5_TYPELESS = 269,
DXGI_FORMAT_ASTC_6x5_UNORM = 270,
DXGI_FORMAT_ASTC_6x5_UNORM_SRGB = 271,
DXGI_FORMAT_ASTC_6x6_TYPELESS = 272,
DXGI_FORMAT_ASTC_6x6_UNORM = 273,
DXGI_FORMAT_ASTC_6x6_UNORM_SRGB = 274,
DXGI_FORMAT_ASTC_8x5_TYPELESS = 275,
DXGI_FORMAT_ASTC_8x5_UNORM = 276,
DXGI_FORMAT_ASTC_8x5_UNORM_SRGB = 277,
DXGI_FORMAT_ASTC_8x6_TYPELESS = 278,
DXGI_FORMAT_ASTC_8x6_UNORM = 279,
DXGI_FORMAT_ASTC_8x6_UNORM_SRGB = 280,
DXGI_FORMAT_ASTC_8x8_TYPELESS = 281,
DXGI_FORMAT_ASTC_8x8_UNORM = 282,
DXGI_FORMAT_ASTC_8x8_UNORM_SRGB = 283,
DXGI_FORMAT_ASTC_10x5_TYPELESS = 284,
DXGI_FORMAT_ASTC_10x5_UNORM = 285,
DXGI_FORMAT_ASTC_10x5_UNORM_SRGB = 286,
DXGI_FORMAT_ASTC_10x6_TYPELESS = 287,
DXGI_FORMAT_ASTC_10x6_UNORM = 288,
DXGI_FORMAT_ASTC_10x6_UNORM_SRGB = 289,
DXGI_FORMAT_ASTC_10x8_TYPELESS = 290,
DXGI_FORMAT_ASTC_10x8_UNORM = 291,
DXGI_FORMAT_ASTC_10x8_UNORM_SRGB = 292,
DXGI_FORMAT_ASTC_10x10_TYPELESS = 293,
DXGI_FORMAT_ASTC_10x10_UNORM = 294,
DXGI_FORMAT_ASTC_10x10_UNORM_SRGB = 295,
DXGI_FORMAT_ASTC_12x10_TYPELESS = 296,
DXGI_FORMAT_ASTC_12x10_UNORM = 297,
DXGI_FORMAT_ASTC_12x10_UNORM_SRGB = 298,
DXGI_FORMAT_ASTC_12x12_TYPELESS = 299,
DXGI_FORMAT_ASTC_12x12_UNORM = 300,
DXGI_FORMAT_ASTC_12x12_UNORM_SRGB = 301,
DXGI_FORMAT_FORCE_UINT = 0xffffffff
} DXGI_FORMAT;
#endif
+85
View File
@@ -0,0 +1,85 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYCOMMON_BASETYPES_H
#define CRYINCLUDE_CRYCOMMON_BASETYPES_H
#pragma once
#include "CompileTimeAssert.h"
COMPILE_TIME_ASSERT(sizeof(char) == 1);
COMPILE_TIME_ASSERT(sizeof(float) == 4);
COMPILE_TIME_ASSERT(sizeof(int) >= 4);
typedef unsigned char uchar;
typedef signed char schar;
typedef unsigned short ushort;
typedef signed short sshort;
#if !defined(CLANG_FIX_UINT_REDEF)
typedef unsigned int uint;
#endif
typedef signed int sint;
typedef unsigned long ulong;
typedef signed long slong;
typedef unsigned long long ulonglong;
typedef signed long long slonglong;
COMPILE_TIME_ASSERT(sizeof(uchar) == sizeof(schar));
COMPILE_TIME_ASSERT(sizeof(ushort) == sizeof(sshort));
COMPILE_TIME_ASSERT(sizeof(uint) == sizeof(sint));
COMPILE_TIME_ASSERT(sizeof(ulong) == sizeof(slong));
COMPILE_TIME_ASSERT(sizeof(ulonglong) == sizeof(slonglong));
COMPILE_TIME_ASSERT(sizeof(uchar) <= sizeof(ushort));
COMPILE_TIME_ASSERT(sizeof(ushort) <= sizeof(uint));
COMPILE_TIME_ASSERT(sizeof(uint) <= sizeof(ulong));
COMPILE_TIME_ASSERT(sizeof(ulong) <= sizeof(ulonglong));
typedef schar int8;
typedef schar sint8;
typedef uchar uint8;
COMPILE_TIME_ASSERT(sizeof(uint8) == 1);
COMPILE_TIME_ASSERT(sizeof(sint8) == 1);
typedef sshort int16;
typedef sshort sint16;
typedef ushort uint16;
COMPILE_TIME_ASSERT(sizeof(uint16) == 2);
COMPILE_TIME_ASSERT(sizeof(sint16) == 2);
typedef sint int32;
typedef sint sint32;
typedef uint uint32;
COMPILE_TIME_ASSERT(sizeof(uint32) == 4);
COMPILE_TIME_ASSERT(sizeof(sint32) == 4);
typedef slonglong int64;
typedef slonglong sint64;
typedef ulonglong uint64;
COMPILE_TIME_ASSERT(sizeof(uint64) == 8);
COMPILE_TIME_ASSERT(sizeof(sint64) == 8);
typedef float f32;
typedef double f64;
COMPILE_TIME_ASSERT(sizeof(f32) == 4);
COMPILE_TIME_ASSERT(sizeof(f64) == 8);
#endif // CRYINCLUDE_CRYCOMMON_BASETYPES_H
+321
View File
@@ -0,0 +1,321 @@
/*
* 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.
#ifndef __BEZIER_H__
#define __BEZIER_H__
#include <AnimTime.h>
#include <Serialization/IArchive.h>
#include <Serialization/Math.h>
struct SBezierControlPoint
{
SBezierControlPoint()
: m_value(0.0f)
, m_inTangent(ZERO)
, m_outTangent(ZERO)
, m_inTangentType(eTangentType_Auto)
, m_outTangentType(eTangentType_Auto)
, m_bBreakTangents(false)
{
}
enum ETangentType
{
eTangentType_Custom,
eTangentType_Auto,
eTangentType_Zero,
eTangentType_Step,
eTangentType_Linear,
};
void Serialize(Serialization::IArchive& ar)
{
ar(m_value, "value", "Value");
if (ar.IsOutput())
{
bool breakTangents = m_bBreakTangents;
ar(breakTangents, "breakTangents", "Break Tangents");
}
else
{
bool breakTangents = false;
ar(breakTangents, "breakTangents", "Break Tangents");
m_bBreakTangents = breakTangents;
}
if (ar.IsOutput())
{
ETangentType inTangentType = m_inTangentType;
ar(inTangentType, "inTangentType", "Incoming tangent type");
}
else
{
ETangentType inTangentType = eTangentType_Auto;
ar(inTangentType, "inTangentType", "Incoming tangent type");
m_inTangentType = inTangentType;
}
ar(m_inTangent, "inTangent", (m_inTangentType == eTangentType_Custom) ? "Incoming Tangent" : NULL);
if (ar.IsOutput())
{
ETangentType outTangentType = m_outTangentType;
ar(outTangentType, "outTangentType", "Outgoing tangent type");
}
else
{
ETangentType outTangentType = eTangentType_Auto;
ar(outTangentType, "outTangentType", "Outgoing tangent type");
m_outTangentType = outTangentType;
}
ar(m_outTangent, "outTangent", (m_outTangentType == eTangentType_Custom) ? "Outgoing Tangent" : NULL);
}
float m_value;
// For 1D Bezier only the Y component is used
Vec2 m_inTangent;
Vec2 m_outTangent;
ETangentType m_inTangentType : 4;
ETangentType m_outTangentType : 4;
bool m_bBreakTangents : 1;
};
struct SBezierKey
{
SBezierKey()
: m_time(0) {}
void Serialize(Serialization::IArchive& ar)
{
ar(m_time, "time", "Time");
ar(m_controlPoint, "controlPoint", "Control Point");
}
SAnimTime m_time;
SBezierControlPoint m_controlPoint;
};
namespace Bezier
{
inline float Evaluate(float t, float p0, float p1, float p2, float p3)
{
const float a = 1 - t;
const float aSq = a * a;
const float tSq = t * t;
return (aSq * a * p0) + (3.0f * aSq * t * p1) + (3.0f * a * tSq * p2) + (tSq * t * p3);
}
inline float EvaluateDeriv(float t, float p0, float p1, float p2, float p3)
{
const float a = 1 - t;
const float ta = t * a;
const float aSq = a * a;
const float tSq = t * t;
return 3.0f * ((-p2 * tSq) + (p3 * tSq) - (p0 * aSq) + (p1 * aSq) + 2.0f * ((-p1 * ta) + (p2 * ta)));
}
inline float EvaluateX(const float t, const float duration, const SBezierControlPoint& start, const SBezierControlPoint& end)
{
const float p0 = 0.0f;
const float p1 = p0 + start.m_outTangent.x;
const float p3 = duration;
const float p2 = p3 + end.m_inTangent.x;
return Evaluate(t, p0, p1, p2, p3);
}
inline float EvaluateY(const float t, const SBezierControlPoint& start, const SBezierControlPoint& end)
{
const float p0 = start.m_value;
const float p1 = p0 + start.m_outTangent.y;
const float p3 = end.m_value;
const float p2 = p3 + end.m_inTangent.y;
return Evaluate(t, p0, p1, p2, p3);
}
// Duration = (time at end key) - (time at start key)
inline float EvaluateDerivX(const float t, const float duration, const SBezierControlPoint& start, const SBezierControlPoint& end)
{
const float p0 = 0.0f;
const float p1 = p0 + start.m_outTangent.x;
const float p3 = duration;
const float p2 = p3 + end.m_inTangent.x;
return EvaluateDeriv(t, p0, p1, p2, p3);
}
inline float EvaluateDerivY(const float t, const SBezierControlPoint& start, const SBezierControlPoint& end)
{
const float p0 = start.m_value;
const float p1 = p0 + start.m_outTangent.y;
const float p3 = end.m_value;
const float p2 = p3 + end.m_inTangent.y;
return EvaluateDeriv(t, p0, p1, p2, p3);
}
// Find interpolation factor where 2D bezier curve has the given x value. Works only for curves where x is monotonically increasing.
// The passed x must be in range [0, duration]. Uses the Newton-Raphson root finding method. Usually takes 2 or 3 iterations.
//
// Note: This is for "1D" 2D bezier curves as used in TrackView. The curves are restricted by the curve editor to be monotonically increasing.
//
inline float InterpolationFactorFromX(const float x, const float duration, const SBezierControlPoint& start, const SBezierControlPoint& end)
{
float t = (x / duration);
const float epsilon = 0.00001f;
const uint maxSteps = 10;
for (uint i = 0; i < maxSteps; ++i)
{
const float currentX = EvaluateX(t, duration, start, end) - x;
if (fabs(currentX) <= epsilon)
{
break;
}
const float currentXDeriv = EvaluateDerivX(t, duration, start, end);
t -= currentX / currentXDeriv;
}
return t;
}
inline SBezierControlPoint CalculateInTangent(
float time, const SBezierControlPoint& point,
float leftTime, const SBezierControlPoint* pLeftPoint,
float rightTime, const SBezierControlPoint* pRightPoint)
{
SBezierControlPoint newPoint = point;
// In tangent X can never be positive
newPoint.m_inTangent.x = std::min(point.m_inTangent.x, 0.0f);
if (pLeftPoint)
{
switch (point.m_inTangentType)
{
case SBezierControlPoint::eTangentType_Custom:
{
// Need to clamp tangent if it is reaching over last point
const float deltaTime = time - leftTime;
if (deltaTime < -newPoint.m_inTangent.x)
{
if (newPoint.m_inTangent.x == 0)
{
newPoint.m_inTangent = Vec2(ZERO);
}
else
{
float scaleFactor = deltaTime / -newPoint.m_inTangent.x;
newPoint.m_inTangent.x = -deltaTime;
newPoint.m_inTangent.y *= scaleFactor;
}
}
}
break;
case SBezierControlPoint::eTangentType_Zero:
// Fall through. Zero for y is same as Auto, x is set to 0.0f
case SBezierControlPoint::eTangentType_Auto:
{
const SBezierControlPoint& rightPoint = pRightPoint ? *pRightPoint : point;
const float deltaTime = (pRightPoint ? rightTime : time) - leftTime;
if (deltaTime > 0.0f)
{
const float ratio = (time - leftTime) / deltaTime;
const float deltaValue = rightPoint.m_value - pLeftPoint->m_value;
const bool bIsZeroTangent = (point.m_inTangentType == SBezierControlPoint::eTangentType_Zero);
newPoint.m_inTangent = Vec2(-(deltaTime * ratio) / 3.0f, bIsZeroTangent ? 0.0f : -(deltaValue * ratio) / 3.0f);
}
else
{
newPoint.m_inTangent = Vec2(ZERO);
}
}
break;
case SBezierControlPoint::eTangentType_Linear:
newPoint.m_inTangent = Vec2((leftTime - time) / 3.0f,
(pLeftPoint->m_value - point.m_value) / 3.0f);
break;
}
}
return newPoint;
}
inline SBezierControlPoint CalculateOutTangent(
float time, const SBezierControlPoint& point,
float leftTime, const SBezierControlPoint* pLeftPoint,
float rightTime, const SBezierControlPoint* pRightPoint)
{
SBezierControlPoint newPoint = point;
// Out tangent X can never be negative
newPoint.m_outTangent.x = std::max(point.m_outTangent.x, 0.0f);
if (pRightPoint)
{
switch (point.m_outTangentType)
{
case SBezierControlPoint::eTangentType_Custom:
{
// Need to clamp tangent if it is reaching over next point
const float deltaTime = rightTime - time;
if (deltaTime < newPoint.m_outTangent.x)
{
if (newPoint.m_outTangent.x == 0)
{
newPoint.m_outTangent = Vec2(ZERO);
}
else
{
float scaleFactor = deltaTime / newPoint.m_outTangent.x;
newPoint.m_outTangent.x = deltaTime;
newPoint.m_outTangent.y *= scaleFactor;
}
}
}
break;
case SBezierControlPoint::eTangentType_Zero:
// Fall through. Zero for y is same as Auto, x is set to 0.0f
case SBezierControlPoint::eTangentType_Auto:
{
const SBezierControlPoint& leftPoint = pLeftPoint ? *pLeftPoint : point;
const float deltaTime = rightTime - (pLeftPoint ? leftTime : time);
if (deltaTime > 0.0f)
{
const float ratio = (rightTime - time) / deltaTime;
const float deltaValue = pRightPoint->m_value - leftPoint.m_value;
const bool bIsZeroTangent = (point.m_outTangentType == SBezierControlPoint::eTangentType_Zero);
newPoint.m_outTangent = Vec2((deltaTime * ratio) / 3.0f, bIsZeroTangent ? 0.0f : (deltaValue * ratio) / 3.0f);
}
else
{
newPoint.m_outTangent = Vec2(ZERO);
}
}
break;
case SBezierControlPoint::eTangentType_Linear:
newPoint.m_outTangent = Vec2((rightTime - time) / 3.0f,
(pRightPoint->m_value - point.m_value) / 3.0f);
break;
}
}
return newPoint;
}
}
#endif
+598
View File
@@ -0,0 +1,598 @@
/*
* 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 : various integer bit fiddling hacks
#pragma once
#include "CompileTimeAssert.h"
#include <AzCore/Casting/numeric_cast.h>
// Section dictionary
#if defined(AZ_RESTRICTED_PLATFORM)
#define BITFIDDLING_H_SECTION_TRAITS 1
#define BITFIDDLING_H_SECTION_INTEGERLOG2 2
#endif
// Traits
#if defined(AZ_RESTRICTED_PLATFORM)
#define AZ_RESTRICTED_SECTION BITFIDDLING_H_SECTION_TRAITS
#include AZ_RESTRICTED_FILE(BitFiddling_h)
#elif defined(LINUX) || defined(APPLE)
#define BITFIDDLING_H_TRAIT_HAS_COUNT_LEADING_ZEROS 1
#endif
#if BITFIDDLING_H_TRAIT_HAS_COUNT_LEADING_ZEROS
#define countLeadingZeros32(x) __builtin_clz(x)
#else // Windows implementation
ILINE uint32 countLeadingZeros32(uint32 x)
{
DWORD result = 32 ^ 31; // assumes result is unmodified if _BitScanReverse returns 0
_BitScanReverse(&result, x);
PREFAST_SUPPRESS_WARNING(6102);
result ^= 31; // needed because the index is from LSB (whereas all other implementations are from MSB)
return result;
}
#endif
inline uint32 circularShift(uint32 nbits, uint32 i)
{
return (i << nbits) | (i >> (32 - nbits));
}
template <typename T>
inline size_t countTrailingZeroes(T v)
{
size_t n = 0;
v = ~v & (v - 1);
while (v)
{
++n;
v >>= 1;
}
return n;
}
// this function returns the integer logarithm of various numbers without branching
#define IL2VAL(mask, shift) \
c |= ((x & mask) != 0) * shift; \
x >>= ((x & mask) != 0) * shift
template <typename TInteger>
inline bool IsPowerOfTwo(TInteger x)
{
return (x & (x - 1)) == 0;
}
// compile time version of IsPowerOfTwo, useful for STATIC_CHECK
template <int nValue>
struct IsPowerOfTwoCompileTime
{
enum
{
IsPowerOfTwo = ((nValue & (nValue - 1)) == 0)
};
};
inline uint32 NextPower2(uint32 n)
{
n--;
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 8;
n |= n >> 16;
n++;
return n;
}
inline uint8 IntegerLog2(uint8 x)
{
uint8 c = 0;
IL2VAL(0xf0, 4);
IL2VAL(0xc, 2);
IL2VAL(0x2, 1);
return c;
}
inline uint16 IntegerLog2(uint16 x)
{
uint16 c = 0;
IL2VAL(0xff00, 8);
IL2VAL(0xf0, 4);
IL2VAL(0xc, 2);
IL2VAL(0x2, 1);
return c;
}
inline uint32 IntegerLog2(uint32 x)
{
return 31 - countLeadingZeros32(x);
}
inline uint64 IntegerLog2(uint64 x)
{
uint64 c = 0;
IL2VAL(0xffffffff00000000ull, 32);
IL2VAL(0xffff0000u, 16);
IL2VAL(0xff00, 8);
IL2VAL(0xf0, 4);
IL2VAL(0xc, 2);
IL2VAL(0x2, 1);
return c;
}
#if defined(APPLE) || defined(LINUX)
inline unsigned long int IntegerLog2(unsigned long int x)
{
#if defined(PLATFORM_64BIT)
return IntegerLog2((uint64)x);
#else
return IntegerLog2((uint32)x);
#endif
}
#endif
#undef IL2VAL
#if defined(AZ_RESTRICTED_PLATFORM)
#define AZ_RESTRICTED_SECTION BITFIDDLING_H_SECTION_INTEGERLOG2
#include AZ_RESTRICTED_FILE(BitFiddling_h)
#endif
template <typename TInteger>
inline TInteger IntegerLog2_RoundUp(TInteger x)
{
return 1 + IntegerLog2(x - 1);
}
static ILINE uint8 BitIndex(uint8 v)
{
uint32 vv = v;
return aznumeric_caster(31 - countLeadingZeros32(vv));
}
static ILINE uint8 BitIndex(uint16 v)
{
uint32 vv = v;
return aznumeric_caster(31 - countLeadingZeros32(vv));
}
static ILINE uint8 BitIndex(uint32 v)
{
return aznumeric_caster(31 - countLeadingZeros32(v));
}
static ILINE uint8 CountBits(uint8 v)
{
uint8 c = v;
c = ((c >> 1) & 0x55) + (c & 0x55);
c = ((c >> 2) & 0x33) + (c & 0x33);
c = ((c >> 4) & 0x0f) + (c & 0x0f);
return c;
}
static ILINE uint8 CountBits(uint16 v)
{
return CountBits((uint8)(v & 0xff)) +
CountBits((uint8)((v >> 8) & 0xff));
}
static ILINE uint8 CountBits(uint32 v)
{
return CountBits((uint8)(v & 0xff)) +
CountBits((uint8)((v >> 8) & 0xff)) +
CountBits((uint8)((v >> 16) & 0xff)) +
CountBits((uint8)((v >> 24) & 0xff));
}
// Branchless version of return v < 0 ? alt : v;
ILINE int32 Isel32(int32 v, int32 alt)
{
return ((static_cast<int32>(v) >> 31) & alt) | ((static_cast<int32>(~v) >> 31) & v);
}
template <uint32 ILOG>
struct CompileTimeIntegerLog2
{
static const uint32 result = 1 + CompileTimeIntegerLog2<(ILOG >> 1)>::result;
};
template <>
struct CompileTimeIntegerLog2<1>
{
static const uint32 result = 0;
};
template <>
struct CompileTimeIntegerLog2<0>; // keep it undefined, we cannot represent "minus infinity" result
COMPILE_TIME_ASSERT(CompileTimeIntegerLog2<1>::result == 0);
COMPILE_TIME_ASSERT(CompileTimeIntegerLog2<2>::result == 1);
COMPILE_TIME_ASSERT(CompileTimeIntegerLog2<3>::result == 1);
COMPILE_TIME_ASSERT(CompileTimeIntegerLog2<4>::result == 2);
COMPILE_TIME_ASSERT(CompileTimeIntegerLog2<5>::result == 2);
COMPILE_TIME_ASSERT(CompileTimeIntegerLog2<255>::result == 7);
COMPILE_TIME_ASSERT(CompileTimeIntegerLog2<256>::result == 8);
COMPILE_TIME_ASSERT(CompileTimeIntegerLog2<257>::result == 8);
template <uint32 ILOG>
struct CompileTimeIntegerLog2_RoundUp
{
static const uint32 result = CompileTimeIntegerLog2<ILOG>::result + ((ILOG & (ILOG - 1)) != 0);
};
template <>
struct CompileTimeIntegerLog2_RoundUp<0>; // we can return 0, but let's keep it undefined (same as CompileTimeIntegerLog2<0>)
COMPILE_TIME_ASSERT(CompileTimeIntegerLog2_RoundUp<1>::result == 0);
COMPILE_TIME_ASSERT(CompileTimeIntegerLog2_RoundUp<2>::result == 1);
COMPILE_TIME_ASSERT(CompileTimeIntegerLog2_RoundUp<3>::result == 2);
COMPILE_TIME_ASSERT(CompileTimeIntegerLog2_RoundUp<4>::result == 2);
COMPILE_TIME_ASSERT(CompileTimeIntegerLog2_RoundUp<5>::result == 3);
COMPILE_TIME_ASSERT(CompileTimeIntegerLog2_RoundUp<255>::result == 8);
COMPILE_TIME_ASSERT(CompileTimeIntegerLog2_RoundUp<256>::result == 8);
COMPILE_TIME_ASSERT(CompileTimeIntegerLog2_RoundUp<257>::result == 9);
// Character-to-bitfield mapping
inline uint32 AlphaBit(char c)
{
return c >= 'a' && c <= 'z' ? 1 << (c - 'z' + 31) : 0;
}
inline uint64 AlphaBit64(char c)
{
return (c >= 'a' && c <= 'z' ? 1U << (c - 'z' + 31) : 0) |
(c >= 'A' && c <= 'Z' ? 1LL << (c - 'Z' + 63) : 0);
}
inline uint32 AlphaBits(uint32 wc)
{
// Handle wide multi-char constants, can be evaluated at compile-time.
return AlphaBit((char)wc)
| AlphaBit((char)(wc >> 8))
| AlphaBit((char)(wc >> 16))
| AlphaBit((char)(wc >> 24));
}
inline uint32 AlphaBits(const char* s)
{
// Handle string of any length.
uint32 n = 0;
while (*s)
{
n |= AlphaBit(*s++);
}
return n;
}
inline uint64 AlphaBits64(const char* s)
{
// Handle string of any length.
uint64 n = 0;
while (*s)
{
n |= AlphaBit64(*s++);
}
return n;
}
// s should point to a buffer at least 65 chars long
inline void BitsAlpha64(uint64 n, char* s)
{
for (int i = 0; n != 0; n >>= 1, i++)
{
if (n & 1)
{
*s++ = i < 32 ? static_cast<char>(i + 'z' - 31) : static_cast<char>(i + 'Z' - 63);
}
}
*s++ = '\0';
}
// if hardware doesn't support 3Dc we can convert to DXT5 (different channels are used)
// with almost the same quality but the same memory requirements
inline void ConvertBlock3DcToDXT5(uint8 pDstBlock[16], const uint8 pSrcBlock[16])
{
assert(pDstBlock != pSrcBlock); // does not work in place
// 4x4 block requires 8 bytes in DXT5 or 3DC
// DXT5: 8 bit alpha0, 8 bit alpha1, 16*3 bit alpha lerp
// 16bit col0, 16 bit col1 (R5G6B5 low byte then high byte), 16*2 bit color lerp
// 3DC: 8 bit x0, 8 bit x1, 16*3 bit x lerp
// 8 bit y0, 8 bit y1, 16*3 bit y lerp
for (uint32 dwK = 0; dwK < 8; ++dwK)
{
pDstBlock[dwK] = pSrcBlock[dwK];
}
for (uint32 dwK = 8; dwK < 16; ++dwK)
{
pDstBlock[dwK] = 0;
}
// 6 bit green channel (highest bits)
// by using all 3 channels with a slight offset we can get more precision but then a dot product would be needed in PS
// because of bilinear filter we cannot just distribute bits to get perfect result
uint16 colDst0 = (((uint16)pSrcBlock[8] + 2) >> 2) << 5;
uint16 colDst1 = (((uint16)pSrcBlock[9] + 2) >> 2) << 5;
bool bFlip = colDst0 <= colDst1;
if (bFlip)
{
uint16 help = colDst0;
colDst0 = colDst1;
colDst1 = help;
}
bool bEqual = colDst0 == colDst1;
// distribute bytes by hand to not have problems with endianess
pDstBlock[8 + 0] = (uint8)colDst0;
pDstBlock[8 + 1] = (uint8)(colDst0 >> 8);
pDstBlock[8 + 2] = (uint8)colDst1;
pDstBlock[8 + 3] = (uint8)(colDst1 >> 8);
uint16* pSrcBlock16 = (uint16*)(pSrcBlock + 10);
uint16* pDstBlock16 = (uint16*)(pDstBlock + 12);
// distribute 16 3 bit values to 16 2 bit values (loosing LSB)
for (uint32 dwK = 0; dwK < 16; ++dwK)
{
uint32 dwBit0 = dwK * 3 + 0;
uint32 dwBit1 = dwK * 3 + 1;
uint32 dwBit2 = dwK * 3 + 2;
uint8 hexDataIn = (((pSrcBlock16[(dwBit2 >> 4)] >> (dwBit2 & 0xf)) & 1) << 2) // get HSB
| (((pSrcBlock16[(dwBit1 >> 4)] >> (dwBit1 & 0xf)) & 1) << 1)
| ((pSrcBlock16[(dwBit0 >> 4)] >> (dwBit0 & 0xf)) & 1); // get LSB
uint8 hexDataOut = 0;
switch (hexDataIn)
{
case 0:
hexDataOut = 0;
break; // color 0
case 1:
hexDataOut = 1;
break; // color 1
case 2:
hexDataOut = 0;
break; // mostly color 0
case 3:
hexDataOut = 2;
break;
case 4:
hexDataOut = 2;
break;
case 5:
hexDataOut = 3;
break;
case 6:
hexDataOut = 3;
break;
case 7:
hexDataOut = 1;
break; // mostly color 1
default:
assert(0);
}
if (bFlip)
{
if (hexDataOut < 2)
{
hexDataOut = 1 - hexDataOut; // 0<->1
}
else
{
hexDataOut = 5 - hexDataOut; // 2<->3
}
}
if (bEqual)
{
if (hexDataOut == 3)
{
hexDataOut = 1;
}
}
pDstBlock16[(dwK >> 3)] |= (hexDataOut << ((dwK & 0x7) << 1));
}
}
// is a bit on in a new bit field, but off in an old bit field
static ILINE bool TurnedOnBit(unsigned bit, unsigned oldBits, unsigned newBits)
{
return (newBits & bit) != 0 && (oldBits & bit) == 0;
}
inline uint32 cellUtilCountLeadingZero(uint32 x)
{
uint32 y;
uint32 n = 32;
y = x >> 16;
if (y != 0)
{
n = n - 16;
x = y;
}
y = x >> 8;
if (y != 0)
{
n = n - 8;
x = y;
}
y = x >> 4;
if (y != 0)
{
n = n - 4;
x = y;
}
y = x >> 2;
if (y != 0)
{
n = n - 2;
x = y;
}
y = x >> 1;
if (y != 0)
{
return n - 2;
}
return n - x;
}
inline uint32 cellUtilLog2(uint32 x)
{
return 31 - cellUtilCountLeadingZero(x);
}
inline void convertSwizzle(uint8*& dst, const uint8*& src,
const uint32 SrcPitch, const uint32 depth,
const uint32 xpos, const uint32 ypos,
const uint32 SciX1, const uint32 SciY1,
const uint32 SciX2, const uint32 SciY2,
const uint32 level)
{
if (level == 1)
{
switch (depth)
{
case 16:
if (xpos >= SciX1 && xpos < SciX2 && ypos >= SciY1 && ypos < SciY2)
{
// *((uint32*&)dst)++ = ((uint32*)src)[ypos * width + xpos];
// *((uint32*&)dst)++ = ((uint32*)src)[ypos * width + xpos+1];
// *((uint32*&)dst)++ = ((uint32*)src)[ypos * width + xpos+2];
// *((uint32*&)dst)++ = ((uint32*)src)[ypos * width + xpos+3];
*((uint32*&)dst)++ = *((uint32*)(src + (ypos * SrcPitch + xpos * 16)));
*((uint32*&)dst)++ = *((uint32*)(src + (ypos * SrcPitch + xpos * 16 + 4)));
*((uint32*&)dst)++ = *((uint32*)(src + (ypos * SrcPitch + xpos * 16 + 8)));
*((uint32*&)dst)++ = *((uint32*)(src + (ypos * SrcPitch + xpos * 16 + 12)));
}
else
{
((uint32*&)dst) += 4;
}
break;
case 8:
if (xpos >= SciX1 && xpos < SciX2 && ypos >= SciY1 && ypos < SciY2)
{
*((uint32*&)dst)++ = *((uint32*)(src + (ypos * SrcPitch + xpos * 8)));
*((uint32*&)dst)++ = *((uint32*)(src + (ypos * SrcPitch + xpos * 8 + 4)));
}
else
{
((uint32*&)dst) += 2;
}
break;
case 4:
if (xpos >= SciX1 && xpos < SciX2 && ypos >= SciY1 && ypos < SciY2)
{
*((uint32*&)dst) = *((uint32*)(src + (ypos * SrcPitch + xpos * 4)));
}
dst += 4;
break;
case 3:
if (xpos >= SciX1 && xpos < SciX2 && ypos >= SciY1 && ypos < SciY2)
{
*dst++ = src[ypos * SrcPitch + xpos * depth];
*dst++ = src[ypos * SrcPitch + xpos * depth + 1];
*dst++ = src[ypos * SrcPitch + xpos * depth + 2];
}
else
{
dst += 3;
}
break;
case 1:
if (xpos >= SciX1 && xpos < SciX2 && ypos >= SciY1 && ypos < SciY2)
{
*dst++ = src[ypos * SrcPitch + xpos * depth];
}
else
{
dst++;
}
break;
default:
assert(0);
}
return;
}
else
{
convertSwizzle(dst, src, SrcPitch, depth, xpos, ypos, SciX1, SciY1, SciX2, SciY2, level - 1);
convertSwizzle(dst, src, SrcPitch, depth, xpos + (1U << (level - 2)), ypos, SciX1, SciY1, SciX2, SciY2, level - 1);
convertSwizzle(dst, src, SrcPitch, depth, xpos, ypos + (1U << (level - 2)), SciX1, SciY1, SciX2, SciY2, level - 1);
convertSwizzle(dst, src, SrcPitch, depth, xpos + (1U << (level - 2)), ypos + (1U << (level - 2)), SciX1, SciY1, SciX2, SciY2, level - 1);
}
}
inline void Linear2Swizzle(uint8* dst,
const uint8* src,
const uint32 SrcPitch,
const uint32 width,
const uint32 height,
const uint32 depth,
const uint32 SciX1, const uint32 SciY1,
const uint32 SciX2, const uint32 SciY2)
{
src -= SciY1 * SrcPitch + SciX1 * depth;
if (width == height)
{
convertSwizzle(dst, src, SrcPitch, depth, 0, 0, SciX1, SciY1, SciX2, SciY2, cellUtilLog2(width) + 1);
}
else
if (width > height)
{
uint32 baseLevel = cellUtilLog2(width) - (cellUtilLog2(width) - cellUtilLog2(height));
for (uint32 i = 0; i < (1UL << (cellUtilLog2(width) - cellUtilLog2(height))); i++)
{
convertSwizzle(dst, src, SrcPitch, depth, (1U << baseLevel) * i, 0, SciX1, SciY1, SciX2, SciY2, baseLevel + 1);
}
}
else
// if (width < height)//wtf
{
uint32 baseLevel = cellUtilLog2(height) - (cellUtilLog2(height) - cellUtilLog2(width));
for (uint32 i = 0; i < (1UL << (cellUtilLog2(height) - cellUtilLog2(width))); i++)
{
convertSwizzle(dst, src, SrcPitch, depth, 0, (1U << baseLevel) * i, SciX1, SciY1, SciX2, SciY2, baseLevel + 1);
}
}
}
+903
View File
@@ -0,0 +1,903 @@
/*
* 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 : Describe contents on CGF file.
#ifndef CRYINCLUDE_CRYCOMMON_CGFCONTENT_H
#define CRYINCLUDE_CRYCOMMON_CGFCONTENT_H
#pragma once
#include <IIndexedMesh.h> // <> required for Interfuscator
#include <IChunkFile.h> // <> required for Interfuscator
#include <CryHeaders.h>
#include <Cry_Color.h>
#include <CryArray.h>
#include <StringUtils.h>
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/std/containers/unordered_map.h> //Required for LOD support for touch bending vegetation
#include <AzCore/std/string/string.h> //Required for LOD support for touch bending vegetation
const int CGF_NODE_NAME_LENGTH = 64;
//END: Add LOD support for touch bending vegetation
struct CMaterialCGF;
struct IConvertContext;
#define CGF_NODE_NAME_LOD_PREFIX "$lod"
//////////////////////////////////////////////////////////////////////////
// This structure represents CGF node.
//////////////////////////////////////////////////////////////////////////
struct CNodeCGF
: public _cfg_reference_target<CNodeCGF>
{
enum ENodeType
{
NODE_MESH,
NODE_LIGHT,
NODE_HELPER,
};
enum EPhysicalizeFlags
{
ePhysicsalizeFlag_MeshNotNeeded = BIT(2), // When set physics data doesn't need additional Mesh indices or vertices.
ePhysicsalizeFlag_NoBreaking = BIT(3), // node is unsuitable for procedural 3d breaking
};
ENodeType type;
//START: Add LOD support for touch bending vegetation
char name[CGF_NODE_NAME_LENGTH];
//END: Add LOD support for touch bending vegetation
string properties;
Matrix34 localTM; // Local space transformation matrix.
Matrix34 worldTM; // World space transformation matrix.
CNodeCGF* pParent; // Pointer to parent node.
CNodeCGF* pSharedMesh; // Not NULL if this node is sharing mesh and physics from referenced Node.
CMesh* pMesh; // Pointer to mesh loaded for this node. (Only when type == NODE_MESH)
HelperTypes helperType; // Only relevant if type==NODE_HELPER
Vec3 helperSize; // Only relevant if type==NODE_HELPER
CMaterialCGF* pMaterial; // Material node.
// Physical data of the node with mesh.
int nPhysicalizeFlags; // Saved into the nFlags2 chunk member.
AZStd::vector<char> physicalGeomData[4];
int nPhysTriCount; // Not saved! only used for statistics in RC
//////////////////////////////////////////////////////////////////////////
// Used internally.
int nChunkId; // Chunk id as loaded from CGF.
int nParentChunkId; // Chunk id of parent Node.
int nObjectChunkId; // Chunk id of the corresponding mesh.
int pos_cont_id; // position controller chunk id
int rot_cont_id; // rotation controller chunk id
int scl_cont_id; // scale controller chunk id
//////////////////////////////////////////////////////////////////////////
// True if worldTM is identity.
bool bIdentityMatrix;
// True when this node is invisible physics proxy.
bool bPhysicsProxy;
// These values are not saved, but are only used for loading empty mesh chunks.
struct MeshInfo
{
int nVerts;
int nIndices;
int nSubsets;
Vec3 bboxMin;
Vec3 bboxMax;
float fGeometricMean;
};
MeshInfo meshInfo;
CrySkinVtx* pSkinInfo; // for skinning with skeleton meshes (deformable objects)
//////////////////////////////////////////////////////////////////////////
// Constructor.
//////////////////////////////////////////////////////////////////////////
void Init()
{
type = NODE_MESH;
localTM.SetIdentity();
worldTM.SetIdentity();
pParent = 0;
pSharedMesh = 0;
pMesh = 0;
pMaterial = 0;
helperType = HP_POINT;
helperSize.Set(0, 0, 0);
nPhysicalizeFlags = 0;
nChunkId = 0;
nParentChunkId = 0;
nObjectChunkId = 0;
pos_cont_id = rot_cont_id = scl_cont_id = 0;
bIdentityMatrix = true;
bPhysicsProxy = false;
pSkinInfo = 0;
nPhysTriCount = 0;
ZeroStruct(meshInfo);
}
CNodeCGF()
{
Init();
}
explicit CNodeCGF(_cfg_reference_target<CNodeCGF>::DeleteFncPtr pDeleteFnc)
: _cfg_reference_target<CNodeCGF>(pDeleteFnc)
{
Init();
}
~CNodeCGF()
{
if (!pSharedMesh)
{
delete pMesh;
}
if (pSkinInfo)
{
delete[] pSkinInfo;
}
}
};
//////////////////////////////////////////////////////////////////////////
// structures for skinning
//////////////////////////////////////////////////////////////////////////
struct TFace
{
uint16 i0, i1, i2;
TFace() {}
TFace(uint16 v0, uint16 v1, uint16 v2) { i0 = v0; i1 = v1; i2 = v2; }
TFace(const CryFace& face) { i0 = aznumeric_caster(face[0]); i1 = aznumeric_caster(face[1]); i2 = aznumeric_caster(face[2]); }
void operator = (const TFace& f) { i0 = f.i0; i1 = f.i1; i2 = f.i2; }
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const{}
AUTO_STRUCT_INFO
};
struct PhysicalProxy
{
uint32 ChunkID;
DynArray<Vec3> m_arrPoints;
DynArray<uint16> m_arrIndices;
DynArray<char> m_arrMaterials;
};
struct MorphTargets
{
uint32 MeshID;
string m_strName;
DynArray<SMeshMorphTargetVertex> m_arrIntMorph;
DynArray<SMeshMorphTargetVertex> m_arrExtMorph;
};
typedef MorphTargets* MorphTargetsPtr;
struct IntSkinVertex
{
Vec3 __obsolete0; // thin/fat vertex position. must be removed in the next RC refactoring
Vec3 pos; // vertex-position of model.2
Vec3 __obsolete2; // thin/fat vertex position. must be removed in the next RC refactoring
uint16 boneIDs[4];
f32 weights[4];
ColorB color; //index for blend-array
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const{}
AUTO_STRUCT_INFO
};
//////////////////////////////////////////////////////////////////////////
// TCB Controller implementation.
//////////////////////////////////////////////////////////////////////////
// retrieves the position and orientation (in the logarithmic space, i.e. instead of quaternion, its logarithm is returned)
// may be optimal for motion interpolation
struct PQLog
{
Vec3 vPos;
Vec3 vRotLog; // logarithm of the rotation
void blendPQ (const PQLog& pqFrom, const PQLog& pqTo, f32 fBlend);
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const{}
};
struct CControllerType
{
uint16 m_controllertype;
uint16 m_index;
CControllerType()
{
m_controllertype = 0xffff;
m_index = 0xffff;
}
};
struct TCBFlags
{
uint8 f0, f1;
TCBFlags() { f0 = f1 = 0; }
};
struct CStoredSkinningInfo
{
int32 m_nTicksPerFrame;
f32 m_secsPerTick;
int32 m_nStart;
int32 m_nEnd;
f32 m_Speed;
f32 m_Distance;
f32 m_Slope;
int m_nAssetFlags;
f32 m_LHeelStart, m_LHeelEnd;
f32 m_LToe0Start, m_LToe0End;
f32 m_RHeelStart, m_RHeelEnd;
f32 m_RToe0Start, m_RToe0End;
Vec3 m_MoveDirection; // raw storage
CStoredSkinningInfo()
: m_Speed(-1.0f)
, m_Distance(-1.0f)
, m_nAssetFlags(0)
, m_LHeelStart(-10000.0f)
, m_LHeelEnd(-10000.0f)
, m_LToe0Start(-10000.0f)
, m_LToe0End(-10000.0f)
, m_RHeelStart(-10000.0f)
, m_RHeelEnd(-10000.0f)
, m_RToe0Start(-10000.0f)
, m_RToe0End(-10000.0f)
, m_Slope(-1.0f)
{
}
AUTO_STRUCT_INFO
};
// structure for recreating controllers
struct CControllerInfo
{
uint32 m_nControllerID;
uint32 m_nPosKeyTimeTrack;
uint32 m_nPosTrack;
uint32 m_nRotKeyTimeTrack;
uint32 m_nRotTrack;
CControllerInfo()
: m_nControllerID(~0)
, m_nPosKeyTimeTrack(~0)
, m_nPosTrack(~0)
, m_nRotKeyTimeTrack(~0)
, m_nRotTrack(~0) {}
AUTO_STRUCT_INFO
};
struct MeshCollisionInfo
{
AABB m_aABB;
OBB m_OBB;
Vec3 m_Pos;
DynArray<int16> m_arrIndexes;
int32 m_iBoneId;
MeshCollisionInfo()
{
// This didn't help much.
// The BBs are reset to opposite infinites,
// but never clamped/grown by any member points.
m_aABB.min.zero();
m_aABB.max.zero();
m_OBB.m33.SetIdentity();
m_OBB.h.zero();
m_OBB.c.zero();
m_Pos.zero();
}
void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(m_arrIndexes);
}
};
struct SJointsAimIK_Rot
{
const char* m_strJointName;
int16 m_nJointIdx;
int16 m_nPosIndex;
uint8 m_nPreEvaluate;
uint8 m_nAdditive;
int16 m_nRotJointParentIdx;
SJointsAimIK_Rot()
{
m_strJointName = 0;
m_nJointIdx = -1;
m_nPosIndex = -1;
m_nPreEvaluate = 0;
m_nAdditive = 0;
m_nRotJointParentIdx = -1;
};
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const{}
};
struct SJointsAimIK_Pos
{
const char* m_strJointName;
int16 m_nJointIdx;
uint8 m_nAdditive;
uint8 m_nEmpty;
SJointsAimIK_Pos()
{
m_strJointName = 0;
m_nJointIdx = -1;
m_nAdditive = 0;
m_nEmpty = 0;
};
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const{}
};
struct DirectionalBlends
{
string m_AnimToken;
uint32 m_AnimTokenCRC32;
const char* m_strParaJointName;
int16 m_nParaJointIdx;
int16 m_nRotParaJointIdx;
const char* m_strStartJointName;
int16 m_nStartJointIdx;
int16 m_nRotStartJointIdx;
const char* m_strReferenceJointName;
int32 m_nReferenceJointIdx;
DirectionalBlends()
{
m_AnimTokenCRC32 = 0;
m_strParaJointName = 0;
m_nParaJointIdx = -1;
m_nRotParaJointIdx = -1;
m_strStartJointName = 0;
m_nStartJointIdx = -1;
m_nRotStartJointIdx = -1;
m_strReferenceJointName = 0;
m_nReferenceJointIdx = 1; //by default we use the Pelvis
};
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {}
};
struct CSkinningInfo
: public _reference_target_t
{
DynArray<CryBoneDescData> m_arrBonesDesc; //animation-bones
DynArray<SJointsAimIK_Rot> m_LookIK_Rot; //rotational joints used for Look-IK
DynArray<SJointsAimIK_Pos> m_LookIK_Pos; //positional joints used for Look-IK
DynArray<DirectionalBlends> m_LookDirBlends; //positional joints used for Look-IK
DynArray<SJointsAimIK_Rot> m_AimIK_Rot; //rotational joints used for Aim-IK
DynArray<SJointsAimIK_Pos> m_AimIK_Pos; //positional joints used for Aim-IK
DynArray<DirectionalBlends> m_AimDirBlends; //positional joints used for Aim-IK
DynArray<PhysicalProxy> m_arrPhyBoneMeshes; //collision proxi
DynArray<MorphTargetsPtr> m_arrMorphTargets;
DynArray<TFace> m_arrIntFaces;
DynArray<IntSkinVertex> m_arrIntVertices;
DynArray<uint16> m_arrExt2IntMap;
DynArray<BONE_ENTITY> m_arrBoneEntities; //physical-bones
DynArray<MeshCollisionInfo> m_arrCollisions;
uint32 m_numChunks{ 0 };
bool m_bRotatedMorphTargets;
bool m_bProperBBoxes;
CSkinningInfo()
: m_bRotatedMorphTargets(false)
, m_bProperBBoxes(false) {}
~CSkinningInfo()
{
for (DynArray<MorphTargetsPtr>::iterator it = m_arrMorphTargets.begin(), end = m_arrMorphTargets.end(); it != end; ++it)
{
delete *it;
}
}
int32 GetJointIDByName(const char* strJointName) const
{
uint32 numJoints = m_arrBonesDesc.size();
for (uint32 i = 0; i < numJoints; i++)
{
if (_stricmp(m_arrBonesDesc[i].m_arrBoneName, strJointName) == 0)
{
return i;
}
}
return -1;
}
// Return name of bone from bone table, return zero id nId is out of range
const char* GetJointNameByID(int32 nJointID) const
{
int32 numJoints = m_arrBonesDesc.size();
if (nJointID >= 0 && nJointID < numJoints)
{
return m_arrBonesDesc[nJointID].m_arrBoneName;
}
return ""; // invalid bone id
}
};
//////////////////////////////////////////////////////////////////////////
// This structure represents Material inside CGF.
//////////////////////////////////////////////////////////////////////////
struct CMaterialCGF
: public _cfg_reference_target<CMaterialCGF>
{
char name[128]; // Material name;
int nFlags; // Material flags.
int nPhysicalizeType;
bool bOldMaterial;
float shOpacity;
// Array of sub materials.
DynArray<CMaterialCGF*> subMaterials;
//////////////////////////////////////////////////////////////////////////
// Used internally.
int nChunkId;
//////////////////////////////////////////////////////////////////////////
void Init()
{
nFlags = 0;
nChunkId = 0;
bOldMaterial = false;
nPhysicalizeType = PHYS_GEOM_TYPE_DEFAULT;
shOpacity = 1.f;
}
CMaterialCGF() { Init(); }
explicit CMaterialCGF(_cfg_reference_target<CMaterialCGF>::DeleteFncPtr pDeleteFnc)
: _cfg_reference_target<CMaterialCGF>(pDeleteFnc)
{ Init(); }
};
//////////////////////////////////////////////////////////////////////////
// Info about physicalization of the CGF.
//////////////////////////////////////////////////////////////////////////
struct CPhysicalizeInfoCGF
{
bool bWeldVertices;
float fWeldTolerance; // Min Distance between vertices when they collapse to single vertex if bWeldVertices enabled.
// breakable physics
int nGranularity;
int nMode;
Vec3* pRetVtx;
int nRetVtx;
int* pRetTets;
int nRetTets;
CPhysicalizeInfoCGF()
: bWeldVertices(true)
, fWeldTolerance(0.01f)
, nMode(-1)
, nGranularity(-1)
, pRetVtx(0)
, nRetVtx(0)
, pRetTets(0)
, nRetTets(0){}
~CPhysicalizeInfoCGF()
{
if (pRetVtx)
{
delete []pRetVtx;
pRetVtx = 0;
}
if (pRetTets)
{
delete []pRetTets;
pRetTets = 0;
}
}
};
//////////////////////////////////////////////////////////////////////////
// Serialized skinnable foliage data
//////////////////////////////////////////////////////////////////////////
#define NODE_PROPERTY_STIFFNESS "stiffness"
#define NODE_PROPERTY_DAMPING "damping"
#define NODE_PROPERTY_THICKNESS "thickness"
struct SSpineRC
{
SSpineRC()
: pVtx(nullptr)
, pSegDim(nullptr)
, nVtx(0)
, len(0)
, pBoneIDs(nullptr)
, parentBoneID(-1)
, pStiffness(nullptr)
, pDamping(nullptr)
, pThickness(nullptr) {}
~SSpineRC()
{
if (pVtx)
{
delete[] pVtx;
}
if (pSegDim)
{
delete[] pSegDim;
}
if (pBoneIDs)
{
delete[] pBoneIDs;
}
if (pStiffness)
{
delete[] pStiffness;
}
if (pDamping)
{
delete[] pDamping;
}
if (pThickness)
{
delete[] pThickness;
}
}
/// Add Skinned Geometry (.CGF) export type (for touch bending vegetation)
static float GetDefaultStiffness() { return 0.5f; }
static float GetDefaultDamping() { return 0.5f; }
static float GetDefaultThickness() { return 0.03f; }
Vec3* pVtx;
Vec4* pSegDim;
int nVtx;
float len;
Vec3 navg;
int parentBoneID;
int* pBoneIDs;
//Per Bone parameters.
float* pStiffness;
float* pDamping;
float* pThickness;
int iAttachSpine;
int iAttachSeg;
};
struct SFoliageInfoCGF
{
SFoliageInfoCGF() { nSpines = 0; pSpines = 0; pBoneMapping = 0; }
~SFoliageInfoCGF()
{
if (pSpines)
{
for (int i = 1; i < nSpines; i++) // spines 1..n-1 use the same buffer, so make sure they don't delete it
{
pSpines[i].pVtx = nullptr;
pSpines[i].pSegDim = nullptr;
pSpines[i].pBoneIDs = nullptr;
pSpines[i].pStiffness = nullptr;
pSpines[i].pDamping = nullptr;
pSpines[i].pThickness = nullptr;
}
delete[] pSpines;
}
SAFE_DELETE_ARRAY(pBoneMapping);
AZStd::unordered_map<AZStd::string, SMeshBoneMappingInfo_uint8*>::iterator iter = boneMappings.begin();
while (iter != boneMappings.end())
{
if (iter->second != nullptr)
{
SAFE_DELETE_ARRAY(iter->second->pBoneMapping);
}
iter++;
}
}
SSpineRC* pSpines;
int nSpines;
///Bone mappings for each LOD level
AZStd::unordered_map<AZStd::string, SMeshBoneMappingInfo_uint8*> boneMappings;
///Bone mapping for legacy format
struct SMeshBoneMapping_uint8* pBoneMapping;
int nSkinnedVtx;
DynArray<uint16> chunkBoneIds;
};
//////////////////////////////////////////////////////////////////////////
struct CExportInfoCGF
{
bool bMergeAllNodes;
bool bUseCustomNormals;
bool bCompiledCGF;
bool bHavePhysicsProxy;
bool bHaveAutoLods;
bool bNoMesh;
bool bWantF32Vertices;
bool b8WeightsPerVertex;
/// Prevent reprocessing skinning data for skinned CGF
bool bSkinnedCGF;
bool bFromColladaXSI;
bool bFromColladaMAX;
bool bFromColladaMAYA;
unsigned int rc_version[4]; // Resource compiler version.
char rc_version_string[16]; // Version as a string.
unsigned int authorToolVersion;
};
//////////////////////////////////////////////////////////////////////////
// This class contain all info loaded from the CGF file.
//////////////////////////////////////////////////////////////////////////
class CContentCGF
{
public:
//////////////////////////////////////////////////////////////////////////
CContentCGF(const char* filename)
{
azstrcpy(m_filename, AZ_ARRAY_SIZE(m_filename), filename);
memset(&m_exportInfo, 0, sizeof(m_exportInfo));
m_exportInfo.bMergeAllNodes = true;
m_exportInfo.bUseCustomNormals = false;
m_exportInfo.bWantF32Vertices = false;
m_exportInfo.b8WeightsPerVertex = false;
m_exportInfo.bSkinnedCGF = false;
m_pCommonMaterial = 0;
m_bConsoleFormat = false;
m_pOwnChunkFile = 0;
}
//////////////////////////////////////////////////////////////////////////
virtual ~CContentCGF()
{
// Free nodes.
m_nodes.clear();
if (m_pOwnChunkFile)
{
m_pOwnChunkFile->Release();
}
}
//////////////////////////////////////////////////////////////////////////
const char* GetFilename() const
{
return m_filename;
}
void SetFilename(const char* filename)
{
azstrcpy(m_filename, AZ_ARRAY_SIZE(m_filename), filename);
}
//////////////////////////////////////////////////////////////////////////
// Access to CGF nodes.
void AddNode(CNodeCGF* pNode)
{
m_nodes.push_back(pNode);
}
int GetNodeCount() const
{
return m_nodes.size();
}
CNodeCGF* GetNode(int i)
{
return m_nodes[i];
}
const CNodeCGF* GetNode(int i) const
{
return m_nodes[i];
}
void ClearNodes()
{
m_nodes.clear();
}
void RemoveNode(CNodeCGF* pNode)
{
assert(pNode);
for (int i = 0; i < m_nodes.size(); ++i)
{
if (m_nodes[i] == pNode)
{
pNode->pParent = 0;
m_nodes.erase(i);
break;
}
}
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Access to CGF materials.
void AddMaterial(CMaterialCGF* pNode)
{
m_materials.push_back(pNode);
}
int GetMaterialCount() const
{
return m_materials.size();
}
CMaterialCGF* GetMaterial(int i)
{
return m_materials[i];
}
void ClearMaterials()
{
m_materials.clear();
}
CMaterialCGF* GetCommonMaterial() const
{
return m_pCommonMaterial;
}
void SetCommonMaterial(CMaterialCGF* pMtl)
{
m_pCommonMaterial = pMtl;
}
DynArray<int>& GetUsedMaterialIDs()
{
return m_usedMaterialIds;
}
const DynArray<int>& GetUsedMaterialIDs() const
{
return m_usedMaterialIds;
}
//////////////////////////////////////////////////////////////////////////
CPhysicalizeInfoCGF* GetPhysicalizeInfo()
{
return &m_physicsInfo;
}
const CPhysicalizeInfoCGF* GetPhysicalizeInfo() const
{
return &m_physicsInfo;
}
CExportInfoCGF* GetExportInfo()
{
return &m_exportInfo;
}
const CExportInfoCGF* GetExportInfo() const
{
return &m_exportInfo;
}
CSkinningInfo* GetSkinningInfo()
{
return &m_SkinningInfo;
}
const CSkinningInfo* GetSkinningInfo() const
{
return &m_SkinningInfo;
}
SFoliageInfoCGF* GetFoliageInfo()
{
return &m_foliageInfo;
}
bool GetConsoleFormat()
{
return m_bConsoleFormat;
}
bool ValidateMeshes(const char** const ppErrorDescription) const
{
for (int i = 0; i < m_nodes.size(); ++i)
{
const CNodeCGF* const pNode = m_nodes[i];
if (pNode && pNode->pMesh && (!pNode->pMesh->Validate(ppErrorDescription)))
{
return false;
}
}
return true;
}
// Set chunk file that this CGF owns.
void SetChunkFile(IChunkFile* pChunkFile)
{
m_pOwnChunkFile = pChunkFile;
}
public:
bool m_bConsoleFormat;
private:
char m_filename[260];
CSkinningInfo m_SkinningInfo;
DynArray<_smart_ptr<CNodeCGF> > m_nodes;
DynArray<_smart_ptr<CMaterialCGF> > m_materials;
DynArray<int> m_usedMaterialIds;
_smart_ptr<CMaterialCGF> m_pCommonMaterial;
CPhysicalizeInfoCGF m_physicsInfo;
CExportInfoCGF m_exportInfo;
SFoliageInfoCGF m_foliageInfo;
IChunkFile* m_pOwnChunkFile;
};
namespace AZ
{
namespace SceneAPI
{
namespace DataTypes
{
class IAnimationGroup;
}
}
}
// Asset Writer interface for writing CContentCGF content to asset file
struct IAssetWriter
{
virtual ~IAssetWriter()
{
}
virtual bool WriteCGF(CContentCGF* content) = 0;
virtual bool WriteCHR(CContentCGF* content, IConvertContext* convertContext) = 0;
virtual bool WriteSKIN(CContentCGF* content, IConvertContext* convertContext, bool exportMorphTargets) = 0;
};
#endif // CRYINCLUDE_CRYCOMMON_CGFCONTENT_H
@@ -0,0 +1,68 @@
/*
* 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.
#include "TypeInfo_impl.h"
#include "CGFContent.h"
STRUCT_INFO_BEGIN(TFace)
STRUCT_VAR_INFO(i0, TYPE_INFO(uint16))
STRUCT_VAR_INFO(i1, TYPE_INFO(uint16))
STRUCT_VAR_INFO(i2, TYPE_INFO(uint16))
STRUCT_INFO_END(TFace)
STRUCT_INFO_BEGIN(IntSkinVertex)
STRUCT_VAR_INFO(__obsolete0, TYPE_INFO(Vec3))
STRUCT_VAR_INFO(pos, TYPE_INFO(Vec3))
STRUCT_VAR_INFO(__obsolete2, TYPE_INFO(Vec3))
STRUCT_VAR_INFO(boneIDs, TYPE_ARRAY(4, TYPE_INFO(uint16)))
STRUCT_VAR_INFO(weights, TYPE_ARRAY(4, TYPE_INFO(f32)))
STRUCT_VAR_INFO(color, TYPE_INFO(ColorB))
STRUCT_INFO_END(IntSkinVertex)
STRUCT_INFO_BEGIN(CStoredSkinningInfo)
STRUCT_VAR_INFO(m_nTicksPerFrame, TYPE_INFO(int32))
STRUCT_VAR_INFO(m_secsPerTick, TYPE_INFO(f32))
STRUCT_VAR_INFO(m_nStart, TYPE_INFO(int32))
STRUCT_VAR_INFO(m_nEnd, TYPE_INFO(int32))
STRUCT_VAR_INFO(m_Speed, TYPE_INFO(f32))
STRUCT_VAR_INFO(m_Distance, TYPE_INFO(f32))
STRUCT_VAR_INFO(m_Slope, TYPE_INFO(f32))
STRUCT_VAR_INFO(m_nAssetFlags, TYPE_INFO(int))
STRUCT_VAR_INFO(m_LHeelStart, TYPE_INFO(f32))
STRUCT_VAR_INFO(m_LHeelEnd, TYPE_INFO(f32))
STRUCT_VAR_INFO(m_LToe0Start, TYPE_INFO(f32))
STRUCT_VAR_INFO(m_LToe0End, TYPE_INFO(f32))
STRUCT_VAR_INFO(m_RHeelStart, TYPE_INFO(f32))
STRUCT_VAR_INFO(m_RHeelEnd, TYPE_INFO(f32))
STRUCT_VAR_INFO(m_RToe0Start, TYPE_INFO(f32))
STRUCT_VAR_INFO(m_RToe0End, TYPE_INFO(f32))
STRUCT_VAR_INFO(m_MoveDirection, TYPE_INFO(Vec3))
STRUCT_INFO_END(CStoredSkinningInfo)
STRUCT_INFO_BEGIN(CControllerInfo)
STRUCT_VAR_INFO(m_nControllerID, TYPE_INFO(uint32))
STRUCT_VAR_INFO(m_nPosKeyTimeTrack, TYPE_INFO(uint32))
STRUCT_VAR_INFO(m_nPosTrack, TYPE_INFO(uint32))
STRUCT_VAR_INFO(m_nRotKeyTimeTrack, TYPE_INFO(uint32))
STRUCT_VAR_INFO(m_nRotTrack, TYPE_INFO(uint32))
STRUCT_INFO_END(CControllerInfo)
STRUCT_INFO_BEGIN(UCol)
STRUCT_VAR_INFO(dcolor, TYPE_INFO(uint32))
STRUCT_INFO_END(UCol)
STRUCT_INFO_BEGIN(SVF_P3S_C4B_T2S)
STRUCT_VAR_INFO(xyz, TYPE_INFO(Vec3f16))
STRUCT_VAR_INFO(color, TYPE_INFO(UCol))
STRUCT_VAR_INFO(st, TYPE_INFO(Vec2f16))
STRUCT_INFO_END(SVF_P3S_C4B_T2S)
+82
View File
@@ -0,0 +1,82 @@
#
# 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.
#
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME})
ly_get_pal_tool_dirs(pal_tool_dirs ${CMAKE_CURRENT_LIST_DIR}/Platform)
ly_add_target(
NAME CryCommon STATIC
NAMESPACE Legacy
FILES_CMAKE
crycommon_files.cmake
${pal_dir}/crycommon_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
PLATFORM_INCLUDE_FILES
${pal_dir}/crycommon_${PAL_PLATFORM_NAME_LOWERCASE}.cmake
INCLUDE_DIRECTORIES
PUBLIC
. # Lots of code without CryCommon/
.. # Dangerous since exports CryEngine's path (client code can do CrySystem/ without depending on that target)
${pal_dir}
${pal_tool_dirs}
BUILD_DEPENDENCIES
PUBLIC
AZ::AzCore
AZ::AzFramework
)
ly_add_target(
NAME CryCommon.EngineSettings.Static STATIC
NAMESPACE Legacy
FILES_CMAKE
crycommon_enginesettings_files.cmake
${pal_dir}/crycommon_enginesettings_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
INCLUDE_DIRECTORIES
PUBLIC
.
${pal_dir}
BUILD_DEPENDENCIES
PUBLIC
AZ::AzCore
AZ::AzFramework
)
ly_add_target(
NAME CryCommon.EngineSettings.RC.Static STATIC
NAMESPACE Legacy
FILES_CMAKE
crycommon_enginesettings_files.cmake
${pal_dir}/crycommon_enginesettings_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
INCLUDE_DIRECTORIES
PUBLIC
.
${pal_dir}
COMPILE_DEFINITIONS
PRIVATE
RESOURCE_COMPILER
BUILD_DEPENDENCIES
PUBLIC
AZ::AzCore
AZ::AzFramework
)
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
ly_add_target(
NAME CryCommonMocks HEADERONLY
NAMESPACE Legacy
FILES_CMAKE
crycommon_testing_files.cmake
INCLUDE_DIRECTORIES
INTERFACE
Mocks
)
endif()
+158
View File
@@ -0,0 +1,158 @@
/*
* 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.
#ifndef __CREBASECLOUD_H__
#define __CREBASECLOUD_H__
//================================================================================
class SCloudParticle
{
public:
inline SCloudParticle();
inline SCloudParticle(const Vec3& vPos, float fRadius, const ColorF& baseColor, float fTransparency = 0);
inline SCloudParticle(const Vec3& vPos, float fRadiusX, float fRadiusY, float fRotMin, float fRotMax, Vec2 vUV[]);
inline ~SCloudParticle();
float GetRadiusX() const { return m_fSize[0]; }
float GetRadiusY() const { return m_fSize[1]; }
float GetTransparency() const { return m_fTransparency; }
const Vec3& GetPosition() const { return m_vPosition; }
const ColorF& GetBaseColor() const { return m_vBaseColor; }
uint32 GetNumLitColors() const { return m_vLitColors.size(); }
inline const ColorF GetLitColor(unsigned int index) const;
float GetSquareSortDistance() const { return m_fSquareSortDistance; }
//! Sets the radius of the particle.
void SetRadiusX(float rad) { m_fSize[0] = rad; }
void SetRadiusY(float rad) { m_fSize[1] = rad; }
void SetTransparency(float trans) { m_fTransparency = trans; }
void SetPosition(const Vec3& pos) { m_vPosition = pos; }
void SetBaseColor(const ColorF& col) { m_vBaseColor = col; }
void AddLitColor(const ColorF& col) { m_vLitColors.push_back(col); }
void ClearLitColors() { m_vLitColors.clear(); }
void SetSquareSortDistance(float fSquareDistance) { m_fSquareSortDistance = fSquareDistance; }
bool operator<(const SCloudParticle& p) const
{
return (m_fSquareSortDistance < p.m_fSquareSortDistance);
}
bool operator>(const SCloudParticle& p) const
{
return (m_fSquareSortDistance > p.m_fSquareSortDistance);
}
protected:
float m_fTransparency;
Vec3 m_vPosition;
float m_fSize[2];
float m_fRotMin;
float m_fRotMax;
ColorF m_vBaseColor;
TArray<ColorF> m_vLitColors;
Vec3 m_vEye;
// for sorting particles during shading
float m_fSquareSortDistance;
public:
Vec2 m_vUV[2];
};
inline SCloudParticle::SCloudParticle()
{
m_fSize[0] = 0;
m_fTransparency = 0;
m_vPosition = Vec3(0, 0, 0);
m_vBaseColor = Col_Black;
m_vEye = Vec3(0, 0, 0);
m_fSquareSortDistance = 0;
m_vLitColors.clear();
}
inline SCloudParticle::SCloudParticle(const Vec3& pos, float fRadius, const ColorF& baseColor, float fTransparency)
{
m_fSize[0] = fRadius;
m_fSize[1] = fRadius;
m_fTransparency = fTransparency;
m_vPosition = pos;
m_vBaseColor = baseColor;
m_vUV[0] = Vec2(0, 0);
m_vUV[1] = Vec2(1, 1);
m_fRotMin = 0;
m_fRotMax = 0;
m_vEye = Vec3(0, 0, 0);
m_fSquareSortDistance = 0;
m_vLitColors.clear();
}
inline SCloudParticle::SCloudParticle(const Vec3& vPos, float fRadiusX, float fRadiusY, float fRotMin, float fRotMax, Vec2 vUV[2])
{
m_fSize[0] = fRadiusX;
m_fSize[1] = fRadiusY;
m_vPosition = vPos;
m_vBaseColor = Col_White;
m_vUV[0] = vUV[0];
m_vUV[1] = vUV[1];
m_fRotMin = fRotMin;
m_fRotMax = fRotMax;
m_fTransparency = 1.0f;
m_vEye = Vec3(0, 0, 0);
m_fSquareSortDistance = 0;
m_vLitColors.clear();
}
inline SCloudParticle::~SCloudParticle()
{
m_vLitColors.clear();
}
inline const ColorF SCloudParticle::GetLitColor(unsigned int index) const
{
if (index <= m_vLitColors.size())
{
return m_vLitColors[index];
}
else
{
return Col_Black;
}
}
//===========================================================================
class CREBaseCloud
: public CRendElementBase
{
friend class CRECloud;
public:
CREBaseCloud()
: CRendElementBase()
{
mfSetType(eDATA_Cloud);
mfUpdateFlags(FCEF_TRANSFORM);
}
virtual void SetParticles(SCloudParticle* pParticles, int nNumParticles) = 0;
virtual void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(this, sizeof(*this));
}
};
#endif // __CREBASECLOUD_H__
+66
View File
@@ -0,0 +1,66 @@
/*
* 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.
#ifndef _CREFOGVOLUME_
#define _CREFOGVOLUME_
#pragma once
#include "VertexFormats.h"
struct IFogVolumeRenderNode;
class CREFogVolume
: public CRendElementBase
{
public:
CREFogVolume();
virtual ~CREFogVolume();
virtual void mfPrepare(bool bCheckOverflow);
virtual bool mfDraw(CShader* ef, SShaderPass* sfm);
virtual void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(this, sizeof(*this));
}
Vec3 m_center;
uint32 m_viewerInsideVolume : 1;
uint32 m_affectsThisAreaOnly : 1;
uint32 m_stencilRef : 8;
uint32 m_volumeType : 1;
uint32 m_reserved : 21;
AABB m_localAABB;
Matrix34 m_matWSInv;
float m_globalDensity;
float m_densityOffset;
float m_nearCutoff;
Vec2 m_softEdgesLerp;
ColorF m_fogColor; // color already combined with fHDRDynamic
Vec3 m_heightFallOffDirScaled;
Vec3 m_heightFallOffBasePoint;
Vec3 m_eyePosInWS;
Vec3 m_eyePosInOS;
Vec3 m_rampParams;
Vec3 m_windOffset;
float m_noiseScale;
Vec3 m_noiseFreq;
float m_noiseOffset;
float m_noiseElapsedTime;
Vec3 m_scale;
};
#endif // #ifndef _CREFOGVOLUME_
+63
View File
@@ -0,0 +1,63 @@
/*
* 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.
#ifndef _CREGameEffect_
#define _CREGameEffect_
#pragma once
//==================================================================================================
// Name: IREGameEffect
// Desc: Interface for game effect render elements, designed to be instantiated in game code, and
// called from the CREGameEffect within the engine. This then allows render elements
// to be created in game code as well as in the engine.
// Author: James Chilvers
//==================================================================================================
struct IREGameEffect
{
virtual ~IREGameEffect(){}
virtual void mfPrepare(bool bCheckOverflow) = 0;
virtual bool mfDraw(CShader* ef, SShaderPass* sfm, CRenderObject* renderObj) = 0;
};//------------------------------------------------------------------------------------------------
//==================================================================================================
// Name: CREGameEffect
// Desc: Render element that uses the IREGameEffect interface for its functionality
// Author: James Chilvers
//==================================================================================================
class CREGameEffect
: public CRendElementBase
{
public:
CREGameEffect();
~CREGameEffect();
// CRendElementBase interface
void mfPrepare(bool bCheckOverflow);
bool mfDraw(CShader* ef, SShaderPass* sfm);
// CREGameEffect interface
inline void SetPrivateImplementation(IREGameEffect* pImpl) { m_pImpl = pImpl; }
inline IREGameEffect* GetPrivateImplementation() const { return m_pImpl; }
virtual void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(this, sizeof(*this));
}
private:
IREGameEffect* m_pImpl; // Implementation of of render element
};//------------------------------------------------------------------------------------------------
#endif // #ifndef _CREGameEffect_
+95
View File
@@ -0,0 +1,95 @@
/*
* 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 : Backend part of geometry cache rendering
#ifndef CRYINCLUDE_CRYCOMMON_CREGEOMCACHE_H
#define CRYINCLUDE_CRYCOMMON_CREGEOMCACHE_H
#pragma once
#if defined(USE_GEOM_CACHES)
#include "../RenderDll/Common/Shaders/Vertex.h"
#include <CryCommon/StaticInstance.h>
class CREGeomCache
: public CRendElementBase
{
public:
struct SMeshInstance
{
AABB m_aabb;
Matrix34 m_matrix;
Matrix34 m_prevMatrix;
};
struct SMeshRenderData
{
DynArray<SMeshInstance> m_instances;
_smart_ptr<IRenderMesh> m_pRenderMesh;
};
struct UpdateList
{
CryCriticalSection m_mutex;
AZStd::vector<CREGeomCache*, AZ::AZStdAlloc<CryLegacySTLAllocator>> m_geoms;
};
public:
CREGeomCache();
~CREGeomCache();
bool Update(const int flags, const bool bTesselation);
static void UpdateModified();
// CRendElementBase interface
virtual bool mfUpdate(int Flags, bool bTessellation);
virtual void mfPrepare(bool bCheckOverflow);
virtual bool mfDraw(CShader* ef, SShaderPass* sfm);
// CREGeomCache interface
virtual void InitializeRenderElement(const uint numMeshes, _smart_ptr<IRenderMesh>* pMeshes, uint16 materialId);
virtual void SetupMotionBlur(CRenderObject* pRenderObject, const SRenderingPassInfo& passInfo);
virtual volatile int* SetAsyncUpdateState(int& threadId);
virtual DynArray<SMeshRenderData>* GetMeshFillDataPtr();
virtual DynArray<SMeshRenderData>* GetRenderDataPtr();
virtual void DisplayFilledBuffer(const int threadId);
AZ::Vertex::Format GetVertexFormat() const override;
bool GetGeometryInfo(SGeometryInfo &streams) override;
private:
uint16 m_materialId;
volatile bool m_bUpdateFrame[2];
volatile int m_transformUpdateState[2];
// We use a double buffered m_meshFillData array for input from the main thread. When data
// was successfully sent from the main thread it gets copied to m_meshRenderData
// This simplifies the cases where frame data is missing, e.g. meshFillData is not updated for a frame
// Note that meshFillData really needs to be double buffered because the copy occurs in render thread
// so the next main thread could already be touching the data again
//
// Note: m_meshRenderData is directly accessed for ray intersections via GetRenderDataPtr.
// This is safe, because it's only used in editor.
DynArray<SMeshRenderData> m_meshFillData[2];
DynArray<SMeshRenderData> m_meshRenderData;
static StaticInstance<UpdateList> sm_updateList[2]; // double buffered update lists
AZ::Vertex::Format m_geomCacheVertexFormat;
};
#endif
#endif // CRYINCLUDE_CRYCOMMON_CREGEOMCACHE_H
+194
View File
@@ -0,0 +1,194 @@
/*
* 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.
#pragma once
#include <IRenderer.h>
#include "Cry_Camera.h"
//================================================================================
struct SDynTexture2;
struct SDynTexture;
class IDynTexture;
class CameraViewParameters;
struct IImposterRenderElement
{
virtual void GetMemoryUsage(ICrySizer* pSizer) const = 0;
virtual void mfPrepare(bool bCheckOverflow) = 0;
virtual bool mfDraw(CShader* ef, SShaderPass* sl) = 0;
virtual const SMinMaxBox& mfGetWorldSpaceBounds() = 0;
virtual bool IsSplit() = 0;
virtual bool IsScreenImposter() = 0;
virtual float GetRadiusX() = 0;
virtual float GetRadiusY() = 0;
virtual Vec3* GetQuadCorners() = 0;
virtual Vec3 GetNearPoint() = 0;
virtual Vec3 GetFarPoint() = 0;
virtual float GetErrorToleranceCosAngle() = 0;
virtual uint32 GetState() = 0;
virtual int GetAlphaRef() = 0;
virtual ColorF GetColorHelper() = 0;
virtual Vec3 GetLastSunDirection() = 0;
virtual uint8 GetLastBestEdge() = 0;
virtual float GetNear() = 0;
virtual float GetFar() = 0;
virtual float GetTransparency() = 0;
virtual Vec3 GetPosition();
virtual int GetLogResolutionX() = 0;
virtual int GetLogResolutionY() = 0;
virtual CameraViewParameters& GetLastViewParameters() = 0;
virtual IDynTexture* GetTexture() = 0;
virtual IDynTexture* GetScreenTexture() = 0;
virtual IDynTexture* GetFrontTexture() = 0;
virtual IDynTexture* GetDepthTexture() = 0;
virtual const SMinMaxBox& GetWorldSpaceBounds() = 0;
virtual void SetBBox(const Vec3& min, const Vec3& max) = 0;
virtual void SetScreenImposterState(bool state) = 0;
virtual void SetState(uint32 state) = 0;
virtual void SetAlphaRef(uint32 ref) = 0;
virtual void SetPosition(Vec3 pos) = 0;
virtual void SetFrameResetValue(int frameResetValue) = 0;
virtual void SetTexture(IDynTexture* texture) = 0;
virtual void SetScreenTexture(IDynTexture* texture) = 0;
virtual void SetFrontTexture(IDynTexture* texture) = 0;
virtual void SetDepthTexture(IDynTexture* texture) = 0;
};
class CREImposter
: public CRendElementBase
{
friend class CRECloud;
static IDynTexture* m_pScreenTexture;
CameraViewParameters m_LastViewParameters;
bool m_bScreenImposter;
bool m_bSplit;
float m_fRadiusX;
float m_fRadiusY;
Vec3 m_vQuadCorners[4]; // in world space, relative to m_vPos, in clockwise order, can be rotated
Vec3 m_vNearPoint;
Vec3 m_vFarPoint;
int m_nLogResolutionX;
int m_nLogResolutionY;
IDynTexture* m_pTexture;
IDynTexture* m_pFrontTexture;
IDynTexture* m_pTextureDepth;
float m_fErrorToleranceCosAngle; // cosine of m_fErrorToleranceAngle used to check if IsImposterValid
SMinMaxBox m_WorldSpaceBV;
uint32 m_State;
int m_AlphaRef;
float m_fCurTransparency;
ColorF m_ColorHelper;
Vec3 m_vPos;
Vec3 m_vLastSunDir;
uint8 m_nLastBestEdge; // 0..11 this edge is favored to not jitter between different edges
float m_fNear;
float m_fFar;
bool IsImposterValid(const CameraViewParameters& viewParameters, float fRadiusX, float fRadiusY, float fCamRadiusX, float fCamRadiusY,
const int iRequiredLogResX, const int iRequiredLogResY, const uint32 dwBestEdge);
bool Display(bool bDisplayFrontOfSplit);
public:
int m_nFrameReset;
int m_FrameUpdate;
float m_fTimeUpdate;
static int m_MemUpdated;
static int m_MemPostponed;
static int m_PrevMemUpdated;
static int m_PrevMemPostponed;
CREImposter()
: CRendElementBase()
, m_pTexture(NULL)
, m_pFrontTexture(NULL)
, m_pTextureDepth(NULL)
, m_bSplit(false)
, m_fRadiusX(0)
, m_fRadiusY(0)
, m_fErrorToleranceCosAngle(cos(DEG2RAD(0.25f)))
, m_bScreenImposter(false)
, m_State(GS_DEPTHWRITE)
, m_AlphaRef(-1)
, m_fCurTransparency(1.0f)
, m_FrameUpdate(0)
, m_nFrameReset(0)
, m_fTimeUpdate(0)
, m_vLastSunDir(0, 0, 0)
, m_nLogResolutionX(0)
, m_nLogResolutionY(0)
, m_nLastBestEdge(0)
{
mfSetType(eDATA_Imposter);
mfUpdateFlags(FCEF_TRANSFORM);
m_ColorHelper = Col_White;
}
virtual ~CREImposter()
{
ReleaseResources();
}
bool UpdateImposter();
void ReleaseResources();
bool PrepareForUpdate();
virtual void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(this, sizeof(*this));
}
virtual void mfPrepare(bool bCheckOverflow);
virtual bool mfDraw(CShader* ef, SShaderPass* sl);
const SMinMaxBox& mfGetWorldSpaceBounds() { return m_WorldSpaceBV; }
virtual bool IsSplit() { return m_bSplit; }
virtual bool IsScreenImposter() { return m_bScreenImposter; }
virtual float GetRadiusX() { return m_fRadiusX; }
virtual float GetRadiusY() { return m_fRadiusY; }
virtual Vec3* GetQuadCorners() { return &m_vQuadCorners[0]; }
virtual Vec3 GetNearPoint() { return m_vNearPoint; }
virtual Vec3 GetFarPoint() { return m_vFarPoint; }
virtual float GetErrorToleranceCosAngle() { return m_fErrorToleranceCosAngle; }
virtual uint32 GetState() { return m_State; }
virtual int GetAlphaRef() { return m_AlphaRef; }
virtual ColorF GetColorHelper() { return m_ColorHelper; }
virtual Vec3 GetLastSunDirection() { return m_vLastSunDir; }
virtual uint8 GetLastBestEdge() { return m_nLastBestEdge; }
virtual float GetNear() { return m_fNear; }
virtual float GetFar() { return m_fFar; }
virtual float GetTransparency() { return m_fCurTransparency; }
virtual Vec3 GetPosition();
virtual int GetLogResolutionX() { return m_nLogResolutionX; }
virtual int GetLogResolutionY() { return m_nLogResolutionY; }
virtual CameraViewParameters& GetLastViewParameters() { return m_LastViewParameters; }
virtual IDynTexture** GetTexture() { return &m_pTexture; }
virtual IDynTexture** GetScreenTexture() { return &m_pScreenTexture; }
virtual IDynTexture** GetFrontTexture() { return &m_pFrontTexture; }
virtual IDynTexture** GetDepthTexture() { return &m_pTextureDepth; }
virtual const SMinMaxBox& GetWorldSpaceBounds() { return m_WorldSpaceBV; }
virtual int GetFrameReset() { return m_nFrameReset; }
virtual void SetBBox(const Vec3& min, const Vec3& max) { m_WorldSpaceBV.SetMin(min); m_WorldSpaceBV.SetMax(max); }
virtual void SetScreenImposterState(bool state) { m_bScreenImposter = state; }
virtual void SetState(uint32 state) { m_State = state; }
virtual void SetAlphaRef(uint32 ref) { m_AlphaRef = ref; }
virtual void SetPosition(Vec3 pos) { m_vPos = pos; }
virtual void SetFrameResetValue(int frameResetValue) { m_nFrameReset = frameResetValue; }
};
+57
View File
@@ -0,0 +1,57 @@
/*
* 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.
#ifndef __CREMESH_H__
#define __CREMESH_H__
class CREMesh
: public CRendElementBase
{
public:
struct CRenderChunk* m_pChunk;
class CRenderMesh* m_pRenderMesh;
// Copy of Chunk to avoid indirections
int32 m_nFirstIndexId;
int32 m_nNumIndices;
uint32 m_nFirstVertId;
uint32 m_nNumVerts;
protected:
CREMesh()
{
mfSetType(eDATA_Mesh);
mfUpdateFlags(FCEF_TRANSFORM);
m_pChunk = NULL;
m_pRenderMesh = NULL;
m_nFirstIndexId = -1;
m_nNumIndices = -1;
m_nFirstVertId = 0;
m_nNumVerts = 0;
}
virtual ~CREMesh()
{
}
// Ideally should be declared and left unimplemented to prevent slicing at compile time
// but this would prevent auto code gen in renderer later on.
// To track potential slicing, uncomment the following (and their equivalent in CREMeshImpl)
//CREMesh(CREMesh&);
//CREMesh& operator=(CREMesh& rhs);
};
#endif // __CREMESH_H__
@@ -0,0 +1,116 @@
/*
* 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.
#ifndef __CREOCCLUSIONQUERY_H__
#define __CREOCCLUSIONQUERY_H__
#define SUPP_HMAP_OCCL
#define SUPP_HWOBJ_OCCL
//=============================================================
class CRenderMesh;
class CREOcclusionQuery
: public CRendElementBase
{
friend class CRender3D;
bool m_bSucceeded;
public:
int m_nVisSamples;
int m_nCheckFrame;
int m_nDrawFrame;
Vec3 m_vBoxMin;
Vec3 m_vBoxMax;
UINT_PTR m_nOcclusionID; // this will carry a pointer LPDIRECT3DQUERY9, so it needs to be 64-bit on Windows 64
CRenderMesh* m_pRMBox;
static uint32 m_nQueriesPerFrameCounter;
static uint32 m_nReadResultNowCounter;
static uint32 m_nReadResultTryCounter;
CREOcclusionQuery()
{
m_nOcclusionID = 0;
m_nVisSamples = 800 * 600;
m_nCheckFrame = 0;
m_nDrawFrame = 0;
m_vBoxMin = Vec3(0, 0, 0);
m_vBoxMax = Vec3(0, 0, 0);
m_pRMBox = NULL;
mfSetType(eDATA_OcclusionQuery);
mfUpdateFlags(FCEF_TRANSFORM);
}
bool RT_ReadResult_Try(uint32 nDefaultNumSamples);
ILINE bool HasSucceeded() const { return m_bSucceeded; }
virtual ~CREOcclusionQuery();
virtual void mfPrepare(bool bCheckOverflow);
virtual bool mfDraw(CShader* ef, SShaderPass* sfm);
virtual void mfReset();
virtual bool mfReadResult_Try(uint32 nDefaultNumSamples = 1);
virtual bool mfReadResult_Now();
virtual void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(this, sizeof(*this));
}
};
struct OcclusionTestClient
{
OcclusionTestClient()
: nLastOccludedMainFrameID(0)
, nLastVisibleMainFrameID(0)
{
#ifdef SUPP_HMAP_OCCL
vLastVisPoint.Set(0, 0, 0);
nTerrainOccLastFrame = 0;
#endif
#ifdef SUPP_HWOBJ_OCCL
bOccluded = true;
pREOcclusionQuery = 0;
#endif
//nInstantTestRequested=0;
}
#ifdef SUPP_HWOBJ_OCCL
~OcclusionTestClient()
{
if (pREOcclusionQuery)
{
pREOcclusionQuery->Release(false);
}
}
#endif
uint32 nLastVisibleMainFrameID, nLastOccludedMainFrameID;
uint32 nLastShadowCastMainFrameID, nLastNoShadowCastMainFrameID;
#ifdef SUPP_HMAP_OCCL
Vec3 vLastVisPoint;
int nTerrainOccLastFrame;
#endif
#ifdef SUPP_HWOBJ_OCCL
CREOcclusionQuery* pREOcclusionQuery;
uint8 bOccluded;
#endif
//uint8 nInstantTestRequested;
};
#endif // CRYINCLUDE_CRYCOMMON_CREOCCLUSIONQUERY_H
+56
View File
@@ -0,0 +1,56 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYCOMMON_CREPOSTPROCESS_H
#define CRYINCLUDE_CRYCOMMON_CREPOSTPROCESS_H
#pragma once
class CREPostProcess
: public CRendElementBase
{
friend class CD3D9Renderer;
public:
CREPostProcess();
virtual ~CREPostProcess();
virtual void mfPrepare(bool bCheckOverflow);
virtual bool mfDraw(CShader* ef, SShaderPass* sfm);
// Use for setting numeric values, vec4 (colors, position, vectors, wtv), strings
virtual int mfSetParameter(const char* pszParam, float fValue, bool bForceValue = false) const;
virtual int mfSetParameterVec4(const char* pszParam, const Vec4& pValue, bool bForceValue = false) const;
virtual int mfSetParameterString(const char* pszParam, const char* pszArg) const;
virtual void mfGetParameter(const char* pszParam, float& fValue) const;
virtual void mfGetParameterVec4(const char* pszParam, Vec4& pValue) const;
virtual void mfGetParameterString(const char* pszParam, const char*& pszArg) const;
virtual int32 mfGetPostEffectID(const char* pPostEffectName) const;
// Reset all post processing effects
virtual void Reset(bool bOnSpecChange = false);
virtual void mfReset()
{
Reset();
}
virtual void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(this, sizeof(*this));
}
};
#endif // CRYINCLUDE_CRYCOMMON_CREPOSTPROCESS_H
+40
View File
@@ -0,0 +1,40 @@
/*
* 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.
#ifndef _CREPRISMOBJECT_
#define _CREPRISMOBJECT_
#pragma once
#if !defined(EXCLUDE_DOCUMENTATION_PURPOSE)
class CREPrismObject
: public CRendElementBase
{
public:
CREPrismObject();
virtual ~CREPrismObject() {}
virtual void mfPrepare(bool bCheckOverflow);
virtual bool mfDraw(CShader* ef, SShaderPass* sfm);
virtual void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(this, sizeof(*this));
}
Vec3 m_center;
};
#endif // EXCLUDE_DOCUMENTATION_PURPOSE
#endif // _CREPRISMOBJECT_
+92
View File
@@ -0,0 +1,92 @@
/*
* 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.
#ifndef __CRESKY_H__
#define __CRESKY_H__
//=============================================================
#include "VertexFormats.h"
#include "../RenderDll/Common/Shaders/Vertex.h"
struct SSkyLightRenderParams;
class CRESky
: public CRendElementBase
{
friend class CRender3D;
public:
float m_fTerrainWaterLevel;
float m_fSkyBoxStretching;
float m_fAlpha;
int m_nSphereListId;
public:
CRESky();
virtual ~CRESky();
virtual void mfPrepare(bool bCheckOverflow);
virtual bool mfDraw(CShader* ef, SShaderPass* sfm);
virtual void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(this, sizeof(*this));
}
AZ::Vertex::Format GetVertexFormat() const override;
bool GetGeometryInfo(SGeometryInfo& streams) override;
private:
AZ::Vertex::Format m_skyVertexFormat;
};
class CREHDRSky
: public CRendElementBase
{
public:
CREHDRSky();
virtual ~CREHDRSky();
virtual void mfPrepare(bool bCheckOverflow);
virtual bool mfDraw(CShader* ef, SShaderPass* sfm);
virtual void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(this, sizeof(*this));
}
void GenerateSkyDomeTextures(int32 width, int32 height);
virtual AZ::Vertex::Format GetVertexFormat() const override;
virtual bool GetGeometryInfo(SGeometryInfo& streams) override;
public:
const SSkyLightRenderParams* m_pRenderParams;
int m_moonTexId;
class CTexture* m_pSkyDomeTextureMie;
class CTexture* m_pSkyDomeTextureRayleigh;
static void SetCommonMoonParams(CShader* ef, bool bUseMoon = false);
private:
void Init();
private:
int m_skyDomeTextureLastTimeStamp;
int m_frameReset;
class CStars* m_pStars;
AZ::Vertex::Format m_hdrSkyVertexFormat;
};
#endif // __CRESKY_H__
@@ -0,0 +1,70 @@
/*
* 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.
#ifndef _CREVOLUMEOBJECT_
#define _CREVOLUMEOBJECT_
#pragma once
#include "VertexFormats.h"
struct IVolumeObjectRenderNode;
struct IVolumeTexture
{
public:
virtual ~IVolumeTexture() {}
virtual void Release() = 0;
virtual bool Create(unsigned int width, unsigned int height, unsigned int depth, unsigned char* pData) = 0;
virtual bool Update(unsigned int width, unsigned int height, unsigned int depth, const unsigned char* pData) = 0;
virtual int GetTexID() const = 0;
virtual uint32 GetWidth() const = 0;
virtual uint32 GetHeight() const = 0;
virtual uint32 GetDepth() const = 0;
virtual ITexture* GetTexture() const = 0;
};
class CREVolumeObject
: public CRendElementBase
{
public:
CREVolumeObject();
virtual ~CREVolumeObject();
virtual void mfPrepare(bool bCheckOverflow);
virtual bool mfDraw(CShader* ef, SShaderPass* sfm);
virtual IVolumeTexture* CreateVolumeTexture() const;
virtual void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(this, sizeof(*this));
}
Vec3 m_center;
Matrix34 m_matInv;
Vec3 m_eyePosInWS;
Vec3 m_eyePosInOS;
Plane m_volumeTraceStartPlane;
AABB m_renderBoundsOS;
bool m_viewerInsideVolume;
bool m_nearPlaneIntersectsVolume;
float m_alpha;
float m_scale;
IVolumeTexture* m_pDensVol;
IVolumeTexture* m_pShadVol;
_smart_ptr<IRenderMesh> m_pHullMesh;
};
#endif // #ifndef _CREVOLUMEOBJECT_
+57
View File
@@ -0,0 +1,57 @@
/*
* 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.
#ifndef _CREWATEROCEAN_
#define _CREWATEROCEAN_
class CWater;
class CREWaterOcean
: public CRendElementBase
{
public:
CREWaterOcean();
virtual ~CREWaterOcean();
virtual void mfPrepare(bool bCheckOverflow);
virtual bool mfDraw(CShader* ef, SShaderPass* sfm);
virtual void mfGetPlane(Plane& pl);
virtual void Create(uint32 nVerticesCount, SVF_P3F_C4B_T2F* pVertices, uint32 nIndicesCount, const void* pIndices, uint32 nIndexSizeof);
void ReleaseOcean();
virtual Vec3 GetPositionAt(float x, float y) const;
virtual Vec4* GetDisplaceGrid() const;
virtual void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(this, sizeof(*this));
}
private:
uint32 m_nVerticesCount;
uint32 m_nIndicesCount;
uint32 m_nIndexSizeof;
void* m_pVertDecl;
void* m_pVertices;
void* m_pIndices;
private:
void UpdateFFT();
void FrameUpdate();
};
#endif
+110
View File
@@ -0,0 +1,110 @@
/*
* 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.
#ifndef _CREWATERVOLUME_
#define _CREWATERVOLUME_
#pragma once
#include "VertexFormats.h"
class CREWaterVolume
: public CRendElementBase
{
public:
CREWaterVolume();
virtual ~CREWaterVolume();
virtual void mfPrepare(bool bCheckOverflow);
virtual bool mfDraw(CShader* ef, SShaderPass* sfm);
virtual void mfGetPlane(Plane& pl);
virtual void mfCenter(Vec3& vCenter, CRenderObject* pObj);
virtual void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(this, sizeof(*this));
}
public:
struct SParams
{
SParams()
: m_pVertices(0)
, m_pIndices(0)
, m_numVertices(0)
, m_numIndices(0)
, m_center(0, 0, 0)
, m_WSBBox(Vec3(-1, -1, -1), Vec3(1, 1, 1))
, m_fogPlane(Vec3(0, 0, 1), 0)
, m_fogDensity(0.1f)
, m_fogColor(0.2f, 0.5f, 0.7f)
, m_fogColorAffectedBySun(true)
, m_fogShadowing(0.5f)
, m_caustics(true)
, m_causticIntensity(1.0f)
, m_causticTiling(1.0f)
, m_causticHeight(0.9f)
, m_viewerInsideVolume(false)
, m_viewerCloseToWaterPlane(false)
, m_viewerCloseToWaterVolume(false)
{
}
const SVF_P3F_C4B_T2F* m_pVertices;
const uint16* m_pIndices;
size_t m_numVertices;
size_t m_numIndices;
Vec3 m_center;
AABB m_WSBBox;
Plane m_fogPlane;
float m_fogDensity;
Vec3 m_fogColor;
bool m_fogColorAffectedBySun;
float m_fogShadowing;
bool m_caustics;
float m_causticIntensity;
float m_causticTiling;
float m_causticHeight;
bool m_viewerInsideVolume;
bool m_viewerCloseToWaterPlane;
bool m_viewerCloseToWaterVolume;
};
struct SOceanParams
{
SOceanParams()
: m_fogColor(0.2f, 0.5f, 0.7f)
, m_fogColorShallow(0.2f, 0.5f, 0.7f)
, m_fogDensity(0.2f)
{
}
Vec3 m_fogColor;
Vec3 m_fogColorShallow;
float m_fogDensity;
};
public:
const SParams* m_pParams;
const SOceanParams* m_pOceanParams;
bool m_drawWaterSurface;
bool m_drawFastPath;
};
#endif // #ifndef _CREWATERVOLUME_
@@ -0,0 +1,165 @@
/*
* 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.
#include "TypeInfo_impl.h"
#include "Cry_Geo.h"
STRUCT_INFO_T_BEGIN(Vec2_tpl, class, F)
VAR_INFO(x)
VAR_INFO(y)
STRUCT_INFO_T_END(Vec2_tpl, class, F)
#include "Cry_Vector3.h"
STRUCT_INFO_T_BEGIN(Vec3_tpl, typename, F)
VAR_INFO(x)
VAR_INFO(y)
VAR_INFO(z)
STRUCT_INFO_T_END(Vec3_tpl, typename, F)
typedef TFixed<unsigned char, 1, 255, 0> TFixedUChar_1_255_0;
STRUCT_INFO_T_INSTANTIATE(Vec3_tpl, TFixedUChar_1_255_0)
STRUCT_INFO_T_BEGIN(Vec4_tpl, typename, F)
VAR_INFO(x)
VAR_INFO(y)
VAR_INFO(z)
VAR_INFO(w)
STRUCT_INFO_T_END(Vec4_tpl, typename, F)
STRUCT_INFO_T_INSTANTIATE(Vec4_tpl, short)
STRUCT_INFO_T_BEGIN(Ang3_tpl, typename, F)
VAR_INFO(x)
VAR_INFO(y)
VAR_INFO(z)
STRUCT_INFO_T_END(Ang3_tpl, typename, F)
STRUCT_INFO_T_BEGIN(Plane_tpl, typename, F)
VAR_INFO(n)
VAR_INFO(d)
STRUCT_INFO_T_END(Plane_tpl, typename, F)
//-----------------------------------------------------------------
//#include "Cry_Quat_info.h"
STRUCT_INFO_T_BEGIN(Quat_tpl, typename, F)
VAR_INFO(v)
VAR_INFO(w)
STRUCT_INFO_T_END(Quat_tpl, typename, F)
STRUCT_INFO_T_INSTANTIATE(Quat_tpl, float)
STRUCT_INFO_T_BEGIN(QuatT_tpl, typename, F)
VAR_INFO(q)
VAR_INFO(t)
STRUCT_INFO_T_END(QuatT_tpl, typename, F)
STRUCT_INFO_T_INSTANTIATE(QuatT_tpl, float)
STRUCT_INFO_T_BEGIN(QuatTS_tpl, typename, F)
VAR_INFO(q)
VAR_INFO(t)
VAR_INFO(s)
STRUCT_INFO_T_END(QuatTS_tpl, typename, F)
STRUCT_INFO_T_BEGIN(DualQuat_tpl, typename, F)
VAR_INFO(nq)
VAR_INFO(dq)
STRUCT_INFO_T_END(DualQuat_tpl, typename, F)
//------------------------------------------------------------
//#include "Cry_Matrix_info.h"
STRUCT_INFO_T_BEGIN(Matrix33_tpl, typename, F)
VAR_INFO(m00)
VAR_INFO(m01)
VAR_INFO(m02)
VAR_INFO(m10)
VAR_INFO(m11)
VAR_INFO(m12)
VAR_INFO(m20)
VAR_INFO(m21)
VAR_INFO(m22)
STRUCT_INFO_T_END(Matrix33_tpl, typename, F)
STRUCT_INFO_T_BEGIN(Matrix34_tpl, typename, F)
VAR_INFO(m00)
VAR_INFO(m01)
VAR_INFO(m02)
VAR_INFO(m03)
VAR_INFO(m10)
VAR_INFO(m11)
VAR_INFO(m12)
VAR_INFO(m13)
VAR_INFO(m20)
VAR_INFO(m21)
VAR_INFO(m22)
VAR_INFO(m23)
STRUCT_INFO_T_END(Matrix34_tpl, typename, F)
STRUCT_INFO_T_INSTANTIATE(Matrix34_tpl, float)
STRUCT_INFO_T_BEGIN(Matrix44_tpl, typename, F)
VAR_INFO(m00)
VAR_INFO(m01)
VAR_INFO(m02)
VAR_INFO(m03)
VAR_INFO(m10)
VAR_INFO(m11)
VAR_INFO(m12)
VAR_INFO(m13)
VAR_INFO(m20)
VAR_INFO(m21)
VAR_INFO(m22)
VAR_INFO(m23)
VAR_INFO(m30)
VAR_INFO(m31)
VAR_INFO(m32)
VAR_INFO(m33)
STRUCT_INFO_T_END(Matrix44_tpl, typename, F)
//#include "Cry_Color_info.h"
STRUCT_INFO_T_BEGIN(Color_tpl, class, T)
VAR_INFO(r)
VAR_INFO(g)
VAR_INFO(b)
VAR_INFO(a)
STRUCT_INFO_T_END(Color_tpl, class, T)
STRUCT_INFO_T_INSTANTIATE(Color_tpl, unsigned char)
//#include "Cry_Geo_info.h"
STRUCT_INFO_BEGIN(AABB)
VAR_INFO(min)
VAR_INFO(max)
STRUCT_INFO_END(AABB)
STRUCT_INFO_BEGIN(RectF)
VAR_INFO(x)
VAR_INFO(y)
VAR_INFO(w)
VAR_INFO(h)
STRUCT_INFO_END(RectF)
#include "TimeValue_info.h"
#include "CryHalf_info.h"
// Manually instantiate templates as needed here.
template struct Vec3_tpl<float>;
template struct Vec4_tpl<float>;
template struct Vec2_tpl<float>;
template struct Ang3_tpl<float>;
template struct Plane_tpl<float>;
template struct Matrix33_tpl<float>;
template struct Color_tpl<float>;
@@ -0,0 +1,60 @@
/*
* 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.
// Inspired by the Boost library's BOOST_STATIC_ASSERT(),
// see http://www.boost.org/doc/libs/1_49_0/doc/html/boost_staticassert/how.html
// or http://www.boost.org/libs/static_assert
#ifndef CRYINCLUDE_CRYCOMMON_COMPILETIMEASSERT_H
#define CRYINCLUDE_CRYCOMMON_COMPILETIMEASSERT_H
#pragma once
#if defined(__cplusplus)
/*
template <bool b>
struct COMPILE_TIME_ASSERT_FAIL;
template <>
struct COMPILE_TIME_ASSERT_FAIL<true>
{
};
template <int i>
struct COMPILE_TIME_ASSERT_TEST
{
enum { dummy = i };
};
#define COMPILE_TIME_ASSERT_BUILD_NAME2(x, y) x##y
#define COMPILE_TIME_ASSERT_BUILD_NAME1(x, y) COMPILE_TIME_ASSERT_BUILD_NAME2(x, y)
#define COMPILE_TIME_ASSERT_BUILD_NAME(x, y) COMPILE_TIME_ASSERT_BUILD_NAME1(x, y)
#ifndef __RECODE__
#define COMPILE_TIME_ASSERT(expr) \
typedef COMPILE_TIME_ASSERT_TEST<sizeof(COMPILE_TIME_ASSERT_FAIL<(bool)(expr)>)> \
COMPILE_TIME_ASSERT_BUILD_NAME(compile_time_assert_test_, __LINE__)
// note: for MS Visual Studio we could use __COUNTER__ instead of __LINE__
#else
#define COMPILE_TIME_ASSERT(expr)
#endif // __RECODE__
#else
#define COMPILE_TIME_ASSERT(expr)
*/
#endif
#define COMPILE_TIME_ASSERT_MSG(expr, msg) static_assert(expr, msg)
#define COMPILE_TIME_ASSERT(expr) COMPILE_TIME_ASSERT_MSG(expr, "Compile Time Assert")
#endif // CRYINCLUDE_CRYCOMMON_COMPILETIMEASSERT_H
+24
View File
@@ -0,0 +1,24 @@
/*
* 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.
*
*/
#pragma once
#include <AzCore/PlatformRestrictedFileDef.h>
#include <memory>
namespace std
{
#if defined(AZ_RESTRICTED_PLATFORM)
#include AZ_RESTRICTED_FILE(Console_std_h)
#endif
}
+77
View File
@@ -0,0 +1,77 @@
/*
* 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 : A wrapper that counts the number of times the wrapped object
// has been set This is useful for netserializing an object
// that might be given a new value that s the same as the old value
#ifndef CRYINCLUDE_CRYCOMMON_COUNTEDVALUE_H
#define CRYINCLUDE_CRYCOMMON_COUNTEDVALUE_H
#pragma once
template <typename T>
struct CountedValue
{
public:
CountedValue()
: m_lastProducedId(0)
, m_lastConsumedId(0) {}
typedef uint32 TCountedID;
void SetAndDirty(const T& value)
{
m_value = value;
++m_lastProducedId;
CRY_ASSERT(m_lastProducedId > 0);
}
const T* GetLatestValue()
{
bool bHasNewValue = IsDirty(); // check for dirtiness before updating ids
m_lastConsumedId = m_lastProducedId;
return bHasNewValue ? &m_value : NULL;
}
inline bool IsDirty() const
{
return m_lastProducedId != m_lastConsumedId;
}
const T& Peek() const
{
return m_value;
}
TCountedID GetLatestID() const
{
return m_lastProducedId;
}
// This method should only be used to update the object during serialization!
void UpdateDuringSerializationOnly(const T& value, TCountedID lastProducedId)
{
m_value = value;
m_lastProducedId = lastProducedId;
}
private:
TCountedID m_lastProducedId;
TCountedID m_lastConsumedId;
T m_value;
};
#endif // CRYINCLUDE_CRYCOMMON_COUNTEDVALUE_H
+160
View File
@@ -0,0 +1,160 @@
/*
* 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.
// support for leak dumping and statistics gathering using vs Crt Debug
// should be included in every DLL below DllMain()
#ifndef CRYINCLUDE_CRYCOMMON_CRTDEBUGSTATS_H
#define CRYINCLUDE_CRYCOMMON_CRTDEBUGSTATS_H
#pragma once
#ifdef WIN32
#ifdef _DEBUG
#include <ILog.h>
#include <ISystem.h> // CryLogAlways
#include <crtdbg.h>
// copied from DBGINT.H (not a public header!)
#define nNoMansLandSize 4
typedef struct _CrtMemBlockHeader
{
struct _CrtMemBlockHeader* pBlockHeaderNext;
struct _CrtMemBlockHeader* pBlockHeaderPrev;
char* szFileName;
int nLine;
size_t nDataSize;
int nBlockUse;
long lRequest;
unsigned char gap[nNoMansLandSize];
/* followed by:
* unsigned char data[nDataSize];
* unsigned char anotherGap[nNoMansLandSize];
*/
} _CrtMemBlockHeader;
struct SFileInfo
{
int blocks;
INT_PTR bytes; //AMD Port
SFileInfo(INT_PTR b) { blocks = 1; bytes = b; }; //AMD Port
};
_CrtMemState lastcheckpoint;
bool checkpointset = false;
extern "C" void __declspec(dllexport) CheckPoint()
{
_CrtMemCheckpoint(&lastcheckpoint);
checkpointset = true;
};
bool pairgreater(const std::pair<string, SFileInfo>& elem1, const std::pair<string, SFileInfo>& elem2)
{
return elem1.second.bytes > elem2.second.bytes;
}
extern "C" void __declspec(dllexport) UsageSummary([[maybe_unused]] ILog * log, char* modulename, int* extras)
{
_CrtMemState state;
if (checkpointset)
{
_CrtMemState recent;
_CrtMemCheckpoint(&recent);
_CrtMemDifference(&state, &lastcheckpoint, &recent);
}
else
{
_CrtMemCheckpoint(&state);
};
INT_PTR numblocks = state.lCounts[_NORMAL_BLOCK]; //AMD Port
INT_PTR totalalloc = state.lSizes[_NORMAL_BLOCK]; //AMD Port
check_convert(extras[0]) = totalalloc;
check_convert(extras[1]) = numblocks;
CryLogAlways("$5---------------------------------------------------------------------------------------------------");
if (!numblocks)
{
CryLogAlways("$3Module %s has no memory in use", modulename);
return;
}
;
CryLogAlways("$5Usage summary for module %s", modulename);
CryLogAlways("%d kbytes (peak %d) in %d objects of %d average bytes\n",
totalalloc / 1024, state.lHighWaterCount / 1024, numblocks, numblocks ? totalalloc / numblocks : 0);
CryLogAlways("%d kbytes allocated over time\n", state.lTotalCount / 1024);
typedef std::map<string, SFileInfo> FileMap;
FileMap fm;
for (_CrtMemBlockHeader* h = state.pBlockHeader; h; h = h->pBlockHeaderNext)
{
if (_BLOCK_TYPE(h->nBlockUse) != _NORMAL_BLOCK)
{
continue;
}
string s = h->szFileName ? h->szFileName : "NO_SOURCE";
if (h->nLine > 0)
{
char buf[16];
sprintf_s(buf, "_%d", h->nLine);
s += buf;
}
FileMap::iterator it = fm.find(s);
if (it != fm.end())
{
(*it).second.blocks++;
(*it).second.bytes += h->nDataSize;
}
else
{
fm.insert(FileMap::value_type(s, SFileInfo(h->nDataSize)));
};
}
;
typedef std::vector< std::pair<string, SFileInfo> > FileVector;
FileVector fv;
for (FileMap::iterator it = fm.begin(); it != fm.end(); ++it)
{
fv.push_back((*it));
}
std::sort(fv.begin(), fv.end(), pairgreater);
for (FileVector::iterator it = fv.begin(); it != fv.end(); ++it)
{
CryLogAlways("%6d kbytes / %6d blocks allocated from %s\n",
(*it).second.bytes / 1024, (*it).second.blocks, (*it).first.c_str());
}
;
};
#endif // _DEBUG
#if !defined(_RELEASE) && !defined(_DLL) && defined(HANDLE)
extern "C" HANDLE _crtheap;
extern "C" HANDLE __declspec(dllexport) GetDLLHeap() {
return _crtheap;
};
#endif
#endif // WIN32
#endif // CRYINCLUDE_CRYCOMMON_CRTDEBUGSTATS_H
File diff suppressed because it is too large Load Diff
+84
View File
@@ -0,0 +1,84 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYCOMMON_ARRAY2D_H
#define CRYINCLUDE_CRYCOMMON_ARRAY2D_H
#pragma once
// Dynamic replacement for static 2d array
template <class T>
struct Array2d
{
Array2d()
{
m_nSize = 0;
m_pData = 0;
}
int GetSize() const { return m_nSize; }
int GetDataSize() const { return m_nSize * m_nSize * sizeof(T); }
T* GetData() { return m_pData; }
T* GetDataEnd() { return &m_pData[m_nSize * m_nSize]; }
void SetData(T* pData, int nSize)
{
Allocate(nSize);
memcpy(m_pData, pData, nSize * nSize * sizeof(T));
}
void Allocate(int nSize)
{
if (m_nSize == nSize)
{
return;
}
delete [] m_pData;
m_nSize = nSize;
m_pData = new T [nSize * nSize];
memset(m_pData, 0, nSize * nSize * sizeof(T));
}
~Array2d()
{
delete [] m_pData;
}
void Reset()
{
delete [] m_pData;
m_pData = 0;
m_nSize = 0;
}
T* m_pData;
int m_nSize;
T* operator [] (const int& nPos) const
{
assert(nPos >= 0 && nPos < m_nSize);
return &m_pData[nPos * m_nSize];
}
Array2d& operator = (const Array2d& other)
{
Allocate(other.m_nSize);
memcpy(m_pData, other.m_pData, m_nSize * m_nSize * sizeof(T));
return *this;
}
};
#endif // CRYINCLUDE_CRYCOMMON_ARRAY2D_H
+105
View File
@@ -0,0 +1,105 @@
/*
* 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 : Assert dialog box
#pragma once
#include <AzCore/base.h>
//-----------------------------------------------------------------------------------------------------
// Just undef this if you want to use the standard assert function
//-----------------------------------------------------------------------------------------------------
// if AZ_ENABLE_TRACING is enabled, then calls to AZ_Assert(...) will flow in. This is the case
// even in Profile mode - thus if you want to manage what happens, USE_CRY_ASSERT also needs to be enabled in those cases.
// if USE_CRY_ASSERT is not enabled, but AZ_ENABLE_TRACING is enabled, then the default behavior for assets will occur instead
// which is to throw the DEBUG BREAK exception / signal, which tends to end with application shutdown.
#if defined(AZ_ENABLE_TRACE_ASSERTS)
#define USE_AZ_ASSERT
#endif
#if !defined (USE_AZ_ASSERT) && defined(AZ_ENABLE_TRACING)
#undef USE_CRY_ASSERT
#define USE_CRY_ASSERT
#endif
// you can undefine this. It will cause the assert message box to appear anywhere that USE_CRY_ASSERT is enabled
// instead of it only appearing in debug.
// if this is DEFINED then only in debug builds will you see the message box. In other builds, CRY_ASSERTS become CryWarning instead of
// instead (showing no message box, only a warning).
#define CRY_ASSERT_DIALOG_ONLY_IN_DEBUG
#if defined(FORCE_STANDARD_ASSERT) || defined(USE_AZ_ASSERT)
#undef USE_CRY_ASSERT
#undef CRY_ASSERT_DIALOG_ONLY_IN_DEBUG
#endif
// Using AZ_Assert for all assert kinds (assert =, CRY_ASSERT, AZ_Assert). This is for Provo and Xenia
// see Trace::Assert for implementation
#if defined(USE_AZ_ASSERT)
#undef assert
#define assert(condition) AZ_Assert(condition, "%s", #condition)
#endif //defined(USE_AZ_ASSERT)
//-----------------------------------------------------------------------------------------------------
// Use like this:
// CRY_ASSERT(expression);
// CRY_ASSERT_MESSAGE(expression,"Useful message");
// CRY_ASSERT_TRACE(expression,("This should never happen because parameter n%d named %s is %f",iParameter,szParam,fValue));
//-----------------------------------------------------------------------------------------------------
#if defined(AZ_RESTRICTED_PLATFORM)
#include AZ_RESTRICTED_FILE(CryAssert_h)
#endif
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
#elif defined(WIN32) || defined(APPLE) || defined(LINUX)
#define CRYASSERT_H_TRAIT_USE_CRY_ASSERT_MESSAGE 1
#endif
#if defined(USE_CRY_ASSERT) && CRYASSERT_H_TRAIT_USE_CRY_ASSERT_MESSAGE
void CryAssertTrace(const char*, ...);
bool CryAssert(const char*, const char*, unsigned int, bool*);
void CryDebugBreak();
#define CRY_ASSERT(condition) CRY_ASSERT_MESSAGE(condition, NULL)
#define CRY_ASSERT_MESSAGE(condition, message) CRY_ASSERT_TRACE(condition, (message))
#define CRY_ASSERT_TRACE(condition, parenthese_message) \
do \
{ \
static bool s_bIgnoreAssert = false; \
if (!s_bIgnoreAssert && !(condition)) \
{ \
CryAssertTrace parenthese_message; \
if (CryAssert(#condition, __FILE__, __LINE__, &s_bIgnoreAssert)) \
{ \
DEBUG_BREAK; \
} \
} \
} while (0)
#undef assert
#define assert CRY_ASSERT
#elif !defined(CRY_ASSERT)
#ifndef USE_AZ_ASSERT
#include <assert.h>
#endif //USE_AZ_ASSERT
#define CRY_ASSERT(condition) assert(condition)
#define CRY_ASSERT_MESSAGE(condition, message) assert(condition)
#define CRY_ASSERT_TRACE(condition, parenthese_message) assert(condition)
#endif
//-----------------------------------------------------------------------------------------------------
@@ -0,0 +1,105 @@
/*
* 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 : Assert dialog box for android
#ifndef CRYINCLUDE_CRYCOMMON_CRYASSERT_ANDROID_H
#define CRYINCLUDE_CRYCOMMON_CRYASSERT_ANDROID_H
#pragma once
#if defined(USE_CRY_ASSERT) && defined(ANDROID)
#include <AzCore/NativeUI/NativeUIRequests.h>
static char gs_szMessage[MAX_PATH];
void CryAssertTrace(const char* szFormat, ...)
{
if (gEnv == 0)
{
return;
}
if (!gEnv->bIgnoreAllAsserts || gEnv->bTesting)
{
if (szFormat == NULL)
{
gs_szMessage[0] = '\0';
}
else
{
va_list args;
va_start(args, szFormat);
vsnprintf(gs_szMessage, sizeof(gs_szMessage), szFormat, args);
va_end(args);
}
}
}
bool CryAssert(const char* szCondition, const char* szFile, unsigned int line, bool* pIgnore)
{
if (!gEnv)
{
return true;
}
#if defined(CRY_ASSERT_DIALOG_ONLY_IN_DEBUG) && !defined(AZ_DEBUG_BUILD)
// we are in a non-debug build, so we should turn this into a warning instead.
if ((gEnv) && (gEnv->pLog))
{
if (!gEnv->bIgnoreAllAsserts)
{
gEnv->pLog->LogWarning("%s(%u): Assertion failed - \"%s\"", szFile, line, szCondition);
}
}
if (pIgnore)
{
// avoid showing the same one repeatedly.
*pIgnore = true;
}
return false;
#endif
gEnv->pSystem->OnAssert(szCondition, gs_szMessage, szFile, line);
if (!gEnv->bNoAssertDialog && !gEnv->bIgnoreAllAsserts)
{
AZ::NativeUI::AssertAction result;
EBUS_EVENT_RESULT(result, AZ::NativeUI::NativeUIRequestBus, DisplayAssertDialog, gs_szMessage);
switch (result)
{
case AZ::NativeUI::AssertAction::IGNORE_ASSERT:
return false;
case AZ::NativeUI::AssertAction::IGNORE_ALL_ASSERTS:
gEnv->bNoAssertDialog = true;
gEnv->bIgnoreAllAsserts = true;
return false;
case AZ::NativeUI::AssertAction::BREAK:
return true;
default:
break;
}
return true;
}
else
{
return false;
}
}
#endif
#endif // CRYINCLUDE_CRYCOMMON_CRYASSERT_ANDROID_H
+136
View File
@@ -0,0 +1,136 @@
/*
* 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 :
// Assert dialog box for LINUX. The linux assert dialog is based on a
// small ncurses application which writes the choice to a file. This
// was chosen since there is no default UI system on Linux. X11 wasn't
// used due to the possibility of the system running another display
// protocol (e.g.: WayLand, Mir)
#ifndef CRYINCLUDE_CRYCOMMON_CRYASSERT_LINUX_H
#define CRYINCLUDE_CRYCOMMON_CRYASSERT_LINUX_H
#pragma once
#if defined(USE_CRY_ASSERT) && defined(LINUX) && !defined(ANDROID)
static char gs_szMessage[MAX_PATH];
void CryAssertTrace(const char* szFormat, ...)
{
if (gEnv == 0)
{
return;
}
if (!gEnv->bIgnoreAllAsserts || gEnv->bTesting)
{
if (szFormat == NULL)
{
gs_szMessage[0] = '\0';
}
else
{
va_list args;
va_start(args, szFormat);
vsnprintf(gs_szMessage, sizeof(gs_szMessage), szFormat, args);
va_end(args);
}
}
}
bool CryAssert(const char* szCondition, const char* szFile, unsigned int line, bool* pIgnore)
{
if (!gEnv)
{
return false;
}
#if defined(CRY_ASSERT_DIALOG_ONLY_IN_DEBUG) && !defined(AZ_DEBUG_BUILD)
// we are in a non-debug build, so we should turn this into a warning instead.
if (gEnv->pLog)
{
if (!gEnv->bIgnoreAllAsserts)
{
gEnv->pLog->LogWarning("%s(%u): Assertion failed - \"%s\"", szFile, line, szCondition);
}
}
if (pIgnore)
{
// avoid showing the same one repeatedly.
*pIgnore = true;
}
return false;
#endif
static const int max_len = 4096;
static char gs_command_str[4096];
static CryLockT<CRYLOCK_RECURSIVE> lock;
gEnv->pSystem->OnAssert(szCondition, gs_szMessage, szFile, line);
size_t file_len = strlen(szFile);
if (!gEnv->bNoAssertDialog && !gEnv->bIgnoreAllAsserts)
{
CryAutoLock< CryLockT<CRYLOCK_RECURSIVE> > lk (lock);
snprintf(gs_command_str, max_len, "xterm -geometry 100x20 -n 'Assert Dialog [Linux Launcher]' -T 'Assert Dialog [Linux Launcher]' -e 'BinLinux/assert_term \"%s\" \"%s\" %d \"%s\"; echo \"$?\" > .assert_return'",
szCondition, (file_len > 60) ? szFile + (file_len - 61) : szFile, line, gs_szMessage);
int ret = system(gs_command_str);
if (ret != 0)
{
CryLogAlways("<Assert> Terminal failed to execute");
return false;
}
FILE* assert_file = fopen(".assert_return", "r");
if (!assert_file)
{
CryLogAlways("<Assert> Couldn't open assert file");
return false;
}
int result = -1;
fscanf(assert_file, "%d", &result);
fclose(assert_file);
switch (result)
{
case 0:
break;
case 1:
*pIgnore = true;
break;
case 2:
gEnv->bIgnoreAllAsserts = true;
break;
case 3:
return true;
break;
case 4:
raise(SIGABRT);
exit(-1);
break;
default:
CryLogAlways("<Assert> Unknown result in assert file: %d", result);
return false;
}
}
return false;
}
#endif
#endif // CRYINCLUDE_CRYCOMMON_CRYASSERT_LINUX_H
+150
View File
@@ -0,0 +1,150 @@
/*
* 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 : Assert dialog box for Mac OS X
#ifndef CRYINCLUDE_CRYCOMMON_CRYASSERT_MAC_H
#define CRYINCLUDE_CRYCOMMON_CRYASSERT_MAC_H
#pragma once
#if defined(USE_CRY_ASSERT) && defined(MAC)
#include <AzCore/NativeUI/NativeUIRequests.h>
static char gs_szMessage[MAX_PATH];
void CryAssertTrace(const char* szFormat, ...)
{
if (gEnv == 0)
{
return;
}
if (!gEnv->bIgnoreAllAsserts || gEnv->bTesting)
{
if (szFormat == NULL)
{
gs_szMessage[0] = '\0';
}
else
{
va_list args;
va_start(args, szFormat);
vsnprintf(gs_szMessage, sizeof(gs_szMessage), szFormat, args);
va_end(args);
}
}
}
/*
bool CryAssert(const char* szCondition, const char* szFile,unsigned int line, bool *pIgnore)
{
if (!gEnv) return false;
gEnv->pSystem->OnAssert(szCondition, gs_szMessage, szFile, line);
if (!gEnv->bNoAssertDialog && !gEnv->bIgnoreAllAsserts)
{
EDialogAction action = MacOSXHandleAssert(szCondition, szFile, line, gs_szMessage, gEnv->pRenderer != NULL);
switch (action) {
case eDAStop:
raise(SIGABRT);
exit(-1);
case eDABreak:
return true;
case eDAIgnoreAll:
gEnv->bIgnoreAllAsserts = true;
break;
case eDAIgnore:
*pIgnore = true;
break;
case eDAReportAsBug:
if ( gEnv && gEnv->pSystem)
{
gEnv->pSystem->ReportBug("Assert: %s - %s", szCondition,gs_szMessage);
}
case eDAContinue:
default:
break;
}
}
return false;
}*/
bool CryAssert(const char* szCondition, const char* szFile, unsigned int line, bool* pIgnore)
{
if (!gEnv)
{
return false;
}
#if defined(CRY_ASSERT_DIALOG_ONLY_IN_DEBUG) && !defined(AZ_DEBUG_BUILD)
// we are in a non-debug build, so we should turn this into a warning instead.
if ((gEnv) && (gEnv->pLog))
{
if (!gEnv->bIgnoreAllAsserts)
{
gEnv->pLog->LogWarning("%s(%u): Assertion failed - \"%s\"", szFile, line, szCondition);
}
}
if (pIgnore)
{
// avoid showing the same one repeatedly.
*pIgnore = true;
}
return false;
#endif
static const int max_len = 4096;
static char gs_command_str[4096];
static CryLockT<CRYLOCK_RECURSIVE> lock;
gEnv->pSystem->OnAssert(szCondition, gs_szMessage, szFile, line);
size_t file_len = strlen(szFile);
if (!gEnv->bNoAssertDialog && !gEnv->bIgnoreAllAsserts)
{
AZ::NativeUI::AssertAction result;
EBUS_EVENT_RESULT(result, AZ::NativeUI::NativeUIRequestBus, DisplayAssertDialog, gs_szMessage);
switch(result)
{
case AZ::NativeUI::AssertAction::IGNORE_ASSERT:
return false;
case AZ::NativeUI::AssertAction::IGNORE_ALL_ASSERTS:
gEnv->bNoAssertDialog = true;
gEnv->bIgnoreAllAsserts = true;
return false;
case AZ::NativeUI::AssertAction::BREAK:
return true;
default:
break;
}
// For asserts on the Mac always trigger a debug break. Annoying but at least it does not kill the thread like assert() does.
__asm__("int $3");
}
return false;
}
#endif
#endif // CRYINCLUDE_CRYCOMMON_CRYASSERT_MAC_H
+103
View File
@@ -0,0 +1,103 @@
/*
* 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 : Assert dialog box for Mac OS X
#ifndef CRYINCLUDE_CRYCOMMON_CRYASSERT_IOS_H
#define CRYINCLUDE_CRYCOMMON_CRYASSERT_IOS_H
#pragma once
#if defined(USE_CRY_ASSERT) && (defined(IOS)
#include <AzCore/NativeUI/NativeUIRequests.h>
static char gs_szMessage[MAX_PATH];
void CryAssertTrace(const char* szFormat, ...)
{
if (gEnv == 0)
{
return;
}
if (!gEnv->bIgnoreAllAsserts || gEnv->bTesting)
{
if (szFormat == NULL)
{
gs_szMessage[0] = '\0';
}
else
{
va_list args;
va_start(args, szFormat);
vsnprintf(gs_szMessage, sizeof(gs_szMessage), szFormat, args);
va_end(args);
}
}
}
bool CryAssert(const char* szCondition, const char* szFile, unsigned int line, bool* pIgnore)
{
if (!gEnv)
{
return false;
}
#if defined(CRY_ASSERT_DIALOG_ONLY_IN_DEBUG) && !defined(AZ_DEBUG_BUILD)
// we are in a non-debug build, so we should turn this into a warning instead.
if ((gEnv) && (gEnv->pLog))
{
if (!gEnv->bIgnoreAllAsserts)
{
gEnv->pLog->LogWarning("%s(%u): Assertion failed - \"%s\"", szFile, line, szCondition);
}
}
if (pIgnore)
{
// avoid showing the same one repeatedly.
*pIgnore = true;
}
return false;
#endif
gEnv->pSystem->OnAssert(szCondition, gs_szMessage, szFile, line);
if (!gEnv->bNoAssertDialog && !gEnv->bIgnoreAllAsserts)
{
printf("!!ASSERT!!\n\tCondition: %s\n\tMessage : %s\n\tFile : %s\n\tLine : %d", szCondition, gs_szMessage, szFile, line);
AZ::NativeUI::AssertAction result;
EBUS_EVENT_RESULT(result, AZ::NativeUI::NativeUIRequestBus, DisplayAssertDialog, gs_szMessage);
switch(result)
{
case AZ::NativeUI::AssertAction::IGNORE_ASSERT:
return false;
case AZ::NativeUI::AssertAction::IGNORE_ALL_ASSERTS:
gEnv->bNoAssertDialog = true;
gEnv->bIgnoreAllAsserts = true;
return false;
case AZ::NativeUI::AssertAction::BREAK:
return true;
default:
break;
}
}
return false;
}
#endif
#endif // CRYINCLUDE_CRYCOMMON_CRYASSERT_IOS_H
+473
View File
@@ -0,0 +1,473 @@
/*
* 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 : Assert dialog box
#pragma once
#if defined(AZ_RESTRICTED_PLATFORM)
#undef AZ_RESTRICTED_SECTION
#define CRYASSERT_IMPL_H_SECTION_1 1
#define CRYASSERT_IMPL_H_SECTION_2 2
#endif
#if defined(USE_CRY_ASSERT)
#if defined(AZ_RESTRICTED_PLATFORM)
#define AZ_RESTRICTED_SECTION CRYASSERT_IMPL_H_SECTION_1
#include AZ_RESTRICTED_FILE(CryAssert_impl_h)
#endif
#if defined(APPLE)
#if defined(MAC)
#include "CryAssert_Mac.h"
#else
#include "CryAssert_iOS.h"
#endif
#endif
#if defined(LINUX)
#if defined(ANDROID)
#include "CryAssert_Android.h"
#else
#include "CryAssert_Linux.h"
#endif
#endif
#if defined(AZ_RESTRICTED_PLATFORM)
#define AZ_RESTRICTED_SECTION CRYASSERT_IMPL_H_SECTION_2
#include AZ_RESTRICTED_FILE(CryAssert_impl_h)
#elif defined(WIN32)
//-----------------------------------------------------------------------------------------------------
#include <signal.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
//-----------------------------------------------------------------------------------------------------
#define IDD_DIALOG_ASSERT 101
#define IDC_CRYASSERT_EDIT_LINE 1000
#define IDC_CRYASSERT_EDIT_FILE 1001
#define IDC_CRYASSERT_EDIT_CONDITION 1002
#define IDC_CRYASSERT_BUTTON_CONTINUE 1003
#define IDC_CRYASSERT_EDIT_REASON 1004
#define IDC_CRYASSERT_BUTTON_IGNORE 1005
#define IDC_CRYASSERT_BUTTON_STOP 1007
#define IDC_CRYASSERT_BUTTON_BREAK 1008
#define IDC_CRYASSERT_BUTTON_IGNORE_ALL 1009
#define IDC_CRYASSERT_STATIC_TEXT 0
#define DLG_TITLE L"Assertion Failed"
#define DLG_FONT L"MS Sans Serif"
#define DLG_ITEM_TEXT_0 L"Continue"
#define DLG_ITEM_TEXT_1 L"Stop"
#define DLG_ITEM_TEXT_2 L"Info"
#define DLG_ITEM_TEXT_3 L""
#define DLG_ITEM_TEXT_4 L"Line"
#define DLG_ITEM_TEXT_5 L""
#define DLG_ITEM_TEXT_6 L"File"
#define DLG_ITEM_TEXT_7 L"Condition"
#define DLG_ITEM_TEXT_8 L""
#define DLG_ITEM_TEXT_9 L"failed"
#define DLG_ITEM_TEXT_10 L""
#define DLG_ITEM_TEXT_11 L"Reason"
#define DLG_ITEM_TEXT_12 L"Ignore"
#define DLG_ITEM_TEXT_14 L"Break"
#define DLG_ITEM_TEXT_15 L"Ignore All"
#define DLG_NB_ITEM 15
template<int iTitleSize>
struct SDlgItem
{
// If use my struct instead of DLGTEMPLATE, or else (for some strange reason) it is not DWORD aligned !!
DWORD style;
DWORD dwExtendedStyle;
short x;
short y;
short cx;
short cy;
WORD id;
WORD ch;
WORD c;
WCHAR t[iTitleSize];
WORD dummy;
};
#define SDLGITEM(TEXT, V) SDlgItem<sizeof(TEXT) / 2> V;
struct SDlgData
{
DLGTEMPLATE dlt;
WORD _menu;
WORD _class;
WCHAR _title[sizeof(DLG_TITLE) / 2];
WORD pointSize;
WCHAR _font[sizeof(DLG_FONT) / 2];
SDLGITEM(DLG_ITEM_TEXT_0, i0);
SDLGITEM(DLG_ITEM_TEXT_12, i12);
SDLGITEM(DLG_ITEM_TEXT_15, i15);
SDLGITEM(DLG_ITEM_TEXT_14, i14);
SDLGITEM(DLG_ITEM_TEXT_1, i1);
SDLGITEM(DLG_ITEM_TEXT_2, i2);
SDLGITEM(DLG_ITEM_TEXT_3, i3);
SDLGITEM(DLG_ITEM_TEXT_4, i4);
SDLGITEM(DLG_ITEM_TEXT_5, i5);
SDLGITEM(DLG_ITEM_TEXT_6, i6);
SDLGITEM(DLG_ITEM_TEXT_7, i7);
SDLGITEM(DLG_ITEM_TEXT_8, i8);
SDLGITEM(DLG_ITEM_TEXT_9, i9);
SDLGITEM(DLG_ITEM_TEXT_10, i10);
SDLGITEM(DLG_ITEM_TEXT_11, i11);
};
//-----------------------------------------------------------------------------------------------------
static SDlgData g_dialogRC =
{
{DS_SETFOREGROUND | DS_MODALFRAME | DS_3DLOOK | DS_SETFONT | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 0, DLG_NB_ITEM, 0, 0, 330, 134}, 0, 0, DLG_TITLE, 8, DLG_FONT,
{BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 12, 113, 50, 14, IDC_CRYASSERT_BUTTON_CONTINUE, 0xFFFF, 0x0080, DLG_ITEM_TEXT_0, 0},
{BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 66, 113, 50, 14, IDC_CRYASSERT_BUTTON_IGNORE, 0xFFFF, 0x0080, DLG_ITEM_TEXT_12, 0},
{BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 120, 113, 50, 14, IDC_CRYASSERT_BUTTON_IGNORE_ALL, 0xFFFF, 0x0080, DLG_ITEM_TEXT_15, 0},
{BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 214, 113, 50, 14, IDC_CRYASSERT_BUTTON_BREAK, 0xFFFF, 0x0080, DLG_ITEM_TEXT_14, 0},
{BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 268, 113, 50, 14, IDC_CRYASSERT_BUTTON_STOP, 0xFFFF, 0x0080, DLG_ITEM_TEXT_1, 0},
{BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 0, 7, 7, 316, 100, IDC_CRYASSERT_STATIC_TEXT, 0xFFFF, 0x0080, DLG_ITEM_TEXT_2, 0},
{ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_BORDER | WS_CHILD | WS_VISIBLE, 0, 50, 48, 25, 13, IDC_CRYASSERT_EDIT_LINE, 0xFFFF, 0x0081, DLG_ITEM_TEXT_3, 0},
{WS_CHILD | WS_VISIBLE, 0, 14, 50, 14, 8, IDC_CRYASSERT_STATIC_TEXT, 0xFFFF, 0x0082, DLG_ITEM_TEXT_4, 0},
{ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_BORDER | WS_CHILD | WS_VISIBLE, 0, 50, 32, 240, 13, IDC_CRYASSERT_EDIT_FILE, 0xFFFF, 0x0081, DLG_ITEM_TEXT_5, 0},
{WS_CHILD | WS_VISIBLE, 0, 14, 34, 12, 8, IDC_CRYASSERT_STATIC_TEXT, 0xFFFF, 0x0082, DLG_ITEM_TEXT_6, 0},
{WS_CHILD | WS_VISIBLE, 0, 13, 18, 30, 8, IDC_CRYASSERT_STATIC_TEXT, 0xFFFF, 0x0082, DLG_ITEM_TEXT_7, 0},
{ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_BORDER | WS_CHILD | WS_VISIBLE, 0, 50, 16, 240, 13, IDC_CRYASSERT_EDIT_CONDITION, 0xFFFF, 0x0081, DLG_ITEM_TEXT_8, 0},
{WS_CHILD | WS_VISIBLE, 0, 298, 19, 18, 8, IDC_CRYASSERT_STATIC_TEXT, 0xFFFF, 0x0082, DLG_ITEM_TEXT_9, 0},
{ES_LEFT | ES_AUTOHSCROLL | ES_READONLY | WS_BORDER | WS_CHILD | WS_VISIBLE, 0, 50, 67, 240, 13, IDC_CRYASSERT_EDIT_REASON, 0xFFFF, 0x0081, DLG_ITEM_TEXT_10, 0},
{WS_CHILD | WS_VISIBLE, 0, 15, 69, 26, 8, IDC_CRYASSERT_STATIC_TEXT, 0xFFFF, 0x0082, DLG_ITEM_TEXT_11, 0},
};
//-----------------------------------------------------------------------------------------------------
struct SCryAssertInfo
{
const char* pszCondition;
const char* pszFile;
const char* pszMessage;
unsigned int uiLine;
enum
{
BUTTON_CONTINUE,
BUTTON_IGNORE,
BUTTON_IGNORE_ALL,
BUTTON_BREAK,
BUTTON_STOP,
BUTTON_REPORT_AS_BUG,
} btnChosen;
unsigned int uiX;
unsigned int uiY;
};
//-----------------------------------------------------------------------------------------------------
static INT_PTR CALLBACK DlgProc(HWND _hDlg, UINT _uiMsg, WPARAM _wParam, LPARAM _lParam)
{
static SCryAssertInfo* pAssertInfo = NULL;
const UINT WM_USER_SHOWFILE_MESSAGE = (WM_USER + 0x4000);
switch (_uiMsg)
{
case WM_INITDIALOG:
{
pAssertInfo = (SCryAssertInfo*) _lParam;
SetWindowText(GetDlgItem(_hDlg, IDC_CRYASSERT_EDIT_CONDITION), pAssertInfo->pszCondition);
SetWindowText(GetDlgItem(_hDlg, IDC_CRYASSERT_EDIT_FILE), pAssertInfo->pszFile);
// Want to move the cursor on the file text, so that the end of the file is the first thing visible,
// instead of the beginning, which will be the user's depot, and the same for pretty much every file.
// Have to do this delayed, because if it's done in WM_INITDIALOG, it doesn't work.
// PostMessage will add this to the end of the message queue.
PostMessage(_hDlg, WM_USER_SHOWFILE_MESSAGE, 0, 0);
char szLine[MAX_PATH];
sprintf_s(szLine, "%d", pAssertInfo->uiLine);
SetWindowText(GetDlgItem(_hDlg, IDC_CRYASSERT_EDIT_LINE), szLine);
if (pAssertInfo->pszMessage && pAssertInfo->pszMessage[0] != '\0')
{
SetWindowText(GetDlgItem(_hDlg, IDC_CRYASSERT_EDIT_REASON), pAssertInfo->pszMessage);
}
else
{
SetWindowText(GetDlgItem(_hDlg, IDC_CRYASSERT_EDIT_REASON), "No Reason");
}
SetWindowPos(_hDlg, HWND_TOPMOST, pAssertInfo->uiX, pAssertInfo->uiY, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE);
break;
}
case WM_USER_SHOWFILE_MESSAGE:
{
// Still have to delay sending this message, or it won't work for some reason.
// Windows does a whole bunch of stuff behind the scenes. Using PostMessage here seems to work better.
PostMessage(GetDlgItem(_hDlg, IDC_CRYASSERT_EDIT_FILE), EM_SETSEL, strlen(pAssertInfo->pszFile), -1);
break;
}
case WM_COMMAND:
{
switch (LOWORD(_wParam))
{
case IDCANCEL:
case IDC_CRYASSERT_BUTTON_CONTINUE:
{
pAssertInfo->btnChosen = SCryAssertInfo::BUTTON_CONTINUE;
EndDialog(_hDlg, 0);
break;
}
case IDC_CRYASSERT_BUTTON_IGNORE:
{
pAssertInfo->btnChosen = SCryAssertInfo::BUTTON_IGNORE;
EndDialog(_hDlg, 0);
break;
}
case IDC_CRYASSERT_BUTTON_IGNORE_ALL:
{
pAssertInfo->btnChosen = SCryAssertInfo::BUTTON_IGNORE_ALL;
EndDialog(_hDlg, 0);
break;
}
case IDC_CRYASSERT_BUTTON_BREAK:
{
pAssertInfo->btnChosen = SCryAssertInfo::BUTTON_BREAK;
EndDialog(_hDlg, 0);
break;
}
case IDC_CRYASSERT_BUTTON_STOP:
{
pAssertInfo->btnChosen = SCryAssertInfo::BUTTON_STOP;
EndDialog(_hDlg, 1);
break;
}
default:
break;
}
;
break;
}
case WM_DESTROY:
{
if (pAssertInfo)
{
RECT rcWindowBounds;
GetWindowRect(_hDlg, &rcWindowBounds);
pAssertInfo->uiX = rcWindowBounds.left;
pAssertInfo->uiY = rcWindowBounds.top;
}
break;
}
default:
return FALSE;
}
;
return TRUE;
}
//-----------------------------------------------------------------------------------------------------
static char gs_szMessage[MAX_PATH];
//-----------------------------------------------------------------------------------------------------
void CryAssertTrace(const char* _pszFormat, ...)
{
if (gEnv == 0)
{
return;
}
if (!gEnv->bIgnoreAllAsserts || gEnv->bTesting)
{
if (NULL == _pszFormat)
{
gs_szMessage[0] = '\0';
}
else
{
va_list args;
va_start(args, _pszFormat);
vsnprintf_s(gs_szMessage, sizeof(gs_szMessage), _TRUNCATE, _pszFormat, args);
va_end(args);
}
}
}
//-----------------------------------------------------------------------------------------------------
static const char* gs_strRegSubKey = "Software\\Amazon\\Lumberyard\\AssertWindow";
static const char* gs_strRegXValue = "AssertInfoX";
static const char* gs_strRegYValue = "AssertInfoY";
//-----------------------------------------------------------------------------------------------------
void RegistryReadUInt32(const char* _strSubKey, const char* _strRegName, unsigned int* _puiValue, unsigned int _uiDefault)
{
HKEY hKey;
RegCreateKeyEx(HKEY_CURRENT_USER, _strSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
DWORD dwType;
DWORD dwLength = sizeof(DWORD);
if (ERROR_SUCCESS != RegQueryValueEx(hKey, _strRegName, 0, &dwType, (BYTE*) _puiValue, &dwLength))
{
*_puiValue = _uiDefault;
}
RegCloseKey(hKey);
}
//-----------------------------------------------------------------------------------------------------
void RegistryWriteUInt32(const char* _strSubKey, const char* _strRegName, unsigned int _uiValue)
{
HKEY hKey;
RegCreateKeyEx(HKEY_CURRENT_USER, _strSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
RegSetValueEx (hKey, _strRegName, 0, REG_DWORD, (BYTE*) &_uiValue, sizeof(DWORD));
RegCloseKey (hKey);
}
//-----------------------------------------------------------------------------------------------------
class CCursorShowerWithStack
{
public:
void StoreCurrentAndShow()
{
m_numberOfShows = 1;
while (ShowCursor(TRUE) < 0)
{
++m_numberOfShows;
}
}
void RevertToPrevious()
{
while (m_numberOfShows > 0)
{
ShowCursor(FALSE);
--m_numberOfShows;
}
}
private:
int m_numberOfShows;
};
bool CryAssert(const char* _pszCondition, const char* _pszFile, unsigned int _uiLine, bool* _pbIgnore)
{
if (!gEnv)
{
return false;
}
#if defined(CRY_ASSERT_DIALOG_ONLY_IN_DEBUG) && !defined(AZ_DEBUG_BUILD)
// we are in a non-debug build, so we should turn this into a warning instead.
if ((gEnv) && (gEnv->pLog))
{
if (!gEnv->bIgnoreAllAsserts)
{
gEnv->pLog->LogWarning("%s(%u): Assertion failed - \"%s\"", _pszFile, _uiLine, _pszCondition);
}
}
if (_pbIgnore)
{
// avoid showing the same one repeatedly.
*_pbIgnore = true;
}
return false;
#endif
if (!gEnv->bNoAssertDialog && !gEnv->bIgnoreAllAsserts)
{
SCryAssertInfo assertInfo;
assertInfo.pszCondition = _pszCondition;
assertInfo.pszFile = _pszFile;
assertInfo.pszMessage = gs_szMessage;
assertInfo.uiLine = _uiLine;
assertInfo.btnChosen = SCryAssertInfo::BUTTON_CONTINUE;
gEnv->pSystem->SetAssertVisible(true);
RegistryReadUInt32(gs_strRegSubKey, gs_strRegXValue, &assertInfo.uiX, 10);
RegistryReadUInt32(gs_strRegSubKey, gs_strRegYValue, &assertInfo.uiY, 10);
CCursorShowerWithStack cursorShowerWithStack;
cursorShowerWithStack.StoreCurrentAndShow();
DialogBoxIndirectParam(GetModuleHandle(NULL), (DLGTEMPLATE*) &g_dialogRC, GetDesktopWindow(), DlgProc, (LPARAM) &assertInfo);
cursorShowerWithStack.RevertToPrevious();
RegistryWriteUInt32(gs_strRegSubKey, gs_strRegXValue, assertInfo.uiX);
RegistryWriteUInt32(gs_strRegSubKey, gs_strRegYValue, assertInfo.uiY);
gEnv->pSystem->SetAssertVisible(false);
switch (assertInfo.btnChosen)
{
case SCryAssertInfo::BUTTON_IGNORE:
*_pbIgnore = true;
break;
case SCryAssertInfo::BUTTON_IGNORE_ALL:
gEnv->bIgnoreAllAsserts = true;
break;
case SCryAssertInfo::BUTTON_BREAK:
return true;
case SCryAssertInfo::BUTTON_STOP:
raise(SIGABRT);
exit(-1);
case SCryAssertInfo::BUTTON_REPORT_AS_BUG:
if (gEnv && gEnv->pSystem)
{
const char* pszSafeMessage = (assertInfo.pszMessage && assertInfo.pszMessage[0]) ? assertInfo.pszMessage : "<no reason>";
gEnv->pSystem->ReportBug("Assert: %s - %s", assertInfo.pszCondition, pszSafeMessage);
}
break;
}
}
if (gEnv && gEnv->pSystem)
{
// this also can cause fatal / shutdown behavior:
gEnv->pSystem->OnAssert(_pszCondition, gs_szMessage, _pszFile, _uiLine);
}
return false;
}
//-----------------------------------------------------------------------------------------------------
#endif
#endif
//-----------------------------------------------------------------------------------------------------
+57
View File
@@ -0,0 +1,57 @@
/*
* 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.
// This contains compiled code that is used by other projects in the solution.
// Because we don't want static DLL dependencies, the CryCommon project is not compiled into a library.
// Instead, this .cpp file is included in every project which needs it.
// But we also include it in the CryCommon project (disabled in the build),
// so that CryCommon can have the same editable settings as other projects.
// Set this to 1 to get an output of some pre-defined compiler symbols.
#if 0
#ifdef _WIN32
#pragma message("_WIN32")
#endif
#ifdef _WIN64
#pragma message("_WIN64")
#endif
#ifdef _M_IX86
#pragma message("_M_IX86")
#endif
#ifdef _M_PPC
#pragma message("_M_PPC")
#endif
#ifdef _DEBUG
#pragma message("_DEBUG")
#endif
#ifdef _DLL
#pragma message("_DLL")
#endif
#ifdef _USRDLL
#pragma message("_USRDLL")
#endif
#ifdef _MT
#pragma message("_MT")
#endif
#endif
#include <AzCore/PlatformIncl.h>
#include "TypeInfo_impl.h"
+214
View File
@@ -0,0 +1,214 @@
/*
* 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.
#pragma once
#include "BaseTypes.h"
// CRC-32
//
// Polynomial:
// 0x04C11DB7
// x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
//
// Validation:
// CCrc32::Compute("123456789") == 0xCBF43926
//
// Examples of using:
//
// printf("crc32: %08x\n", (unsigned)CCrc32::Compute(ptr, size));
//
// CCrc32 crc;
// crc.Add(ptr0, size0);
// crc.Add(ptr1, size1);
// printf("crc32: %08x\n", (unsigned)crc.Get());
class CCrc32
{
public:
static uint32 Compute(const void* const pData, const size_t sizeInBytes)
{
CCrc32 c;
c.Add(pData, sizeInBytes);
return c.Get();
}
static uint32 Compute(const char* const szData)
{
CCrc32 c;
c.Add(szData);
return c.Get();
}
static uint32 ComputeLowercase(const char* const pData, const size_t sizeInBytes)
{
CCrc32 c;
c.AddLowercase(pData, sizeInBytes);
return c.Get();
}
static uint32 ComputeLowercase(const char* const szData)
{
CCrc32 c;
c.AddLowercase(szData);
return c.Get();
}
CCrc32()
: m_crc(0xFFFFffff)
, m_pTable(GetTable())
{
}
CCrc32(unsigned int initializer)
: m_crc(initializer)
, m_pTable(GetTable())
{
}
void Reset()
{
m_crc = 0xFFFFffff;
}
uint32 Get() const
{
return ~m_crc;
}
unsigned int Add(const void* const pData, size_t sizeInBytes)
{
const uint8* p = (const uint8*)pData;
while (sizeInBytes--)
{
m_crc = (m_crc >> 8) ^ m_pTable[(m_crc & 0xFF) ^ (*p++)];
}
return Get();
}
unsigned int Add(const char* szData)
{
while (*szData)
{
m_crc = (m_crc >> 8) ^ m_pTable[(m_crc & 0xFF) ^ uint8(*szData++)];
}
return Get();
}
#if defined(CRY_TMP_ASCII_TO_LOWER)
# error CRY_TMP_ASCII_TO_LOWER already defined
#endif
#define CRY_TMP_ASCII_TO_LOWER(c) uint8(((c) <= 'Z' && (c) >= 'A') ? (c) + ('a' - 'A') : (c))
unsigned int AddLowercase(const char* pData, size_t sizeInBytes)
{
while (sizeInBytes--)
{
const uint8 c = *pData++;
m_crc = (m_crc >> 8) ^ m_pTable[(m_crc & 0xFF) ^ CRY_TMP_ASCII_TO_LOWER(c)];
}
return Get();
}
unsigned int AddLowercase(const char* szData)
{
while (*szData)
{
const uint8 c = *szData++;
m_crc = (m_crc >> 8) ^ m_pTable[(m_crc & 0xFF) ^ CRY_TMP_ASCII_TO_LOWER(c)];
}
return Get();
}
#undef CRY_TMP_ASCII_TO_LOWER
private:
static const uint32* GetTable()
{
static const uint32 table[256] =
{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
return &table[0];
}
private:
uint32 m_crc;
const uint32* const m_pTable;
};
// eof
File diff suppressed because it is too large Load Diff
+299
View File
@@ -0,0 +1,299 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYCOMMON_CRYENDIAN_H
#define CRYINCLUDE_CRYCOMMON_CRYENDIAN_H
#pragma once
#include <BaseTypes.h>
//////////////////////////////////////////////////////////////////////////
// Endian support
//////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
// NEED_ENDIAN_SWAP is an older define still used in several places to toggle endian swapping.
// It is only used when reading files which are assumed to be little-endian.
// For legacy support, define it to swap on big endian platforms.
/////////////////////////////////////////////////////////////////////////////////////
typedef bool EEndian;
#if defined(SYSTEM_IS_LITTLE_ENDIAN)
# undef SYSTEM_IS_LITTLE_ENDIAN
#endif
#if defined(SYSTEM_IS_BIG_ENDIAN)
# undef SYSTEM_IS_BIG_ENDIAN
#endif
#if 0 // no big-endian platforms right now, but keep the code
// Big-endian platform
# define SYSTEM_IS_LITTLE_ENDIAN 0
# define SYSTEM_IS_BIG_ENDIAN 1
#else
// Little-endian platform
# define SYSTEM_IS_LITTLE_ENDIAN 1
# define SYSTEM_IS_BIG_ENDIAN 0
#endif
#if SYSTEM_IS_BIG_ENDIAN
// Big-endian platform. Swap to/from little.
#define eBigEndian false
#define eLittleEndian true
#define NEED_ENDIAN_SWAP
#else
// Little-endian platform. Swap to/from big.
#define eLittleEndian false
#define eBigEndian true
#undef NEED_ENDIAN_SWAP
#endif
enum EEndianness
{
eEndianness_Little,
eEndianness_Big,
#if SYSTEM_IS_BIG_ENDIAN
eEndianness_Native = eEndianness_Big,
eEndianness_NonNative = eEndianness_Little,
#else
eEndianness_Native = eEndianness_Little,
eEndianness_NonNative = eEndianness_Big,
#endif
};
// Legacy macros
#define GetPlatformEndian() false
/////////////////////////////////////////////////////////////////////////////////////
inline bool IsSystemLittleEndian()
{
const int a = 1;
return 1 == *(const char*)&a;
}
/////////////////////////////////////////////////////////////////////////////////////
// SwapEndian function, using TypeInfo.
struct CTypeInfo;
void SwapEndian(const CTypeInfo& Info, size_t nSizeCheck, void* pData, size_t nCount = 1, bool bWriting = false);
// Default template utilizes TypeInfo.
template<class T>
inline void SwapEndianBase(T* t, size_t nCount = 1, bool bWriting = false)
{
SwapEndian(TypeInfo(t), sizeof(T), t, nCount, bWriting);
}
/////////////////////////////////////////////////////////////////////////////////////
// SwapEndianBase functions.
// Always swap the data (the functions named SwapEndian swap based on an optional bSwapEndian parameter).
// The bWriting parameter must be specified in general when the output is for writing,
// but it matters only for types with bitfields.
// Overrides for base types.
template<>
inline void SwapEndianBase(char* p, size_t nCount, bool bWriting)
{
(void)p;
(void)nCount;
(void)bWriting;
}
template<>
inline void SwapEndianBase(uint8* p, size_t nCount, bool bWriting)
{
(void)p;
(void)nCount;
(void)bWriting;
}
template<>
inline void SwapEndianBase(int8* p, size_t nCount, bool bWriting)
{
(void)p;
(void)nCount;
(void)bWriting;
}
template<>
inline void SwapEndianBase(uint16* p, size_t nCount, bool bWriting)
{
(void)bWriting;
for (; nCount-- > 0; p++)
{
*p = (uint16) (((*p >> 8) + (*p << 8)) & 0xFFFF);
}
}
template<>
inline void SwapEndianBase(int16* p, size_t nCount, bool bWriting)
{
(void)bWriting;
SwapEndianBase((uint16*)p, nCount);
}
template<>
inline void SwapEndianBase(uint32* p, size_t nCount, bool bWriting)
{
(void)bWriting;
for (; nCount-- > 0; p++)
{
*p = (*p >> 24) + ((*p >> 8) & 0xFF00) + ((*p & 0xFF00) << 8) + (*p << 24);
}
}
template<>
inline void SwapEndianBase(int32* p, size_t nCount, bool bWriting)
{
(void)bWriting;
SwapEndianBase((uint32*)p, nCount);
}
template<>
inline void SwapEndianBase(float* p, size_t nCount, bool bWriting)
{
(void)bWriting;
SwapEndianBase((uint32*)p, nCount);
}
template<>
inline void SwapEndianBase(uint64* p, size_t nCount, bool bWriting)
{
(void)bWriting;
for (; nCount-- > 0; p++)
{
*p = (*p >> 56) + ((*p >> 40) & 0xFF00) + ((*p >> 24) & 0xFF0000) + ((*p >> 8) & 0xFF000000)
+ ((*p & 0xFF000000) << 8) + ((*p & 0xFF0000) << 24) + ((*p & 0xFF00) << 40) + (*p << 56);
}
}
template<>
inline void SwapEndianBase(int64* p, size_t nCount, bool bWriting)
{
(void)bWriting;
SwapEndianBase((uint64*)p, nCount);
}
template<>
inline void SwapEndianBase(double* p, size_t nCount, bool bWriting)
{
(void)bWriting;
SwapEndianBase((uint64*)p, nCount);
}
//---------------------------------------------------------------------------
// SwapEndian functions.
// bSwapEndian argument optional, and defaults to swapping from LittleEndian format.
template<class T>
inline void SwapEndian(T* t, size_t nCount, bool bSwapEndian = eLittleEndian)
{
if (bSwapEndian)
{
SwapEndianBase(t, nCount);
}
}
// Specify int and uint as well as size_t, to resolve overload ambiguities.
template<class T>
inline void SwapEndian(T* t, int nCount, bool bSwapEndian = eLittleEndian)
{
if (bSwapEndian)
{
SwapEndianBase(t, nCount);
}
}
#if defined(PLATFORM_64BIT)
template<class T>
inline void SwapEndian(T* t, unsigned int nCount, bool bSwapEndian = eLittleEndian)
{
if (bSwapEndian)
{
SwapEndianBase(t, nCount);
}
}
#endif
template<class T>
inline void SwapEndian(T& t, bool bSwapEndian = eLittleEndian)
{
if (bSwapEndian)
{
SwapEndianBase(&t, 1);
}
}
template<class T>
inline T SwapEndianValue(T t, bool bSwapEndian = eLittleEndian)
{
if (bSwapEndian)
{
SwapEndianBase(&t, 1);
}
return t;
}
//---------------------------------------------------------------------------
// Object-oriented data extraction for endian-swapping reading.
template<class T, class D>
inline T* StepData(D*& pData, size_t nCount, bool bSwapEndian)
{
T* Elems = (T*)pData;
SwapEndian(Elems, nCount, bSwapEndian);
pData = (D*)((T*)pData + nCount);
return Elems;
}
template<class T, class D>
inline T* StepData(D*& pData, bool bSwapEndian)
{
return StepData<T, D>(pData, 1, bSwapEndian);
}
template<class T, class D>
inline void StepData(T*& Result, D*& pData, size_t nCount, bool bSwapEndian)
{
Result = StepData<T, D>(pData, nCount, bSwapEndian);
}
template<class T, class D>
inline void StepDataCopy(T* Dest, D*& pData, size_t nCount, bool bSwapEndian)
{
memcpy(Dest, pData, nCount * sizeof(T));
SwapEndian(Dest, nCount, bSwapEndian);
pData = (D*)((T*)pData + nCount);
}
template<class T, class D>
inline void StepDataWrite(D*& pDest, const T* aSrc, size_t nCount, bool bSwapEndian)
{
memcpy(pDest, aSrc, nCount * sizeof(T));
if (bSwapEndian)
{
SwapEndianBase((T*)pDest, nCount, true);
}
(T*&)pDest += nCount;
}
template<class T, class D>
inline void StepDataWrite(D*& pDest, const T& Src, bool bSwapEndian)
{
StepDataWrite(pDest, &Src, 1, bSwapEndian);
}
#endif // CRYINCLUDE_CRYCOMMON_CRYENDIAN_H
@@ -0,0 +1,77 @@
/*
* 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 : declaration of struct CryEngineDecalInfo.
// Note:
// 3D Engine and Character Animation subsystems (as well as perhaps
// some others) transfer data about the decals that need to be spawned
// via this structure. This is to avoid passing many parameters through
// each function call, and to save on copying these parameters when just
// simply passing the structure from one function to another.
#ifndef CRYINCLUDE_CRYCOMMON_CRYENGINEDECALINFO_H
#define CRYINCLUDE_CRYCOMMON_CRYENGINEDECALINFO_H
#pragma once
#include "Cry_Math.h"
// Summary:
// Structure containing common parameters that describe a decal
struct SDecalOwnerInfo
{
SDecalOwnerInfo() { memset(this, 0, sizeof(*this)); nRenderNodeSlotId = nRenderNodeSlotSubObjectId = -1; }
struct IStatObj* GetOwner(Matrix34A& objMat);
struct IRenderNode* pRenderNode; // Owner (decal will be attached to or wrapped around of this object)
PodArray<struct SRNInfo>* pDecalReceivers;
int nRenderNodeSlotId; // is set internally by 3dengine
int nRenderNodeSlotSubObjectId; // is set internally by 3dengine
int nMatID;
};
struct CryEngineDecalInfo
{
SDecalOwnerInfo ownerInfo;
Vec3 vPos; // Decal position (world coordinates)
Vec3 vNormal; // Decal/face normal
float fSize; // Decal size
float fLifeTime; // Decal life time (in seconds)
float fAngle; // Angle of rotation
struct IStatObj* pIStatObj; // Decal geometry
Vec3 vHitDirection; // Direction from weapon/player position to decal position (bullet direction)
float fGrowTime, fGrowTimeAlpha;// Used for blood pools
unsigned int nGroupId; // Used for multi-component decals
bool bSkipOverlappingTest; // Always spawn decals even if there are a lot of other decals in same place
bool bAssemble; // Assemble to bigger decals if more than 1 decal is on the same place
bool bForceEdge; // force the decal to the nearest edge of the owner mesh and project it accordingly
bool bForceSingleOwner; // Do not attempt to cast the decal into the environment even if it's large enough
bool bDeferred;
uint8 sortPrio;
char szMaterialName[_MAX_PATH]; // name of material used for rendering the decal (in favor of szTextureName/nTid and the default decal shader)
bool preventDecalOnGround; // mainly for decal placement support
const Matrix33* pExplicitRightUpFront; // mainly for decal placement support
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const{}
// the constructor fills in some non-obligatory fields; the other fields must be filled in by the client
CryEngineDecalInfo ()
{
memset(this, 0, sizeof(*this));
ownerInfo.nRenderNodeSlotId = ownerInfo.nRenderNodeSlotSubObjectId = -1;
sortPrio = 255;
}
};
#endif // CRYINCLUDE_CRYCOMMON_CRYENGINEDECALINFO_H
@@ -0,0 +1,96 @@
/*
* 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 : Part of CryEngine's extension framework.
#ifndef CRYINCLUDE_CRYEXTENSION_CRYCREATECLASSINSTANCE_H
#define CRYINCLUDE_CRYEXTENSION_CRYCREATECLASSINSTANCE_H
#pragma once
#include "ICryUnknown.h"
#include "ICryFactory.h"
#include "ICryFactoryRegistry.h"
#include <ISystem.h> // <> required for Interfuscator
template <class T>
bool CryCreateClassInstance(const CryClassID& cid, AZStd::shared_ptr<T>& p)
{
p = AZStd::shared_ptr<T>();
ICryFactoryRegistry* pFactoryReg = gEnv->pSystem->GetCryFactoryRegistry();
if (pFactoryReg)
{
ICryFactory* pFactory = pFactoryReg->GetFactory(cid);
if (pFactory && pFactory->ClassSupports(cryiidof<T>()))
{
ICryUnknownPtr pUnk = pFactory->CreateClassInstance();
AZStd::shared_ptr<T> pT = cryinterface_cast<T>(pUnk);
if (pT)
{
p = pT;
}
}
}
return p.get() != NULL;
}
template <class T>
bool CryCreateClassInstance(const char* cname, AZStd::shared_ptr<T>& p)
{
p = AZStd::shared_ptr<T>();
ICryFactoryRegistry* pFactoryReg = gEnv->pSystem->GetCryFactoryRegistry();
if (pFactoryReg)
{
ICryFactory* pFactory = pFactoryReg->GetFactory(cname);
if (pFactory != NULL && pFactory->ClassSupports(cryiidof<T>()))
{
ICryUnknownPtr pUnk = pFactory->CreateClassInstance();
AZStd::shared_ptr<T> pT = cryinterface_cast<T>(pUnk);
if (pT)
{
p = pT;
}
}
}
return p.get() != NULL;
}
template <class T>
bool CryCreateClassInstanceForInterface(const CryInterfaceID& iid, AZStd::shared_ptr<T>& p)
{
p = AZStd::shared_ptr<T>();
ICryFactoryRegistry* pFactoryReg = gEnv->pSystem->GetCryFactoryRegistry();
if (pFactoryReg)
{
size_t numFactories = 1;
ICryFactory* pFactory = 0;
pFactoryReg->IterateFactories(iid, &pFactory, numFactories);
if (numFactories == 1 && pFactory)
{
ICryUnknownPtr pUnk = pFactory->CreateClassInstance();
AZStd::shared_ptr<T> pT = cryinterface_cast<T>(pUnk);
if (pT)
{
p = pT;
}
}
}
return p.get() != NULL;
}
#endif // CRYINCLUDE_CRYEXTENSION_CRYCREATECLASSINSTANCE_H
@@ -0,0 +1,123 @@
/*
* 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 : Part of CryEngine's extension framework.
#ifndef CRYINCLUDE_CRYEXTENSION_CRYGUID_H
#define CRYINCLUDE_CRYEXTENSION_CRYGUID_H
#pragma once
#include "Serialization/IArchive.h"
#include "Random.h"
#include <functional>
struct CryGUID
{
uint64 hipart;
uint64 lopart;
// !!! Do NOT turn CryGUID into a non-aggregate !!!
// It will prevent inlining and type list unrolling opportunities within
// cryinterface_cast<T>() and cryiidof<T>(). As such prevent constructors,
// non-public members, base classes and virtual functions!
//CryGUID() : hipart(0), lopart(0) {}
//CryGUID(uint64 h, uint64 l) : hipart(h), lopart(l) {}
static CryGUID Construct(const uint64& hipart, const uint64& lopart)
{
CryGUID guid = {hipart, lopart};
return guid;
}
static CryGUID Create()
{
uint64 lopart = 0;
uint64 hipart = 0;
while (lopart == 0 || hipart == 0)
{
const uint32 a = cry_random_uint32();
const uint32 b = cry_random_uint32();
const uint32 c = cry_random_uint32();
const uint32 d = cry_random_uint32();
lopart = (uint64)a | ((uint64)b << 32);
hipart = (uint64)c | ((uint64)d << 32);
}
return Construct(lopart, hipart);
}
static CryGUID Null()
{
return Construct(0, 0);
}
bool operator ==(const CryGUID& rhs) const {return hipart == rhs.hipart && lopart == rhs.lopart; }
bool operator !=(const CryGUID& rhs) const {return hipart != rhs.hipart || lopart != rhs.lopart; }
bool operator <(const CryGUID& rhs) const {return hipart == rhs.hipart ? lopart < rhs.lopart : hipart < rhs.hipart; }
void Serialize(Serialization::IArchive& ar)
{
if (ar.IsInput())
{
uint32 dwords[4];
ar(dwords, "guid");
lopart = (((uint64)dwords[1]) << 32) | (uint64)dwords[0];
hipart = (((uint64)dwords[3]) << 32) | (uint64)dwords[2];
}
else
{
uint32 guid[4] = {
(uint32)(lopart & 0xFFFFFFFF), (uint32)((lopart >> 32) & 0xFFFFFFFF),
(uint32)(hipart & 0xFFFFFFFF), (uint32)((hipart >> 32) & 0xFFFFFFFF)
};
ar(guid, "guid");
}
}
};
// This is only used by the editor where we use C++ 11.
namespace std
{
template<>
struct hash<CryGUID>
{
public:
size_t operator()(const CryGUID& guid) const
{
std::hash<uint64> hasher;
return hasher(guid.lopart) ^ hasher(guid.hipart);
}
};
}
namespace AZStd
{
template<>
struct hash<CryGUID>
{
public:
size_t operator()(const CryGUID& guid) const
{
std::hash<CryGUID> hasher;
return hasher(guid);
}
};
}
#define MAKE_CRYGUID(high, low) CryGUID::Construct((uint64) high##LL, (uint64) low##LL)
#endif // CRYINCLUDE_CRYEXTENSION_CRYGUID_H
@@ -0,0 +1,29 @@
/*
* 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 : Part of CryEngine's extension framework.
#ifndef CRYINCLUDE_CRYEXTENSION_CRYTYPEID_H
#define CRYINCLUDE_CRYEXTENSION_CRYTYPEID_H
#pragma once
#include "CryGUID.h"
typedef CryGUID CryInterfaceID;
typedef CryGUID CryClassID;
#endif // CRYINCLUDE_CRYEXTENSION_CRYTYPEID_H
@@ -0,0 +1,41 @@
/*
* 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 : Part of CryEngine's extension framework.
#ifndef CRYINCLUDE_CRYEXTENSION_ICRYFACTORY_H
#define CRYINCLUDE_CRYEXTENSION_ICRYFACTORY_H
#pragma once
#include "CryTypeID.h"
#include <SmartPointersHelpers.h>
struct ICryUnknown;
DECLARE_SMART_POINTERS(ICryUnknown);
struct ICryFactory
{
virtual const char* GetName() const = 0;
virtual const CryClassID& GetClassID() const = 0;
virtual bool ClassSupports(const CryInterfaceID& iid) const = 0;
virtual void ClassSupports(const CryInterfaceID*& pIIDs, size_t& numIIDs) const = 0;
virtual ICryUnknownPtr CreateClassInstance() const = 0;
protected:
// prevent explicit destruction from client side (delete, shared_ptr, etc)
virtual ~ICryFactory() {}
};
#endif // CRYINCLUDE_CRYEXTENSION_ICRYFACTORY_H
@@ -0,0 +1,56 @@
/*
* 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 : Part of CryEngine's extension framework.
#ifndef CRYINCLUDE_CRYEXTENSION_ICRYFACTORYREGISTRY_H
#define CRYINCLUDE_CRYEXTENSION_ICRYFACTORYREGISTRY_H
#pragma once
#include "CryTypeID.h"
struct ICryFactory;
struct ICryFactoryRegistry
{
virtual ICryFactory* GetFactory(const char* cname) const = 0;
virtual ICryFactory* GetFactory(const CryClassID& cid) const = 0;
/**
* Iterates all factories implementing the interface specified by \p iid.
* \param[in] iid ID of the interface to iterate. Often procured using cryiidof<...>().
* \param[out] pFactories A pointer of the array of factories to fill in. May be nullptr (see below).
* \param[in] Size (in elements) of the pFactories array [out] Number of elements actually written to pFactories or, when pFactories is null, the number of elements that would be written if sufficient storage was available.
*
* Example:
* \code{.cpp}
* size_t factoryCount = 0;
* // Assigns the number of found factories to factoryCount
* factoryRegistry->IterateFactories(cryiidof<TPointer>(), 0, factoryCount);
* // Allocate an array of the proper length on the stack
* ICryFactory** factories = static_cast<ICryFactory**>(alloca(sizeof(ICryFactory*) * factoryCount);
* // Fill in factories with factoryCount results.
* factoryRegistry->IterateFactories(cryiidof<TPointer>(), factories, factoryCount);
* \endcode
*/
virtual void IterateFactories(const CryInterfaceID& iid, ICryFactory** pFactories, size_t& numFactories) const = 0;
protected:
// prevent explicit destruction from client side (delete, shared_ptr, etc)
virtual ~ICryFactoryRegistry() {}
};
#endif // CRYINCLUDE_CRYEXTENSION_ICRYFACTORYREGISTRY_H
@@ -0,0 +1,224 @@
/*
* 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 : Part of CryEngine's extension framework.
#ifndef CRYINCLUDE_CRYEXTENSION_ICRYUNKNOWN_H
#define CRYINCLUDE_CRYEXTENSION_ICRYUNKNOWN_H
#pragma once
#include "CryTypeID.h"
#include <SmartPointersHelpers.h>
struct ICryFactory;
struct ICryUnknown;
namespace InterfaceCastSemantics
{
template <class T>
const CryInterfaceID& cryiidof()
{
return T::IID();
}
#define _BEFRIEND_CRYIIDOF() \
template <class T> \
friend const CryInterfaceID&InterfaceCastSemantics::cryiidof();
template <class Dst, class Src>
Dst* cryinterface_cast(Src* p)
{
return static_cast<Dst*>(p ? p->QueryInterface(cryiidof<Dst>()) : 0);
}
template <class Dst, class Src>
Dst* cryinterface_cast(const Src* p)
{
return static_cast<const Dst*>(p ? p->QueryInterface(cryiidof<Dst>()) : 0);
}
namespace Internal
{
template <class Dst, class Src>
struct cryinterface_cast_shared_ptr_helper;
template <class Dst, class Src>
struct cryinterface_cast_shared_ptr_helper
{
static AZStd::shared_ptr<Dst> Op(const AZStd::shared_ptr<Src>& p)
{
Dst* dp = cryinterface_cast<Dst>(p.get());
return dp ? AZStd::shared_ptr<Dst>(p, dp) : AZStd::shared_ptr<Dst>();
}
};
template <class Src>
struct cryinterface_cast_shared_ptr_helper<ICryUnknown, Src>
{
static AZStd::shared_ptr<ICryUnknown> Op(const AZStd::shared_ptr<Src>& p)
{
ICryUnknown* dp = cryinterface_cast<ICryUnknown>(p.get());
return dp ? AZStd::shared_ptr<ICryUnknown>(*((const AZStd::shared_ptr<ICryUnknown>*) & p), dp) : AZStd::shared_ptr<ICryUnknown>();
}
};
template <class Src>
struct cryinterface_cast_shared_ptr_helper<const ICryUnknown, Src>
{
static AZStd::shared_ptr<const ICryUnknown> Op(const AZStd::shared_ptr<Src>& p)
{
const ICryUnknown* dp = cryinterface_cast<const ICryUnknown>(p.get());
return dp ? AZStd::shared_ptr<const ICryUnknown>(*((const AZStd::shared_ptr<const ICryUnknown>*) & p), dp) : AZStd::shared_ptr<const ICryUnknown>();
}
};
} // namespace Internal
template <class Dst, class Src>
AZStd::shared_ptr<Dst> cryinterface_cast(const AZStd::shared_ptr<Src>& p)
{
return Internal::cryinterface_cast_shared_ptr_helper<Dst, Src>::Op(p);
}
#define _BEFRIEND_CRYINTERFACE_CAST() \
template <class Dst, class Src> \
friend Dst * InterfaceCastSemantics::cryinterface_cast(Src*); \
template <class Dst, class Src> \
friend Dst * InterfaceCastSemantics::cryinterface_cast(const Src*); \
template <class Dst, class Src> \
friend AZStd::shared_ptr<Dst> InterfaceCastSemantics::cryinterface_cast(const AZStd::shared_ptr<Src>&);
} // namespace InterfaceCastSemantics
using InterfaceCastSemantics::cryiidof;
using InterfaceCastSemantics::cryinterface_cast;
template <class S, class T>
bool CryIsSameClassInstance(S* p0, T* p1)
{
return static_cast<const void*>(p0) == static_cast<const void*>(p1) || cryinterface_cast<const ICryUnknown>(p0) == cryinterface_cast<const ICryUnknown>(p1);
}
template <class S, class T>
bool CryIsSameClassInstance(const AZStd::shared_ptr<S>& p0, T* p1)
{
return CryIsSameClassInstance(p0.get(), p1);
}
template <class S, class T>
bool CryIsSameClassInstance(S* p0, const AZStd::shared_ptr<T>& p1)
{
return CryIsSameClassInstance(p0, p1.get());
}
template <class S, class T>
bool CryIsSameClassInstance(const AZStd::shared_ptr<S>& p0, const AZStd::shared_ptr<T>& p1)
{
return CryIsSameClassInstance(p0.get(), p1.get());
}
namespace CompositeQuerySemantics
{
template <class Src>
AZStd::shared_ptr<ICryUnknown> crycomposite_query(Src* p, const char* name, bool* pExposed = 0)
{
void* pComposite = p ? p->QueryComposite(name) : 0;
pExposed ? *pExposed = pComposite != 0 : 0;
return pComposite ? *static_cast<AZStd::shared_ptr<ICryUnknown>*>(pComposite) : AZStd::shared_ptr<ICryUnknown>();
}
template <class Src>
AZStd::shared_ptr<const ICryUnknown> crycomposite_query(const Src* p, const char* name, bool* pExposed = 0)
{
void* pComposite = p ? p->QueryComposite(name) : 0;
pExposed ? *pExposed = pComposite != 0 : 0;
return pComposite ? *static_cast<AZStd::shared_ptr<const ICryUnknown>*>(pComposite) : AZStd::shared_ptr<const ICryUnknown>();
}
template <class Src>
AZStd::shared_ptr<ICryUnknown> crycomposite_query(const AZStd::shared_ptr<Src>& p, const char* name, bool* pExposed = 0)
{
return crycomposite_query(p.get(), name, pExposed);
}
template <class Src>
AZStd::shared_ptr<const ICryUnknown> crycomposite_query(const AZStd::shared_ptr<const Src>& p, const char* name, bool* pExposed = 0)
{
return crycomposite_query(p.get(), name, pExposed);
}
#define _BEFRIEND_CRYCOMPOSITE_QUERY() \
template <class Src> \
friend AZStd::shared_ptr<ICryUnknown> CompositeQuerySemantics::crycomposite_query(Src*, const char*, bool*); \
template <class Src> \
friend AZStd::shared_ptr<const ICryUnknown> CompositeQuerySemantics::crycomposite_query(const Src*, const char*, bool*); \
template <class Src> \
friend AZStd::shared_ptr<ICryUnknown> CompositeQuerySemantics::crycomposite_query(const AZStd::shared_ptr<Src>&, const char*, bool*); \
template <class Src> \
friend AZStd::shared_ptr<const ICryUnknown> CompositeQuerySemantics::crycomposite_query(const AZStd::shared_ptr<const Src>&, const char*, bool*);
} // namespace CompositeQuerySemantics
using CompositeQuerySemantics::crycomposite_query;
#define _BEFRIEND_MAKE_SHARED() \
template <class T> \
friend class AZStd::Internal::sp_ms_deleter; \
template <class T> \
friend AZStd::shared_ptr<T> AZStd::make_shared(); \
template <class T, class A> \
friend AZStd::shared_ptr<T> AZStd::allocate_shared(A const& a);
// prevent explicit destruction from client side
#define _PROTECTED_DTOR(iname) \
protected: \
virtual ~iname() {}
// Befriending cryinterface_cast<T>() and crycomposite_query() via CRYINTERFACE_DECLARE is actually only needed for ICryUnknown
// since QueryInterface() and QueryComposite() are usually not redeclared in derived interfaces but it doesn't hurt either
#define CRYINTERFACE_DECLARE(iname, iidHigh, iidLow) \
_BEFRIEND_CRYIIDOF() \
_BEFRIEND_CRYINTERFACE_CAST() \
_BEFRIEND_CRYCOMPOSITE_QUERY() \
_BEFRIEND_MAKE_SHARED() \
_PROTECTED_DTOR(iname) \
\
private: \
static const CryInterfaceID& IID() \
{ \
static const CryInterfaceID iid = {(uint64) iidHigh##LL, (uint64) iidLow##LL}; \
return iid; \
} \
public:
struct ICryUnknown
{
CRYINTERFACE_DECLARE(ICryUnknown, 0x1000000010001000, 0x1000100000000000)
virtual ICryFactory * GetFactory() const = 0;
protected:
virtual void* QueryInterface(const CryInterfaceID& iid) const = 0;
virtual void* QueryComposite(const char* name) const = 0;
};
DECLARE_SMART_POINTERS(ICryUnknown);
#endif // CRYINCLUDE_CRYEXTENSION_ICRYUNKNOWN_H
@@ -0,0 +1,461 @@
/*
* 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 : Part of CryEngine's extension framework.
#ifndef CRYINCLUDE_CRYEXTENSION_IMPL_CLASSWEAVER_H
#define CRYINCLUDE_CRYEXTENSION_IMPL_CLASSWEAVER_H
#pragma once
#include "TypeList.h"
#include "Conversion.h"
#include "RegFactoryNode.h"
#include "../ICryUnknown.h"
#include "../ICryFactory.h"
#include <AzCore/Memory/Memory.h>
namespace CW
{
namespace Internal
{
template <class Dst>
struct InterfaceCast;
template <class Dst>
struct InterfaceCast
{
template <class T>
static void* Op(T* p)
{
return (Dst*) p;
}
};
template <>
struct InterfaceCast<ICryUnknown>
{
template <class T>
static void* Op(T* p)
{
return const_cast<ICryUnknown*>(static_cast<const ICryUnknown*>(static_cast<const void*>(p)));
}
};
}
template <class TList>
struct InterfaceCast;
template <>
struct InterfaceCast<TL::NullType>
{
template <class T>
static void* Op(T*, const CryInterfaceID&)
{
return 0;
}
};
template <class Head, class Tail>
struct InterfaceCast<TL::Typelist<Head, Tail> >
{
template <class T>
static void* Op(T* p, const CryInterfaceID& iid)
{
if (cryiidof<Head>() == iid)
{
return Internal::InterfaceCast<Head>::Op(p);
}
return InterfaceCast<Tail>::Op(p, iid);
}
};
template <class TList>
struct FillIIDs;
template <>
struct FillIIDs<TL::NullType>
{
static void Op(CryInterfaceID*)
{
}
};
template <class Head, class Tail>
struct FillIIDs<TL::Typelist<Head, Tail> >
{
static void Op(CryInterfaceID* p)
{
*p++ = cryiidof<Head>();
FillIIDs<Tail>::Op(p);
}
};
namespace Internal
{
template <bool, typename S>
struct PickList;
template <bool, typename S>
struct PickList
{
typedef TL::BuildTypelist<>::Result Result;
};
template <typename S>
struct PickList<true, S>
{
typedef typename S::FullCompositeList Result;
};
}
template <typename T>
struct ProbeFullCompositeList
{
private:
typedef char y[1];
typedef char n[2];
template <typename S>
static y& test(typename S::FullCompositeList*);
template <typename>
static n& test(...);
public:
enum
{
listFound = sizeof(test<T>(0)) == sizeof(y)
};
typedef typename Internal::PickList<listFound, T>::Result ListType;
};
namespace Internal
{
template <class TList>
struct CompositeQuery;
template <>
struct CompositeQuery<TL::NullType>
{
template<typename T>
static void* Op(const T&, const char*)
{
return 0;
}
};
template <class Head, class Tail>
struct CompositeQuery<TL::Typelist<Head, Tail> >
{
template<typename T>
static void* Op(const T& ref, const char* name)
{
void* p = ref.Head::CompositeQueryImpl(name);
return p ? p : CompositeQuery<Tail>::Op(ref, name);
}
};
}
struct CompositeQuery
{
template <typename T>
static void* Op(const T& ref, const char* name)
{
return Internal::CompositeQuery<typename ProbeFullCompositeList<T>::ListType>::Op(ref, name);
}
};
inline bool NameMatch(const char* name, const char* compositeName)
{
if (!name || !compositeName)
{
return false;
}
size_t i = 0;
for (; name[i] && name[i] == compositeName[i]; ++i)
{
}
return name[i] == compositeName[i];
}
template <typename T>
void* CheckCompositeMatch(const char* name, const AZStd::shared_ptr<T>& composite, const char* compositeName)
{
typedef TC::SuperSubClass<ICryUnknown, T> Rel;
COMPILE_TIME_ASSERT(Rel::exists);
return NameMatch(name, compositeName) ? const_cast<void*>(static_cast<const void*>(&composite)) : 0;
}
} // namespace CW
#define CRYINTERFACE_BEGIN() \
private: \
typedef TL::BuildTypelist < ICryUnknown
#define CRYINTERFACE_ADD(iname) , iname
#define CRYINTERFACE_END() > ::Result _UserDefinedPartialInterfaceList; \
protected: \
typedef TL::NoDuplicates<_UserDefinedPartialInterfaceList>::Result FullInterfaceList;
#define _CRY_TPL_APPEND0(base) TL::Append<base::FullInterfaceList, _UserDefinedPartialInterfaceList>::Result
#define _CRY_TPL_APPEND(base, intermediate) TL::Append<base::FullInterfaceList, intermediate>::Result
#define CRYINTERFACE_ENDWITHBASE(base) > ::Result _UserDefinedPartialInterfaceList; \
protected: \
typedef TL::NoDuplicates<_CRY_TPL_APPEND0(base)>::Result FullInterfaceList;
#define CRYINTERFACE_ENDWITHBASE2(base0, base1) > ::Result _UserDefinedPartialInterfaceList; \
protected: \
typedef TL::NoDuplicates<_CRY_TPL_APPEND(base0, _CRY_TPL_APPEND0(base1))>::Result FullInterfaceList;
#define CRYINTERFACE_ENDWITHBASE3(base0, base1, base2) > ::Result _UserDefinedPartialInterfaceList; \
protected: \
typedef TL::NoDuplicates<_CRY_TPL_APPEND(base0, _CRY_TPL_APPEND(base1, _CRY_TPL_APPEND0(base2)))>::Result FullInterfaceList;
#define CRYINTERFACE_SIMPLE(iname) \
CRYINTERFACE_BEGIN() \
CRYINTERFACE_ADD(iname) \
CRYINTERFACE_END()
#define CRYCOMPOSITE_BEGIN() \
private: \
void* CompositeQueryImpl(const char* name) const \
{ \
(void)(name); \
void* res = 0; (void)(res); \
#define CRYCOMPOSITE_ADD(member, membername) \
COMPILE_TIME_ASSERT((sizeof(membername) / sizeof(membername[0])) > 1); \
if ((res = CW::CheckCompositeMatch(name, member, membername)) != 0) { \
return res; }
#define _CRYCOMPOSITE_END(implclassname) \
return 0; \
}; \
protected: \
typedef TL::BuildTypelist<implclassname>::Result _PartialCompositeList; \
\
template <bool, typename S> \
friend struct CW::Internal::PickList;
#define CRYCOMPOSITE_END(implclassname) \
_CRYCOMPOSITE_END(implclassname) \
protected: \
typedef _PartialCompositeList FullCompositeList;
#define _CRYCOMPOSITE_APPEND0(base) TL::Append<_PartialCompositeList, CW::ProbeFullCompositeList<base>::ListType>::Result
#define _CRYCOMPOSITE_APPEND(base, intermediate) TL::Append<intermediate, CW::ProbeFullCompositeList<base>::ListType>::Result
#define CRYCOMPOSITE_ENDWITHBASE(implclassname, base) \
_CRYCOMPOSITE_END(implclassname) \
protected: \
typedef _CRYCOMPOSITE_APPEND0 (base) FullCompositeList;
#define CRYCOMPOSITE_ENDWITHBASE2(implclassname, base0, base1) \
_CRYCOMPOSITE_END(implclassname) \
protected: \
typedef TL::NoDuplicates<_CRYCOMPOSITE_APPEND(base1, _CRYCOMPOSITE_APPEND0(base0))>::Result FullCompositeList;
#define CRYCOMPOSITE_ENDWITHBASE3(implclassname, base0, base1, base2) \
_CRYCOMPOSITE_END(implclassname) \
protected: \
typedef TL::NoDuplicates<_CRYCOMPOSITE_APPEND(base2, _CRYCOMPOSITE_APPEND(base1, _CRYCOMPOSITE_APPEND0(base0)))>::Result FullCompositeList;
template<typename T>
class CFactory
: public ICryFactory
{
public:
virtual const char* GetName() const
{
return T::GetCName();
}
virtual const CryClassID& GetClassID() const
{
return T::GetCID();
}
virtual bool ClassSupports(const CryInterfaceID& iid) const
{
for (size_t i = 0; i < m_numIIDs; ++i)
{
if (iid == m_pIIDs[i])
{
return true;
}
}
return false;
}
virtual void ClassSupports(const CryInterfaceID*& pIIDs, size_t& numIIDs) const
{
pIIDs = m_pIIDs;
numIIDs = m_numIIDs;
}
public:
virtual ICryUnknownPtr CreateClassInstance() const
{
AZStd::shared_ptr<T> p = AZStd::make_shared<T>();
return cryinterface_cast<ICryUnknown> (p);
}
CFactory<T>()
: m_numIIDs(0)
, m_pIIDs(0)
, m_regFactory()
{
static CryInterfaceID supportedIIDs[TL::Length < typename T::FullInterfaceList > ::value];
CW::FillIIDs<typename T::FullInterfaceList>::Op(supportedIIDs);
m_pIIDs = &supportedIIDs[0];
m_numIIDs = TL::Length<typename T::FullInterfaceList>::value;
new(&m_regFactory)SRegFactoryNode(this);
}
protected:
CFactory(const CFactory&);
CFactory& operator =(const CFactory&);
size_t m_numIIDs;
CryInterfaceID* m_pIIDs;
SRegFactoryNode m_regFactory;
};
template<typename T>
class CSingletonFactory
: public CFactory<T>
{
public:
CSingletonFactory()
: CFactory<T>()
, m_csCreateClassInstance()
{
}
virtual ICryUnknownPtr CreateClassInstance() const
{
CryAutoLock<CryCriticalSection> lock(m_csCreateClassInstance);
// override the allocator. These function static instances are being destroyed after the AZ alloctor has been deleted.
// On win, TerminateProcess() prevents these destructors from being called, but that is not the case on OSX.
static typename AZStd::aligned_storage<sizeof(AZStd::Internal::sp_counted_impl_pda<T*, AZStd::Internal::sp_ms_deleter<T>,SingletonAllocator>), AZStd::alignment_of<T>::value>::type m_storage;
static ICryUnknownPtr p = AZStd::allocate_shared<T>(SingletonAllocator(AZStd::addressof(m_storage)));
return p;
}
mutable CryCriticalSection m_csCreateClassInstance;
struct SingletonAllocator
{
SingletonAllocator(void* ptr) :
m_data(ptr)
{}
void* allocate(size_t /*byteSize*/, size_t /*alignment*/, int /*flags*/ = 0)
{
return m_data;
}
void deallocate(void* /*ptr*/, size_t /*byteSize*/, size_t /*alignment*/)
{
// nothing to see here
}
void* m_data;
};
};
#define _CRYFACTORY_DECLARE(implclassname) \
private: \
friend class CFactory<implclassname>; \
static CFactory<implclassname> s_factory;
#define _CRYFACTORY_DECLARE_SINGLETON(implclassname) \
private: \
friend class CFactory<implclassname>; \
friend void* Get##implclassname##Factory(); \
static CSingletonFactory<implclassname> s_factory;
#define _IMPLEMENT_ICRYUNKNOWN() \
public: \
virtual ICryFactory* GetFactory() const \
{ \
return &s_factory; \
} \
\
protected: \
virtual void* QueryInterface(const CryInterfaceID&iid) const \
{ \
return CW::InterfaceCast<FullInterfaceList>::Op(this, iid); \
} \
\
template <class TList> \
friend struct CW::Internal::CompositeQuery; \
\
virtual void* QueryComposite(const char* name) const \
{ \
return CW::CompositeQuery::Op(*this, name); \
}
#define _ENFORCE_CRYFACTORY_USAGE(implclassname, cname, cidHigh, cidLow) \
public: \
static const char* GetCName() \
{ \
return cname; \
} \
static const CryClassID& GetCID() \
{ \
static const CryClassID cid = {(uint64) cidHigh##LL, (uint64) cidLow##LL}; \
return cid; \
} \
static AZStd::shared_ptr<implclassname> CreateClassInstance() \
{ \
ICryUnknownPtr p = s_factory.CreateClassInstance(); \
return AZStd::shared_ptr<implclassname>(*static_cast<AZStd::shared_ptr<implclassname>*>(static_cast<void*>(&p))); \
} \
\
protected: \
implclassname(); \
virtual ~implclassname();
#define _BEFRIEND_OPS() \
_BEFRIEND_CRYINTERFACE_CAST() \
_BEFRIEND_CRYCOMPOSITE_QUERY() \
_BEFRIEND_MAKE_SHARED()
#define CRYGENERATE_CLASS(implclassname, cname, cidHigh, cidLow) \
_CRYFACTORY_DECLARE(implclassname) \
_BEFRIEND_OPS() \
_IMPLEMENT_ICRYUNKNOWN() \
_ENFORCE_CRYFACTORY_USAGE(implclassname, cname, cidHigh, cidLow)
#define CRYGENERATE_SINGLETONCLASS(implclassname, cname, cidHigh, cidLow) \
_CRYFACTORY_DECLARE_SINGLETON(implclassname) \
_BEFRIEND_OPS() \
_IMPLEMENT_ICRYUNKNOWN() \
_ENFORCE_CRYFACTORY_USAGE(implclassname, cname, cidHigh, cidLow)
#define CRYREGISTER_CLASS(implclassname) \
CFactory<implclassname> implclassname::s_factory;
#define DECLARE_CRYREGISTER_SINGLETON_CLASS(implclassname) \
void* Get##implclassname##Factory();
#define CRYREGISTER_SINGLETON_CLASS(implclassname) \
CSingletonFactory<implclassname> implclassname::s_factory; \
void* Get##implclassname##Factory() { \
return &implclassname::s_factory; \
}
#endif // CRYINCLUDE_CRYEXTENSION_IMPL_CLASSWEAVER_H
@@ -0,0 +1,109 @@
/*
* 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 : Part of CryEngine's extension framework.
#ifndef CRYINCLUDE_CRYEXTENSION_IMPL_CONVERSION_H
#define CRYINCLUDE_CRYEXTENSION_IMPL_CONVERSION_H
#pragma once
namespace TC
{
//template <class T, class U>
//struct Conversion
//{
//private:
// typedef char y[1];
// typedef char n[2];
// static y& Test(U);
// static n& Test(...);
// static T MakeT();
//public:
// enum
// {
// exists = sizeof(Test(MakeT())) == sizeof(y),
// sameType = false
// };
//};
//template <class T>
//struct Conversion<T, T>
//{
//public:
// enum
// {
// exists = true,
// sameType = true
// };
//};
//template<typename Base, typename Derived>
//struct CheckInheritance
//{
// enum
// {
// exists = Conversion<const Derived*, const Base*>::exists && !Conversion<const Base*, const void*>::sameType
// };
//};
//template<typename Base, typename Derived>
//struct CheckStrictInheritance
//{
// enum
// {
// exists = CheckInheritance<Base, Derived>::exists && !Conversion<const Base*, const Derived*>::sameType
// };
//};
template <typename Base, typename Derived>
struct SuperSubClass
{
private:
typedef char y[1];
typedef char n[2];
template<typename T>
static y& check(const volatile Derived&, T);
static n& check(const volatile Base&, int);
struct C
{
operator const volatile Base&() const;
operator const volatile Derived&();
};
static C getC();
public:
enum
{
exists = sizeof(check(getC(), 0)) == sizeof(y),
sameType = false
};
};
template <typename T>
struct SuperSubClass<T, T>
{
enum
{
exists = true
};
};
} // namespace TC
#endif // CRYINCLUDE_CRYEXTENSION_IMPL_CONVERSION_H
@@ -0,0 +1,67 @@
/*
* 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 : Part of CryEngine's extension framework.
#ifndef CRYINCLUDE_CRYEXTENSION_IMPL_CRYGUIDHELPER_H
#define CRYINCLUDE_CRYEXTENSION_IMPL_CRYGUIDHELPER_H
#pragma once
#include "../CryGUID.h"
#include "../../CryString.h"
namespace CryGUIDHelper
{
string Print(const CryGUID& val)
{
char buf[39]; // sizeof("{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}")
static const char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
char* p = buf;
*p++ = '{';
for (int i = 15; i >= 8; --i)
{
*p++ = hex[(unsigned char) ((val.hipart >> (i << 2)) & 0xF)];
}
*p++ = '-';
for (int i = 7; i >= 4; --i)
{
*p++ = hex[(unsigned char) ((val.hipart >> (i << 2)) & 0xF)];
}
*p++ = '-';
for (int i = 3; i >= 0; --i)
{
*p++ = hex[(unsigned char) ((val.hipart >> (i << 2)) & 0xF)];
}
*p++ = '-';
for (int i = 15; i >= 12; --i)
{
*p++ = hex[(unsigned char) ((val.lopart >> (i << 2)) & 0xF)];
}
*p++ = '-';
for (int i = 11; i >= 0; --i)
{
*p++ = hex[(unsigned char) ((val.lopart >> (i << 2)) & 0xF)];
}
*p++ = '}';
*p++ = '\0';
return string(buf);
}
}
#endif // CRYINCLUDE_CRYEXTENSION_IMPL_CRYGUIDHELPER_H
@@ -0,0 +1,58 @@
/*
* 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 : Part of CryEngine's extension framework.
#ifndef CRYINCLUDE_CRYEXTENSION_IMPL_ICRYFACTORYREGISTRYIMPL_H
#define CRYINCLUDE_CRYEXTENSION_IMPL_ICRYFACTORYREGISTRYIMPL_H
#pragma once
#include "../ICryFactoryRegistry.h"
struct SRegFactoryNode;
struct ICryFactoryRegistryCallback
{
virtual void OnNotifyFactoryRegistered(ICryFactory* pFactory) = 0;
virtual void OnNotifyFactoryUnregistered(ICryFactory* pFactory) = 0;
protected:
virtual ~ICryFactoryRegistryCallback() {}
};
struct ICryFactoryRegistryImpl
: public ICryFactoryRegistry
{
virtual ICryFactory* GetFactory(const char* cname) const = 0;
virtual ICryFactory* GetFactory(const CryClassID& cid) const = 0;
virtual void IterateFactories(const CryInterfaceID& iid, ICryFactory** pFactories, size_t& numFactories) const = 0;
virtual void RegisterCallback(ICryFactoryRegistryCallback* pCallback) = 0;
virtual void UnregisterCallback(ICryFactoryRegistryCallback* pCallback) = 0;
virtual void RegisterFactories(const SRegFactoryNode* pFactories) = 0;
virtual void UnregisterFactories(const SRegFactoryNode* pFactories) = 0;
virtual void UnregisterFactory(ICryFactory* const pFactory) = 0;
protected:
// prevent explicit destruction from client side (delete, shared_ptr, etc)
virtual ~ICryFactoryRegistryImpl() {}
};
#endif // CRYINCLUDE_CRYEXTENSION_IMPL_ICRYFACTORYREGISTRYIMPL_H
@@ -0,0 +1,52 @@
/*
* 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 : Part of CryEngine's extension framework.
#ifndef CRYINCLUDE_CRYEXTENSION_IMPL_REGFACTORYNODE_H
#define CRYINCLUDE_CRYEXTENSION_IMPL_REGFACTORYNODE_H
#pragma once
struct ICryFactory;
struct SRegFactoryNode;
extern SRegFactoryNode* g_pHeadToRegFactories;
struct SRegFactoryNode
{
SRegFactoryNode()
{
}
SRegFactoryNode(ICryFactory* pFactory)
: m_pFactory(pFactory)
, m_pNext(g_pHeadToRegFactories)
{
g_pHeadToRegFactories = this;
}
static void* operator new(size_t, void* p)
{
return p;
}
static void operator delete(void*, void*)
{
}
ICryFactory* m_pFactory;
SRegFactoryNode* m_pNext;
};
#endif // CRYINCLUDE_CRYEXTENSION_IMPL_REGFACTORYNODE_H
@@ -0,0 +1,236 @@
/*
* 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 : Part of CryEngine's extension framework.
#ifndef CRYINCLUDE_CRYEXTENSION_TYPELIST_H
#define CRYINCLUDE_CRYEXTENSION_TYPELIST_H
#pragma once
namespace TL
{
// typelist terminator
class NullType
{
};
// structure for typelist generation
template <class T, class U = NullType>
struct Typelist
{
typedef T Head;
typedef U Tail;
};
// helper structure to automatically build typelists containing n types
template
<
typename T0 = NullType, typename T1 = NullType, typename T2 = NullType, typename T3 = NullType, typename T4 = NullType,
typename T5 = NullType, typename T6 = NullType, typename T7 = NullType, typename T8 = NullType, typename T9 = NullType,
typename T10 = NullType, typename T11 = NullType, typename T12 = NullType, typename T13 = NullType, typename T14 = NullType,
typename T15 = NullType, typename T16 = NullType, typename T17 = NullType, typename T18 = NullType, typename T19 = NullType
>
struct BuildTypelist
{
private:
typedef typename BuildTypelist<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>::Result TailResult;
public:
typedef Typelist<T0, TailResult> Result;
};
template <>
struct BuildTypelist<>
{
typedef NullType Result;
};
// typelist operation : Length
template <class TList>
struct Length;
template <>
struct Length<NullType>
{
enum
{
value = 0
};
};
template <class T, class U>
struct Length<Typelist<T, U> >
{
enum
{
value = 1 + Length<U>::value
};
};
// typelist operation : TypeAt
template <class TList, unsigned int index>
struct TypeAt;
template <class Head, class Tail>
struct TypeAt<Typelist<Head, Tail>, 0>
{
typedef Head Result;
};
template <class Head, class Tail, unsigned int index>
struct TypeAt<Typelist<Head, Tail>, index>
{
typedef typename TypeAt<Tail, index - 1>::Result Result;
};
// typelist operation : IndexOf
template <class TList, class T>
struct IndexOf;
template <class T>
struct IndexOf<NullType, T>
{
enum
{
value = -1
};
};
template <class T, class Tail>
struct IndexOf<Typelist<T, Tail>, T>
{
enum
{
value = 0
};
};
template <class Head, class Tail, class T>
struct IndexOf<Typelist<Head, Tail>, T>
{
private:
enum
{
temp = IndexOf<Tail, T>::value
};
public:
enum
{
value = temp == -1 ? -1 : 1 + temp
};
};
// typelist operation : Append
template <class TList, class T>
struct Append;
template <>
struct Append<NullType, NullType>
{
typedef NullType Result;
};
template <class T>
struct Append<NullType, T>
{
typedef Typelist<T, NullType> Result;
};
template <class Head, class Tail>
struct Append<NullType, Typelist<Head, Tail> >
{
typedef Typelist<Head, Tail> Result;
};
template <class Head, class Tail, class T>
struct Append<Typelist<Head, Tail>, T>
{
typedef Typelist<Head, typename Append<Tail, T>::Result> Result;
};
// typelist operation : Erase
template <class TList, class T>
struct Erase;
template <class T>
struct Erase<NullType, T>
{
typedef NullType Result;
};
template <class T, class Tail>
struct Erase<Typelist<T, Tail>, T>
{
typedef Tail Result;
};
template <class Head, class Tail, class T>
struct Erase<Typelist<Head, Tail>, T>
{
typedef Typelist<Head, typename Erase<Tail, T>::Result> Result;
};
// typelist operation : Erase All
template <class TList, class T>
struct EraseAll;
template <class T>
struct EraseAll<NullType, T>
{
typedef NullType Result;
};
template <class T, class Tail>
struct EraseAll<Typelist<T, Tail>, T>
{
typedef typename EraseAll<Tail, T>::Result Result;
};
template <class Head, class Tail, class T>
struct EraseAll<Typelist<Head, Tail>, T>
{
typedef Typelist<Head, typename EraseAll<Tail, T>::Result> Result;
};
// typelist operation : NoDuplicates
template <class TList>
struct NoDuplicates;
template <>
struct NoDuplicates<NullType>
{
typedef NullType Result;
};
template <class Head, class Tail>
struct NoDuplicates<Typelist<Head, Tail> >
{
private:
typedef typename NoDuplicates<Tail>::Result L1;
typedef typename Erase<L1, Head>::Result L2;
public:
typedef Typelist<Head, L2> Result;
};
} // namespace TL
#endif // CRYINCLUDE_CRYEXTENSION_TYPELIST_H
+442
View File
@@ -0,0 +1,442 @@
/*
* 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 : File wrapper.
#ifndef CRYINCLUDE_CRYCOMMON_CRYFILE_H
#define CRYINCLUDE_CRYCOMMON_CRYFILE_H
#pragma once
#include <CryPath.h>
#include <ISystem.h>
#include <AzFramework/Archive/IArchive.h>
#include <IConsole.h>
#include "StringUtils.h"
#include <AzCore/IO/FileIO.h>
//////////////////////////////////////////////////////////////////////////
// Defines for CryEngine filetypes extensions.
//////////////////////////////////////////////////////////////////////////
#define CRY_GEOMETRY_FILE_EXT "cgf"
#define CRY_SKEL_FILE_EXT "chr" //will be a SKEL soon
#define CRY_SKIN_FILE_EXT "skin"
#define CRY_CHARACTER_ANIMATION_FILE_EXT "caf"
#define CRY_CHARACTER_DEFINITION_FILE_EXT "cdf"
#define CRY_CHARACTER_LIST_FILE_EXT "cid"
#define CRY_ANIM_GEOMETRY_FILE_EXT "cga"
#define CRY_ANIM_GEOMETRY_ANIMATION_FILE_EXT "anm"
#define CRY_COMPILED_FILE_EXT "(c)"
#define CRY_BINARY_XML_FILE_EXT "binxml"
#define CRY_XML_FILE_EXT "xml"
#define CRY_CHARACTER_PARAM_FILE_EXT "chrparams"
#define CRY_GEOM_CACHE_FILE_EXT "cax"
//////////////////////////////////////////////////////////////////////////
#define CRYFILE_MAX_PATH 260
//////////////////////////////////////////////////////////////////////////
inline const char* CryGetExt(const char* filepath)
{
const char* str = filepath;
size_t len = strlen(filepath);
for (const char* p = str + len - 1; p >= str; --p)
{
switch (*p)
{
case ':':
case '/':
case '\\':
// we've reached a path separator - it means there's no extension in this name
return "";
case '.':
// there's an extension in this file name
return p + 1;
}
}
return "";
}
// Summary:
// Checks if specified file name is a character file.
// Summary:
// Checks if specified file name is a character file.
inline bool IsCharacterFile(const char* filename)
{
const char* ext = CryGetExt(filename);
if (_stricmp(ext, CRY_SKEL_FILE_EXT) == 0 || _stricmp(ext, CRY_SKIN_FILE_EXT) == 0 || _stricmp(ext, CRY_CHARACTER_DEFINITION_FILE_EXT) == 0 || _stricmp(ext, CRY_ANIM_GEOMETRY_FILE_EXT) == 0)
{
return true;
}
else
{
return false;
}
}
// Description:
// Checks if specified file name is a static geometry file.
inline bool IsStatObjFile(const char* filename)
{
const char* ext = CryGetExt(filename);
if (_stricmp(ext, CRY_GEOMETRY_FILE_EXT) == 0)
{
return true;
}
else
{
return false;
}
}
// Summary:
// Wrapper on file system.
class CCryFile
{
public:
CCryFile();
CCryFile(AZ::IO::IArchive* pIArchive); // allow an alternative IArchiveinterface
CCryFile(const char* filename, const char* mode);
~CCryFile();
bool Open(const char* filename, const char* mode, int nOpenFlagsEx = 0);
void Close();
// Summary:
// Writes data in a file to the current file position.
size_t Write(const void* lpBuf, size_t nSize);
// Summary:
// Reads data from a file at the current file position.
size_t ReadRaw(void* lpBuf, size_t nSize);
// Summary:
// Template version, for automatic size support.
template<class T>
inline size_t ReadTypeRaw(T* pDest, size_t nCount = 1)
{
return ReadRaw(pDest, sizeof(T) * nCount);
}
// Summary:
// Automatic endian-swapping version.
template<class T>
inline size_t ReadType(T* pDest, size_t nCount = 1)
{
size_t nRead = ReadRaw(pDest, sizeof(T) * nCount);
SwapEndian(pDest, nCount);
return nRead;
}
// Summary:
// Retrieves the length of the file.
size_t GetLength();
// Summary:
// Moves the current file pointer to the specified position.
size_t Seek(size_t seek, int mode);
// Summary:
// Moves the current file pointer at the beginning of the file.
void SeekToBegin();
// Summary:
// Moves the current file pointer at the end of the file.
size_t SeekToEnd();
// Summary:
// Retrieves the current file pointer.
size_t GetPosition();
// Summary:
// Tests for end-of-file on a selected file.
bool IsEof();
// Summary:
// Flushes any data yet to be written.
void Flush();
// Summary:
// Gets a handle to a pack object.
AZ::IO::HandleType GetHandle() const { return m_fileHandle; };
// Description:
// Retrieves the filename of the selected file.
const char* GetFilename() const { return m_filename; };
// Description:
// Retrieves the filename after adjustment to the real relative to engine root path.
// Example:
// Original filename "textures/red.dds" adjusted filename will look like "game/textures/red.dds"
// Return:
// Adjusted filename, this is a pointer to a static string, copy return value if you want to keep it.
const char* GetAdjustedFilename() const;
// Summary:
// Checks if file is opened from Archive file.
bool IsInPak() const;
// Summary:
// Gets path of archive this file is in.
const char* GetPakPath() const;
private:
char m_filename[CRYFILE_MAX_PATH];
AZ::IO::HandleType m_fileHandle;
AZ::IO::IArchive* m_pIArchive;
};
// Summary:
// CCryFile implementation.
inline CCryFile::CCryFile()
{
m_fileHandle = AZ::IO::InvalidHandle;
m_pIArchive = gEnv ? gEnv->pCryPak : NULL;
}
inline CCryFile::CCryFile(AZ::IO::IArchive* pIArchive)
{
m_fileHandle = AZ::IO::InvalidHandle;
m_pIArchive = pIArchive;
}
//////////////////////////////////////////////////////////////////////////
inline CCryFile::CCryFile(const char* filename, const char* mode)
{
m_fileHandle = AZ::IO::InvalidHandle;
m_pIArchive = gEnv ? gEnv->pCryPak : NULL;
Open(filename, mode);
}
//////////////////////////////////////////////////////////////////////////
inline CCryFile::~CCryFile()
{
Close();
}
//////////////////////////////////////////////////////////////////////////
// Notes:
// For nOpenFlagsEx see IArchive::EFOpenFlags
// See also:
// IArchive::EFOpenFlags
inline bool CCryFile::Open(const char* filename, const char* mode, int nOpenFlagsEx)
{
char tempfilename[CRYFILE_MAX_PATH] = "";
cry_strcpy(tempfilename, filename);
#if !defined (_RELEASE)
if (gEnv && gEnv->IsEditor() && gEnv->pConsole)
{
ICVar* const pCvar = gEnv->pConsole->GetCVar("ed_lowercasepaths");
if (pCvar)
{
const int lowercasePaths = pCvar->GetIVal();
if (lowercasePaths)
{
const string lowerString = PathUtil::ToLower(tempfilename);
cry_strcpy(tempfilename, lowerString.c_str());
}
}
}
#endif
if (m_fileHandle != AZ::IO::InvalidHandle)
{
Close();
}
cry_strcpy(m_filename, tempfilename);
if (m_pIArchive)
{
m_fileHandle = m_pIArchive->FOpen(tempfilename, mode, nOpenFlagsEx);
}
else
{
AZ::IO::FileIOBase::GetInstance()->Open(tempfilename, AZ::IO::GetOpenModeFromStringMode(mode), m_fileHandle);
}
return m_fileHandle != AZ::IO::InvalidHandle;
}
//////////////////////////////////////////////////////////////////////////
inline void CCryFile::Close()
{
if (m_fileHandle != AZ::IO::InvalidHandle)
{
if (m_pIArchive)
{
m_pIArchive->FClose(m_fileHandle);
}
else
{
AZ::IO::FileIOBase::GetInstance()->Close(m_fileHandle);
}
m_fileHandle = AZ::IO::InvalidHandle;
m_filename[0] = 0;
}
}
//////////////////////////////////////////////////////////////////////////
inline size_t CCryFile::Write(const void* lpBuf, size_t nSize)
{
assert(m_fileHandle != AZ::IO::InvalidHandle);
if (m_pIArchive)
{
return m_pIArchive->FWrite(lpBuf, 1, nSize, m_fileHandle);
}
if (AZ::IO::FileIOBase::GetInstance()->Write(m_fileHandle, lpBuf, nSize))
{
return nSize;
}
return 0;
}
//////////////////////////////////////////////////////////////////////////
inline size_t CCryFile::ReadRaw(void* lpBuf, size_t nSize)
{
assert(m_fileHandle != AZ::IO::InvalidHandle);
if (m_pIArchive)
{
return m_pIArchive->FReadRaw(lpBuf, 1, nSize, m_fileHandle);
}
AZ::u64 bytesRead = 0;
AZ::IO::FileIOBase::GetInstance()->Read(m_fileHandle, lpBuf, nSize, false, &bytesRead);
return static_cast<size_t>(bytesRead);
}
//////////////////////////////////////////////////////////////////////////
inline size_t CCryFile::GetLength()
{
assert(m_fileHandle != AZ::IO::InvalidHandle);
if (m_pIArchive)
{
return m_pIArchive->FGetSize(m_fileHandle);
}
//long curr = ftell(m_file);
AZ::u64 size = 0;
AZ::IO::FileIOBase::GetInstance()->Size(m_fileHandle, size);
return static_cast<size_t>(size);
}
//////////////////////////////////////////////////////////////////////////
inline size_t CCryFile::Seek(size_t seek, int mode)
{
assert(m_fileHandle != AZ::IO::InvalidHandle);
if (m_pIArchive)
{
return m_pIArchive->FSeek(m_fileHandle, long(seek), mode);
}
if (AZ::IO::FileIOBase::GetInstance()->Seek(m_fileHandle, seek, AZ::IO::GetSeekTypeFromFSeekMode(mode)))
{
return 0;
}
return 1;
}
//////////////////////////////////////////////////////////////////////////
inline void CCryFile::SeekToBegin()
{
Seek(0, SEEK_SET);
}
//////////////////////////////////////////////////////////////////////////
inline size_t CCryFile::SeekToEnd()
{
return Seek(0, SEEK_END);
}
//////////////////////////////////////////////////////////////////////////
inline size_t CCryFile::GetPosition()
{
assert(m_fileHandle != AZ::IO::InvalidHandle);
if (m_pIArchive)
{
return m_pIArchive->FTell(m_fileHandle);
}
AZ::u64 tellOffset = 0;
AZ::IO::FileIOBase::GetInstance()->Tell(m_fileHandle, tellOffset);
return static_cast<size_t>(tellOffset);
}
//////////////////////////////////////////////////////////////////////////
inline bool CCryFile::IsEof()
{
assert(m_fileHandle != AZ::IO::InvalidHandle);
if (m_pIArchive)
{
return m_pIArchive->FEof(m_fileHandle) != 0;
}
return AZ::IO::FileIOBase::GetInstance()->Eof(m_fileHandle);
}
//////////////////////////////////////////////////////////////////////////
inline void CCryFile::Flush()
{
assert(m_fileHandle != AZ::IO::InvalidHandle);
if (m_pIArchive)
{
m_pIArchive->FFlush(m_fileHandle);
}
AZ::IO::FileIOBase::GetInstance()->Flush(m_fileHandle);
}
//////////////////////////////////////////////////////////////////////////
inline bool CCryFile::IsInPak() const
{
if (m_fileHandle != AZ::IO::InvalidHandle && m_pIArchive)
{
return m_pIArchive->GetFileArchivePath(m_fileHandle) != NULL;
}
return false;
}
//////////////////////////////////////////////////////////////////////////
inline const char* CCryFile::GetPakPath() const
{
if (m_fileHandle != AZ::IO::InvalidHandle && m_pIArchive)
{
const char* sPath = m_pIArchive->GetFileArchivePath(m_fileHandle);
if (sPath != NULL)
{
return sPath;
}
}
return "";
}
//////////////////////////////////////////////////////////////////////////
inline const char* CCryFile::GetAdjustedFilename() const
{
static char szAdjustedFile[AZ::IO::IArchive::MaxPath];
assert(m_pIArchive);
if (!m_pIArchive)
{
return "";
}
// Gets mod path to file.
const char* gameUrl = m_pIArchive->AdjustFileName(m_filename, szAdjustedFile, AZ::IO::IArchive::MaxPath, 0);
// Returns standard path otherwise.
if (gameUrl != &szAdjustedFile[0])
{
cry_strcpy(szAdjustedFile, gameUrl);
}
return szAdjustedFile;
}
#endif // CRYINCLUDE_CRYCOMMON_CRYFILE_H
+309
View File
@@ -0,0 +1,309 @@
/*
* 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.
/*
CryFixedArray.h
- no longer support being created on the stack (since the alignment code was changed to support adding CryFixedArrays into stl::vectors)
- performs construction or destruction only on elements as they become live/dead or are moved around during the RemoveAt() reshuffle
- just a range checked equivelant of a standard array
- for now only allows push_back() population of array
- if using as a class member variable ensure to put the CryFixedArrays after all other member variables at the bottom of your class
to ensure all members stay on the same cacheline
*/
#ifndef CRYINCLUDE_CRYCOMMON_CRYFIXEDARRAY_H
#define CRYINCLUDE_CRYCOMMON_CRYFIXEDARRAY_H
#pragma once
#define DEBUG_CRYFIXED_ARRAY _DEBUG
template<
unsigned int align >
struct CryFixedArrayDatum
{
};
template<>
struct CryFixedArrayDatum< 4 >
{
typedef uint32 TDatum;
};
template<>
struct CryFixedArrayDatum< 8 >
{
typedef uint64 TDatum;
};
template <class T, unsigned int N>
class CryFixedArray
{
protected:
enum
{
ALIGN = MAX(alignof(T), sizeof(unsigned int))
}; // ALIGN at least sizeof(unsigned int)
typedef typename CryFixedArrayDatum< ALIGN >::TDatum TDatum;
uint32 m_curSize[ sizeof (TDatum) / sizeof (uint32) ]; // Padded for alignment
TDatum m_data[(N * sizeof(T) + (sizeof(TDatum) - 1)) / sizeof(TDatum)]; // simple debugging - in VS: just add to a watch as "(T*)m_data, <N>" to see the array. ie. "(int*)m_data, 5" - the size of the array has to be a literal int
public:
typedef T* iterator;
typedef const T* const_iterator;
CryFixedArray()
{
#if DEBUG_CRYFIXED_ARRAY
if (((uintptr_t)m_data & (ALIGN - 1)) != 0)
{
CryLogAlways("CryFixedArray() error - data is not aligned. This may happen if you are creating a CryFixedArray on the stack, which isn't supported.");
}
#endif
CRY_ASSERT_MESSAGE(((uintptr_t)m_data & (ALIGN - 1)) == 0, "CryFixedArray() error - data is not aligned. This may happen if you are creating a CryFixedArray on the stack, which isn't supported.");
m_curSize[0] = 0;
}
CryFixedArray(const CryFixedArray& other)
{
// doesn't require clear() this is newly constructed
m_curSize[0] = other.m_curSize[0];
int size = m_curSize[0];
for (int i = 0; i < size; i++)
{
T& ele = operator[](i);
const T& otherEle = other.operator[](i);
new (&ele)T(otherEle); // placement new
}
}
CryFixedArray& operator=(const CryFixedArray& other)
{
if (this != &other)
{
clear(); // necessary to avoid potentially leaking within existing elements
m_curSize[0] = other.m_curSize[0];
int size = m_curSize[0];
for (int i = 0; i < size; i++)
{
T& ele = operator[](i);
const T& otherEle = other.operator[](i);
//ele = otherEle; // assignment instead of placement new to keep type of operation consistent - this cannot be done until this is rewritten to assign over existing elements and deconstruct any left overs, and placement new any new elements
new (&ele)T(otherEle); // placement new
}
}
return *this;
}
virtual ~CryFixedArray()
{
clear();
}
ILINE T& at(unsigned int i)
{
#if DEBUG_CRYFIXED_ARRAY
if (i < size())
{
return alias_cast<T*>(m_data)[i];
}
else
{
// Log is required now as its possible to turn off assert output logging, yet you really want to know if this is happening!!!!
CryLogAlways("CryFixedArray::at(i=%d) failed as i is out of range of curSize=%d (maxSize=%d) - forcing a crash", i, m_curSize[0], N);
CRY_ASSERT_MESSAGE(0, string().Format("CryFixedArray::at(i=%d) failed as i is out of range of curSize=%d (maxSize=%d)", i, m_curSize[0], N));
abort(); // better option than dereferncing a nullptr?
}
#else
return alias_cast<T*>(m_data)[i];
#endif
}
ILINE const T& at(unsigned int i) const
{
#if DEBUG_CRYFIXED_ARRAY
if (i < size())
{
return alias_cast<const T*>(m_data)[i];
}
else
{
// Log is required now as its possible to turn off assert output logging, yet you really want to know if this is happening!!!!
CryLogAlways("CryFixedArray::at(i=%d) failed as i is out of range of curSize=%d (maxSize=%d) - forcing a crash", i, m_curSize[0], N);
CRY_ASSERT_MESSAGE(0, string().Format("CryFixedArray::at(i=%d) failed as i is out of range of curSize=%d (maxSize=%d)", i, m_curSize[0], N));
abort(); // better option than dereferncing a nullptr?
}
#else
return alias_cast<const T*>(m_data)[i];
#endif
}
ILINE const T& operator[](unsigned int i) const
{
return at(i);
}
ILINE T& operator[](unsigned int i)
{
return at(i);
}
ILINE void clear()
{
for (uint32 i = 0; i < m_curSize[0]; i++)
{
T& ele = operator[](i);
ele.~T();
}
m_curSize[0] = 0;
#if DEBUG_CRYFIXED_ARRAY
memset(m_data, 0, N * sizeof(T));
#endif
}
ILINE iterator begin()
{
return alias_cast<T*>(m_data);
}
ILINE const_iterator begin() const
{
return alias_cast<T*>(m_data);
}
ILINE iterator end()
{
return &(alias_cast<T*>(m_data))[m_curSize[0]];
}
ILINE const_iterator end() const
{
return &(alias_cast<T*>(m_data))[m_curSize[0]];
}
ILINE unsigned int max_size() const { return N; }
ILINE unsigned int size() const { return m_curSize[0]; }
ILINE bool empty() const { return size() == 0; }
ILINE unsigned int isfull() const { return (size() == max_size()); }
// allows you to push back default constructed elements
ILINE void push_back ()
{
unsigned int curSize = size();
if (curSize < N)
{
T* newT = &(alias_cast<T*>(m_data))[curSize];
new (newT) T();
m_curSize[0]++;
}
else
{
CryLogAlways("CryFixedArray::push_back() failing as array of size %u is full - NOT adding element", N);
CRY_ASSERT_TRACE(0, ("CryFixedArray::push_back() failing as array of size %u is full - NOT adding element", N));
}
}
ILINE void push_back (const T& ele)
{
unsigned int curSize = size();
if (curSize < N)
{
T* newT = &(alias_cast<T*>(m_data))[curSize];
new (newT) T(ele); // placement new copy constructor - setup vtable etc
m_curSize[0]++;
}
else
{
CryLogAlways("CryFixedArray::push_back() failing as array of size %u is full - NOT adding element", N);
CRY_ASSERT_TRACE(0, ("CryFixedArray::push_back() failing as array of size %u is full - NOT adding element", N));
}
}
ILINE void pop_back()
{
if (size() > 0)
{
back().~T(); // destruct back
m_curSize[0]--;
}
else
{
CryLogAlways("CryFixedArray::pop_back() failed as array is empty");
CRY_ASSERT_MESSAGE(0, "CryFixedArray::pop_back() failed as array is empty");
}
}
protected:
ILINE const T& backEx() const
{
#if DEBUG_CRYFIXED_ARRAY
if (m_curSize[0] > 0)
{
return (alias_cast<T*>(m_data))[m_curSize[0] - 1];
}
else
{
CryLogAlways("CryFixedArray::back() failed as array is empty");
CRY_ASSERT_MESSAGE(0, "CryFixedArray::back() failed as array is empty");
abort(); // better option than dereferncing a nullptr?
}
#else
return (alias_cast<T*>(m_data))[m_curSize[0] - 1];
#endif
}
public:
ILINE const T& back() const
{
return backEx();
}
ILINE T& back()
{
return (T&)(backEx());
}
// if returns true then an element has been swapped into the new element[i] and as such may need updating to reflect its new location in memory
ILINE bool removeAt(uint32 i)
{
bool swappedElement = false;
if (i < m_curSize[0])
{
if (i != m_curSize[0] - 1)
{
operator[](i).~T(); // destruct element being removed
// copy back() into element i
T* newT = &(alias_cast<T*>(m_data))[i];
new (newT) T(back()); // placement new copy constructor - setup vtable etc
swappedElement = true;
}
pop_back(); // will destruct back()
}
else
{
CryLog("CryFixedArray::removeAt() failed as i=%d is out of range of curSize=%d", i, m_curSize[0]);
CRY_ASSERT_MESSAGE(0, string().Format("CryFixedArray::removeAt() failed as i=%d is out of range of curSize=%d", i, m_curSize[0]));
}
return swappedElement;
}
};
#endif // CRYINCLUDE_CRYCOMMON_CRYFIXEDARRAY_H
File diff suppressed because it is too large Load Diff
+35
View File
@@ -0,0 +1,35 @@
/*
* 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.
*/
#pragma once
#include <AzCore/EBus/EBus.h>
#include <CryCommon/ISystem.h>
namespace AZ
{
/*!
* Signal LY to create an ICryFont
*/
class CryFontCreationRequests
: public AZ::EBusTraits
{
public:
using MutexType = AZStd::recursive_mutex;
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
virtual bool CreateCryFont([[maybe_unused]] SSystemGlobalEnvironment& env, [[maybe_unused]] const SSystemInitParams& initParams) {return false;} //! return false to fall back to default CryFont initialization
};
using CryFontCreationRequestBus = AZ::EBus<CryFontCreationRequests>;
}
+207
View File
@@ -0,0 +1,207 @@
/*
* 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.
#ifndef CRY_HALF_INL
#define CRY_HALF_INL
#pragma once
typedef uint16 CryHalf;
class ICrySizer;
typedef union floatint_union
{
float f;
uint32 i;
} floatint_union;
__forceinline CryHalf CryConvertFloatToHalf(const float Value)
{
#if defined(LINUX) || defined(MAC)
asm volatile("" ::: "memory");
#endif
unsigned int Result;
unsigned int IValue = ((unsigned int*)(&Value))[0];
unsigned int Sign = (IValue & 0x80000000U) >> 16U;
IValue = IValue & 0x7FFFFFFFU; // Hack off the sign
if (IValue > 0x47FFEFFFU)
{
// The number is too large to be represented as a half. Saturate to infinity.
Result = 0x7FFFU;
}
else
{
if (IValue < 0x38800000U)
{
// The number is too small to be represented as a normalized half.
// Convert it to a denormalized value.
unsigned int Shift = 113U - (IValue >> 23U);
IValue = (0x800000U | (IValue & 0x7FFFFFU)) >> Shift;
}
else
{
// Rebias the exponent to represent the value as a normalized half.
IValue += 0xC8000000U;
}
Result = ((IValue + 0x0FFFU + ((IValue >> 13U) & 1U)) >> 13U) & 0x7FFFU;
}
return (CryHalf)(Result | Sign);
}
__forceinline float CryConvertHalfToFloat(const CryHalf Value)
{
#if defined(LINUX) || defined(MAC)
asm volatile("" ::: "memory");
#endif
unsigned int Mantissa;
unsigned int Exponent;
unsigned int Result;
Mantissa = (unsigned int)(Value & 0x03FF);
if ((Value & 0x7C00) != 0) // The value is normalized
{
Exponent = (unsigned int)((Value >> 10) & 0x1F);
}
else if (Mantissa != 0) // The value is denormalized
{
// Normalize the value in the resulting float
Exponent = 1;
do
{
Exponent--;
Mantissa <<= 1;
} while ((Mantissa & 0x0400) == 0);
Mantissa &= 0x03FF;
}
else // The value is zero
{
Exponent = (unsigned int)-112;
}
Result = ((Value & 0x8000) << 16) | // Sign
((Exponent + 112) << 23) | // Exponent
(Mantissa << 13); // Mantissa
return *(float*)&Result;
}
struct CryHalf2
{
CryHalf x;
CryHalf y;
CryHalf2()
{
}
CryHalf2(CryHalf _x, CryHalf _y)
: x(_x)
, y(_y)
{
}
CryHalf2(const CryHalf* const __restrict pArray)
{
x = pArray[0];
y = pArray[1];
}
CryHalf2(float _x, float _y)
{
x = CryConvertFloatToHalf(_x);
y = CryConvertFloatToHalf(_y);
}
CryHalf2(const float* const __restrict pArray)
{
x = CryConvertFloatToHalf(pArray[0]);
y = CryConvertFloatToHalf(pArray[1]);
}
CryHalf2& operator= (const CryHalf2& Half2)
{
x = Half2.x;
y = Half2.y;
return *this;
}
bool operator !=(const CryHalf2& rhs) const
{
return x != rhs.x || y != rhs.y;
}
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {}
AUTO_STRUCT_INFO
};
struct CryHalf4
{
CryHalf x;
CryHalf y;
CryHalf z;
CryHalf w;
CryHalf4()
{
}
CryHalf4(CryHalf _x, CryHalf _y, CryHalf _z, CryHalf _w)
: x(_x)
, y(_y)
, z(_z)
, w(_w)
{
}
CryHalf4(const CryHalf* const __restrict pArray)
{
x = pArray[0];
y = pArray[1];
z = pArray[2];
w = pArray[3];
}
CryHalf4(float _x, float _y, float _z, float _w)
{
x = CryConvertFloatToHalf(_x);
y = CryConvertFloatToHalf(_y);
z = CryConvertFloatToHalf(_z);
w = CryConvertFloatToHalf(_w);
}
CryHalf4(const float* const __restrict pArray)
{
x = CryConvertFloatToHalf(pArray[0]);
y = CryConvertFloatToHalf(pArray[1]);
z = CryConvertFloatToHalf(pArray[2]);
w = CryConvertFloatToHalf(pArray[3]);
}
CryHalf4& operator= (const CryHalf4& Half4)
{
x = Half4.x;
y = Half4.y;
z = Half4.z;
w = Half4.w;
return *this;
}
bool operator !=(const CryHalf4& rhs) const
{
return x != rhs.x || y != rhs.y || z != rhs.z || w != rhs.w;
}
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {}
AUTO_STRUCT_INFO
};
#endif // #ifndef CRY_HALF_INL
+32
View File
@@ -0,0 +1,32 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYCOMMON_CRYHALF_INFO_H
#define CRYINCLUDE_CRYCOMMON_CRYHALF_INFO_H
#pragma once
#include "CryHalf.inl"
STRUCT_INFO_BEGIN(CryHalf2)
STRUCT_VAR_INFO(x, TYPE_INFO(CryHalf))
STRUCT_VAR_INFO(y, TYPE_INFO(CryHalf))
STRUCT_INFO_END(CryHalf2)
STRUCT_INFO_BEGIN(CryHalf4)
STRUCT_VAR_INFO(x, TYPE_INFO(CryHalf))
STRUCT_VAR_INFO(y, TYPE_INFO(CryHalf))
STRUCT_VAR_INFO(z, TYPE_INFO(CryHalf))
STRUCT_VAR_INFO(w, TYPE_INFO(CryHalf))
STRUCT_INFO_END(CryHalf4)
#endif // CRYINCLUDE_CRYCOMMON_CRYHALF_INFO_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,490 @@
/*
* 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.
#include "TypeInfo_impl.h"
#include "CryHeaders.h"
STRUCT_INFO_BEGIN(CryVertex)
STRUCT_VAR_INFO(p, TYPE_INFO(Vec3))
STRUCT_VAR_INFO(n, TYPE_INFO(Vec3))
STRUCT_INFO_END(CryVertex)
STRUCT_INFO_BEGIN(CryFace)
STRUCT_VAR_INFO(v0, TYPE_INFO(int))
STRUCT_VAR_INFO(v1, TYPE_INFO(int))
STRUCT_VAR_INFO(v2, TYPE_INFO(int))
STRUCT_VAR_INFO(MatID, TYPE_INFO(int))
STRUCT_INFO_END(CryFace)
STRUCT_INFO_BEGIN(CryUV)
STRUCT_VAR_INFO(u, TYPE_INFO(float))
STRUCT_VAR_INFO(v, TYPE_INFO(float))
STRUCT_INFO_END(CryUV)
STRUCT_INFO_BEGIN(CrySkinVtx)
STRUCT_VAR_INFO(bVolumetric, TYPE_INFO(int))
STRUCT_VAR_INFO(idx, TYPE_INFO_ARRAY(4, TYPE_INFO(int)))
STRUCT_VAR_INFO(w, TYPE_INFO_ARRAY(4, TYPE_INFO(float)))
STRUCT_VAR_INFO(M, TYPE_INFO(Matrix33))
STRUCT_INFO_END(CrySkinVtx)
STRUCT_INFO_BEGIN(CryLink)
STRUCT_VAR_INFO(BoneID, TYPE_INFO(int))
STRUCT_VAR_INFO(offset, TYPE_INFO(Vec3))
STRUCT_VAR_INFO(Blending, TYPE_INFO(float))
STRUCT_INFO_END(CryLink)
STRUCT_INFO_BEGIN(CryIRGB)
STRUCT_VAR_INFO(r, TYPE_INFO(unsigned char))
STRUCT_VAR_INFO(g, TYPE_INFO(unsigned char))
STRUCT_VAR_INFO(b, TYPE_INFO(unsigned char))
STRUCT_INFO_END(CryIRGB)
STRUCT_INFO_BEGIN(CryBonePhysics_Comp)
STRUCT_VAR_INFO(nPhysGeom, TYPE_INFO(int))
STRUCT_VAR_INFO(flags, TYPE_INFO(int))
STRUCT_VAR_INFO(min, TYPE_ARRAY(3, TYPE_INFO(float)))
STRUCT_VAR_INFO(max, TYPE_ARRAY(3, TYPE_INFO(float)))
STRUCT_VAR_INFO(spring_angle, TYPE_ARRAY(3, TYPE_INFO(float)))
STRUCT_VAR_INFO(spring_tension, TYPE_ARRAY(3, TYPE_INFO(float)))
STRUCT_VAR_INFO(damping, TYPE_ARRAY(3, TYPE_INFO(float)))
STRUCT_VAR_INFO(framemtx, TYPE_ARRAY(3, TYPE_ARRAY(3, TYPE_INFO(float))))
STRUCT_INFO_END(CryBonePhysics_Comp)
STRUCT_INFO_BEGIN(CryBoneDescData_Comp)
STRUCT_VAR_INFO(m_nControllerID, TYPE_INFO(unsigned int))
STRUCT_VAR_INFO(m_PhysInfo, TYPE_ARRAY(2, TYPE_INFO(BONE_PHYSICS_COMP)))
STRUCT_VAR_INFO(m_fMass, TYPE_INFO(float))
STRUCT_VAR_INFO(m_DefaultW2B, TYPE_INFO(Matrix34))
STRUCT_VAR_INFO(m_DefaultB2W, TYPE_INFO(Matrix34))
STRUCT_VAR_INFO(m_arrBoneName, TYPE_ARRAY(256, TYPE_INFO(char)))
STRUCT_VAR_INFO(m_nLimbId, TYPE_INFO(int))
STRUCT_VAR_INFO(m_nOffsetParent, TYPE_INFO(int))
STRUCT_VAR_INFO(m_numChildren, TYPE_INFO(unsigned int))
STRUCT_VAR_INFO(m_nOffsetChildren, TYPE_INFO(int))
STRUCT_INFO_END(CryBoneDescData_Comp)
STRUCT_INFO_BEGIN(BONE_ENTITY)
STRUCT_VAR_INFO(BoneID, TYPE_INFO(int))
STRUCT_VAR_INFO(ParentID, TYPE_INFO(int))
STRUCT_VAR_INFO(nChildren, TYPE_INFO(int))
STRUCT_VAR_INFO(ControllerID, TYPE_INFO(unsigned int))
STRUCT_VAR_INFO(prop, TYPE_ARRAY(32, TYPE_INFO(char)))
STRUCT_VAR_INFO(phys, TYPE_INFO(BONE_PHYSICS_COMP))
STRUCT_INFO_END(BONE_ENTITY)
ENUM_INFO_BEGIN(ChunkTypes)
ENUM_ELEM_INFO(, ChunkType_ANY)
ENUM_ELEM_INFO(, ChunkType_Mesh)
ENUM_ELEM_INFO(, ChunkType_Helper)
ENUM_ELEM_INFO(, ChunkType_VertAnim)
ENUM_ELEM_INFO(, ChunkType_BoneAnim)
ENUM_ELEM_INFO(, ChunkType_GeomNameList)
ENUM_ELEM_INFO(, ChunkType_BoneNameList)
ENUM_ELEM_INFO(, ChunkType_MtlList)
ENUM_ELEM_INFO(, ChunkType_MRM)
ENUM_ELEM_INFO(, ChunkType_SceneProps)
ENUM_ELEM_INFO(, ChunkType_Light)
ENUM_ELEM_INFO(, ChunkType_PatchMesh)
ENUM_ELEM_INFO(, ChunkType_Node)
ENUM_ELEM_INFO(, ChunkType_Mtl)
ENUM_ELEM_INFO(, ChunkType_Controller)
ENUM_ELEM_INFO(, ChunkType_Timing)
ENUM_ELEM_INFO(, ChunkType_BoneMesh)
ENUM_ELEM_INFO(, ChunkType_BoneLightBinding)
ENUM_ELEM_INFO(, ChunkType_MeshMorphTarget)
ENUM_ELEM_INFO(, ChunkType_BoneInitialPos)
ENUM_ELEM_INFO(, ChunkType_SourceInfo)
ENUM_ELEM_INFO(, ChunkType_MtlName)
ENUM_ELEM_INFO(, ChunkType_ExportFlags)
ENUM_ELEM_INFO(, ChunkType_DataStream)
ENUM_ELEM_INFO(, ChunkType_MeshSubsets)
ENUM_ELEM_INFO(, ChunkType_MeshPhysicsData)
ENUM_ELEM_INFO(, ChunkType_CompiledBones)
ENUM_ELEM_INFO(, ChunkType_CompiledPhysicalBones)
ENUM_ELEM_INFO(, ChunkType_CompiledMorphTargets)
ENUM_ELEM_INFO(, ChunkType_CompiledPhysicalProxies)
ENUM_ELEM_INFO(, ChunkType_CompiledIntFaces)
ENUM_ELEM_INFO(, ChunkType_CompiledIntSkinVertices)
ENUM_ELEM_INFO(, ChunkType_CompiledExt2IntMap)
ENUM_ELEM_INFO(, ChunkType_BreakablePhysics)
ENUM_ELEM_INFO(, ChunkType_FaceMap)
ENUM_ELEM_INFO(, ChunkType_MotionParameters)
ENUM_ELEM_INFO(, ChunkType_FootPlantInfo)
ENUM_ELEM_INFO(, ChunkType_BonesBoxes)
ENUM_ELEM_INFO(, ChunkType_FoliageInfo)
ENUM_INFO_END(ChunkTypes)
STRUCT_INFO_BEGIN(RANGE_ENTITY)
STRUCT_VAR_INFO(name, TYPE_ARRAY(32, TYPE_INFO(char)))
STRUCT_VAR_INFO(start, TYPE_INFO(int))
STRUCT_VAR_INFO(end, TYPE_INFO(int))
STRUCT_INFO_END(RANGE_ENTITY)
STRUCT_INFO_BEGIN(TIMING_CHUNK_DESC_0918)
STRUCT_VAR_INFO(m_SecsPerTick, TYPE_INFO(float))
STRUCT_VAR_INFO(m_TicksPerFrame, TYPE_INFO(int))
STRUCT_VAR_INFO(global_range, TYPE_INFO(RANGE_ENTITY))
STRUCT_VAR_INFO(qqqqnSubRanges, TYPE_INFO(int))
STRUCT_INFO_END(TIMING_CHUNK_DESC_0918)
STRUCT_INFO_BEGIN(SPEED_CHUNK_DESC_2)
STRUCT_VAR_INFO(Speed, TYPE_INFO(float))
STRUCT_VAR_INFO(Distance, TYPE_INFO(float))
STRUCT_VAR_INFO(Slope, TYPE_INFO(float))
STRUCT_VAR_INFO(AnimFlags, TYPE_INFO(int))
STRUCT_VAR_INFO(MoveDir, TYPE_ARRAY(3, TYPE_INFO(f32)))
STRUCT_VAR_INFO(StartPosition, TYPE_INFO(QuatT))
STRUCT_INFO_END(SPEED_CHUNK_DESC_2)
STRUCT_INFO_BEGIN(MTL_NAME_CHUNK_DESC_0800)
STRUCT_VAR_INFO(nFlags, TYPE_INFO(int))
STRUCT_VAR_INFO(nFlags2, TYPE_INFO(int))
STRUCT_VAR_INFO(name, TYPE_ARRAY(128, TYPE_INFO(char)))
STRUCT_VAR_INFO(nPhysicalizeType, TYPE_INFO(int))
STRUCT_VAR_INFO(nSubMaterials, TYPE_INFO(int))
STRUCT_VAR_INFO(nSubMatChunkId, TYPE_ARRAY(MTL_NAME_CHUNK_DESC_0800_MAX_SUB_MATERIALS, TYPE_INFO(int)))
STRUCT_VAR_INFO(nAdvancedDataChunkId, TYPE_INFO(int))
STRUCT_VAR_INFO(sh_opacity, TYPE_INFO(float))
STRUCT_VAR_INFO(reserve, TYPE_ARRAY(32, TYPE_INFO(int)))
STRUCT_INFO_END(MTL_NAME_CHUNK_DESC_0800)
STRUCT_INFO_BEGIN(MTL_NAME_CHUNK_DESC_0802)
STRUCT_VAR_INFO(name, TYPE_ARRAY(128, TYPE_INFO(char)))
STRUCT_VAR_INFO(nSubMaterials, TYPE_INFO(int))
STRUCT_INFO_END(MTL_NAME_CHUNK_DESC_0802)
STRUCT_INFO_BEGIN(MESH_CHUNK_DESC_0745)
STRUCT_VAR_INFO(flags1, TYPE_INFO(unsigned char))
STRUCT_VAR_INFO(flags2, TYPE_INFO(unsigned char))
STRUCT_VAR_INFO(nVerts, TYPE_INFO(int))
STRUCT_VAR_INFO(nTVerts, TYPE_INFO(int))
STRUCT_VAR_INFO(nFaces, TYPE_INFO(int))
STRUCT_VAR_INFO(VertAnimID, TYPE_INFO(int))
STRUCT_INFO_END(MESH_CHUNK_DESC_0745)
STRUCT_INFO_BEGIN(MESH_CHUNK_DESC_0801)
STRUCT_VAR_INFO(nFlags, TYPE_INFO(int))
STRUCT_VAR_INFO(nFlags2, TYPE_INFO(int))
STRUCT_VAR_INFO(nVerts, TYPE_INFO(int))
STRUCT_VAR_INFO(nIndices, TYPE_INFO(int))
STRUCT_VAR_INFO(nSubsets, TYPE_INFO(int))
STRUCT_VAR_INFO(nSubsetsChunkId, TYPE_INFO(int))
STRUCT_VAR_INFO(nVertAnimID, TYPE_INFO(int))
STRUCT_VAR_INFO(nStreamChunkID, TYPE_ARRAY(16, TYPE_INFO(int)))
STRUCT_VAR_INFO(nPhysicsDataChunkId, TYPE_ARRAY(4, TYPE_INFO(int)))
STRUCT_VAR_INFO(bboxMin, TYPE_INFO(Vec3))
STRUCT_VAR_INFO(bboxMax, TYPE_INFO(Vec3))
STRUCT_VAR_INFO(texMappingDensity, TYPE_INFO(float))
STRUCT_VAR_INFO(geometricMeanFaceArea, TYPE_INFO(float))
STRUCT_VAR_INFO(reserved, TYPE_ARRAY(30, TYPE_INFO(int)))
STRUCT_INFO_END(MESH_CHUNK_DESC_0801)
STRUCT_INFO_BEGIN(MESH_CHUNK_DESC_0802)
STRUCT_VAR_INFO(nFlags, TYPE_INFO(int))
STRUCT_VAR_INFO(nFlags2, TYPE_INFO(int))
STRUCT_VAR_INFO(nVerts, TYPE_INFO(int))
STRUCT_VAR_INFO(nIndices, TYPE_INFO(int))
STRUCT_VAR_INFO(nSubsets, TYPE_INFO(int))
STRUCT_VAR_INFO(nSubsetsChunkId, TYPE_INFO(int))
STRUCT_VAR_INFO(nVertAnimID, TYPE_INFO(int))
STRUCT_VAR_INFO(nStreamChunkID, TYPE_ARRAY(16, TYPE_ARRAY(8, TYPE_INFO(int))))
STRUCT_VAR_INFO(nPhysicsDataChunkId, TYPE_ARRAY(4, TYPE_INFO(int)))
STRUCT_VAR_INFO(bboxMin, TYPE_INFO(Vec3))
STRUCT_VAR_INFO(bboxMax, TYPE_INFO(Vec3))
STRUCT_VAR_INFO(texMappingDensity, TYPE_INFO(float))
STRUCT_VAR_INFO(geometricMeanFaceArea, TYPE_INFO(float))
STRUCT_VAR_INFO(reserved, TYPE_ARRAY(30, TYPE_INFO(int)))
STRUCT_INFO_END(MESH_CHUNK_DESC_0802)
STRUCT_INFO_BEGIN(STREAM_DATA_CHUNK_DESC_0800)
STRUCT_VAR_INFO(nFlags, TYPE_INFO(int))
STRUCT_VAR_INFO(nStreamType, TYPE_INFO(int))
STRUCT_VAR_INFO(nCount, TYPE_INFO(int))
STRUCT_VAR_INFO(nElementSize, TYPE_INFO(int))
STRUCT_VAR_INFO(reserved, TYPE_ARRAY(2, TYPE_INFO(int)))
STRUCT_INFO_END(STREAM_DATA_CHUNK_DESC_0800)
STRUCT_INFO_BEGIN(STREAM_DATA_CHUNK_DESC_0801)
STRUCT_VAR_INFO(nFlags, TYPE_INFO(int))
STRUCT_VAR_INFO(nStreamType, TYPE_INFO(int))
STRUCT_VAR_INFO(nStreamIndex, TYPE_INFO(int))
STRUCT_VAR_INFO(nCount, TYPE_INFO(int))
STRUCT_VAR_INFO(nElementSize, TYPE_INFO(int))
STRUCT_VAR_INFO(reserved, TYPE_ARRAY(2, TYPE_INFO(int)))
STRUCT_INFO_END(STREAM_DATA_CHUNK_DESC_0801)
STRUCT_INFO_BEGIN(MESH_SUBSETS_CHUNK_DESC_0800::MeshSubset)
STRUCT_VAR_INFO(nFirstIndexId, TYPE_INFO(int))
STRUCT_VAR_INFO(nNumIndices, TYPE_INFO(int))
STRUCT_VAR_INFO(nFirstVertId, TYPE_INFO(int))
STRUCT_VAR_INFO(nNumVerts, TYPE_INFO(int))
STRUCT_VAR_INFO(nMatID, TYPE_INFO(int))
STRUCT_VAR_INFO(fRadius, TYPE_INFO(float))
STRUCT_VAR_INFO(vCenter, TYPE_INFO(Vec3))
STRUCT_INFO_END(MESH_SUBSETS_CHUNK_DESC_0800::MeshSubset)
STRUCT_INFO_BEGIN(MESH_SUBSETS_CHUNK_DESC_0800::MeshBoneIDs)
STRUCT_VAR_INFO(numBoneIDs, TYPE_INFO(uint32))
STRUCT_VAR_INFO(arrBoneIDs, TYPE_ARRAY(128, TYPE_INFO(uint16)))
STRUCT_INFO_END(MESH_SUBSETS_CHUNK_DESC_0800::MeshBoneIDs)
STRUCT_INFO_BEGIN(MESH_SUBSETS_CHUNK_DESC_0800::MeshSubsetTexelDensity)
STRUCT_VAR_INFO(texelDensity, TYPE_INFO(float))
STRUCT_INFO_END(MESH_SUBSETS_CHUNK_DESC_0800::MeshSubsetTexelDensity)
STRUCT_INFO_BEGIN(MESH_SUBSETS_CHUNK_DESC_0800)
STRUCT_VAR_INFO(nFlags, TYPE_INFO(int))
STRUCT_VAR_INFO(nCount, TYPE_INFO(int))
STRUCT_VAR_INFO(reserved, TYPE_ARRAY(2, TYPE_INFO(int)))
STRUCT_INFO_END(MESH_SUBSETS_CHUNK_DESC_0800)
STRUCT_INFO_BEGIN(MESH_PHYSICS_DATA_CHUNK_DESC_0800)
STRUCT_VAR_INFO(nDataSize, TYPE_INFO(int))
STRUCT_VAR_INFO(nFlags, TYPE_INFO(int))
STRUCT_VAR_INFO(nTetrahedraDataSize, TYPE_INFO(int))
STRUCT_VAR_INFO(nTetrahedraChunkId, TYPE_INFO(int))
STRUCT_VAR_INFO(reserved, TYPE_ARRAY(2, TYPE_INFO(int)))
STRUCT_INFO_END(MESH_PHYSICS_DATA_CHUNK_DESC_0800)
STRUCT_INFO_BEGIN(BONEANIM_CHUNK_DESC_0290)
STRUCT_VAR_INFO(nBones, TYPE_INFO(int))
STRUCT_INFO_END(BONEANIM_CHUNK_DESC_0290)
STRUCT_INFO_BEGIN(BONENAMELIST_CHUNK_DESC_0745)
STRUCT_VAR_INFO(numEntities, TYPE_INFO(int))
STRUCT_INFO_END(BONENAMELIST_CHUNK_DESC_0745)
STRUCT_INFO_BEGIN(COMPILED_BONE_CHUNK_DESC_0800)
STRUCT_VAR_INFO(reserved, TYPE_ARRAY(32, TYPE_INFO(char)))
STRUCT_INFO_END(COMPILED_BONE_CHUNK_DESC_0800)
STRUCT_INFO_BEGIN(COMPILED_PHYSICALBONE_CHUNK_DESC_0800)
STRUCT_VAR_INFO(reserved, TYPE_ARRAY(32, TYPE_INFO(char)))
STRUCT_INFO_END(COMPILED_PHYSICALBONE_CHUNK_DESC_0800)
STRUCT_INFO_BEGIN(COMPILED_PHYSICALPROXY_CHUNK_DESC_0800)
STRUCT_VAR_INFO(numPhysicalProxies, TYPE_INFO(uint32))
STRUCT_INFO_END(COMPILED_PHYSICALPROXY_CHUNK_DESC_0800)
STRUCT_INFO_BEGIN(COMPILED_MORPHTARGETS_CHUNK_DESC_0800)
STRUCT_VAR_INFO(numMorphTargets, TYPE_INFO(uint32))
STRUCT_INFO_END(COMPILED_MORPHTARGETS_CHUNK_DESC_0800)
STRUCT_INFO_BEGIN(COMPILED_INTSKINVERTICES_CHUNK_DESC_0800)
STRUCT_VAR_INFO(reserved, TYPE_ARRAY(32, TYPE_INFO(char)))
STRUCT_INFO_END(COMPILED_INTSKINVERTICES_CHUNK_DESC_0800)
STRUCT_INFO_BEGIN(BaseKey)
STRUCT_VAR_INFO(time, TYPE_INFO(int))
STRUCT_INFO_END(BaseKey)
STRUCT_INFO_BEGIN(BaseTCB)
STRUCT_VAR_INFO(t, TYPE_INFO(float))
STRUCT_VAR_INFO(c, TYPE_INFO(float))
STRUCT_VAR_INFO(b, TYPE_INFO(float))
STRUCT_VAR_INFO(ein, TYPE_INFO(float))
STRUCT_VAR_INFO(eout, TYPE_INFO(float))
STRUCT_INFO_END(BaseTCB)
STRUCT_INFO_BEGIN(BaseKey3)
STRUCT_BASE_INFO(BaseKey)
STRUCT_VAR_INFO(val, TYPE_INFO(Vec3))
STRUCT_INFO_END(BaseKey3)
STRUCT_INFO_BEGIN(BaseKeyQ)
STRUCT_BASE_INFO(BaseKey)
STRUCT_VAR_INFO(val, TYPE_INFO(CryQuat))
STRUCT_INFO_END(BaseKeyQ)
STRUCT_INFO_BEGIN(CryTCB3Key)
STRUCT_BASE_INFO(BaseKey3)
STRUCT_BASE_INFO(BaseTCB)
STRUCT_INFO_END(CryTCB3Key)
STRUCT_INFO_BEGIN(CryTCBQKey)
STRUCT_BASE_INFO(BaseKeyQ)
STRUCT_BASE_INFO(BaseTCB)
STRUCT_INFO_END(CryTCBQKey)
STRUCT_INFO_BEGIN(CryKeyPQLog)
STRUCT_VAR_INFO(nTime, TYPE_INFO(int))
STRUCT_VAR_INFO(vPos, TYPE_INFO(Vec3))
STRUCT_VAR_INFO(vRotLog, TYPE_INFO(Vec3))
STRUCT_INFO_END(CryKeyPQLog)
ENUM_INFO_BEGIN(CtrlTypes)
ENUM_ELEM_INFO(, CTRL_NONE)
ENUM_ELEM_INFO(, CTRL_CRYBONE)
ENUM_ELEM_INFO(, CTRL_LINEER1)
ENUM_ELEM_INFO(, CTRL_LINEER3)
ENUM_ELEM_INFO(, CTRL_LINEERQ)
ENUM_ELEM_INFO(, CTRL_BEZIER1)
ENUM_ELEM_INFO(, CTRL_BEZIER3)
ENUM_ELEM_INFO(, CTRL_BEZIERQ)
ENUM_ELEM_INFO(, CTRL_TCB1)
ENUM_ELEM_INFO(, CTRL_TCB3)
ENUM_ELEM_INFO(, CTRL_TCBQ)
ENUM_ELEM_INFO(, CTRL_BSPLINE_2O)
ENUM_ELEM_INFO(, CTRL_BSPLINE_1O)
ENUM_ELEM_INFO(, CTRL_BSPLINE_2C)
ENUM_ELEM_INFO(, CTRL_BSPLINE_1C)
ENUM_ELEM_INFO(, CTRL_CONST)
ENUM_INFO_END(CtrlTypes)
STRUCT_INFO_BEGIN(CONTROLLER_CHUNK_DESC_0826)
STRUCT_VAR_INFO(type, TYPE_INFO(CtrlTypes))
STRUCT_VAR_INFO(nKeys, TYPE_INFO(int))
STRUCT_VAR_INFO(nFlags, TYPE_INFO(unsigned int))
STRUCT_VAR_INFO(nControllerId, TYPE_INFO(unsigned int))
STRUCT_INFO_END(CONTROLLER_CHUNK_DESC_0826)
STRUCT_INFO_BEGIN(CONTROLLER_CHUNK_DESC_0827)
STRUCT_VAR_INFO(numKeys, TYPE_INFO(unsigned int))
STRUCT_VAR_INFO(nControllerId, TYPE_INFO(unsigned int))
STRUCT_INFO_END(CONTROLLER_CHUNK_DESC_0827)
STRUCT_INFO_BEGIN(CONTROLLER_CHUNK_DESC_0829)
STRUCT_VAR_INFO(nControllerId, TYPE_INFO(unsigned int))
STRUCT_VAR_INFO(numRotationKeys, TYPE_INFO(uint16))
STRUCT_VAR_INFO(numPositionKeys, TYPE_INFO(uint16))
STRUCT_VAR_INFO(RotationFormat, TYPE_INFO(uint8))
STRUCT_VAR_INFO(RotationTimeFormat, TYPE_INFO(uint8))
STRUCT_VAR_INFO(PositionFormat, TYPE_INFO(uint8))
STRUCT_VAR_INFO(PositionKeysInfo, TYPE_INFO(uint8))
STRUCT_VAR_INFO(PositionTimeFormat, TYPE_INFO(uint8))
STRUCT_VAR_INFO(TracksAligned, TYPE_INFO(uint8))
STRUCT_INFO_END(CONTROLLER_CHUNK_DESC_0829)
STRUCT_INFO_BEGIN(CONTROLLER_CHUNK_DESC_0830)
STRUCT_VAR_INFO(numKeys, TYPE_INFO(unsigned int))
STRUCT_VAR_INFO(nFlags, Type_info(unsigned int))
STRUCT_VAR_INFO(nControllerId, TYPE_INFO(unsigned int))
STRUCT_INFO_END(CONTROLLER_CHUNK_DESC_0830)
STRUCT_INFO_BEGIN(CONTROLLER_CHUNK_DESC_0831)
STRUCT_VAR_INFO(nControllerId, TYPE_INFO(unsigned int))
STRUCT_VAR_INFO(nFlags, Type_info(unsigned int))
STRUCT_VAR_INFO(numRotationKeys, TYPE_INFO(uint16))
STRUCT_VAR_INFO(numPositionKeys, TYPE_INFO(uint16))
STRUCT_VAR_INFO(RotationFormat, TYPE_INFO(uint8))
STRUCT_VAR_INFO(RotationTimeFormat, TYPE_INFO(uint8))
STRUCT_VAR_INFO(PositionFormat, TYPE_INFO(uint8))
STRUCT_VAR_INFO(PositionKeysInfo, TYPE_INFO(uint8))
STRUCT_VAR_INFO(PositionTimeFormat, TYPE_INFO(uint8))
STRUCT_VAR_INFO(TracksAligned, TYPE_INFO(uint8))
STRUCT_INFO_END(CONTROLLER_CHUNK_DESC_0831)
STRUCT_INFO_BEGIN(CONTROLLER_CHUNK_DESC_0905)
STRUCT_VAR_INFO(numKeyPos, TYPE_INFO(uint32))
STRUCT_VAR_INFO(numKeyRot, TYPE_INFO(uint32))
STRUCT_VAR_INFO(numKeyTime, TYPE_INFO(uint32))
STRUCT_VAR_INFO(numAnims, TYPE_INFO(uint32))
STRUCT_INFO_END(CONTROLLER_CHUNK_DESC_0905)
STRUCT_INFO_BEGIN(NODE_CHUNK_DESC_0824)
STRUCT_VAR_INFO(name, TYPE_ARRAY(64, TYPE_INFO(char)))
STRUCT_VAR_INFO(ObjectID, TYPE_INFO(int))
STRUCT_VAR_INFO(ParentID, TYPE_INFO(int))
STRUCT_VAR_INFO(nChildren, TYPE_INFO(int))
STRUCT_VAR_INFO(MatID, TYPE_INFO(int))
STRUCT_VAR_INFO(_obsoleteA_, TYPE_ARRAY(4, TYPE_INFO(uint8)))
STRUCT_VAR_INFO(tm, TYPE_ARRAY(4, TYPE_ARRAY(4, TYPE_INFO(float))))
STRUCT_VAR_INFO(_obsoleteB_, TYPE_ARRAY(3, TYPE_INFO(float)))
STRUCT_VAR_INFO(_obsoleteC_, TYPE_ARRAY(4, TYPE_INFO(float)))
STRUCT_VAR_INFO(_obsoleteD_, TYPE_ARRAY(3, TYPE_INFO(float)))
STRUCT_VAR_INFO(pos_cont_id, TYPE_INFO(int))
STRUCT_VAR_INFO(rot_cont_id, TYPE_INFO(int))
STRUCT_VAR_INFO(scl_cont_id, TYPE_INFO(int))
STRUCT_VAR_INFO(PropStrLen, TYPE_INFO(int))
STRUCT_INFO_END(NODE_CHUNK_DESC_0824)
ENUM_INFO_BEGIN(HelperTypes)
ENUM_ELEM_INFO(, HP_POINT)
ENUM_ELEM_INFO(, HP_DUMMY)
ENUM_ELEM_INFO(, HP_XREF)
ENUM_ELEM_INFO(, HP_CAMERA)
ENUM_ELEM_INFO(, HP_GEOMETRY)
ENUM_INFO_END(HelperTypes)
STRUCT_INFO_BEGIN(HELPER_CHUNK_DESC_0744)
STRUCT_VAR_INFO(type, TYPE_INFO(HelperTypes))
STRUCT_VAR_INFO(size, TYPE_INFO(Vec3))
STRUCT_INFO_END(HELPER_CHUNK_DESC_0744)
STRUCT_INFO_BEGIN(MESHMORPHTARGET_CHUNK_DESC_0001)
STRUCT_VAR_INFO(nChunkIdMesh, TYPE_INFO(unsigned int))
STRUCT_VAR_INFO(numMorphVertices, TYPE_INFO(unsigned int))
STRUCT_INFO_END(MESHMORPHTARGET_CHUNK_DESC_0001)
STRUCT_INFO_BEGIN(SMeshMorphTargetVertex)
STRUCT_VAR_INFO(nVertexId, TYPE_INFO(unsigned int))
STRUCT_VAR_INFO(ptVertex, TYPE_INFO(Vec3))
STRUCT_INFO_END(SMeshMorphTargetVertex)
STRUCT_INFO_BEGIN(SMeshMorphTargetHeader)
STRUCT_VAR_INFO(MeshID, TYPE_INFO(uint32))
STRUCT_VAR_INFO(NameLength, TYPE_INFO(uint32))
STRUCT_VAR_INFO(numIntVertices, TYPE_INFO(uint32))
STRUCT_VAR_INFO(numExtVertices, TYPE_INFO(uint32))
STRUCT_INFO_END(SMeshMorphTargetHeader)
STRUCT_INFO_BEGIN(SMeshPhysicalProxyHeader)
STRUCT_VAR_INFO(ChunkID, TYPE_INFO(uint32))
STRUCT_VAR_INFO(numPoints, TYPE_INFO(uint32))
STRUCT_VAR_INFO(numIndices, TYPE_INFO(uint32))
STRUCT_VAR_INFO(numMaterials, TYPE_INFO(uint32))
STRUCT_INFO_END(SMeshPhysicalProxyHeader)
STRUCT_INFO_BEGIN(BONEINITIALPOS_CHUNK_DESC_0001)
STRUCT_VAR_INFO(nChunkIdMesh, TYPE_INFO(unsigned int))
STRUCT_VAR_INFO(numBones, TYPE_INFO(unsigned int))
STRUCT_INFO_END(BONEINITIALPOS_CHUNK_DESC_0001)
STRUCT_INFO_BEGIN(SBoneInitPosMatrix)
STRUCT_VAR_INFO(mx, TYPE_ARRAY(4, TYPE_ARRAY(3, TYPE_INFO(float))))
STRUCT_INFO_END(SBoneInitPosMatrix)
STRUCT_INFO_BEGIN(EXPORT_FLAGS_CHUNK_DESC)
STRUCT_VAR_INFO(flags, TYPE_INFO(unsigned int))
STRUCT_VAR_INFO(rc_version, TYPE_ARRAY(4, TYPE_INFO(unsigned int)))
STRUCT_VAR_INFO(rc_version_string, TYPE_ARRAY(16, TYPE_INFO(char)))
STRUCT_VAR_INFO(assetAuthorTool, TYPE_INFO(uint32))
STRUCT_VAR_INFO(authorToolVersion, TYPE_INFO(uint32))
STRUCT_VAR_INFO(reserved, TYPE_ARRAY(30, TYPE_INFO(unsigned int)))
STRUCT_INFO_END(EXPORT_FLAGS_CHUNK_DESC)
STRUCT_INFO_BEGIN(BREAKABLE_PHYSICS_CHUNK_DESC)
STRUCT_VAR_INFO(granularity, TYPE_INFO(unsigned int))
STRUCT_VAR_INFO(nMode, TYPE_INFO(int))
STRUCT_VAR_INFO(nRetVtx, TYPE_INFO(int))
STRUCT_VAR_INFO(nRetTets, TYPE_INFO(int))
STRUCT_VAR_INFO(nReserved, TYPE_ARRAY(10, TYPE_INFO(int)))
STRUCT_INFO_END(BREAKABLE_PHYSICS_CHUNK_DESC)
STRUCT_INFO_BEGIN(FOLIAGE_INFO_CHUNK_DESC)
STRUCT_VAR_INFO(nSpines, TYPE_INFO(int))
STRUCT_VAR_INFO(nSpineVtx, TYPE_INFO(int))
STRUCT_VAR_INFO(nSkinnedVtx, TYPE_INFO(int))
STRUCT_VAR_INFO(nBoneIds, TYPE_INFO(int))
STRUCT_INFO_END(FOLIAGE_INFO_CHUNK_DESC)
STRUCT_INFO_BEGIN(FOLIAGE_SPINE_SUB_CHUNK)
STRUCT_VAR_INFO(nVtx, TYPE_INFO(char))
STRUCT_VAR_INFO(len, TYPE_INFO(float))
STRUCT_VAR_INFO(navg, TYPE_INFO(Vec3))
STRUCT_VAR_INFO(iAttachSpine, TYPE_INFO(unsigned char))
STRUCT_VAR_INFO(iAttachSeg, TYPE_INFO(unsigned char))
STRUCT_INFO_END(FOLIAGE_SPINE_SUB_CHUNK)
@@ -0,0 +1,226 @@
/*
* 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.
*
*/
#pragma once
#include "LegacyAllocator.h"
#include <AzCore/std/algorithm.h>
//-----------------------------------------------------------------------------
// CryModule allocation API
//-----------------------------------------------------------------------------
#define CryModuleMalloc(size) CryModuleMallocImpl(size, __FILE__, __LINE__)
inline void* CryModuleMallocImpl(size_t size, const char* file, const int line)
{
return AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().Allocate(size, 0, 0, "LegacyAllocator malloc", file, line);
}
#define CryModuleFree(ptr) CryModuleFreeImpl(ptr, __FILE__, __LINE__)
#define CryModuleMemalignFree(ptr) CryModuleFreeImpl(ptr, __FILE__, __LINE__)
inline void CryModuleFreeImpl(void* ptr, const char* file, const int line)
{
AZ::IAllocator& allocator = AZ::AllocatorInstance<AZ::LegacyAllocator>::GetAllocator();
if (allocator.IsAllocationSourceChanged())
{
allocator.GetAllocationSource()->DeAllocate(ptr);
}
else
{
static_cast<AZ::LegacyAllocator&>(allocator).DeAllocate(ptr, file, line);
}
}
#define CryModuleMemalign(size, alignment) CryModuleMemalignImpl(size, alignment, __FILE__, __LINE__)
inline void* CryModuleMemalignImpl(size_t size, size_t alignment, const char* file, const int line)
{
return AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().Allocate(size, alignment, 0, "LegacyAllocator memalign", file, line);
}
#define CryModuleCalloc(num, size) CryModuleCallocImpl(num, size, __FILE__, __LINE__)
inline void* CryModuleCallocImpl(size_t num, size_t size, const char* file, const int line)
{
void* ptr = AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().Allocate(num * size, 0, 0, "LegacyAllocator calloc", file, line);
::memset(ptr, 0, num * size);
return ptr;
}
#define CryModuleRealloc(ptr, size) CryModuleReallocAlignImpl(ptr, size, 0, __FILE__, __LINE__)
#define CryModuleReallocAlign(ptr, size, alignment) CryModuleReallocAlignImpl(ptr, size, alignment, __FILE__, __LINE__)
inline void* CryModuleReallocAlignImpl(void* prev, size_t size, size_t alignment, const char* file, const int line)
{
if (!prev)
{
// map realloc(nullptr, ...) -> alloc() so that we can track the location of the initial alloc
return CryModuleMemalignImpl(size, alignment, file, line);
}
if (size == 0)
{
CryModuleFreeImpl(prev, file, line);
return nullptr;
}
// There should not be any code using CryRealloc during static-init time or before the allocators
// are initialized.
#if defined(AZ_MONOLITHIC_BUILD)
if (!AZ::AllocatorInstance<AZ::LegacyAllocator>::IsReady())
{
AZ_Assert(false, "CryRealloc/CryReallocAlign cannot be used unless the LegacyAllocator has been initialized");
return nullptr;
}
#endif
AZ::IAllocator& allocator = AZ::AllocatorInstance<AZ::LegacyAllocator>::GetAllocator();
void *ptr;
if (allocator.IsAllocationSourceChanged())
{
ptr = allocator.GetAllocationSource()->ReAllocate(prev, size, 0);
}
else
{
ptr = static_cast<AZ::LegacyAllocator&>(allocator).ReAllocate(prev, size, 0, file, line);
}
return ptr;
}
//-----------------------------------------------------------------------------
// CryCrt alloc API
//-----------------------------------------------------------------------------
inline size_t CryCrtSize(void* p)
{
return AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().AllocationSize(p);
}
inline void* CryCrtMalloc(size_t size)
{
return CryModuleMalloc(size);
}
inline size_t CryCrtFree(void* p)
{
size_t size = CryCrtSize(p);
CryModuleFree(p);
return size;
};
//-----------------------------------------------------------------------------
// CrySystemCrt alloc API
//-----------------------------------------------------------------------------
inline size_t CrySystemCrtSize(void* p)
{
return AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().AllocationSize(p);
}
inline void* CrySystemCrtMalloc(size_t size)
{
return AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().Allocate(size, 0, 0, "AZ::LegacyAllocator");
}
inline void* CrySystemCrtRealloc(void* p, size_t size)
{
// Use LegacyAllocator's special ReAllocate
return AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().ReAllocate(p, size, 0);
}
inline size_t CrySystemCrtFree(void* p)
{
size_t size = CrySystemCrtSize(p);
CryModuleFree(p);
return size;
}
inline size_t CrySystemCrtGetUsedSpace()
{
return AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().NumAllocatedBytes();
}
//-----------------------------------------------------------------------------
// CryMalloc API
//-----------------------------------------------------------------------------
inline void* CryMalloc(size_t size, size_t& allocated, size_t alignment)
{
if (!size)
{
allocated = 0;
return nullptr;
}
// The original implementation guaranteed 16 byte min alignment
alignment = AZStd::GetMax<size_t>(alignment, 16);
void* ptr = AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().Allocate(size, alignment, 0, "CryMalloc", __FILE__, __LINE__);
allocated = AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().AllocationSize(ptr);
return ptr;
}
inline void* CryRealloc(void* memblock, size_t size, size_t& allocated, size_t& oldsize, size_t alignment)
{
oldsize = AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().AllocationSize(memblock);
void* ptr = AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().ReAllocate(memblock, size, alignment);
allocated = AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().AllocationSize(ptr);
return ptr;
}
inline size_t CryFree(void* p, size_t /*alignment*/)
{
size_t size = AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().AllocationSize(p);
AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().DeAllocate(p, size);
return size;
}
inline size_t CryGetMemSize(void* memblock, size_t /*sourceSize*/)
{
return AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().AllocationSize(memblock);
}
inline int CryMemoryGetAllocatedSize()
{
return AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().NumAllocatedBytes();
}
//////////////////////////////////////////////////////////////////////////
inline int CryMemoryGetPoolSize()
{
return 0;
}
//////////////////////////////////////////////////////////////////////////
inline int CryStats([[maybe_unused]] char* buf)
{
return 0;
}
inline int CryGetUsedHeapSize()
{
return AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().NumAllocatedBytes();
}
inline int CryGetWastedHeapSize()
{
return 0;
}
inline void CryCleanup()
{
AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().GarbageCollect();
}
inline void CryResetStats(void)
{
}
+51
View File
@@ -0,0 +1,51 @@
/*
* 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.
#include <CryCommon/CryLibrary.h>
#if !defined(AZ_RESTRICTED_PLATFORM) && defined(WIN32)
HMODULE CryLoadLibrary(const char* libName)
{
HMODULE module = ::LoadLibraryA(libName);
if (module != NULL)
{
// We need to inject the environment first thing so that allocators are available immediately
InjectEnvironmentFunction injectEnv = reinterpret_cast<InjectEnvironmentFunction>(::GetProcAddress(module, INJECT_ENVIRONMENT_FUNCTION));
if (injectEnv)
{
auto env = AZ::Environment::GetInstance();
injectEnv(env);
}
}
return module;
}
// Cry code seems to have used void* as their abstraction for HMODULE across
// platforms.
bool CryFreeLibrary(void* lib)
{
if (lib != NULL)
{
DetachEnvironmentFunction detachEnv = reinterpret_cast<DetachEnvironmentFunction>(::GetProcAddress((HMODULE)lib, DETACH_ENVIRONMENT_FUNCTION));
if (detachEnv)
{
detachEnv();
}
return ::FreeLibrary((HMODULE)lib) != FALSE;
}
return false;
}
#endif
+199
View File
@@ -0,0 +1,199 @@
/*
* 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.
#pragma once
/*!
CryLibrary
Convenience-Macros which abstract the use of DLLs/shared libraries in a platform independent way.
A short explanation of the different macros follows:
CrySharedLibrarySupported:
This macro can be used to test if the current active platform supports shared library calls. The default
value is false. This gets redefined if a certain platform (WIN32 or LINUX) is desired.
CrySharedLibraryPrefix:
The default prefix which will get prepended to library names in calls to CryLoadLibraryDefName
(see below).
CrySharedLibraryExtension:
The default extension which will get appended to library names in calls to CryLoadLibraryDefName
(see below).
CryLoadLibrary(libName):
Loads a shared library.
CryLoadLibraryDefName(libName):
Loads a shared library. The platform-specific default library prefix and extension are appended to the libName.
This allows writing of somewhat platform-independent library loading code and is therefore the function
which should be used most of the time, unless some special extensions are used (e.g. for plugins).
CryGetProcAddress(libHandle, procName):
Import function from the library presented by libHandle.
CryFreeLibrary(libHandle):
Unload the library presented by libHandle.
HISTORY:
03.03.2004 MarcoK
- initial version
- added to CryPlatform
*/
#include <stdio.h>
#include <AzCore/PlatformDef.h>
#include <AzCore/Module/Environment.h>
#define INJECT_ENVIRONMENT_FUNCTION "InjectEnvironment"
#define DETACH_ENVIRONMENT_FUNCTION "DetachEnvironment"
using InjectEnvironmentFunction = void(*)(void*);
using DetachEnvironmentFunction = void(*)();
#if defined(AZ_RESTRICTED_PLATFORM)
#include AZ_RESTRICTED_FILE(CryLibrary_h)
#elif defined(WIN32)
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif
#include <CryWindows.h>
HMODULE CryLoadLibrary(const char* libName);
// Cry code seems to have used void* as their abstraction for HMODULE across
// platforms.
bool CryFreeLibrary(void* lib);
#define CRYLIBRARY_H_TRAIT_USE_WINDOWS_DLL 1
#elif ((defined(LINUX) || AZ_TRAIT_OS_PLATFORM_APPLE))
#include <dlfcn.h>
#include <stdlib.h>
#include <libgen.h>
#include "platform.h"
#include <AzCore/Debug/Trace.h>
// for compatibility with code written for windows
#define CrySharedLibrarySupported true
#define CrySharedLibraryPrefix "lib"
#if AZ_TRAIT_OS_PLATFORM_APPLE
#include <mach-o/dyld.h>
#define CrySharedLibraryExtension ".dylib"
#else
#define CrySharedLibraryExtension ".so"
#endif
#define CryGetProcAddress(libHandle, procName) ::dlsym(libHandle, procName)
#define HMODULE void*
static const char* gEnvName("MODULE_PATH");
static const char* GetModulePath()
{
return getenv(gEnvName);
}
static void SetModulePath(const char* pModulePath)
{
setenv(gEnvName, pModulePath ? pModulePath : "", true);
}
// bInModulePath is only ever set to false in RC, because rc needs to load dlls from a $PATH that
// it has modified to include ..
static HMODULE CryLoadLibrary(const char* libName, bool bLazy = false, bool bInModulePath = true)
{
const char* libPath = nullptr;
char pathBuffer[MAX_PATH] = {0};
libPath = libName;
#if !defined(AZ_PLATFORM_ANDROID)
if (bInModulePath)
{
char exePath[MAX_PATH + 1] = { 0 };
const char* modulePath = GetModulePath();
if (!modulePath)
{
modulePath = ".";
#if defined(LINUX)
int len = readlink("/proc/self/exe", exePath, MAX_PATH);
if (len != -1)
{
exePath[len] = 0;
modulePath = dirname(exePath);
}
#elif AZ_TRAIT_OS_PLATFORM_APPLE
uint32_t bufsize = MAX_PATH;
if (_NSGetExecutablePath(exePath, &bufsize) == 0)
{
exePath[bufsize] = 0;
modulePath = dirname(exePath);
}
#endif
}
sprintf_s(pathBuffer, "%s/%s", modulePath, libName);
libPath = pathBuffer;
}
#endif
HMODULE module;
#if defined(LINUX) && !defined(ANDROID)
module = ::dlopen(libPath, (bLazy ? RTLD_LAZY : RTLD_NOW) | RTLD_DEEPBIND);
#else
module = ::dlopen(libPath, bLazy ? RTLD_LAZY : RTLD_NOW);
#endif
AZ_Warning("LMBR", module, "Can't load library [%s]: %s", libName, dlerror());
if (module)
{
// We need to inject the environment first thing so that allocators are available immediately
InjectEnvironmentFunction injectEnv = reinterpret_cast<InjectEnvironmentFunction>(CryGetProcAddress(module, INJECT_ENVIRONMENT_FUNCTION));
if (injectEnv)
{
injectEnv(AZ::Environment::GetInstance());
}
}
return module;
}
static bool CryFreeLibrary(void* lib)
{
if (lib)
{
DetachEnvironmentFunction detachEnv = reinterpret_cast<DetachEnvironmentFunction>(CryGetProcAddress(lib, DETACH_ENVIRONMENT_FUNCTION));
if (detachEnv)
{
detachEnv();
}
return (::dlclose(lib) == 0);
}
return false;
}
#endif
#if CRYLIBRARY_H_TRAIT_USE_WINDOWS_DLL
#define CrySharedLibrarySupported true
#define CrySharedLibraryPrefix ""
#define CrySharedLibraryExtension ".dll"
#define CryGetProcAddress(libHandle, procName) ::GetProcAddress((HMODULE)(libHandle), procName)
#elif !defined(CrySharedLibrarySupported)
#define CrySharedLibrarySupported false
#define CrySharedLibraryPrefix ""
#define CrySharedLibraryExtension ""
#define CryLoadLibrary(libName) NULL
#define CryGetProcAddress(libHandle, procName) NULL
#define CryFreeLibrary(libHandle)
#define GetModuleHandle(x) 0
#endif
#define CryLibraryDefName(libName) CrySharedLibraryPrefix libName CrySharedLibraryExtension
#define CryLoadLibraryDefName(libName) CryLoadLibrary(CryLibraryDefName(libName))
+618
View File
@@ -0,0 +1,618 @@
/*
* 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 : A simple, intelligent and efficient container for listeners.
// This is designed to provide a simple & consistent interface and behavior
// for adding, removing and iterating listeners - hopefully avoiding the
// common pitfalls such as duplicated elements, invalid iterators and
// dangling pointers.
#ifndef CRYINCLUDE_CRYCOMMON_CRYLISTENERSET_H
#define CRYINCLUDE_CRYCOMMON_CRYLISTENERSET_H
#pragma once
#include <CrySizer.h>
/************************************************************************
Core elements:
* CListenerSet<T> - The collection of listeners.
* CListenerSet<T>::Notifier - The iterator for safely calling listeners in sequence.
[Where T is a pointer or something with pointer traits]
Advantages:
* Greatly reduces the complexity of managing listener collections.
* Can safely add and remove listeners during listener iteration.
* Automatically and safely removes NULL elements.
* Simple interface (but different from an STL collection to avoid confusion).
* Checks to see all listeners have been removed at destruction.
* Low overhead implementation (cheap use of std::vector and minimal heap allocation).
* Can add debug checks as needed - including stack tracing of Add() calls.
* Safe for recursive notification chains.
* Works with vanilla pointers and smart pointers.
* Provides full support for named listeners to aid debugging.
* Listener names tracked during notification to help resolve crashes.
* Designed to ensure names are recorded correctly in crash dump files.
Named listener support:
Supplying a name for a listener provides valuable debug information in the following cases:
* Resolving crashes during listener notification - the name will help trace what listener caused the crash.
* Resolving which listeners are present in the CListenerSet during runtime.
IMPORTANT: Please ensure heap allocated strings passed in as names are marked as such ie.
m_listeners.Add(pListener, "MyListener"); // OK: Static string passed.
m_listeners.Add(pListener2, m_myName.c_str(), false); // OK: Heap string passed and marked as non-static.
m_listeners.Add(pListener3, m_myName.c_str(), true); // BAD: Heap string passed and marked as static (potential CRASH).
Why store names like this?
* 99% of use cases use static strings - so why allocate memory to make copies of static data?
* Pointers to static strings will *always* survive crash dumps - great for debugging crashes.
* We can enable debug support in QA builds - key for catching rare listener related crashes.
Example:
class CMyWorld
{
public:
void AddListener(IMyWorldListener* pListener, const char* szName) { m_listeners.Add(pListener, szName); }
void RemoveListener(IMyWorldListener* pListener) { m_listeners.Remove(pListener); }
void NotifyListeners(CSomeEvent& event)
{
for (TWorldListeners::Notifier notifier(m_listeners); notifier.IsValid(); notifier.Next())
{
notifier->OnWorldEvent(event);
}
}
private:
typedef CListenerSet<IMyWorldListener*> TWorldListeners;
TWorldListeners m_listeners;
};
// Implements IMyWorldListener
CMyWorldUser::OnWorldEvent(CSomeEvent& event)
{
// OK: Removing a listeners within an event handler
m_pWorld->RemoveListener(this);
// OK: Notifying listeners within an event handler
m_pWorld->NotifyListeners(CSomeEvent newEvent(USER_REMOVED, this));
}
*************************************************************************/
#ifndef _RELEASE
#define CRY_LISTENERSET_DEBUG
#endif
// Forward decl.
template <typename T>
class CListenerNotifier;
// Main listener collection class used in conjunction with CListenerNotifier.
template <typename T>
class CListenerSet
{
public:
// NOTE: No default constructor in favor of forcing users to provide an expectedCapacity
inline CListenerSet(size_t expectedCapacity);
inline /*non-virtual*/ ~CListenerSet();
// Appends a listener to the end of the collection. Name is optional but recommended.
inline bool Add(T pListener, const char* name = NULL, bool staticName = true);
// Removes a listener from the collection.
inline void Remove(T pListener);
// Removes all listeners from the collection (NOTE: prefer informing listeners to remove themselves)
inline void Clear(bool bFreeMemory = false);
// Returns true if this contains pListener
inline bool Contains(T pListener) const;
// Returns number of valid listeners
inline size_t ValidListenerCount() const;
// Returns true if no valid listeners exist
inline bool Empty() const;
// Reserves space to help avoid runtime reallocation
inline void Reserve(size_t capacity);
// Returns the memory size of this object (to support CrySizer)
inline size_t MemSize() const;
// Returns true if currently in the process of notifying listeners.
inline bool IsNotifying() const;
// Allow access for Notifier for iteration
friend class CListenerNotifier<T>;
// Allow TListeners::Notifier style usage
typedef class CListenerNotifier<T> Notifier;
void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddContainer(m_listeners);
#if defined(CRY_LISTENERSET_DEBUG)
pSizer->AddContainer(m_allocatedNames);
#endif
}
private: // DO NOT REMOVE - following methods only to be accessed only via CNotifier
struct ListenerRecord
{
ListenerRecord()
: m_pListener() {}
ListenerRecord(T pListener, [[maybe_unused]] const char* szName = NULL)
: m_pListener(pListener)
#ifdef CRY_LISTENERSET_DEBUG
, m_szName(szName)
#endif
{}
bool operator==(const ListenerRecord& other) const { return m_pListener == other.m_pListener; }
bool operator==(const T& other) const { return m_pListener == other; }
T m_pListener; // The listener reference
#ifdef CRY_LISTENERSET_DEBUG
const char* m_szName; // Name of tracked listener (owned if pointing to data in m_allocatedNames)
#endif
};
typedef std::vector<ListenerRecord> TListenerVec;
typedef std::vector<string> TAllocatedNameVec;
inline void StartNotificationScope();
inline void EndNotificationScope();
inline void EraseNullElements();
private:
TListenerVec m_listeners; // Collection of unique listeners.
size_t m_activeNotifications; // Counts current notifications in progress (cleanup cannot occur unless this is 0).
bool m_cleanupRequired; // Indicates NULL elements in listener.
bool m_freeMemOnCleanup; // Indicates how to clean up.
#ifdef CRY_LISTENERSET_DEBUG
// Used to delete heap allocated names
inline void DeleteName(const char* name);
TAllocatedNameVec m_allocatedNames; // Collection of strings pointing at heap allocated (i.e. copied) names (typically empty)
#endif
};
// Helper class used to iterate listeners during listener notification.
template <typename T>
class CListenerNotifier
{
public:
ILINE CListenerNotifier(CListenerSet<T>& listeners);
ILINE /*non-virtual*/ ~CListenerNotifier();
// True if the current element is ready for iteration
ILINE bool IsValid();
// Dereference current listener, MUST only be done after a call to IsValid().
ILINE T operator->();
// Dereference current listener, MUST only be done after a call to IsValid().
ILINE T operator*();
// Move to next valid listener (skipping NULL elements)
ILINE void Next();
// Returns the name of the listener (if available)
inline const char* Name() const;
private:
CListenerSet<T>& m_listenerSet; // ListenerSet being notified
T m_pListener; // Current listener at index (resolved by IsValid(), cleared after each dereference)
size_t m_index; // Current index of element (incremented by next)
#ifdef CRY_LISTENERSET_DEBUG
const char* m_szName; // Name of the listener (if provided) to aid debugging
#endif
};
/******************************************************************************************/
template <typename T>
inline CListenerSet<T>::CListenerSet(size_t expectedCapacity)
: m_activeNotifications(0)
, m_cleanupRequired(false)
, m_freeMemOnCleanup(false)
{
// Reserve the expected capacity to avoid reallocations
m_listeners.reserve(expectedCapacity);
}
template <typename T>
inline CListenerSet<T>::~CListenerSet()
{
// Ensure no notifications are in progress
CRY_ASSERT(m_activeNotifications == 0);
// Ensure NULL elements were removed at end of last notification
CRY_ASSERT(!m_cleanupRequired);
}
// Appends a listener to the end of the collection. Name is optional but recommended.
template <typename T>
inline bool CListenerSet<T>::Add(T pListener, const char* name, [[maybe_unused]] bool staticName)
{
bool success = false;
// Ensure the listener exists
CRY_ASSERT(pListener);
if (pListener)
{
// Ensure the listener is only added once
if (!Contains(pListener))
{
// Resolve name buffer safe for usage outside of this scope
const char* safeName = name;
#ifdef CRY_LISTENERSET_DEBUG
// If a name was provided but it's not static data
if (name && !staticName)
{
// Add it to the list of heap allocated names (that we need to later delete)
m_allocatedNames.push_back(name);
safeName = m_allocatedNames.back().c_str();
}
#endif
m_listeners.push_back(ListenerRecord(pListener, safeName));
success = true;
}
}
return success;
}
// Removes a listener from the collection.
template <typename T>
inline void CListenerSet<T>::Remove(T pListener)
{
typename TListenerVec::iterator endIter(m_listeners.end());
typename TListenerVec::iterator iter(std::find(m_listeners.begin(), endIter, pListener));
if (iter != endIter)
{
#ifdef CRY_LISTENERSET_DEBUG
// Delete name if it was heap allocated
if (const char* name = iter->m_szName)
{
DeleteName(name);
}
#endif
// If no notifications in progress
if (m_activeNotifications == 0)
{
// Just delete the listener entry immediately
m_listeners.erase(iter);
}
else // Notification(s) in progress, cannot re-order listeners
{
// Mark for cleanup
iter->m_pListener = NULL;
m_cleanupRequired = true;
m_freeMemOnCleanup = false;
}
}
else // The listener is not in the set
{
// TODO: Warn about redundant Remove()
}
}
// Removes all listeners from the collection (NOTE: prefer informing listeners to remove themselves)
template <typename T>
inline void CListenerSet<T>::Clear(bool bFreeMemory)
{
// If no notifications in progress
if (m_activeNotifications == 0)
{
// Simply clear the listeners immediately
if (bFreeMemory)
{
stl::free_container(m_listeners);
}
else
{
m_listeners.clear();
}
}
else
{
// Mark all listeners for cleanup
std::fill(m_listeners.begin(), m_listeners.end(), ListenerRecord());
m_cleanupRequired = true;
m_freeMemOnCleanup = true;
}
#ifdef CRY_LISTENERSET_DEBUG
// Safe to clear allocated names immediately (no references exist any more)
if (bFreeMemory)
{
stl::free_container(m_allocatedNames);
}
else
{
m_allocatedNames.clear();
}
#endif
}
// Returns true if this contains pListener
template <typename T>
inline bool CListenerSet<T>::Contains(T pListener) const
{
return stl::find(m_listeners, pListener);
}
// Returns number of valid listeners
template <typename T>
inline size_t CListenerSet<T>::ValidListenerCount() const
{
size_t validCount = m_listeners.size();
if (m_cleanupRequired)
{
// Remove the count of NULL elements from the result
validCount = validCount - std::count(m_listeners.begin(), m_listeners.end(), T());
}
return validCount;
}
// Returns true if no valid listeners exist
template <typename T>
inline bool CListenerSet<T>::Empty() const
{
return ValidListenerCount() == 0;
}
// Reserves space to help avoid runtime reallocation
template <typename T>
inline void CListenerSet<T>::Reserve(size_t capacity)
{
m_listeners.reserve(capacity);
}
// Returns the memory size of this object (to support CrySizer)
template <typename T>
inline size_t CListenerSet<T>::MemSize() const
{
size_t size = sizeof(CListenerSet<T>) + sizeof(ListenerRecord) * m_listeners.size();
#ifdef CRY_LISTENERSET_DEBUG
size += sizeof(typename TAllocatedNameVec::value_type);
for (typename TAllocatedNameVec::const_iterator iter(m_allocatedNames.begin()); iter != m_allocatedNames.end(); ++iter)
{
size += iter->GetAllocatedMemory();
}
#endif
return size;
}
template <typename T>
inline bool CListenerSet<T>::IsNotifying() const
{
return m_activeNotifications > 0;
}
template <typename T>
inline void CListenerSet<T>::StartNotificationScope()
{
++m_activeNotifications;
}
template <typename T>
inline void CListenerSet<T>::EndNotificationScope()
{
// Ensure at least one notification scope was started
CRY_ASSERT(m_activeNotifications > 0);
// If this is the last notification
if (--m_activeNotifications == 0)
{
EraseNullElements();
}
}
template <typename T>
inline void CListenerSet<T>::EraseNullElements()
{
// Ensure no modification while notification(s) are ongoing
CRY_ASSERT(m_activeNotifications == 0);
if (m_cleanupRequired && m_activeNotifications == 0)
{
stl::find_and_erase_all(m_listeners, T());
if (m_freeMemOnCleanup && m_listeners.empty())
{
stl::free_container(m_listeners);
}
m_cleanupRequired = false;
m_freeMemOnCleanup = false;
}
}
#ifdef CRY_LISTENERSET_DEBUG
// Used to delete heap allocated names
template <typename T>
inline void CListenerSet<T>::DeleteName(const char* name)
{
if (!m_allocatedNames.empty())
{
typename TAllocatedNameVec::iterator endIter(m_allocatedNames.end());
for (typename TAllocatedNameVec::iterator iter(m_allocatedNames.begin()); iter != endIter; ++iter)
{
// Is this the source string?
if (iter->c_str() == name)
{
// Delete it
m_allocatedNames.erase(iter);
break;
}
}
}
}
#endif // defined CRY_LISTENERSET_DEBUG
/******************************************************************************************/
template <typename T>
ILINE CListenerNotifier<T>::CListenerNotifier(CListenerSet<T>& listeners)
: m_listenerSet(listeners)
, m_pListener()
, m_index(0)
#ifdef CRY_LISTENERSET_DEBUG
, m_szName()
#endif
{
// Flag iteration to listener set to ensure no erase is attempted during iteration
m_listenerSet.StartNotificationScope();
// If first element is NULL, move to next valid element
if (!IsValid())
{
Next();
}
}
template <typename T>
ILINE CListenerNotifier<T>::~CListenerNotifier()
{
// Erases any NULL elements from listeners
m_listenerSet.EndNotificationScope();
}
// True if the current element is ready for iteration
template <typename T>
ILINE bool CListenerNotifier<T>::IsValid()
{
if (!m_pListener)
{
// Always check with original collection
if (m_index < m_listenerSet.m_listeners.size())
{
const typename CListenerSet<T>::ListenerRecord & record(m_listenerSet.m_listeners[m_index]);
m_pListener = record.m_pListener;
#ifdef CRY_LISTENERSET_DEBUG
m_szName = record.m_szName;
#endif
}
}
return m_pListener != NULL;
}
// Dereference current listener, MUST only be done after a call to IsReady().
template <typename T>
ILINE T CListenerNotifier<T>::operator->()
{
return operator*();
}
// Dereference current listener, MUST only be done after a call to IsReady().
template <typename T>
ILINE T CListenerNotifier<T>::operator*()
{
// Ensure IsReady() was called and its return value checked
CRY_ASSERT(m_pListener);
// Clear cached listener pointer to force a IsReady() call before this can be called again.
// This is done as the listener could be removed during any call to its own event handlers
// resulting in m_pListener becoming a dangling pointer.
T pListener(m_pListener);
m_pListener = T();
return pListener;
}
// Move to next valid listener
template <typename T>
ILINE void CListenerNotifier<T>::Next()
{
size_t index = m_index;
typename CListenerSet<T>::ListenerRecord * pNextRecord = NULL;
m_pListener = NULL; // Always assume there's no next, let the code below prove otherwise!
const size_t listenerCount = m_listenerSet.m_listeners.size();
while (++index < listenerCount)
{
typename CListenerSet<T>::ListenerRecord & record(m_listenerSet.m_listeners[index]);
// Is this element valid?
if (record.m_pListener)
{
pNextRecord = &record;
break;
}
// Else move to next element
}
if (pNextRecord)
{
m_pListener = pNextRecord->m_pListener;
#ifdef CRY_LISTENERSET_DEBUG
m_szName = pNextRecord->m_szName;
#endif
}
m_index = index;
}
// Returns the name of the listener (if available)
template <typename T>
inline const char* CListenerNotifier<T>::Name() const
{
#ifdef CRY_LISTENERSET_DEBUG
return m_szName;
#else
return NULL;
#endif
}
#endif // CRYINCLUDE_CRYCOMMON_CRYLISTENERSET_H
@@ -0,0 +1,274 @@
/*
* 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.
/*
* Part of this code coming from STLPort alloc
*
* Copyright (c) 1996,1997
* Silicon Graphics Computer Systems, Inc.
*
* Copyright (c) 1997
* Moscow Center for SPARC Technology
*
* Copyright (c) 1999
* Boris Fomitchev
*
*
*/
#ifndef CRYINCLUDE_CRYCOMMON_CRYMEMORYALLOCATOR_H
#define CRYINCLUDE_CRYCOMMON_CRYMEMORYALLOCATOR_H
#pragma once
#include <algorithm>
#define CRY_STL_ALLOC
#if defined(LINUX64) || defined(APPLE)
#include <sys/mman.h>
#endif
#include <string.h> // memset
// DON't USE _MAX_BYTES as identifier for Max Bytes, STLPORT defines the same enum
// this leads to situation where the wrong enum is choosen in different compilation units
// which in case leads to errors(The stlport one is defined as 128)
#if defined (__OS400__) || defined (_WIN64) || defined(MAC) || defined(LINUX64)
enum {_ALIGNMENT = 16, _ALIGN_SHIFT = 4, __MAX_BYTES = 512, NFREELISTS=32, ADDRESSSPACE = 2 * 1024 * 1024, ADDRESS_SHIFT = 40};
#else
enum {_ALIGNMENT = 8, _ALIGN_SHIFT = 3, __MAX_BYTES = 512, NFREELISTS = 64, ADDRESSSPACE = 2 * 1024 * 1024, ADDRESS_SHIFT = 20};
#endif /* __OS400__ */
#define CRY_MEMORY_ALLOCATOR
#define S_FREELIST_INDEX(__bytes) ((__bytes - size_t(1)) >> (int)_ALIGN_SHIFT)
class _Node_alloc_obj {
public:
_Node_alloc_obj * _M_next;
};
#if defined (_WIN64) || defined(APPLE) || defined(LINUX64)
#define MASK_COUNT 0x000000FFFFFFFFFF
#define MASK_VALUE 0xFFFFFF
#define MASK_NEXT 0xFFFFFFFFFF000000
#define MASK_SHIFT 24
#else
#define MASK_COUNT 0x000FFFFF
#define MASK_VALUE 0xFFF
#define MASK_NEXT 0xFFFFF000
#define MASK_SHIFT 12
#endif
#define NUM_OBJ 64
struct _Obj_Address {
// short int * _M_next;
// short int
size_t GetNext(size_t pBase) {
return pBase +(size_t)(_M_value >> MASK_SHIFT);
}
//size_t GetNext() {
// return (size_t)(_M_value >> 20);
//}
size_t GetCount() {
return _M_value & MASK_VALUE;
}
void SetNext(/*void **/size_t pNext) {
_M_value &= MASK_COUNT;
_M_value |= (size_t)pNext << MASK_SHIFT;
}
void SetCount(size_t count) {
_M_value &= MASK_NEXT;
_M_value |= count & MASK_VALUE;
}
private:
size_t _M_value;
// short int * _M_end;
};
//struct _Node_Allocations_Tree {
// enum { eListSize = _Size / (sizeof(void *) * _Num_obj); };
// _Obj_Address * _M_allocations_list[eListSize];
// int _M_Count;
// _Node_Allocations_Tree * _M_next;
//};
template<int _Size>
struct _Node_Allocations_Tree {
//Pointer to the end of the memory block
char *_M_end;
enum { eListSize = _Size / (sizeof(void *) * NUM_OBJ) };
// List of allocations
_Obj_Address _M_allocations_list[eListSize];
int _M_allocations_count;
//Pointer to the next memory block
_Node_Allocations_Tree *_M_Block_next;
};
struct _Node_alloc_Mem_block_Huge {
//Pointer to the end of the memory block
char *_M_end;
// number
int _M_count;
_Node_alloc_Mem_block_Huge *_M_next;
};
template<int _Size>
struct _Node_alloc_Mem_block {
//Pointer to the end of the memory block
char *_M_end;
//Pointer to the next memory block
_Node_alloc_Mem_block_Huge *_M_huge_block;
_Node_alloc_Mem_block *_M_next;
};
// Allocators!
enum EAllocFreeType
{
eCryDefaultMalloc,
eCryMallocCryFreeCRTCleanup,
};
template <EAllocFreeType type>
struct Node_Allocator
{
inline void * pool_alloc(size_t size)
{
return CryModuleMalloc(size);
};
inline void * cleanup_alloc(size_t size)
{
return CryCrtMalloc(size);
};
inline size_t pool_free(void * ptr)
{
CryModuleFree(ptr);
return 0;
};
inline void cleanup_free(void * ptr)
{
CryCrtFree(ptr);
};
inline size_t getSize(void * ptr)
{
return CryCrtSize(ptr);
}
};
// partial
template <>
struct Node_Allocator<eCryDefaultMalloc>
{
inline void * pool_alloc(size_t size)
{
return CryCrtMalloc(size);
};
inline void * cleanup_alloc(size_t size)
{
return CryCrtMalloc(size);
};
inline size_t pool_free(void * ptr)
{
size_t n = CryCrtSize(ptr);
CryCrtFree(ptr);
return n;
};
inline void cleanup_free(void * ptr)
{
CryCrtFree(ptr);
};
inline size_t getSize(void * ptr)
{
return CryCrtSize(ptr);
}
};
// partial
template <>
struct Node_Allocator<eCryMallocCryFreeCRTCleanup>
{
inline void * pool_alloc(size_t size)
{
return CryCrtMalloc(size);
};
inline void * cleanup_alloc(size_t size)
{
return CryCrtMalloc(size);
};
inline size_t pool_free(void * ptr)
{
return CryCrtFree(ptr);
};
inline void cleanup_free(void * ptr)
{
CryCrtFree(ptr);
};
inline size_t getSize(void * ptr)
{
return CryCrtSize(ptr);
}
};
#include "MultiThread.h"
struct InternalCriticalSectionDummy {
char padding[128];
} ;
inline void CryInternalCreateCriticalSection(void * pCS)
{
CryCreateCriticalSectionInplace(pCS);
}
// A class that forward node allocator calls directly to CRT
struct cry_crt_node_allocator
{
static const size_t MaxSize = ~0;
static void *alloc(size_t __n)
{
return CryCrtMalloc(__n);
}
static size_t dealloc( void *p )
{
return CryCrtFree(p);
}
static void *allocate(size_t __n)
{
return alloc(__n);
}
static void *allocate(size_t __n, [[maybe_unused]] size_t nAlignment)
{
return alloc(__n);
}
static size_t deallocate(void *__p)
{
return dealloc(__p);
}
void cleanup() {}
};
//#endif // WIN32|DEBUG
#endif // CRYINCLUDE_CRYCOMMON_CRYMEMORYALLOCATOR_H
+298
View File
@@ -0,0 +1,298 @@
/*
* 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 : Defines functions for CryEngine custom memory manager.
#pragma once
// Section dictionary
#if defined(AZ_RESTRICTED_PLATFORM)
#define CRYMEMORYMANAGER_H_SECTION_TRAITS 1
#define CRYMEMORYMANAGER_H_SECTION_ALLOCPOLICY 2
#endif
#include <AzCore/PlatformRestrictedFileDef.h>
// Traits
#if defined(AZ_RESTRICTED_PLATFORM)
#define AZ_RESTRICTED_SECTION CRYMEMORYMANAGER_H_SECTION_TRAITS
#include AZ_RESTRICTED_FILE(CryMemoryManager_h)
#else
#if !defined(APPLE)
#define CRYMEMORYMANAGER_H_TRAIT_INCLUDE_MALLOC_H 1
#endif
#if defined(LINUX) || defined(APPLE)
#define CRYMEMORYMANAGER_H_TRAIT_INCLUDE_NEW_NOT_NEW_H 1
#endif
#if !defined(LINUX) && !defined(APPLE)
#define CRYMEMORYMANAGER_H_TRAIT_INCLUDE_CRTDBG_H 1
#endif
#if !defined(APPLE)
#define CRYMEMORYMANAGER_H_TRAIT_USE_CRTCHECKMEMORY 1
#endif
#endif
#include "platform.h"
#include <stdarg.h>
#include <algorithm>
#if defined(APPLE) || defined(ANDROID)
#include <AzCore/Memory/OSAllocator.h> // memalign
#endif // defined(APPLE)
#ifndef STLALLOCATOR_CLEANUP
#define STLALLOCATOR_CLEANUP
#endif
#define _CRY_DEFAULT_MALLOC_ALIGNMENT 4
#if CRYMEMORYMANAGER_H_TRAIT_INCLUDE_MALLOC_H
#include <malloc.h>
#endif
#if defined(__cplusplus)
#if CRYMEMORYMANAGER_H_TRAIT_INCLUDE_NEW_NOT_NEW_H
#include <new>
#else
#include <new.h>
#endif
#endif
#ifdef CRYSYSTEM_EXPORTS
#define CRYMEMORYMANAGER_API DLL_EXPORT
#else
#define CRYMEMORYMANAGER_API DLL_IMPORT
#endif
#ifdef __cplusplus
#if defined(_DEBUG) && CRYMEMORYMANAGER_H_TRAIT_INCLUDE_CRTDBG_H
#include <crtdbg.h>
#endif //_DEBUG
#include "LegacyAllocator.h"
namespace CryMemory
{
// checks if the heap is valid in debug; in release, this function shouldn't be called
// returns non-0 if it's valid and 0 if not valid
ILINE int IsHeapValid()
{
#if (defined(_DEBUG) && !defined(RELEASE_RUNTIME) && CRYMEMORYMANAGER_H_TRAIT_USE_CRTCHECKMEMORY) || (defined(DEBUG_MEMORY_MANAGER))
return _CrtCheckMemory();
#else
return true;
#endif
}
inline void* AllocPages(size_t size)
{
const size_t alignment = AZ_PAGE_SIZE;
void* ret = AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().Allocate(size, alignment, 0, "AllocPages", __FILE__, __LINE__);
return ret;
}
inline void FreePages(void* p, size_t size)
{
const size_t alignment = AZ_PAGE_SIZE;
AZ::AllocatorInstance<AZ::LegacyAllocator>::Get().DeAllocate(p, size, alignment);
}
}
//////////////////////////////////////////////////////////////////////////
#endif //__cplusplus
struct ICustomMemoryHeap;
class IGeneralMemoryHeap;
class IPageMappingHeap;
class IDefragAllocator;
class IMemoryAddressRange;
// Description:
// Interfaces that allow access to the CryEngine memory manager.
struct IMemoryManager
{
typedef unsigned char HeapHandle;
enum
{
BAD_HEAP_HANDLE = 0xFF
};
struct SProcessMemInfo
{
uint64 PageFaultCount;
uint64 PeakWorkingSetSize;
uint64 WorkingSetSize;
uint64 QuotaPeakPagedPoolUsage;
uint64 QuotaPagedPoolUsage;
uint64 QuotaPeakNonPagedPoolUsage;
uint64 QuotaNonPagedPoolUsage;
uint64 PagefileUsage;
uint64 PeakPagefileUsage;
uint64 TotalPhysicalMemory;
int64 FreePhysicalMemory;
uint64 TotalVideoMemory;
int64 FreeVideoMemory;
};
enum EAllocPolicy
{
eapDefaultAllocator,
eapPageMapped,
eapCustomAlignment,
#if defined(AZ_RESTRICTED_PLATFORM)
#define AZ_RESTRICTED_SECTION CRYMEMORYMANAGER_H_SECTION_ALLOCPOLICY
#include AZ_RESTRICTED_FILE(CryMemoryManager_h)
#endif
};
virtual ~IMemoryManager(){}
virtual bool GetProcessMemInfo(SProcessMemInfo& minfo) = 0;
//////////////////////////////////////////////////////////////////////////
// Heap Tracing API
virtual HeapHandle TraceDefineHeap(const char* heapName, size_t size, const void* pBase) = 0;
virtual void TraceHeapAlloc(HeapHandle heap, void* mem, size_t size, size_t blockSize, const char* sUsage, const char* sNameHint = 0) = 0;
virtual void TraceHeapFree(HeapHandle heap, void* mem, size_t blockSize) = 0;
virtual void TraceHeapSetColor(uint32 color) = 0;
virtual uint32 TraceHeapGetColor() = 0;
virtual void TraceHeapSetLabel(const char* sLabel) = 0;
//////////////////////////////////////////////////////////////////////////
// Create an instance of ICustomMemoryHeap
virtual ICustomMemoryHeap* const CreateCustomMemoryHeapInstance(EAllocPolicy const eAllocPolicy) = 0;
virtual IGeneralMemoryHeap* CreateGeneralExpandingMemoryHeap(size_t upperLimit, size_t reserveSize, const char* sUsage) = 0;
virtual IGeneralMemoryHeap* CreateGeneralMemoryHeap(void* base, size_t sz, const char* sUsage) = 0;
virtual IMemoryAddressRange* ReserveAddressRange(size_t capacity, const char* sName) = 0;
virtual IPageMappingHeap* CreatePageMappingHeap(size_t addressSpace, const char* sName) = 0;
virtual IDefragAllocator* CreateDefragAllocator() = 0;
};
// Global function implemented in CryMemoryManager_impl.h
IMemoryManager* CryGetIMemoryManager();
// Summary:
// Structure filled by call to CryModuleGetMemoryInfo().
struct CryModuleMemoryInfo
{
uint64 requested;
// Total Ammount of memory allocated.
uint64 allocated;
// Total Ammount of memory freed.
uint64 freed;
// Total number of memory allocations.
int num_allocations;
// Allocated in CryString.
uint64 CryString_allocated;
// Allocated in STL.
uint64 STL_allocated;
// Amount of memory wasted in pools in stl (not usefull allocations).
uint64 STL_wasted;
};
struct CryReplayInfo
{
uint64 uncompressedLength;
uint64 writtenLength;
uint32 trackingSize;
const char* filename;
};
//////////////////////////////////////////////////////////////////////////
// Extern declarations of globals inside CrySystem.
//////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
extern "C" {
#endif //__cplusplus
void* CryMalloc(size_t size, size_t& allocated, size_t alignment);
void* CryRealloc(void* memblock, size_t size, size_t& allocated, size_t& oldsize, size_t alignment);
size_t CryFree(void* p, size_t alignment);
size_t CryGetMemSize(void* p, size_t size);
int CryStats(char* buf);
void CryFlushAll();
void CryCleanup();
int CryGetUsedHeapSize();
int CryGetWastedHeapSize();
size_t CrySystemCrtGetUsedSpace();
CRYMEMORYMANAGER_API void CryGetIMemoryManagerInterface(void** pIMemoryManager);
#ifdef __cplusplus
}
#endif //__cplusplus
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Cry Memory Manager accessible in all build modes.
//////////////////////////////////////////////////////////////////////////
#if !defined(USING_CRY_MEMORY_MANAGER)
#define USING_CRY_MEMORY_MANAGER
#endif
#include "CryLegacyAllocator.h"
template<typename T, typename ... Args>
inline T* CryAlignedNew(Args&& ... args)
{
void* pAlignedMemory = CryModuleMemalign(sizeof(T), std::alignment_of<T>::value);
return new(pAlignedMemory) T(std::forward<Args>(args) ...);
}
// This utility function should be used for allocating arrays of objects with specific alignment requirements on the heap.
// Note: The caller must remember the number of items in the array, since CryAlignedDeleteArray needs this information.
template<typename T>
inline T* CryAlignedNewArray(size_t count)
{
T* const pAlignedMemory = reinterpret_cast<T*>(CryModuleMemalign(sizeof(T) * count, std::alignment_of<T>::value));
T* pCurrentItem = pAlignedMemory;
for (size_t i = 0; i < count; ++i, ++pCurrentItem)
{
new(static_cast<void*>(pCurrentItem))T();
}
return pAlignedMemory;
}
// Utility function that frees an object previously allocated with CryAlignedNew.
template<typename T>
inline void CryAlignedDelete(T* pObject)
{
if (pObject)
{
pObject->~T();
CryModuleMemalignFree(pObject);
}
}
// Utility function that frees an array of objects previously allocated with CryAlignedNewArray.
// The same count used to allocate the array must be passed to this function.
template<typename T>
inline void CryAlignedDeleteArray(T* pObject, size_t count)
{
if (pObject)
{
for (size_t i = 0; i < count; ++i)
{
(pObject + i)->~T();
}
CryModuleMemalignFree(pObject);
}
}
@@ -0,0 +1,41 @@
/*
* 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 : Provides implementation for CryMemoryManager globally defined functions.
// This file included only by platform_impl.cpp, do not include it directly in code!
#pragma once
#ifdef AZ_MONOLITHIC_BUILD
#include <ISystem.h> // <> required for Interfuscator
#endif // AZ_MONOLITHIC_BUILD
#include "CryLibrary.h"
#include <AzCore/Module/Environment.h>
#define DLL_ENTRY_GETMEMMANAGER "CryGetIMemoryManagerInterface"
// Resolve IMemoryManager by looking in this DLL, then loading and rummaging through
// CrySystem. Cache the result per DLL, because this is not quick.
IMemoryManager* CryGetIMemoryManager()
{
static AZ::EnvironmentVariable<IMemoryManager*> memMan = nullptr;
if (!memMan)
{
memMan = AZ::Environment::FindVariable<IMemoryManager*>("CryIMemoryManagerInterface");
AZ_Assert(memMan, "Unable to find CryIMemoryManagerInterface via AZ::Environment");
}
return *memMan;
}
+569
View File
@@ -0,0 +1,569 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYCOMMON_CRYNAME_H
#define CRYINCLUDE_CRYCOMMON_CRYNAME_H
#pragma once
#include <ISystem.h>
#include <StlUtils.h>
#include <CrySizer.h>
#include <CryCrc32.h>
#include <STLGlobalAllocator.h>
#include <AzCore/std/containers/unordered_map.h>
class CNameTable;
struct INameTable
{
virtual ~INameTable(){}
// Name entry header, immediately after this header in memory starts actual string data.
struct SNameEntry
{
enum
{
TAG = 0xdeadbeef
};
int nTag; // tag to ensure that this is actually a name entry
// Reference count of this string.
int nRefCount;
// Current length of string.
int nLength;
// Size of memory allocated at the end of this class.
int nAllocSize;
// Here in memory starts character buffer of size nAllocSize.
//char data[nAllocSize]
const char* GetStr() { return (char*)(this + 1); }
void AddRef() { nRefCount++; /*InterlockedIncrement(&_header()->nRefCount);*/};
int Release() { return --nRefCount; };
int GetMemoryUsage() { return sizeof(SNameEntry) + strlen(GetStr()); }
int GetLength(){return nLength; }
};
// Finds an existing name table entry, or creates a new one if not found.
virtual INameTable::SNameEntry* GetEntry(const char* str) = 0;
// Only finds an existing name table entry, return 0 if not found.
virtual INameTable::SNameEntry* FindEntry(const char* str) = 0;
// Release existing name table entry.
virtual void Release(SNameEntry* pEntry) = 0;
virtual int GetMemoryUsage() = 0;
virtual int GetNumberOfEntries() = 0;
// Output all names from the table to log.
virtual void LogNames() = 0;
virtual void GetMemoryUsage(ICrySizer* pSizer) const = 0;
};
//////////////////////////////////////////////////////////////////////////
class CNameTable
: public INameTable
{
private:
typedef AZStd::unordered_map<const char*, SNameEntry*, stl::hash_string_caseless<const char*>, stl::equality_string_caseless<const char*> > NameMap;
NameMap m_nameMap;
public:
CNameTable()
{
// Ensure that SNameEntry is an aligned size
static_assert(sizeof(INameTable::SNameEntry) % sizeof(void*) == 0, "SNameEntry must be an aligned size");
}
~CNameTable()
{
for (NameMap::iterator it = m_nameMap.begin(); it != m_nameMap.end(); ++it)
{
CryModuleFree(it->second);
}
}
// Only finds an existing name table entry, return 0 if not found.
virtual INameTable::SNameEntry* FindEntry(const char* str)
{
SNameEntry* pEntry = stl::find_in_map(m_nameMap, str, 0);
return pEntry;
}
// Finds an existing name table entry, or creates a new one if not found.
virtual INameTable::SNameEntry* GetEntry(const char* str)
{
SNameEntry* pEntry = FindEntry(str);
if (!pEntry)
{
// Create a new entry.
unsigned int nLen = strlen(str);
unsigned int allocLen = sizeof(SNameEntry) + (nLen + 1) * sizeof(char);
pEntry = (SNameEntry*)CryModuleMalloc(allocLen);
assert(pEntry != NULL);
pEntry->nTag = SNameEntry::TAG;
pEntry->nRefCount = 0;
pEntry->nLength = nLen;
pEntry->nAllocSize = allocLen;
// Copy string to the end of name entry.
char* pEntryStr = const_cast<char*>(pEntry->GetStr());
memcpy(pEntryStr, str, nLen + 1);
// put in map.
//m_nameMap.insert( NameMap::value_type(pEntry->GetStr(),pEntry) );
m_nameMap[pEntry->GetStr()] = pEntry;
}
return pEntry;
}
// Release existing name table entry.
virtual void Release(SNameEntry* pEntry)
{
assert(pEntry);
m_nameMap.erase(pEntry->GetStr());
CryModuleFree(pEntry);
}
virtual int GetMemoryUsage()
{
int nSize = 0;
NameMap::iterator it;
int n = 0;
for (it = m_nameMap.begin(); it != m_nameMap.end(); it++)
{
nSize += strlen(it->first);
nSize += it->second->GetMemoryUsage();
n++;
}
nSize += n * 8;
return nSize;
}
virtual void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(this, sizeof(*this));
pSizer->AddContainer(m_nameMap);
}
virtual int GetNumberOfEntries()
{
return m_nameMap.size();
}
// Log all names inside CryName table.
virtual void LogNames()
{
NameMap::iterator it;
for (it = m_nameMap.begin(); it != m_nameMap.end(); ++it)
{
SNameEntry* pNameEntry = it->second;
CryLog("[%4d] %s", pNameEntry->nLength, pNameEntry->GetStr());
}
}
};
///////////////////////////////////////////////////////////////////////////////
// Class CCryName.
//////////////////////////////////////////////////////////////////////////
class CCryName
{
public:
CCryName();
CCryName(const CCryName& n);
explicit CCryName(const char* s);
CCryName(const char* s, bool bOnlyFind);
~CCryName();
CCryName& operator=(const CCryName& n);
CCryName& operator=(const char* s);
bool operator==(const CCryName& n) const;
bool operator!=(const CCryName& n) const;
bool operator==(const char* s) const;
bool operator!=(const char* s) const;
bool operator<(const CCryName& n) const;
bool operator>(const CCryName& n) const;
bool empty() const { return !m_str || !m_str[0]; }
void reset() { _release(m_str); m_str = 0; }
void addref() { _addref(m_str); }
const char* c_str() const
{
return (m_str) ? m_str : "";
}
int length() const { return _length(); };
static bool find(const char* str) { return GetNameTable()->FindEntry(str) != 0; }
void GetMemoryUsage(ICrySizer* pSizer) const
{
//pSizer->AddObject(m_str);
pSizer->AddObject(GetNameTable()); // cause for slowness?
}
static int GetMemoryUsage()
{
#ifdef USE_STATIC_NAME_TABLE
CNameTable* pTable = GetNameTable();
#else
INameTable* pTable = GetNameTable();
#endif
return pTable->GetMemoryUsage();
}
static int GetNumberOfEntries()
{
#ifdef USE_STATIC_NAME_TABLE
CNameTable* pTable = GetNameTable();
#else
INameTable* pTable = GetNameTable();
#endif
return pTable->GetNumberOfEntries();
}
// Compare functor for sorting CCryNames lexically.
struct CmpLex
{
bool operator () (const CCryName& n1, const CCryName& n2) const
{
return strcmp(n1.c_str(), n2.c_str()) < 0;
}
};
private:
typedef INameTable::SNameEntry SNameEntry;
#ifdef USE_STATIC_NAME_TABLE
static CNameTable* GetNameTable()
{
// Note: can not use a 'static CNameTable sTable' here, because that
// implies a static destruction order depenency - the name table is
// accessed from static destructor calls.
static CNameTable* table = NULL;
if (table == NULL)
{
table = new CNameTable();
}
return table;
}
#else
//static INameTable* GetNameTable() { return GetISystem()->GetINameTable(); }
static INameTable* GetNameTable()
{
assert(gEnv && gEnv->pNameTable);
return gEnv->pNameTable;
}
#endif
SNameEntry* _entry(const char* pBuffer) const
{
CRY_ASSERT(pBuffer);
CRY_ASSERT((((SNameEntry*)pBuffer) - 1)->nTag == SNameEntry::TAG);
return ((SNameEntry*)pBuffer) - 1;
}
void _release(const char* pBuffer)
{
if (pBuffer && _entry(pBuffer)->Release() <= 0 && gEnv)
{
GetNameTable()->Release(_entry(pBuffer));
}
}
int _length() const { return (m_str) ? _entry(m_str)->nLength : 0; };
void _addref(const char* pBuffer)
{
if (pBuffer)
{
_entry(pBuffer)->AddRef();
}
}
const char* m_str;
};
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// CryName
//////////////////////////////////////////////////////////////////////////
inline CCryName::CCryName()
{
m_str = 0;
}
//////////////////////////////////////////////////////////////////////////
inline CCryName::CCryName(const CCryName& n)
{
_addref(n.m_str);
m_str = n.m_str;
}
//////////////////////////////////////////////////////////////////////////
inline CCryName::CCryName(const char* s)
{
m_str = 0;
*this = s;
}
//////////////////////////////////////////////////////////////////////////
inline CCryName::CCryName(const char* s, [[maybe_unused]] bool bOnlyFind)
{
assert(s);
m_str = 0;
if (*s) // if not empty
{
SNameEntry* pNameEntry = GetNameTable()->FindEntry(s);
if (pNameEntry)
{
m_str = pNameEntry->GetStr();
_addref(m_str);
}
}
}
inline CCryName::~CCryName()
{
_release(m_str);
}
//////////////////////////////////////////////////////////////////////////
inline CCryName& CCryName::operator=(const CCryName& n)
{
if (m_str != n.m_str)
{
_release(m_str);
m_str = n.m_str;
_addref(m_str);
}
return *this;
}
//////////////////////////////////////////////////////////////////////////
inline CCryName& CCryName::operator=(const char* s)
{
assert(s);
const char* pBuf = 0;
if (s && *s) // if not empty
{
pBuf = GetNameTable()->GetEntry(s)->GetStr();
}
if (m_str != pBuf)
{
_release(m_str);
m_str = pBuf;
_addref(m_str);
}
return *this;
}
//////////////////////////////////////////////////////////////////////////
inline bool CCryName::operator==(const CCryName& n) const
{
return m_str == n.m_str;
}
inline bool CCryName::operator!=(const CCryName& n) const
{
return !(*this == n);
}
inline bool CCryName::operator==(const char* str) const
{
return m_str && _stricmp(m_str, str) == 0;
}
inline bool CCryName::operator!=(const char* str) const
{
if (!m_str)
{
return true;
}
return _stricmp(m_str, str) != 0;
}
inline bool CCryName::operator<(const CCryName& n) const
{
return m_str < n.m_str;
}
inline bool CCryName::operator>(const CCryName& n) const
{
return m_str > n.m_str;
}
inline bool operator==(const string& s, const CCryName& n)
{
return n == s;
}
inline bool operator!=(const string& s, const CCryName& n)
{
return n != s;
}
inline bool operator==(const char* s, const CCryName& n)
{
return n == s;
}
inline bool operator!=(const char* s, const CCryName& n)
{
return n != s;
}
///////////////////////////////////////////////////////////////////////////////
// Class CCryNameCRC.
//////////////////////////////////////////////////////////////////////////
class CCryNameCRC
{
public:
CCryNameCRC();
CCryNameCRC(const CCryNameCRC& n);
CCryNameCRC(const char* s);
CCryNameCRC(const char* s, bool bOnlyFind);
explicit CCryNameCRC(uint32 n) { m_nID = n; } // We use "explicit" to prevent comparison of strings with ints due to implicit conversion.
~CCryNameCRC();
CCryNameCRC& operator=(const CCryNameCRC& n);
CCryNameCRC& operator=(const char* s);
bool operator==(const CCryNameCRC& n) const;
bool operator!=(const CCryNameCRC& n) const;
bool operator==(const char* s) const;
bool operator!=(const char* s) const;
bool operator<(const CCryNameCRC& n) const;
bool operator>(const CCryNameCRC& n) const;
bool empty() const { return m_nID == 0; }
void reset() { m_nID = 0; }
uint32 get() const { return m_nID; }
void add(int nAdd) { m_nID += nAdd; }
AUTO_STRUCT_INFO
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const { /*nothing*/}
private:
uint32 m_nID;
};
//////////////////////////////////////////////////////////////////////////
// CCryNameCRC
//////////////////////////////////////////////////////////////////////////
inline CCryNameCRC::CCryNameCRC()
{
m_nID = 0;
}
//////////////////////////////////////////////////////////////////////////
inline CCryNameCRC::CCryNameCRC(const CCryNameCRC& n)
{
m_nID = n.m_nID;
}
//////////////////////////////////////////////////////////////////////////
inline CCryNameCRC::CCryNameCRC(const char* s)
{
m_nID = 0;
*this = s;
}
inline CCryNameCRC::~CCryNameCRC()
{
m_nID = 0;
}
//////////////////////////////////////////////////////////////////////////
inline CCryNameCRC& CCryNameCRC::operator=(const CCryNameCRC& n)
{
m_nID = n.m_nID;
return *this;
}
//////////////////////////////////////////////////////////////////////////
inline CCryNameCRC& CCryNameCRC::operator=(const char* s)
{
assert(s);
if (*s) // if not empty
{
m_nID = CCrc32::ComputeLowercase(s);
}
return *this;
}
//////////////////////////////////////////////////////////////////////////
inline bool CCryNameCRC::operator==(const CCryNameCRC& n) const
{
return m_nID == n.m_nID;
}
inline bool CCryNameCRC::operator!=(const CCryNameCRC& n) const
{
return !(*this == n);
}
inline bool CCryNameCRC::operator==(const char* str) const
{
assert(str);
if (*str) // if not empty
{
uint32 nID = CCrc32::ComputeLowercase(str);
return m_nID == nID;
}
return m_nID == 0;
}
inline bool CCryNameCRC::operator!=(const char* str) const
{
if (!m_nID)
{
return true;
}
if (*str) // if not empty
{
uint32 nID = CCrc32::ComputeLowercase(str);
return m_nID != nID;
}
return false;
}
inline bool CCryNameCRC::operator<(const CCryNameCRC& n) const
{
return m_nID < n.m_nID;
}
inline bool CCryNameCRC::operator>(const CCryNameCRC& n) const
{
return m_nID > n.m_nID;
}
inline bool operator==(const string& s, const CCryNameCRC& n)
{
return n == s;
}
inline bool operator!=(const string& s, const CCryNameCRC& n)
{
return n != s;
}
inline bool operator==(const char* s, const CCryNameCRC& n)
{
return n == s;
}
inline bool operator!=(const char* s, const CCryNameCRC& n)
{
return n != s;
}
#endif // CRYINCLUDE_CRYCOMMON_CRYNAME_H
+623
View File
@@ -0,0 +1,623 @@
/*
* 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 : Defines namespace PathUtil for operations on files paths.
#ifndef CRYINCLUDE_CRYCOMMON_CRYPATH_H
#define CRYINCLUDE_CRYCOMMON_CRYPATH_H
#pragma once
#include <ISystem.h>
#include <AzFramework/Archive/IArchive.h>
#include <IConsole.h>
#include "platform.h"
#define UNIX_PATH_SEP_STR "/"
#define UNIX_PATH_SEP_CHR '/'
#define DOS_PATH_SEP_STR "\\"
#define DOS_PATH_SEP_CHR '\\'
#if AZ_LEGACY_CRYCOMMON_TRAIT_USE_UNIX_PATHS
#define CRY_NATIVE_PATH_SEPSTR UNIX_PATH_SEP_STR
#else
#define CRY_NATIVE_PATH_SEPSTR DOS_PATH_SEP_STR
#endif
namespace PathUtil
{
const static int maxAliasLength = 32;
inline string GetLocalizationFolder()
{
return gEnv->pCryPak->GetLocalizationFolder();
}
inline string GetLocalizationRoot()
{
return gEnv->pCryPak->GetLocalizationRoot();
}
//! Convert a path to the uniform form.
inline string ToUnixPath(const string& strPath)
{
if (strPath.find(DOS_PATH_SEP_CHR) != string::npos)
{
string path = strPath;
path.replace(DOS_PATH_SEP_CHR, UNIX_PATH_SEP_CHR);
return path;
}
return strPath;
}
//! Convert a path to the uniform form in place on stack
inline void ToUnixPath(stack_string& rConv)
{
const char* const cpEnd = &(rConv.c_str()[rConv.size()]);
char* __restrict pC = rConv.begin();
while (pC != cpEnd)
{
char c = *pC;
if (c == DOS_PATH_SEP_CHR)
{
c = UNIX_PATH_SEP_CHR;
}
*pC++ = c;
}
}
//! Convert a path to the DOS form.
inline string ToDosPath(const string& strPath)
{
if (strPath.find(UNIX_PATH_SEP_CHR) != string::npos)
{
string path = strPath;
path.replace(UNIX_PATH_SEP_CHR, DOS_PATH_SEP_CHR);
return path;
}
return strPath;
}
//! Convert a path to the Native form.
inline string ToNativePath(const string& strPath)
{
#if AZ_LEGACY_CRYCOMMON_TRAIT_USE_UNIX_PATHS
return ToUnixPath(strPath);
#else
return ToDosPath(strPath);
#endif
}
//! Convert a path to lowercase form
inline string ToLower(const string& strPath)
{
string path = strPath;
path.MakeLower();
return path;
}
//! Split full file name to path and filename
//! @param filepath [IN] Full file name including path.
//! @param path [OUT] Extracted file path.
//! @param filename [OUT] Extracted file (without extension).
//! @param ext [OUT] Extracted files extension.
inline void Split(const string& filepath, string& path, string& filename, string& fext)
{
path = filename = fext = string();
if (filepath.empty())
{
return;
}
const char* str = filepath.c_str();
const char* pext = str + filepath.length() - 1;
const char* p;
for (p = str + filepath.length() - 1; p >= str; --p)
{
switch (*p)
{
case ':':
case '/':
case '\\':
path = filepath.substr(0, p - str + 1);
filename = filepath.substr(p - str + 1, pext - p);
return;
case '.':
// there's an extension in this file name
fext = filepath.substr(p - str + 1);
pext = p;
break;
}
}
filename = filepath.substr(p - str + 1, pext - p);
}
//! Split full file name to path and filename
//! @param filepath [IN] Full file name inclusing path.
//! @param path [OUT] Extracted file path.
//! @param file [OUT] Extracted file (with extension).
inline void Split(const string& filepath, string& path, string& file)
{
string fext;
Split(filepath, path, file, fext);
file += fext;
}
// Extract extension from full specified file path
// Returns
// pointer to the extension (without .) or pointer to an empty 0-terminated string
inline const char* GetExt(const char* filepath)
{
const char* str = filepath;
size_t len = strlen(filepath);
for (const char* p = str + len - 1; p >= str; --p)
{
switch (*p)
{
case ':':
case '/':
case '\\':
// we've reached a path separator - it means there's no extension in this name
return "";
case '.':
// there's an extension in this file name
return p + 1;
}
}
return "";
}
//! Extract path from full specified file path.
inline string GetPath(const string& filepath)
{
const char* str = filepath.c_str();
for (const char* p = str + filepath.length() - 1; p >= str; --p)
{
switch (*p)
{
case ':':
case '/':
case '\\':
return filepath.substr(0, p - str + 1);
}
}
return "";
}
//! Extract path from full specified file path.
inline string GetPath(const char* filepath)
{
return GetPath(string(filepath));
}
//! Extract path from full specified file path.
inline stack_string GetPath(const stack_string& filepath)
{
const char* str = filepath.c_str();
for (const char* p = str + filepath.length() - 1; p >= str; --p)
{
switch (*p)
{
case ':':
case '/':
case '\\':
return filepath.substr(0, p - str + 1);
}
}
return "";
}
//! Extract file name with extension from full specified file path.
inline string GetFile(const string& filepath)
{
const char* str = filepath.c_str();
for (const char* p = str + filepath.length() - 1; p >= str; --p)
{
switch (*p)
{
case ':':
case '/':
case '\\':
return filepath.substr(p - str + 1);
}
}
return filepath;
}
inline const char* GetFile(const char* filepath)
{
const size_t len = strlen(filepath);
for (const char* p = filepath + len - 1; p >= filepath; --p)
{
switch (*p)
{
case ':':
case '/':
case '\\':
return p + 1;
}
}
return filepath;
}
//! Replace extension for given file.
inline void RemoveExtension(string& filepath)
{
const char* str = filepath.c_str();
for (const char* p = str + filepath.length() - 1; p >= str; --p)
{
switch (*p)
{
case ':':
case '/':
case '\\':
// we've reached a path separator - it means there's no extension in this name
return;
case '.':
// there's an extension in this file name
filepath = filepath.substr(0, p - str);
return;
}
}
// it seems the file name is a pure name, without path or extension
}
//! Replace extension for given file.
inline void RemoveExtension(stack_string& filepath)
{
const char* str = filepath.c_str();
for (const char* p = str + filepath.length() - 1; p >= str; --p)
{
switch (*p)
{
case ':':
case '/':
case '\\':
// we've reached a path separator - it means there's no extension in this name
return;
case '.':
// there's an extension in this file name
filepath = filepath.substr(0, p - str);
return;
}
}
// it seems the file name is a pure name, without path or extension
}
//! Extract file name without extension from full specified file path.
inline string GetFileName(const string& filepath)
{
string file = filepath;
RemoveExtension(file);
return GetFile(file);
}
//! Removes the trailing slash or backslash from a given path.
inline string RemoveSlash(const string& path)
{
if (path.empty() || (path[path.length() - 1] != '/' && path[path.length() - 1] != '\\'))
{
return path;
}
return path.substr(0, path.length() - 1);
}
//! get slash
inline string GetSlash()
{
return CRY_NATIVE_PATH_SEPSTR;
}
//! add a backslash if needed
inline string AddSlash(const string& path)
{
if (path.empty() || path[path.length() - 1] == '/')
{
return path;
}
if (path[path.length() - 1] == '\\')
{
return path.substr(0, path.length() - 1) + "/";
}
return path + "/";
}
//! add a backslash if needed
inline stack_string AddSlash(const stack_string& path)
{
if (path.empty() || path[path.length() - 1] == '/')
{
return path;
}
if (path[path.length() - 1] == '\\')
{
return path.substr(0, path.length() - 1) + "/";
}
return path + "/";
}
//! add a backslash if needed
inline string AddSlash(const char* path)
{
return AddSlash(string(path));
}
inline stack_string ReplaceExtension(const stack_string& filepath, const char* ext)
{
stack_string str = filepath;
if (ext != 0)
{
RemoveExtension(str);
if (ext[0] != 0 && ext[0] != '.')
{
str += ".";
}
str += ext;
}
return str;
}
//! Replace extension for given file.
inline string ReplaceExtension(const string& filepath, const char* ext)
{
string str = filepath;
if (ext != 0)
{
RemoveExtension(str);
if (ext[0] != 0 && ext[0] != '.')
{
str += ".";
}
str += ext;
}
return str;
}
//! Replace extension for given file.
inline string ReplaceExtension(const char* filepath, const char* ext)
{
return ReplaceExtension(string(filepath), ext);
}
//! Makes a fully specified file path from path and file name.
inline string Make(const string& path, const string& file)
{
return AddSlash(path) + file;
}
//! Makes a fully specified file path from path and file name.
inline string Make(const string& dir, const string& filename, const string& ext)
{
string path = ReplaceExtension(filename, ext);
path = AddSlash(dir) + path;
return path;
}
//! Makes a fully specified file path from path and file name.
inline string Make(const string& dir, const string& filename, const char* ext)
{
return Make(dir, filename, string(ext));
}
//! Makes a fully specified file path from path and file name.
inline stack_string Make(const stack_string& path, const stack_string& file)
{
return AddSlash(path) + file;
}
//! Makes a fully specified file path from path and file name.
inline stack_string Make(const stack_string& dir, const stack_string& filename, const stack_string& ext)
{
stack_string path = ReplaceExtension(filename, ext);
path = AddSlash(dir) + path;
return path;
}
//! Makes a fully specified file path from path and file name.
inline string Make(const char* path, const string& file)
{
return Make(string(path), file);
}
//! Makes a fully specified file path from path and file name.
inline string Make(const string& path, const char* file)
{
return Make(path, string(file));
}
//! Makes a fully specified file path from path and file name.
inline string Make(const char path[], const char file[])
{
return Make(string(path), string(file));
}
//! Makes a fully specified file path from path and file name.
inline string Make(const char* path, const char* file, const char* ext)
{
return Make(string(path), string(file), string(ext));
}
//! Makes a fully specified file path from path and file name.
inline string MakeFullPath(const string& relativePath)
{
return relativePath;
}
inline string GetParentDirectory (const string& strFilePath, int nGeneration = 1)
{
for (const char* p = strFilePath.c_str() + strFilePath.length() - 2; // -2 is for the possible trailing slash: there always must be some trailing symbol which is the file/directory name for which we should get the parent
p >= strFilePath.c_str();
--p)
{
switch (*p)
{
case ':':
return string (strFilePath.c_str(), p);
case '/':
case '\\':
// we've reached a path separator - return everything before it.
if (!--nGeneration)
{
return string(strFilePath.c_str(), p);
}
break;
}
}
// it seems the file name is a pure name, without path or extension
return string();
}
template<typename T, size_t SIZE>
inline CryStackStringT<T, SIZE> GetParentDirectoryStackString(const CryStackStringT<T, SIZE>& strFilePath, int nGeneration = 1)
{
for (const char* p = strFilePath.c_str() + strFilePath.length() - 2; // -2 is for the possible trailing slash: there always must be some trailing symbol which is the file/directory name for which we should get the parent
p >= strFilePath.c_str();
--p)
{
switch (*p)
{
case ':':
return CryStackStringT<T, SIZE> (strFilePath.c_str(), p);
case '/':
case '\\':
// we've reached a path separator - return everything before it.
if (!--nGeneration)
{
return CryStackStringT<T, SIZE>(strFilePath.c_str(), p);
}
break;
}
}
// it seems the file name is a pure name, without path or extension
return CryStackStringT<T, SIZE>();
}
//////////////////////////////////////////////////////////////////////////
// Description:
// Make a game correct path out of any input path.
inline stack_string MakeGamePath(const stack_string& path)
{
stack_string relativePath(ToUnixPath(path));
if ((!gEnv) || (!gEnv->pFileIO))
{
return relativePath;
}
unsigned int index = 0;
if (relativePath.length() && relativePath[index] == '@') // already aliased
{
if (relativePath.compareNoCase(0, 9, "@assets@/") == 0)
{
return relativePath.substr(9); // assets is assumed.
}
return relativePath;
}
const char* rootValue = gEnv->pFileIO->GetAlias("@root@");
if (rootValue)
{
stack_string rootPath(ToUnixPath(rootValue));
if (
(rootPath.size() > 0) &&
(rootPath.size() < relativePath.size()) &&
(relativePath.compareNoCase(0, rootPath.size(), rootPath) == 0)
)
{
stack_string chopped_string = relativePath.substr(rootPath.size());
stack_string rooted = stack_string("@root@") + chopped_string;
return rooted;
}
}
return relativePath;
}
//////////////////////////////////////////////////////////////////////////
// Description:
// Make a game correct path out of any input path.
inline string MakeGamePath(const string& path)
{
stack_string stackPath(path.c_str());
return MakeGamePath(stackPath).c_str();
}
// returns true if the string matches the wildcard
inline bool MatchWildcard (const char* szString, const char* szWildcard)
{
const char* pString = szString, * pWildcard = szWildcard;
// skip the obviously the same starting substring
while (*pWildcard && *pWildcard != '*' && *pWildcard != '?')
{
if (*pString != *pWildcard)
{
return false; // must be exact match unless there's a wildcard character in the wildcard string
}
else
{
++pString, ++pWildcard;
}
}
if (!*pString)
{
// this will only match if there are no non-wild characters in the wildcard
for (; *pWildcard; ++pWildcard)
{
if (*pWildcard != '*' && *pWildcard != '?')
{
return false;
}
}
return true;
}
switch (*pWildcard)
{
case '\0':
return false; // the only way to match them after the leading non-wildcard characters is !*pString, which was already checked
// we have a wildcard with wild character at the start.
case '*':
{
// merge consecutive ? and *, since they are equivalent to a single *
while (*pWildcard == '*' || *pWildcard == '?')
{
++pWildcard;
}
if (!*pWildcard)
{
return true; // the rest of the string doesn't matter: the wildcard ends with *
}
for (; *pString; ++pString)
{
if (MatchWildcard(pString, pWildcard))
{
return true;
}
}
return false;
}
case '?':
return MatchWildcard(pString + 1, pWildcard + 1) || MatchWildcard(pString, pWildcard + 1);
default:
assert (0);
return false;
}
}
};
#endif // CRYINCLUDE_CRYCOMMON_CRYPATH_H
@@ -0,0 +1,32 @@
/*
* 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.
*
*/
// Description: Utilities and functions used when cryphysics is disabled
#pragma once
// Assert if CryPhysics is disabled and no functionality replacement has been implemented
// 1: Runtime AZ_Error
// 2: Runtime Assertion
// 3: Compilation error
// Other: Do nothing
#define ENABLE_CRY_PHYSICS_REPLACEMENT_ASSERT 0
#if (ENABLE_CRY_PHYSICS_REPLACEMENT_ASSERT == 1)
#define CRY_PHYSICS_REPLACEMENT_ASSERT() AZ_Error("CryPhysics", false, __FUNCTION__ " - CRYPHYSICS REPLACEMENT NOT IMPLEMENTED")
#elif (ENABLE_CRY_PHYSICS_REPLACEMENT_ASSERT == 2)
#define CRY_PHYSICS_REPLACEMENT_ASSERT() AZ_Assert(false, "CRYPHYSICS REPLACEMENT NOT IMPLEMENTED")
#elif (ENABLE_CRY_PHYSICS_REPLACEMENT_ASSERT == 3)
#define CRY_PHYSICS_REPLACEMENT_ASSERT() static_assert(false, __FUNCTION__ " - CRYPHYSICS REPLACEMENT NOT IMPLEMENTED")
#else
#define CRY_PHYSICS_REPLACEMENT_ASSERT()
#endif
+216
View File
@@ -0,0 +1,216 @@
/*
* 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 : Simple POD types container
#ifndef CRYINCLUDE_CRYCOMMON_CRYPODARRAY_H
#define CRYINCLUDE_CRYCOMMON_CRYPODARRAY_H
#pragma once
#include <AzCore/std/containers/vector.h>
//////////////////////////////////////////////////////////////////////////
// POD Array
// vector like class (random access O(1)) without construction/destructor/copy constructor/assignment handling
// over-allocation allows safe prefetching where required without worrying about memory page boundaries
//////////////////////////////////////////////////////////////////////////
template <class T, size_t overAllocBytes = 0>
class PodArray
{
AZStd::vector<T> m_elements;
public:
typedef T value_type;
typedef T* iterator;
typedef const T* const_iterator;
//////////////////////////////////////////////////////////////////////////
// STL compatible interface
//////////////////////////////////////////////////////////////////////////
void resize(size_t numElements)
{
m_elements.resize(numElements);
}
//////////////////////////////////////////////////////////////////////////
ILINE void reserve(unsigned numElements) { m_elements.reserve(numElements); }
ILINE void push_back(const T& rElement) { m_elements.push_back(rElement); }
ILINE size_t size() const { return m_elements.size(); }
ILINE size_t capacity() const { return m_elements.capacity(); }
ILINE void clear() { m_elements.clear(); }
ILINE T* begin() { return m_elements.begin(); }
ILINE T* end() { return m_elements.end(); }
ILINE const T* begin() const { return m_elements.begin(); }
ILINE const T* end() const { return m_elements.end(); }
ILINE bool empty() const { return m_elements.empty(); }
ILINE const T& front() const { return m_elements.front(); }
ILINE T& front() { return m_elements.front(); }
ILINE const T& back() const { return m_elements.back(); }
ILINE T& back() { return m_elements.back(); }
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
PodArray()
: m_elements()
{
}
PodArray(int elem_count, int nNewCount = 0)
{
m_elements.reserve(elem_count);
m_elements.resize(nNewCount);
}
PodArray(const PodArray<T>& from)
: m_elements(from.m_elements)
{
}
~PodArray()
{
}
void Reset() { m_elements.clear(); }
void Free()
{
m_elements.clear();
m_elements.shrink_to_fit();
}
ILINE void Clear()
{
m_elements.clear();
}
int Find(const T& p)
{
const auto it = AZStd::find(m_elements.begin(), m_elements.end(), p);
if (it != m_elements.end())
{
return static_cast<int>(AZStd::distance(m_elements.begin(), it));
}
return -1;
}
inline void AddList(const PodArray<T>& lstAnother)
{
AZStd::copy(lstAnother.m_elements.begin(), lstAnother.m_elements.end(), AZStd::back_inserter(m_elements));
}
inline void AddList(T* pAnotherArray, int nAnotherCount)
{
AZStd::copy(pAnotherArray, pAnotherArray + nAnotherCount, AZStd::back_inserter(m_elements));
}
ILINE void Add(const T& p)
{
m_elements.push_back(p);
}
ILINE T& AddNew()
{
m_elements.emplace_back();
return m_elements.back();
}
void InsertBefore(const T& p, const unsigned int nBefore)
{
m_elements.insert(m_elements.begin() + nBefore, p);
}
void CheckAllocated(int elem_count)
{
if (m_elements.size() < elem_count)
{
m_elements.resize(elem_count);
}
}
void PreAllocate(int elem_count, int nNewCount = -1)
{
m_elements.reserve(elem_count);
if (nNewCount >= 0)
{
m_elements.resize(nNewCount);
}
}
inline void Delete(const int nElemId, const int nElemCount = 1)
{
AZ_Assert(nElemId >= 0 && nElemId + nElemCount <= size(), "Index out of bounds");
m_elements.erase(m_elements.begin() + nElemId, m_elements.begin() + nElemId + nElemCount);
}
inline void DeleteFastUnsorted(const int nElemId, const int nElemCount = 1)
{
AZ_Assert(nElemId >= 0 && nElemId + nElemCount <= size(), "Index out of bounds");
m_elements.erase(m_elements.begin() + nElemId, m_elements.begin() + nElemId + nElemCount);
}
inline bool Delete(const T& del)
{
const size_t numElements = m_elements.size();
m_elements.erase(std::remove(m_elements.begin(), m_elements.end(), del), m_elements.end());
return numElements != m_elements.size();
}
ILINE int Count() const { return m_elements.size(); }
ILINE unsigned int Size() const { return m_elements.size(); }
ILINE int IsEmpty() const { return m_elements.empty(); }
ILINE const T& operator [] (int i) const { return m_elements[i]; }
ILINE T& operator [] (int i) { return m_elements[i]; }
ILINE const T& GetAt(int i) const { return m_elements[i]; }
ILINE T& GetAt(int i) { return m_elements[i]; }
ILINE const T* Get(int i) const { return &m_elements[i]; }
ILINE T* Get(int i) { return &m_elements[i]; }
ILINE const T* GetElements() const { return m_elements.data(); }
ILINE T* GetElements() { return m_elements.data(); }
ILINE unsigned int GetDataSize() const { return m_elements.size() * sizeof(T); }
const T& Last() const { return m_elements.back(); }
T& Last() { return m_elements.back(); }
ILINE void DeleteLast()
{
assert(!m_elements.empty());
m_elements.pop_back();
}
PodArray<T>& operator=(const PodArray<T>& source_list)
{
m_elements = source_list.m_elements;
return *this;
}
//////////////////////////////////////////////////////////////////////////
// Return true if arrays have the same data.
bool Compare(const PodArray<T>& l) const
{
return m_elements == l.m_elements;
}
// for statistics
ILINE size_t ComputeSizeInMemory() const
{
return (sizeof(*this) + sizeof(T) * m_elements.capacity()) + overAllocBytes;
}
ILINE void RemoveIf(AZStd::function<bool(const T&)> testFunc)
{
m_elements.erase(AZStd::remove_if(m_elements.begin(), m_elements.end(), testFunc), m_elements.end());
}
};
#endif // CRYINCLUDE_CRYCOMMON_CRYPODARRAY_H
@@ -0,0 +1,207 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYPOOL_ALLOCATOR_H
#define CRYINCLUDE_CRYPOOL_ALLOCATOR_H
#pragma once
namespace NCryPoolAlloc
{
template<class TPool, class TItem>
class CFirstFit
: public TPool
{
public:
ILINE CFirstFit()
{
}
template<class T>
ILINE T Allocate(size_t Size, size_t Align = 1)
{
//fastpath?
if (TPool::m_pEmpty && TPool::m_pEmpty->Available(Size, Align))
{
TItem* pItem = TPool::Split(TPool::m_pEmpty, Size, Align);
if (!pItem)
{
return 0;
}
pItem->InUse(Align);
TPool::AllocatedMemory(pItem->MemSize());
//not fully occupied empty space?
TPool::m_pEmpty = pItem != TPool::m_pEmpty ? TPool::m_pEmpty : 0;
return TPool::Handle(pItem);
}
TItem* pBestItem;
for (pBestItem = TPool::m_Items.First(); pBestItem; pBestItem = pBestItem->Next())
{
if (pBestItem->Available(Size, Align)) // && (!pBestItem || pItem->MemSize()<pBestItem->MemSize()))
{
break;
}
}
if (!pBestItem)
{
return 0; //out of mem
}
TItem* pItem = TPool::Split(pBestItem, Size, Align);
if (!pItem) //no free node
{
return 0;
}
pItem->InUse(Align);
TPool::AllocatedMemory(pItem->MemSize());
//not fully occupied empty space?
TPool::m_pEmpty = pItem != pBestItem ? pBestItem : 0;
return TPool::Handle(pItem);
}
template<class T>
ILINE bool Free(T Handle, bool ForceBoundsCheck = false)
{
return Handle ? TPool::Free(Handle, ForceBoundsCheck) : false;
}
};
template<class TPool, class TItem>
class CWorstFit
: public TPool
{
public:
ILINE CWorstFit()
{
}
template<class T>
ILINE T Allocate(size_t Size, size_t Align = 1)
{
TItem* pBestItem = 0;
for (TItem* pItem = TPool::m_Items.First(); pItem; pItem = pItem->Next())
{
if (pItem->IsFree() && (!pBestItem || pItem->MemSize() > pBestItem->MemSize()))
{
pBestItem = pItem;
}
}
if (!pBestItem || !pBestItem->Available(Size, Align))
{
return 0; //out of mem
}
TItem* pItem = Split(pBestItem, Size, Align);
if (!pItem) //no free node
{
return 0;
}
pItem->InUse(Align);
AllocatedMemory(pItem->MemSize());
return Handle(pItem);
}
};
template<class TPool, class TItem>
class CBestFit
: public TPool
{
public:
ILINE CBestFit()
{
}
template<class T>
ILINE T Allocate(size_t Size, size_t Align = 1)
{
TItem* pBestItem = 0;
for (TItem* pItem = TPool::m_Items.First(); pItem; pItem = pItem->Next())
{
if ((!pBestItem || pItem->MemSize() < pBestItem->MemSize()) && pItem->Available(Size, Align))
{
if (pItem->MemSize() == Size)
{
pItem->InUse(Align);
AllocatedMemory(pItem->MemSize());
return (T)Handle(pItem);
}
pBestItem = pItem;
}
}
if (!pBestItem)
{
return 0; //out of mem
}
TItem* pItem = Split(pBestItem, Size, Align);
if (!pItem) //no free node
{
return 0;
}
pItem->InUse(Align);
AllocatedMemory(pItem->MemSize());
return (T)Handle(pItem);
}
};
template<class TAllocator>
class CReallocator
: public TAllocator
{
public:
template<class T>
ILINE bool Reallocate(T* pData, size_t Size, size_t Alignment)
{
//special cases
if (!Size) //just free?
{
TAllocator::Free(*pData);
*pData = 0;
return true;
}
if (!*pData) //just alloc?
{
*pData = TAllocator::template Allocate<T>(Size, Alignment);
return *pData != 0;
}
//same size, nothing to do at all?
if (TAllocator::Item(*pData)->MemSize() == Size)
{
return true;
}
if (TAllocator::ReSize(pData, Size))
{
return true;
}
T pNewData = TAllocator::template Allocate<T>(Size, Alignment);
if (!pNewData)
{
return false;
}
memcpy(TAllocator::template Resolve<uint8*>(pNewData),
TAllocator::template Resolve<uint8*>(*pData), min(TAllocator::Item(*pData)->MemSize(), Size));
TAllocator::template Free(*pData);
*pData = pNewData;
return true;
}
};
}
#endif // CRYINCLUDE_CRYPOOL_ALLOCATOR_H
@@ -0,0 +1,655 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYPOOL_CONTAINER_H
#define CRYINCLUDE_CRYPOOL_CONTAINER_H
#pragma once
namespace NCryPoolAlloc
{
template<size_t TElementCount, class TElement>
class CPool
: public CMemoryStatic<TElementCount* sizeof(TElement)>
{
class CPoolNode;
class CPoolNode
: public CListItem<CPoolNode>
{
};
CList<CPoolNode> m_List;
public:
ILINE CPool()
{
CPoolNode* pPrev = 0;
CPoolNode* pNode = 0;
for (size_t a = 1; a < TElementCount; a++) //skip first element as it would be counted as zero ptr
{
uint8* pData = &CMemoryStatic<TElementCount* sizeof(TElement)>::Data()[a * sizeof(TElement)];
pNode = reinterpret_cast<CPoolNode*>(pData);
pNode->Prev(pPrev);
if (pPrev)
{
pPrev->Next(pNode);
}
else
{
m_List.First(pNode);
}
pPrev = pNode;
// m_List.AddLast(pNode);
}
if (pPrev)
{
pPrev->Next(0);
m_List.Last(pPrev);
}
}
ILINE uint8* Allocate([[maybe_unused]] size_t Size, [[maybe_unused]] size_t Align = 1)
{
CPoolNode* pNode = m_List.PopFirst();
return reinterpret_cast<uint8*>(pNode);
}
template<class T>
ILINE void Free(T* pData)
{
if (pData)
{
CPoolNode* pNode = reinterpret_cast<CPoolNode*>(pData);
m_List.AddLast(pNode);
}
}
ILINE TElement& operator[](uint32 Idx)
{
uint8* pData = &CMemoryStatic<TElementCount* sizeof(TElement)>::Data()[Idx * sizeof(TElement)];
return *reinterpret_cast<TElement*>(pData);
}
ILINE const TElement& operator[](uint32 Idx) const
{
const uint8* pData = &CMemoryStatic<TElementCount* sizeof(TElement)>::Data()[Idx * sizeof(TElement)];
return *reinterpret_cast<const TElement*>(pData);
}
};
template<class TMemory, bool BoundsCheck = false>
class CInPlace
: public TMemory
{
protected:
CList<CListItemInPlace> m_Items;
size_t m_Allocated;
CListItemInPlace* m_pEmpty;
ILINE void AllocatedMemory(size_t S)
{
m_Allocated += S + sizeof(CListItemInPlace);
}
ILINE void FreedMemory(size_t S)
{
m_Allocated -= S + sizeof(CListItemInPlace);
}
ILINE void Stack(CListItemInPlace* pItem)
{
}
public:
ILINE CInPlace()
: m_Allocated(0)
{
}
ILINE void InitMem(const size_t S = 0, uint8* pData = 0)
{
TMemory::InitMem(S, pData);
if (!TMemory::MemSize())
{
return;
}
pData = TMemory::Data();
CListItemInPlace* pFirst = reinterpret_cast<CListItemInPlace*>(pData);
CListItemInPlace* pFree = pFirst + 1;
CListItemInPlace* pLast = reinterpret_cast<CListItemInPlace*>(pData + TMemory::MemSize()) - 1;
m_Items.~CList<CListItemInPlace>();
new (&m_Items)CList<CListItemInPlace>();
m_Items.AddLast(pFirst);
m_Items.AddLast(pFree);
m_Items.AddLast(pLast);
pFirst->InUse(0); //static first item
pFree->Free();
pLast->InUse(0); //static last item
m_pEmpty = pFree;
m_Allocated = 0;
}
ILINE size_t FragmentCount() const
{
return m_Items.Count();
}
ILINE CListItemInPlace* Split(CListItemInPlace* pItem, size_t Size, size_t Align)
{
size_t Offset = reinterpret_cast<size_t>(pItem->Data());
Offset += pItem->MemSize(); //ptr to end
Offset -= Size; //minus size
Size += Offset & (Align - 1); //adjust size to fit required alignment
Offset -= Offset & (Align - 1);
size_t TSize = sizeof(CListItemInPlace);
Offset -= TSize; //header
if (Offset <= reinterpret_cast<size_t>(pItem + 1)) //not enough space for splitting?
{
return pItem;
}
CListItemInPlace* pItemNext = reinterpret_cast<CListItemInPlace*>(Offset);
const size_t Offset2 = reinterpret_cast<size_t>(pItemNext->Data());
CPA_ASSERT(!(Offset2 & (Align - 1)));
m_Items.AddBehind(pItemNext, pItem);
//pItemNext->Prev(pItem);
//pItemNext->Next(pItem->Next());
// if(pItem->Next())
// pItem->Next()->Prev(pItemNext);
// pItem->Next(pItemNext);
pItemNext->Free();
return pItemNext;
}
ILINE void Merge(CListItemInPlace* pItem)
{
//merge with next if possible
CListItemInPlace* pItemNext = pItem->Next();
if (pItemNext->IsFree())
{
if (m_pEmpty == pItemNext)
{
m_pEmpty = pItem;
}
m_Items.Remove(pItemNext);
//pItem->Next(pItemNext->Next());
//pItem->Next()->Prev(pItem);
}
//merge with prev if possible
CListItemInPlace* pItemPrev = pItem->Prev();
if (pItemPrev->IsFree())
{
if (m_pEmpty == pItem)
{
m_pEmpty = pItemPrev;
}
m_Items.Remove(pItem);
//pItemPrev->Next(pItem->Next());
//pItem->Next()->Prev(pItemPrev);
pItem = pItemPrev;
}
}
template<class T>
ILINE T Resolve(void* rItem) const
{
return reinterpret_cast<T>(rItem);
}
template<class T>
ILINE size_t Size(const T* pData) const
{
const CListItemInPlace* pItem = Item(pData);
return pItem->MemSize();
}
bool InBounds(const void* pData, const bool Check) const
{
return !Check || (
reinterpret_cast<size_t>(pData) >= reinterpret_cast<size_t>(TMemory::Data()) &&
reinterpret_cast<size_t>(pData) < reinterpret_cast<size_t>(TMemory::Data()) + TMemory::MemSize());
}
template<class T>
ILINE bool Free(T* pData, bool ForceBoundsCheck = false)
{
if (pData && InBounds(pData, BoundsCheck | ForceBoundsCheck))
{
CListItemInPlace* pItem = Item(pData);
FreedMemory(pItem->MemSize());
pItem->Free();
Merge(pItem);
return true;
}
return false;
}
ILINE bool Beat(){return false; }//dummy beat in case no defragmentator is wraping
ILINE size_t MemFree() const{return TMemory::MemSize() - m_Allocated; }
ILINE size_t MemSize() const{return TMemory::MemSize(); }
ILINE uint8* Handle(CListItemInPlace* pItem) const
{
return pItem->Data();
}
template<class T>
ILINE CListItemInPlace* Item(T* pData)
{
return reinterpret_cast<CListItemInPlace*>(pData) - 1;
}
template<class T>
ILINE const CListItemInPlace* Item(const T* pData) const
{
return reinterpret_cast<const CListItemInPlace*>(pData) - 1;
}
ILINE static bool Defragmentable(){return false; }
template<class T>
ILINE bool ReSize(T* pData, size_t SizeNew)
{
//special cases
CListItemInPlace* pItem = Item(*pData);
const size_t SizeOld = pItem->MemSize();
//reduction
if (SizeOld > SizeNew)
{
if (pItem->Next()->IsFree())
{
CListItemInPlace* pNextNext = pItem->Next()->Next();
size_t Offset = reinterpret_cast<size_t>(pItem->Data());
Offset += SizeNew; //Offset to next
CListItemInPlace* pItemNext = reinterpret_cast<CListItemInPlace*>(Offset);
pItem->Next(pItemNext);
pNextNext->Prev(pItemNext);
pItemNext->Prev(pItem);
pItemNext->Next(pNextNext);
pItemNext->Free();
return true;
}
if (SizeOld - SizeNew <= sizeof(CListItemInPlace))
{
return true; //header is bigger than the amount of freed memory
}
//split
size_t Offset = reinterpret_cast<size_t>(pItem->Data());
Offset += SizeNew; //Offset to next
CListItemInPlace* pItemNext = reinterpret_cast<CListItemInPlace*>(Offset);
m_Items.AddBehind(pItemNext, pItem);
pItemNext->Free();
return true;
}
//SizeOld<SizeNew grow
CListItemInPlace* pNext = pItem->Next();
CListItemInPlace* pNextNext = pNext->Next();
const size_t SizeNext = pNext->IsFree() ? pNext->MemSize() + sizeof(CListItemInPlace) : 0;
if (SizeNew <= SizeNext + SizeOld)
{
if (SizeNew + sizeof(CListItemInPlace) + 1 < SizeNext + SizeOld)
{
size_t Offset = reinterpret_cast<size_t>(pItem->Data());
Offset += SizeNew; //Offset to next
CListItemInPlace* pItemNext = reinterpret_cast<CListItemInPlace*>(Offset);
pItem->Next(pItemNext);
pNextNext->Prev(pItemNext);
pItemNext->Prev(pItem);
pItemNext->Next(pNextNext);
pItemNext->Free();
}
else
{
pItem->Next(pNextNext);
pNextNext->Prev(pItem);
}
return true;
}
return false; //no further in-place realloc possible
}
};
template<class TMemory, size_t TNodeCount, bool BoundsCheck = false>
class CReferenced
: public TMemory
{
typedef CPool<TNodeCount, CListItemReference> tdNodePool;
protected:
tdNodePool m_NodePool;
CList<CListItemReference> m_Items;
size_t m_Allocated;
CListItemReference* m_pEmpty;
ILINE void AllocatedMemory(size_t S)
{
m_Allocated += S;
}
ILINE void FreedMemory(size_t S)
{
m_Allocated -= S;
}
ILINE void Stack(CListItemReference* pItem)
{
m_Items.Validate(pItem);
CListItemReference* pItem2 = 0;
CListItemReference* pNext = pItem->Next();
uint8* pData = pItem->Data(pNext->Align());
if (pData != pItem->Data()) //needs splitting 'cause of alignment?
{
pItem2 = reinterpret_cast<CListItemReference*>(m_NodePool.Allocate(1, 1));
if (!pItem2) //no free node found for splitting?
{
return; //failed to stack -> return
}
}
memmove(pData, pNext->Data(), pNext->MemSize());
if (pItem2) //was not aligned?
{
//then keep the current ITem
const size_t SizeItem = pItem->MemSize();
const size_t SizeNext = pNext->MemSize();
m_Items.AddBehind(pItem2, pNext);
pItem2->Data(pData + SizeNext);
pNext->Data(pData);
pItem2->MemSize(pItem2->Next()->Data() - pItem2->Data());
pNext->MemSize(SizeNext);
pItem->MemSize(pNext->Data() - pItem->Data());
m_Items.Validate(pItem);
m_Items.Validate(pItem2);
m_Items.Validate(pNext);
}
else
{
const size_t SizeItem = pItem->MemSize();
const size_t SizeNext = pNext->MemSize();
m_Items.Remove(pItem);
m_Items.AddBehind(pItem, pNext);
pItem->Data(pNext->Data());
pNext->Data(pData);
pNext->MemSize(SizeItem);
pItem->MemSize(SizeNext);
m_Items.Validate(pItem);
m_Items.Validate(pNext);
}
}
public:
ILINE CReferenced()
: m_Allocated(0)
{
}
ILINE void InitMem(const size_t S = 0, uint8* pData = 0)
{
TMemory::InitMem(S, pData);
if (!TMemory::MemSize())
{
return;
}
pData = TMemory::Data();
CListItemReference* pItem = reinterpret_cast<CListItemReference*>(m_NodePool.Allocate(1, 1));
CListItemReference* pLast = reinterpret_cast<CListItemReference*>(m_NodePool.Allocate(1, 1));
m_Items.AddFirst(pItem);
m_Items.AddLast(pLast);
pLast->Init(pData + TMemory::MemSize(), 0, pItem, 0);
pLast->InUse(0);
pItem->Init(pData, TMemory::MemSize(), 0, pLast);
pItem->Free();
m_pEmpty = pItem;
m_Allocated = 0;
}
ILINE size_t FragmentCount() const
{
return m_Items.Count();
}
ILINE CListItemReference* Split(CListItemReference* pItem, size_t Size, size_t Align)
{
size_t Offset = reinterpret_cast<size_t>(pItem->Data());
if (!(Offset & (Align - 1))) //perfectly aligned?
{
if (pItem->MemSize() != Size) //not perfectly fitting?
{ //then split
CListItemReference* pItemPrev = reinterpret_cast<CListItemReference*>(m_NodePool.Allocate(1, 1));
if (!pItemPrev)
{
return 0;
}
const size_t OrgSize = pItem->MemSize();
m_Items.AddBefore(pItemPrev, pItem);
pItemPrev->Data(pItem->Data());
pItem->Data(pItem->Data() + Size);
pItem->MemSize(OrgSize - Size);
pItemPrev->MemSize(Size);
pItem = pItemPrev;
}
return pItem;
}
//not aligned to block start
//then lets try to align to block end
Offset += pItem->MemSize(); //ptr to end
Offset -= Size; //minus size
if (!(Offset & (Align - 1))) //perfectly aligned?
{
CListItemReference* pItemPrev = reinterpret_cast<CListItemReference*>(m_NodePool.Allocate(1, 1));
if (!pItemPrev)
{
return 0;
}
const size_t OrgSize = pItem->MemSize();
m_Items.AddBefore(pItemPrev, pItem);
pItemPrev->Data(pItem->Data());
pItem->Data(reinterpret_cast<uint8*>(Offset));
pItemPrev->MemSize(OrgSize - Size);
pItem->MemSize(Size);
pItemPrev->Free();
return pItem;
}
//last resort, fragment it into 3 parts
//Size +=Offset&(Align-1); //adjust size to fit required alignment
Offset -= Offset & (Align - 1);
CListItemReference* pItemPrev = reinterpret_cast<CListItemReference*>(m_NodePool.Allocate(1, 1));
CListItemReference* pItemNext = reinterpret_cast<CListItemReference*>(m_NodePool.Allocate(1, 1));
if (!pItemPrev || !pItemNext)
{
return 0;
}
const size_t OrgSize = pItem->MemSize();
m_Items.AddBefore(pItemPrev, pItem);
m_Items.AddBehind(pItemNext, pItem);
pItemPrev->Data(pItem->Data());
pItem->Data(reinterpret_cast<uint8*>(Offset));
pItemNext->Data(pItem->Data() + Size);
pItemPrev->MemSize(pItem->Data() - pItemPrev->Data());
pItemNext->MemSize(OrgSize - pItemPrev->MemSize() - Size);
pItem->MemSize(Size);
pItemPrev->Free();
pItemNext->Free();
return pItem;
}
ILINE void Merge(CListItemReference* pItem)
{
m_Items.Validate(pItem);
//merge with next if possible
CListItemReference* pItemNext = pItem->Next();
if (pItemNext && pItemNext->IsFree())
{
if (m_pEmpty == pItemNext)
{
m_pEmpty = pItem;
}
const size_t OrgSize = pItem->MemSize();
const size_t NextSize = pItemNext->MemSize();
m_Items.Remove(pItemNext);
pItem->MemSize(OrgSize + NextSize);
m_NodePool.Free(pItemNext);
}
//merge with prev if possible
CListItemReference* pItemPrev = pItem->Prev();
if (pItemPrev && pItemPrev->IsFree())
{
if (m_pEmpty == pItem)
{
m_pEmpty = pItemPrev;
}
const size_t OrgSize = pItem->MemSize();
const size_t PrevSize = pItemPrev->MemSize();
m_Items.Remove(pItem);
pItemPrev->MemSize(PrevSize + OrgSize);
m_NodePool.Free(pItem);
}
}
template<class T>
ILINE T Resolve(const uint32 ID)
{
CPA_ASSERT(ID); //0 is invalid
return reinterpret_cast<T>(Item(ID)->Data());
}
ILINE uint32 AddressToHandle(void* pData)
{
for (CListItemReference* pItem = m_Items.First(); pItem; pItem = pItem->Next())
{
if (pItem->Data() == pData)
{
return Handle(pItem);
}
}
return 0;
}
template<class T>
ILINE size_t Size(T ID) const
{
CPA_ASSERT(ID); //0 is invalid
return Item(ID)->MemSize();
}
template<class T>
bool InBounds([[maybe_unused]] T ID, [[maybe_unused]] const bool Check) const
{
//boundscheck doesn't work for Referenced containers
return true;
}
template<class T>
ILINE bool Free(T ID, bool ForceBoundsCheck = false)
{
IF (!ID, false)
{
return true;
}
IF (!InBounds(ID, BoundsCheck | ForceBoundsCheck), false)
{
return false;
}
CListItemReference* pItem = Item(ID);
FreedMemory(pItem->MemSize());
pItem->Free();
Merge(pItem);
return true;
}
ILINE bool Beat(){return false; }//dummy beat in case no defragmentator is wraping
ILINE size_t MemFree() const{return TMemory::MemSize() - m_Allocated; }
ILINE size_t MemSize() const{return TMemory::MemSize(); }
ILINE uint32 Handle(CListItemReference* pItem) const
{
return static_cast<uint32>(pItem - &m_NodePool[0]);
}
ILINE CListItemReference* Item(uint32 ID)
{
return &m_NodePool[ID];
}
ILINE const CListItemReference* Item(uint32 ID) const
{
return &m_NodePool[ID];
}
ILINE static bool Defragmentable(){return true; }
template<class T>
ILINE bool ReSize(T* pData, size_t SizeNew)
{
CListItemReference* pItem = Item(*pData);
const size_t SizeOld = pItem->MemSize();
//reduction
if (SizeOld > SizeNew)
{
if (pItem->Next()->IsFree())
{
CListItemReference* pNext = pItem->Next();
const size_t NextSize = pNext->MemSize();
pNext->Data(pNext->Data() + SizeNew - SizeOld);
pNext->MemSize(NextSize - SizeNew + SizeOld);
pItem->MemSize(SizeNew);
return true;
}
//split
CListItemReference* pItemNext = reinterpret_cast<CListItemReference*>(m_NodePool.Allocate(1, 1));
m_Items.AddBehind(pItemNext, pItem);
pItemNext->Data(pItem->Data() + SizeNew);
pItem->MemSize(SizeNew);
pItemNext->MemSize(SizeOld - SizeNew);
pItemNext->Free();
return true;
}
//SizeOld<SizeNew grow
CListItemReference* pNext = pItem->Next();
const size_t SizeNext = pNext->IsFree() ? pNext->MemSize() : 0;
if (SizeNew <= SizeNext + SizeOld)
{
if (SizeNew == SizeNext + SizeOld)
{
m_Items.Remove(pNext);
m_NodePool.Free(pNext);
}
else
{
pNext->Data(pNext->Data() + SizeNew - SizeOld);
pNext->MemSize(SizeNext - SizeNew + SizeOld);
}
pItem->MemSize(SizeNew);
return true;
}
return false; //no further in-place realloc possible
}
};
}
#endif // CRYINCLUDE_CRYPOOL_CONTAINER_H
+65
View File
@@ -0,0 +1,65 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYPOOL_DEFRAG_H
#define CRYINCLUDE_CRYPOOL_DEFRAG_H
#pragma once
namespace NCryPoolAlloc
{
template<class T>
class CDefragStacked
: public T
{
template<class TItem>
ILINE bool DefragElement(TItem* pItem)
{
T::m_Items.Validate();
if (pItem)
{
for (; pItem->Next(); pItem = pItem->Next())
{
if (!pItem->IsFree())
{
continue;
}
if (pItem->Next()->Locked())
{
continue;
}
if (!pItem->Available(pItem->Next()->Align(), pItem->Next()->Align()))
{
continue;
}
T::m_Items.Validate(pItem);
Stack(pItem);
T::m_Items.Validate(pItem);
Merge(pItem);
T::m_Items.Validate();
return true;
}
}
return false;
}
public:
ILINE bool Beat()
{
return T::Defragmentable() && DefragElement(T::m_Items.First());
};
};
}
#endif // CRYINCLUDE_CRYPOOL_DEFRAG_H
@@ -0,0 +1,81 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYPOOL_FALLBACK_H
#define CRYINCLUDE_CRYPOOL_FALLBACK_H
#pragma once
namespace NCryPoolAlloc
{
enum EFallbackMode
{
EFM_DISABLED,
EFM_ENABLED,
EFM_ALWAYS
};
template<class TAllocator>
class CFallback
: public TAllocator
{
EFallbackMode m_Fallback;
public:
ILINE CFallback()
: m_Fallback(EFM_DISABLED)
{
}
template<class T>
ILINE T Allocate(size_t Size, size_t Align = 1)
{
if (EFM_ALWAYS == m_Fallback)
{
return reinterpret_cast<T>(CPA_ALLOC(Align, Size));
}
T pRet = TAllocator::template Allocate<T>(Size, Align);
if (!pRet && EFM_ENABLED == m_Fallback)
{
return reinterpret_cast<T>(CPA_ALLOC(Align, Size));
}
return pRet;
}
template<class T>
ILINE bool Free(T Handle)
{
if (!Handle)
{
return true;
}
if (EFM_ALWAYS == m_Fallback)
{
CPA_FREE(Handle);
return true;
}
if (EFM_ENABLED == m_Fallback && TAllocator::InBounds(Handle, true))
{
CPA_FREE(Handle);
return true;
}
return TAllocator::template Free<T>(Handle);
}
void FallbackMode(EFallbackMode M){m_Fallback = M; }
EFallbackMode FallbaclMode() const{return m_Fallback; }
};
}
#endif // CRYINCLUDE_CRYPOOL_FALLBACK_H
@@ -0,0 +1,203 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYPOOL_INSPECTOR_H
#define CRYINCLUDE_CRYPOOL_INSPECTOR_H
#pragma once
namespace NCryPoolAlloc
{
template<class TAllocator>
class CInspector
: public TAllocator
{
enum
{
EITableSize = 30
};
size_t m_Allocations[EITableSize];
size_t m_Alignment[EITableSize];
char m_LogFileName[1024];
size_t m_AllocCount;
size_t m_FreeCount;
size_t m_ResizeCount;
size_t m_FailAllocCount;
size_t m_FailFreeCount;
size_t m_FailResizeCount;
void WriteOut(const char* pFileName, uint32 Stack, const char* pFormat, ...) const
{
/*
if(!pFileName)
{
if(!*m_LogFileName)
return;
pFileName = m_LogFileName;
}
FILE* File = fopen(pFileName,"a");
if(File)
{
char Buffer[1024];
for(uint32 a=0;a<Stack;a++)
Buffer[a]=' ';
va_list args;
va_start(args,pFormat);
vsprintf(Buffer+Stack,pFormat,args);
fwrite(Buffer,1,strlen(Buffer),File);
fclose(File);
va_end(args);
}
*/
}
size_t Bit(size_t C) const
{
size_t Count = 0;
C >>= 1;
while (C)
{
Count++;
C >>= 1;
}
return Count >= EITableSize ? EITableSize - 1 : Count;
}
public:
CInspector()
{
for (size_t a = 0; a < EITableSize; a++)
{
m_Allocations[a] = m_Alignment[a] = 0;
}
m_LogFileName[0] = 0;
m_AllocCount = 0;
m_FreeCount = 0;
m_ResizeCount = 0;
m_FailAllocCount = 0;
m_FailFreeCount = 0;
m_FailResizeCount = 0;
}
bool LogFileName(const char* pFileName)
{
const size_t Size = strlen(pFileName) + 1;
if (Size > sizeof(m_LogFileName))
{
m_LogFileName[0] = 0;
return false;
}
memcpy(m_LogFileName, pFileName, Size);
WriteOut(0, "[log start]\n");
return true;
}
void SaveStats(const char* pFileName) const
{
WriteOut(pFileName, 0, "stats:\n");
WriteOut(pFileName, 1, "Counter calls|fails\n");
WriteOut(pFileName, 2, "Alloc: %6d|%6d\n", m_AllocCount, m_FailAllocCount);
WriteOut(pFileName, 2, "Free: %6d|%6d\n", m_FreeCount, m_FailFreeCount);
WriteOut(pFileName, 2, "Resize:%6d|%6d\n", m_ResizeCount, m_FailResizeCount);
WriteOut(pFileName, 1, "Allocations:\n");
for (size_t a = 0; a < EITableSize; a++)
{
WriteOut(pFileName, 2, "%9dByte: %8d\n", 1 << a, m_Allocations[a]);
}
WriteOut(pFileName, 1, "Alignment:\n");
for (size_t a = 0; a < EITableSize; a++)
{
WriteOut(pFileName, 2, "%9dByte: %8d\n", 1 << a, m_Alignment[a]);
}
}
template<class T>
ILINE T Allocate(size_t Size, size_t Align = 1)
{
m_AllocCount++;
m_Allocations[Bit(Size)]++;
m_Alignment[Bit(Align)]++;
T pData = TAllocator::template Allocate<T>(Size, Align);
WriteOut(0, 0, "[A|%d|%d|%d]", (int)pData, Size, Align);
if (!pData)
{
m_FailAllocCount++;
WriteOut(0, 0, "[failed]", Size, Align);
}
return pData;
}
template<class T>
ILINE bool Free(T pData, bool ForceBoundsCheck = false)
{
m_FreeCount++;
const bool Ret = TAllocator::Free(pData, ForceBoundsCheck);
WriteOut(0, 0, "[F|%d|%d|%d]", (int)pData, (int)ForceBoundsCheck, (int)Ret);
m_FailFreeCount += !Ret;
return Ret;
}
//template<class T>
//ILINE bool Free(T pData)
// {
// m_FreeCount++;
// const bool Ret = TAllocator::Free(pData);
// WriteOut(0,0,"[F|%d|%d|%d]",(int)pData,(int)-1,(int)Ret);
// m_FailFreeCount+=!Ret;
// return Ret;
// }
template<class T>
ILINE bool Resize(T** pData, size_t Size, size_t Alignment)
{
m_ResizeCount++;
const bool Ret = TAllocator::Resize(pData, Size, Alignment);
WriteOut(0, 0, "[R|%d|%d|%d]", (int)*pData, (int)-1, (int)Ret);
m_FailResizeCount += !Ret;
return Ret;
}
template<class T>
ILINE size_t FindBiggest(const T* pItem)
{
size_t Biggest = 0;
while (pItem)
{
if (pItem->IsFree() && pItem->MemSize() > Biggest)
{
Biggest = pItem->MemSize();
}
pItem = pItem->Next();
}
return Biggest;
}
ILINE size_t BiggestFreeBlock()
{
return FindBiggest(TAllocator::m_Items.First());
}
ILINE uint8* FirstItem()
{
return TAllocator::m_Items.First()->Data();
}
};
}
#endif // CRYINCLUDE_CRYPOOL_INSPECTOR_H
+366
View File
@@ -0,0 +1,366 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYPOOL_LIST_H
#define CRYINCLUDE_CRYPOOL_LIST_H
#pragma once
namespace NCryPoolAlloc
{
class CListItemInPlace;
class CListItemReference;
template<typename TItem>
class CListItem
{
TItem* m_pPrev;
TItem* m_pNext;
public:
ILINE TItem* Prev(){return m_pPrev; }
ILINE TItem* Next(){return m_pNext; }
ILINE const TItem* Prev() const{return m_pPrev; }
ILINE const TItem* Next() const{return m_pNext; }
ILINE void Prev(TItem* pPrev){ m_pPrev = pPrev; }
ILINE void Next(TItem* pNext){ m_pNext = pNext; }
//debugging
void Validate();
};
template<typename TItem>
class CListItemFlagged
: public CListItem<TItem>
{
enum
{
ELIF_INUSE = (1 << 0),
ELIF_LOCKED = (1 << 1),
};
uint32 m_Flags : 8;
uint32 m_Align : 24;
public:
ILINE CListItemFlagged()
: m_Flags(0)
{
}
ILINE bool IsFree() const{return (m_Flags & ELIF_INUSE) != ELIF_INUSE; }
ILINE void Free(){m_Flags &= ~ELIF_INUSE; }
ILINE void InUse(uint32 A){m_Flags |= ELIF_INUSE; m_Align = A; }
ILINE bool Locked() const{return ELIF_LOCKED == (m_Flags & ELIF_LOCKED); }
ILINE void Lock(){m_Flags |= ELIF_LOCKED; }
ILINE void Unlock(){m_Flags &= ~ELIF_LOCKED; }
ILINE uint32 Align() const{return m_Align; }
};
class CListItemInPlace
: public CListItemFlagged<CListItemInPlace>
{
public:
ILINE void Init([[maybe_unused]] uint8* pData, [[maybe_unused]] size_t Size, CListItemInPlace* pPrev, CListItemInPlace* pNext)
{
Prev(pPrev);
Next(pNext);
CPA_ASSERT(Size == MemSize());
}
ILINE bool Available(size_t Size, size_t Align) const
{
size_t Offset = reinterpret_cast<size_t>(Data());
if (Offset & (Align - 1)) //not aligned?
{
Size += sizeof(CListItemInPlace) + Align - 1; //then an intermedian node needs to fit
}
return Size <= MemSize() && IsFree();
}
ILINE uint8* Data(){return reinterpret_cast<uint8*>(this) + sizeof(CListItemInPlace); }
ILINE const uint8* Data() const{return reinterpret_cast<const uint8*>(this) + sizeof(CListItemInPlace); }
ILINE size_t MemSize() const
{
const uint8* pNext = reinterpret_cast<const uint8*>(Next());
const uint8* pThis = reinterpret_cast<const uint8*>(this);
const size_t ESize = sizeof(CListItemInPlace);
size_t Delta = pNext - pThis;
Delta -= ESize;
return Delta;
}
};
class CListItemReference
: public CListItemFlagged<CListItemReference>
{
uint8* m_pData;
// size_t m_Size;
public:
ILINE void Init(uint8* pData, size_t Size, CListItemReference* pPrev, CListItemReference* pNext)
{
Data(pData);
Prev(pPrev);
Next(pNext);
MemSize(Size);
}
ILINE bool Available(size_t Size, size_t Align) const
{
size_t Offset = reinterpret_cast<size_t>(Data());
if ((Offset & (Align - 1)))
{
Size += Align - (Offset & (Align - 1));
}
return Size <= MemSize() && IsFree();
}
ILINE void Data(uint8* pData){m_pData = pData; }
ILINE uint8* Data(size_t Align)
{
Align--;
size_t Offset = reinterpret_cast<size_t>(m_pData);
Offset = (Offset + Align) & ~Align;
return reinterpret_cast<uint8*>(Offset);
}
ILINE uint8* Data(){return m_pData; }
ILINE const uint8* Data() const{return m_pData; }
ILINE void MemSize([[maybe_unused]] size_t Size) { }
ILINE size_t MemSize() const
{
const size_t T = reinterpret_cast<size_t>(Data());
const size_t N = Next() ? reinterpret_cast<size_t>(Next()->Data()) : T;
return N - T;
}
//ILINE void MemSize(size_t Size){m_Size=Size;}
//ILINE size_t MemSize()const{return m_Size;}
};
template<class TItem, bool VALIDATE = false>
class CList
{
TItem* m_pFirst;
TItem* m_pLast;
size_t m_Count;
public:
ILINE CList()
: m_pFirst(0)
, m_pLast(0)
, m_Count(0)
{
}
ILINE void First(TItem* pItem){m_pFirst = pItem; }
ILINE TItem* First(){return m_pFirst; }
ILINE void Last(TItem* pItem){m_pLast = pItem; }
ILINE TItem* Last(){return m_pLast; }
ILINE bool Empty() const{return m_pFirst == 0; }
ILINE TItem* PopFirst()
{
Validate();
if (!m_pFirst)
{
return 0;
}
TItem* pRet = m_pFirst;
m_pFirst = m_pFirst->Next();
if (m_pFirst) //if any element exists
{
m_pFirst->Prev(0); //set prev ptr of this element to 0
}
else
{
m_pLast = 0; //set ptr to last element to 0 if ptr to first is zero as well
}
Validate();
m_Count--;
return pRet;
}
ILINE TItem* PopLast()
{
Validate();
if (!m_pLast)
{
return 0;
}
TItem* pRet = m_pLast;
m_pLast = m_pLast->Prev();
if (m_pLast) //if any element exists
{
m_pLast->Next(0); //set prev ptr of this element to 0
}
else
{
m_pFirst = 0; //set ptr to last element to 0 if ptr to first is zero as well
}
Validate();
m_Count--;
return pRet;
}
ILINE void AddFirst(TItem* pItem)
{
CPA_ASSERT(pItem); //ERROR AddFirst got 0 pointer
Validate();
pItem->Prev(0);
pItem->Next(m_pFirst);
if (!m_pFirst)
{
m_pLast = pItem;
}
else
{
m_pFirst->Prev(pItem);
}
m_pFirst = pItem;
m_Count++;
Validate();
}
ILINE void AddLast(TItem* pItem)
{
CPA_ASSERT(pItem); //ERROR AddLast got 0 pointer
Validate();
pItem->Prev(m_pLast);
pItem->Next(0);
if (!m_pLast)
{
m_pFirst = pItem;
}
else
{
m_pLast->Next(pItem);
}
m_pLast = pItem;
m_Count++;
Validate();
}
ILINE void AddBefore(TItem* pItem, TItem* pItemSuccessor)
{
CPA_ASSERT(pItem);
CPA_ASSERT(pItemSuccessor);
Validate();
pItem->Next(pItemSuccessor);
pItem->Prev(pItemSuccessor->Prev());
pItemSuccessor->Prev(pItem);
if (pItemSuccessor == m_pFirst)
{
m_pFirst = pItem;
}
else
{
pItem->Prev()->Next(pItem);
}
m_Count++;
Validate();
}
ILINE void AddBehind(TItem* pItem, TItem* pItemPredecessor)
{
CPA_ASSERT(pItem);
CPA_ASSERT(pItemPredecessor);
Validate();
pItem->Next(pItemPredecessor->Next());
pItem->Prev(pItemPredecessor);
pItemPredecessor->Next(pItem);
if (pItemPredecessor == m_pLast)
{
m_pLast = pItem;
}
else
{
pItem->Next()->Prev(pItem);
}
m_Count++;
Validate();
}
ILINE void Remove(TItem* pItem)
{
CPA_ASSERT(pItem); //ERROR releasing empty item
if (pItem == m_pFirst)
{
PopFirst();
return;
}
if (pItem == m_pLast)
{
PopLast();
return;
}
Validate(pItem);
pItem->Prev()->Next(pItem->Next());
pItem->Next()->Prev(pItem->Prev());
m_Count--;
Validate();
}
//debug
ILINE void Validate(TItem* pReferenceItem = 0)
{
if (!VALIDATE)
{
return;
}
//one-sided empty?
CPA_ASSERT((!First() && !Last()) || (First() && Last())); //ERROR validating item-list, just one end is 0
// endles linking?
TItem* pPrev = 0;
TItem* pItem = First();
while (pItem)
{
if (pReferenceItem == pItem)
{
pReferenceItem = 0;
}
CPA_ASSERT(pPrev == pItem->Prev()); //ERROR validating item-list, endless linking NULL
pPrev = pItem;
pItem = pItem->Next();
}
CPA_ASSERT(pPrev == Last()); //ERROR validating item-list, broken list, does not end at specified Last item
CPA_ASSERT(!pReferenceItem); //ERROR reference item not found in the item-list
}
ILINE size_t Count() const{return m_Count; }
};
}
#endif // CRYINCLUDE_CRYPOOL_LIST_H
+70
View File
@@ -0,0 +1,70 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYPOOL_MEMORY_H
#define CRYINCLUDE_CRYPOOL_MEMORY_H
#pragma once
namespace NCryPoolAlloc
{
class CMemoryDynamic
{
size_t m_Size;
uint8* m_pData;
protected:
ILINE CMemoryDynamic()
: m_Size(0)
, m_pData(0){}
public:
ILINE void InitMem(const size_t S, uint8* pData)
{
m_Size = S;
m_pData = pData;
CPA_ASSERT(S);
CPA_ASSERT(pData);
}
ILINE size_t MemSize() const{return m_Size; }
ILINE uint8* Data(){return m_pData; }
ILINE const uint8* Data() const{return m_pData; }
};
template<size_t TSize>
class CMemoryStatic
{
uint8 m_Data[TSize];
protected:
ILINE CMemoryStatic()
{
}
public:
ILINE void InitMem(const size_t S, uint8* pData)
{
}
ILINE size_t MemSize() const{return TSize; }
ILINE uint8* Data(){return m_Data; }
ILINE const uint8* Data() const{return m_Data; }
};
}
#endif // CRYINCLUDE_CRYPOOL_MEMORY_H
@@ -0,0 +1,55 @@
/*
* 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.
#pragma once
#if defined(POOLALLOCTESTSUIT)
//cheat just for unit testing on windows
#include "BaseTypes.h"
#define ILINE inline
#endif
// Traits
#if defined(AZ_RESTRICTED_PLATFORM)
#include AZ_RESTRICTED_FILE(CryPool/PoolAlloc_h)
#elif defined(APPLE) || defined(LINUX)
#define POOLALLOC_H_TRAIT_USE_MEMALIGN 1
#endif
#if POOLALLOC_H_TRAIT_USE_MEMALIGN
#define CPA_ALLOC memalign
#define CPA_FREE free
#else
#define CPA_ALLOC _aligned_malloc
#define CPA_FREE _aligned_free
#endif
#define CPA_ASSERT assert
#define CPA_ASSERT_STATIC(X) {uint8 assertdata[(X) ? 0 : 1]; }
#define CPA_BREAK __debugbreak()
#include "List.h"
#include "Memory.h"
#include "Container.h"
#include "Allocator.h"
#include "Defrag.h"
#include "STLWrapper.h"
#include "Inspector.h"
#include "Fallback.h"
#if !defined(POOLALLOCTESTSUIT)
#include "ThreadSafe.h"
#endif
#undef CPA_ASSERT
#undef CPA_ASSERT_STATIC
#undef CPA_BREAK
@@ -0,0 +1,148 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYPOOL_STLWRAPPER_H
#define CRYINCLUDE_CRYPOOL_STLWRAPPER_H
#pragma once
namespace NCryPoolAlloc
{
//namespace CSTLPoolAllocWrapperHelper
//{
// inline void destruct(char *) {}
// inline void destruct(wchar_t*) {}
// template <typename T>
// inline void destruct(T *t) {t->~T();}
//}
//template <size_t S, class L, size_t A, typename T>
//struct CSTLPoolAllocWrapperStatic
//{
// static PoolAllocator<S, L, A> * allocator;
//};
//template <class T, class L, size_t A>
//struct CSTLPoolAllocWrapperKungFu : public CSTLPoolAllocWrapperStatic<sizeof(T),L,A,T>
//{
//};
template <class T, class TCont>
class CSTLPoolAllocWrapper
{
private:
static TCont* m_pContainer;
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
static TCont* Container(){return m_pContainer; }
static void Container(TCont* pContainer){m_pContainer = pContainer; }
template <class U>
struct rebind
{
typedef CSTLPoolAllocWrapper<T, TCont> other;
};
CSTLPoolAllocWrapper() throw()
{
}
CSTLPoolAllocWrapper(const CSTLPoolAllocWrapper&) throw()
{
}
template <class TTemp, class TTempCont>
CSTLPoolAllocWrapper(const CSTLPoolAllocWrapper<TTemp, TTempCont>&) throw()
{
}
~CSTLPoolAllocWrapper() throw()
{
}
pointer address(reference x) const
{
return &x;
}
const_pointer address(const_reference x) const
{
return &x;
}
pointer allocate(size_type n = 1, const_pointer hint = 0)
{
TCont* pContainer = Container();
uint8* pData = pContainer->TCont::template Allocate<uint8*>(n * sizeof(T), sizeof(T));
return pContainer->TCont::template Resolve<pointer>(pData);
// return Container()?Container()->Allocate<void*>(n*sizeof(T),sizeof(T)):0
}
void deallocate(pointer p, size_type n = 1)
{
if (Container())
{
Container()->Free(p);
}
}
size_type max_size() const throw()
{
return Container() ? Container()->MemSize() : 0;
}
void construct(pointer p, const T& val)
{
new(static_cast<void*>(p))T(val);
}
void construct(pointer p)
{
new(static_cast<void*>(p))T();
}
void destroy(pointer p)
{
p->~T();
}
pointer new_pointer()
{
return new(allocate())T();
}
pointer new_pointer(const T& val)
{
return new(allocate())T(val);
}
void delete_pointer(pointer p)
{
p->~T();
deallocate(p);
}
bool operator==(const CSTLPoolAllocWrapper&) {return true; }
bool operator!=(const CSTLPoolAllocWrapper&) {return false; }
};
}
#endif // CRYINCLUDE_CRYPOOL_STLWRAPPER_H
@@ -0,0 +1,58 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYPOOL_THREADSAFE_H
#define CRYINCLUDE_CRYPOOL_THREADSAFE_H
#pragma once
#include <CryThread.h>
namespace NCryPoolAlloc
{
template<class TAllocator>
class CThreadSafe
: public TAllocator
{
CryCriticalSection m_Mutex;
public:
template<class T>
ILINE T Allocate(size_t Size, size_t Align = 1)
{
CryAutoLock<CryCriticalSection> lock(m_Mutex);
return TAllocator::template Allocate<T>(Size, Align);
}
template<class T>
ILINE bool Free(T pData, bool ForceBoundsCheck = false)
{
CryAutoLock<CryCriticalSection> lock(m_Mutex);
return TAllocator::Free(pData, ForceBoundsCheck);
}
template<class T>
ILINE bool Resize(T** pData, size_t Size, size_t Alignment)
{
CryAutoLock<CryCriticalSection> lock(m_Mutex);
return TAllocator::Resize(pData, Size, Alignment);
}
};
}
#endif // CRYINCLUDE_CRYPOOL_THREADSAFE_H
+287
View File
@@ -0,0 +1,287 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYPOOL_EXAMPLE_H
#define CRYINCLUDE_CRYPOOL_EXAMPLE_H
#pragma once
//The documentation is split up into 3 main parts, so strg+f for
// -Theory
// -Building blocks
// -Usage
// -FAQ
// -Realloc/Resize
/////////////////////////////////////////////////////////////////////////
// -Theory
/////////////////////////////////////////////////////////////////////////
//this includes the 3 major parts of the allocate suite
//1. the memory location templates
//2. container types
//3. some allocator version
//addtional you get
//4. a simple stack based defragmentation template
//5. helper
//1. memory location templates
// There are two types of them, static and dynamic
//1.1 CMemoryStatic<size> allows you do define on compile time what size
// it should have, suitable for pool you know that they won't grow or
// shrink
//1.2 CMemoryDynamic, this one has no template parameter, it has just one
// indirection via ptr to the memory location and size, that you will
// set during initialization.
//2. Container types
// We have also two container types, one so called "In Place"
// and one "Referenced".
//2.1 "In Place" means that a header is placed above every allocation,
// this is the usual way most allocators work.
//2.2 "Referenced", has an extra pool of headers that point to the actual
// memory. This is suitable for
// - external memory locations that are not directly accessable by the
// cpu. E.g. pools on disk, networks, rsx memory..
// - defragmentation, because you don't save a ptr to the real memory
// location, just a "handle" of the referencing item.
// - big alignments, having 4kb of alignment would waste also
// - 4kb for ever "In Place" header, you might not want that.
//3. Allocators
// This time we have 3 of them, "BestFit", "WorstFit" and "FirstFit"
//3.1 FirstFit just seeks for any location big enought to fit your
// requested size of memory. Internally it also saves the last used
// free memory area to speed up allocations.
// Use this also if you have just one particular allocation size.
//3.2 WorstFit, although it might sound illogical, WorstFit can reduce
// memory fragmentation in a cases with very random allocation sizes,
// because it gives smaller free blocks the chance to concatenate to
// bigger free blocks again while filling up those previously
// generated big blocks. The bad side is that it takes quite some time
// to find the biggest block as this needs to be done every time you
// allocate, so use this just when having a low amount of allocations
// or you're really desperately looking for mem.
//3.3 BestFit, it's best used if you don't have just one allocation size,
// but still very few varying sizes. Previously released blocks of
// the currently allocating sizes will be seeked and reused, this
// strongly helps to reduce fragmentation. While this might be slow
// in some cases, it can save you from doing any defragmentation.
//4. Defragmentation
// At the moment just one defragmentation algorithm is implemented:
// "Stack defragmentator"
// If you don't want some block to be moved, "Lock" it using your
// memory handle.
//4.1 Stack based
// To reduce fragmentation, holes are filled up with the next used,
// memory area. This defragmentation sheme is useful when you have
// some long living locations as well as very short living ones.
// At some point all long live memory will end up at the bottom of
// the stack, while leaving empty memory areas at the top for short
// living allocations.
//5. Helper
// this should be filled up with some handy helper tools for this
// pool suite.
// The first tool is a wrapper for the usage with stl
//5.1 Wrapper for STL
// As you know, you can pass your own allocator as the last
// parameter of stl containers, with this helper you can use a pool
// created with this suite and wrap it for the stl.
/////////////////////////////////////////////////////////////////////////
// -Building blocks
/////////////////////////////////////////////////////////////////////////
//That's the theory, so how does it work?
//It's pretty simple, you compose the pool of your dreams by cascading
//templates.
//Lets start with an exmaple
//Per level you want to allocate a fixed amount of memory for your
//textures.
CMemoryDynamic
//- They are placed in some memory you can access directly with the cpu:
CInPlace
//- and you don't want to defragmentate, so you prefer an allocation
// sheme that reduces fragmentation.
CBestFit
//now you combine them
typedef CBestFit<CInPlace<CMemoryDynamic>, CListItemInPlace> TMyOwnPool;
//Yes, it's that simple.
//ok, ok, texture memory is usually nothing you want to access directly
//with your cpu, so let's create a referencing pool. Therefor you need
//to also specify how many nodes that can reference your pool will have.
//We won't have more than 4000 textures, so let's start with
{
enum TEXTURE_NODE_COUNT = 4096
};
//and now our referencing pool
typedef CBestFit < CReferenced<CMemoryDynamic, TEXTURE_NODE_COUNT> TMyOwnPool;
//But yeah, you're right, texture memory has also a fixed size, lets
//assume it's 128MB.
{
enum TEXTURE_MEMORY_SIZE = 128 * 1024 * 1024
};
//and our fixed sized memory pool
typedef CBestFit < CReferenced<CMemoryStatic<TEXTURE_MEMORY_SIZE>, TEXTURE_NODE_COUNT> TMyOwnPool;
//ok, but you don't trust the best fit allocator in all cases, you prefer
//a fast one and you accept the slow down for defragmentation incase the
//allocation fails.
//So lets created a straight First Fit allocator with defragmentation:
typedef CDefragStacked < CFirstFit<CReferenced<CMemoryStatic<TEXTURE_MEMORY_SIZE>, TEXTURE_NODE_COUNT> > TMyOwnPool;
//here you see how simple you can add defragmentation, but be careful, it
//works of course just on Reference based memory containers, if you have
//Direct pointers to In Place allocation, we cannot shuffle them around.
/////////////////////////////////////////////////////////////////////////
// -Usage
/////////////////////////////////////////////////////////////////////////
//it all starts by including the meain header
#include "PoolAlloc.h"
//Define your dream allocator, preferably using a typedef (or macro)
typedef CBestFit<CInPlace<CMemoryDynamic>, CListItemInPlace> TMyOwnPool;
//also typedef (or macro) your handle
typedef uint8* TMyHandle; //in case of "In Place" allocations
typedef uint32 TMyHandle; //in case of "Referenced"
//Instantiate it
TMyOwnPool g_MyMemory;
//now you need to initialize it,
g_MyMemory.InitMem(pMemoryArea, MemorySize); //in case you use "CMemoryDynamic"
g_MyMemory.InitMem(); //in case you use "CmemoryStatic,
//altough you could pass the same
//parameters, they'd be ignored.
//Use this also to flush the pool
//quickly
//now allocate
TMyHandle MemID = g_MyMemory.Allocate<TMyHandle>(Size);
//optionally alignment can be passed as 2nd parameter
TMyHandle MemID = g_MyMemory.Allocate<TMyHandle>(Size, Align);
//free it simply by calling
g_Memory.Free(MemID);
//you might want to call the beat function to defragment the memory
//on regular base
g_Memory.Beat();
//you might also want to call it just when an allocation failed to
//defragmentate the memory as good as possible
if (!(MemID = g_Memoery.Allocate<TMyHandle>(Size)))
{
while (g_Memory.Beat())
{
;
}
MemID = g_Memoery.Allocate<TMyHandle>(Size);
}
//To acquire the pointer to your data, you need to resolve the handle
MyObject* pObject = g_Memory.Resolve<MyOBject*>(MemID);
/////////////////////////////////////////////////////////////////////////
// -Realloc/Resize
/////////////////////////////////////////////////////////////////////////
// The Containers provide a "resize" function. This one does nothing else
// than the name suggest, it is freeing some memory at the end of your
// allocation or, if free memory is available, allocates some memory to
// the end of your buffer. But it may also fail, if not enough memory
// available to allocate.
// "Realloc" on the other side requires an extra template that you wrap
// around your existing one like:
typedef CReallocator<TMyOwnPool> TMyOwnPoolWithReallocation;
// This one will first try to use resize, but in case it fails, it will
// allocate a seperate memory area, copy the data and free the old one.
//
// But this may fail as well, therefor the result is not a pointer to the
// allocation, but true/false.
// There for you need to pass a pointer to your pointer to the memory area
// or handle you deal with.
Handle = rMemory.Allocate<TPtr>(10, 1);
if (!rMemory.Reallocate<TPtr>(&Handles, 11, 1))
{
//handle realloc failure
}
/////////////////////////////////////////////////////////////////////////
// -FAQ
/////////////////////////////////////////////////////////////////////////
//"DO I HAVE TO ALWAYS RESOLVE?"
//if you use "In Place" memory, not at all, all resolve does is to
//cast your handle to your object ptr and returns it.
//if you use "Referenced" memory and you don't defragmentate, you
//can do it once and keep the ptr, but you also need to keep the
//handle to free the memory later on.
//"any reason I should resolve?"
//Yes, first of all, it makes it very easy to switch between various
//pool configuration for testing, you simply change some params of
//your typedef (or macro) and it should work out of the box.
//second, for defragmentation it's the only way to go and for future
//things it might be needed as well
//"but isn't resolving just overhead?"
//in case of "In Place": no, the resolve function just returns the
//pointer, casting to your wanted type
//in case of "Referenced": it cost you one indirection.
//"How do I flush the whole pool without freeing all items?"
g_Memory.InitMem()
//yes, you can call "InitMem" once again, you need to pass the mem
//ptr and size if using CMemoryDynamic e.g.
g_Memory.Init(g_Memory.Size(), g_Memory.Data());
//"How do I lock the allocated memory to avoid any reallocation"
g_Memory.Item(ptr)->Lock();
//"How do I get the size of a memory block?"
g_Memory.Item(ptr)->MemSize();
//"Is there any example?"
//for a real life example check PAUnitTest.cpp used to validate all
//functions of this pool.
//bug reports? questions? support?
//just ask me :) (michael kopietz)
#endif // CRYINCLUDE_CRYPOOL_EXAMPLE_H
+100
View File
@@ -0,0 +1,100 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYCOMMON_CRYPTRARRAY_H
#define CRYINCLUDE_CRYCOMMON_CRYPTRARRAY_H
#pragma once
#include "CryArray.h"
#include "CrySizer.h"
//---------------------------------------------------------------------------
template<class T, class P = T*>
struct PtrArray
: DynArray<P>
{
typedef DynArray<P> super;
// Overrides.
typedef T value_type;
ILINE ~PtrArray(){}
inline T& operator [](int i) const
{ return *super::operator[](i); }
// Iterators.
struct iterator
{
iterator(P* p)
: _ptr(p)
{}
operator P* () const
{
return _ptr;
}
void operator++()
{ _ptr++; }
void operator--()
{ _ptr--; }
T& operator*() const
{ assert(_ptr); return **_ptr; }
T* operator->() const
{ assert(_ptr); return *_ptr; }
protected:
P* _ptr;
};
struct const_iterator
{
const_iterator(const P* p)
: _ptr(p)
{}
operator const P* () const
{
return _ptr;
}
void operator++()
{ _ptr++; }
void operator--()
{ _ptr--; }
T& operator*() const
{ assert(_ptr); return **_ptr; }
T* operator->() const
{ assert(_ptr); return *_ptr; }
protected:
const P* _ptr;
};
void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(this->begin(), this->get_alloc_size());
for (int i = 0; i < this->size(); ++i)
{
pSizer->AddObject(this->super::operator [](i));
}
}
};
//---------------------------------------------------------------------------
template<class T>
struct SmartPtrArray
: PtrArray< T, _smart_ptr<T> >
{
};
#endif // CRYINCLUDE_CRYCOMMON_CRYPTRARRAY_H
@@ -0,0 +1,168 @@
/*
* 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.
#pragma once
#include <algorithm> // std::swap()
#include <limits> // std::numeric_limits
#include <type_traits> // std::make_unsigned
#include "BaseTypes.h" // uint32, uint64
#include "CompileTimeAssert.h"
#include "Cry_Vector2.h"
#include "Cry_Vector3.h"
#include "Cry_Vector4.h"
namespace CryRandom_Internal
{
template <class R, class T, size_t size>
struct BoundedRandomUint
{
COMPILE_TIME_ASSERT(std::numeric_limits<T>::is_integer);
COMPILE_TIME_ASSERT(!std::numeric_limits<T>::is_signed);
COMPILE_TIME_ASSERT(sizeof(T) == size);
COMPILE_TIME_ASSERT(sizeof(T) <= sizeof(uint32));
inline static T Get(R& randomGenerator, const T maxValue)
{
const uint32 r = randomGenerator.GenerateUint32();
// Note that the computation below is biased. An alternative computation
// (also biased): uint32((uint64)r * ((uint64)maxValue + 1)) >> 32)
return (T)((uint64)r % ((uint64)maxValue + 1));
}
};
template <class R, class T>
struct BoundedRandomUint<R, T, 8>
{
COMPILE_TIME_ASSERT(std::numeric_limits<T>::is_integer);
COMPILE_TIME_ASSERT(!std::numeric_limits<T>::is_signed);
COMPILE_TIME_ASSERT(sizeof(T) == sizeof(uint64));
inline static T Get(R& randomGenerator, const T maxValue)
{
const uint64 r = randomGenerator.GenerateUint64();
if (maxValue >= (std::numeric_limits<uint64>::max)())
{
return r;
}
// Note that the computation below is biased.
return (T)(r % ((uint64)maxValue + 1));
}
};
//////////////////////////////////////////////////////////////////////////
template <class R, class T, bool bInteger = std::numeric_limits<T>::is_integer>
struct BoundedRandom;
template <class R, class T>
struct BoundedRandom<R, T, true>
{
COMPILE_TIME_ASSERT(std::numeric_limits<T>::is_integer);
typedef typename std::make_unsigned<T>::type UT;
COMPILE_TIME_ASSERT(sizeof(T) == sizeof(UT));
COMPILE_TIME_ASSERT(std::numeric_limits<UT>::is_integer);
COMPILE_TIME_ASSERT(!std::numeric_limits<UT>::is_signed);
inline static T Get(R& randomGenerator, T minValue, T maxValue)
{
if (minValue > maxValue)
{
std::swap(minValue, maxValue);
}
return (T)((UT)minValue + (UT)BoundedRandomUint<R, UT, sizeof(UT)>::Get(randomGenerator, (UT)(maxValue - minValue)));
}
};
template <class R, class T>
struct BoundedRandom<R, T, false>
{
COMPILE_TIME_ASSERT(!std::numeric_limits<T>::is_integer);
inline static T Get(R& randomGenerator, const T minValue, const T maxValue)
{
return minValue + (maxValue - minValue) * randomGenerator.GenerateFloat();
}
};
//////////////////////////////////////////////////////////////////////////
template <class R, class VT, class T = typename VT::value_type, size_t componentCount = VT::component_count>
struct BoundedRandomComponentwise;
template <class R, class VT, class T>
struct BoundedRandomComponentwise<R, VT, T, 2>
{
inline static VT Get(R& randomGenerator, const VT& minValue, const VT& maxValue)
{
const T x = BoundedRandom<R, T>::Get(randomGenerator, minValue.x, maxValue.x);
const T y = BoundedRandom<R, T>::Get(randomGenerator, minValue.y, maxValue.y);
return VT(x, y);
}
};
template <class R, class VT, class T>
struct BoundedRandomComponentwise<R, VT, T, 3>
{
inline static VT Get(R& randomGenerator, const VT& minValue, const VT& maxValue)
{
const T x = BoundedRandom<R, T>::Get(randomGenerator, minValue.x, maxValue.x);
const T y = BoundedRandom<R, T>::Get(randomGenerator, minValue.y, maxValue.y);
const T z = BoundedRandom<R, T>::Get(randomGenerator, minValue.z, maxValue.z);
return VT(x, y, z);
}
};
template <class R, class VT, class T>
struct BoundedRandomComponentwise<R, VT, T, 4>
{
inline static VT Get(R& randomGenerator, const VT& minValue, const VT& maxValue)
{
const T x = BoundedRandom<R, T>::Get(randomGenerator, minValue.x, maxValue.x);
const T y = BoundedRandom<R, T>::Get(randomGenerator, minValue.y, maxValue.y);
const T z = BoundedRandom<R, T>::Get(randomGenerator, minValue.z, maxValue.z);
const T w = BoundedRandom<R, T>::Get(randomGenerator, minValue.w, maxValue.w);
return VT(x, y, z, w);
}
};
//////////////////////////////////////////////////////////////////////////
template <class R, class VT>
inline VT GetRandomUnitVector(R& randomGenerator)
{
typedef typename VT::value_type T;
COMPILE_TIME_ASSERT(!std::numeric_limits<T>::is_integer);
VT res;
T lenSquared;
do
{
res = BoundedRandomComponentwise<R, VT>::Get(randomGenerator, VT(-1), VT(1));
lenSquared = res.GetLengthSquared();
} while (lenSquared > 1);
if (lenSquared >= (std::numeric_limits<T>::min)())
{
return res * isqrt_tpl(lenSquared);
}
res = VT(ZERO);
res.x = 1;
return res;
}
} // namespace CryRandom_Internal
// eof
+619
View File
@@ -0,0 +1,619 @@
/*
* 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 : Declaration and definition of the CrySizer class, which is used to
// calculate the memory usage by the subsystems and components, to help
// the artists keep the memory budged low.
#ifndef CRYINCLUDE_CRYCOMMON_CRYSIZER_H
#define CRYINCLUDE_CRYCOMMON_CRYSIZER_H
#pragma once
//////////////////////////////////////////////////////////////////////////
// common containers for overloads
#include <list>
#include "Cry_Math.h"
#include <StlUtils.h>
#include <Tarray.h>
#include <CryPodArray.h>
#include <Cry_Vector3.h>
#include <Cry_Quat.h>
#include <Cry_Color.h>
#include <CryArray2d.h>
#include <smartptr.h>
// forward declarations for overloads
struct AABB;
struct SVF_P3F;
struct SVF_P3F_C4B_T2F;
struct SVF_P3F_C4B_T2S;
struct SVF_P3S_C4B_T2S;
struct SPipTangents;
#ifdef WIN64
#include <string.h> // workaround for Amd64 compiler
#endif
#include <IResourceCollector.h> // <> required for Interfuscator. IResourceCollector
namespace AZ
{
class Vector3;
}
// flags applicable to the ICrySizer (retrieved via getFlags() method)
//
enum ICrySizerFlagsEnum
{
// if this flag is set, during getSize(), the subsystem must count all the objects
// it uses in the other subsystems also
CSF_RecurseSubsystems = 1 << 0,
CSF_Reserved1 = 1 << 1,
CSF_Reserved2 = 1 << 2
};
//////////////////////////////////////////////////////////////////////////
// Helper functions to calculate size of the std containers.
//////////////////////////////////////////////////////////////////////////
namespace stl
{
template <class Map>
inline size_t size_of_map(const Map& m)
{
if (!m.empty())
{
return m.size() * sizeof(typename Map::value_type) + m.size() * sizeof(MapLikeStruct);
}
return 0;
}
template <class Map>
inline size_t size_of_set(const Map& m)
{
if (!m.empty())
{
return m.size() * sizeof(typename Map::value_type) + m.size() * sizeof(MapLikeStruct);
}
return 0;
}
template <class List>
inline size_t size_of_list(const List& c)
{
if (!c.empty())
{
return c.size() * sizeof(typename List::value_type) + c.size() * sizeof(void*) * 2; // sizeof stored type + 2 pointers prev,next
}
return 0;
}
template <class Deque>
inline size_t size_of_deque(const Deque& c)
{
if (!c.empty())
{
return c.size() * sizeof(typename Deque::value_type);
}
return 0;
}
};
//////////////////////////////////////////////////////////////////////////
// interface ICrySizer
// USAGE
// An instance of this class is passed down to each and every component in the system.
// Every component it's passed to optionally pushes its name on top of the
// component name stack (thus ensuring that all the components calculated down
// the tree will be assigned the correct subsystem/component name)
// Every component must Add its size with one of the Add* functions, and Add the
// size of all its subcomponents recursively
// In order to push the component/system name on the name stack, the clients must
// use the SIZER_COMPONENT_NAME macro or CrySizerComponentNameHelper class:
//
// void X::getSize (ICrySizer* pSizer)
// {
// SIZER_COMPONENT_NAME(pSizer, X);
// if (!pSizer->Add (this))
// return;
// pSizer->Add (m_arrMySimpleArray);
// pSizer->Add (m_setMySimpleSet);
// m_pSubobject->getSize (pSizer);
// }
//
// The Add* functions return bool. If they return true, then the object has been added
// to the set for the first time, and you should go on recursively adding all its children.
// If it returns false, then you can spare time and rather not go on into recursion;
// however it doesn't reflect on the results: an object that's added more than once is
// counted only once.
//
// WARNING:
// If you have an array (pointer), you should Add its size with addArray
class ICrySizer
{
public:
virtual ~ICrySizer(){}
// this class is used to push/pop the name to/from the stack automatically
// (to exclude stack overruns or underruns at runtime)
friend class CrySizerComponentNameHelper;
virtual void Release() = 0;
// Return total calculated size.
virtual size_t GetTotalSize() = 0;
// Return total objects added.
virtual size_t GetObjectCount() = 0;
// Resets the counting.
virtual void Reset() = 0;
virtual void End() = 0;
// adds an object identified by the unique pointer (it needs not be
// the actual object position in the memory, though it would be nice,
// but it must be unique throughout the system and unchanging for this object)
// nCount parameter is only used for counting number of objects, it doesnt affect the size of the object.
// RETURNS: true if the object has actually been added (for the first time)
// and calculated
virtual bool AddObject (const void* pIdentifier, size_t nSizeBytes, int nCount = 1) = 0;
template<typename Type>
bool AddObjectSize(const Type* pObj)
{
return AddObject(pObj, sizeof *pObj);
}
////////////////////////////////////////////////////////////////////////////////////////
// temp dummy function while checking in the CrySizer changes, will be removed soon
template<typename Type>
void AddObject(const Type& rObj)
{
(void)rObj;
}
template<typename Type>
void AddObject(Type* pObj)
{
if (pObj)
{
//forward to reference object to allow function overload
this->AddObject(*pObj);
}
}
// overloads for smart_ptr and other common objects
template<typename T>
void AddObject(const _smart_ptr<T>& rObj) { this->AddObject(rObj.get()); }
template<typename T>
void AddObject(const AZStd::shared_ptr<T>& rObj) { this->AddObject(rObj.get()); }
template<typename T>
void AddObject(const std::shared_ptr<T>& rObj) { this->AddObject(rObj.get()); }
template<typename T>
void AddObject(const std::unique_ptr<T>& rObj) { this->AddObject(rObj.get()); }
template<typename T, typename U>
void AddObject(const std::pair<T, U>& rPair)
{
this->AddObject(rPair.first);
this->AddObject(rPair.second);
}
template<typename T, typename U>
void AddObject(const AZStd::pair<T, U>& rPair)
{
this->AddObject(rPair.first);
this->AddObject(rPair.second);
}
void AddObject(const string& rString) {this->AddObject(rString.c_str(), rString.capacity()); }
void AddObject(const CryStringT<wchar_t>& rString) {this->AddObject(rString.c_str(), rString.capacity()); }
void AddObject(const CryFixedStringT<32>&){}
void AddObject(const wchar_t&) {}
void AddObject(const char&) {}
void AddObject(const unsigned char&) {}
void AddObject(const signed char&) {}
void AddObject(const short&) {}
void AddObject(const unsigned short&) {}
void AddObject(const int&) {}
void AddObject(const unsigned int&) {}
void AddObject(const long&) {}
void AddObject(const unsigned long&) {}
void AddObject(const float&) {}
void AddObject(const bool&) {}
void AddObject(const unsigned long long&) {}
void AddObject(const long long&) {}
void AddObject(const double&) {}
void AddObject(const Vec2&) {}
void AddObject(const Vec3&) {}
void AddObject(const Vec4&) {}
void AddObject(const Ang3&) {}
void AddObject(const Matrix34&) {}
void AddObject(const Quat&) {}
void AddObject(const QuatT&) {}
void AddObject(const QuatTS&) {}
void AddObject(const ColorF&) {}
void AddObject(const AABB&) {}
void AddObject(const SVF_P3F&) {}
void AddObject(const SVF_P3F_C4B_T2F&) {}
void AddObject(const SVF_P3F_C4B_T2S&) {}
void AddObject(const SVF_P3S_C4B_T2S&) {}
void AddObject(const SPipTangents&) {}
void AddObject([[maybe_unused]] const AZ::Vector3& rObj) {}
void AddObject(void*) {}
template<typename T>
void AddObject(const Array2d<T>& array2d)
{
this->AddObject(array2d.m_pData, array2d.GetDataSize());
}
// overloads for container, will automaticly traverse the content
template<typename T, typename Alloc>
void AddObject(const std::list<T, Alloc>& rList)
{
// dummy struct to get correct element size
struct Dummy
{
void* a;
void* b;
T t;
};
for (typename std::list<T, Alloc>::const_iterator it = rList.begin(); it != rList.end(); ++it)
{
if (this->AddObject(&(*it), sizeof(Dummy)))
{
this->AddObject(*it);
}
}
}
template<typename K, typename T, typename Comp, typename Equal, typename Alloc>
void AddObject([[maybe_unused]] const AZStd::unordered_map<K, T, Comp, Equal, Alloc>& rVector)
{
}
template<typename T, typename Alloc>
void AddObject(const std::vector<T, Alloc>& rVector)
{
if (rVector.empty())
{
this->AddObject(&rVector, rVector.capacity() * sizeof(T));
return;
}
if (!this->AddObject(&rVector[0], rVector.capacity() * sizeof(T)))
{
return;
}
for (typename std::vector<T, Alloc>::const_iterator it = rVector.begin(); it != rVector.end(); ++it)
{
this->AddObject(*it);
}
}
template<typename T, typename Alloc>
void AddObject(const std::deque<T, Alloc>& rVector)
{
for (typename std::deque<T, Alloc>::const_iterator it = rVector.begin(); it != rVector.end(); ++it)
{
if (this->AddObject(&(*it), sizeof(T)))
{
this->AddObject(*it);
}
}
}
template<typename T, typename I, typename S>
void AddObject(const DynArray<T, I, S>& rVector)
{
if (rVector.empty())
{
this->AddObject(rVector.begin(), rVector.get_alloc_size());
return;
}
if (!this->AddObject(rVector.begin(), rVector.get_alloc_size()))
{
return;
}
for (typename DynArray<T, I, S>::const_iterator it = rVector.begin(); it != rVector.end(); ++it)
{
this->AddObject(*it);
}
}
template<typename T>
void AddObject(const TArray<T>& rVector)
{
if (!this->AddObject(rVector.begin(), rVector.capacity() * sizeof(T)))
{
return;
}
for (int i = 0, end = rVector.size(); i < end; ++i)
{
this->AddObject(rVector[i]);
}
}
template<typename T>
void AddObject(const PodArray<T>& rVector)
{
if (!this->AddObject(rVector.begin(), rVector.capacity() * sizeof(T)))
{
return;
}
for (typename PodArray<T>::const_iterator it = rVector.begin(); it != rVector.end(); ++it)
{
this->AddObject(*it);
}
}
template<typename K, typename T, typename Comp, typename Alloc>
void AddObject(const std::map<K, T, Comp, Alloc>& rVector)
{
// dummy struct to get correct element size
struct Dummy
{
void* a;
void* b;
void* c;
void* d;
K k;
T t;
};
for (typename std::map<K, T, Comp, Alloc>::const_iterator it = rVector.begin(); it != rVector.end(); ++it)
{
if (this->AddObject(&(*it), sizeof(Dummy)))
{
this->AddObject(it->first);
this->AddObject(it->second);
}
}
}
template<typename T, typename Comp, typename Alloc>
void AddObject(const std::set<T, Comp, Alloc>& rVector)
{
// dummy struct to get correct element size
struct Dummy
{
void* a;
void* b;
void* c;
void* d;
T t;
};
for (typename std::set<T, Comp, Alloc>::const_iterator it = rVector.begin(); it != rVector.end(); ++it)
{
if (this->AddObject(&(*it), sizeof(Dummy)))
{
this->AddObject(*it);
}
}
}
template <typename TKey, typename TValue, typename TPredicate, typename TAlloc>
void AddObject (const std::multimap<TKey, TValue, TPredicate, TAlloc>& rContainer)
{
AddContainer(rContainer);
}
////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
bool Add (const T* pId, size_t num)
{
return AddObject(pId, num * sizeof(T));
}
template <class T>
bool Add (const T& rObject)
{
return AddObject (&rObject, sizeof(T));
}
// used to collect the assets needed for streaming and to gather statistics
// always returns a valid reference
virtual IResourceCollector* GetResourceCollector() = 0;
virtual void SetResourceCollector(IResourceCollector* pColl) = 0;
bool Add (const char* szText)
{
return AddObject(szText, strlen(szText) + 1);
}
template <class StringCls>
bool AddString (const StringCls& strText)
{
if (!strText.empty())
{
return AddObject (strText.c_str(), strText.size());
}
else
{
return false;
}
}
#ifdef _XSTRING_
template <class Elem, class Traits, class Allocator>
bool Add (const std::basic_string<Elem, Traits, Allocator>& strText)
{
AddString (strText);
return true;
}
#endif
#ifndef NOT_USE_CRY_STRING
bool Add (const string& strText)
{
AddString(strText);
return true;
}
#endif
// Template helper function to add generic stl container
template <typename Container>
bool AddContainer (const Container& rContainer)
{
if (rContainer.capacity())
{
return AddObject (&rContainer, rContainer.capacity() * sizeof(typename Container::value_type));
}
return false;
}
template <typename Container>
bool AddHashMap(const Container& rContainer)
{
if (!rContainer.empty())
{
return AddObject (&(*rContainer.begin()), rContainer.size() * sizeof(typename Container::value_type));
}
return false;
}
// Specialization of the AddContainer for the std::list
template <typename Type, typename TAlloc>
bool AddContainer (const std::list<Type, TAlloc>& rContainer)
{
if (!rContainer.empty())
{
return AddObject(&(*rContainer.begin()), stl::size_of_list(rContainer));
}
return false;
}
// Specialization of the AddContainer for the std::deque
template <typename Type, typename TAlloc>
bool AddContainer (const std::deque<Type, TAlloc>& rContainer)
{
if (!rContainer.empty())
{
return AddObject(&(*rContainer.begin()), stl::size_of_deque(rContainer));
}
return false;
}
// Specialization of the AddContainer for the std::map
template <typename TKey, typename TValue, typename TPredicate, typename TAlloc>
bool AddContainer (const std::map<TKey, TValue, TPredicate, TAlloc>& rContainer)
{
if (!rContainer.empty())
{
return AddObject(&(*rContainer.begin()), stl::size_of_map(rContainer));
}
return false;
}
// Specialization of the AddContainer for the std::multimap
template <typename TKey, typename TValue, typename TPredicate, typename TAlloc>
bool AddContainer (const std::multimap<TKey, TValue, TPredicate, TAlloc>& rContainer)
{
if (!rContainer.empty())
{
return AddObject(&(*rContainer.begin()), stl::size_of_map(rContainer));
}
return false;
}
// Specialization of the AddContainer for the std::set
template <typename TKey, typename TPredicate, typename TAlloc>
bool AddContainer (const std::set<TKey, TPredicate, TAlloc>& rContainer)
{
if (!rContainer.empty())
{
return AddObject(&(*rContainer.begin()), stl::size_of_set(rContainer));
}
return false;
}
// Specialization of the AddContainer for the AZStd::unordered_map
template <typename KEY, typename TYPE, class HASH, class EQUAL, class ALLOCATOR>
bool AddContainer(const AZStd::unordered_map<KEY, TYPE, HASH, EQUAL, ALLOCATOR>& rContainer)
{
if (!rContainer.empty())
{
return AddObject(&(*rContainer.begin()), rContainer.size() * sizeof(typename AZStd::unordered_map<KEY, TYPE, HASH, EQUAL, ALLOCATOR>::value_type));
}
else
{
return false;
}
}
void Test()
{
std::map<int, float> mymap;
AddContainer(mymap);
}
// returns the flags
unsigned GetFlags() const {return m_nFlags; }
protected:
// these functions must operate on the component name stack
// they are to be only accessible from within class CrySizerComponentNameHelper
// which should be used through macro SIZER_COMPONENT_NAME
virtual void Push (const char* szComponentName) = 0;
// pushes the name that is the name of the previous component . (dot) this name
virtual void PushSubcomponent (const char* szSubcomponentName) = 0;
virtual void Pop () = 0;
unsigned m_nFlags;
};
//////////////////////////////////////////////////////////////////////////
// This is on-stack class that is only used to push/pop component names
// to/from the sizer name stack.
//
// USAGE:
//
// Create an instance of this class at the start of a function, before
// calling Add* methods of the sizer interface. Everything added in the
// function and below will be considered this component, unless
// explicitly set otherwise.
//
class CrySizerComponentNameHelper
{
public:
// pushes the component name on top of the name stack of the given sizer
CrySizerComponentNameHelper (ICrySizer* pSizer, const char* szComponentName, bool bSubcomponent)
: m_pSizer(pSizer)
{
if (bSubcomponent)
{
pSizer->PushSubcomponent (szComponentName);
}
else
{
pSizer->Push (szComponentName);
}
}
// pops the component name off top of the name stack of the sizer
~CrySizerComponentNameHelper()
{
m_pSizer->Pop();
}
protected:
ICrySizer* m_pSizer;
};
// use this to push (and automatically pop) the sizer component name at the beginning of the
// getSize() function
#define SIZER_COMPONENT_NAME(pSizerPointer, szComponentName) PREFAST_SUPPRESS_WARNING(6246) CrySizerComponentNameHelper AZ_JOIN(sizerHelper, __LINE__)(pSizerPointer, szComponentName, false)
#define SIZER_SUBCOMPONENT_NAME(pSizerPointer, szComponentName) PREFAST_SUPPRESS_WARNING(6246) CrySizerComponentNameHelper AZ_JOIN(sizerHelper, __LINE__)(pSizerPointer, szComponentName, true)
#endif // CRYINCLUDE_CRYCOMMON_CRYSIZER_H
File diff suppressed because it is too large Load Diff
+90
View File
@@ -0,0 +1,90 @@
/*
* 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.
*/
#ifndef CRYINCLUDE_CRYCOMMON_CRYSYSTEMBUS_H
#define CRYINCLUDE_CRYCOMMON_CRYSYSTEMBUS_H
#pragma once
#include <AzCore/EBus/EBus.h>
struct ISystem;
struct SSystemInitParams;
/*!
* Events from CrySystem
*/
class CrySystemEvents
: public AZ::EBusTraits
{
public:
//! ISystem has been created and is about to initialize.
virtual void OnCrySystemPreInitialize(ISystem&, const SSystemInitParams&) {}
//! ISystem and IConsole has been created but the cfg files have not been parsed
virtual void OnCrySystemCVarRegistry() {}
//! ISystem has been created and initialized.
virtual void OnCrySystemInitialized(ISystem&, const SSystemInitParams&) {}
//! In-Editor systems have been created and initialized.
virtual void OnCryEditorInitialized() {}
//! Editor has started a level export
virtual void OnCryEditorBeginLevelExport() {}
//! Editor has finished a level export
virtual void OnCryEditorEndLevelExport(bool /*success*/) {}
//! ISystem is about to begin shutting down
virtual void OnCrySystemShutdown(ISystem&) {}
//! ISystem has shut down.
virtual void OnCrySystemPostShutdown() {}
//! Engine pre physics update.
virtual void OnCrySystemPrePhysicsUpdate() {}
//! Engine post physics update.
virtual void OnCrySystemPostPhysicsUpdate() {}
//! Sent when a new level is being created.
virtual void OnCryEditorBeginCreate() {}
//! Sent after a new level has been created.
virtual void OnCryEditorEndCreate() {}
//! Sent when a level is about to be loaded.
virtual void OnCryEditorBeginLoad() {}
//! Sent after a level has been loaded.
virtual void OnCryEditorEndLoad() {}
//! Sent when the document is about to close.
virtual void OnCryEditorCloseScene() {}
//! Sent when the document is closed.
virtual void OnCryEditorSceneClosed() {}
};
using CrySystemEventBus = AZ::EBus<CrySystemEvents>;
/*!
* Requests to CrySystem
*/
class CrySystemRequests
: public AZ::EBusTraits
{
public:
//! Get CrySystem
virtual ISystem* GetCrySystem() = 0;
};
using CrySystemRequestBus = AZ::EBus<CrySystemRequests>;
#endif // CRYINCLUDE_CRYCOMMON_CRYSYSTEMBUS_H
+828
View File
@@ -0,0 +1,828 @@
/*
* 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 : Public include file for the multi-threading API.
#pragma once
// Include basic multithread primitives.
#include "MultiThread.h"
#include "BitFiddling.h"
#include <AzCore/std/string/string.h>
//////////////////////////////////////////////////////////////////////////
// Lock types:
//
// CRYLOCK_FAST
// A fast potentially (non-recursive) mutex.
// CRYLOCK_RECURSIVE
// A recursive mutex.
//////////////////////////////////////////////////////////////////////////
enum CryLockType
{
CRYLOCK_FAST = 1,
CRYLOCK_RECURSIVE = 2,
};
#define CRYLOCK_HAVE_FASTLOCK 1
void CryThreadSetName(threadID nThreadId, const char* sThreadName);
const char* CryThreadGetName(threadID nThreadId);
/////////////////////////////////////////////////////////////////////////////
//
// Primitive locks and conditions.
//
// Primitive locks are represented by instance of class CryLockT<Type>
//
//
template<CryLockType Type>
class CryLockT
{
/* Unsupported lock type. */
};
//////////////////////////////////////////////////////////////////////////
// Typedefs.
//////////////////////////////////////////////////////////////////////////
typedef CryLockT<CRYLOCK_RECURSIVE> CryCriticalSection;
typedef CryLockT<CRYLOCK_FAST> CryCriticalSectionNonRecursive;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// CryAutoCriticalSection implements a helper class to automatically
// lock critical section in constructor and release on destructor.
//
//////////////////////////////////////////////////////////////////////////
template<class LockClass>
class CryAutoLock
{
private:
LockClass* m_pLock;
CryAutoLock();
CryAutoLock(const CryAutoLock<LockClass>&);
CryAutoLock<LockClass>& operator = (const CryAutoLock<LockClass>&);
public:
CryAutoLock(LockClass& Lock)
: m_pLock(&Lock) { m_pLock->Lock(); }
CryAutoLock(const LockClass& Lock)
: m_pLock(const_cast<LockClass*>(&Lock)) { m_pLock->Lock(); }
~CryAutoLock() { m_pLock->Unlock(); }
};
//////////////////////////////////////////////////////////////////////////
//
// CryOptionalAutoLock implements a helper class to automatically
// lock critical section (if needed) in constructor and release on destructor.
//
//////////////////////////////////////////////////////////////////////////
template<class LockClass>
class CryOptionalAutoLock
{
private:
LockClass* m_Lock;
bool m_bLockAcquired;
CryOptionalAutoLock();
CryOptionalAutoLock(const CryOptionalAutoLock<LockClass>&);
CryOptionalAutoLock<LockClass>& operator = (const CryOptionalAutoLock<LockClass>&);
public:
CryOptionalAutoLock(LockClass& Lock, bool acquireLock)
: m_Lock(&Lock)
, m_bLockAcquired(false)
{
if (acquireLock)
{
Acquire();
}
}
~CryOptionalAutoLock()
{
Release();
}
void Release()
{
if (m_bLockAcquired)
{
m_Lock->Unlock();
m_bLockAcquired = false;
}
}
void Acquire()
{
if (!m_bLockAcquired)
{
m_Lock->Lock();
m_bLockAcquired = true;
}
}
};
//////////////////////////////////////////////////////////////////////////
//
// CryAutoSet implements a helper class to automatically
// set and reset value in constructor and release on destructor.
//
//////////////////////////////////////////////////////////////////////////
template<class ValueClass>
class CryAutoSet
{
private:
ValueClass* m_pValue;
CryAutoSet();
CryAutoSet(const CryAutoSet<ValueClass>&);
CryAutoSet<ValueClass>& operator = (const CryAutoSet<ValueClass>&);
public:
CryAutoSet(ValueClass& value)
: m_pValue(&value) { *m_pValue = (ValueClass)1; }
~CryAutoSet() { *m_pValue = (ValueClass)0; }
};
//////////////////////////////////////////////////////////////////////////
//
// Auto critical section is the most commonly used type of auto lock.
//
//////////////////////////////////////////////////////////////////////////
typedef CryAutoLock<CryCriticalSection> CryAutoCriticalSection;
#define AUTO_LOCK_T(Type, lock) PREFAST_SUPPRESS_WARNING(6246); CryAutoLock<Type> __AutoLock(lock)
#define AUTO_LOCK(lock) AUTO_LOCK_T(CryCriticalSection, lock)
#define AUTO_LOCK_CS(csLock) CryAutoCriticalSection __AL__##csLock(csLock)
/////////////////////////////////////////////////////////////////////////////
//
// Threads.
// Base class for runnable objects.
//
// A runnable is an object with a Run() and a Cancel() method. The Run()
// method should perform the runnable's job. The Cancel() method may be
// called by another thread requesting early termination of the Run() method.
// The runnable may ignore the Cancel() call, the default implementation of
// Cancel() does nothing.
class CryRunnable
{
public:
virtual ~CryRunnable() { }
virtual void Run() = 0;
virtual void Cancel() { }
};
// Class holding information about a thread.
//
// A reference to the thread information can be obtained by calling GetInfo()
// on the CrySimpleThread (or derived class) instance.
//
// NOTE:
// If the code is compiled with NO_THREADINFO defined, then the GetInfo()
// method will return a reference to a static dummy instance of this
// structure. It is currently undecided if NO_THREADINFO will be defined for
// release builds!
struct CryThreadInfo
{
// The symbolic name of the thread.
//
// You may set this name directly or through the SetName() method of
// CrySimpleThread (or derived class).
AZStd::string m_Name;
// A thread identification number.
// The number is unique but architecture specific. Do not assume anything
// about that number except for being unique.
//
// This field is filled when the thread is started (i.e. before the Run()
// method or thread routine is called). It is advised that you do not
// change this number manually.
uint32 m_ID;
};
// Simple thread class.
//
// CrySimpleThread is a simple wrapper around a system thread providing
// nothing but system-level functionality of a thread. There are two typical
// ways to use a simple thread:
//
// 1. Derive from the CrySimpleThread class and provide an implementation of
// the Run() (and optionally Cancel()) methods.
// 2. Specify a runnable object when the thread is started. The default
// runnable type is CryRunnable.
//
// The Runnable class specfied as the template argument must provide Run()
// and Cancel() methods compatible with the following signatures:
//
// void Runnable::Run();
// void Runnable::Cancel();
//
// If the Runnable does not support cancellation, then the Cancel() method
// should do nothing.
//
// The same instance of CrySimpleThread may be used for multiple thread
// executions /in sequence/, i.e. it is valid to re-start the thread by
// calling Start() after the thread has been joined by calling WaitForThread().
template<class Runnable = CryRunnable>
class CrySimpleThread;
// Standard thread class.
//
// The class provides a lock (mutex) and an associated condition variable. If
// you don't need the lock, then you should used CrySimpleThread instead of
// CryThread.
template<class Runnable = CryRunnable>
class CryThread;
///////////////////////////////////////////////////////////////////////////////
// Include architecture specific code.
#if AZ_LEGACY_CRYCOMMON_TRAIT_USE_PTHREADS
#include <CryThread_pthreads.h>
#define AZ_RESTRICTED_SECTION_IMPLEMENTED
#elif defined(WIN32) || defined(WIN64)
#include <CryThread_windows.h>
#define AZ_RESTRICTED_SECTION_IMPLEMENTED
#elif defined(AZ_RESTRICTED_PLATFORM)
#include AZ_RESTRICTED_FILE(CryThread_h)
#endif
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
#else
// Put other platform specific includes here!
#include <CryThread_dummy.h>
#endif
#if !defined _CRYTHREAD_CONDLOCK_GLITCH
typedef CryLockT<CRYLOCK_RECURSIVE> CryMutex;
#endif // !_CRYTHREAD_CONDLOCK_GLITCH
// The the architecture specific code does not define a class CryRWLock, then
// a default implementation is provided here.
#if !defined _CRYTHREAD_HAVE_RWLOCK && !defined _CRYTHREAD_CONDLOCK_GLITCH
class CryRWLock
{
CryCriticalSection m_lockExclusiveAccess;
CryCriticalSection m_lockSharedAccessComplete;
CryConditionVariable m_condSharedAccessComplete;
int m_nSharedAccessCount;
int m_nCompletedSharedAccessCount;
bool m_bExclusiveAccess;
CryRWLock(const CryRWLock&);
CryRWLock& operator= (const CryRWLock&);
void AdjustSharedAccessCount()
{
m_nSharedAccessCount -= m_nCompletedSharedAccessCount;
m_nCompletedSharedAccessCount = 0;
}
public:
CryRWLock()
: m_nSharedAccessCount(0)
, m_nCompletedSharedAccessCount(0)
, m_bExclusiveAccess(false)
{ }
void RLock()
{
m_lockExclusiveAccess.Lock();
if (++m_nSharedAccessCount == INT_MAX)
{
m_lockSharedAccessComplete.Lock();
AdjustSharedAccessCount();
m_lockSharedAccessComplete.Unlock();
}
m_lockExclusiveAccess.Unlock();
}
bool TryRLock()
{
if (!m_lockExclusiveAccess.TryLock())
{
return false;
}
if (++m_nSharedAccessCount == INT_MAX)
{
m_lockSharedAccessComplete.Lock();
AdjustSharedAccessCount();
m_lockSharedAccessComplete.Unlock();
}
m_lockExclusiveAccess.Unlock();
return true;
}
void RUnlock()
{
Unlock();
}
void WLock()
{
m_lockExclusiveAccess.Lock();
m_lockSharedAccessComplete.Lock();
assert(!m_bExclusiveAccess);
AdjustSharedAccessCount();
if (m_nSharedAccessCount > 0)
{
m_nCompletedSharedAccessCount -= m_nSharedAccessCount;
do
{
m_condSharedAccessComplete.Wait(m_lockSharedAccessComplete);
}
while (m_nCompletedSharedAccessCount < 0);
m_nSharedAccessCount = 0;
}
m_bExclusiveAccess = true;
}
bool TryWLock()
{
if (!m_lockExclusiveAccess.TryLock())
{
return false;
}
if (!m_lockSharedAccessComplete.TryLock())
{
m_lockExclusiveAccess.Unlock();
return false;
}
assert(!m_bExclusiveAccess);
AdjustSharedAccessCount();
if (m_nSharedAccessCount > 0)
{
m_lockSharedAccessComplete.Unlock();
m_lockExclusiveAccess.Unlock();
return false;
}
else
{
m_bExclusiveAccess = true;
}
return true;
}
void WUnlock()
{
Unlock();
}
void Unlock()
{
if (!m_bExclusiveAccess)
{
m_lockSharedAccessComplete.Lock();
if (++m_nCompletedSharedAccessCount == 0)
{
m_condSharedAccessComplete.NotifySingle();
}
m_lockSharedAccessComplete.Unlock();
}
else
{
m_bExclusiveAccess = false;
m_lockSharedAccessComplete.Unlock();
m_lockExclusiveAccess.Unlock();
}
}
};
#endif // !defined _CRYTHREAD_HAVE_RWLOCK
// Thread class.
//
// CryThread is an extension of CrySimpleThread providing a lock (mutex) and a
// condition variable per instance.
template<class Runnable>
class CryThread
: public CrySimpleThread<Runnable>
{
CryMutex m_Lock;
CryConditionVariable m_Cond;
CryThread(const CryThread<Runnable>&);
void operator = (const CryThread<Runnable>&);
public:
CryThread() { }
void Lock() { m_Lock.Lock(); }
bool TryLock() { return m_Lock.TryLock(); }
void Unlock() { m_Lock.Unlock(); }
void Wait() { m_Cond.Wait(m_Lock); }
// Timed wait on the associated condition.
//
// The 'milliseconds' parameter specifies the relative timeout in
// milliseconds. The method returns true if a notification was received and
// false if the specified timeout expired without receiving a notification.
//
// UNIX note: the method will _not_ return if the calling thread receives a
// signal. Instead the call is re-started with the _original_ timeout
// value. This misfeature may be fixed in the future.
bool TimedWait(uint32 milliseconds)
{
return m_Cond.TimedWait(m_Lock, milliseconds);
}
void Notify() { m_Cond.Notify(); }
void NotifySingle() { m_Cond.NotifySingle(); }
CryMutex& GetLock() { return m_Lock; }
};
//////////////////////////////////////////////////////////////////////////
//
// Sync primitive for multiple reads and exclusive locking change access
//
// Desc:
// Useful in case if you have rarely modified object that needs
// to be read quite often from different threads but still
// need to be exclusively modified sometimes
// Debug functionality:
// Can be used for debug-only lock calls, which verify that no
// simultaneous access is attempted.
// Use the bDebug argument of LockRead or LockModify,
// or use the DEBUG_READLOCK or DEBUG_MODIFYLOCK macros.
// There is no overhead in release builds, if you use the macros,
// and the lock definition is inside #ifdef _DEBUG.
//////////////////////////////////////////////////////////////////////////
class CryReadModifyLock
{
public:
CryReadModifyLock()
: m_modifyCount(0)
, m_readCount(0)
{
SetDebugLocked(false);
}
bool LockRead(bool bTry = false, cstr strDebug = 0, bool bDebug = false) const
{
if (!WriteLock(bTry, bDebug, strDebug)) // wait until write unlocked
{
return false;
}
CryInterlockedIncrement(&m_readCount); // increment read counter
m_writeLock.Unlock();
return true;
}
void UnlockRead() const
{
SetDebugLocked(false);
const int counter = CryInterlockedDecrement(&m_readCount); // release read
assert(counter >= 0);
if (m_writeLock.TryLock())
{
m_writeLock.Unlock();
}
else
if (counter == 0 && m_modifyCount)
{
m_ReadReleased.Set(); // signal the final read released
}
}
bool LockModify(bool bTry = false, cstr strDebug = 0, bool bDebug = false) const
{
if (!WriteLock(bTry, bDebug, strDebug))
{
return false;
}
CryInterlockedIncrement(&m_modifyCount); // increment write counter (counter is for nested cases)
while (m_readCount)
{
m_ReadReleased.Wait(); // wait for all threads finish read operation
}
return true;
}
void UnlockModify() const
{
SetDebugLocked(false);
int counter = CryInterlockedDecrement(&m_modifyCount); // decrement write counter
assert(counter >= 0);
m_writeLock.Unlock(); // release exclusive lock
}
protected:
mutable volatile int m_readCount;
mutable volatile int m_modifyCount;
mutable CryEvent m_ReadReleased;
mutable CryCriticalSection m_writeLock;
mutable bool m_debugLocked;
mutable const char* m_debugLockStr;
void SetDebugLocked([[maybe_unused]] bool b, [[maybe_unused]] const char* str = 0) const
{
#ifdef _DEBUG
m_debugLocked = b;
m_debugLockStr = str;
#endif
}
bool WriteLock(bool bTry, [[maybe_unused]] bool bDebug, [[maybe_unused]] const char* strDebug) const
{
if (!m_writeLock.TryLock())
{
#ifdef _DEBUG
assert(!m_debugLocked);
assert(!bDebug);
#endif
if (bTry)
{
return false;
}
m_writeLock.Lock();
}
#ifdef _DEBUG
if (!m_readCount && !m_modifyCount) // not yet locked
{
SetDebugLocked(bDebug, strDebug);
}
#endif
return true;
}
};
// Auto-locking classes.
template<class T, bool bDEBUG = false>
class AutoLockRead
{
protected:
const T& m_lock;
public:
AutoLockRead(const T& lock, cstr strDebug = 0)
: m_lock(lock) { m_lock.LockRead(bDEBUG, strDebug, bDEBUG); }
~AutoLockRead()
{ m_lock.UnlockRead(); }
};
template<class T, bool bDEBUG = false>
class AutoLockModify
{
protected:
const T& m_lock;
public:
AutoLockModify(const T& lock, cstr strDebug = 0)
: m_lock(lock) { m_lock.LockModify(bDEBUG, strDebug, bDEBUG); }
~AutoLockModify()
{ m_lock.UnlockModify(); }
};
#define AUTO_READLOCK(p) PREFAST_SUPPRESS_WARNING(6246) AutoLockRead<CryReadModifyLock> AZ_JOIN(__readlock, __LINE__)(p, __FUNC__)
#define AUTO_READLOCK_PROT(p) PREFAST_SUPPRESS_WARNING(6246) AutoLockRead<CryReadModifyLock> AZ_JOIN(__readlock_prot, __LINE__)(p, __FUNC__)
#define AUTO_MODIFYLOCK(p) PREFAST_SUPPRESS_WARNING(6246) AutoLockModify<CryReadModifyLock> AZ_JOIN(__modifylock, __LINE__)(p, __FUNC__)
#if defined(_DEBUG)
#define DEBUG_READLOCK(p) AutoLockRead<CryReadModifyLock> AZ_JOIN(__readlock, __LINE__)(p, __FUNC__)
#define DEBUG_MODIFYLOCK(p) AutoLockModify<CryReadModifyLock> AZ_JOIN(__modifylock, __LINE__)(p, __FUNC__)
#else
#define DEBUG_READLOCK(p)
#define DEBUG_MODIFYLOCK(p)
#endif
// producer consumer queue implementations, but here instead of MultiThread_Container.h
// since they requiere platform specific code, and including windows.h in a very common
// header file leads to all kinds of problems
namespace CryMT
{
//////////////////////////////////////////////////////////////////////////
// Producer/Consumer Queue for 1 to 1 thread communication
// Realized with only volatile variables and memory barriers
// *warning* this producer/consumer queue is only thread safe in a 1 to 1 situation
// and doesn't provide any yields or similar to prevent spinning
//////////////////////////////////////////////////////////////////////////
template<typename T>
class SingleProducerSingleConsumerQueue
: public CryMT::detail::SingleProducerSingleConsumerQueueBase
{
public:
SingleProducerSingleConsumerQueue();
~SingleProducerSingleConsumerQueue();
void Init(size_t nSize);
void Push(const T& rObj);
void Pop(T* pResult);
uint32 Size() { return (m_nProducerIndex - m_nComsumerIndex); }
uint32 BufferSize() { return m_nBufferSize; }
uint32 FreeCount() { return (m_nBufferSize - (m_nProducerIndex - m_nComsumerIndex)); }
private:
T* m_arrBuffer;
uint32 m_nBufferSize;
volatile uint32 m_nProducerIndex _ALIGN(16);
volatile uint32 m_nComsumerIndex _ALIGN(16);
} _ALIGN(128);
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline SingleProducerSingleConsumerQueue<T>::SingleProducerSingleConsumerQueue()
: m_arrBuffer(NULL)
, m_nBufferSize(0)
, m_nProducerIndex(0)
, m_nComsumerIndex(0)
{}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline SingleProducerSingleConsumerQueue<T>::~SingleProducerSingleConsumerQueue()
{
CryModuleMemalignFree(m_arrBuffer);
m_nBufferSize = 0;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void SingleProducerSingleConsumerQueue<T>::Init(size_t nSize)
{
assert(m_arrBuffer == NULL);
assert(m_nBufferSize == 0);
assert((nSize & (nSize - 1)) == 0);
m_arrBuffer = alias_cast<T*>(CryModuleMemalign(nSize * sizeof(T), 16));
m_nBufferSize = nSize;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void SingleProducerSingleConsumerQueue<T>::Push(const T& rObj)
{
assert(m_arrBuffer != NULL);
assert(m_nBufferSize != 0);
SingleProducerSingleConsumerQueueBase::Push((void*)&rObj, m_nProducerIndex, m_nComsumerIndex, m_nBufferSize, m_arrBuffer, sizeof(T));
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void SingleProducerSingleConsumerQueue<T>::Pop(T* pResult)
{
assert(m_arrBuffer != NULL);
assert(m_nBufferSize != 0);
SingleProducerSingleConsumerQueueBase::Pop(pResult, m_nProducerIndex, m_nComsumerIndex, m_nBufferSize, m_arrBuffer, sizeof(T));
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Producer/Consumer Queue for N to 1 thread communication
// lockfree implemenation, to copy with multiple producers,
// a internal producer refcount is managed, the queue is empty
// as soon as there are no more producers and no new elements
//////////////////////////////////////////////////////////////////////////
template<typename T>
class N_ProducerSingleConsumerQueue
: public CryMT::detail::N_ProducerSingleConsumerQueueBase
{
public:
N_ProducerSingleConsumerQueue();
~N_ProducerSingleConsumerQueue();
void Init(size_t nSize);
void Push(const T& rObj);
bool Pop(T* pResult);
// needs to be called before using, assumes that there is at least one producer
// so the first one doesn't need to call AddProducer, but he has to deregister itself
void SetRunningState();
// to correctly track when the queue is empty(and no new jobs will be added), refcount the producer
void AddProducer();
void RemoveProducer();
uint32 Size() { return (m_nProducerIndex - m_nComsumerIndex); }
uint32 BufferSize() { return m_nBufferSize; }
uint32 FreeCount() { return (m_nBufferSize - (m_nProducerIndex - m_nComsumerIndex)); }
private:
T* m_arrBuffer;
volatile uint32* m_arrStates;
uint32 m_nBufferSize;
volatile uint32 m_nProducerIndex;
volatile uint32 m_nComsumerIndex;
volatile uint32 m_nRunning;
volatile uint32 m_nProducerCount;
} _ALIGN(128);
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline N_ProducerSingleConsumerQueue<T>::N_ProducerSingleConsumerQueue()
: m_arrBuffer(NULL)
, m_arrStates(NULL)
, m_nBufferSize(0)
, m_nProducerIndex(0)
, m_nComsumerIndex(0)
, m_nRunning(0)
, m_nProducerCount(0)
{}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline N_ProducerSingleConsumerQueue<T>::~N_ProducerSingleConsumerQueue()
{
CryModuleMemalignFree(m_arrBuffer);
CryModuleMemalignFree((void*)m_arrStates);
m_nBufferSize = 0;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void N_ProducerSingleConsumerQueue<T>::Init(size_t nSize)
{
assert(m_arrBuffer == NULL);
assert(m_arrStates == NULL);
assert(m_nBufferSize == 0);
assert((nSize & (nSize - 1)) == 0);
m_arrBuffer = alias_cast<T*>(CryModuleMemalign(nSize * sizeof(T), 16));
m_arrStates = alias_cast<uint32*>(CryModuleMemalign(nSize * sizeof(uint32), 16));
memset((void*)m_arrStates, 0, sizeof(uint32) * nSize);
m_nBufferSize = nSize;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void N_ProducerSingleConsumerQueue<T>::SetRunningState()
{
#if !defined(_RELEASE)
if (m_nRunning == 1)
{
__debugbreak();
}
#endif
m_nRunning = 1;
m_nProducerCount = 1;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void N_ProducerSingleConsumerQueue<T>::AddProducer()
{
assert(m_arrBuffer != NULL);
assert(m_arrStates != NULL);
assert(m_nBufferSize != 0);
#if !defined(_RELEASE)
if (m_nRunning == 0)
{
__debugbreak();
}
#endif
CryInterlockedIncrement((volatile int*)&m_nProducerCount);
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void N_ProducerSingleConsumerQueue<T>::RemoveProducer()
{
assert(m_arrBuffer != NULL);
assert(m_arrStates != NULL);
assert(m_nBufferSize != 0);
#if !defined(_RELEASE)
if (m_nRunning == 0)
{
__debugbreak();
}
#endif
if (CryInterlockedDecrement((volatile int*)&m_nProducerCount) == 0)
{
m_nRunning = 0;
}
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void N_ProducerSingleConsumerQueue<T>::Push(const T& rObj)
{
assert(m_arrBuffer != NULL);
assert(m_arrStates != NULL);
assert(m_nBufferSize != 0);
CryMT::detail::N_ProducerSingleConsumerQueueBase::Push((void*)&rObj, m_nProducerIndex, m_nComsumerIndex, m_nRunning, m_arrBuffer, m_nBufferSize, sizeof(T), m_arrStates);
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline bool N_ProducerSingleConsumerQueue<T>::Pop(T* pResult)
{
assert(m_arrBuffer != NULL);
assert(m_arrStates != NULL);
assert(m_nBufferSize != 0);
return CryMT::detail::N_ProducerSingleConsumerQueueBase::Pop(pResult, m_nProducerIndex, m_nComsumerIndex, m_nRunning, m_arrBuffer, m_nBufferSize, sizeof(T), m_arrStates);
}
} //namespace CryMT
// Include all multithreading containers.
#include "MultiThread_Containers.h"
+52
View File
@@ -0,0 +1,52 @@
/*
* 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.
#pragma once
#include <CryThread.h>
// Include architecture specific code.
#if defined(LINUX) || defined(APPLE)
#include <CryThreadImpl_pthreads.h>
#define AZ_RESTRICTED_SECTION_IMPLEMENTED
#elif defined(WIN32) || defined(WIN64)
#include <CryThreadImpl_windows.h>
#define AZ_RESTRICTED_SECTION_IMPLEMENTED
#elif defined(AZ_RESTRICTED_PLATFORM)
#include AZ_RESTRICTED_FILE(CryThreadImpl_h)
#endif
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
#else
// Put other platform specific includes here!
#endif
#include <IThreadTask.h>
void CryThreadSetName(threadID dwThreadId, const char* sThreadName)
{
if (gEnv && gEnv->pSystem && gEnv->pSystem->GetIThreadTaskManager())
{
gEnv->pSystem->GetIThreadTaskManager()->SetThreadName(dwThreadId, sThreadName);
}
}
const char* CryThreadGetName(threadID dwThreadId)
{
if (gEnv && gEnv->pSystem && gEnv->pSystem->GetIThreadTaskManager())
{
return gEnv->pSystem->GetIThreadTaskManager()->GetThreadName(dwThreadId);
}
return "";
}
@@ -0,0 +1,305 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYCOMMON_CRYTHREADIMPL_PTHREADS_H
#define CRYINCLUDE_CRYCOMMON_CRYTHREADIMPL_PTHREADS_H
#pragma once
#include "CryThread_pthreads.h"
#if PLATFORM_SUPPORTS_THREADLOCAL
THREADLOCAL CrySimpleThreadSelf
* CrySimpleThreadSelf::m_Self = NULL;
#else
TLS_DEFINE(CrySimpleThreadSelf*, g_CrySimpleThreadSelf)
#endif
//////////////////////////////////////////////////////////////////////////
// CryEvent(Timed) implementation
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void CryEventTimed::Reset()
{
m_lockNotify.Lock();
m_flag = false;
m_lockNotify.Unlock();
}
//////////////////////////////////////////////////////////////////////////
void CryEventTimed::Set()
{
m_lockNotify.Lock();
m_flag = true;
m_cond.Notify();
m_lockNotify.Unlock();
}
//////////////////////////////////////////////////////////////////////////
void CryEventTimed::Wait()
{
m_lockNotify.Lock();
if (!m_flag)
{
m_cond.Wait(m_lockNotify);
}
m_flag = false;
m_lockNotify.Unlock();
}
//////////////////////////////////////////////////////////////////////////
bool CryEventTimed::Wait(const uint32 timeoutMillis)
{
bool bResult = true;
m_lockNotify.Lock();
if (!m_flag)
{
bResult = m_cond.TimedWait(m_lockNotify, timeoutMillis);
}
m_flag = false;
m_lockNotify.Unlock();
return bResult;
}
///////////////////////////////////////////////////////////////////////////////
// CryCriticalSection implementation
///////////////////////////////////////////////////////////////////////////////
typedef CryLockT<CRYLOCK_RECURSIVE> TCritSecType;
void CryDeleteCriticalSection(void* cs)
{
delete ((TCritSecType*)cs);
}
void CryEnterCriticalSection(void* cs)
{
((TCritSecType*)cs)->Lock();
}
bool CryTryCriticalSection(void* cs)
{
return false;
}
void CryLeaveCriticalSection(void* cs)
{
((TCritSecType*)cs)->Unlock();
}
void CryCreateCriticalSectionInplace(void* pCS)
{
new (pCS) TCritSecType;
}
void CryDeleteCriticalSectionInplace(void*)
{
}
void* CryCreateCriticalSection()
{
return (void*) new TCritSecType;
}
#if AZ_TRAIT_SKIP_CRYINTERLOCKED
#elif defined(INTERLOCKED_COMPARE_EXCHANGE_128_NOT_SUPPORTED)
//////////////////////////////////////////////////////////////////////////
void CryInterlockedPushEntrySList(SLockFreeSingleLinkedListHeader& list, SLockFreeSingleLinkedListEntry& element)
{
AZStd::lock_guard<AZStd::mutex> lock(list.mutex);
element.pNext = list.pNext;
list.pNext = &element;
}
//////////////////////////////////////////////////////////////////////////
void* CryInterlockedPopEntrySList(SLockFreeSingleLinkedListHeader& list)
{
AZStd::lock_guard<AZStd::mutex> lock(list.mutex);
SLockFreeSingleLinkedListEntry* returnValue = list.pNext;
if (list.pNext)
{
list.pNext = list.pNext->pNext;
}
return returnValue;
}
//////////////////////////////////////////////////////////////////////////
void CryInitializeSListHead(SLockFreeSingleLinkedListHeader& list)
{
AZStd::lock_guard<AZStd::mutex> lock(list.mutex);
list.pNext = NULL;
}
//////////////////////////////////////////////////////////////////////////
void* CryInterlockedFlushSList(SLockFreeSingleLinkedListHeader& list)
{
AZStd::lock_guard<AZStd::mutex> lock(list.mutex);
SLockFreeSingleLinkedListEntry* returnValue = list.pNext;
list.pNext = nullptr;
return returnValue;
}
#elif defined(LINUX32)
//////////////////////////////////////////////////////////////////////////
// Implementation for Linux32 with gcc using uint64
//////////////////////////////////////////////////////////////////////////
void CryInterlockedPushEntrySList(SLockFreeSingleLinkedListHeader& list, SLockFreeSingleLinkedListEntry& element)
{
uint32 curSetting[2];
uint32 newSetting[2];
uint32 newPointer = (uint32) & element;
do
{
curSetting[0] = (uint32)list.pNext;
curSetting[1] = list.salt;
element.pNext = (SLockFreeSingleLinkedListEntry*)curSetting[0];
newSetting[0] = newPointer; // new pointer
newSetting[1] = curSetting[1] + 1; // new salt
}
while (false == __sync_bool_compare_and_swap((volatile uint64*)&list.pNext, *(uint64*)&curSetting[0], *(uint64*)&newSetting[0]));
}
//////////////////////////////////////////////////////////////////////////
void* CryInterlockedPopEntrySList(SLockFreeSingleLinkedListHeader& list)
{
uint32 curSetting[2];
uint32 newSetting[2];
do
{
curSetting[1] = list.salt;
curSetting[0] = (uint32)list.pNext;
if (curSetting[0] == 0)
{
return NULL;
}
newSetting[0] = *(uint32*)curSetting[0]; // new pointer
newSetting[1] = curSetting[1] + 1; // new salt
}
while (false == __sync_bool_compare_and_swap((volatile uint64*)&list.pNext, *(uint64*)&curSetting[0], *(uint64*)&newSetting[0]));
return (void*)curSetting[0];
}
//////////////////////////////////////////////////////////////////////////
void CryInitializeSListHead(SLockFreeSingleLinkedListHeader& list)
{
list.salt = 0;
list.pNext = NULL;
}
//////////////////////////////////////////////////////////////////////////
void* CryInterlockedFlushSList(SLockFreeSingleLinkedListHeader& list)
{
uint32 curSetting[2];
uint32 newSetting[2];
uint32 newSalt;
uint32 newPointer;
do
{
curSetting[1] = list.salt;
curSetting[0] = (uint32)list.pNext;
if (curSetting[0] == 0)
{
return NULL;
}
newSetting[0] = 0;
newSetting[1] = curSetting[1] + 1;
}
while (false == __sync_bool_compare_and_swap((volatile uint64*)&list.pNext, *(uint64*)&curSetting[0], *(uint64*)&newSetting[0]));
return (void*)curSetting[0];
}
#else
// This implementation get's used on multiple platforms that support uint128 compare and swap.
//////////////////////////////////////////////////////////////////////////
// LINUX64 Implementation of Lockless Single Linked List
//////////////////////////////////////////////////////////////////////////
typedef __uint128_t uint128;
//////////////////////////////////////////////////////////////////////////
// Implementation for Linux64 with gcc using __int128_t
//////////////////////////////////////////////////////////////////////////
void CryInterlockedPushEntrySList(SLockFreeSingleLinkedListHeader& list, SLockFreeSingleLinkedListEntry& element)
{
uint64 curSetting[2];
uint64 newSetting[2];
uint64 newPointer = (uint64) & element;
do
{
curSetting[0] = (uint64)list.pNext;
curSetting[1] = list.salt;
element.pNext = (SLockFreeSingleLinkedListEntry*)curSetting[0];
newSetting[0] = newPointer; // new pointer
newSetting[1] = curSetting[1] + 1; // new salt
}
// while (false == __sync_bool_compare_and_swap( (volatile uint128*)&list.pNext,*(uint128*)&curSetting[0],*(uint128*)&newSetting[0] ));
while (0 == _InterlockedCompareExchange128((volatile int64*)&list.pNext, (int64)newSetting[1], (int64)newSetting[0], (int64*)&curSetting[0]));
}
//////////////////////////////////////////////////////////////////////////
void* CryInterlockedPopEntrySList(SLockFreeSingleLinkedListHeader& list)
{
uint64 curSetting[2];
uint64 newSetting[2];
do
{
curSetting[1] = list.salt;
curSetting[0] = (uint64)list.pNext;
if (curSetting[0] == 0)
{
return NULL;
}
newSetting[0] = *(uint64*)curSetting[0]; // new pointer
newSetting[1] = curSetting[1] + 1; // new salt
}
//while (false == __sync_bool_compare_and_swap( (volatile uint128*)&list.pNext,*(uint128*)&curSetting[0],*(uint128*)&newSetting[0] ));
while (0 == _InterlockedCompareExchange128((volatile int64*)&list.pNext, (int64)newSetting[1], (int64)newSetting[0], (int64*)&curSetting[0]));
return (void*)curSetting[0];
}
//////////////////////////////////////////////////////////////////////////
void CryInitializeSListHead(SLockFreeSingleLinkedListHeader& list)
{
list.salt = 0;
list.pNext = NULL;
}
//////////////////////////////////////////////////////////////////////////
void* CryInterlockedFlushSList(SLockFreeSingleLinkedListHeader& list)
{
uint64 curSetting[2];
uint64 newSetting[2];
uint64 newSalt;
uint64 newPointer;
do
{
curSetting[1] = list.salt;
curSetting[0] = (uint64)list.pNext;
if (curSetting[0] == 0)
{
return NULL;
}
newSetting[0] = 0;
newSetting[1] = curSetting[1] + 1;
}
// while (false == __sync_bool_compare_and_swap( (volatile uint128*)&list.pNext,*(uint128*)&curSetting[0],*(uint128*)&newSetting[0] ));
while (0 == _InterlockedCompareExchange128((volatile int64*)&list.pNext, (int64)newSetting[1], (int64)newSetting[0], (int64*)&curSetting[0]));
return (void*)curSetting[0];
}
//////////////////////////////////////////////////////////////////////////
#endif
#endif // CRYINCLUDE_CRYCOMMON_CRYTHREADIMPL_PTHREADS_H
@@ -0,0 +1,605 @@
/*
* 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.
#pragma once
//#include <IThreadTask.h>
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <process.h>
#include <AzCore/std/parallel/semaphore.h> // for CreateSemaphore
struct SThreadNameDesc
{
DWORD dwType;
LPCSTR szName;
DWORD dwThreadID;
DWORD dwFlags;
};
THREADLOCAL CrySimpleThreadSelf* CrySimpleThreadSelf::m_Self = NULL;
//////////////////////////////////////////////////////////////////////////
CryEvent::CryEvent()
{
m_handle = (void*)CreateEvent(NULL, FALSE, FALSE, NULL);
}
//////////////////////////////////////////////////////////////////////////
CryEvent::~CryEvent()
{
CloseHandle(m_handle);
}
//////////////////////////////////////////////////////////////////////////
void CryEvent::Reset()
{
ResetEvent(m_handle);
}
//////////////////////////////////////////////////////////////////////////
void CryEvent::Set()
{
SetEvent(m_handle);
}
//////////////////////////////////////////////////////////////////////////
void CryEvent::Wait() const
{
WaitForSingleObject(m_handle, INFINITE);
}
//////////////////////////////////////////////////////////////////////////
bool CryEvent::Wait(const uint32 timeoutMillis) const
{
if (WaitForSingleObject(m_handle, timeoutMillis) == WAIT_TIMEOUT)
{
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////////
// CryLock_WinMutex
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
CryLock_WinMutex::CryLock_WinMutex()
: m_hdl(CreateMutex(NULL, FALSE, NULL)) {}
CryLock_WinMutex::~CryLock_WinMutex()
{
CloseHandle(m_hdl);
}
//////////////////////////////////////////////////////////////////////////
void CryLock_WinMutex::Lock()
{
WaitForSingleObject(m_hdl, INFINITE);
}
//////////////////////////////////////////////////////////////////////////
void CryLock_WinMutex::Unlock()
{
ReleaseMutex(m_hdl);
}
//////////////////////////////////////////////////////////////////////////
bool CryLock_WinMutex::TryLock()
{
return WaitForSingleObject(m_hdl, 0) != WAIT_TIMEOUT;
}
//////////////////////////////////////////////////////////////////////////
// CryLock_CritSection
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
CryLock_CritSection::CryLock_CritSection()
{
InitializeCriticalSection((CRITICAL_SECTION*)&m_cs);
}
//////////////////////////////////////////////////////////////////////////
CryLock_CritSection::~CryLock_CritSection()
{
DeleteCriticalSection((CRITICAL_SECTION*)&m_cs);
}
//////////////////////////////////////////////////////////////////////////
void CryLock_CritSection::Lock()
{
EnterCriticalSection((CRITICAL_SECTION*)&m_cs);
}
//////////////////////////////////////////////////////////////////////////
void CryLock_CritSection::Unlock()
{
LeaveCriticalSection((CRITICAL_SECTION*)&m_cs);
}
//////////////////////////////////////////////////////////////////////////
bool CryLock_CritSection::TryLock()
{
return TryEnterCriticalSection((CRITICAL_SECTION*)&m_cs) != FALSE;
}
//////////////////////////////////////////////////////////////////////////
// most of this is taken from http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
//////////////////////////////////////////////////////////////////////////
CryConditionVariable::CryConditionVariable()
{
m_waitersCount = 0;
m_wasBroadcast = 0;
m_sema = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
InitializeCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
m_waitersDone = CreateEvent(NULL, FALSE, FALSE, NULL);
}
//////////////////////////////////////////////////////////////////////////
CryConditionVariable::~CryConditionVariable()
{
CloseHandle(m_sema);
DeleteCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
CloseHandle(m_waitersDone);
}
//////////////////////////////////////////////////////////////////////////
void CryConditionVariable::Wait(LockType& lock)
{
EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
m_waitersCount++;
LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
SignalObjectAndWait(lock._get_win32_handle(), m_sema, INFINITE, FALSE);
EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
m_waitersCount--;
bool lastWaiter = m_wasBroadcast && m_waitersCount == 0;
LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
if (lastWaiter)
{
SignalObjectAndWait(m_waitersDone, lock._get_win32_handle(), INFINITE, FALSE);
}
else
{
WaitForSingleObject(lock._get_win32_handle(), INFINITE);
}
}
//////////////////////////////////////////////////////////////////////////
bool CryConditionVariable::TimedWait(LockType& lock, uint32 millis)
{
EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
m_waitersCount++;
LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
bool ok = true;
if (WAIT_TIMEOUT == SignalObjectAndWait(lock._get_win32_handle(), m_sema, millis, FALSE))
{
ok = false;
}
EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
m_waitersCount--;
bool lastWaiter = m_wasBroadcast && m_waitersCount == 0;
LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
if (lastWaiter)
{
SignalObjectAndWait(m_waitersDone, lock._get_win32_handle(), INFINITE, FALSE);
}
else
{
WaitForSingleObject(lock._get_win32_handle(), INFINITE);
}
return ok;
}
//////////////////////////////////////////////////////////////////////////
void CryConditionVariable::NotifySingle()
{
EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
bool haveWaiters = m_waitersCount > 0;
LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
if (haveWaiters)
{
ReleaseSemaphore(m_sema, 1, 0);
}
}
//////////////////////////////////////////////////////////////////////////
void CryConditionVariable::Notify()
{
EnterCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
bool haveWaiters = false;
if (m_waitersCount > 0)
{
m_wasBroadcast = 1;
haveWaiters = true;
}
if (haveWaiters)
{
ReleaseSemaphore(m_sema, m_waitersCount, 0);
LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
WaitForSingleObject(m_waitersDone, INFINITE);
m_wasBroadcast = 0;
}
else
{
LeaveCriticalSection((CRITICAL_SECTION*)&m_waitersCountLock);
}
}
//////////////////////////////////////////////////////////////////////////
CrySemaphore::CrySemaphore(int nMaximumCount, int nInitialCount)
{
m_Semaphore = (void*)CreateSemaphore(NULL, nInitialCount, nMaximumCount, NULL);
}
//////////////////////////////////////////////////////////////////////////
CrySemaphore::~CrySemaphore()
{
CloseHandle((HANDLE)m_Semaphore);
}
//////////////////////////////////////////////////////////////////////////
void CrySemaphore::Acquire()
{
WaitForSingleObject((HANDLE)m_Semaphore, INFINITE);
}
//////////////////////////////////////////////////////////////////////////
void CrySemaphore::Release()
{
ReleaseSemaphore((HANDLE)m_Semaphore, 1, NULL);
}
//////////////////////////////////////////////////////////////////////////
CryFastSemaphore::CryFastSemaphore(int nMaximumCount, int nInitialCount)
: m_Semaphore(nMaximumCount)
, m_nCounter(nInitialCount)
{
}
//////////////////////////////////////////////////////////////////////////
CryFastSemaphore::~CryFastSemaphore()
{
}
//////////////////////////////////////////////////////////////////////////
void CryFastSemaphore::Acquire()
{
int nCount = ~0;
do
{
nCount = *const_cast<volatile int*>(&m_nCounter);
} while (CryInterlockedCompareExchange(alias_cast<volatile LONG*>(&m_nCounter), nCount - 1, nCount) != nCount);
// if the count would have been 0 or below, go to kernel semaphore
if ((nCount - 1) < 0)
{
m_Semaphore.Acquire();
}
}
//////////////////////////////////////////////////////////////////////////
void CryFastSemaphore::Release()
{
int nCount = ~0;
do
{
nCount = *const_cast<volatile int*>(&m_nCounter);
} while (CryInterlockedCompareExchange(alias_cast<volatile LONG*>(&m_nCounter), nCount + 1, nCount) != nCount);
// wake up kernel semaphore if we have waiter
if (nCount < 0)
{
m_Semaphore.Release();
}
}
//////////////////////////////////////////////////////////////////////////
CryRWLock::CryRWLock()
{
STATIC_ASSERT(sizeof(m_Lock) == sizeof(PSRWLOCK), "RWLock-pointer has invalid size");
InitializeSRWLock(reinterpret_cast<PSRWLOCK>(&m_Lock));
}
//////////////////////////////////////////////////////////////////////////
CryRWLock::~CryRWLock()
{
}
//////////////////////////////////////////////////////////////////////////
void CryRWLock::RLock()
{
AcquireSRWLockShared(reinterpret_cast<PSRWLOCK>(&m_Lock));
}
//////////////////////////////////////////////////////////////////////////
#if defined(_CRYTHREAD_WANT_TRY_RWLOCK)
bool CryRWLock::TryRLock()
{
return TryAcquireSRWLockShared(reinterpret_cast<PSRWLOCK>(&m_Lock)) != 0;
}
#endif
//////////////////////////////////////////////////////////////////////////
void CryRWLock::RUnlock()
{
ReleaseSRWLockShared(reinterpret_cast<PSRWLOCK>(&m_Lock));
}
//////////////////////////////////////////////////////////////////////////
void CryRWLock::WLock()
{
AcquireSRWLockExclusive(reinterpret_cast<PSRWLOCK>(&m_Lock));
}
//////////////////////////////////////////////////////////////////////////
#if defined(_CRYTHREAD_WANT_TRY_RWLOCK)
bool CryRWLock::TryWLock()
{
return TryAcquireSRWLockExclusive(reinterpret_cast<PSRWLOCK>(&m_Lock)) != 0;
}
#endif
//////////////////////////////////////////////////////////////////////////
void CryRWLock::WUnlock()
{
ReleaseSRWLockExclusive(reinterpret_cast<PSRWLOCK>(&m_Lock));
}
//////////////////////////////////////////////////////////////////////////
void CryRWLock::Lock()
{
WLock();
}
//////////////////////////////////////////////////////////////////////////
#if defined(_CRYTHREAD_WANT_TRY_RWLOCK)
bool CryRWLock::TryLock()
{
return TryWLock();
}
#endif
//////////////////////////////////////////////////////////////////////////
void CryRWLock::Unlock()
{
WUnlock();
}
//////////////////////////////////////////////////////////////////////////
CrySimpleThreadSelf::CrySimpleThreadSelf()
: m_thread(NULL)
, m_threadId(0)
{
}
//////////////////////////////////////////////////////////////////////////
void CrySimpleThreadSelf::WaitForThread()
{
assert(m_thread);
PREFAST_ASSUME(m_thread);
if (GetCurrentThreadId() != m_threadId)
{
WaitForSingleObject((HANDLE)m_thread, INFINITE);
}
}
CrySimpleThreadSelf::~CrySimpleThreadSelf()
{
if (m_thread)
{
CloseHandle(m_thread);
}
}
void CrySimpleThreadSelf::StartThread(unsigned (__stdcall * func)(void*), void* argList)
{
#if defined(AZ_RESTRICTED_PLATFORM)
#include AZ_RESTRICTED_FILE(CryThreadImpl_windows_h)
#endif
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
#else
m_thread = (void*)_beginthreadex(NULL, 0, func, argList, CREATE_SUSPENDED, &m_threadId);
#endif
assert(m_thread);
PREFAST_ASSUME(m_thread);
ResumeThread((HANDLE)m_thread);
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void CryInterlockedPushEntrySList(SLockFreeSingleLinkedListHeader& list, SLockFreeSingleLinkedListEntry& element)
{
STATIC_CHECK(sizeof(SLockFreeSingleLinkedListHeader) == sizeof(SLIST_HEADER), CRY_INTERLOCKED_SLIST_HEADER_HAS_WRONG_SIZE);
STATIC_CHECK(sizeof(SLockFreeSingleLinkedListEntry) >= sizeof(SLIST_ENTRY), CRY_INTERLOCKED_SLIST_ENTRY_HAS_WRONG_SIZE);
assert(IsAligned(&list, MEMORY_ALLOCATION_ALIGNMENT) && "LockFree SingleLink List Header has wrong Alignment");
assert(IsAligned(&element, MEMORY_ALLOCATION_ALIGNMENT) && "LockFree SingleLink List Entry has wrong Alignment");
InterlockedPushEntrySList(alias_cast<PSLIST_HEADER>(&list), alias_cast<PSLIST_ENTRY>(&element));
}
//////////////////////////////////////////////////////////////////////////
void* CryInterlockedPopEntrySList(SLockFreeSingleLinkedListHeader& list)
{
STATIC_CHECK(sizeof(SLockFreeSingleLinkedListHeader) == sizeof(SLIST_HEADER), CRY_INTERLOCKED_SLIST_HEADER_HAS_WRONG_SIZE);
assert(IsAligned(&list, MEMORY_ALLOCATION_ALIGNMENT) && "LockFree SingleLink List Header has wrong Alignment");
return reinterpret_cast<void*>(InterlockedPopEntrySList(alias_cast<PSLIST_HEADER>(&list)));
}
//////////////////////////////////////////////////////////////////////////
void CryInitializeSListHead(SLockFreeSingleLinkedListHeader& list)
{
assert(IsAligned(&list, MEMORY_ALLOCATION_ALIGNMENT) && "LockFree SingleLink List Header has wrong Alignment");
STATIC_CHECK(sizeof(SLockFreeSingleLinkedListHeader) == sizeof(SLIST_HEADER), CRY_INTERLOCKED_SLIST_HEADER_HAS_WRONG_SIZE);
InitializeSListHead(alias_cast<PSLIST_HEADER>(&list));
}
//////////////////////////////////////////////////////////////////////////
void* CryInterlockedFlushSList(SLockFreeSingleLinkedListHeader& list)
{
assert(IsAligned(&list, MEMORY_ALLOCATION_ALIGNMENT) && "LockFree SingleLink List Header has wrong Alignment");
STATIC_CHECK(sizeof(SLockFreeSingleLinkedListHeader) == sizeof(SLIST_HEADER), CRY_INTERLOCKED_SLIST_HEADER_HAS_WRONG_SIZE);
return InterlockedFlushSList(alias_cast<PSLIST_HEADER>(&list));
}
///////////////////////////////////////////////////////////////////////////////
// base class for lock less Producer/Consumer queue, due platforms specific they
// are implemeted in CryThead_platform.h
namespace CryMT {
namespace detail {
///////////////////////////////////////////////////////////////////////////////
void SingleProducerSingleConsumerQueueBase::Push(void* pObj, volatile uint32& rProducerIndex, volatile uint32& rComsumerIndex, uint32 nBufferSize, void* arrBuffer, uint32 nObjectSize)
{
// spin if queue is full
int iter = 0;
while (rProducerIndex - rComsumerIndex == nBufferSize)
{
CryLowLatencySleep(iter++ > 10 ? 1 : 0);
}
MemoryBarrier();
char* pBuffer = alias_cast<char*>(arrBuffer);
uint32 nIndex = rProducerIndex % nBufferSize;
memcpy(pBuffer + (nIndex * nObjectSize), pObj, nObjectSize);
MemoryBarrier();
rProducerIndex += 1;
MemoryBarrier();
}
///////////////////////////////////////////////////////////////////////////////
void SingleProducerSingleConsumerQueueBase::Pop(void* pObj, volatile uint32& rProducerIndex, volatile uint32& rComsumerIndex, uint32 nBufferSize, void* arrBuffer, uint32 nObjectSize)
{
MemoryBarrier();
// busy-loop if queue is empty
int iter = 0;
while (rProducerIndex - rComsumerIndex == 0)
{
CryLowLatencySleep(iter++ > 10 ? 1 : 0);
}
char* pBuffer = alias_cast<char*>(arrBuffer);
uint32 nIndex = rComsumerIndex % nBufferSize;
memcpy(pObj, pBuffer + (nIndex * nObjectSize), nObjectSize);
MemoryBarrier();
rComsumerIndex += 1;
MemoryBarrier();
}
///////////////////////////////////////////////////////////////////////////////
void N_ProducerSingleConsumerQueueBase::Push(void* pObj, volatile uint32& rProducerIndex, volatile uint32& rComsumerIndex, [[maybe_unused]] volatile uint32& rRunning, void* arrBuffer, uint32 nBufferSize, uint32 nObjectSize, volatile uint32* arrStates)
{
MemoryBarrier();
uint32 nProducerIndex;
uint32 nComsumerIndex;
int iter = 0;
do
{
nProducerIndex = rProducerIndex;
nComsumerIndex = rComsumerIndex;
if (nProducerIndex - nComsumerIndex == nBufferSize)
{
CryLowLatencySleep(iter++ > 10 ? 1 : 0);
if (iter > 20) // 10 spins + 10 ms wait
{
uint32 nSizeToAlloc = sizeof(SFallbackList) + nObjectSize - 1;
SFallbackList* pFallbackEntry = (SFallbackList*)CryModuleMemalign(nSizeToAlloc, 128);
memcpy(pFallbackEntry->object, pObj, nObjectSize);
MemoryBarrier();
CryInterlockedPushEntrySList(fallbackList, pFallbackEntry->nextEntry);
return;
}
continue;
}
if (CryInterlockedCompareExchange(alias_cast<volatile LONG*>(&rProducerIndex), nProducerIndex + 1, nProducerIndex) == nProducerIndex)
{
break;
}
} while (true);
MemoryBarrier();
char* pBuffer = alias_cast<char*>(arrBuffer);
uint32 nIndex = nProducerIndex % nBufferSize;
memcpy(pBuffer + (nIndex * nObjectSize), pObj, nObjectSize);
MemoryBarrier();
arrStates[nIndex] = 1;
MemoryBarrier();
}
///////////////////////////////////////////////////////////////////////////////
bool N_ProducerSingleConsumerQueueBase::Pop(void* pObj, volatile uint32& rProducerIndex, volatile uint32& rComsumerIndex, volatile uint32& rRunning, void* arrBuffer, uint32 nBufferSize, uint32 nObjectSize, volatile uint32* arrStates)
{
MemoryBarrier();
// busy-loop if queue is empty
int iter = 0;
if (rRunning && rProducerIndex - rComsumerIndex == 0)
{
while (rRunning && rProducerIndex - rComsumerIndex == 0)
{
CryLowLatencySleep(iter++ > 10 ? 1 : 0);
}
}
if (rRunning == 0 && rProducerIndex - rComsumerIndex == 0)
{
SFallbackList* pFallback = (SFallbackList*)CryInterlockedPopEntrySList(fallbackList);
IF (pFallback, 0)
{
memcpy(pObj, pFallback->object, nObjectSize);
CryModuleMemalignFree(pFallback);
return true;
}
// if the queue was empty, make sure we really are empty
return false;
}
iter = 0;
while (arrStates[rComsumerIndex % nBufferSize] == 0)
{
CryLowLatencySleep(iter++ > 10 ? 1 : 0);
}
char* pBuffer = alias_cast<char*>(arrBuffer);
uint32 nIndex = rComsumerIndex % nBufferSize;
memcpy(pObj, pBuffer + (nIndex * nObjectSize), nObjectSize);
MemoryBarrier();
arrStates[nIndex] = 0;
MemoryBarrier();
rComsumerIndex += 1;
MemoryBarrier();
return true;
}
} // namespace detail
} // namespace CryMT
@@ -0,0 +1,632 @@
/*
* 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 : Specialized Container for Renderer data with the following proberties:
// - Created during the 3DEngine Update, comsumed in the renderer in the following frame
// - This Container is very restricted and likely not optimal for other situations
#ifndef CRYINCLUDE_CRYCOMMON_CRYTHREADSAFERENDERERCONTAINER_H
#define CRYINCLUDE_CRYCOMMON_CRYTHREADSAFERENDERERCONTAINER_H
#pragma once
// This container is specialized for data which is generated in the 3DEngine and consumed by the renderer
// in the following frame due to multithreaded rendering. To be useable by Jobs as well as other Threads
// some very specific desing choices were taken:
// First of the underlying continous memory block is only resized during a call to 'CoalesceMemory'
// to prevent freeing a memory block which could be used by another thread.
// If new memory is requiered, a page of 4 KB is allocated and used as a temp storage till the next
// call to 'CoalesceMemory' which then copies all page memory into one continous block.
// Also all threading relevant functions are implemented LockLess to prevent lock contention and make
// this container useable from Jobs
//
// Right now, the main usage pattern of this container is by the RenderThread, who calls at the beginning
// of its frame 'CoalesceMemory', since then we can be sure that the 3DEngine has finished creating it's elements.
//
// Since the main purpose of this container is multi-threading adding of elements, a slight change was done to the
// push_back interface compared to std::vector:
// All implemented push_back variants can return a pointer into the storage (safe since no memory is freed during adding)
// and a index for this elements. This is done since calling operator[] could be expensive when called before 'CoalesceMemory'
//
// For ease of implementation (and a little bit of speed), this container only supports POD types (which can be copied with memcpy)
// also note that this container only supports push_back (and resize back to 0) and no pop back due cost (performance and code complexity) of supporting lock-free in parallel pop_back
#define TSRC_ALIGN _MS_ALIGN(128)
template<typename T>
class TSRC_ALIGN CThreadSafeRendererContainer
{
public:
CThreadSafeRendererContainer();
~CThreadSafeRendererContainer();
//NOTE: be aware that these valus can potentially change if some objects are added in parallel
size_t size() const;
size_t empty() const;
size_t capacity() const;
//NOTE: be aware that this operator can be more expensive if the memory was not coalesced before
T& operator[](size_t n);
const T& operator[](size_t n) const;
T* push_back_new();
T* push_back_new(size_t& nIndex);
void push_back(const T&);
void push_back(const T&, size_t& nIndex);
// NOTE: These functions are changing the size of the continous memory block and thus are *not* thread-safe
void clear();
void resize(size_t n);
void reserve(size_t n);
void CoalesceMemory();
void GetMemoryUsage(ICrySizer*) const;
// disable copy/assignment
CThreadSafeRendererContainer(const CThreadSafeRendererContainer& rOther) = delete;
CThreadSafeRendererContainer& operator=(const CThreadSafeRendererContainer& rOther) = delete;
private:
/////////////////////////////////////
// Struct to represent a memory chunk
// used in fallback allocations during 'Fill' phase
class CMemoryPage
{
public:
// size of a page to allocate, the CMemoryPage is just the header,
// the actual object data is stored in the 4KB chunk right
// after the header (while keeping the requiered alignment and so on)
enum
{
nMemoryPageSize = 4096
};
CMemoryPage();
// allocation functions
static CMemoryPage* AllocateNewPage();
bool TryAllocateElement(size_t& nIndex, T*& pObj);
// access to the elements
T& GetElement(size_t n);
T* GetData() const;
// information about the page (NOTE: not thread-safe in all combinations)
size_t Size() const;
size_t Capacity() const;
size_t GetDataSize() const;
CMemoryPage* m_pNext; // Pointer to next entry in single-linked list of CMemoryPages
private:
LONG m_nSize; // Number of elements currently in the page
LONG m_nCapacity; // Number of elements which could fit into the page
T* m_arrData; // Element memory, from the same memory chunk right after the CMemoryPage class
};
/////////////////////////////////////
// Private functions which do the lock-less updating
T* push_back_impl(size_t& nIndex);
bool try_append_to_continous_memory(size_t& nIndex, T*& pObj);
T& GetMemoryPageElement(size_t n);
/////////////////////////////////////
// Private Member Variables
T* m_arrData; // Storage for the continous memory part, during coalescing resized to hold all page memory
LONG m_nCapacity; // Avaible Memory in continous memory part, if exhausted during 'Fill' phase, pages as temp memory chunks are allocated
CMemoryPage* m_pMemoryPages; // Single linked list of memory chunks, used for fallback allocations during 'Fill' phase (to prevent changing the continous memory block during 'Fill'
LONG m_nSize; // Number of elements currently in the container, can be larger than m_nCapacity due the nonContinousPages
bool m_bElementAccessSafe; // bool to indicate if we are currently doing a 'CoalasceMemory' step, during which some operations are now allowed
} _ALIGN(128);
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline CThreadSafeRendererContainer<T>::CThreadSafeRendererContainer()
: m_arrData(NULL)
, m_nCapacity(0)
, m_pMemoryPages(NULL)
, m_nSize(0)
, m_bElementAccessSafe(true)
{
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline CThreadSafeRendererContainer<T>::~CThreadSafeRendererContainer()
{
clear();
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline size_t CThreadSafeRendererContainer<T>::size() const
{
return *const_cast<volatile LONG*>(&m_nSize);
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline size_t CThreadSafeRendererContainer<T>::empty() const
{
return *const_cast<volatile LONG*>(&m_nSize) == 0;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline size_t CThreadSafeRendererContainer<T>::capacity() const
{
// capacity of continous memory block
LONG nCapacity = m_nCapacity;
// add capacity of all memory pages
CMemoryPage* pCurrentMemoryPage = m_pMemoryPages;
while (pCurrentMemoryPage)
{
nCapacity += pCurrentMemoryPage->Capacity();
pCurrentMemoryPage = pCurrentMemoryPage->m_pNext;
}
return nCapacity;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline T& CThreadSafeRendererContainer<T>::operator[](size_t n)
{
assert(m_bElementAccessSafe);
T* pRet = NULL;
#if !defined(NULL_RENDERER)
assert((LONG)n < m_nSize);
#endif
if ((LONG)n < m_nCapacity)
{
pRet = &m_arrData[n];
}
else
{
pRet = &GetMemoryPageElement(n);
}
return *pRet;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline const T& CThreadSafeRendererContainer<T>::operator[](size_t n) const
{
return const_cast<const T&>(const_cast<CThreadSafeRendererContainer<T>*>(this)->operator[](n));
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline T* CThreadSafeRendererContainer<T>::push_back_new()
{
assert(m_bElementAccessSafe);
size_t nUnused = ~0;
return push_back_impl(nUnused);
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline T* CThreadSafeRendererContainer<T>::push_back_new(size_t& nIndex)
{
assert(m_bElementAccessSafe);
return push_back_impl(nIndex);
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void CThreadSafeRendererContainer<T>::push_back(const T& rObj)
{
assert(m_bElementAccessSafe);
size_t nUnused = ~0;
T* pObj = push_back_impl(nUnused);
*pObj = rObj;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void CThreadSafeRendererContainer<T>::push_back(const T& rObj, size_t& nIndex)
{
assert(m_bElementAccessSafe);
T* pObj = push_back_impl(nIndex);
*pObj = rObj;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void CThreadSafeRendererContainer<T>::clear()
{
assert(m_bElementAccessSafe);
// free continous part
CryModuleMemalignFree(m_arrData);
m_arrData = NULL;
// free non-continous pages if we have some
CMemoryPage* pCurrentMemoryPage = m_pMemoryPages;
while (pCurrentMemoryPage)
{
CMemoryPage* pOldPage = pCurrentMemoryPage;
pCurrentMemoryPage = pCurrentMemoryPage->m_pNext;
CryModuleFree(pOldPage);
}
m_pMemoryPages = NULL;
m_nSize = 0;
m_nCapacity = 0;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void CThreadSafeRendererContainer<T>::resize(size_t n)
{
assert(m_bElementAccessSafe);
CoalesceMemory();
size_t nOldSize = m_nSize;
m_nSize = n;
if ((LONG)n <= m_nCapacity)
{
return;
}
T* arrOldData = m_arrData;
m_arrData = reinterpret_cast<T*>(CryModuleMemalign(n * sizeof(T), alignof(T)));
memcpy(m_arrData, arrOldData, nOldSize * sizeof(T));
memset(&m_arrData[m_nCapacity], 0, (n - m_nCapacity) * sizeof(T));
CryModuleMemalignFree(arrOldData);
m_nCapacity = n;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void CThreadSafeRendererContainer<T>::reserve(size_t n)
{
assert(m_bElementAccessSafe);
CoalesceMemory();
if ((LONG)n <= m_nCapacity)
{
return;
}
T* arrOldData = m_arrData;
m_arrData = reinterpret_cast<T*>(CryModuleMemalign(n * sizeof(T), alignof(T)));
memcpy(m_arrData, arrOldData, m_nSize * sizeof(T));
memset(&m_arrData[m_nCapacity], 0, (n - m_nCapacity) * sizeof(T));
CryModuleMemalignFree(arrOldData);
m_nCapacity = n;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline bool CThreadSafeRendererContainer<T>::try_append_to_continous_memory(size_t& nIndex, T*& pObj)
{
assert(m_bElementAccessSafe);
LONG nSize = ~0;
LONG nCapacity = ~0;
do
{
// read volatile the new size
nSize = *const_cast<volatile LONG*>(&m_nSize);
nCapacity = *const_cast<volatile LONG*>(&m_nCapacity);
if (nSize >= nCapacity)
{
return false;
}
} while (CryInterlockedCompareExchange(alias_cast<volatile LONG*>(&m_nSize), nSize + 1, nSize) != nSize);
nIndex = nSize;
pObj = &m_arrData[nSize];
return true;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline T* CThreadSafeRendererContainer<T>::push_back_impl(size_t& nIndex)
{
assert(m_bElementAccessSafe);
T* pObj = NULL;
// non atomic check to see if there is space in the continous array
if (try_append_to_continous_memory(nIndex, pObj))
{
return pObj;
}
// exhausted continous memory, falling back to page allocation
for (;; )
{
assert(m_bElementAccessSafe);
size_t nPageBaseIndex = 0;
// traverse the page list till the first page with free memory
CMemoryPage* pCurrentMemoryPage = m_pMemoryPages;
while (pCurrentMemoryPage)
{
size_t nAvaibleElements = pCurrentMemoryPage->Capacity() - pCurrentMemoryPage->Size();
if (nAvaibleElements)
{
break;
}
// no memory in this page, go to the next one
nPageBaseIndex += pCurrentMemoryPage->Capacity();
pCurrentMemoryPage = pCurrentMemoryPage->m_pNext;
}
// try to allocate a element on this page
if (pCurrentMemoryPage && pCurrentMemoryPage->TryAllocateElement(nIndex, pObj))
{
// update global elements counter
CryInterlockedIncrement(alias_cast<volatile int*>(&m_nSize));
// adjust in-page-index to global index
nIndex += nPageBaseIndex + m_nCapacity;
return pObj;
}
else
{
// all pages are empty, allocate and link a new one
CMemoryPage* pNewPage = CMemoryPage::AllocateNewPage();
void* volatile* ppLastMemoryPageAddress = NULL;
do
{
// find place to link in page
CMemoryPage* pLastMemoryPage = m_pMemoryPages;
ppLastMemoryPageAddress = alias_cast<void* volatile*>(&m_pMemoryPages);
while (pLastMemoryPage)
{
ppLastMemoryPageAddress = alias_cast<void* volatile*>(&(pLastMemoryPage->m_pNext));
pLastMemoryPage = pLastMemoryPage->m_pNext;
}
} while (CryInterlockedCompareExchangePointer(ppLastMemoryPageAddress, pNewPage, NULL) != NULL);
}
}
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline T& CThreadSafeRendererContainer<T>::GetMemoryPageElement(size_t n)
{
assert(m_bElementAccessSafe);
size_t nFirstListIndex = m_nCapacity;
CMemoryPage* pCurrentMemoryPage = m_pMemoryPages;
size_t nPageCapacity = pCurrentMemoryPage->Capacity();
while (n >= (nFirstListIndex + nPageCapacity))
{
// this is threadsafe because we assume that if we want to get element 'n'
// the clientcode did already fill the container up to element 'n'
// thus up to 'n', m_pNonContinousList will have valid pages
// NOTE: This is not safe when trying to read a element behind the valid
// range (same as std::vector)
nFirstListIndex += nPageCapacity;
pCurrentMemoryPage = pCurrentMemoryPage->m_pNext;
// update page capacity, since it can differe due alignment
nPageCapacity = pCurrentMemoryPage->Capacity();
}
return pCurrentMemoryPage->GetElement(n - nFirstListIndex);
}
///////////////////////////////////////////////////////////////////////////////
// When not not in the 'Fill' phase, it is safe to colace all page entries into one continous memory block
template<typename T>
inline void CThreadSafeRendererContainer<T>::CoalesceMemory()
{
assert(m_bElementAccessSafe);
if (m_pMemoryPages == NULL)
{
return; // nothing to do
}
// mark state as not accessable
m_bElementAccessSafe = false;
size_t nOldSize = m_nSize;
// compute required memory
size_t nRequieredElements = 0;
{
CMemoryPage* pCurrentMemoryPage = m_pMemoryPages;
while (pCurrentMemoryPage)
{
nRequieredElements += pCurrentMemoryPage->Size();
pCurrentMemoryPage = pCurrentMemoryPage->m_pNext;
}
}
T* arrOldData = m_arrData;
m_arrData = reinterpret_cast<T*>(CryModuleMemalign((m_nCapacity + nRequieredElements) * sizeof(T), alignof(T)));
memcpy(m_arrData, arrOldData, m_nCapacity * sizeof(T));
CryModuleMemalignFree(arrOldData);
// copy page data into continous memory block
{
size_t nBeginToFillIndex = m_nCapacity;
CMemoryPage* pCurrentMemoryPage = m_pMemoryPages;
while (pCurrentMemoryPage)
{
// copy data
memcpy(&m_arrData[nBeginToFillIndex], pCurrentMemoryPage->GetData(), pCurrentMemoryPage->GetDataSize());
nBeginToFillIndex += pCurrentMemoryPage->Size();
// free page
CMemoryPage* pOldPage = pCurrentMemoryPage;
pCurrentMemoryPage = pCurrentMemoryPage->m_pNext;
CryModuleFree(pOldPage);
}
m_pMemoryPages = NULL;
}
assert(nOldSize == m_nSize);
m_nCapacity += nRequieredElements;
// the container can be used again
m_bElementAccessSafe = true;
}
///////////////////////////////////////////////////////////////////////////////
// Collect information about used memory
template<typename T>
void CThreadSafeRendererContainer<T>::GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(m_arrData, m_nCapacity * sizeof(T));
CMemoryPage* pCurrentMemoryPage = m_pMemoryPages;
while (pCurrentMemoryPage)
{
pSizer->AddObject(pCurrentMemoryPage, CMemoryPage::nMemoryPageSize);
pCurrentMemoryPage = pCurrentMemoryPage->m_pNext;
}
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline CThreadSafeRendererContainer<T>::CMemoryPage::CMemoryPage()
: m_pNext(NULL)
, m_nSize(0)
{
// compute offset for actual data
size_t nObjectAlignment = alignof(T);
UINT_PTR nMemoryBlockBegin = alias_cast<UINT_PTR>(this);
UINT_PTR nMemoryBlockEnd = alias_cast<UINT_PTR>(this) + nMemoryPageSize;
nMemoryBlockBegin += sizeof(CMemoryPage);
nMemoryBlockBegin = (nMemoryBlockBegin + nObjectAlignment - 1) & ~(nObjectAlignment - 1);
// compute number of avaible elements
assert((nMemoryBlockEnd - nMemoryBlockBegin) > 0);
m_nCapacity = (LONG)((nMemoryBlockEnd - nMemoryBlockBegin) / sizeof(T));
// store pointer to store data to
m_arrData = alias_cast<T*>(nMemoryBlockBegin);
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline typename CThreadSafeRendererContainer<T>::CMemoryPage * CThreadSafeRendererContainer<T>::CMemoryPage::AllocateNewPage()
{
void* pNewPageMemoryChunk = CryModuleMalloc(nMemoryPageSize);
assert(pNewPageMemoryChunk != NULL);
memset(pNewPageMemoryChunk, 0, nMemoryPageSize);
CMemoryPage* pNewPage = new(pNewPageMemoryChunk) CMemoryPage();
return pNewPage;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline bool CThreadSafeRendererContainer<T>::CMemoryPage::TryAllocateElement(size_t & nIndex, T * &pObj)
{
LONG nSize = ~0;
LONG nCapacity = ~0;
do
{
// read volatile the new size
nSize = *const_cast<volatile LONG*>(&m_nSize);
nCapacity = *const_cast<volatile LONG*>(&m_nCapacity);
// stop trying if this page is full
if (nSize >= nCapacity)
{
return false;
}
} while (CryInterlockedCompareExchange(alias_cast<volatile LONG*>(&m_nSize), nSize + 1, nSize) != nSize);
//Note: this is the index in the page and it is adjusted in the calling context
nIndex = nSize;
pObj = &m_arrData[nSize];
return true;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline T&CThreadSafeRendererContainer<T>::CMemoryPage::GetElement(size_t n)
{
assert((LONG)n < m_nSize);
assert(m_nSize <= m_nCapacity);
return m_arrData[n];
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline T * CThreadSafeRendererContainer<T>::CMemoryPage::GetData() const
{
return m_arrData;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline size_t CThreadSafeRendererContainer<T>::CMemoryPage::Size() const
{
return m_nSize;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline size_t CThreadSafeRendererContainer<T>::CMemoryPage::GetDataSize() const
{
return m_nSize * sizeof(T);
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline size_t CThreadSafeRendererContainer<T>::CMemoryPage::Capacity() const
{
return m_nCapacity;
}
#endif // CRYINCLUDE_CRYCOMMON_CRYTHREADSAFERENDERERCONTAINER_H
@@ -0,0 +1,602 @@
/*
* 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 : Specialized Container for Renderer data with the following properties:
// Created during the 3DEngine Update, consumed in the renderer in the following frame
// This Container is very restricted and likely not optimal for other situations
#ifndef CRYINCLUDE_CRYCOMMON_CRYTHREADSAFEWORKERCONTAINER_H
#define CRYINCLUDE_CRYCOMMON_CRYTHREADSAFEWORKERCONTAINER_H
#pragma once
#include "platform.h"
#include <vector>
#include <AzCore/Jobs/JobContext.h>
#include <AzCore/Jobs/JobManager.h>
#include <AzCore/std/typetraits/typetraits.h>
//
// !!! BE CAREFULL WHEN USING THIS CONTAINER !!!
//
// --- Properties: ---
// - Stores data local to worker thread to avoid thread-safety semantics
// - Allows for a single non-worker thread to be tracked which is stored in m_workers[0]
// Hence: As m_workers[0] is shared between all non-worker threads, ensure that only one additional non-worker thread may access this container e.g. MainThread
// - Coalesce memory to obtain a continues memory block
// - Coalesce memory to for faster element access to a continues memory block
//
// --- Restrictions:---
// - The workers own the memory structure
// - The coalesced memory stores a copy of the workers used memory
// Hence: Be careful when altering data within the coalesced memory.
// If the templated element is a pointer type than altering the memory pointed to, is not be an issue
// If the templated element is of type class or struct than ensure that data changes are done on the worker local data and not on the coalesced memory. Use worker encoded indices to do so.
//
template <class T>
class CThreadSafeWorkerContainer
{
public:
struct SDefaultNoOpFunctor
{
ILINE void operator()(T* pData) const{}
};
struct SDefaultDestructorFunctor
{
ILINE void operator()(T* pData) const
{
pData->~T();
}
};
public:
CThreadSafeWorkerContainer();
~CThreadSafeWorkerContainer();
void Init();
void SetNonWorkerThreadID(threadID nThreadId) { m_foreignThreadId = nThreadId; }
// Safe access of elements for calling thread via operator[]
uint32 ConvertToEncodedWorkerId_threadlocal(uint32 nIndex) const;
// Returns the number of threads that can use this container, including the one non-worker-thread.
uint32 GetNumWorkers() const;
// Returns the Worker ID for the current thread. Ranges from 0 to GetNumWorkers()-1.
// Note, WorkerId is not the same thing as JobManager's WorkerThreadId.
uint32 GetWorkerId_threadlocal() const;
//NOTE: be aware that these values can potentially change if some objects are added in parallel
size_t size() const;
size_t empty() const;
size_t capacity() const;
size_t size_threadlocal() const;
size_t empty_threadlocal() const;
size_t capacity_threadlocal() const;
//NOTE: be aware that this operator is more expensive if the memory was not coalesced before
T& operator[](size_t n);
const T& operator[](size_t n) const;
T* push_back_new();
T* push_back_new(size_t& nIndex);
void push_back(const T& rObj);
void push_back(const T& rObj, size_t& nIndex);
// NOTE: These functions are changing the size of the continous memory block and thus are *not* thread-safe
void clear();
template< class OnElementDeleteFunctor>
void clear(const OnElementDeleteFunctor& rFunctor = CThreadSafeWorkerContainer<T>::SDefaultNoOpFunctor());
void erase(const T& rObj);
void resize(size_t n);
void reserve(size_t n);
// *not* thread-safe functions
void PrefillContainer(T* pElement, size_t numElements);
void CoalesceMemory();
void GetMemoryUsage(ICrySizer* pSizer) const;
private:
void clear(AZStd::true_type);
void clear(AZStd::false_type);
class SWorker
{
public:
AZ_CLASS_ALLOCATOR(SWorker, AZ::LegacyAllocator, 0);
SWorker()
: m_dataSize(0) {}
uint32 m_dataSize;
AZStd::vector<T> m_data;
} _ALIGN(128);
T* push_back_impl(size_t& nIndex);
void ReserverCoalescedMemory(size_t n);
threadID m_foreignThreadId; // OS thread ID of the non-job-manager-worker-thread allowed to use this container, too.
AZStd::vector<SWorker> m_workers; // Holds data for each thread that can use this container. A non-worker-thread (Main) has data stored at 0. Actual worker threads range from 1 to m_nNumWorkers-1
uint32 m_nNumWorkers = 0; // The number of threads that can use this container, including one non-worker-thread.
uint32 m_coalescedArrCapacity;
T* m_coalescedArr;
bool m_isCoalesced;
};
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline CThreadSafeWorkerContainer<T>::CThreadSafeWorkerContainer()
: m_nNumWorkers(0)
, m_coalescedArrCapacity(0)
, m_coalescedArr(0)
, m_isCoalesced(false)
{
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline CThreadSafeWorkerContainer<T>::~CThreadSafeWorkerContainer()
{
clear();
m_workers.clear();
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void CThreadSafeWorkerContainer<T>::Init()
{
m_nNumWorkers = AZ::JobContext::GetGlobalContext()->GetJobManager().GetNumWorkerThreads() + 1;
m_workers.resize(m_nNumWorkers);
m_foreignThreadId = THREADID_NULL;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline size_t CThreadSafeWorkerContainer<T>::size() const
{
uint32 totalSize = 0;
for (int i = 0; i < m_nNumWorkers; ++i)
{
totalSize += m_workers[i].m_dataSize;
}
return totalSize;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline size_t CThreadSafeWorkerContainer<T>::empty() const
{
return size() == 0;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline size_t CThreadSafeWorkerContainer<T>::capacity() const
{
uint32 totalCapacity = 0;
for (int i = 0; i < m_nNumWorkers; ++i)
{
totalCapacity += m_workers[i].m_data.capacity();
}
return totalCapacity;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline size_t CThreadSafeWorkerContainer<T>::size_threadlocal() const
{
const uint32 nWorkerThreadId = GetWorkerId_threadlocal();
return m_workers[nWorkerThreadId].m_dataSize;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline size_t CThreadSafeWorkerContainer<T>::empty_threadlocal() const
{
const uint32 nWorkerThreadId = GetWorkerId_threadlocal();
return m_workers[nWorkerThreadId].m_data.empty();
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline size_t CThreadSafeWorkerContainer<T>::capacity_threadlocal() const
{
const uint32 nWorkerThreadId = GetWorkerId_threadlocal();
return m_workers[nWorkerThreadId].m_data.capacity();
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline T& CThreadSafeWorkerContainer<T>::operator[](size_t n)
{
const uint32 nHasWorkerEncodedIndex = (n & 0x80000000) >> 31;
IF ((m_isCoalesced && !nHasWorkerEncodedIndex), 1)
{
AZ_Assert(m_coalescedArr, "null array");
AZ_Assert(n < m_coalescedArrCapacity, "Index out of bounds");
return m_coalescedArr[n];
}
else
{
const uint32 nWorkerThreadId = (n & 0x7F00007F) >> 24; // Mask bit 24-30 (0 is starting bit)
const uint32 nOffset = (n & ~0xFF000000); // Mask out top 8 bits
// Encoded offset into worker local array
if (nHasWorkerEncodedIndex)
{
return m_workers[nWorkerThreadId].m_data[nOffset];
}
else // None-coalesced and none worker encoded offset
{
uint32 nTotalOffset = nOffset;
for (int i = 0; i < m_nNumWorkers; ++i)
{
SWorker& worker = m_workers[i];
if (nTotalOffset < worker.m_dataSize)
{
return worker.m_data[nTotalOffset];
}
else
{
nTotalOffset -= worker.m_dataSize;
}
}
// Out of bound access detected!
CRY_ASSERT_MESSAGE(false, "CThreadSafeWorkerContainer::operator[] - Out of bounds access");
__debugbreak();
AZ_Assert(m_coalescedArr, "null array");
AZ_Assert(m_coalescedArrCapacity > 0, "Index out of bounds");
return m_coalescedArr[0];
}
}
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline const T& CThreadSafeWorkerContainer<T>::operator[](size_t n) const
{
return const_cast<const T&>(const_cast<CThreadSafeWorkerContainer<T>*>(this)->operator[](n));
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline T* CThreadSafeWorkerContainer<T>::push_back_new()
{
size_t unused = ~0;
return push_back_impl(unused);
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline T* CThreadSafeWorkerContainer<T>::push_back_new(size_t& nIndex)
{
return push_back_impl(nIndex);
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void CThreadSafeWorkerContainer<T>::push_back(const T& rObj)
{
size_t nUnused = ~0;
T* pObj = push_back_impl(nUnused);
*pObj = rObj;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void CThreadSafeWorkerContainer<T>::push_back(const T& rObj, size_t& nIndex)
{
T* pObj = push_back_impl(nIndex);
*pObj = rObj;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void CThreadSafeWorkerContainer<T>::clear()
{
clear(typename std::is_destructible<T>::type());
}
template<typename T>
void CThreadSafeWorkerContainer<T>::clear(AZStd::true_type)
{
clear(SDefaultDestructorFunctor());
}
template<typename T>
void CThreadSafeWorkerContainer<T>::clear(AZStd::false_type)
{
clear(SDefaultNoOpFunctor());
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
template<class OnElementDeleteFunctor>
inline void CThreadSafeWorkerContainer<T>::clear(const OnElementDeleteFunctor& rFunctor)
{
// Reset worker data
for (int i = 0; i < m_nNumWorkers; ++i)
{
// Delete elements
uint32 nSize = m_workers[i].m_data.size();
for (int j = 0; j < nSize; ++j)
{
// Call on element delete functor
// Note: Default functor will do nothing with the element
rFunctor(&m_workers[i].m_data[j]);
}
m_workers[i].m_data.clear();
m_workers[i].m_dataSize = 0;
}
// Reset container data
if (m_coalescedArr)
{
CryModuleMemalignFree(m_coalescedArr);
}
m_coalescedArr = 0;
m_coalescedArrCapacity = 0;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void CThreadSafeWorkerContainer<T>::erase(const T& rObj)
{
for (int i = 0; i < m_nNumWorkers; ++i)
{
typename std::vector<T>::iterator iter = m_workers[i].m_data.begin();
typename std::vector<T>::iterator iterEnd = m_workers[i].m_data.end();
for (; iter != iterEnd; ++iter)
{
if (rObj == *iter)
{
m_workers[i].m_data.erase(iter);
--m_workers[i].m_dataSize;
m_isCoalesced = false;
return;
}
}
}
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void CThreadSafeWorkerContainer<T>::resize(size_t n)
{
CoalesceMemory();
uint32 nSizePerWorker = n / m_nNumWorkers;
uint32 nExcessSize = n % m_nNumWorkers;
// Resize workers evenly
for (int i = 0; i < m_nNumWorkers; ++i)
{
uint32 nWorkerSize = nSizePerWorker + nExcessSize;
if (nWorkerSize > m_workers[i].m_data.size())
{
m_workers[i].m_data.resize(nWorkerSize);
}
m_workers[i].m_dataSize = nWorkerSize;
nExcessSize = 0; // First worker creates excess items
}
ReserverCoalescedMemory(n);
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void CThreadSafeWorkerContainer<T>::reserve(size_t n)
{
CoalesceMemory();
uint32 nSizePerWorker = n / m_nNumWorkers;
uint32 nExcessSize = n % m_nNumWorkers;
// Resize workers evenly
for (int i = 0; i < m_nNumWorkers; ++i)
{
uint32 nWorkerSize = nSizePerWorker + nExcessSize;
if (nWorkerSize > m_workers[i].m_data.size())
{
m_workers[i].m_data.resize(nWorkerSize);
}
nExcessSize = 0; // First worker creates excess items
}
ReserverCoalescedMemory(n);
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void CThreadSafeWorkerContainer<T>::PrefillContainer(T* pElement, size_t numElements)
{
reserve(numElements);
uint32 nOffset = 0;
uint32 nNumItemPerWorker = numElements / m_nNumWorkers;
uint32 nNumExcessItems = numElements % m_nNumWorkers;
// Store items evenly in workers
for (int i = 0; i < m_nNumWorkers; ++i)
{
uint32 nNumItems = nNumItemPerWorker + nNumExcessItems;
for (int j = 0; j < nNumItems; ++j)
{
m_workers[i].m_data[j] = pElement[nOffset + j];
}
m_workers[i].m_dataSize = nNumItems;
nOffset += nNumItems;
nNumExcessItems = 0; // First worker stores excess items
}
m_isCoalesced = false;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void CThreadSafeWorkerContainer<T>::CoalesceMemory()
{
if (m_isCoalesced)
{
return;
}
// Ensure enough memory exists
uint32 minSizeNeeded = 0;
for (int i = 0; i < m_nNumWorkers; ++i)
{
minSizeNeeded += m_workers[i].m_dataSize;
}
IF (minSizeNeeded >= m_coalescedArrCapacity, 0)
{
ReserverCoalescedMemory(minSizeNeeded + (minSizeNeeded / 4));
}
// Copy data to coalesced array
uint32 nOffest = 0;
for (int i = 0; i < m_nNumWorkers; ++i)
{
SWorker& rWorker = m_workers[i];
if (rWorker.m_dataSize == 0)
{
continue;
}
AZ_Assert((nOffest + rWorker.m_dataSize) <= m_coalescedArrCapacity, "Index out of bounds");
memcpy(m_coalescedArr + nOffest, &rWorker.m_data[0], sizeof(T) * rWorker.m_dataSize);
nOffest += rWorker.m_dataSize;
}
m_isCoalesced = true;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
uint32 CThreadSafeWorkerContainer<T>::ConvertToEncodedWorkerId_threadlocal(uint32 nIndex) const
{
const uint32 workerId = GetWorkerId_threadlocal();
assert(nIndex < m_workers[workerId].m_dataSize);
return (uint32)((1 << 31) | (workerId << 24) | nIndex);
}
//////////////////////////////////////////////////////////////////////////
template<typename T>
uint32 CThreadSafeWorkerContainer<T>::GetNumWorkers() const
{
return m_nNumWorkers;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void CThreadSafeWorkerContainer<T>::GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(m_coalescedArr, m_coalescedArrCapacity * sizeof(T));
for (int i = 0; i < m_nNumWorkers; ++i)
{
pSizer->AddContainer(m_workers[i].m_data);
}
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline void CThreadSafeWorkerContainer<T>::ReserverCoalescedMemory(size_t n)
{
if (n <= m_coalescedArrCapacity)
{
return;
}
T* arrOldData = m_coalescedArr;
m_coalescedArr = reinterpret_cast<T*>(CryModuleMemalign(n * sizeof(T), alignof(T)));
memcpy(m_coalescedArr, arrOldData, m_coalescedArrCapacity * sizeof(T));
if (arrOldData)
{
CryModuleMemalignFree(arrOldData);
}
m_coalescedArrCapacity = n;
}
///////////////////////////////////////////////////////////////////////////////
template<typename T>
inline T* CThreadSafeWorkerContainer<T>::push_back_impl(size_t& nIndex)
{
// Avoid writing to thread share resource and take hit of 'if statement to avoid false-sharing between threads
IF (m_isCoalesced, 0)
{
m_isCoalesced = false;
}
// Get worker id
const uint32 nWorkerThreadId = GetWorkerId_threadlocal();
SWorker& activeWorker = m_workers[nWorkerThreadId];
// Ensure enough space
if (activeWorker.m_dataSize >= activeWorker.m_data.size())
{
activeWorker.m_data.resize(activeWorker.m_data.size() + (activeWorker.m_data.size() / 2) + 1);
}
// Encode worker local offset into index and return
T* retItem = &activeWorker.m_data[activeWorker.m_dataSize];
nIndex = (size_t)((1 << 31) | (nWorkerThreadId << 24) | activeWorker.m_dataSize);
++activeWorker.m_dataSize;
return retItem;
}
template<typename T>
uint32 CThreadSafeWorkerContainer<T>::GetWorkerId_threadlocal() const
{
const uint32 workerThreadId = AZ::JobContext::GetGlobalContext()->GetJobManager().GetWorkerThreadId();
if (workerThreadId == AZ::JobManager::InvalidWorkerThreadId)
{
// Only one non-worker thread is allowed, so check to see if this is that thread.
const threadID currentThreadId = CryGetCurrentThreadId();
if (m_foreignThreadId != currentThreadId)
{
CryFatalError("Trying to access CThreadSafeWorkerContainer from an unspecified non-worker thread. The only non-worker threadId with access rights: %" PRI_THREADID ". Current threadId: %" PRI_THREADID, m_foreignThreadId, currentThreadId);
}
}
// Non-worker has id of ~0 ... add +1 to shift to 0. Worker0 will use slot 1 etc.
static_assert(AZ::JobManager::InvalidWorkerThreadId == ~0u, "Assumptions about InvalidWorkerId no longer hold true");
return workerThreadId + 1;
}
#endif // CRYINCLUDE_CRYCOMMON_CRYTHREADSAFEWORKERCONTAINER_H
+156
View File
@@ -0,0 +1,156 @@
/*
* 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.
#ifndef CRYINCLUDE_CRYCOMMON_CRYTHREAD_DUMMY_H
#define CRYINCLUDE_CRYCOMMON_CRYTHREAD_DUMMY_H
#pragma once
#include <AzCore/base.h>
//////////////////////////////////////////////////////////////////////////
CryEvent::CryEvent() {}
CryEvent::~CryEvent() {}
void CryEvent::Reset() {}
void CryEvent::Set() {}
void CryEvent::Wait() const {}
bool CryEvent::Wait(const uint32 timeoutMillis) const {}
typedef CryEvent CryEventTimed;
//////////////////////////////////////////////////////////////////////////
class _DummyLock
{
public:
_DummyLock();
void Lock();
bool TryLock();
void Unlock();
#if defined(AZ_DEBUG_BUILD)
bool IsLocked();
#endif
};
template<>
class CryLock<CRYLOCK_FAST>
: public _DummyLock
{
CryLock(const CryLock<CRYLOCK_FAST>&);
void operator = (const CryLock<CRYLOCK_FAST>&);
public:
CryLock();
};
template<>
class CryLock<CRYLOCK_RECURSIVE>
: public _DummyLock
{
CryLock(const CryLock<CRYLOCK_RECURSIVE>&);
void operator = (const CryLock<CRYLOCK_RECURSIVE>&);
public:
CryLock();
};
template<>
class CryCondLock<CRYLOCK_FAST>
: public CryLock<CRYLOCK_FAST>
{
};
template<>
class CryCondLock<CRYLOCK_RECURSIVE>
: public CryLock<CRYLOCK_FAST>
{
};
template<>
class CryCond< CryLock<CRYLOCK_FAST> >
{
typedef CryLock<CRYLOCK_FAST> LockT;
CryCond(const CryCond<LockT>&);
void operator = (const CryCond<LockT>&);
public:
CryCond();
void Notify();
void NotifySingle();
void Wait(LockT&);
bool TimedWait(LockT &, uint32);
};
template<>
class CryCond< CryLock<CRYLOCK_RECURSIVE> >
{
typedef CryLock<CRYLOCK_RECURSIVE> LockT;
CryCond(const CryCond<LockT>&);
void operator = (const CryCond<LockT>&);
public:
CryCond();
void Notify();
void NotifySingle();
void Wait(LockT&);
bool TimedWait(LockT &, uint32);
};
class _DummyRWLock
{
public:
_DummyRWLock() { }
void RLock();
bool TryRLock();
void WLock();
bool TryWLock();
void Lock() { WLock(); }
bool TryLock() { return TryWLock(); }
void Unlock();
};
template<class Runnable>
class CrySimpleThread
: public CryRunnable
{
public:
typedef void (* ThreadFunction)(void*);
CrySimpleThread();
virtual ~CrySimpleThread();
#if !defined(NO_THREADINFO)
CryThreadInfo& GetInfo();
#endif
const char* GetName();
void SetName(const char*);
virtual void Run();
virtual void Cancel();
virtual void Start(Runnable&, unsigned = 0, const char* = NULL);
virtual void Start(unsigned = 0, const char* = NULL);
void StartFunction(ThreadFunction, void* = NULL, unsigned = 0);
void Exit();
void Join();
unsigned SetCpuMask(unsigned);
unsigned GetCpuMask();
void Stop();
bool IsStarted() const;
bool IsRunning() const;
};
#endif // CRYINCLUDE_CRYCOMMON_CRYTHREAD_DUMMY_H
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More