Refactored layer functions for const Layers args + optimisations.

This commit is contained in:
Cubitect 2020-07-23 22:42:38 +02:00
parent 470a42968c
commit b26f4eb1f7
5 changed files with 966 additions and 963 deletions

View File

@ -97,10 +97,8 @@ int main(int argc, char *argv[])
// so we can test the biome at these positions.
Pos qhpos[4];
// Setup a dummy layer for Layer 19: Biome, to make preliminary seed tests.
Layer layerBiomeDummy;
layerBiomeDummy.scale = 256;
setupLayer(&layerBiomeDummy, NULL, 200, NULL);
// layerSeed for Layer 19: Biome, to make preliminary seed tests.
int64_t lsBiome = g.layers[L_BIOME_256].layerSeed;
int areaX = (regPosX << 1) + 1;
@ -137,12 +135,13 @@ int main(int argc, char *argv[])
// generator is quite bad, the "mcNextRand() mod 6" check has a period
// pattern of ~3 on the high seed-bits, which means we can avoid
// checking all 16 high-bit combinations.
int64_t ss, cs;
for (j = 0; j < 5; j++)
{
seed = base + ((j+0x53) << 48);
setWorldSeed(&layerBiomeDummy, seed);
setChunkSeed(&layerBiomeDummy, areaX+1, areaZ+1);
if (mcNextInt(&layerBiomeDummy, 6) == 5)
ss = getStartSeed(seed, lsBiome);
cs = getChunkSeed(ss, areaX+1, areaZ+1);
if (mcFirstInt(cs, 6) == 5)
break;
}
if (j >= 5)
@ -158,10 +157,9 @@ int main(int argc, char *argv[])
/** Pre-Generation Checks **/
// We can check that at least one swamp could generate in this area
// before doing the biome generator checks.
setWorldSeed(&layerBiomeDummy, seed);
setChunkSeed(&layerBiomeDummy, areaX+1, areaZ+1);
if (mcNextInt(&layerBiomeDummy, 6) != 5)
ss = getStartSeed(seed, lsBiome);
cs = getChunkSeed(ss, areaX+1, areaZ+1);
if (mcFirstInt(cs, 6) != 5)
continue;
// This seed base does not seem to contain many quad huts, so make
@ -170,12 +168,12 @@ int main(int argc, char *argv[])
if (hits == 0 && (j & 0xfff) == 0xfff)
{
swpc = 0;
setChunkSeed(&layerBiomeDummy, areaX, areaZ+1);
swpc += mcNextInt(&layerBiomeDummy, 6) == 5;
setChunkSeed(&layerBiomeDummy, areaX+1, areaZ);
swpc += mcNextInt(&layerBiomeDummy, 6) == 5;
setChunkSeed(&layerBiomeDummy, areaX, areaZ);
swpc += mcNextInt(&layerBiomeDummy, 6) == 5;
cs = getChunkSeed(ss, areaX, areaZ+1);
swpc += mcFirstInt(cs, 6) == 5;
cs = getChunkSeed(ss, areaX+1, areaZ);
swpc += mcFirstInt(cs, 6) == 5;
cs = getChunkSeed(ss, areaX, areaZ);
swpc += mcFirstInt(cs, 6) == 5;
if (swpc < (j > 0x1000 ? 2 : 1))
break;

View File

@ -993,7 +993,7 @@ Pos findBiomePosition(
{
for (i = 0, j = 2; i < width*height; i++)
{
if (!isValid[map[i] & 0xff]) continue;
if (!biomeExists(map[i]) || !isValid[map[i]]) continue;
if ((found == 0 || nextInt(seed, j++) == 0))
{
out.x = (x1 + i%width) << 2;
@ -1007,7 +1007,7 @@ Pos findBiomePosition(
{
for (i = 0; i < width*height; i++)
{
if (isValid[map[i] & 0xff] &&
if (biomeExists(map[i]) && isValid[map[i]] &&
(found == 0 || nextInt(seed, found + 1) == 0))
{
out.x = (x1 + i%width) << 2;
@ -1063,7 +1063,7 @@ int areBiomesViable(
for (i = 0; i < width*height; i++)
{
if (!isValid[ map[i] & 0xff ])
if (!biomeExists(map[i]) || !isValid[ map[i] ])
{
if (cache == NULL) free(map);
return 0;
@ -1601,11 +1601,6 @@ int64_t filterAllTempCats(
map = cache ? cache : allocCache(lFilterSpecial, sX, sZ);
// Construct a dummy Edge,Special layer.
Layer layerSpecial;
layerSpecial.scale = 1024;
setupLayer(&layerSpecial, NULL, 3, NULL);
int64_t sidx, hits, seed;
int types[9];
int specialCnt;
@ -1623,14 +1618,14 @@ int64_t filterAllTempCats(
// tested for without going through the previous layers. (We'll get
// false positives due to Oceans, but this works fine to rule out some
// seeds early on.)
setWorldSeed(&layerSpecial, seed);
int64_t ss = getStartSeed(seed, lFilterSpecial->layerSeed);
specialCnt = 0;
for (i = 0; i < sX; i++)
{
for (j = 0; j < sZ; j++)
{
setChunkSeed(&layerSpecial, (int64_t)(i+pX), (int64_t)(j+pZ));
if (mcNextInt(&layerSpecial, 13) == 0)
int64_t cs = getChunkSeed(ss, i+pX, j+pZ);
if (mcFirstInt(cs, 13) == 0)
specialCnt++;
}
}
@ -1956,15 +1951,15 @@ int64_t checkForBiomes(
// temperature categories present.
if (filter.tempNormal || filter.tempSpecial)
{
ss = processWorldSeed(seed, lspecial->baseSeed);
ss = getStartSeed(seed, lspecial->layerSeed);
types[0] = types[1] = 0;
for (z = 0; z < areaHeight1024; z++)
{
for (x = 0; x < areaWidth1024; x++)
{
cs = getChunkSeed(ss, (int64_t)(x + areaX1024), (int64_t)(z + areaZ1024));
types[(cs >> 24) % 13 == 0]++;
cs = getChunkSeed(ss, x + areaX1024, z + areaZ1024);
types[mcFirstInt(cs, 13) == 0]++;
}
}
@ -1977,14 +1972,14 @@ int64_t checkForBiomes(
// Check there is a mushroom island, provided there is an ocean.
if (filter.requireMushroom)
{
ss = processWorldSeed(seed, lmushroom->baseSeed);
ss = getStartSeed(seed, lmushroom->layerSeed);
for (z = 0; z < areaHeight256; z++)
{
for (x = 0; x < areaWidth256; x++)
{
cs = getChunkSeed(ss, (int64_t)(x + areaX256), (int64_t)(z + areaZ256));
if ((cs >> 24) % 100 == 0)
if (mcFirstInt(cs, 100) == 0)
{
goto after_protomushroom;
}
@ -1997,7 +1992,7 @@ int64_t checkForBiomes(
if (filter.checkBiomePotential)
{
ss = processWorldSeed(seed, lbiomes->baseSeed);
ss = getStartSeed(seed, lbiomes->layerSeed);
potential = 0;
required = filter.biomesToFind & (

View File

@ -6,22 +6,25 @@
#include <string.h>
void setupLayer(Layer *l, Layer *p, int s, void (*getMap)(Layer *layer, int *out, int x, int z, int w, int h))
void setupLayer(Layer *l, Layer *p, int s,
void (*getMap)(const Layer * RESTRICT, int *, int, int, int, int))
{
setBaseSeed(l, s);
l->layerSeed = getLayerSeed(s);
l->startSalt = 0;
l->startSeed = 0;
l->p = p;
l->p2 = NULL;
l->scale = 0;
l->getMap = getMap;
l->oceanRnd = NULL;
}
void setupMultiLayer(Layer *l, Layer *p1, Layer *p2, int s, void (*getMap)(Layer *layer, int *out, int x, int z, int w, int h))
void setupMultiLayer(Layer *l, Layer *p1, Layer *p2, int s,
void (*getMap)(const Layer * RESTRICT, int *, int, int, int, int))
{
setBaseSeed(l, s);
l->p = p1;
setupLayer(l, p1, s, getMap);
l->p2 = p2;
l->getMap = getMap;
l->oceanRnd = NULL;
}
@ -54,7 +57,7 @@ static LayerStack setupGeneratorImpl(const int mcversion, const int largeBiomes)
g.layers = (Layer *) calloc(g.layerCnt, sizeof(Layer));
Layer *l = g.layers;
// LAYER PARENT SEED LAYER_FUNCTION
// LAYER PARENT SALT LAYER_FUNCTION
setupLayer(&l[L_ISLAND_4096], NULL, 1, mapIsland);
setupLayer(&l[L_ZOOM_2048], &l[L_ISLAND_4096], 2000, mapZoom);
setupLayer(&l[L_ADD_ISLAND_2048], &l[L_ZOOM_2048], 1, mapAddIsland);
@ -79,11 +82,11 @@ static LayerStack setupGeneratorImpl(const int mcversion, const int largeBiomes)
mcversion != MCBE ? mapBiome : mapBiomeBE);
if (mcversion <= MC_1_13)
setupLayer(&l[L_ZOOM_128], &l[L_BIOME_256], 1000, mapZoom);
setupLayer(&l[L_ZOOM_128], &l[L_BIOME_256], 1000, mapZoom);
else
{
setupLayer(&l[L14_BAMBOO_256], &l[L_BIOME_256], 1001, mapAddBamboo);
setupLayer(&l[L_ZOOM_128], &l[L14_BAMBOO_256], 1000, mapZoom);
setupLayer(&l[L14_BAMBOO_256], &l[L_BIOME_256], 1001, mapAddBamboo);
setupLayer(&l[L_ZOOM_128], &l[L14_BAMBOO_256], 1000, mapZoom);
}
setupLayer(&l[L_ZOOM_64], &l[L_ZOOM_128], 1001, mapZoom);
@ -204,6 +207,7 @@ static void getMaxArea(Layer *layer, int areaX, int areaZ, int *maxX, int *maxZ)
layer->getMap != mapIsland &&
layer->getMap != mapSpecial &&
layer->getMap != mapBiome &&
layer->getMap != mapRareBiome &&
layer->getMap != mapRiverInit &&
layer->getMap != mapRiverMix &&
layer->getMap != mapOceanTemp)
@ -245,7 +249,7 @@ void applySeed(LayerStack *g, int64_t seed)
setWorldSeed(&g->layers[L_VORONOI_ZOOM_1], seed);
}
void genArea(Layer *layer, int *out, int areaX, int areaZ, int areaWidth, int areaHeight)
void genArea(const Layer *layer, int *out, int areaX, int areaZ, int areaWidth, int areaHeight)
{
memset(out, 0, areaWidth*areaHeight*sizeof(*out));
layer->getMap(layer, out, areaX, areaZ, areaWidth, areaHeight);

1462
layers.c

File diff suppressed because it is too large Load Diff

378
layers.h
View File

@ -13,29 +13,11 @@
#define NULL ((void*)0)
#endif
#define SIMD_NOTIFY 0
#if defined USE_SIMD && __AVX2__
#include <emmintrin.h>
#include <smmintrin.h>
#include <immintrin.h>
#if SIMD_NOTIFY
#warning "Using AVX2 extensions."
#endif
#elif defined USE_SIMD && defined __SSE4_2__
#include <emmintrin.h>
#include <smmintrin.h>
#if SIMD_NOTIFY
#warning "Using SSE4.2 extensions."
#endif
#else
//#warning "Using no SIMD extensions."
#endif
#define RESTRICT __restrict
#define REGISTER register
#define STRUCT(S) typedef struct S S; struct S
#define OPT_O2 __attribute__((optimize("O2")))
enum BiomeID
{
@ -164,16 +146,15 @@ STRUCT(OceanRnd)
STRUCT(Layer)
{
int64_t baseSeed; // Generator seed (depends only on layer hierarchy)
int64_t worldSeed; // based on the seed of the world
int64_t chunkSeed; // randomiser seed
int64_t layerSeed; // (depends only on layer salt)
int64_t startSalt; // (world seed dependent) for RND ints beyond the first
int64_t startSeed; // (world seed dependent) starting point for chunk seeds
OceanRnd *oceanRnd; // world seed dependent data for ocean temperatures
int scale; // map scale of this layer (map entry = scale x scale blocks)
void (*getMap)(Layer *layer, int *out, int x, int z, int w, int h);
void (*getMap)(const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
Layer *p, *p2; // parent layers
};
@ -284,306 +265,107 @@ static inline int isBiomeSnowy(int id)
return biomeExists(id) && biomes[id].temp < 0.1;
}
static inline int mcNextInt(Layer *layer, int mod)
/**
* The seed pipeline:
*
* Salt of Layer -> layerSeed (ls)
* layerSeed (ls) + worldSeed (ws) -> startSalt (st) + startSeed (ss)
* startSeed (ls) + coords (x,z) -> chunkSeed (cs)
*
* The chunkSeed alone is enough to generate the first RND integer with:
* mcFirstInt(cs, mod)
* subsequent RND integers are generated by stepping the chunkSeed forwards,
* salted with startSalt:
* cs_next = mcStepSeed(cs, st)
*/
static inline int64_t mcStepSeed(int64_t s, int64_t salt)
{
int ret = (int)((layer->chunkSeed >> 24) % (int64_t)mod);
return s * (s * 6364136223846793005LL + 1442695040888963407LL) + salt;
}
static inline int mcFirstInt(int64_t s, int mod)
{
int ret = (int)((s >> 24) % mod);
if (ret < 0)
{
ret += mod;
}
layer->chunkSeed *= layer->chunkSeed * 6364136223846793005LL + 1442695040888963407LL;
layer->chunkSeed += layer->worldSeed;
return ret;
}
static inline int64_t processWorldSeed(register int64_t ws, const int64_t bs)
static inline int mcIsFirstZero(int64_t s, int mod)
{
ws *= ws * 6364136223846793005LL + 1442695040888963407LL;
ws += bs;
ws *= ws * 6364136223846793005LL + 1442695040888963407LL;
ws += bs;
ws *= ws * 6364136223846793005LL + 1442695040888963407LL;
ws += bs;
ws *= ws * 6364136223846793005LL + 1442695040888963407LL;
return ws;
return (int)((s >> 24) % mod) == 0;
}
static inline int64_t getChunkSeed(register int64_t ss, const int64_t x, const int64_t z)
static inline int64_t getChunkSeed(int64_t ss, int x, int z)
{
ss += x;
ss *= ss * 6364136223846793005LL + 1442695040888963407LL;
ss += z;
ss *= ss * 6364136223846793005LL + 1442695040888963407LL;
ss += x;
ss *= ss * 6364136223846793005LL + 1442695040888963407LL;
ss += z;
int64_t cs = ss + x;
cs = mcStepSeed(cs, z);
cs = mcStepSeed(cs, x);
cs = mcStepSeed(cs, z);
return cs;
}
static inline int64_t getLayerSeed(int64_t salt)
{
int64_t ls = mcStepSeed(salt, salt);
ls = mcStepSeed(ls, salt);
ls = mcStepSeed(ls, salt);
return ls;
}
static inline int64_t getStartSeed(int64_t ws, int64_t ls)
{
int64_t ss = ws;
ss = mcStepSeed(ss, ls);
ss = mcStepSeed(ss, ls);
ss = mcStepSeed(ss, ls);
ss = mcStepSeed(ss, 0);
return ss;
}
static inline void setChunkSeed(Layer *layer, int64_t chunkX, int64_t chunkZ)
{
layer->chunkSeed = layer->worldSeed;
layer->chunkSeed *= layer->chunkSeed * 6364136223846793005LL + 1442695040888963407LL;
layer->chunkSeed += chunkX;
layer->chunkSeed *= layer->chunkSeed * 6364136223846793005LL + 1442695040888963407LL;
layer->chunkSeed += chunkZ;
layer->chunkSeed *= layer->chunkSeed * 6364136223846793005LL + 1442695040888963407LL;
layer->chunkSeed += chunkX;
layer->chunkSeed *= layer->chunkSeed * 6364136223846793005LL + 1442695040888963407LL;
layer->chunkSeed += chunkZ;
}
static inline void setBaseSeed(Layer *layer, int64_t seed)
{
layer->baseSeed = seed;
layer->baseSeed *= layer->baseSeed * 6364136223846793005LL + 1442695040888963407LL;
layer->baseSeed += seed;
layer->baseSeed *= layer->baseSeed * 6364136223846793005LL + 1442695040888963407LL;
layer->baseSeed += seed;
layer->baseSeed *= layer->baseSeed * 6364136223846793005LL + 1442695040888963407LL;
layer->baseSeed += seed;
layer->p = NULL;
layer->worldSeed = 0;
layer->chunkSeed = 0;
}
#if defined USE_SIMD && __AVX2__
static inline __m256i set8ChunkSeeds(int ws, __m256i xs, __m256i zs)
{
__m256i out = _mm256_set1_epi32(ws);
__m256i mul = _mm256_set1_epi32(1284865837);
__m256i add = _mm256_set1_epi32(4150755663);
out = _mm256_add_epi32(xs, _mm256_mullo_epi32(out, _mm256_add_epi32(add, _mm256_mullo_epi32(out, mul))));
out = _mm256_add_epi32(zs, _mm256_mullo_epi32(out, _mm256_add_epi32(add, _mm256_mullo_epi32(out, mul))));
out = _mm256_add_epi32(xs, _mm256_mullo_epi32(out, _mm256_add_epi32(add, _mm256_mullo_epi32(out, mul))));
return _mm256_add_epi32(zs, _mm256_mullo_epi32(out, _mm256_add_epi32(add, _mm256_mullo_epi32(out, mul))));
}
static inline __m256i mc8NextInt(__m256i* cs, int ws, int mask)
{
__m256i andm = _mm256_set1_epi32(mask);
__m256i ret = _mm256_and_si256(andm, _mm256_srli_epi32(*cs, 24));
*cs = _mm256_add_epi32(_mm256_set1_epi32(ws), _mm256_mullo_epi32(*cs, _mm256_add_epi32(_mm256_set1_epi32(4150755663), _mm256_mullo_epi32(*cs, _mm256_set1_epi32(1284865837)))));
return _mm256_add_epi32(ret, _mm256_and_si256(andm, _mm256_cmpgt_epi32(_mm256_set1_epi32(0), ret)));
}
static inline __m256i select8Random2(__m256i* cs, int ws, __m256i a1, __m256i a2)
{
__m256i cmp = _mm256_cmpeq_epi32(_mm256_set1_epi32(0), mc8NextInt(cs, ws, 0x1));
return _mm256_or_si256(_mm256_and_si256(cmp, a1), _mm256_andnot_si256(cmp, a2));
}
static inline __m256i select8Random4(__m256i* cs, int ws, __m256i a1, __m256i a2, __m256i a3, __m256i a4)
{
__m256i val = mc8NextInt(cs, ws, 0x3);
__m256i v2 = _mm256_set1_epi32(2);
__m256i cmp1 = _mm256_cmpeq_epi32(val, _mm256_set1_epi32(0));
__m256i cmp2 = _mm256_cmpeq_epi32(v2, val);
__m256i cmp3 = _mm256_cmpgt_epi32(v2, val);
return _mm256_or_si256(
_mm256_and_si256(cmp3, _mm256_or_si256(_mm256_and_si256(cmp1, a1), _mm256_andnot_si256(cmp1, a2))),
_mm256_andnot_si256(cmp3, _mm256_or_si256(_mm256_and_si256(cmp2, a3), _mm256_andnot_si256(cmp2, a4)))
);
}
static inline __m256i select8ModeOrRandom(__m256i* cs, int ws, __m256i a1, __m256i a2, __m256i a3, __m256i a4)
{
__m256i cmp1 = _mm256_cmpeq_epi32(a1, a2);
__m256i cmp2 = _mm256_cmpeq_epi32(a1, a3);
__m256i cmp3 = _mm256_cmpeq_epi32(a1, a4);
__m256i cmp4 = _mm256_cmpeq_epi32(a2, a3);
__m256i cmp5 = _mm256_cmpeq_epi32(a2, a4);
__m256i cmp6 = _mm256_cmpeq_epi32(a3, a4);
__m256i isa1 = _mm256_or_si256(
_mm256_andnot_si256(cmp6, cmp1),
_mm256_or_si256 (
_mm256_andnot_si256(cmp5, cmp2),
_mm256_andnot_si256(cmp4, cmp3)
)
);
__m256i isa2 = _mm256_or_si256(
_mm256_andnot_si256(cmp3, cmp4),
_mm256_andnot_si256(cmp2, cmp5)
);
__m256i isa3 = _mm256_andnot_si256(cmp1, cmp6);
return _mm256_or_si256(
_mm256_andnot_si256(
_mm256_or_si256(
isa1,
_mm256_or_si256(isa2, isa3)
),
select8Random4(cs, ws, a1, a2, a3, a4)
),
_mm256_or_si256(
_mm256_and_si256(isa1, a1),
_mm256_or_si256(
_mm256_and_si256(isa2, a2),
_mm256_and_si256(isa3, a3)
)
)
);
}
#elif defined USE_SIMD && defined __SSE4_2__
static inline __m128i set4ChunkSeeds(int ws, __m128i xs, __m128i zs)
{
__m128i out = _mm_set1_epi32(ws);
__m128i mul = _mm_set1_epi32(1284865837);
__m128i add = _mm_set1_epi32(4150755663);
out = _mm_add_epi32(xs, _mm_mullo_epi32(out, _mm_add_epi32(add, _mm_mullo_epi32(out, mul))));
out = _mm_add_epi32(zs, _mm_mullo_epi32(out, _mm_add_epi32(add, _mm_mullo_epi32(out, mul))));
out = _mm_add_epi32(xs, _mm_mullo_epi32(out, _mm_add_epi32(add, _mm_mullo_epi32(out, mul))));
return _mm_add_epi32(zs, _mm_mullo_epi32(out, _mm_add_epi32(add, _mm_mullo_epi32(out, mul))));
}
static inline __m128i mc4NextInt(__m128i* cs, int ws, int mask)
{
__m128i andm = _mm_set1_epi32(mask);
__m128i ret = _mm_and_si128(andm, _mm_srli_epi32(*cs, 24));
*cs = _mm_add_epi32( _mm_set1_epi32(ws), _mm_mullo_epi32(*cs, _mm_add_epi32(_mm_set1_epi32(4150755663), _mm_mullo_epi32(*cs, _mm_set1_epi32(1284865837)))));
return _mm_add_epi32(ret, _mm_and_si128(andm, _mm_cmplt_epi32(ret, _mm_set1_epi32(0))));
}
static inline __m128i select4Random2(__m128i* cs, int ws, __m128i a1, __m128i a2)
{
__m128i cmp = _mm_cmpeq_epi32(_mm_set1_epi32(0), mc4NextInt(cs, ws, 0x1));
return _mm_or_si128(_mm_and_si128(cmp, a1), _mm_andnot_si128(cmp, a2));
}
static inline __m128i select4Random4(__m128i* cs, int ws, __m128i a1, __m128i a2, __m128i a3, __m128i a4)
{
__m128i val = mc4NextInt(cs, ws, 0x3);
__m128i v2 = _mm_set1_epi32(2);
__m128i cmp1 = _mm_cmpeq_epi32(val, _mm_set1_epi32(0));
__m128i cmp2 = _mm_cmpeq_epi32(val, v2);
__m128i cmp3 = _mm_cmplt_epi32(val, v2);
return _mm_or_si128(
_mm_and_si128(cmp3, _mm_or_si128(_mm_and_si128(cmp1, a1), _mm_andnot_si128(cmp1, a2))),
_mm_andnot_si128(cmp3, _mm_or_si128(_mm_and_si128(cmp2, a3), _mm_andnot_si128(cmp2, a4)))
);
}
static inline __m128i select4ModeOrRandom(__m128i* cs, int ws, __m128i a1, __m128i a2, __m128i a3, __m128i a4)
{
//((a == b)&(c != d) | (a == c)&(b != d) | (a == d)&(b != c))&a | ((b == c)&(a != d) | (b == d)&(a != c))&b | ((c == d)&(a != b))&c
__m128i cmp1 = _mm_cmpeq_epi32(a1, a2);
__m128i cmp2 = _mm_cmpeq_epi32(a1, a3);
__m128i cmp3 = _mm_cmpeq_epi32(a1, a4);
__m128i cmp4 = _mm_cmpeq_epi32(a2, a3);
__m128i cmp5 = _mm_cmpeq_epi32(a2, a4);
__m128i cmp6 = _mm_cmpeq_epi32(a3, a4);
__m128i isa1 = _mm_or_si128(
_mm_andnot_si128(cmp6, cmp1),
_mm_or_si128 (
_mm_andnot_si128(cmp5, cmp2),
_mm_andnot_si128(cmp4, cmp3)
)
);
__m128i isa2 = _mm_or_si128(
_mm_andnot_si128(cmp3, cmp4),
_mm_andnot_si128(cmp2, cmp5)
);
__m128i isa3 = _mm_andnot_si128(cmp1, cmp6);
return _mm_or_si128(
_mm_andnot_si128(
_mm_or_si128(
isa1,
_mm_or_si128(isa2, isa3)
),
select4Random4(cs, ws, a1, a2, a3, a4)
),
_mm_or_si128(
_mm_and_si128(isa1, a1),
_mm_or_si128(
_mm_and_si128(isa2, a2),
_mm_and_si128(isa3, a3)
)
)
);
}
#else
static inline int selectRandom2(Layer *l, int a1, int a2)
{
int i = mcNextInt(l, 2);
return i == 0 ? a1 : a2;
}
static inline int selectRandom4(Layer *l, int a1, int a2, int a3, int a4)
{
int i = mcNextInt(l, 4);
return i == 0 ? a1 : i == 1 ? a2 : i == 2 ? a3 : a4;
}
static inline int selectModeOrRandom(Layer *l, int a1, int a2, int a3, int a4)
{
int rndarg = selectRandom4(l, a1, a2, a3, a4);
if (a2 == a3 && a3 == a4) return a2;
if (a1 == a2 && a1 == a3) return a1;
if (a1 == a2 && a1 == a4) return a1;
if (a1 == a3 && a1 == a4) return a1;
if (a1 == a2 && a3 != a4) return a1;
if (a1 == a3 && a2 != a4) return a1;
if (a1 == a4 && a2 != a3) return a1;
if (a2 == a3 && a1 != a4) return a2;
if (a2 == a4 && a1 != a3) return a2;
if (a3 == a4 && a1 != a2) return a3;
return rndarg;
}
#endif
//==============================================================================
// Layers
//==============================================================================
// A null layer does nothing, and can be used to apply a layer to existing data.
void mapNull(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapNull (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
// A skip layer simply calls its first parent without modification.
// This can be used as an easy way to skip a layer in a generator.
void mapSkip(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapSkip (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapIsland(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapZoom(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapAddIsland(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapRemoveTooMuchOcean(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapAddSnow(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapCoolWarm(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapHeatIce(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapSpecial(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapAddMushroomIsland(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapDeepOcean(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapBiome(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapBiomeBE(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapAddBamboo(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapRiverInit(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapBiomeEdge(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapHills(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapRiver(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapSmooth(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapRareBiome(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapShore(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapRiverMix(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapIsland (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapZoom (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapAddIsland (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapRemoveTooMuchOcean (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapAddSnow (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapCoolWarm (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapHeatIce (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapSpecial (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapAddMushroomIsland (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapDeepOcean (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapBiome (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapBiomeBE (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapAddBamboo (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapRiverInit (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapBiomeEdge (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapHills (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapRiver (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapSmooth (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapRareBiome (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapShore (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapRiverMix (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
// 1.13 layers
void mapHills113(Layer *l, int * __restrict out, int x, int z, int w, int h);
void mapOceanTemp(Layer *l, int * __restrict out, int areaX, int areaZ, int areaWidth, int areaHeight);
void mapOceanMix(Layer *l, int * __restrict out, int areaX, int areaZ, int areaWidth, int areaHeight);
void mapHills113 (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapOceanTemp (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapOceanMix (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
void mapVoronoiZoom(Layer *l, int * __restrict out, int x, int z, int w, int h);
// final layer 1:1
void mapVoronoiZoom (const Layer * RESTRICT, int * RESTRICT, int, int, int, int);
#ifdef __cplusplus