From e2e75774748591fb44bfc905080e7a14008d4ec3 Mon Sep 17 00:00:00 2001 From: Ali Cheraghi Date: Sun, 9 Mar 2025 18:02:46 +0330 Subject: [PATCH] spirv: lower more types in assembler --- lib/std/gpu.zig | 15 ++++++--- src/codegen/spirv/Assembler.zig | 56 ++++++++++++++++++++++++++------- 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/lib/std/gpu.zig b/lib/std/gpu.zig index b9ad2fcda0..d02b2424d4 100644 --- a/lib/std/gpu.zig +++ b/lib/std/gpu.zig @@ -80,7 +80,8 @@ pub fn fragmentDepth(comptime ptr: *addrspace(.output) f32) void { /// Forms the main linkage for `input` and `output` address spaces. /// `ptr` must be a reference to variable or struct field. pub fn location(comptime ptr: anytype, comptime loc: u32) void { - asm volatile ("OpDecorate %ptr Location $loc" + asm volatile ( + \\OpDecorate %ptr Location $loc : : [ptr] "" (ptr), [loc] "c" (loc), @@ -110,7 +111,8 @@ pub const Origin = enum(u32) { /// The coordinates appear to originate in the specified `origin`. /// Only valid with the `Fragment` calling convention. pub fn fragmentOrigin(comptime entry_point: anytype, comptime origin: Origin) void { - asm volatile ("OpExecutionMode %entry_point $origin" + asm volatile ( + \\OpExecutionMode %entry_point $origin : : [entry_point] "" (entry_point), [origin] "c" (@intFromEnum(origin)), @@ -137,7 +139,8 @@ pub const DepthMode = enum(u32) { /// Only valid with the `Fragment` calling convention. pub fn depthMode(comptime entry_point: anytype, comptime mode: DepthMode) void { - asm volatile ("OpExecutionMode %entry_point $mode" + asm volatile ( + \\OpExecutionMode %entry_point $mode : : [entry_point] "" (entry_point), [mode] "c" (mode), @@ -147,7 +150,8 @@ pub fn depthMode(comptime entry_point: anytype, comptime mode: DepthMode) void { /// Indicates the workgroup size in the `x`, `y`, and `z` dimensions. /// Only valid with the `GLCompute` or `Kernel` calling conventions. pub fn workgroupSize(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void { - asm volatile ("OpExecutionMode %entry_point LocalSize %x %y %z" + asm volatile ( + \\OpExecutionMode %entry_point LocalSize %x %y %z : : [entry_point] "" (entry_point), [x] "c" (size[0]), @@ -159,7 +163,8 @@ pub fn workgroupSize(comptime entry_point: anytype, comptime size: @Vector(3, u3 /// A hint to the client, which indicates the workgroup size in the `x`, `y`, and `z` dimensions. /// Only valid with the `GLCompute` or `Kernel` calling conventions. pub fn workgroupSizeHint(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void { - asm volatile ("OpExecutionMode %entry_point LocalSizeHint %x %y %z" + asm volatile ( + \\OpExecutionMode %entry_point LocalSizeHint %x %y %z : : [entry_point] "" (entry_point), [x] "c" (size[0]), diff --git a/src/codegen/spirv/Assembler.zig b/src/codegen/spirv/Assembler.zig index 25a5481fb5..264613b240 100644 --- a/src/codegen/spirv/Assembler.zig +++ b/src/codegen/spirv/Assembler.zig @@ -368,6 +368,40 @@ fn processTypeInstruction(self: *Assembler) !AsmValue { }); break :blk result_id; }, + .OpTypeStruct => blk: { + const ids = try self.gpa.alloc(IdRef, operands[1..].len); + defer self.gpa.free(ids); + for (operands[1..], ids) |op, *id| id.* = try self.resolveRefId(op.ref_id); + const result_id = self.spv.allocId(); + try self.spv.structType(result_id, ids, null); + break :blk result_id; + }, + .OpTypeImage => blk: { + const sampled_type = try self.resolveRefId(operands[1].ref_id); + const result_id = self.spv.allocId(); + try section.emit(self.gpa, .OpTypeImage, .{ + .id_result = result_id, + .sampled_type = sampled_type, + .dim = @enumFromInt(operands[2].value), + .depth = operands[3].literal32, + .arrayed = operands[4].literal32, + .ms = operands[5].literal32, + .sampled = operands[6].literal32, + .image_format = @enumFromInt(operands[7].value), + }); + break :blk result_id; + }, + .OpTypeSampler => blk: { + const result_id = self.spv.allocId(); + try section.emit(self.gpa, .OpTypeSampler, .{ .id_result = result_id }); + break :blk result_id; + }, + .OpTypeSampledImage => blk: { + const image_type = try self.resolveRefId(operands[1].ref_id); + const result_id = self.spv.allocId(); + try section.emit(self.gpa, .OpTypeSampledImage, .{ .id_result = result_id, .image_type = image_type }); + break :blk result_id; + }, .OpTypeFunction => blk: { const param_operands = operands[2..]; const return_type = try self.resolveRefId(operands[1].ref_id); @@ -406,18 +440,18 @@ fn processGenericInstruction(self: *Assembler) !?AsmValue { else => switch (self.inst.opcode) { .OpEntryPoint => unreachable, .OpExecutionMode, .OpExecutionModeId => &self.spv.sections.execution_modes, - .OpVariable => switch (@as(spec.StorageClass, @enumFromInt(operands[2].value))) { - .Function => &self.func.prologue, - .Input, .Output => section: { - maybe_spv_decl_index = try self.spv.allocDecl(.global); - try self.func.decl_deps.put(self.spv.gpa, maybe_spv_decl_index.?, {}); - // TODO: In theory this can be non-empty if there is an initializer which depends on another global... - try self.spv.declareDeclDeps(maybe_spv_decl_index.?, &.{}); + .OpVariable => section: { + const storage_class: spec.StorageClass = @enumFromInt(operands[2].value); + if (storage_class == .Function) break :section &self.func.prologue; + maybe_spv_decl_index = try self.spv.allocDecl(.global); + if (self.spv.version.minor < 4 and storage_class != .Input and storage_class != .Output) { + // Before version 1.4, the interface’s storage classes are limited to the Input and Output break :section &self.spv.sections.types_globals_constants; - }, - // These don't need to be marked in the dependency system. - // Probably we should add them anyway, then filter out PushConstant globals. - else => &self.spv.sections.types_globals_constants, + } + try self.func.decl_deps.put(self.spv.gpa, maybe_spv_decl_index.?, {}); + // TODO: In theory this can be non-empty if there is an initializer which depends on another global... + try self.spv.declareDeclDeps(maybe_spv_decl_index.?, &.{}); + break :section &self.spv.sections.types_globals_constants; }, // Default case - to be worked out further. else => &self.func.body,