adding functions management
Some checks failed
Build / build (push) Successful in 1m57s
Test / build (push) Failing after 6m35s

This commit is contained in:
2026-01-17 13:39:45 +01:00
parent db82448ac0
commit 8b0b0a72ae
6 changed files with 132 additions and 73 deletions

View File

@@ -7,15 +7,15 @@ struct FragOut
[location(0)] color: vec4[f32]
}
fn computeColor() -> f32
fn computeColor(val: f32) -> f32
{
return 1.0;
return 2.0 * val;
}
[entry(frag)]
fn main() -> FragOut
{
let output: FragOut;
output.color = vec4[f32](computeColor(), computeColor(), computeColor(), computeColor());
output.color = vec4[f32](computeColor(1.0), computeColor(2.0), computeColor(3.0), computeColor(4.0));
return output;
}

Binary file not shown.

View File

@@ -1,50 +1,65 @@
Version 1.0
Generator: 2560130
Bound: 27
Bound: 38
Schema: 0
OpCapability Capability(Shader)
OpCapability Capability(Float64)
OpMemoryModel AddressingModel(Logical) MemoryModel(GLSL450)
OpEntryPoint ExecutionModel(Fragment) %14 "main" %8
OpExecutionMode %14 ExecutionMode(OriginUpperLeft)
OpEntryPoint ExecutionModel(Fragment) %18 "main" %9
OpExecutionMode %18 ExecutionMode(OriginUpperLeft)
OpSource SourceLanguage(NZSL) 4198400
OpSourceExtension "Version: 1.1"
OpName %9 "FragOut"
OpMemberName %9 0 "color"
OpName %8 "color"
OpName %13 "computeColor"
OpName %14 "main"
OpDecorate %8 Decoration(Location) 0
OpMemberDecorate %9 0 Decoration(Offset) 0
OpName %10 "FragOut"
OpMemberName %10 0 "color"
OpName %9 "color"
OpName %17 "computeColor"
OpName %18 "main"
OpDecorate %9 Decoration(Location) 0
OpMemberDecorate %10 0 Decoration(Offset) 0
%1 = OpTypeFloat 32
%2 = OpTypeFunction %1
%3 = OpConstant %1 f32(1)
%4 = OpTypeVoid
%5 = OpTypeFunction %4
%6 = OpTypeVector %1 4
%7 = OpTypePointer StorageClass(Output) %6
%9 = OpTypeStruct %6
%10 = OpTypePointer StorageClass(Function) %9
%11 = OpTypeInt 32 1
%12 = OpConstant %11 i32(0)
%24 = OpTypePointer StorageClass(Function) %6
%8 = OpVariable %7 StorageClass(Output)
%13 = OpFunction %1 FunctionControl(0) %2
%15 = OpLabel
OpReturnValue %3
%2 = OpTypePointer StorageClass(Function) %1
%3 = OpTypeFunction %1 %2
%4 = OpConstant %1 f32(2)
%5 = OpTypeVoid
%6 = OpTypeFunction %5
%7 = OpTypeVector %1 4
%8 = OpTypePointer StorageClass(Output) %7
%10 = OpTypeStruct %7
%11 = OpTypePointer StorageClass(Function) %10
%12 = OpTypeInt 32 1
%13 = OpConstant %12 i32(0)
%14 = OpConstant %1 f32(1)
%15 = OpConstant %1 f32(3)
%16 = OpConstant %1 f32(4)
%35 = OpTypePointer StorageClass(Function) %7
%9 = OpVariable %8 StorageClass(Output)
%17 = OpFunction %1 FunctionControl(0) %3
%19 = OpFunctionParameter %2
%20 = OpLabel
%21 = OpLoad %1 %19
%22 = OpFMul %1 %4 %21
OpReturnValue %22
OpFunctionEnd
%14 = OpFunction %4 FunctionControl(0) %5
%16 = OpLabel
%17 = OpVariable %10 StorageClass(Function)
%18 = OpFunctionCall %1 %13
%19 = OpFunctionCall %1 %13
%20 = OpFunctionCall %1 %13
%21 = OpFunctionCall %1 %13
%22 = OpCompositeConstruct %6 %18 %19 %20 %21
%23 = OpAccessChain %24 %17 %12
OpStore %23 %22
%25 = OpLoad %9 %17
%26 = OpCompositeExtract %6 %25 0
OpStore %8 %26
%18 = OpFunction %5 FunctionControl(0) %6
%23 = OpLabel
%24 = OpVariable %11 StorageClass(Function)
%25 = OpVariable %2 StorageClass(Function)
%26 = OpVariable %2 StorageClass(Function)
%27 = OpVariable %2 StorageClass(Function)
%28 = OpVariable %2 StorageClass(Function)
OpStore %25 %14
%29 = OpFunctionCall %1 %17 %25
OpStore %26 %4
%30 = OpFunctionCall %1 %17 %26
OpStore %27 %15
%31 = OpFunctionCall %1 %17 %27
OpStore %28 %16
%32 = OpFunctionCall %1 %17 %28
%33 = OpCompositeConstruct %7 %29 %30 %31 %32
%34 = OpAccessChain %35 %24 %13
OpStore %34 %33
%36 = OpLoad %10 %24
%37 = OpCompositeExtract %7 %36 0
OpStore %9 %37
OpReturn
OpFunctionEnd

