authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-10-21 13:04:18+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-10-21 17:46:52+02:00
log5090d75e48ba0a044997b93b0c5cf1f7dcec60f1
treeba940a217a474f6eace8a3b42970c941da5741db
parent200bca360e333abeb29f4af6d050adf42c2ca5a7
signaturebadge-check Signed by SSH key SHA256:CQ99aPxq+RueiL9u7z0FEki5Fm7V6T8q4PrEGmINrA4

spirv: make load() and store() accept MemoryOptions

This struct is used to configure the load, such as to make it volatile. Previously this was done using a single bool, but this struct makes it shorter to write non-volatile loads (the usual) and more clear whats going on when a volatile load is required.

1 files changed, 23 insertions(+), 19 deletions(-)

src/codegen/spirv.zig+23-19
...@@ -1910,11 +1910,15 @@ const DeclGen = struct {...@@ -1910,11 +1910,15 @@ const DeclGen = struct {
1910 return try self.convertToDirect(result_ty, result_id);1910 return try self.convertToDirect(result_ty, result_id);
1911 }1911 }
19121912
1913 fn load(self: *DeclGen, value_ty: Type, ptr_id: IdRef, is_volatile: bool) !IdRef {1913 const MemoryOptions = struct {
1914 is_volatile: bool = false,
1915 };
1916
1917 fn load(self: *DeclGen, value_ty: Type, ptr_id: IdRef, options: MemoryOptions) !IdRef {
1914 const indirect_value_ty_ref = try self.resolveType(value_ty, .indirect);1918 const indirect_value_ty_ref = try self.resolveType(value_ty, .indirect);
1915 const result_id = self.spv.allocId();1919 const result_id = self.spv.allocId();
1916 const access = spec.MemoryAccess.Extended{1920 const access = spec.MemoryAccess.Extended{
1917 .Volatile = is_volatile,1921 .Volatile = options.is_volatile,
1918 };1922 };
1919 try self.func.body.emit(self.spv.gpa, .OpLoad, .{1923 try self.func.body.emit(self.spv.gpa, .OpLoad, .{
1920 .id_result_type = self.typeId(indirect_value_ty_ref),1924 .id_result_type = self.typeId(indirect_value_ty_ref),
...@@ -1925,10 +1929,10 @@ const DeclGen = struct {...@@ -1925,10 +1929,10 @@ const DeclGen = struct {
1925 return try self.convertToDirect(value_ty, result_id);1929 return try self.convertToDirect(value_ty, result_id);
1926 }1930 }
19271931
1928 fn store(self: *DeclGen, value_ty: Type, ptr_id: IdRef, value_id: IdRef, is_volatile: bool) !void {1932 fn store(self: *DeclGen, value_ty: Type, ptr_id: IdRef, value_id: IdRef, options: MemoryOptions) !void {
1929 const indirect_value_id = try self.convertToIndirect(value_ty, value_id);1933 const indirect_value_id = try self.convertToIndirect(value_ty, value_id);
1930 const access = spec.MemoryAccess.Extended{1934 const access = spec.MemoryAccess.Extended{
1931 .Volatile = is_volatile,1935 .Volatile = options.is_volatile,
1932 };1936 };
1933 try self.func.body.emit(self.spv.gpa, .OpStore, .{1937 try self.func.body.emit(self.spv.gpa, .OpStore, .{
1934 .pointer = ptr_id,1938 .pointer = ptr_id,
...@@ -2849,14 +2853,14 @@ const DeclGen = struct {...@@ -2849,14 +2853,14 @@ const DeclGen = struct {
2849 const dst_ptr_ty_ref = try self.ptrType(dst_ty, .Function);2853 const dst_ptr_ty_ref = try self.ptrType(dst_ty, .Function);
28502854
2851 const tmp_id = try self.alloc(src_ty, .{ .storage_class = .Function });2855 const tmp_id = try self.alloc(src_ty, .{ .storage_class = .Function });
2852 try self.store(src_ty, tmp_id, src_id, false);2856 try self.store(src_ty, tmp_id, src_id, .{});
2853 const casted_ptr_id = self.spv.allocId();2857 const casted_ptr_id = self.spv.allocId();
2854 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{2858 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
2855 .id_result_type = self.typeId(dst_ptr_ty_ref),2859 .id_result_type = self.typeId(dst_ptr_ty_ref),
2856 .id_result = casted_ptr_id,2860 .id_result = casted_ptr_id,
2857 .operand = tmp_id,2861 .operand = tmp_id,
2858 });2862 });
2859 return try self.load(dst_ty, casted_ptr_id, false);2863 return try self.load(dst_ty, casted_ptr_id, .{});
2860 }2864 }
28612865
2862 fn airBitCast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2866 fn airBitCast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
...@@ -3219,7 +3223,7 @@ const DeclGen = struct {...@@ -3219,7 +3223,7 @@ const DeclGen = struct {
32193223
3220 const slice_ptr = try self.extractField(ptr_ty, slice_id, 0);3224 const slice_ptr = try self.extractField(ptr_ty, slice_id, 0);
3221 const elem_ptr = try self.ptrAccessChain(ptr_ty_ref, slice_ptr, index_id, &.{});3225 const elem_ptr = try self.ptrAccessChain(ptr_ty_ref, slice_ptr, index_id, &.{});
3222 return try self.load(slice_ty.childType(mod), elem_ptr, slice_ty.isVolatilePtr(mod));3226 return try self.load(slice_ty.childType(mod), elem_ptr, .{ .is_volatile = slice_ty.isVolatilePtr(mod) });
3223 }3227 }
32243228
3225 fn ptrElemPtr(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef, index_id: IdRef) !IdRef {3229 fn ptrElemPtr(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef, index_id: IdRef) !IdRef {
...@@ -3273,9 +3277,9 @@ const DeclGen = struct {...@@ -3273,9 +3277,9 @@ const DeclGen = struct {
3273 const elem_ptr_ty_ref = try self.ptrType(elem_ty, .Function);3277 const elem_ptr_ty_ref = try self.ptrType(elem_ty, .Function);
32743278
3275 const tmp_id = try self.alloc(array_ty, .{ .storage_class = .Function });3279 const tmp_id = try self.alloc(array_ty, .{ .storage_class = .Function });
3276 try self.store(array_ty, tmp_id, array_id, false);3280 try self.store(array_ty, tmp_id, array_id, .{});
3277 const elem_ptr_id = try self.accessChainId(elem_ptr_ty_ref, tmp_id, &.{index_id});3281 const elem_ptr_id = try self.accessChainId(elem_ptr_ty_ref, tmp_id, &.{index_id});
3278 return try self.load(elem_ty, elem_ptr_id, false);3282 return try self.load(elem_ty, elem_ptr_id, .{});
3279 }3283 }
32803284
3281 fn airPtrElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {3285 fn airPtrElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
...@@ -3288,7 +3292,7 @@ const DeclGen = struct {...@@ -3288,7 +3292,7 @@ const DeclGen = struct {
3288 const ptr_id = try self.resolve(bin_op.lhs);3292 const ptr_id = try self.resolve(bin_op.lhs);
3289 const index_id = try self.resolve(bin_op.rhs);3293 const index_id = try self.resolve(bin_op.rhs);
3290 const elem_ptr_id = try self.ptrElemPtr(ptr_ty, ptr_id, index_id);3294 const elem_ptr_id = try self.ptrElemPtr(ptr_ty, ptr_id, index_id);
3291 return try self.load(elem_ty, elem_ptr_id, ptr_ty.isVolatilePtr(mod));3295 return try self.load(elem_ty, elem_ptr_id, .{ .is_volatile = ptr_ty.isVolatilePtr(mod) });
3292 }3296 }
32933297
3294 fn airSetUnionTag(self: *DeclGen, inst: Air.Inst.Index) !void {3298 fn airSetUnionTag(self: *DeclGen, inst: Air.Inst.Index) !void {
...@@ -3307,10 +3311,10 @@ const DeclGen = struct {...@@ -3307,10 +3311,10 @@ const DeclGen = struct {
3307 const new_tag_id = try self.resolve(bin_op.rhs);3311 const new_tag_id = try self.resolve(bin_op.rhs);
33083312
3309 if (layout.payload_size == 0) {3313 if (layout.payload_size == 0) {
3310 try self.store(tag_ty, union_ptr_id, new_tag_id, un_ptr_ty.isVolatilePtr(mod));3314 try self.store(tag_ty, union_ptr_id, new_tag_id, .{ .is_volatile = un_ptr_ty.isVolatilePtr(mod) });
3311 } else {3315 } else {
3312 const ptr_id = try self.accessChain(tag_ptr_ty_ref, union_ptr_id, &.{layout.tag_index});3316 const ptr_id = try self.accessChain(tag_ptr_ty_ref, union_ptr_id, &.{layout.tag_index});
3313 try self.store(tag_ty, ptr_id, new_tag_id, un_ptr_ty.isVolatilePtr(mod));3317 try self.store(tag_ty, ptr_id, new_tag_id, .{ .is_volatile = un_ptr_ty.isVolatilePtr(mod) });
3314 }3318 }
3315 }3319 }
33163320
...@@ -3384,13 +3388,13 @@ const DeclGen = struct {...@@ -3384,13 +3388,13 @@ const DeclGen = struct {
3384 const tag_ptr_ty_ref = try self.ptrType(maybe_tag_ty.?, .Function);3388 const tag_ptr_ty_ref = try self.ptrType(maybe_tag_ty.?, .Function);
3385 const ptr_id = try self.accessChain(tag_ptr_ty_ref, tmp_id, &.{@as(u32, @intCast(layout.tag_index))});3389 const ptr_id = try self.accessChain(tag_ptr_ty_ref, tmp_id, &.{@as(u32, @intCast(layout.tag_index))});
3386 const tag_id = try self.constInt(tag_ty_ref, tag_int);3390 const tag_id = try self.constInt(tag_ty_ref, tag_int);
3387 try self.store(maybe_tag_ty.?, ptr_id, tag_id, false);3391 try self.store(maybe_tag_ty.?, ptr_id, tag_id, .{});
3388 }3392 }
33893393
3390 if (layout.active_field_size != 0) {3394 if (layout.active_field_size != 0) {
3391 const active_field_ptr_ty_ref = try self.ptrType(layout.active_field_ty, .Function);3395 const active_field_ptr_ty_ref = try self.ptrType(layout.active_field_ty, .Function);
3392 const ptr_id = try self.accessChain(active_field_ptr_ty_ref, tmp_id, &.{@as(u32, @intCast(layout.active_field_index))});3396 const ptr_id = try self.accessChain(active_field_ptr_ty_ref, tmp_id, &.{@as(u32, @intCast(layout.active_field_index))});
3393 try self.store(layout.active_field_ty, ptr_id, payload.?, false);3397 try self.store(layout.active_field_ty, ptr_id, payload.?, .{});
3394 } else {3398 } else {
3395 assert(payload == null);3399 assert(payload == null);
3396 }3400 }
...@@ -3468,7 +3472,7 @@ const DeclGen = struct {...@@ -3468,7 +3472,7 @@ const DeclGen = struct {
3468 .id_result = tmp_id,3472 .id_result = tmp_id,
3469 .storage_class = .Function,3473 .storage_class = .Function,
3470 });3474 });
3471 try self.store(object_ty, tmp_id, object_id, false);3475 try self.store(object_ty, tmp_id, object_id, .{});
3472 const casted_tmp_id = self.spv.allocId();3476 const casted_tmp_id = self.spv.allocId();
3473 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{3477 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
3474 .id_result_type = self.typeId(un_active_ptr_ty_ref),3478 .id_result_type = self.typeId(un_active_ptr_ty_ref),
...@@ -3477,7 +3481,7 @@ const DeclGen = struct {...@@ -3477,7 +3481,7 @@ const DeclGen = struct {
3477 });3481 });
3478 const layout = self.unionLayout(object_ty, field_index);3482 const layout = self.unionLayout(object_ty, field_index);
3479 const field_ptr_id = try self.accessChain(field_ptr_ty_ref, casted_tmp_id, &.{layout.active_field_index});3483 const field_ptr_id = try self.accessChain(field_ptr_ty_ref, casted_tmp_id, &.{layout.active_field_index});
3480 return try self.load(field_ty, field_ptr_id, false);3484 return try self.load(field_ty, field_ptr_id, .{});
3481 },3485 },
3482 },3486 },
3483 else => unreachable,3487 else => unreachable,
...@@ -3730,7 +3734,7 @@ const DeclGen = struct {...@@ -3730,7 +3734,7 @@ const DeclGen = struct {
3730 const operand = try self.resolve(ty_op.operand);3734 const operand = try self.resolve(ty_op.operand);
3731 if (!ptr_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) return null;3735 if (!ptr_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) return null;
37323736
3733 return try self.load(elem_ty, operand, ptr_ty.isVolatilePtr(mod));3737 return try self.load(elem_ty, operand, .{ .is_volatile = ptr_ty.isVolatilePtr(mod) });
3734 }3738 }
37353739
3736 fn airStore(self: *DeclGen, inst: Air.Inst.Index) !void {3740 fn airStore(self: *DeclGen, inst: Air.Inst.Index) !void {
...@@ -3740,7 +3744,7 @@ const DeclGen = struct {...@@ -3740,7 +3744,7 @@ const DeclGen = struct {
3740 const ptr = try self.resolve(bin_op.lhs);3744 const ptr = try self.resolve(bin_op.lhs);
3741 const value = try self.resolve(bin_op.rhs);3745 const value = try self.resolve(bin_op.rhs);
37423746
3743 try self.store(elem_ty, ptr, value, ptr_ty.isVolatilePtr(self.module));3747 try self.store(elem_ty, ptr, value, .{ .is_volatile = ptr_ty.isVolatilePtr(self.module) });
3744 }3748 }
37453749
3746 fn airLoop(self: *DeclGen, inst: Air.Inst.Index) !void {3750 fn airLoop(self: *DeclGen, inst: Air.Inst.Index) !void {
...@@ -3804,7 +3808,7 @@ const DeclGen = struct {...@@ -3804,7 +3808,7 @@ const DeclGen = struct {
3804 }3808 }
38053809
3806 const ptr = try self.resolve(un_op);3810 const ptr = try self.resolve(un_op);
3807 const value = try self.load(ret_ty, ptr, ptr_ty.isVolatilePtr(mod));3811 const value = try self.load(ret_ty, ptr, .{ .is_volatile = ptr_ty.isVolatilePtr(mod) });
3808 try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{3812 try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{
3809 .value = value,3813 .value = value,
3810 });3814 });