authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-05-29 14:10:02+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-05-30 19:43:36+02:00
logaade6f1195d64ad091c065e225184aaa52628282
tree96c94b1d4a701516ce6724a4a2bf145a67f60042
parentb2a984cda67edd25fa2bf3ebe697649d561ff80f
signaturelock-open Commit is signed but in an unrecognized format.

spirv: cache for floats


1 files changed, 112 insertions(+), 3 deletions(-)

src/codegen/spirv/TypeConstantCache.zig+112-3
...@@ -56,11 +56,40 @@ const Tag = enum {...@@ -56,11 +56,40 @@ const Tag = enum {
56 type_array,56 type_array,
5757
58 // -- Values58 // -- 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,
5968
60 const SimpleType = enum { void, bool };69 const SimpleType = enum { void, bool };
6170
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};
6594
66pub const Ref = enum(u32) { _ };95pub 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,
80109
81 // -- values110 // -- values
111 float: Float,
82112
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 };
100130
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 }
106160
...@@ -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 the196/// 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`.
144pub fn materialize(self: *Self, spv: *Module) !Section {198pub 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}
152206
153fn emit(207fn 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}
211278
279/// Get the ref for a key that has already been added to the cache.
280fn 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.
287fn 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 that291/// Add a key to this cache. Returns a reference to the key that
213/// was added. The corresponding result-id can be queried using292/// 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);
256353
...@@ -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}
290399