View File

@@ -251,13 +251,17 @@ variant: ?union(Variant) {
source_location: usize,
return_type: SpvWord,
function_type: SpvWord,
params: []const SpvWord,
params: []SpvWord,
},
AccessChain: struct {
target: SpvWord,
value: Value,
},
FunctionParameter: struct {},
FunctionParameter: struct {
type_word: SpvWord,
type: Type,
value_ptr: ?*Value,
},
Label: struct {
source_location: usize,
},
@@ -293,6 +297,7 @@ pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
.Constant => |*c| c.value.deinit(allocator),
.Variable => |*v| v.value.deinit(allocator),
//.AccessChain => |*a| a.value.deinit(allocator),
.Function => |f| allocator.free(f.params),
else => {},
}
}
@@ -303,6 +308,8 @@ pub fn getValueTypeWord(self: *Self) RuntimeError!SpvWord {
return switch (self.variant orelse return RuntimeError.InvalidSpirV) {
.Variable => |v| v.type_word,
.Constant => |c| c.type_word,
.AccessChain => |*a| a.target,
.FunctionParameter => |p| p.type_word,
else => RuntimeError.InvalidSpirV,
};
}
@@ -311,6 +318,7 @@ pub fn getValueType(self: *Self) RuntimeError!Type {
return switch (self.variant orelse return RuntimeError.InvalidSpirV) {
.Variable => |v| v.type,
.Constant => |c| c.type,
.FunctionParameter => |p| p.type,
else => RuntimeError.InvalidSpirV,
};
}
@@ -319,6 +327,8 @@ pub fn getValue(self: *Self) RuntimeError!*Value {
return switch (self.variant orelse return RuntimeError.InvalidSpirV) {
.Variable => |*v| &v.value,
.Constant => |*c| &c.value,
.AccessChain => |*a| &a.value,
.FunctionParameter => |*p| p.value_ptr orelse return RuntimeError.InvalidSpirV,
else => RuntimeError.InvalidSpirV,
};
}

View File

@@ -27,6 +27,7 @@ pub const RuntimeError = error{
pub const Function = struct {
source_location: usize,
result: *Result,
ret: *Result,
};
mod: *Module,
@@ -35,6 +36,7 @@ it: WordIterator,
/// Local deep copy of module's results to be able to run multiple runtimes concurrently
results: []Result,
current_parameter_index: SpvWord,
current_function: ?*Result,
function_stack: std.ArrayList(Function),
@@ -49,6 +51,7 @@ pub fn init(allocator: std.mem.Allocator, module: *Module) RuntimeError!Self {
}
break :blk results;
},
.current_parameter_index = 0,
.current_function = null,
.function_stack = .empty,
};
@@ -103,6 +106,11 @@ pub fn callEntryPoint(self: *Self, allocator: std.mem.Allocator, entry_point_ind
switch (variant) {
.Function => |f| {
if (!self.it.jumpToSourceLocation(f.source_location)) return RuntimeError.InvalidEntryPoint;
self.function_stack.append(allocator, .{
.source_location = f.source_location,
.result = entry_point_result,
.ret = &self.results[f.return_type],
}) catch return RuntimeError.OutOfMemory;
},
else => return RuntimeError.InvalidEntryPoint,
}
@@ -127,7 +135,7 @@ pub fn callEntryPoint(self: *Self, allocator: std.mem.Allocator, entry_point_ind
self.it = it_tmp;
} else {
self.it.did_jump = false;
_ = it_tmp.skip();
//_ = self.it.skip();
}
}

View File

