Add FieldOffsets class
This commit is contained in:
parent
7736312c2f
commit
7fd3264d08
|
|
@ -309,6 +309,40 @@ namespace Nz
|
|||
SamplerWrap_Max = SamplerWrap_Repeat
|
||||
};
|
||||
|
||||
enum StructFieldType
|
||||
{
|
||||
StructFieldType_Bool1,
|
||||
StructFieldType_Bool2,
|
||||
StructFieldType_Bool3,
|
||||
StructFieldType_Bool4,
|
||||
StructFieldType_Float1,
|
||||
StructFieldType_Float2,
|
||||
StructFieldType_Float3,
|
||||
StructFieldType_Float4,
|
||||
StructFieldType_Double1,
|
||||
StructFieldType_Double2,
|
||||
StructFieldType_Double3,
|
||||
StructFieldType_Double4,
|
||||
StructFieldType_Int1,
|
||||
StructFieldType_Int2,
|
||||
StructFieldType_Int3,
|
||||
StructFieldType_Int4,
|
||||
StructFieldType_UInt1,
|
||||
StructFieldType_UInt2,
|
||||
StructFieldType_UInt3,
|
||||
StructFieldType_UInt4,
|
||||
|
||||
StructFieldType_Max = StructFieldType_UInt4
|
||||
};
|
||||
|
||||
enum StructLayout
|
||||
{
|
||||
StructLayout_Packed,
|
||||
StructLayout_Std140,
|
||||
|
||||
StructLayout_Max = StructLayout_Std140
|
||||
};
|
||||
|
||||
enum StencilOperation
|
||||
{
|
||||
StencilOperation_Decrement,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright (C) 2019 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Utility module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_FIELDOFFSETS_HPP
|
||||
#define NAZARA_FIELDOFFSETS_HPP
|
||||
|
||||
#include <Nazara/Utility/Config.hpp>
|
||||
#include <Nazara/Utility/Enums.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_UTILITY_API FieldOffsets
|
||||
{
|
||||
public:
|
||||
inline FieldOffsets(StructLayout layout);
|
||||
FieldOffsets(const FieldOffsets&) = default;
|
||||
FieldOffsets(FieldOffsets&&) = default;
|
||||
~FieldOffsets() = default;
|
||||
|
||||
std::size_t AddField(StructFieldType type);
|
||||
std::size_t AddFieldArray(StructFieldType type, std::size_t arraySize);
|
||||
std::size_t AddMatrix(StructFieldType cellType, unsigned int columns, unsigned int rows, bool columnMajor);
|
||||
std::size_t AddMatrixArray(StructFieldType cellType, unsigned int columns, unsigned int rows, bool columnMajor, std::size_t arraySize);
|
||||
std::size_t AddStruct(const FieldOffsets& fieldStruct);
|
||||
std::size_t AddStructArray(const FieldOffsets& fieldStruct, std::size_t arraySize);
|
||||
|
||||
inline std::size_t GetLargestFieldAlignement() const;
|
||||
inline std::size_t GetSize() const;
|
||||
|
||||
FieldOffsets& operator=(const FieldOffsets&) = default;
|
||||
FieldOffsets& operator=(FieldOffsets&&) = default;
|
||||
|
||||
static std::size_t GetAlignement(StructLayout layout, StructFieldType fieldType);
|
||||
static std::size_t GetCount(StructFieldType fieldType);
|
||||
static std::size_t GetSize(StructFieldType fieldType);
|
||||
|
||||
private:
|
||||
static inline std::size_t Align(std::size_t source, std::size_t alignment);
|
||||
|
||||
std::size_t m_largestFieldAlignment;
|
||||
std::size_t m_offsetRounding;
|
||||
std::size_t m_size;
|
||||
StructLayout m_layout;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Utility/FieldOffsets.inl>
|
||||
|
||||
#endif // NAZARA_FIELDOFFSETS_HPP
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
// Copyright (C) 2019 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Utility module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Utility/FieldOffsets.hpp>
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <Nazara/Utility/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline FieldOffsets::FieldOffsets(StructLayout layout) :
|
||||
m_largestFieldAlignment(1),
|
||||
m_offsetRounding(1),
|
||||
m_size(0),
|
||||
m_layout(layout)
|
||||
{
|
||||
}
|
||||
|
||||
inline std::size_t FieldOffsets::GetLargestFieldAlignement() const
|
||||
{
|
||||
return m_largestFieldAlignment;
|
||||
}
|
||||
|
||||
inline std::size_t FieldOffsets::GetSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
inline std::size_t FieldOffsets::GetAlignement(StructLayout layout, StructFieldType fieldType)
|
||||
{
|
||||
switch (layout)
|
||||
{
|
||||
case StructLayout_Packed:
|
||||
return 1;
|
||||
|
||||
case StructLayout_Std140:
|
||||
{
|
||||
switch (fieldType)
|
||||
{
|
||||
case StructFieldType_Bool1:
|
||||
case StructFieldType_Float1:
|
||||
case StructFieldType_Int1:
|
||||
case StructFieldType_UInt1:
|
||||
return 4;
|
||||
|
||||
case StructFieldType_Bool2:
|
||||
case StructFieldType_Float2:
|
||||
case StructFieldType_Int2:
|
||||
case StructFieldType_UInt2:
|
||||
return 2 * 4;
|
||||
|
||||
case StructFieldType_Bool3:
|
||||
case StructFieldType_Float3:
|
||||
case StructFieldType_Int3:
|
||||
case StructFieldType_UInt3:
|
||||
case StructFieldType_Bool4:
|
||||
case StructFieldType_Float4:
|
||||
case StructFieldType_Int4:
|
||||
case StructFieldType_UInt4:
|
||||
return 4 * 4;
|
||||
|
||||
case StructFieldType_Double1:
|
||||
return 8;
|
||||
|
||||
case StructFieldType_Double2:
|
||||
return 2 * 8;
|
||||
|
||||
case StructFieldType_Double3:
|
||||
case StructFieldType_Double4:
|
||||
return 4 * 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline std::size_t FieldOffsets::GetCount(StructFieldType fieldType)
|
||||
{
|
||||
switch (fieldType)
|
||||
{
|
||||
case StructFieldType_Bool1:
|
||||
case StructFieldType_Double1:
|
||||
case StructFieldType_Float1:
|
||||
case StructFieldType_Int1:
|
||||
case StructFieldType_UInt1:
|
||||
return 1;
|
||||
|
||||
case StructFieldType_Bool2:
|
||||
case StructFieldType_Double2:
|
||||
case StructFieldType_Float2:
|
||||
case StructFieldType_Int2:
|
||||
case StructFieldType_UInt2:
|
||||
return 2;
|
||||
|
||||
case StructFieldType_Bool3:
|
||||
case StructFieldType_Double3:
|
||||
case StructFieldType_Float3:
|
||||
case StructFieldType_Int3:
|
||||
case StructFieldType_UInt3:
|
||||
return 3;
|
||||
|
||||
case StructFieldType_Bool4:
|
||||
case StructFieldType_Double4:
|
||||
case StructFieldType_Float4:
|
||||
case StructFieldType_Int4:
|
||||
case StructFieldType_UInt4:
|
||||
return 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline std::size_t FieldOffsets::GetSize(StructFieldType fieldType)
|
||||
{
|
||||
switch (fieldType)
|
||||
{
|
||||
case StructFieldType_Bool1:
|
||||
case StructFieldType_Float1:
|
||||
case StructFieldType_Int1:
|
||||
case StructFieldType_UInt1:
|
||||
return 4;
|
||||
|
||||
case StructFieldType_Bool2:
|
||||
case StructFieldType_Float2:
|
||||
case StructFieldType_Int2:
|
||||
case StructFieldType_UInt2:
|
||||
return 2 * 4;
|
||||
|
||||
case StructFieldType_Bool3:
|
||||
case StructFieldType_Float3:
|
||||
case StructFieldType_Int3:
|
||||
case StructFieldType_UInt3:
|
||||
return 3 * 4;
|
||||
|
||||
case StructFieldType_Bool4:
|
||||
case StructFieldType_Float4:
|
||||
case StructFieldType_Int4:
|
||||
case StructFieldType_UInt4:
|
||||
return 4 * 4;
|
||||
|
||||
case StructFieldType_Double1:
|
||||
return 8;
|
||||
|
||||
case StructFieldType_Double2:
|
||||
return 2 * 8;
|
||||
|
||||
case StructFieldType_Double3:
|
||||
return 3 * 8;
|
||||
|
||||
case StructFieldType_Double4:
|
||||
return 4 * 8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline std::size_t FieldOffsets::Align(std::size_t source, std::size_t alignment)
|
||||
{
|
||||
if (source == 0)
|
||||
return source;
|
||||
|
||||
assert(alignment > 0);
|
||||
return ((source + alignment - 1) / alignment) * alignment;
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/Utility/DebugOff.hpp>
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
// Copyright (C) 2019 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Utility module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Utility/FieldOffsets.hpp>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <Nazara/Utility/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
std::size_t FieldOffsets::AddField(StructFieldType type)
|
||||
{
|
||||
std::size_t fieldAlignement = GetAlignement(m_layout, type);
|
||||
|
||||
m_largestFieldAlignment = std::max(m_largestFieldAlignment, fieldAlignement);
|
||||
|
||||
std::size_t offset = Align(m_size, Align(fieldAlignement, m_offsetRounding));
|
||||
m_size = offset + GetSize(type);
|
||||
|
||||
m_offsetRounding = 1;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
std::size_t FieldOffsets::AddFieldArray(StructFieldType type, std::size_t arraySize)
|
||||
{
|
||||
std::size_t fieldAlignement = GetAlignement(m_layout, type);
|
||||
if (m_layout == StructLayout_Std140)
|
||||
fieldAlignement = Align(fieldAlignement, GetAlignement(StructLayout_Std140, StructFieldType_Float4));
|
||||
|
||||
m_largestFieldAlignment = std::max(fieldAlignement, m_largestFieldAlignment);
|
||||
|
||||
std::size_t offset = Align(m_size, Align(fieldAlignement, m_offsetRounding));
|
||||
m_size = offset + GetSize(type) * arraySize;
|
||||
|
||||
m_offsetRounding = 1;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
std::size_t FieldOffsets::AddMatrix(StructFieldType cellType, unsigned int columns, unsigned int rows, bool columnMajor)
|
||||
{
|
||||
assert(GetCount(cellType) == 1);
|
||||
assert(columns >= 2 && columns <= 4);
|
||||
assert(rows >= 2 && rows <= 4);
|
||||
|
||||
if (columnMajor)
|
||||
return AddFieldArray(static_cast<StructFieldType>(cellType + rows - 1), columns);
|
||||
else
|
||||
return AddFieldArray(static_cast<StructFieldType>(cellType + columns - 1), rows);
|
||||
}
|
||||
|
||||
std::size_t FieldOffsets::AddMatrixArray(StructFieldType cellType, unsigned int columns, unsigned int rows, bool columnMajor, std::size_t arraySize)
|
||||
{
|
||||
assert(GetCount(cellType) == 1);
|
||||
assert(columns >= 2 && columns <= 4);
|
||||
assert(rows >= 2 && rows <= 4);
|
||||
|
||||
if (columnMajor)
|
||||
return AddFieldArray(static_cast<StructFieldType>(cellType + rows - 1), columns * arraySize);
|
||||
else
|
||||
return AddFieldArray(static_cast<StructFieldType>(cellType + columns - 1), rows * arraySize);
|
||||
}
|
||||
|
||||
std::size_t FieldOffsets::AddStruct(const FieldOffsets& fieldStruct)
|
||||
{
|
||||
std::size_t fieldAlignement = fieldStruct.GetLargestFieldAlignement();
|
||||
if (m_layout == StructLayout_Std140)
|
||||
fieldAlignement = Align(fieldAlignement, GetAlignement(StructLayout_Std140, StructFieldType_Float4));
|
||||
|
||||
m_largestFieldAlignment = std::max(m_largestFieldAlignment, fieldAlignement);
|
||||
|
||||
std::size_t offset = Align(m_size, Align(fieldAlignement, m_offsetRounding));
|
||||
m_size = offset + fieldStruct.GetSize();
|
||||
|
||||
m_offsetRounding = std::max<std::size_t>(Align(fieldStruct.GetSize(), fieldAlignement) - fieldStruct.GetSize(), 1);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
std::size_t FieldOffsets::AddStructArray(const FieldOffsets& fieldStruct, std::size_t arraySize)
|
||||
{
|
||||
assert(arraySize > 0);
|
||||
|
||||
std::size_t fieldAlignement = fieldStruct.GetLargestFieldAlignement();
|
||||
if (m_layout == StructLayout_Std140)
|
||||
fieldAlignement = Align(fieldAlignement, GetAlignement(StructLayout_Std140, StructFieldType_Float4));
|
||||
|
||||
m_largestFieldAlignment = std::max(m_largestFieldAlignment, fieldAlignement);
|
||||
|
||||
std::size_t offset = Align(m_size, Align(fieldAlignement, m_offsetRounding));
|
||||
m_size = offset
|
||||
+ fieldStruct.GetSize() * arraySize
|
||||
+ (Align(fieldStruct.GetSize(), fieldAlignement) - fieldStruct.GetSize()) * (arraySize - 1);
|
||||
|
||||
m_offsetRounding = fieldAlignement;
|
||||
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue