FreeValue.h#
↰ Parent directory (types
)
Two classes designed to carry values of arbitrary datatypes along with their “reflective” data (datatypes etc.) FreeValue is statically allocated but has a fixed (max) size of 64 bytes, while TypedMem stores arbitrary sized data.
Includes#
PVRCore/Log.h
PVRCore/math/MathUtils.h
PVRCore/types/GpuDataTypes.h
Namespaces#
Classes#
Source Code#
#pragma once
#include "PVRCore/types/GpuDataTypes.h"
#include "PVRCore/Log.h"
#include "PVRCore/math/MathUtils.h"
namespace pvr {
namespace GpuDatatypesHelper {
template<typename>
struct Metadata;
template<>
struct Metadata<char*>
{
typedef std::array<char, 64> storagetype;
static const GpuDatatypes dataTypeOf() { return GpuDatatypes::Float; }
static const size_t gpuSizeOf() { return 1; }
};
template<>
struct Metadata<unsigned char*>
{
typedef std::array<char, 64> storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::Float; }
static size_t gpuSizeOf() { return 1; }
};
template<>
struct Metadata<const char*>
{
typedef std::array<char, 64> storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::Float; }
static size_t gpuSizeOf() { return 1; }
};
template<>
struct Metadata<const unsigned char*>
{
typedef std::array<char, 64> storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::Float; }
static size_t gpuSizeOf() { return 1; }
};
template<>
struct Metadata<double>
{
typedef float storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::Float; }
static size_t gpuSizeOf() { return 8; }
};
template<>
struct Metadata<float>
{
typedef float storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::Float; }
static size_t gpuSizeOf() { return 4; }
};
template<>
struct Metadata<int64_t>
{
typedef int32_t storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::Integer; }
static size_t gpuSizeOf() { return 8; }
};
template<>
struct Metadata<int32_t>
{
typedef int32_t storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::Integer; }
static size_t gpuSizeOf() { return 4; }
};
template<>
struct Metadata<int16_t>
{
typedef int32_t storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::Integer; }
static size_t gpuSizeOf() { return 2; }
};
template<>
struct Metadata<int8_t>
{
typedef int32_t storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::Integer; }
static size_t gpuSizeOf() { return 1; }
};
template<>
struct Metadata<uint64_t>
{
typedef uint32_t storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::uinteger; }
static size_t gpuSizeOf() { return 8; }
};
template<>
struct Metadata<uint32_t>
{
typedef uint32_t storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::uinteger; }
static size_t gpuSizeOf() { return 4; }
};
template<>
struct Metadata<uint16_t>
{
typedef uint32_t storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::uinteger; }
static size_t gpuSizeOf() { return 2; }
};
template<>
struct Metadata<uint8_t>
{
typedef uint32_t storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::uinteger; }
static size_t gpuSizeOf() { return 1; }
};
template<>
struct Metadata<glm::vec2>
{
typedef glm::vec2 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::vec2; }
static size_t gpuSizeOf() { return 8; }
};
template<>
struct Metadata<glm::vec3>
{
typedef glm::vec3 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::vec3; }
static size_t gpuSizeOf() { return 12; }
};
template<>
struct Metadata<glm::vec4>
{
typedef glm::vec4 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::vec4; }
static size_t gpuSizeOf() { return 16; }
};
template<>
struct Metadata<glm::ivec2>
{
typedef glm::ivec2 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::ivec2; }
static size_t gpuSizeOf() { return 8; }
};
template<>
struct Metadata<glm::ivec3>
{
typedef glm::ivec3 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::ivec3; }
static size_t gpuSizeOf() { return 12; }
};
template<>
struct Metadata<glm::ivec4>
{
typedef glm::ivec4 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::ivec4; }
static size_t gpuSizeOf() { return 16; }
};
template<>
struct Metadata<glm::uvec2>
{
typedef glm::uvec2 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::uvec2; }
static size_t gpuSizeOf() { return 8; }
};
template<>
struct Metadata<glm::uvec3>
{
typedef glm::uvec3 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::uvec3; }
static size_t gpuSizeOf() { return 12; }
};
template<>
struct Metadata<glm::uvec4>
{
typedef glm::uvec4 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::uvec4; }
static size_t gpuSizeOf() { return 16; }
};
template<>
struct Metadata<glm::bvec2>
{
typedef glm::bvec2 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::bvec2; }
static size_t gpuSizeOf() { return 8; }
};
template<>
struct Metadata<glm::bvec3>
{
typedef glm::bvec3 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::bvec3; }
static size_t gpuSizeOf() { return 12; }
};
template<>
struct Metadata<glm::bvec4>
{
typedef glm::bvec4 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::bvec4; }
static size_t gpuSizeOf() { return 16; }
};
template<>
struct Metadata<glm::mat2x2>
{
typedef glm::mat2x2 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::mat2x2; }
static size_t gpuSizeOf() { return 32; }
};
template<>
struct Metadata<glm::mat2x3>
{
typedef glm::mat2x3 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::mat2x3; }
static size_t gpuSizeOf() { return 32; }
};
template<>
struct Metadata<glm::mat2x4>
{
typedef glm::mat2x4 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::mat2x4; }
static size_t gpuSizeOf() { return 32; }
};
template<>
struct Metadata<glm::mat3x2>
{
typedef glm::mat3x2 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::mat3x2; }
static size_t gpuSizeOf() { return 48; }
};
template<>
struct Metadata<glm::mat3x3>
{
typedef glm::mat3x3 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::mat3x3; }
static size_t gpuSizeOf() { return 48; }
};
template<>
struct Metadata<glm::mat3x4>
{
typedef glm::mat3x4 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::mat3x4; }
static size_t gpuSizeOf() { return 48; }
};
template<>
struct Metadata<glm::mat4x2>
{
typedef glm::mat4x2 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::mat4x2; }
static size_t gpuSizeOf() { return 64; }
};
template<>
struct Metadata<glm::mat4x3>
{
typedef glm::mat4x3 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::mat4x3; }
static size_t gpuSizeOf() { return 64; }
};
template<>
struct Metadata<glm::mat4x4>
{
typedef glm::mat4x4 storagetype;
static GpuDatatypes dataTypeOf() { return GpuDatatypes::mat4x4; }
static size_t gpuSizeOf() { return 64; }
};
} // namespace GpuDatatypesHelper
class FreeValueView
{
protected:
unsigned char* value_;
uint32_t arrayElements_;
GpuDatatypes dataType_;
public:
FreeValueView() : value_(0), arrayElements_(0), dataType_(GpuDatatypes::none) {}
GpuDatatypes dataType() const { return dataType_; }
bool isDataCompatible(const FreeValueView& rhs) const { return (dataType_ == rhs.dataType_) && (arrayElements_ == rhs.arrayElements_); }
uint64_t dataSize() const
{
uint32_t isnone = (dataType_ == GpuDatatypes::none);
return isnone ? arrayElements_ : getCpuPackedSize(dataType_, arrayElements_);
}
uint32_t arrayElements() const { return arrayElements_; }
void* raw(uint32_t arrayIndex)
{
size_t offset = (size_t)(arrayIndex * getCpuPackedSize(dataType_));
return value_ + offset;
}
const void* raw(uint32_t arrayIndex) const
{
size_t offset = (size_t)(arrayIndex * getCpuPackedSize(dataType_));
return value_ + offset;
}
void* raw() { return value_; }
const void* raw() const { return value_; }
template<typename Type_>
Type_* rawAs()
{
return reinterpret_cast<Type_*>(value_);
}
template<typename Type_>
const Type_* rawAs() const
{
return reinterpret_cast<Type_*>(value_);
}
float* rawFloats() { return reinterpret_cast<float*>(value_); }
const float* rawFloats() const { return reinterpret_cast<const float*>(value_); }
int32_t* rawInts() { return reinterpret_cast<int32_t*>(value_); }
const int32_t* rawInts() const { return reinterpret_cast<const int32_t*>(value_); }
unsigned char* rawChars() { return value_; }
const unsigned char* rawChars() const { return value_; }
template<typename Type_>
Type_& interpretValueAs(uint32_t entryIndex = 0)
{
return reinterpret_cast<Type_*>(value_)[entryIndex];
}
template<typename Type_>
const Type_& interpretValueAs(uint32_t entryIndex = 0) const
{
return reinterpret_cast<const Type_*>(value_)[entryIndex];
}
};
struct TypedMem : public FreeValueView
{
private:
uint64_t currentSize_;
public:
TypedMem() : currentSize_(0) {}
~TypedMem() { free(FreeValueView::value_); }
void assign(const TypedMem& rhs)
{
uint64_t dataTypeSize = rhs.dataSize();
allocate(rhs.dataType_, rhs.arrayElements_);
memcpy(value_, rhs.value_, (size_t)dataTypeSize);
}
const TypedMem& operator=(const TypedMem& rhs) const
{
uint64_t dataTypeSize = rhs.dataSize();
debug_assertion(dataTypeSize <= dataSize(), "TypedMem operator=: MISMATCHED SIZE");
memcpy(value_, rhs.value_, (size_t)dataTypeSize);
return *this;
}
TypedMem(const TypedMem& rhs) : currentSize_(0)
{
uint64_t dataTypeSize = rhs.dataSize();
allocate(rhs.dataType_, rhs.arrayElements_);
memcpy(value_, rhs.value_, (size_t)dataTypeSize);
}
uint64_t totalSize() const { return currentSize_; }
void shrink(uint32_t arrayElements)
{
uint64_t dataTypeSize = (dataType_ == GpuDatatypes::none ? arrayElements : getCpuPackedSize(dataType_) * arrayElements);
arrayElements_ = arrayElements;
if (!arrayElements)
{
free(value_);
value_ = 0;
}
else if (dataTypeSize != currentSize_)
{
value_ = static_cast<unsigned char*>(realloc(value_, (size_t)dataTypeSize));
}
currentSize_ = dataTypeSize;
}
void clear()
{
dataType_ = GpuDatatypes::none;
arrayElements_ = 0;
}
void allocate(GpuDatatypes dataType, uint32_t arrayElements = 1)
{
uint32_t isnone = (dataType == GpuDatatypes::none);
uint64_t dataTypeSize = isnone * arrayElements + (1 - isnone) * getCpuPackedSize(dataType, arrayElements);
dataType_ = dataType;
arrayElements_ = arrayElements;
if (dataTypeSize > currentSize_)
{
value_ = static_cast<unsigned char*>(realloc(value_, (size_t)dataTypeSize));
currentSize_ = dataTypeSize;
}
}
template<typename Type_>
void setValue(const Type_& rawvalue)
{
allocate(GpuDatatypesHelper::Metadata<Type_>::dataTypeOf(), 1);
memcpy(value_, &rawvalue, sizeof(Type_));
}
template<typename Type_>
void setValue(const Type_& rawvalue, uint32_t arrayIndex)
{
assertion(arrayElements_ > arrayIndex,
"TypedMemory:: If array values "
"are used with this class, they must be pre-allocated");
memcpy(value_ + (arrayIndex * sizeof(Type_)), &rawvalue, sizeof(Type_));
}
template<typename Type_>
void setValues(const Type_* rawvalues, uint32_t numElements, uint32_t startArrayIndex = 0)
{
assertion(numElements > startArrayIndex, "TypedMemory:: If array values are used with this class, they must be pre-allocated");
uint32_t elementsSize = static_cast<uint32_t>(startArrayIndex * sizeof(Type_) + sizeof(Type_) * numElements);
assertion(currentSize_ >= elementsSize, "TypedMemory:: If array values are used with this class, they must be pre-allocated");
memcpy(value_ + (startArrayIndex * sizeof(Type_)), &rawvalues, sizeof(Type_) * numElements);
}
void setValue(const char* c_string_value)
{
this->dataType_ = GpuDatatypes::none;
uint32_t sz = static_cast<uint32_t>(strlen(c_string_value));
allocate(GpuDatatypes::none, sz + 1);
memcpy(value_, c_string_value, sz);
value_[sz] = 0;
}
void setValue(const std::string& rawvalue) { setValue(rawvalue.c_str()); }
};
struct FreeValue : public FreeValueView
{
private:
union
{
double _alignment_[8];
unsigned char chars_[64];
int32_t integer32_[16];
float float32_[16];
int16_t int16_[16];
int64_t int64_[8];
};
public:
FreeValue()
{
value_ = chars_;
arrayElements_ = 1;
}
template<typename Type_>
FreeValue(const Type_& rawvalue) : FreeValue()
{
setValue(rawvalue);
}
void setDataType(GpuDatatypes datatype) { dataType_ = datatype; }
template<typename Type_>
void setValue(const Type_& rawvalue)
{
this->dataType_ = GpuDatatypesHelper::Metadata<Type_>::dataTypeOf();
memcpy(this->chars_, &rawvalue, sizeof(Type_));
}
void setValue(FreeValueView& other)
{
dataType_ = other.dataType();
memcpy(chars_, other.raw(), (size_t)std::min(other.dataSize(), static_cast<uint64_t>(sizeof(chars_))));
}
void setValue(const char* c_string_value)
{
this->dataType_ = GpuDatatypes::none;
size_t sz = strlen(c_string_value);
memcpy(chars_, c_string_value, (size_t)std::min(sz, sizeof(chars_)));
chars_[63] = 0;
}
void setValue(const std::string& rawvalue)
{
this->dataType_ = GpuDatatypes::none;
memcpy(chars_, rawvalue.c_str(), std::min(sizeof(chars_), (size_t)rawvalue.length()));
chars_[63] = 0;
}
void fastSet(GpuDatatypes type, char* value)
{
this->dataType_ = type;
memcpy(this->chars_, value, (size_t)std::min(static_cast<uint64_t>(64), getSize(type)));
}
template<typename Type_>
Type_& interpretValueAs()
{
return *reinterpret_cast<Type_*>(chars_);
}
template<typename Type_>
const Type_& interpretValueAs() const
{
return *reinterpret_cast<const Type_*>(chars_);
}
template<typename Type_>
Type_ castValueScalarToScalar() const
{
switch (dataType_)
{
case GpuDatatypes::Float: return Type_(interpretValueAs<GpuDatatypesHelper::Metadata<float>::storagetype>());
case GpuDatatypes::Integer: return Type_(interpretValueAs<GpuDatatypesHelper::Metadata<int32_t>::storagetype>());
default: Log("FreeValue: Tried to interpret matrix, std::string or vector value as scalar."); return Type_();
}
}
template<typename Type_>
Type_ castValueVectorToVector() const
{
switch (dataType_)
{
case GpuDatatypes::vec2: return Type_(interpretValueAs<GpuDatatypesHelper::Metadata<glm::vec2>::storagetype>());
case GpuDatatypes::vec3: return Type_(interpretValueAs<GpuDatatypesHelper::Metadata<glm::vec3>::storagetype>());
case GpuDatatypes::vec4: return Type_(interpretValueAs<GpuDatatypesHelper::Metadata<glm::vec4>::storagetype>());
case GpuDatatypes::ivec2: return Type_(interpretValueAs<GpuDatatypesHelper::Metadata<glm::ivec2>::storagetype>());
case GpuDatatypes::ivec3: return Type_(interpretValueAs<GpuDatatypesHelper::Metadata<glm::ivec3>::storagetype>());
case GpuDatatypes::ivec4: return Type_(interpretValueAs<GpuDatatypesHelper::Metadata<glm::ivec4>::storagetype>());
default: Log("FreeValue: Tried to interpret matrix, std::string or scalar value as vector."); return Type_();
}
}
template<typename Type_>
Type_ castValueMatrixToMatrix() const
{
switch (dataType_)
{
case GpuDatatypes::mat2x2: return Type_(interpretValueAs<GpuDatatypesHelper::Metadata<glm::mat2x2>::storagetype>());
case GpuDatatypes::mat2x3: return Type_(interpretValueAs<GpuDatatypesHelper::Metadata<glm::mat2x3>::storagetype>());
case GpuDatatypes::mat2x4: return Type_(interpretValueAs<GpuDatatypesHelper::Metadata<glm::mat2x4>::storagetype>());
case GpuDatatypes::mat3x2: return Type_(interpretValueAs<GpuDatatypesHelper::Metadata<glm::mat3x2>::storagetype>());
case GpuDatatypes::mat3x3: return Type_(interpretValueAs<GpuDatatypesHelper::Metadata<glm::mat3x3>::storagetype>());
case GpuDatatypes::mat3x4: return Type_(interpretValueAs<GpuDatatypesHelper::Metadata<glm::mat3x4>::storagetype>());
case GpuDatatypes::mat4x2: return Type_(interpretValueAs<GpuDatatypesHelper::Metadata<glm::mat4x2>::storagetype>());
case GpuDatatypes::mat4x3: return Type_(interpretValueAs<GpuDatatypesHelper::Metadata<glm::mat4x3>::storagetype>());
case GpuDatatypes::mat4x4: return Type_(interpretValueAs<GpuDatatypesHelper::Metadata<glm::mat4x4>::storagetype>());
default: Log("FreeValue: Tried to interpret vector, std::string or scalar value as matrix."); return Type_();
}
}
const char* getValueAsString() const
{
switch (dataType_)
{
case GpuDatatypes::none: return reinterpret_cast<const char*>(chars_);
default: Log("FreeValue: Tried to interpret vector, matrix or scalar value as std::string."); return "";
}
}
};
} // namespace pvr