@@ -75,6 +75,7 @@ pub const SetupDispatcher = block: {
.Function = opFunction,
.FunctionCall = autoSetupConstant,
.FunctionEnd = opFunctionEnd,
.FunctionParameter = opFunctionParameter,
.IAdd = autoSetupConstant,
.IEqual = autoSetupConstant,
.IMul = autoSetupConstant,
@@ -697,10 +698,55 @@ fn opFunction(allocator: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeErr
rt.current_function = &rt.mod.results[id];
}
fn opFunctionCall(allocator: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
_ = rt.it.skip();
const ret = &rt.results[try rt.it.next()];
const func = &rt.results[try rt.it.next()];
for ((func.variant orelse return RuntimeError.InvalidSpirV).Function.params) |param| {
const arg = &rt.results[try rt.it.next()];
(rt.results[param].variant orelse return RuntimeError.InvalidSpirV).FunctionParameter.value_ptr = try arg.getValue();
}
rt.function_stack.items[rt.function_stack.items.len - 1].source_location = rt.it.emitSourceLocation();
const source_location = (func.variant orelse return RuntimeError.InvalidSpirV).Function.source_location;
rt.function_stack.append(allocator, .{
.source_location = source_location,
.result = func,
.ret = ret,
}) catch return RuntimeError.OutOfMemory;
if (!rt.it.jumpToSourceLocation(source_location)) return RuntimeError.InvalidSpirV;
rt.current_parameter_index = 0;
}
fn opFunctionEnd(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
rt.current_function = null;
}
fn opFunctionParameter(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
const var_type = try rt.it.next();
const id = try rt.it.next();
const target = &rt.mod.results[id];
const resolved = rt.mod.results[var_type].resolveType(rt.mod.results);
const member_count = resolved.getMemberCounts();
if (member_count == 0) {
return RuntimeError.InvalidSpirV;
}
target.variant = .{
.FunctionParameter = .{
.type_word = var_type,
.type = switch (resolved.variant orelse return RuntimeError.InvalidSpirV) {
.Type => |t| @as(Result.Type, t),
else => return RuntimeError.InvalidSpirV,
},
.value_ptr = null,
},
};
((rt.current_function orelse return RuntimeError.InvalidSpirV).variant orelse return RuntimeError.InvalidSpirV).Function.params[rt.current_parameter_index] = id;
rt.current_parameter_index += 1;
}
fn opLabel(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
const id = try rt.it.next();
rt.mod.results[id].variant = .{
@@ -714,20 +760,7 @@ fn opLoad(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
_ = rt.it.skip();
const id = try rt.it.next();
const ptr_id = try rt.it.next();
copyValue(
switch (rt.results[id].variant orelse return RuntimeError.InvalidSpirV) {
.Variable => |*v| &v.value,
.Constant => |*c| &c.value,
.AccessChain => |*a| &a.value,
else => return RuntimeError.InvalidSpirV,
},
switch (rt.results[ptr_id].variant orelse return RuntimeError.InvalidSpirV) {
.Variable => |v| &v.value,
.Constant => |c| &c.value,
.AccessChain => |a| &a.value,
else => return RuntimeError.InvalidSpirV,
},
);
copyValue(try rt.results[id].getValue(), try rt.results[ptr_id].getValue());
}
fn opMemberName(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
@@ -775,7 +808,6 @@ fn opName(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) Runti
}
fn opReturn(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
rt.last_return_id = null;
_ = rt.function_stack.pop();
if (rt.function_stack.getLastOrNull()) |function| {
_ = rt.it.jumpToSourceLocation(function.source_location);
@@ -787,6 +819,13 @@ fn opReturn(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
}
fn opReturnValue(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
if (rt.function_stack.getLastOrNull()) |function| {
var ret_res = rt.results[try rt.it.next()];
copyValue(try function.ret.getValue(), try ret_res.getValue());
} else {
return RuntimeError.InvalidSpirV; // No current function ???
}
_ = rt.function_stack.pop();
if (rt.function_stack.getLastOrNull()) |function| {
_ = rt.it.jumpToSourceLocation(function.source_location);
@@ -824,20 +863,7 @@ fn opSourceExtension(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Run
fn opStore(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
const ptr_id = try rt.it.next();
const val_id = try rt.it.next();
copyValue(
switch (rt.results[ptr_id].variant orelse return RuntimeError.InvalidSpirV) {
.Variable => |*v| &v.value,
.Constant => |*c| &c.value,
.AccessChain => |*a| &a.value,
else => return RuntimeError.InvalidSpirV,
},
switch (rt.results[val_id].variant orelse return RuntimeError.InvalidSpirV) {
.Variable => |v| &v.value,
.Constant => |c| &c.value,
.AccessChain => |a| &a.value,
else => return RuntimeError.InvalidSpirV,
},
);
copyValue(try rt.results[ptr_id].getValue(), try rt.results[val_id].getValue());
}
fn opTypeBool(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {