File: UniformAligner.h

package info (click to toggle)
freespace2 24.2.0%2Brepack-1
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 43,716 kB
  • sloc: cpp: 595,001; ansic: 21,741; python: 1,174; sh: 457; makefile: 248; xml: 181
file content (109 lines) | stat: -rw-r--r-- 3,104 bytes parent folder | download | duplicates (2)
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
#pragma once

#include "globalincs/pstypes.h"

#include <cstddef>
#include <cstdint>
#include <vector>

namespace graphics {
namespace util {

size_t alignSize(size_t size, size_t align);

/**
 * @brief Aligns data so that each element starts at a specific offset. Useful for storing uniform buffer data
 */
class UniformAligner {
 private:
	static_assert(sizeof(uint8_t) == 1, "A uint8_t must be exactly one byte!");

	size_t _requiredAlignment = 1;

	uint8_t* _buffer    = nullptr;
	size_t _buffer_size = 0;

	size_t _buffer_offset = 0;
	size_t _numElements   = 0;

	size_t _dataSize = 0;
	size_t _headerSize = 0;

  public:
	UniformAligner();
	UniformAligner(uint8_t* buffer, size_t buffer_size, size_t dataSize, size_t headerSize, size_t element_alignment);

	void* addElement();

	template <typename T>
	T* addTypedElement()
	{
		Assertion(sizeof(T) == _dataSize,
		          "Sizes of template parameter and runtime size do not match! This probably uses the wrong type.");
		static_assert(std::is_trivially_copyable<T>::value, "Element type must be trivially copyable!");

		return reinterpret_cast<T*>(addElement());
	}

	template<typename THeader>
	THeader* getHeader() {
		Assertion(sizeof(THeader) == _headerSize, "Header size does not match requested header type!");
		static_assert(std::is_trivially_copyable<THeader>::value, "Header type must be trivially copyable!");

		return reinterpret_cast<THeader*>(_buffer);
	}

	void* getElement(size_t index);

	template<typename T>
	T* getTypedElement(size_t index) {
		Assertion(sizeof(T) == _dataSize,
				  "Sizes of template parameter and runtime size do not match! This probably uses the wrong type.");
		static_assert(std::is_trivially_copyable<T>::value, "Element type must be trivially copyable!");

		return reinterpret_cast<T*>(getElement(index));
	}

	size_t getOffset(size_t index);

	/**
	 * @brief Gets the offset of the last element in the aligner
	 * @return The offset in bytes
	 */
	size_t getCurrentOffset();

	template<typename T>
	T* nextTypedElement(T* currentEl) {
		Assertion(sizeof(T) == _dataSize,
				  "Sizes of template parameter and runtime size do not match! This probably uses the wrong type.");
		static_assert(std::is_trivially_copyable<T>::value, "Element type must be trivially copyable!");

		return reinterpret_cast<T*>(nextElement(reinterpret_cast<void*>(currentEl)));
	}

	void* nextElement(void* currentEl);

	size_t getNumElements();

	/**
	 * @brief Gets the size in bytes of the data in this aligner
	 * @return The size in bytes
	 */
	size_t getSize();

	void* getData();

	/**
	 * @brief Determine the size a buffer must have for the specified parameters
	 * @param num_elements The number of elements to be stored in the buffer
	 * @param alignment The required alignment for the start of the individual elements
	 * @param dataSize The size of one data element.
	 * @param headerSize The size of the header data
	 * @return The size in bytes required for storing all the data
	 */
	static size_t getBufferSize(size_t num_elements, size_t alignment, size_t dataSize, size_t headerSize = 0);
};

}
}