| ... | ... | @@ -56,11 +56,40 @@ const Tag = enum { |
| 56 | 56 | type_array, |
| 57 | 57 | |
| 58 | 58 | // -- Values |
| 59 | /// Value of type f16 |
| 60 | /// data is value |
| 61 | float16, |
| 62 | /// Value of type f32 |
| 63 | /// data is value |
| 64 | float32, |
| 65 | /// Value of type f64 |
| 66 | /// data is payload to Float16 |
| 67 | float64, |
| 59 | 68 | |
| 60 | 69 | const SimpleType = enum { void, bool }; |
| 61 | 70 | |
| 62 | 71 | const VectorType = Key.VectorType; |
| 63 | 72 | const ArrayType = Key.ArrayType; |
| 73 | |
| 74 | const Float64 = struct { |
| 75 | // Low-order 32 bits of the value. |
| 76 | low: u32, |
| 77 | // High-order 32 bits of the value. |
| 78 | high: u32, |
| 79 | |
| 80 | fn encode(value: f64) Float64 { |
| 81 | const bits = @bitCast(u64, value); |
| 82 | return .{ |
| 83 | .low = @truncate(u32, bits), |
| 84 | .high = @truncate(u32, bits >> 32), |
| 85 | }; |
| 86 | } |
| 87 | |
| 88 | fn decode(self: Float64) f64 { |
| 89 | const bits = @as(u64, self.low) | (@as(u64, self.high) << 32); |
| 90 | return @bitCast(f64, bits); |
| 91 | } |
| 92 | }; |
| 64 | 93 | }; |
| 65 | 94 | |
| 66 | 95 | pub const Ref = enum(u32) { _ }; |
| ... | ... | @@ -79,6 +108,7 @@ pub const Key = union(enum) { |
| 79 | 108 | array_type: ArrayType, |
| 80 | 109 | |
| 81 | 110 | // -- values |
| 111 | float: Float, |
| 82 | 112 | |
| 83 | 113 | pub const IntType = std.builtin.Type.Int; |
| 84 | 114 | pub const FloatType = std.builtin.Type.Float; |
| ... | ... | @@ -98,9 +128,33 @@ pub const Key = union(enum) { |
| 98 | 128 | stride: u32 = 0, |
| 99 | 129 | }; |
| 100 | 130 | |
| 131 | /// Represents a numberic value of some type. |
| 132 | pub const Float = struct { |
| 133 | /// The type: 16, 32, or 64-bit float. |
| 134 | ty: Ref, |
| 135 | /// The actual value. |
| 136 | value: Value, |
| 137 | |
| 138 | pub const Value = union(enum) { |
| 139 | float16: f16, |
| 140 | float32: f32, |
| 141 | float64: f64, |
| 142 | }; |
| 143 | }; |
| 144 | |
| 101 | 145 | fn hash(self: Key) u32 { |
| 102 | 146 | var hasher = std.hash.Wyhash.init(0); |
| 103 | | std.hash.autoHash(&hasher, self); |
| 147 | switch (self) { |
| 148 | .float => |float| { |
| 149 | std.hash.autoHash(&hasher, float.ty); |
| 150 | switch (float.value) { |
| 151 | .float16 => |value| std.hash.autoHash(&hasher, @bitCast(u16, value)), |
| 152 | .float32 => |value| std.hash.autoHash(&hasher, @bitCast(u32, value)), |
| 153 | .float64 => |value| std.hash.autoHash(&hasher, @bitCast(u64, value)), |
| 154 | } |
| 155 | }, |
| 156 | inline else => |key| std.hash.autoHash(&hasher, key), |
| 157 | } |
| 104 | 158 | return @truncate(u32, hasher.final()); |
| 105 | 159 | } |
| 106 | 160 | |
| ... | ... | @@ -141,7 +195,7 @@ pub fn deinit(self: *Self, spv: *const Module) void { |
| 141 | 195 | /// This function returns a spir-v section of (only) constant and type instructions. |
| 142 | 196 | /// Additionally, decorations, debug names, etc, are all directly emitted into the |
| 143 | 197 | /// `spv` module. The section is allocated with `spv.gpa`. |
| 144 | | pub fn materialize(self: *Self, spv: *Module) !Section { |
| 198 | pub fn materialize(self: *const Self, spv: *Module) !Section { |
| 145 | 199 | var section = Section{}; |
| 146 | 200 | errdefer section.deinit(spv.gpa); |
| 147 | 201 | for (self.items.items(.result_id), 0..) |result_id, index| { |
| ... | ... | @@ -151,7 +205,7 @@ pub fn materialize(self: *Self, spv: *Module) !Section { |
| 151 | 205 | } |
| 152 | 206 | |
| 153 | 207 | fn emit( |
| 154 | | self: *Self, |
| 208 | self: *const Self, |
| 155 | 209 | spv: *Module, |
| 156 | 210 | result_id: IdResult, |
| 157 | 211 | ref: Ref, |
| ... | ... | @@ -206,9 +260,34 @@ fn emit( |
| 206 | 260 | try spv.decorate(result_id, .{ .ArrayStride = .{ .array_stride = array.stride } }); |
| 207 | 261 | } |
| 208 | 262 | }, |
| 263 | .float => |float| { |
| 264 | const ty_id = self.resultId(float.ty); |
| 265 | const lit: spec.LiteralContextDependentNumber = switch (float.value) { |
| 266 | .float16 => |value| .{ .uint32 = @bitCast(u16, value) }, |
| 267 | .float32 => |value| .{ .float32 = value }, |
| 268 | .float64 => |value| .{ .float64 = value }, |
| 269 | }; |
| 270 | try section.emit(spv.gpa, .OpConstant, .{ |
| 271 | .id_result_type = ty_id, |
| 272 | .id_result = result_id, |
| 273 | .value = lit, |
| 274 | }); |
| 275 | }, |
| 209 | 276 | } |
| 210 | 277 | } |
| 211 | 278 | |
| 279 | /// Get the ref for a key that has already been added to the cache. |
| 280 | fn get(self: *const Self, key: Key) Ref { |
| 281 | const adapter: Key.Adapter = .{ .self = self }; |
| 282 | const index = self.map.getIndexAdapted(key, adapter).?; |
| 283 | return @intToEnum(Ref, index); |
| 284 | } |
| 285 | |
| 286 | /// Get the result-id for a key that has already been added to the cache. |
| 287 | fn getId(self: *const Self, key: Key) IdResult { |
| 288 | return self.resultId(self.get(key)); |
| 289 | } |
| 290 | |
| 212 | 291 | /// Add a key to this cache. Returns a reference to the key that |
| 213 | 292 | /// was added. The corresponding result-id can be queried using |
| 214 | 293 | /// self.resultId with the result. |
| ... | ... | @@ -251,6 +330,24 @@ pub fn resolve(self: *Self, spv: *Module, key: Key) !Ref { |
| 251 | 330 | .result_id = result_id, |
| 252 | 331 | .data = try self.addExtra(spv, array), |
| 253 | 332 | }, |
| 333 | .float => |float| switch (self.lookup(float.ty).float_type.bits) { |
| 334 | 16 => .{ |
| 335 | .tag = .float16, |
| 336 | .result_id = result_id, |
| 337 | .data = @bitCast(u16, float.value.float16), |
| 338 | }, |
| 339 | 32 => .{ |
| 340 | .tag = .float32, |
| 341 | .result_id = result_id, |
| 342 | .data = @bitCast(u32, float.value.float32), |
| 343 | }, |
| 344 | 64 => .{ |
| 345 | .tag = .float64, |
| 346 | .result_id = result_id, |
| 347 | .data = try self.addExtra(spv, Tag.Float64.encode(float.value.float64)), |
| 348 | }, |
| 349 | else => unreachable, |
| 350 | }, |
| 254 | 351 | }; |
| 255 | 352 | try self.items.append(spv.gpa, item); |
| 256 | 353 | |
| ... | ... | @@ -285,6 +382,18 @@ pub fn lookup(self: *const Self, ref: Ref) Key { |
| 285 | 382 | } }, |
| 286 | 383 | .type_vector => .{ .vector_type = self.extraData(Tag.VectorType, data) }, |
| 287 | 384 | .type_array => .{ .array_type = self.extraData(Tag.ArrayType, data) }, |
| 385 | .float16 => .{ .float = .{ |
| 386 | .ty = self.get(.{ .float_type = .{ .bits = 16 } }), |
| 387 | .value = .{ .float16 = @bitCast(f16, @intCast(u16, data)) }, |
| 388 | } }, |
| 389 | .float32 => .{ .float = .{ |
| 390 | .ty = self.get(.{ .float_type = .{ .bits = 32 } }), |
| 391 | .value = .{ .float32 = @bitCast(f32, data) }, |
| 392 | } }, |
| 393 | .float64 => .{ .float = .{ |
| 394 | .ty = self.get(.{ .float_type = .{ .bits = 32 } }), |
| 395 | .value = .{ .float64 = self.extraData(Tag.Float64, data).decode() }, |
| 396 | } }, |
| 288 | 397 | }; |
| 289 | 398 | } |
| 290 | 399 | |