1#include "IsoSurfaces_internal.h"
2#include "Platform/Instrumentation.h"
4#include "Foundation/Platform/Timer.h"
17void Cogs::Core::IsoSurfaces::analyzeTile_f32(AnalyzeGlobalState* g,
const glm::ivec3
id)
19 CpuInstrumentationScope(SCOPE_ISOSURFACES,
"analyzeTile_f32");
20 auto timer = Timer::startNew();
22 const float* field = (
const float*)g->field;
23 const float* thresholds = (
const float*)g->thresholds;
24 const ivec3 fieldDim = g->fieldDim;
25 const ivec3 tileSize = g->tileSize;
26 const ivec3 scratchSize = tileSize + ivec3(1);
28 const auto exteriorIsLess = g->exteriorIsLess;
29 auto * scratch = g->scratchAcquire(4 *
sizeof(
int) * (scratchSize.x * scratchSize.y * scratchSize.z + 1));
31 ivec3 rA = g->tileSize * id;
32 ivec3 rB = glm::min(g->M, rA + g->tileSize);
33 const auto tileSizeClamped = glm::min(tileSize, rB - rA);
34 const size_t layerStride = g->M.x*g->M.y*g->M.z;
36 for (
unsigned tOff = 0; tOff < g->Nt; tOff += 4) {
37 auto * s =
reinterpret_cast<ivec4*
>(scratch->data());
39 auto lanes = std::min(4u, g->Nt - tOff);
42 vec4 T(thresholds[tOff + std::min(0u, lanes - 1)],
43 thresholds[tOff + std::min(1u, lanes - 1)],
44 thresholds[tOff + std::min(2u, lanes - 1)],
45 thresholds[tOff + std::min(3u, lanes - 1)]);
47 for (
int k = 0; k < scratchSize.z; k++) {
48 for (
int j = 0; j < scratchSize.y; j++) {
49 for (
int i = 0; i < scratchSize.x; i++) {
50 int kk = k + rA.z + g->gridA.z;
51 int jj = j + rA.y + g->gridA.y;
52 int ii = i + rA.x + g->gridA.x;
54 bool m0 = (0 <= ii) && (0 <= jj) && (0 <= kk);
55 bool m1 = (ii < fieldDim.x) && (jj < fieldDim.y) && (kk < fieldDim.z);
59 auto v = field[(kk*fieldDim.y + jj)*fieldDim.x + ii];
60 b = ivec4(v < T.x ? 1 : 0, v < T.y ? 1 : 0, v < T.z ? 1 : 0, v < T.w ? 1 : 0);
63 b = ivec4(exteriorIsLess);
65 s[(k*scratchSize.y + j)*scratchSize.x + i] = b;
70 for (
int i = 0; i < scratchSize.x*scratchSize.y*scratchSize.z - 1; i++) {
71 s[i] = s[i] | (s[i + 1] << 1);
74 for (
int i = 0; i < scratchSize.x*(scratchSize.y*scratchSize.z - 1); i++) {
75 s[i] = s[i] | (s[i + scratchSize.x] << 2);
78 for (
int i = 0; i < scratchSize.x*scratchSize.y*(scratchSize.z - 1); i++) {
79 auto t = s[i] | (s[i + scratchSize.x*scratchSize.y] << 4);
80 t.x = t.x == 255 ? 0 : t.x;
81 t.y = t.y == 255 ? 0 : t.y;
82 t.z = t.z == 255 ? 0 : t.z;
83 t.w = t.w == 255 ? 0 : t.w;
88 for (
int k = 0; k < tileSizeClamped.z; k++) {
89 for (
int j = 0; j < tileSizeClamped.y; j++) {
90 for (
int i = 0; i < tileSizeClamped.x; i++) {
91 ivec4 codes = s[(k*scratchSize.y + j)*scratchSize.x + i];
92 Nc.x += codes.x ? 1 : 0;
93 Nc.y += codes.y ? 1 : 0;
94 Nc.z += codes.z ? 1 : 0;
95 Nc.w += codes.w ? 1 : 0;
102 for (
unsigned l = 0; l < lanes; l++) {
103 const auto t = tOff + l;
104 Oc[l] = g->cellOffsets[t].fetch_add(Nc[l]);
108 for (
int k = 0; k < tileSizeClamped.z; k++) {
109 for (
int j = 0; j < tileSizeClamped.y; j++) {
110 for (
int i = 0; i < tileSizeClamped.x; i++) {
111 const auto I = ivec3(i, j, k) + rA;
113 ivec4 codes = s[(k*scratchSize.y + j)*scratchSize.x + i];
115 ivec4 none(codes.x == 0 ? 1 : 0,
116 codes.y == 0 ? 1 : 0,
117 codes.z == 0 ? 1 : 0,
118 codes.w == 0 ? 1 : 0);
120 if (none.x && none.y && none.z && none.w)
continue;
122 for (
unsigned l = 0; l < lanes; l++) {
123 if (none[l])
continue;
125 const auto t = tOff + l;
126 const auto uncompactedCellIndex = (I.z*M.y + I.y)*M.x + I.x;
127 const auto code = codes[l];
128 const auto c = Oc[l] + (Ni[l]++);
129 g->cellMap[layerStride*t + uncompactedCellIndex] = c;
130 g->activeCellCases[layerStride*t + c] = (uint8_t)code;
131 g->activeCellIndices[layerStride*t + c] = uncompactedCellIndex;
138 g->scratchRelease(scratch);
139 if (g->elapsed_us !=
nullptr) {
140 g->elapsed_us->fetch_add(timer.elapsedMicroseconds());
145void Cogs::Core::IsoSurfaces::analyzeTile_u16(AnalyzeGlobalState* g,
const glm::ivec3
id)
147 CpuInstrumentationScope(SCOPE_ISOSURFACES,
"AnalyzeTile");
148 auto timer = Timer::startNew();
150 const uint16_t* field = (
const uint16_t*)g->field;
151 const uint16_t* thresholds = (
const uint16_t*)g->thresholds;
153 const ivec3 fieldDim = g->fieldDim;
154 const ivec3 tileSize = g->tileSize;
155 const ivec3 scratchSize = tileSize + ivec3(1);
156 const ivec3 M = g->M;
157 const auto exteriorIsLess = g->exteriorIsLess;
158 auto * scratch = g->scratchAcquire(4 *
sizeof(
int) * ((
size_t)scratchSize.x * (
size_t)scratchSize.y * (
size_t)scratchSize.z + 1));
160 ivec3 rA = g->tileSize * id;
161 ivec3 rB = glm::min(g->M, rA + g->tileSize);
162 const auto tileSizeClamped = glm::min(tileSize, rB - rA);
163 const size_t layerStride = (size_t)g->M.x * (
size_t)g->M.y * (size_t)g->M.z;
165 for (
unsigned tOff = 0; tOff < g->Nt; tOff += 4) {
166 auto * s =
reinterpret_cast<ivec4*
>(scratch->data());
168 auto lanes = std::min(4u, g->Nt - tOff);
171 vec4 T(thresholds[tOff + std::min(0u, lanes - 1)],
172 thresholds[tOff + std::min(1u, lanes - 1)],
173 thresholds[tOff + std::min(2u, lanes - 1)],
174 thresholds[tOff + std::min(3u, lanes - 1)]);
176 for (
int k = 0; k < scratchSize.z; k++) {
177 for (
int j = 0; j < scratchSize.y; j++) {
178 for (
int i = 0; i < scratchSize.x; i++) {
179 int kk = k + rA.z + g->gridA.z;
180 int jj = j + rA.y + g->gridA.y;
181 int ii = i + rA.x + g->gridA.x;
183 bool m0 = (0 <= ii) && (0 <= jj) && (0 <= kk);
184 bool m1 = (ii < fieldDim.x) && (jj < fieldDim.y) && (kk < fieldDim.z);
188 auto v = field[(kk*fieldDim.y + jj)*fieldDim.x + ii];
189 b = ivec4(v < T.x ? 1 : 0, v < T.y ? 1 : 0, v < T.z ? 1 : 0, v < T.w ? 1 : 0);
192 b = ivec4(exteriorIsLess);
194 s[(k*scratchSize.y + j)*scratchSize.x + i] = b;
199 for (
int i = 0; i < scratchSize.x*scratchSize.y*scratchSize.z - 1; i++) {
200 s[i] = s[i] | (s[i + 1] << 1);
203 for (
int i = 0; i < scratchSize.x*(scratchSize.y*scratchSize.z - 1); i++) {
204 s[i] = s[i] | (s[i + scratchSize.x] << 2);
207 for (
int i = 0; i < scratchSize.x*scratchSize.y*(scratchSize.z - 1); i++) {
208 auto t = s[i] | (s[i + scratchSize.x*scratchSize.y] << 4);
209 t.x = t.x == 255 ? 0 : t.x;
210 t.y = t.y == 255 ? 0 : t.y;
211 t.z = t.z == 255 ? 0 : t.z;
212 t.w = t.w == 255 ? 0 : t.w;
217 for (
int k = 0; k < tileSizeClamped.z; k++) {
218 for (
int j = 0; j < tileSizeClamped.y; j++) {
219 for (
int i = 0; i < tileSizeClamped.x; i++) {
220 ivec4 codes = s[(k*scratchSize.y + j)*scratchSize.x + i];
221 Nc.x += codes.x ? 1 : 0;
222 Nc.y += codes.y ? 1 : 0;
223 Nc.z += codes.z ? 1 : 0;
224 Nc.w += codes.w ? 1 : 0;
231 for (
unsigned l = 0; l < lanes; l++) {
232 const auto t = tOff + l;
233 Oc[l] = g->cellOffsets[t].fetch_add(Nc[l]);
237 for (
int k = 0; k < tileSizeClamped.z; k++) {
238 for (
int j = 0; j < tileSizeClamped.y; j++) {
239 for (
int i = 0; i < tileSizeClamped.x; i++) {
240 const auto I = ivec3(i, j, k) + rA;
242 ivec4 codes = s[(k*scratchSize.y + j)*scratchSize.x + i];
244 ivec4 none(codes.x == 0 ? 1 : 0,
245 codes.y == 0 ? 1 : 0,
246 codes.z == 0 ? 1 : 0,
247 codes.w == 0 ? 1 : 0);
249 if (none.x && none.y && none.z && none.w)
continue;
251 for (
unsigned l = 0; l < lanes; l++) {
252 if (none[l])
continue;
254 const auto t = tOff + l;
255 const auto uncompactedCellIndex = (I.z*M.y + I.y)*M.x + I.x;
256 const auto code = codes[l];
257 const auto c = Oc[l] + (Ni[l]++);
258 g->cellMap[layerStride*t + uncompactedCellIndex] = c;
259 g->activeCellCases[layerStride*t + c] = (uint8_t)code;
260 g->activeCellIndices[layerStride*t + c] = uncompactedCellIndex;
267 g->scratchRelease(scratch);
268 if (g->elapsed_us !=
nullptr) {
269 g->elapsed_us->fetch_add(timer.elapsedMicroseconds());
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....