-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathshaders.nim
301 lines (239 loc) · 9.49 KB
/
shaders.nim
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
import std/macros
{.experimental: "dotOperators".}
type
ShaderStage* = enum
Vertex = 0
TessellationControl = 1
TessellationEvaluation = 2
Geometry = 3
Fragment = 4
GLCompute = 5
# OpenCL
Kernel = 6
# Turing stages
Task = 5267
Mesh = 5268
RayGeneration = 5313
Intersection = 5314
AnyHit = 5315
ClosestHit = 5316
Miss = 5317
Callable = 5318
BuiltIn* = enum
Position = 0
VertexId = 5
InstanceId = 6
PrimitiveId = 7
NumWorkgroups = 24
WorkgroupSize = 25
WorkgroupId = 26
LocalInvocationId = 27
GlobalInvocationId = 28
LocalInvocationIndex = 29
SubgroupSize = 36
NumSubgroups = 38
SubgroupId = 40
SubgroupLocalInvocationId = 41
SubgroupEqMask = 4416
SubgroupGeMask = 4417
SubgroupGtMask = 4418
SubgroupLeMask = 4419
SubgroupLtMask = 4420
float16* {.importc: "float16".} = object
Vector* {.importc: "Vector".} [T; size: static[int]] = object
MatrixBase* {.importc: "Matrix".} [T; width: static[int]] = object
Matrix* [T; height, width: static[int]] = MatrixBase[Vector[T, height], width]
Vector2* = Vector[float32, 2]
Vector3* = Vector[float32, 3]
Vector4* = Vector[float32, 4]
Matrix3x3* = Matrix[float32, 3, 3]
Matrix4x3* = Matrix[float32, 4, 3]
Matrix4x4* = Matrix[float32, 4, 4]
DepthKind* {.pure} = enum
HasDepth
HasNoDepth
Unspecified
Dimension* {.pure.} = enum
Image1D
Image2D
Image3D
Cube
Rect
Buffer
SubpassData
ArrayKind* {.pure.} = enum
NonArray
Array
MultisampleKind* {.pure.} = enum
SingleSample
MultiSample
SampleKind* {.pure.} = enum
Unspecified
Sampled
Storage
Format* {.pure.} = enum
Unknown = 0
R32f = 3
R16f = 9
AccessQualifier* {.pure.} = enum
ReadOnly
WriteOnly
ReadWrite
Image* [T;
dim: static[Dimension];
depth: static[DepthKind];
arrayed: static[ArrayKind];
ms: static[MultisampleKind];
sampled: static[SampleKind];
format: static[Format];
access: static[AccessQualifier]] {.importc.} = object
Image2D* = Image[void, Dimension.Image2D,
DepthKind.Unspecified, ArrayKind.NonArray,
MultisampleKind.SingleSample, SampleKind.Sampled,
Format.Unknown, AccessQualifier.ReadOnly]
AddressingMode* {.pure.} = enum
None
ClampToEdge
Clamp
Repeat
RepeatMirrored
FilterMode* {.pure.} = enum
Nearest
Linear
Sampler* {.importc.} = object
SampledImage* [T: Image] {.importc.} = object
# template coordType[X: Image](_: typedesc[X]): untyped =
# int
# # var count = 1
# # case T.dimension:
# # of Image1D, Buffer: count = 1
# # of Image2D, Rect, SubpassData: count = 2
proc sampledImage*[T: Image](image: T; sampler: Sampler): SampledImage[T] {.importc: "OpSampledImage".}
proc image*[T: Image](image: SampledImage[T]): T {.importc: "OpImage".}
proc read*(image: Image; coordinate: Vector): Image.T {.importc: "OpImageRead".}
proc sample*(image: SampledImage; coordinate: Vector): SampledImage.T.T {.importc: "OpImageSampleImplicitLod".}
proc sample*(image: SampledImage; coordinate: Vector; bias: SomeFloat): SampledImage.T.T {.importc: "OpImageSampleImplicitLod".}
proc sample*(image: SampledImage; coordinate: Vector; constOffset: distinct Vector): SampledImage.T.T {.importc: "OpImageSampleImplicitLod".}
func `[]`*(self: Vector; index: int): Vector.T {.importc.}
func `[]=`*(self: var Vector; index: int; value: Vector.T) {.importc.}
func `-`*[T: SomeFloat; size: static[int]](self: Vector[T, size]): Vector[T, size] {.importc: "OpFNegate".}
func `+`*[T: SomeFloat; size: static[int]](left, right: Vector[T, size]): Vector[T, size] {.importc: "OpFAdd".}
func `-`*[T: SomeFloat; size: static[int]](left, right: Vector[T, size]): Vector[T, size] {.importc: "OpFSub".}
func `*`*[T: SomeFloat; size: static[int]](left, right: Vector[T, size]): Vector[T, size] {.importc: "OpFMul".}
func `/`*[T: SomeFloat; size: static[int]](left, right: Vector[T, size]): Vector[T, size] {.importc: "OpFDiv".}
func construct*[T](): T {.varargs, importc: "OpCompositeConstruct".}
# proc toVector*[T; size: static[int]](args: varargs[T]): Vector[T, size] =
# construct[Vector[T, size]](args)
func `*`*[T; size: static[int]](left: Vector[T, size]; right: T): Vector[T, size] {.importc: "OpVectorTimesScalar".}
func `*`*[T; height, width: static[int]](left: Matrix[T, height, width]; right: T): Matrix[T, height, width] {.importc: "OpMatrixTimesScalar".}
func `*`*[T; height, width: static[int]](left: Matrix[T, height, width]; right: Vector[T, width]): Vector[T, width] {.importc: "OpMatrixTimesVector".}
func `*`*[T; height, width: static[int]](left: Vector[T, height]; right: Matrix[T, height, width]): Vector[T, height] {.importc: "OpVectorTimesMatrix".}
func `*`*[T; height, width, size: static[int]](left: Matrix[T, height, size]; right: Matrix[T, size, width]): Matrix[T, height, width] {.importc: "OpMatrixTimesMatrix".}
template stage*(ShaderStage) {.pragma.}
template builtIn*(BuiltIn) {.pragma.}
template location*(int) {.pragma.}
template binding*(int) {.pragma.}
template descriptorSet*(int) {.pragma.}
template input*() {.pragma.}
template output*() {.pragma.}
template uniform*() {.pragma.}
template rowMajor*() {.pragma.}
# Vector swizzles
func getSwizzleIndex(c: char): int {.compileTime.} =
case c:
of 'x', 'r': return 0
of 'y', 'g': return 1
of 'z', 'b': return 2
of 'w', 'a': return 3
else: raiseAssert($c & " is not a valid vector swizzle")
# Assumes `[]` operator and the convertor from arrays on vectors
macro `.`*(self: Vector; swizzle: untyped): untyped =
var
cardinality = ($swizzle).len
# For one-element swizzles, just return the scalar element
# v.elements[0]
if cardinality == 1:
return nnkBracketExpr.newTree(self, newIntLitNode(($swizzle)[0].getSwizzleIndex))
else:
# The result is a call to `construct`
result = nnkCall.newTree()
# The first argument is the symbol of the appropriate generic instance of `construct`
result.add quote do:
construct[Vector[type(`self`).T, `cardinality`]]
# Add the call arguments, one for each swizzle index
# [temp[1], temp[0], ...]
for c in $swizzle:
result.add(nnkBracketExpr.newTree(self, newIntLitNode(c.getSwizzleIndex)))
# Assumes `[]` and `[]=` operators on vectors
macro `.=`*(self: var Vector; swizzle: untyped; value: untyped): untyped =
var
cardinality = ($swizzle).len
# For single elements, just do single assignment
if cardinality == 1:
return newAssignment(nnkBracketExpr.newTree(self, newIntLitNode(($swizzle)[0].getSwizzleIndex)), value)
else:
var temp = genSym()
# Evaluate the right-hand side into a temporary variable
# let temp = self
result = newStmtList(
nnkLetSection.newTree(
newIdentDefs(temp, newEmptyNode(), value)))
# For each swizzle index, add an assignment of the corresponding element
# self[swizzleIndex(c)] = temp[i]
for i, c in $swizzle:
result.add(
newAssignment(
nnkBracketExpr.newTree(self, newIntLitNode(c.getSwizzleIndex)),
nnkBracketExpr.newTree(temp, newIntLitNode(i))))
# func getMatrixSwizzles(swizzle: string): seq[(int, int)] {.compileTime.} =
# #assert(match(swizzle, re"(m\d\d)*"), "'" & swizzle & "' is not a valid matrix swizzling")
# assert(swizzle.len mod 3 == 0, "'" & swizzle & "' is not a valid matrix swizzling pattern")
# result = newSeqOfCap[(int, int)](swizzle.len div 3)
# for i in countup(0, swizzle.len - 1, 3):
# assert(swizzle[i] == 'm' and swizzle[i + 1].isDigit and swizzle[i + 2].isDigit, "'" & swizzle & "' is not a valid matrix swizzling pattern")
# result.add((parseInt($swizzle[i + 1]), parseInt($swizzle[i + 2])))
# macro `.`*(self: Matrix; swizzle: untyped): untyped =
# var
# indices = getMatrixSwizzles($swizzle)
# cardinality = indices.len
# # For one-element swizzles, just return the scalar element
# # v.elements[0]
# if cardinality == 1:
# let (row, column) = indices[0]
# return nnkBracketExpr.newTree(self, newIntLitNode(row), newIntLitNode(column))
# else:
# var
# values = newNimNode(nnkBracket)
# temp = genSym()
# # Make an array of values, one for each swizzle index
# # [temp[1, 2], temp[0, 3], ...]
# for index in indices:
# let (row, column) = index
# values.add(nnkBracketExpr.newTree(temp, newIntLitNode(row), newIntLitNode(column)))
# return quote do:
# let `temp` = `self`
# toVector[`temp`.T, `cardinality`](`values`)
# # Assumes `[]` and `[]=` operators on matrices
# macro `.=`*(self: var Matrix; swizzle: untyped; value: untyped): untyped =
# var
# indices = getMatrixSwizzles($swizzle)
# cardinality = indices.len
# # For single elements, just do single assignment
# if cardinality == 1:
# let (row, column) = indices[0]
# return newAssignment(nnkBracketExpr.newTree(self, newIntLitNode(row), newIntLitNode(column)), value)
# else:
# var temp = genSym()
# # Evaluate the right-hand side into a temporary variable
# # let temp = self
# result = newStmtList(
# nnkLetSection.newTree(
# newIdentDefs(temp, newEmptyNode(), value)))
# # For each swizzle index, add an assignment of the corresponding element
# # self[swizzleIndex(c)] = temp[i]
# for i, pos in indices:
# let (row, column) = pos
# result.add(
# newAssignment(
# nnkBracketExpr.newTree(self, newIntLitNode(row), newIntLitNode(column)),
# nnkBracketExpr.newTree(temp, newIntLitNode(i))))