adding component locations
This commit is contained in:
@@ -86,6 +86,7 @@ pub fn initRuntimeDispatcher() void {
|
|||||||
runtime_dispatcher[@intFromEnum(ext.GLSLOp.FAbs)] = MathEngine(.Float, .FAbs).opSingleOperator;
|
runtime_dispatcher[@intFromEnum(ext.GLSLOp.FAbs)] = MathEngine(.Float, .FAbs).opSingleOperator;
|
||||||
runtime_dispatcher[@intFromEnum(ext.GLSLOp.FClamp)] = MathEngine(.Float, .FClamp).opTripleOperators;
|
runtime_dispatcher[@intFromEnum(ext.GLSLOp.FClamp)] = MathEngine(.Float, .FClamp).opTripleOperators;
|
||||||
runtime_dispatcher[@intFromEnum(ext.GLSLOp.FMax)] = MathEngine(.Float, .FMax).opDoubleOperators;
|
runtime_dispatcher[@intFromEnum(ext.GLSLOp.FMax)] = MathEngine(.Float, .FMax).opDoubleOperators;
|
||||||
|
runtime_dispatcher[@intFromEnum(ext.GLSLOp.FMin)] = MathEngine(.Float, .FMin).opDoubleOperators;
|
||||||
runtime_dispatcher[@intFromEnum(ext.GLSLOp.FSign)] = MathEngine(.Float, .FSign).opSingleOperator;
|
runtime_dispatcher[@intFromEnum(ext.GLSLOp.FSign)] = MathEngine(.Float, .FSign).opSingleOperator;
|
||||||
runtime_dispatcher[@intFromEnum(ext.GLSLOp.Floor)] = MathEngine(.Float, .Floor).opSingleOperator;
|
runtime_dispatcher[@intFromEnum(ext.GLSLOp.Floor)] = MathEngine(.Float, .Floor).opSingleOperator;
|
||||||
runtime_dispatcher[@intFromEnum(ext.GLSLOp.Length)] = opLength;
|
runtime_dispatcher[@intFromEnum(ext.GLSLOp.Length)] = opLength;
|
||||||
@@ -203,6 +204,7 @@ fn MathEngine(comptime T: PrimitiveType, comptime Op: MathOp) type {
|
|||||||
fn operation(comptime TT: type, l: TT, r: TT) RuntimeError!TT {
|
fn operation(comptime TT: type, l: TT, r: TT) RuntimeError!TT {
|
||||||
return switch (Op) {
|
return switch (Op) {
|
||||||
.FMax => @max(l, r),
|
.FMax => @max(l, r),
|
||||||
|
.FMin => @min(l, r),
|
||||||
else => RuntimeError.InvalidSpirV,
|
else => RuntimeError.InvalidSpirV,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-4
@@ -75,8 +75,8 @@ geometry_output_count: SpvWord,
|
|||||||
geometry_input: SpvWord,
|
geometry_input: SpvWord,
|
||||||
geometry_output: SpvWord,
|
geometry_output: SpvWord,
|
||||||
|
|
||||||
input_locations: [lib.SPIRV_MAX_INPUT_LOCATIONS]SpvWord,
|
input_locations: [lib.SPIRV_MAX_INPUT_LOCATIONS][4]SpvWord,
|
||||||
output_locations: [lib.SPIRV_MAX_OUTPUT_LOCATIONS]SpvWord,
|
output_locations: [lib.SPIRV_MAX_OUTPUT_LOCATIONS][4]SpvWord,
|
||||||
bindings: std.ArrayList(BindingEntry),
|
bindings: std.ArrayList(BindingEntry),
|
||||||
builtins: std.EnumMap(spv.SpvBuiltIn, SpvWord),
|
builtins: std.EnumMap(spv.SpvBuiltIn, SpvWord),
|
||||||
|
|
||||||
@@ -203,6 +203,14 @@ fn findAccessChainToMember(self: *const Self, base_id: SpvWord, member_index: Sp
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resultComponent(self: *const Self, id: SpvWord) SpvWord {
|
||||||
|
for (self.results[id].decorations.items) |decoration| {
|
||||||
|
if (decoration.rtype == .Component)
|
||||||
|
return decoration.literal_1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
fn applyInterfaceDecoration(self: *Self, storage_class: spv.SpvStorageClass, decoration: Result.Decoration, id: SpvWord) ModuleError!void {
|
fn applyInterfaceDecoration(self: *Self, storage_class: spv.SpvStorageClass, decoration: Result.Decoration, id: SpvWord) ModuleError!void {
|
||||||
switch (storage_class) {
|
switch (storage_class) {
|
||||||
.Input => switch (decoration.rtype) {
|
.Input => switch (decoration.rtype) {
|
||||||
@@ -210,7 +218,7 @@ fn applyInterfaceDecoration(self: *Self, storage_class: spv.SpvStorageClass, dec
|
|||||||
std.enums.fromInt(spv.SpvBuiltIn, decoration.literal_1) orelse return ModuleError.InvalidSpirV,
|
std.enums.fromInt(spv.SpvBuiltIn, decoration.literal_1) orelse return ModuleError.InvalidSpirV,
|
||||||
id,
|
id,
|
||||||
),
|
),
|
||||||
.Location => self.input_locations[decoration.literal_1] = id,
|
.Location => self.input_locations[decoration.literal_1][self.resultComponent(id)] = id,
|
||||||
else => {},
|
else => {},
|
||||||
},
|
},
|
||||||
.Output => switch (decoration.rtype) {
|
.Output => switch (decoration.rtype) {
|
||||||
@@ -218,7 +226,7 @@ fn applyInterfaceDecoration(self: *Self, storage_class: spv.SpvStorageClass, dec
|
|||||||
std.enums.fromInt(spv.SpvBuiltIn, decoration.literal_1) orelse return ModuleError.InvalidSpirV,
|
std.enums.fromInt(spv.SpvBuiltIn, decoration.literal_1) orelse return ModuleError.InvalidSpirV,
|
||||||
id,
|
id,
|
||||||
),
|
),
|
||||||
.Location => self.output_locations[decoration.literal_1] = id,
|
.Location => self.output_locations[decoration.literal_1][self.resultComponent(id)] = id,
|
||||||
else => {},
|
else => {},
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
|
|||||||
+31
-21
@@ -177,13 +177,19 @@ pub fn getResultByName(self: *const Self, name: []const u8) RuntimeError!SpvWord
|
|||||||
return RuntimeError.NotFound;
|
return RuntimeError.NotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getResultByLocation(self: *const Self, location: SpvWord, kind: enum { input, output }) RuntimeError!SpvWord {
|
pub const LocationKind = enum { input, output };
|
||||||
|
|
||||||
|
pub inline fn getResultByLocation(self: *const Self, location: SpvWord, kind: LocationKind) RuntimeError!SpvWord {
|
||||||
|
return self.getResultByLocationComponent(location, 0, kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getResultByLocationComponent(self: *const Self, location: SpvWord, component: SpvWord, kind: LocationKind) RuntimeError!SpvWord {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
.input => if (location < self.mod.input_locations.len and self.mod.input_locations[location] != 0) {
|
.input => if (location < self.mod.input_locations.len and component < 4 and self.mod.input_locations[location][component] != 0) {
|
||||||
return self.mod.input_locations[location];
|
return self.mod.input_locations[location][component];
|
||||||
},
|
},
|
||||||
.output => if (location < self.mod.output_locations.len and self.mod.output_locations[location] != 0) {
|
.output => if (location < self.mod.output_locations.len and component < 4 and self.mod.output_locations[location][component] != 0) {
|
||||||
return self.mod.output_locations[location];
|
return self.mod.output_locations[location][component];
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return RuntimeError.NotFound;
|
return RuntimeError.NotFound;
|
||||||
@@ -371,8 +377,8 @@ const InputLocationTarget = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fn resolveInputLocationTarget(self: *const Self, location: SpvWord) RuntimeError!InputLocationTarget {
|
fn resolveInputLocationTarget(self: *const Self, location: SpvWord) RuntimeError!InputLocationTarget {
|
||||||
if (location < self.mod.input_locations.len and self.mod.input_locations[location] != 0) {
|
if (location < self.mod.input_locations.len and self.mod.input_locations[location][0] != 0) {
|
||||||
const result = self.mod.input_locations[location];
|
const result = self.mod.input_locations[location][0];
|
||||||
const value = try self.results[result].getConstValue();
|
const value = try self.results[result].getConstValue();
|
||||||
switch (value.*) {
|
switch (value.*) {
|
||||||
.Matrix => return .{ .result = result, .matrix_column = 0 },
|
.Matrix => return .{ .result = result, .matrix_column = 0 },
|
||||||
@@ -385,7 +391,7 @@ fn resolveInputLocationTarget(self: *const Self, location: SpvWord) RuntimeError
|
|||||||
base_location -= 1;
|
base_location -= 1;
|
||||||
|
|
||||||
const result = if (base_location < self.mod.input_locations.len)
|
const result = if (base_location < self.mod.input_locations.len)
|
||||||
self.mod.input_locations[base_location]
|
self.mod.input_locations[base_location][0]
|
||||||
else
|
else
|
||||||
0;
|
0;
|
||||||
if (result == 0) continue;
|
if (result == 0) continue;
|
||||||
@@ -429,11 +435,13 @@ fn getInputLocationTargetValue(self: *const Self, target: InputLocationTarget) R
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn readOutput(self: *const Self, output: []u8, result: SpvWord) RuntimeError!void {
|
pub fn readOutput(self: *const Self, output: []u8, result: SpvWord) RuntimeError!void {
|
||||||
if (std.mem.indexOfScalar(SpvWord, &self.mod.output_locations, result)) |_| {
|
for (&self.mod.output_locations) |*location| {
|
||||||
try self.readResultValue(output, result);
|
if (std.mem.indexOfScalar(SpvWord, location, result)) |_| {
|
||||||
} else {
|
try self.readResultValue(output, result);
|
||||||
return RuntimeError.NotFound;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return RuntimeError.NotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readBuiltIn(self: *const Self, output: []u8, builtin: spv.SpvBuiltIn) RuntimeError!void {
|
pub fn readBuiltIn(self: *const Self, output: []u8, builtin: spv.SpvBuiltIn) RuntimeError!void {
|
||||||
@@ -445,16 +453,18 @@ pub fn readBuiltIn(self: *const Self, output: []u8, builtin: spv.SpvBuiltIn) Run
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn writeInput(self: *const Self, input: []const u8, result: SpvWord) RuntimeError!void {
|
pub fn writeInput(self: *const Self, input: []const u8, result: SpvWord) RuntimeError!void {
|
||||||
if (std.mem.indexOfScalar(SpvWord, &self.mod.input_locations, result)) |_| {
|
for (&self.mod.input_locations) |*location| {
|
||||||
try self.writeResultValue(input, result);
|
if (std.mem.indexOfScalar(SpvWord, location, result)) |_| {
|
||||||
if (self.results[result].variant) |*variant| switch (variant.*) {
|
try self.writeResultValue(input, result);
|
||||||
.Variable => |*v| v.value.clearExternalData(),
|
if (self.results[result].variant) |*variant| switch (variant.*) {
|
||||||
.AccessChain => |*a| a.value.clearExternalData(),
|
.Variable => |*v| v.value.clearExternalData(),
|
||||||
else => {},
|
.AccessChain => |*a| a.value.clearExternalData(),
|
||||||
};
|
else => {},
|
||||||
} else {
|
};
|
||||||
return RuntimeError.NotFound;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return RuntimeError.NotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getInputLocationMemorySize(self: *const Self, location: SpvWord) RuntimeError!usize {
|
pub fn getInputLocationMemorySize(self: *const Self, location: SpvWord) RuntimeError!usize {
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ pub inline fn nextAs(self: *Self, comptime E: type) RuntimeError!E {
|
|||||||
if (self.next_force_skip) |skip_index| {
|
if (self.next_force_skip) |skip_index| {
|
||||||
if (self.index == skip_index) {
|
if (self.index == skip_index) {
|
||||||
_ = self.skip();
|
_ = self.skip();
|
||||||
|
self.next_force_skip = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self.nextAsOrNull(E) orelse return RuntimeError.InvalidSpirV;
|
return self.nextAsOrNull(E) orelse return RuntimeError.InvalidSpirV;
|
||||||
|
|||||||
+88
-7
@@ -224,6 +224,11 @@ pub const SetupDispatcher = block: {
|
|||||||
.ShiftLeftLogical = autoSetupConstant,
|
.ShiftLeftLogical = autoSetupConstant,
|
||||||
.ShiftRightArithmetic = autoSetupConstant,
|
.ShiftRightArithmetic = autoSetupConstant,
|
||||||
.ShiftRightLogical = autoSetupConstant,
|
.ShiftRightLogical = autoSetupConstant,
|
||||||
|
.SpecConstant = opSpecConstant,
|
||||||
|
.SpecConstantComposite = opConstantComposite,
|
||||||
|
.SpecConstantFalse = opSpecConstantFalse,
|
||||||
|
.SpecConstantOp = opSpecConstantOp,
|
||||||
|
.SpecConstantTrue = opSpecConstantTrue,
|
||||||
.SourceExtension = opSourceExtension,
|
.SourceExtension = opSourceExtension,
|
||||||
.TypeArray = opTypeArray,
|
.TypeArray = opTypeArray,
|
||||||
.TypeBool = opTypeBool,
|
.TypeBool = opTypeBool,
|
||||||
@@ -378,6 +383,7 @@ pub fn initRuntimeDispatcher() void {
|
|||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.SpecConstantOp)] = opSpecConstantOp;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.SpecConstantOp)] = opSpecConstantOp;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.SpecConstantTrue)] = opSpecConstantTrue;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.SpecConstantTrue)] = opSpecConstantTrue;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.Store)] = opStore;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.Store)] = opStore;
|
||||||
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.Switch)] = opSwitch;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.UConvert)] = ConversionEngine(.UInt, .UInt).op;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.UConvert)] = ConversionEngine(.UInt, .UInt).op;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.UDiv)] = MathEngine(.UInt, .Div, false).op;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.UDiv)] = MathEngine(.UInt, .Div, false).op;
|
||||||
runtime_dispatcher[@intFromEnum(spv.SpvOp.UGreaterThan)] = CondEngine(.UInt, .Greater).op;
|
runtime_dispatcher[@intFromEnum(spv.SpvOp.UGreaterThan)] = CondEngine(.UInt, .Greater).op;
|
||||||
@@ -3220,20 +3226,95 @@ fn opSpecConstantFalse(allocator: std.mem.Allocator, _: SpvWord, rt: *Runtime) R
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn opSwitch(_: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
|
if (word_count < 2)
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
|
||||||
|
const selector = try rt.results[try rt.it.next()].getValue();
|
||||||
|
const default_target = try rt.it.next();
|
||||||
|
|
||||||
|
const SelectorData = struct {
|
||||||
|
value: u64,
|
||||||
|
literal_width: SpvWord,
|
||||||
|
};
|
||||||
|
const selector_data: SelectorData = switch (selector.*) {
|
||||||
|
.Int => |i| switch (i.bit_count) {
|
||||||
|
8 => .{ .value = @as(u64, i.value.uint8), .literal_width = @as(SpvWord, 1) },
|
||||||
|
16 => .{ .value = @as(u64, i.value.uint16), .literal_width = @as(SpvWord, 1) },
|
||||||
|
32 => .{ .value = @as(u64, i.value.uint32), .literal_width = @as(SpvWord, 1) },
|
||||||
|
64 => .{ .value = i.value.uint64, .literal_width = @as(SpvWord, 2) },
|
||||||
|
else => return RuntimeError.InvalidSpirV,
|
||||||
|
},
|
||||||
|
else => return RuntimeError.InvalidValueType,
|
||||||
|
};
|
||||||
|
const selector_value = selector_data.value;
|
||||||
|
const literal_width = selector_data.literal_width;
|
||||||
|
|
||||||
|
var target = default_target;
|
||||||
|
var remaining = word_count - 2;
|
||||||
|
while (remaining != 0) {
|
||||||
|
if (remaining < literal_width + 1)
|
||||||
|
return RuntimeError.InvalidSpirV;
|
||||||
|
|
||||||
|
const literal = if (literal_width == 2) blk: {
|
||||||
|
const low = @as(u64, try rt.it.next());
|
||||||
|
const high = @as(u64, try rt.it.next());
|
||||||
|
break :blk (high << 32) | low;
|
||||||
|
} else try rt.it.next();
|
||||||
|
const literal_target = try rt.it.next();
|
||||||
|
|
||||||
|
if (literal == selector_value)
|
||||||
|
target = literal_target;
|
||||||
|
|
||||||
|
remaining -= literal_width + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rt.previous_label = rt.current_label;
|
||||||
|
_ = rt.it.jumpToSourceLocation(switch ((try rt.results[target].getVariant()).*) {
|
||||||
|
.Label => |l| l.source_location,
|
||||||
|
else => return RuntimeError.InvalidSpirV,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn opSpecConstantOp(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
fn opSpecConstantOp(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
if (word_count < 3)
|
if (word_count < 3)
|
||||||
return RuntimeError.InvalidSpirV;
|
return RuntimeError.InvalidSpirV;
|
||||||
|
|
||||||
const start_location = rt.it.emitSourceLocation();
|
const target = try setupConstant(allocator, rt);
|
||||||
|
|
||||||
_ = try setupConstant(allocator, rt);
|
|
||||||
const inner_op = try rt.it.nextAs(spv.SpvOp);
|
const inner_op = try rt.it.nextAs(spv.SpvOp);
|
||||||
|
|
||||||
_ = rt.it.goToSourceLocation(start_location);
|
const target_value = try target.getValue();
|
||||||
rt.it.forceSkipIndex(2);
|
switch (target_value.*) {
|
||||||
|
.Int => |*dst| {
|
||||||
|
if (word_count != 5)
|
||||||
|
return RuntimeError.UnsupportedSpirV;
|
||||||
|
|
||||||
const pfn = runtime_dispatcher[@intFromEnum(inner_op)] orelse return RuntimeError.UnsupportedSpirV;
|
const lhs = (try rt.results[try rt.it.next()].getValue()).Int;
|
||||||
try pfn(allocator, word_count - 1, rt);
|
const rhs = (try rt.results[try rt.it.next()].getValue()).Int;
|
||||||
|
const lhs_u = lhs.value.uint64;
|
||||||
|
const rhs_u = rhs.value.uint64;
|
||||||
|
|
||||||
|
dst.value.uint64 = switch (inner_op) {
|
||||||
|
.IAdd => @addWithOverflow(lhs_u, rhs_u)[0],
|
||||||
|
.ISub => @subWithOverflow(lhs_u, rhs_u)[0],
|
||||||
|
.IMul => @mulWithOverflow(lhs_u, rhs_u)[0],
|
||||||
|
.UDiv => if (rhs_u != 0) @divTrunc(lhs_u, rhs_u) else return RuntimeError.DivisionByZero,
|
||||||
|
.UMod => if (rhs_u != 0) @mod(lhs_u, rhs_u) else return RuntimeError.DivisionByZero,
|
||||||
|
.SDiv => switch (dst.bit_count) {
|
||||||
|
32 => @as(u32, @bitCast(@divTrunc(lhs.value.sint32, rhs.value.sint32))),
|
||||||
|
64 => @bitCast(@divTrunc(lhs.value.sint64, rhs.value.sint64)),
|
||||||
|
else => return RuntimeError.UnsupportedSpirV,
|
||||||
|
},
|
||||||
|
.SMod => switch (dst.bit_count) {
|
||||||
|
32 => @as(u32, @bitCast(@mod(lhs.value.sint32, rhs.value.sint32))),
|
||||||
|
64 => @bitCast(@mod(lhs.value.sint64, rhs.value.sint64)),
|
||||||
|
else => return RuntimeError.UnsupportedSpirV,
|
||||||
|
},
|
||||||
|
else => return RuntimeError.UnsupportedSpirV,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
else => return RuntimeError.UnsupportedSpirV,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn opCopyMemory(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
fn opCopyMemory(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
|
|||||||
Reference in New Issue
Block a user