authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2025-03-09 18:02:46+03:30
committergravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2025-03-17 21:56:17+03:30
loge2e75774748591fb44bfc905080e7a14008d4ec3
tree30cd3f778609f19711a6900433c3482f32a9a378
parent78ad866dd1fc49cb826215002274991201cbb89e

spirv: lower more types in assembler


2 files changed, 55 insertions(+), 16 deletions(-)

lib/std/gpu.zig+10-5
......@@ -80,7 +80,8 @@ pub fn fragmentDepth(comptime ptr: *addrspace(.output) f32) void {
8080/// Forms the main linkage for `input` and `output` address spaces.
8181/// `ptr` must be a reference to variable or struct field.
8282pub fn location(comptime ptr: anytype, comptime loc: u32) void {
83 asm volatile ("OpDecorate %ptr Location $loc"
83 asm volatile (
84 \\OpDecorate %ptr Location $loc
8485 :
8586 : [ptr] "" (ptr),
8687 [loc] "c" (loc),
......@@ -110,7 +111,8 @@ pub const Origin = enum(u32) {
110111/// The coordinates appear to originate in the specified `origin`.
111112/// Only valid with the `Fragment` calling convention.
112113pub fn fragmentOrigin(comptime entry_point: anytype, comptime origin: Origin) void {
113 asm volatile ("OpExecutionMode %entry_point $origin"
114 asm volatile (
115 \\OpExecutionMode %entry_point $origin
114116 :
115117 : [entry_point] "" (entry_point),
116118 [origin] "c" (@intFromEnum(origin)),
......@@ -137,7 +139,8 @@ pub const DepthMode = enum(u32) {
137139
138140/// Only valid with the `Fragment` calling convention.
139141pub fn depthMode(comptime entry_point: anytype, comptime mode: DepthMode) void {
140 asm volatile ("OpExecutionMode %entry_point $mode"
142 asm volatile (
143 \\OpExecutionMode %entry_point $mode
141144 :
142145 : [entry_point] "" (entry_point),
143146 [mode] "c" (mode),
......@@ -147,7 +150,8 @@ pub fn depthMode(comptime entry_point: anytype, comptime mode: DepthMode) void {
147150/// Indicates the workgroup size in the `x`, `y`, and `z` dimensions.
148151/// Only valid with the `GLCompute` or `Kernel` calling conventions.
149152pub fn workgroupSize(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void {
150 asm volatile ("OpExecutionMode %entry_point LocalSize %x %y %z"
153 asm volatile (
154 \\OpExecutionMode %entry_point LocalSize %x %y %z
151155 :
152156 : [entry_point] "" (entry_point),
153157 [x] "c" (size[0]),
......@@ -159,7 +163,8 @@ pub fn workgroupSize(comptime entry_point: anytype, comptime size: @Vector(3, u3
159163/// A hint to the client, which indicates the workgroup size in the `x`, `y`, and `z` dimensions.
160164/// Only valid with the `GLCompute` or `Kernel` calling conventions.
161165pub fn workgroupSizeHint(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void {
162 asm volatile ("OpExecutionMode %entry_point LocalSizeHint %x %y %z"
166 asm volatile (
167 \\OpExecutionMode %entry_point LocalSizeHint %x %y %z
163168 :
164169 : [entry_point] "" (entry_point),
165170 [x] "c" (size[0]),
src/codegen/spirv/Assembler.zig+45-11
......@@ -368,6 +368,40 @@ fn processTypeInstruction(self: *Assembler) !AsmValue {
368368 });
369369 break :blk result_id;
370370 },
371 .OpTypeStruct => blk: {
372 const ids = try self.gpa.alloc(IdRef, operands[1..].len);
373 defer self.gpa.free(ids);
374 for (operands[1..], ids) |op, *id| id.* = try self.resolveRefId(op.ref_id);
375 const result_id = self.spv.allocId();
376 try self.spv.structType(result_id, ids, null);
377 break :blk result_id;
378 },
379 .OpTypeImage => blk: {
380 const sampled_type = try self.resolveRefId(operands[1].ref_id);
381 const result_id = self.spv.allocId();
382 try section.emit(self.gpa, .OpTypeImage, .{
383 .id_result = result_id,
384 .sampled_type = sampled_type,
385 .dim = @enumFromInt(operands[2].value),
386 .depth = operands[3].literal32,
387 .arrayed = operands[4].literal32,
388 .ms = operands[5].literal32,
389 .sampled = operands[6].literal32,
390 .image_format = @enumFromInt(operands[7].value),
391 });
392 break :blk result_id;
393 },
394 .OpTypeSampler => blk: {
395 const result_id = self.spv.allocId();
396 try section.emit(self.gpa, .OpTypeSampler, .{ .id_result = result_id });
397 break :blk result_id;
398 },
399 .OpTypeSampledImage => blk: {
400 const image_type = try self.resolveRefId(operands[1].ref_id);
401 const result_id = self.spv.allocId();
402 try section.emit(self.gpa, .OpTypeSampledImage, .{ .id_result = result_id, .image_type = image_type });
403 break :blk result_id;
404 },
371405 .OpTypeFunction => blk: {
372406 const param_operands = operands[2..];
373407 const return_type = try self.resolveRefId(operands[1].ref_id);
......@@ -406,18 +440,18 @@ fn processGenericInstruction(self: *Assembler) !?AsmValue {
406440 else => switch (self.inst.opcode) {
407441 .OpEntryPoint => unreachable,
408442 .OpExecutionMode, .OpExecutionModeId => &self.spv.sections.execution_modes,
409 .OpVariable => switch (@as(spec.StorageClass, @enumFromInt(operands[2].value))) {
410 .Function => &self.func.prologue,
411 .Input, .Output => section: {
412 maybe_spv_decl_index = try self.spv.allocDecl(.global);
413 try self.func.decl_deps.put(self.spv.gpa, maybe_spv_decl_index.?, {});
414 // TODO: In theory this can be non-empty if there is an initializer which depends on another global...
415 try self.spv.declareDeclDeps(maybe_spv_decl_index.?, &.{});
443 .OpVariable => section: {
444 const storage_class: spec.StorageClass = @enumFromInt(operands[2].value);
445 if (storage_class == .Function) break :section &self.func.prologue;
446 maybe_spv_decl_index = try self.spv.allocDecl(.global);
447 if (self.spv.version.minor < 4 and storage_class != .Input and storage_class != .Output) {
448 // Before version 1.4, the interface’s storage classes are limited to the Input and Output
416449 break :section &self.spv.sections.types_globals_constants;
417 },
418 // These don't need to be marked in the dependency system.
419 // Probably we should add them anyway, then filter out PushConstant globals.
420 else => &self.spv.sections.types_globals_constants,
450 }
451 try self.func.decl_deps.put(self.spv.gpa, maybe_spv_decl_index.?, {});
452 // TODO: In theory this can be non-empty if there is an initializer which depends on another global...
453 try self.spv.declareDeclDeps(maybe_spv_decl_index.?, &.{});
454 break :section &self.spv.sections.types_globals_constants;
421455 },
422456 // Default case - to be worked out further.
423457 else => &self.func.body,