Mercurial > games > semicongine
comparison src/zamikongine/vertex.nim @ 32:9edca5dc4e93
add: working implementation of uniforms
author | Sam <sam@basx.dev> |
---|---|
date | Sat, 14 Jan 2023 23:34:50 +0700 |
parents | b55d6ecde79d |
children | 94c38e4b5782 |
comparison
equal
deleted
inserted
replaced
31:0996104ad066 | 32:9edca5dc4e93 |
---|---|
2 import std/strutils | 2 import std/strutils |
3 import std/strformat | 3 import std/strformat |
4 import std/typetraits | 4 import std/typetraits |
5 | 5 |
6 import ./math/vector | 6 import ./math/vector |
7 import ./math/matrix | |
7 import ./vulkan | 8 import ./vulkan |
9 import ./glsl_helpers | |
8 | 10 |
9 type | 11 type |
10 VertexAttributeType = SomeNumber|Vec | 12 VertexAttributeType = SomeNumber|Vec |
11 VertexAttribute*[T:VertexAttributeType] = object | 13 AttributePurpose* = enum |
14 Unknown, Position Color | |
15 GenericAttribute*[T:VertexAttributeType] = object | |
12 data*: seq[T] | 16 data*: seq[T] |
17 PositionAttribute*[T:VertexAttributeType] = object | |
18 data*: seq[T] | |
19 ColorAttribute*[T:VertexAttributeType] = object | |
20 data*: seq[T] | |
21 VertexAttribute* = GenericAttribute|PositionAttribute|ColorAttribute | |
13 | 22 |
14 template rawAttributeType(v: VertexAttribute): auto = get(genericParams(typeof(v)), 0) | 23 template getAttributeType*(v: VertexAttribute): auto = get(genericParams(typeof(v)), 0) |
15 | 24 |
16 func datasize*(attribute: VertexAttribute): uint64 = | 25 func datasize*(attribute: VertexAttribute): uint64 = |
17 uint64(sizeof(rawAttributeType(attribute))) * uint64(attribute.data.len) | 26 uint64(sizeof(getAttributeType(attribute))) * uint64(attribute.data.len) |
18 | 27 |
19 # from https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap15.html | 28 # from https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap15.html |
20 func nLocationSlots[T: VertexAttributeType](): int = | 29 func nLocationSlots[T: VertexAttributeType](): int = |
21 when (T is Vec3[float64] or T is Vec3[uint64] or T is Vec4[float64] or T is Vec4[float64]): | 30 when (T is Vec3[float64] or T is Vec3[uint64] or T is Vec4[float64] or T is Vec4[float64]): |
22 2 | 31 2 |
64 elif T is Vec4[uint64]: VK_FORMAT_R64G64B64A64_UINT | 73 elif T is Vec4[uint64]: VK_FORMAT_R64G64B64A64_UINT |
65 elif T is Vec4[int64]: VK_FORMAT_R64G64B64A64_SINT | 74 elif T is Vec4[int64]: VK_FORMAT_R64G64B64A64_SINT |
66 elif T is Vec4[float32]: VK_FORMAT_R32G32B32A32_SFLOAT | 75 elif T is Vec4[float32]: VK_FORMAT_R32G32B32A32_SFLOAT |
67 elif T is Vec4[float64]: VK_FORMAT_R64G64B64A64_SFLOAT | 76 elif T is Vec4[float64]: VK_FORMAT_R64G64B64A64_SFLOAT |
68 | 77 |
69 func getGLSLType[T: VertexAttributeType](): string = | |
70 # todo: likely not correct as we would need to enable some | |
71 # extensions somewhere (Vulkan/GLSL compiler?) to have | |
72 # everything work as intended. Or maybe the GPU driver does | |
73 # some automagic conversion stuf.. | |
74 when T is uint8: "uint" | |
75 elif T is int8: "int" | |
76 elif T is uint16: "uint" | |
77 elif T is int16: "int" | |
78 elif T is uint32: "uint" | |
79 elif T is int32: "int" | |
80 elif T is uint64: "uint" | |
81 elif T is int64: "int" | |
82 elif T is float32: "float" | |
83 elif T is float64: "double" | |
84 | |
85 elif T is Vec2[uint8]: "uvec2" | |
86 elif T is Vec2[int8]: "ivec2" | |
87 elif T is Vec2[uint16]: "uvec2" | |
88 elif T is Vec2[int16]: "ivec2" | |
89 elif T is Vec2[uint32]: "uvec2" | |
90 elif T is Vec2[int32]: "ivec2" | |
91 elif T is Vec2[uint64]: "uvec2" | |
92 elif T is Vec2[int64]: "ivec2" | |
93 elif T is Vec2[float32]: "vec2" | |
94 elif T is Vec2[float64]: "dvec2" | |
95 | |
96 elif T is Vec3[uint8]: "uvec3" | |
97 elif T is Vec3[int8]: "ivec3" | |
98 elif T is Vec3[uint16]: "uvec3" | |
99 elif T is Vec3[int16]: "ivec3" | |
100 elif T is Vec3[uint32]: "uvec3" | |
101 elif T is Vec3[int32]: "ivec3" | |
102 elif T is Vec3[uint64]: "uvec3" | |
103 elif T is Vec3[int64]: "ivec3" | |
104 elif T is Vec3[float32]: "vec3" | |
105 elif T is Vec3[float64]: "dvec3" | |
106 | |
107 elif T is Vec4[uint8]: "uvec4" | |
108 elif T is Vec4[int8]: "ivec4" | |
109 elif T is Vec4[uint16]: "uvec4" | |
110 elif T is Vec4[int16]: "ivec4" | |
111 elif T is Vec4[uint32]: "uvec4" | |
112 elif T is Vec4[int32]: "ivec4" | |
113 elif T is Vec4[uint64]: "uvec4" | |
114 elif T is Vec4[int64]: "ivec4" | |
115 elif T is Vec4[float32]: "vec4" | |
116 elif T is Vec4[float64]: "dvec4" | |
117 | 78 |
118 | 79 |
119 func VertexCount*[T](t: T): uint32 = | 80 func VertexCount*[T](t: T): uint32 = |
120 for name, value in t.fieldPairs: | 81 for name, value in t.fieldPairs: |
121 when typeof(value) is VertexAttribute: | 82 when typeof(value) is VertexAttribute: |
122 if result == 0: | 83 if result == 0: |
123 result = uint32(value.data.len) | 84 result = uint32(value.data.len) |
124 else: | 85 else: |
125 assert result == uint32(value.data.len) | 86 assert result == uint32(value.data.len) |
126 | 87 |
127 func generateGLSLDeclarations*[T](): string = | 88 func generateGLSLVertexDeclarations*[T](): string = |
128 var stmtList: seq[string] | 89 var stmtList: seq[string] |
129 var i = 0 | 90 var i = 0 |
130 for name, value in T().fieldPairs: | 91 for name, value in T().fieldPairs: |
131 when typeof(value) is VertexAttribute: | 92 when typeof(value) is VertexAttribute: |
132 let glsltype = getGLSLType[rawAttributeType(value)]() | 93 let glsltype = getGLSLType[getAttributeType(value)]() |
133 let n = name | 94 let n = name |
134 stmtList.add(&"layout(location = {i}) in {glsltype} {n};") | 95 stmtList.add(&"layout(location = {i}) in {glsltype} {n};") |
135 i += nLocationSlots[rawAttributeType(value)]() | 96 i += nLocationSlots[getAttributeType(value)]() |
136 | 97 |
137 return stmtList.join("\n") | 98 return stmtList.join("\n") |
138 | 99 |
139 func generateInputVertexBinding*[T](bindingoffset: int = 0, locationoffset: int = 0): seq[VkVertexInputBindingDescription] = | 100 func generateInputVertexBinding*[T](bindingoffset: int = 0, locationoffset: int = 0): seq[VkVertexInputBindingDescription] = |
140 # packed attribute data, not interleaved (aks "struct of arrays") | 101 # packed attribute data, not interleaved (aks "struct of arrays") |
142 for name, value in T().fieldPairs: | 103 for name, value in T().fieldPairs: |
143 when typeof(value) is VertexAttribute: | 104 when typeof(value) is VertexAttribute: |
144 result.add( | 105 result.add( |
145 VkVertexInputBindingDescription( | 106 VkVertexInputBindingDescription( |
146 binding: uint32(binding), | 107 binding: uint32(binding), |
147 stride: uint32(sizeof(rawAttributeType(value))), | 108 stride: uint32(sizeof(getAttributeType(value))), |
148 inputRate: VK_VERTEX_INPUT_RATE_VERTEX, # VK_VERTEX_INPUT_RATE_INSTANCE for instances | 109 inputRate: VK_VERTEX_INPUT_RATE_VERTEX, # VK_VERTEX_INPUT_RATE_INSTANCE for instances |
149 ) | 110 ) |
150 ) | 111 ) |
151 binding += 1 | 112 binding += 1 |
152 | 113 |
158 when typeof(value) is VertexAttribute: | 119 when typeof(value) is VertexAttribute: |
159 result.add( | 120 result.add( |
160 VkVertexInputAttributeDescription( | 121 VkVertexInputAttributeDescription( |
161 binding: uint32(binding), | 122 binding: uint32(binding), |
162 location: uint32(location), | 123 location: uint32(location), |
163 format: getVkFormat[rawAttributeType(value)](), | 124 format: getVkFormat[getAttributeType(value)](), |
164 offset: 0, | 125 offset: 0, |
165 ) | 126 ) |
166 ) | 127 ) |
167 location += nLocationSlots[rawAttributeType(value)]() | 128 location += nLocationSlots[getAttributeType(value)]() |
168 binding += 1 | 129 binding += 1 |