Cogs.Core
BoundingBox.cpp
1#include "Services/TaskManager.h"
2#include "Services/Features.h"
3#include "Platform/Instrumentation.h"
4#include "Context.h"
5
6#include "BoundingBox.h"
7
8#include "Foundation/Memory/MemoryBuffer.h"
9
10using namespace Cogs::Core;
11
12void Cogs::Core::EchoSounder::includeInBBox(Context* context,
13 Geometry::BoundingBox& bbox,
14 const float* vertices,
15 size_t vertexStride,
16 const size_t numVertices,
17 const size_t taskSize)
18{
19 auto & tm = context->taskManager;
20 auto N = (numVertices + taskSize - 1) / taskSize;
21
22#ifndef EMSCRIPTEN
23 if (context->features->supported(CPUFeature::SSE2)) {
24 Memory::TypedBuffer<float> minmaxes(8*N);
25
26 auto group = tm->createGroup();
27 for (size_t i = 0; i < N; i++) {
28 auto * minmax = minmaxes.data() + 8 * i;
29 auto ia = i*taskSize;
30 auto ib = std::min(numVertices, ia + taskSize);
31 tm->enqueueChild(group, [vertices, vertexStride, minmax, ia, ib]
32 {
33 CpuInstrumentationScope(SCOPE_GEOMETRY, "BBoxFindSSE2");
34 __m128 min = _mm_set1_ps(std::numeric_limits<float>::max());
35 __m128 max = _mm_sub_ps(_mm_setzero_ps(), min);
36 for (size_t i = ia; i < ib; i++) {
37 __m128 p = _mm_loadu_ps(vertices + i*vertexStride);
38 min = _mm_min_ps(min, p);
39 max = _mm_max_ps(max, p);
40 }
41 _mm_storeu_ps(minmax + 0, min);
42 _mm_storeu_ps(minmax + 4, max);
43 });
44 }
45 tm->wait(group);
46 tm->destroy(group);
47
48 {
49 CpuInstrumentationScope(SCOPE_GEOMETRY, "BBoxMergeSSE2");
50
51 __m128 min = _mm_set1_ps(std::numeric_limits<float>::max());
52 __m128 max = _mm_sub_ps(_mm_setzero_ps(), min);
53 for (size_t i = 0; i < N; i++) {
54 min = _mm_min_ps(min, _mm_loadu_ps(minmaxes.data() + 8 * i + 0));
55 max = _mm_max_ps(max, _mm_loadu_ps(minmaxes.data() + 8 * i + 4));
56 }
57 for (uint32_t k = 0; k < 3; k++) {
58 bbox.min[k] = std::min(bbox.min[k], min.m128_f32[k]);
59 bbox.max[k] = std::max(bbox.max[k], max.m128_f32[k]);
60 }
61 }
62
63 }
64 else {
65#else
66
67 {
68#endif
69 std::vector<Cogs::Geometry::BoundingBox> bboxes(N);
70
71 auto group = tm->createGroup();
72 for (int i = 0; i < N; i++) {
73 auto * sub_bbox = bboxes.data() + i;
74 auto ia = i*taskSize;
75 auto ib = std::min(numVertices, ia + taskSize);
76 tm->enqueueChild(group, [vertices, vertexStride, sub_bbox, ia, ib]
77 {
78 CpuInstrumentationScope(SCOPE_GEOMETRY, "BBoxFind");
79 (*sub_bbox) = Cogs::Geometry::makeEmptyBoundingBox<Cogs::Geometry::BoundingBox>();
80 for (size_t i = ia; i < ib; i++) {
81 (*sub_bbox) += *reinterpret_cast<const glm::vec3*>(vertices + i*vertexStride);
82 }
83 });
84 }
85 tm->wait(group);
86 tm->destroy(group);
87
88 {
89 CpuInstrumentationScope(SCOPE_GEOMETRY, "BBoxMerge");
90 for (int i = 0; i < N; i++) {
91 bbox += bboxes[i];
92 }
93 }
94 }
95}
96
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
std::unique_ptr< class Features > features
Features service instance.
Definition: Context.h:177
std::unique_ptr< class TaskManager > taskManager
TaskManager service instance.
Definition: Context.h:186
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....