1#ifndef VULKAN_VERTEXINPUT
2#define VULKAN_VERTEXINPUT
21 template<
template<
int,
typename, glm::qualifier>
class Vec,
int n,
typename Type, glm::qualifier packing>
22 constexpr bool isGlmVec(Vec<n, Type, packing>) {
23 return n > 0 && n <= 4 &&
24 std::is_fundamental<Type>::value &&
25 std::same_as <Vec<n, Type, packing>, glm::vec<n, Type, packing>>;
29 concept IsVertex =
requires(T,
unsigned int i) {
30 {T::getDescriptors(i)} -> std::same_as<std::pair<VkVertexInputBindingDescription, std::vector<VkVertexInputAttributeDescription>>>;
53 template<
int componentsAmount>
54 class VertexProperties {
60 struct ComponentProperties {
61 unsigned int scalarAmount;
67 std::array<ComponentProperties, componentsAmount> componentsProperties;
69 int arrayDimension = 0;
84 template<
template<
int,
typename, glm::qualifier>
class Vec,
int n,
typename Type, glm::qualifier packing>
requires(isGlmVec(Vec<n, Type, packing>{}))
85 void addComponent(Vec<n, Type, packing>, std::array<size_t, componentsAmount> tupleOffsets) {
86 componentsProperties.at(arrayDimension) = ComponentProperties{ n,
sizeof(Type), tupleOffsets[arrayDimension]};
87 componentsProperties.at(arrayDimension).format = findRightFormat<Type, n>();
88 stride +=
sizeof(Vec<n, Type, packing>);
98 template<
typename Type,
int scalarAmount>
99 static VkFormat findRightFormat() {
101 std::string format =
"VK_FORMAT_";
102 std::string length = std::to_string(
sizeof(Type) * 8);
105 for (
int i = 1; i <= scalarAmount; ++i) {
106 format += RGBA(i) + length;
110 std::string type = std::is_floating_point_v<Type> ?
"SFLOAT" :
111 std::is_unsigned_v<Type> ?
"UINT" :
"SINT";
115 std::map<std::string, VkFormat> formats = {
116 {
"VK_FORMAT_R16_UINTx", VK_FORMAT_R16_UINT},
117 {
"VK_FORMAT_R16_SINT", VK_FORMAT_R16_SINT},
118 {
"VK_FORMAT_R16_SFLOAT", VK_FORMAT_R16_SFLOAT},
119 {
"VK_FORMAT_R16G16_UNORM", VK_FORMAT_R16G16_UNORM},
120 {
"VK_FORMAT_R16G16_SNORM", VK_FORMAT_R16G16_SNORM},
121 {
"VK_FORMAT_R16G16_USCALED", VK_FORMAT_R16G16_USCALED},
122 {
"VK_FORMAT_R16G16_SSCALED", VK_FORMAT_R16G16_SSCALED},
123 {
"VK_FORMAT_R16G16_UINT", VK_FORMAT_R16G16_UINT},
124 {
"VK_FORMAT_R16G16_SINT", VK_FORMAT_R16G16_SINT},
125 {
"VK_FORMAT_R16G16_SFLOAT", VK_FORMAT_R16G16_SFLOAT},
126 {
"VK_FORMAT_R16G16B16_UNORM", VK_FORMAT_R16G16B16_UNORM},
127 {
"VK_FORMAT_R16G16B16_SNORM", VK_FORMAT_R16G16B16_SNORM},
128 {
"VK_FORMAT_R16G16B16_USCALED", VK_FORMAT_R16G16B16_USCALED},
129 {
"VK_FORMAT_R16G16B16_SSCALED", VK_FORMAT_R16G16B16_SSCALED},
130 {
"VK_FORMAT_R16G16B16_UINT", VK_FORMAT_R16G16B16_UINT},
131 {
"VK_FORMAT_R16G16B16_SINT", VK_FORMAT_R16G16B16_SINT},
132 {
"VK_FORMAT_R16G16B16_SFLOAT", VK_FORMAT_R16G16B16_SFLOAT},
133 {
"VK_FORMAT_R16G16B16A16_UNORM", VK_FORMAT_R16G16B16A16_UNORM},
134 {
"VK_FORMAT_R16G16B16A16_SNORM", VK_FORMAT_R16G16B16A16_SNORM},
135 {
"VK_FORMAT_R16G16B16A16_USCALED", VK_FORMAT_R16G16B16A16_USCALED},
136 {
"VK_FORMAT_R16G16B16A16_SSCALED", VK_FORMAT_R16G16B16A16_SSCALED},
137 {
"VK_FORMAT_R16G16B16A16_UINT", VK_FORMAT_R16G16B16A16_UINT},
138 {
"VK_FORMAT_R16G16B16A16_SINT", VK_FORMAT_R16G16B16A16_SINT},
139 {
"VK_FORMAT_R16G16B16A16_SFLOAT", VK_FORMAT_R16G16B16A16_SFLOAT},
140 {
"VK_FORMAT_R32_UINT", VK_FORMAT_R32_UINT},
141 {
"VK_FORMAT_R32_SINT", VK_FORMAT_R32_SINT},
142 {
"VK_FORMAT_R32_SFLOAT", VK_FORMAT_R32_SFLOAT},
143 {
"VK_FORMAT_R32G32_UINT", VK_FORMAT_R32G32_UINT},
144 {
"VK_FORMAT_R32G32_SINT", VK_FORMAT_R32G32_SINT},
145 {
"VK_FORMAT_R32G32_SFLOAT", VK_FORMAT_R32G32_SFLOAT},
146 {
"VK_FORMAT_R32G32B32_UINT", VK_FORMAT_R32G32B32_UINT},
147 {
"VK_FORMAT_R32G32B32_SINT", VK_FORMAT_R32G32B32_SINT},
148 {
"VK_FORMAT_R32G32B32_SFLOAT", VK_FORMAT_R32G32B32_SFLOAT},
149 {
"VK_FORMAT_R32G32B32A32_UINT", VK_FORMAT_R32G32B32A32_UINT},
150 {
"VK_FORMAT_R32G32B32A32_SINT", VK_FORMAT_R32G32B32A32_SINT},
151 {
"VK_FORMAT_R32G32B32A32_SFLOAT", VK_FORMAT_R32G32B32A32_SFLOAT},
152 {
"VK_FORMAT_R64_UINT", VK_FORMAT_R64_UINT},
153 {
"VK_FORMAT_R64_SINT", VK_FORMAT_R64_SINT},
154 {
"VK_FORMAT_R64_SFLOAT", VK_FORMAT_R64_SFLOAT},
155 {
"VK_FORMAT_R64G64_UINT", VK_FORMAT_R64G64_UINT},
156 {
"VK_FORMAT_R64G64_SINT", VK_FORMAT_R64G64_SINT},
157 {
"VK_FORMAT_R64G64_SFLOAT", VK_FORMAT_R64G64_SFLOAT},
158 {
"VK_FORMAT_R64G64B64_UINT", VK_FORMAT_R64G64B64_UINT},
159 {
"VK_FORMAT_R64G64B64_SINT", VK_FORMAT_R64G64B64_SINT},
160 {
"VK_FORMAT_R64G64B64_SFLOAT", VK_FORMAT_R64G64B64_SFLOAT},
161 {
"VK_FORMAT_R64G64B64A64_UINT", VK_FORMAT_R64G64B64A64_UINT},
162 {
"VK_FORMAT_R64G64B64A64_SINT", VK_FORMAT_R64G64B64A64_SINT},
163 {
"VK_FORMAT_R64G64B64A64_SFLOAT", VK_FORMAT_R64G64B64A64_SFLOAT}
166 return formats[format];
173 static std::string RGBA(
int i) {
188 throw VulkanException(
"Error in the amount of scala amount in the component of a Vertex: 1 <= n <= 4, but n == " + i);
202 template<
int I = 0,
typename... E>
203 static constexpr std::array<size_t,
sizeof...(E)> tupleElementsOffset(
const std::tuple<E...>& tuple) {
204 constexpr size_t elementsInTuple =
sizeof...(E);
205 std::array<size_t, elementsInTuple> result{};
206 result[I] = (
char*)&std::get<I>(tuple) - (
char*)&tuple;
209 if constexpr (I < elementsInTuple - 1) {
210 auto tmp = tupleElementsOffset<I + 1>(tuple);
213 for (
int i = I + 1; i < elementsInTuple; ++i) {
230 template<
typename... Vec>
requires (isGlmVec(Vec{}) && ...)
231 VertexProperties(Vec... components) : stride{ 0 }, componentsProperties{} {
232 auto tupleOffsets = tupleElementsOffset(std::tuple{ components... });
234 (addComponent(components, tupleOffsets), ...);
244 const ComponentProperties& operator[](
unsigned int i) {
245 return componentsProperties.at(i);
266 template<
typename... Vec>
requires (isGlmVec(Vec{}) && ...)
274 Vertex(Vec... vertexComponents) : vertexComponents{ vertexComponents... } {}
277 Vertex() : vertexComponents{} {}
280 friend bool operator==(
const Vertex& v1,
const Vertex& v2) {
281 return v1.vertexComponents == v2.vertexComponents;
291 static std::pair<VkVertexInputBindingDescription, std::vector<VkVertexInputAttributeDescription>> getDescriptors(
unsigned int binding) {
292 VkVertexInputBindingDescription bindingDescription{};
293 bindingDescription.binding = binding;
294 bindingDescription.stride =
sizeof(Vertex);
295 bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
297 std::vector <VkVertexInputAttributeDescription> attributeDescriptions(
sizeof...(Vec));
298 for (
int i = 0; i <
sizeof...(Vec); ++i) {
299 attributeDescriptions[i].binding = binding;
300 attributeDescriptions[i].location = i;
301 attributeDescriptions[i].format = vertexProperties[i].format;
302 attributeDescriptions[i].offset = vertexProperties[i].offset;
305 return { bindingDescription, attributeDescriptions };
310 std::tuple<Vec...> vertexComponents;
311 inline static VertexProperties<
sizeof...(Vec)> vertexProperties = VertexProperties<
sizeof...(Vec)>{ Vec{}... };
328 class PipelineVertexArrays {
331 template<IsVertex... V>
332 PipelineVertexArrays(V...) : vertexArraysDescriptor{} {
335 auto extract = [
this, &i]<IsVertex T>()->
void {
336 auto [bindingDescr, attributeDescrs] = T::getDescriptors(i);
339 this->bindingDescriptors.push_back(bindingDescr);
340 this->attributeDescriptors.insert(this->attributeDescriptors.end(), attributeDescrs.begin(), attributeDescrs.end());
343 ((extract.operator() < V > ()), ...);
347 vertexArraysDescriptor.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
348 vertexArraysDescriptor.vertexBindingDescriptionCount = bindingDescriptors.size();
349 vertexArraysDescriptor.pVertexBindingDescriptions = bindingDescriptors.data();
350 vertexArraysDescriptor.vertexAttributeDescriptionCount = attributeDescriptors.size();
351 vertexArraysDescriptor.pVertexAttributeDescriptions = attributeDescriptors.data();
360 const VkPipelineVertexInputStateCreateInfo&
operator+()
const {
361 return vertexArraysDescriptor;
365 VkPipelineVertexInputStateCreateInfo vertexArraysDescriptor;
366 std::vector<VkVertexInputBindingDescription> bindingDescriptors;
367 std::vector< VkVertexInputAttributeDescription> attributeDescriptors;
Position operator+(Position origin, DeltaSpace spaceCovered)
Definition: Foundations.h:307
Definition: Attachment.h:11