| ... | @@ -56,11 +56,40 @@ const Tag = enum { | ... | @@ -56,11 +56,40 @@ const Tag = enum { |
| 56 | type_array, | 56 | type_array, |
| 57 | | 57 | |
| 58 | // -- Values | 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 | const SimpleType = enum { void, bool }; | 69 | const SimpleType = enum { void, bool }; |
| 61 | | 70 | |
| 62 | const VectorType = Key.VectorType; | 71 | const VectorType = Key.VectorType; |
| 63 | const ArrayType = Key.ArrayType; | 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 | pub const Ref = enum(u32) { _ }; | 95 | pub const Ref = enum(u32) { _ }; |
| ... | @@ -79,6 +108,7 @@ pub const Key = union(enum) { | ... | @@ -79,6 +108,7 @@ pub const Key = union(enum) { |
| 79 | array_type: ArrayType, | 108 | array_type: ArrayType, |
| 80 | | 109 | |
| 81 | // -- values | 110 | // -- values |
| | 111 | float: Float, |
| 82 | | 112 | |
| 83 | pub const IntType = std.builtin.Type.Int; | 113 | pub const IntType = std.builtin.Type.Int; |
| 84 | pub const FloatType = std.builtin.Type.Float; | 114 | pub const FloatType = std.builtin.Type.Float; |
| ... | @@ -98,9 +128,33 @@ pub const Key = union(enum) { | ... | @@ -98,9 +128,33 @@ pub const Key = union(enum) { |
| 98 | stride: u32 = 0, | 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 | fn hash(self: Key) u32 { | 145 | fn hash(self: Key) u32 { |
| 102 | var hasher = std.hash.Wyhash.init(0); | 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 | return @truncate(u32, hasher.final()); | 158 | return @truncate(u32, hasher.final()); |
| 105 | } | 159 | } |
| 106 | | 160 | |
| ... | @@ -141,7 +195,7 @@ pub fn deinit(self: *Self, spv: *const Module) void { | ... | @@ -141,7 +195,7 @@ pub fn deinit(self: *Self, spv: *const Module) void { |
| 141 | /// This function returns a spir-v section of (only) constant and type instructions. | 195 | /// This function returns a spir-v section of (only) constant and type instructions. |
| 142 | /// Additionally, decorations, debug names, etc, are all directly emitted into the | 196 | /// Additionally, decorations, debug names, etc, are all directly emitted into the |
| 143 | /// `spv` module. The section is allocated with `spv.gpa`. | 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 | var section = Section{}; | 199 | var section = Section{}; |
| 146 | errdefer section.deinit(spv.gpa); | 200 | errdefer section.deinit(spv.gpa); |
| 147 | for (self.items.items(.result_id), 0..) |result_id, index| { | 201 | for (self.items.items(.result_id), 0..) |result_id, index| { |
| ... | @@ -151,7 +205,7 @@ pub fn materialize(self: *Self, spv: *Module) !Section { | ... | @@ -151,7 +205,7 @@ pub fn materialize(self: *Self, spv: *Module) !Section { |
| 151 | } | 205 | } |
| 152 | | 206 | |
| 153 | fn emit( | 207 | fn emit( |
| 154 | self: *Self, | 208 | self: *const Self, |
| 155 | spv: *Module, | 209 | spv: *Module, |
| 156 | result_id: IdResult, | 210 | result_id: IdResult, |
| 157 | ref: Ref, | 211 | ref: Ref, |
| ... | @@ -206,9 +260,34 @@ fn emit( | ... | @@ -206,9 +260,34 @@ fn emit( |
| 206 | try spv.decorate(result_id, .{ .ArrayStride = .{ .array_stride = array.stride } }); | 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 | /// Add a key to this cache. Returns a reference to the key that | 291 | /// Add a key to this cache. Returns a reference to the key that |
| 213 | /// was added. The corresponding result-id can be queried using | 292 | /// was added. The corresponding result-id can be queried using |
| 214 | /// self.resultId with the result. | 293 | /// self.resultId with the result. |
| ... | @@ -251,6 +330,24 @@ pub fn resolve(self: *Self, spv: *Module, key: Key) !Ref { | ... | @@ -251,6 +330,24 @@ pub fn resolve(self: *Self, spv: *Module, key: Key) !Ref { |
| 251 | .result_id = result_id, | 330 | .result_id = result_id, |
| 252 | .data = try self.addExtra(spv, array), | 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 | try self.items.append(spv.gpa, item); | 352 | try self.items.append(spv.gpa, item); |
| 256 | | 353 | |
| ... | @@ -285,6 +382,18 @@ pub fn lookup(self: *const Self, ref: Ref) Key { | ... | @@ -285,6 +382,18 @@ pub fn lookup(self: *const Self, ref: Ref) Key { |
| 285 | } }, | 382 | } }, |
| 286 | .type_vector => .{ .vector_type = self.extraData(Tag.VectorType, data) }, | 383 | .type_vector => .{ .vector_type = self.extraData(Tag.VectorType, data) }, |
| 287 | .type_array => .{ .array_type = self.extraData(Tag.ArrayType, data) }, | 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 | |