557 lines
14 KiB
C++
557 lines
14 KiB
C++
// FastNoiseSIMD.cpp
|
|
//
|
|
// MIT License
|
|
//
|
|
// Copyright(c) 2017 Jordan Peck
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files(the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions :
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in all
|
|
// copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
// SOFTWARE.
|
|
//
|
|
// The developer's email is jorzixdan.me2@gzixmail.com (for great email, take
|
|
// off every 'zix'.)
|
|
//
|
|
|
|
#include "FastNoiseSIMD.h"
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <algorithm>
|
|
#include <cstdint>
|
|
|
|
#ifdef FN_COMPILE_NO_SIMD_FALLBACK
|
|
#define SIMD_LEVEL_H FN_NO_SIMD_FALLBACK
|
|
#include "FastNoiseSIMD_internal.h"
|
|
#endif
|
|
|
|
#ifdef FN_COMPILE_SSE2
|
|
#define SIMD_LEVEL_H FN_SSE2
|
|
#include "FastNoiseSIMD_internal.h"
|
|
#endif
|
|
|
|
#ifdef FN_COMPILE_SSE41
|
|
#define SIMD_LEVEL_H FN_SSE41
|
|
#include "FastNoiseSIMD_internal.h"
|
|
#endif
|
|
|
|
#ifdef FN_COMPILE_AVX2
|
|
#define SIMD_LEVEL_H FN_AVX2
|
|
#include "FastNoiseSIMD_internal.h"
|
|
#endif
|
|
|
|
#ifdef FN_COMPILE_AVX512
|
|
#define SIMD_LEVEL_H FN_AVX512
|
|
#include "FastNoiseSIMD_internal.h"
|
|
#endif
|
|
|
|
#ifdef FN_COMPILE_NEON
|
|
#define SIMD_LEVEL_H FN_NEON
|
|
#include "FastNoiseSIMD_internal.h"
|
|
#endif
|
|
|
|
// CPUid
|
|
#ifdef _WIN32
|
|
#include <intrin.h>
|
|
#elif defined(FN_ARM)
|
|
#if !defined(__aarch64__) && !defined(FN_IOS)
|
|
#include "ARM/cpu-features.h"
|
|
#endif
|
|
#else
|
|
#include <cpuid.h>
|
|
#include "inttypes.h"
|
|
#endif
|
|
|
|
int FastNoiseSIMD::s_currentSIMDLevel = -1;
|
|
|
|
#ifdef FN_ARM
|
|
int GetFastestSIMD()
|
|
{
|
|
#if defined(__aarch64__) || defined(FN_IOS)
|
|
return FN_NEON;
|
|
#else
|
|
if (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM)
|
|
{
|
|
auto cpuFeatures = android_getCpuFeatures();
|
|
|
|
if (cpuFeatures & ANDROID_CPU_ARM_FEATURE_NEON)
|
|
#ifdef FN_USE_FMA
|
|
if (cpuFeatures & ANDROID_CPU_ARM_FEATURE_NEON_FMA)
|
|
#endif
|
|
return FN_NEON;
|
|
}
|
|
|
|
return FN_NO_SIMD_FALLBACK;
|
|
#endif
|
|
}
|
|
#else
|
|
|
|
#ifdef _WIN32
|
|
void cpuid(int32_t out[4], int32_t x) {
|
|
__cpuidex(out, x, 0);
|
|
}
|
|
uint64_t xgetbv(unsigned int x) {
|
|
return _xgetbv(x);
|
|
}
|
|
#else
|
|
void cpuid(int32_t out[4], int32_t x) {
|
|
__cpuid_count(x, 0, out[0], out[1], out[2], out[3]);
|
|
}
|
|
uint64_t xgetbv(unsigned int index) {
|
|
uint32_t eax, edx;
|
|
__asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index));
|
|
return ((uint64_t)edx << 32) | eax;
|
|
}
|
|
#define _XCR_XFEATURE_ENABLED_MASK 0
|
|
#endif
|
|
|
|
int GetFastestSIMD()
|
|
{
|
|
//https://github.com/Mysticial/FeatureDetector
|
|
|
|
int cpuInfo[4];
|
|
|
|
cpuid(cpuInfo, 0);
|
|
int nIds = cpuInfo[0];
|
|
|
|
if (nIds < 0x00000001)
|
|
return FN_NO_SIMD_FALLBACK;
|
|
|
|
cpuid(cpuInfo, 0x00000001);
|
|
|
|
// SSE2
|
|
if ((cpuInfo[3] & 1 << 26) == 0)
|
|
return FN_NO_SIMD_FALLBACK;
|
|
|
|
// SSE41
|
|
if ((cpuInfo[2] & 1 << 19) == 0)
|
|
return FN_SSE2;
|
|
|
|
// AVX
|
|
bool cpuXSaveSuport = (cpuInfo[2] & 1 << 26) != 0;
|
|
bool osAVXSuport = (cpuInfo[2] & 1 << 27) != 0;
|
|
bool cpuAVXSuport = (cpuInfo[2] & 1 << 28) != 0;
|
|
|
|
if (cpuXSaveSuport && osAVXSuport && cpuAVXSuport)
|
|
{
|
|
uint64_t xcrFeatureMask = xgetbv(_XCR_XFEATURE_ENABLED_MASK);
|
|
if ((xcrFeatureMask & 0x6) != 0x6)
|
|
return FN_SSE41;
|
|
}
|
|
else
|
|
return FN_SSE41;
|
|
|
|
// AVX2 FMA3
|
|
if (nIds < 0x00000007)
|
|
return FN_SSE41;
|
|
|
|
#ifdef FN_USE_FMA
|
|
bool cpuFMA3Support = (cpuInfo[2] & 1 << 12) != 0;
|
|
#else
|
|
bool cpuFMA3Support = true;
|
|
#endif
|
|
|
|
cpuid(cpuInfo, 0x00000007);
|
|
|
|
bool cpuAVX2Support = (cpuInfo[1] & 1 << 5) != 0;
|
|
|
|
if (!cpuFMA3Support || !cpuAVX2Support)
|
|
return FN_SSE41;
|
|
|
|
// AVX512
|
|
bool cpuAVX512Support = (cpuInfo[1] & 1 << 16) != 0;
|
|
bool oxAVX512Support = (xgetbv(_XCR_XFEATURE_ENABLED_MASK) & 0xe6) == 0xe6;
|
|
|
|
if (!cpuAVX512Support || !oxAVX512Support)
|
|
return FN_AVX2;
|
|
|
|
return FN_AVX512;
|
|
}
|
|
#endif
|
|
|
|
FastNoiseSIMD* FastNoiseSIMD::NewFastNoiseSIMD(int seed)
|
|
{
|
|
GetSIMDLevel();
|
|
|
|
#ifdef FN_COMPILE_NEON
|
|
#ifdef FN_COMPILE_NO_SIMD_FALLBACK
|
|
if (s_currentSIMDLevel >= FN_NEON)
|
|
#endif
|
|
return new FastNoiseSIMD_internal::FASTNOISE_SIMD_CLASS(FN_NEON)(seed);
|
|
#endif
|
|
|
|
#ifdef FN_COMPILE_AVX512
|
|
if (s_currentSIMDLevel >= FN_AVX512)
|
|
return new FastNoiseSIMD_internal::FASTNOISE_SIMD_CLASS(FN_AVX512)(seed);
|
|
#endif
|
|
|
|
#ifdef FN_COMPILE_AVX2
|
|
if (s_currentSIMDLevel >= FN_AVX2)
|
|
return new FastNoiseSIMD_internal::FASTNOISE_SIMD_CLASS(FN_AVX2)(seed);
|
|
#endif
|
|
|
|
#ifdef FN_COMPILE_SSE41
|
|
if (s_currentSIMDLevel >= FN_SSE41)
|
|
return new FastNoiseSIMD_internal::FASTNOISE_SIMD_CLASS(FN_SSE41)(seed);
|
|
#endif
|
|
|
|
#ifdef FN_COMPILE_SSE2
|
|
#ifdef FN_COMPILE_NO_SIMD_FALLBACK
|
|
if (s_currentSIMDLevel >= FN_SSE2)
|
|
#endif
|
|
return new FastNoiseSIMD_internal::FASTNOISE_SIMD_CLASS(FN_SSE2)(seed);
|
|
#endif
|
|
|
|
#ifdef FN_COMPILE_NO_SIMD_FALLBACK
|
|
return new FastNoiseSIMD_internal::FASTNOISE_SIMD_CLASS(FN_NO_SIMD_FALLBACK)(seed);
|
|
#endif
|
|
}
|
|
|
|
int FastNoiseSIMD::GetSIMDLevel()
|
|
{
|
|
if (s_currentSIMDLevel < 0)
|
|
s_currentSIMDLevel = GetFastestSIMD();
|
|
|
|
return s_currentSIMDLevel;
|
|
}
|
|
|
|
void FastNoiseSIMD::FreeNoiseSet(float* floatArray)
|
|
{
|
|
#ifdef FN_ALIGNED_SETS
|
|
GetSIMDLevel();
|
|
|
|
if (s_currentSIMDLevel > FN_NO_SIMD_FALLBACK)
|
|
#ifdef _WIN32
|
|
_aligned_free(floatArray);
|
|
#else
|
|
free(floatArray);
|
|
#endif
|
|
else
|
|
#endif
|
|
delete[] floatArray;
|
|
}
|
|
|
|
int FastNoiseSIMD::AlignedSize(int size)
|
|
{
|
|
#ifdef FN_ALIGNED_SETS
|
|
GetSIMDLevel();
|
|
|
|
#ifdef FN_COMPILE_NEON
|
|
if (s_currentSIMDLevel >= FN_NEON)
|
|
return FastNoiseSIMD_internal::FASTNOISE_SIMD_CLASS(FN_NEON)::AlignedSize(size);
|
|
#endif
|
|
|
|
#ifdef FN_COMPILE_AVX512
|
|
if (s_currentSIMDLevel >= FN_AVX512)
|
|
return FastNoiseSIMD_internal::FASTNOISE_SIMD_CLASS(FN_AVX512)::AlignedSize(size);
|
|
#endif
|
|
|
|
#ifdef FN_COMPILE_AVX2
|
|
if (s_currentSIMDLevel >= FN_AVX2)
|
|
return FastNoiseSIMD_internal::FASTNOISE_SIMD_CLASS(FN_AVX2)::AlignedSize(size);
|
|
#endif
|
|
|
|
#ifdef FN_COMPILE_SSE2
|
|
if (s_currentSIMDLevel >= FN_SSE2)
|
|
return FastNoiseSIMD_internal::FASTNOISE_SIMD_CLASS(FN_SSE2)::AlignedSize(size);
|
|
#endif
|
|
#endif
|
|
return size;
|
|
}
|
|
|
|
float* FastNoiseSIMD::GetEmptySet(int size)
|
|
{
|
|
#ifdef FN_ALIGNED_SETS
|
|
GetSIMDLevel();
|
|
|
|
#ifdef FN_COMPILE_NEON
|
|
if (s_currentSIMDLevel >= FN_NEON)
|
|
return FastNoiseSIMD_internal::FASTNOISE_SIMD_CLASS(FN_NEON)::GetEmptySet(size);
|
|
#endif
|
|
|
|
#ifdef FN_COMPILE_AVX512
|
|
if (s_currentSIMDLevel >= FN_AVX512)
|
|
return FastNoiseSIMD_internal::FASTNOISE_SIMD_CLASS(FN_AVX512)::GetEmptySet(size);
|
|
#endif
|
|
|
|
#ifdef FN_COMPILE_AVX2
|
|
if (s_currentSIMDLevel >= FN_AVX2)
|
|
return FastNoiseSIMD_internal::FASTNOISE_SIMD_CLASS(FN_AVX2)::GetEmptySet(size);
|
|
#endif
|
|
|
|
#ifdef FN_COMPILE_SSE2
|
|
if (s_currentSIMDLevel >= FN_SSE2)
|
|
return FastNoiseSIMD_internal::FASTNOISE_SIMD_CLASS(FN_SSE2)::GetEmptySet(size);
|
|
#endif
|
|
#endif
|
|
return new float[size];
|
|
}
|
|
|
|
FastNoiseVectorSet* FastNoiseSIMD::GetVectorSet(int xSize, int ySize, int zSize)
|
|
{
|
|
FastNoiseVectorSet* vectorSet = new FastNoiseVectorSet();
|
|
FillVectorSet(vectorSet, xSize, ySize, zSize);
|
|
return vectorSet;
|
|
}
|
|
|
|
void FastNoiseSIMD::FillVectorSet(FastNoiseVectorSet* vectorSet, int xSize, int ySize, int zSize)
|
|
{
|
|
assert(vectorSet);
|
|
|
|
vectorSet->SetSize(xSize*ySize*zSize);
|
|
vectorSet->sampleScale = 0;
|
|
|
|
int index = 0;
|
|
|
|
for (int ix = 0; ix < xSize; ix++)
|
|
{
|
|
for (int iy = 0; iy < ySize; iy++)
|
|
{
|
|
for (int iz = 0; iz < zSize; iz++)
|
|
{
|
|
vectorSet->xSet[index] = float(ix);
|
|
vectorSet->ySet[index] = float(iy);
|
|
vectorSet->zSet[index] = float(iz);
|
|
index++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
FastNoiseVectorSet* FastNoiseSIMD::GetSamplingVectorSet(int sampleScale, int xSize, int ySize, int zSize)
|
|
{
|
|
FastNoiseVectorSet* vectorSet = new FastNoiseVectorSet();
|
|
FillSamplingVectorSet(vectorSet, sampleScale, xSize, ySize, zSize);
|
|
return vectorSet;
|
|
}
|
|
|
|
void FastNoiseSIMD::FillSamplingVectorSet(FastNoiseVectorSet* vectorSet, int sampleScale, int xSize, int ySize, int zSize)
|
|
{
|
|
assert(vectorSet);
|
|
|
|
if (sampleScale <= 0)
|
|
{
|
|
FillVectorSet(vectorSet, xSize, ySize, zSize);
|
|
return;
|
|
}
|
|
|
|
vectorSet->sampleSizeX = xSize;
|
|
vectorSet->sampleSizeY = ySize;
|
|
vectorSet->sampleSizeZ = zSize;
|
|
|
|
int sampleSize = 1 << sampleScale;
|
|
int sampleMask = sampleSize - 1;
|
|
|
|
int xSizeSample = xSize;
|
|
int ySizeSample = ySize;
|
|
int zSizeSample = zSize;
|
|
|
|
if (xSizeSample & sampleMask)
|
|
xSizeSample = (xSizeSample & ~sampleMask) + sampleSize;
|
|
|
|
if (ySizeSample & sampleMask)
|
|
ySizeSample = (ySizeSample & ~sampleMask) + sampleSize;
|
|
|
|
if (zSizeSample & sampleMask)
|
|
zSizeSample = (zSizeSample & ~sampleMask) + sampleSize;
|
|
|
|
xSizeSample = (xSizeSample >> sampleScale) + 1;
|
|
ySizeSample = (ySizeSample >> sampleScale) + 1;
|
|
zSizeSample = (zSizeSample >> sampleScale) + 1;
|
|
|
|
vectorSet->SetSize(xSizeSample*ySizeSample*zSizeSample);
|
|
vectorSet->sampleScale = sampleScale;
|
|
|
|
int index = 0;
|
|
|
|
for (int ix = 0; ix < xSizeSample; ix++)
|
|
{
|
|
for (int iy = 0; iy < ySizeSample; iy++)
|
|
{
|
|
for (int iz = 0; iz < zSizeSample; iz++)
|
|
{
|
|
vectorSet->xSet[index] = float(ix*sampleSize);
|
|
vectorSet->ySet[index] = float(iy*sampleSize);
|
|
vectorSet->zSet[index] = float(iz*sampleSize);
|
|
index++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
float* FastNoiseSIMD::GetNoiseSet(int xStart, int yStart, int zStart, int xSize, int ySize, int zSize, float scaleModifier)
|
|
{
|
|
float* noiseSet = GetEmptySet(xSize, ySize, zSize);
|
|
|
|
FillNoiseSet(noiseSet, xStart, yStart, zStart, xSize, ySize, zSize, scaleModifier);
|
|
|
|
return noiseSet;
|
|
}
|
|
|
|
void FastNoiseSIMD::FillNoiseSet(float* noiseSet, int xStart, int yStart, int zStart, int xSize, int ySize, int zSize, float scaleModifier)
|
|
{
|
|
switch (m_noiseType)
|
|
{
|
|
case Value:
|
|
FillValueSet(noiseSet, xStart, yStart, zStart, xSize, ySize, zSize, scaleModifier);
|
|
break;
|
|
case ValueFractal:
|
|
FillValueFractalSet(noiseSet, xStart, yStart, zStart, xSize, ySize, zSize, scaleModifier);
|
|
break;
|
|
case Perlin:
|
|
FillPerlinSet(noiseSet, xStart, yStart, zStart, xSize, ySize, zSize, scaleModifier);
|
|
break;
|
|
case PerlinFractal:
|
|
FillPerlinFractalSet(noiseSet, xStart, yStart, zStart, xSize, ySize, zSize, scaleModifier);
|
|
break;
|
|
case Simplex:
|
|
FillSimplexSet(noiseSet, xStart, yStart, zStart, xSize, ySize, zSize, scaleModifier);
|
|
break;
|
|
case SimplexFractal:
|
|
FillSimplexFractalSet(noiseSet, xStart, yStart, zStart, xSize, ySize, zSize, scaleModifier);
|
|
break;
|
|
case WhiteNoise:
|
|
FillWhiteNoiseSet(noiseSet, xStart, yStart, zStart, xSize, ySize, zSize, scaleModifier);
|
|
break;
|
|
case Cellular:
|
|
FillCellularSet(noiseSet, xStart, yStart, zStart, xSize, ySize, zSize, scaleModifier);
|
|
break;
|
|
case Cubic:
|
|
FillCubicSet(noiseSet, xStart, yStart, zStart, xSize, ySize, zSize, scaleModifier);
|
|
break;
|
|
case CubicFractal:
|
|
FillCubicFractalSet(noiseSet, xStart, yStart, zStart, xSize, ySize, zSize, scaleModifier);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void FastNoiseSIMD::FillNoiseSet(float* noiseSet, FastNoiseVectorSet* vectorSet, float xOffset, float yOffset, float zOffset)
|
|
{
|
|
switch (m_noiseType)
|
|
{
|
|
case Value:
|
|
FillValueSet(noiseSet, vectorSet, xOffset, yOffset, zOffset);
|
|
break;
|
|
case ValueFractal:
|
|
FillValueFractalSet(noiseSet, vectorSet, xOffset, yOffset, zOffset);
|
|
break;
|
|
case Perlin:
|
|
FillPerlinSet(noiseSet, vectorSet, xOffset, yOffset, zOffset);
|
|
break;
|
|
case PerlinFractal:
|
|
FillPerlinFractalSet(noiseSet, vectorSet, xOffset, yOffset, zOffset);
|
|
break;
|
|
case Simplex:
|
|
FillSimplexSet(noiseSet, vectorSet, xOffset, yOffset, zOffset);
|
|
break;
|
|
case SimplexFractal:
|
|
FillSimplexFractalSet(noiseSet, vectorSet, xOffset, yOffset, zOffset);
|
|
break;
|
|
case WhiteNoise:
|
|
FillWhiteNoiseSet(noiseSet, vectorSet, xOffset, yOffset, zOffset);
|
|
break;
|
|
case Cellular:
|
|
FillCellularSet(noiseSet, vectorSet, xOffset, yOffset, zOffset);
|
|
break;
|
|
case Cubic:
|
|
FillCubicSet(noiseSet, vectorSet, xOffset, yOffset, zOffset);
|
|
break;
|
|
case CubicFractal:
|
|
FillCubicFractalSet(noiseSet, vectorSet, xOffset, yOffset, zOffset);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
float* FastNoiseSIMD::GetSampledNoiseSet(int xStart, int yStart, int zStart, int xSize, int ySize, int zSize, int sampleScale)
|
|
{
|
|
float* noiseSet = GetEmptySet(xSize, ySize, zSize);
|
|
|
|
FillSampledNoiseSet(noiseSet, xStart, yStart, zStart, xSize, ySize, zSize, sampleScale);
|
|
|
|
return noiseSet;
|
|
}
|
|
|
|
#define GET_SET(f) \
|
|
float* FastNoiseSIMD::Get##f##Set(int xStart, int yStart, int zStart, int xSize, int ySize, int zSize, float scaleModifier)\
|
|
{\
|
|
float* noiseSet = GetEmptySet(xSize, ySize, zSize);\
|
|
\
|
|
Fill##f##Set(noiseSet, xStart, yStart, zStart, xSize, ySize, zSize, scaleModifier);\
|
|
\
|
|
return noiseSet;\
|
|
}
|
|
|
|
GET_SET(WhiteNoise)
|
|
|
|
GET_SET(Value)
|
|
GET_SET(ValueFractal)
|
|
|
|
GET_SET(Perlin)
|
|
GET_SET(PerlinFractal)
|
|
|
|
GET_SET(Simplex)
|
|
GET_SET(SimplexFractal)
|
|
|
|
GET_SET(Cellular)
|
|
|
|
GET_SET(Cubic)
|
|
GET_SET(CubicFractal)
|
|
|
|
float FastNoiseSIMD::CalculateFractalBounding(int octaves, float gain)
|
|
{
|
|
float amp = gain;
|
|
float ampFractal = 1.0f;
|
|
for (int i = 1; i < octaves; i++)
|
|
{
|
|
ampFractal += amp;
|
|
amp *= gain;
|
|
}
|
|
return 1.0f / ampFractal;
|
|
}
|
|
|
|
void FastNoiseSIMD::SetCellularDistance2Indicies(int cellularDistanceIndex0, int cellularDistanceIndex1)
|
|
{
|
|
m_cellularDistanceIndex0 = std::min(cellularDistanceIndex0, cellularDistanceIndex1);
|
|
m_cellularDistanceIndex1 = std::max(cellularDistanceIndex0, cellularDistanceIndex1);
|
|
|
|
m_cellularDistanceIndex0 = std::min(std::max(m_cellularDistanceIndex0, 0), FN_CELLULAR_INDEX_MAX);
|
|
m_cellularDistanceIndex1 = std::min(std::max(m_cellularDistanceIndex1, 0), FN_CELLULAR_INDEX_MAX);
|
|
}
|
|
|
|
void FastNoiseVectorSet::Free()
|
|
{
|
|
size = -1;
|
|
FastNoiseSIMD::FreeNoiseSet(xSet);
|
|
xSet = nullptr;
|
|
ySet = nullptr;
|
|
zSet = nullptr;
|
|
}
|
|
|
|
void FastNoiseVectorSet::SetSize(int _size)
|
|
{
|
|
Free();
|
|
size = _size;
|
|
|
|
int alignedSize = FastNoiseSIMD::AlignedSize(size);
|
|
|
|
xSet = FastNoiseSIMD::GetEmptySet(alignedSize * 3);
|
|
ySet = xSet + alignedSize;
|
|
zSet = ySet + alignedSize;
|
|
}
|