-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathVertexHashTable.h
125 lines (121 loc) · 4.02 KB
/
VertexHashTable.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#pragma once
// C++ libs
#include <memory>
// CUDA stuff
#include <cuda_runtime.h>
#include <device_launch_parameters.h>
// Project files
#include "helper_cuda.h"
namespace p_mc {
/// <summary>
/// Hash table to construct a shared vertex triangle mesh using the
/// standard Marching Cubes algorithms. Triangles are also constructed
/// for rendering purposes.
/// </summary>
struct VertexHashTable {
using uint = unsigned int;
/// size of buffers
int t_size{ 0 };
/// key buffer
int* key{ nullptr };
std::shared_ptr<int> key_{ nullptr };
/// index buffer
int* index{ nullptr };
std::shared_ptr<int> index_{ nullptr };
/// constructors
__host__ VertexHashTable() {}
__host__ VertexHashTable(const int sz) : t_size{ sz }
{
cudaMalloc(&key, sz * sizeof(int));
cudaMalloc(&index, sz * sizeof(int));
cudaCheckError();
key_.reset(key, cudaFree);
index_.reset(index, cudaFree);
}
/// <summary>
/// Destructor
/// </summary>
/// <returns></returns>
__host__ ~VertexHashTable()
{
t_size = 0;
key = nullptr;
key_.reset();
index = nullptr;
index_.reset();
}
/// get size of buffers
__host__ __device__ int size() { return t_size; }
/// set default values
__device__ void init(const int pos)
{
key[pos] = EMPTY_BUCKET_32;
index[pos] = INVALID_INDEX;
}
/// simple hash function
__device__ int hash(const int k)
{
return ((3ll * static_cast<unsigned long long>(k)) % 300000007ll) % t_size;
}
/// a bit mix hash function
__device__ uint hash_function(uint key)
{
key = (key ^ 61) ^ (key >> 16);
key = key + (key << 3);
key = key ^ (key >> 4);
key = key * 0x27d4eb2d;
key = key ^ (key >> 15);
return key;
}
/// <summary>
/// Add vertex into the hash table
/// </summary>
/// <param name="k">key</param>
/// <param name="addr">buffer to keep address of bucket, where vertex was added</param>
/// <param name="pos">position in vertex buffer</param>
/// <returns></returns>
__device__ bool addVertex(const int k, int* addr, const int pos)
{
const int start_address = hash(k);
int h = start_address;
int e = 1;
for (int loop = 0; loop < 128; loop++) {
const int old = atomicCAS(&key[h], EMPTY_BUCKET_32, k);
//if (old == EMPTY_BUCKET_32 || old == k)
if (old == EMPTY_BUCKET_32)
{
// vertex has to be created, return bucket address in field
addr[pos] = h;
return false;
}
else if (old == k)
{
// vertex already exists, return bucket address for this key
addr[pos] = h;
return true;
}
else
{
// step with quadratic probing
h = (h + e * e) % t_size;
e = e + 1;
if (h == start_address) {
addr[pos] = -1;
return false;
}
}
}
addr[pos] = -1;
return false; // something went wrong
}
/// access vertex index
__device__ int v(const int pos) { return index[pos]; }
/// <summary>
/// Set vertex index
/// </summary>
/// <param name="pos">bucket address</param>
/// <param name="val">index to be set</param>
/// <returns></returns>
__device__ void set(const int pos, const int val) { index[pos] = val; }
};
} // namespace p_mc