adding types opcodes
This commit is contained in:
@@ -95,7 +95,7 @@ pub fn init(allocator: std.mem.Allocator, source: []const SpvWord) ModuleError!S
|
|||||||
|
|
||||||
self.it = WordIterator.init(self.code);
|
self.it = WordIterator.init(self.code);
|
||||||
|
|
||||||
const magic = self.it.next() orelse return ModuleError.InvalidSpirV;
|
const magic = self.it.next() catch return ModuleError.InvalidSpirV;
|
||||||
if (magic != spv.SpvMagicNumber) {
|
if (magic != spv.SpvMagicNumber) {
|
||||||
return ModuleError.InvalidMagic;
|
return ModuleError.InvalidMagic;
|
||||||
}
|
}
|
||||||
@@ -103,15 +103,15 @@ pub fn init(allocator: std.mem.Allocator, source: []const SpvWord) ModuleError!S
|
|||||||
return ModuleError.UnsupportedEndianness;
|
return ModuleError.UnsupportedEndianness;
|
||||||
}
|
}
|
||||||
|
|
||||||
const version = self.it.next() orelse return ModuleError.InvalidSpirV;
|
const version = self.it.next() catch return ModuleError.InvalidSpirV;
|
||||||
self.version_major = @intCast((version & 0x00FF0000) >> 16);
|
self.version_major = @intCast((version & 0x00FF0000) >> 16);
|
||||||
self.version_minor = @intCast((version & 0x0000FF00) >> 8);
|
self.version_minor = @intCast((version & 0x0000FF00) >> 8);
|
||||||
|
|
||||||
const generator = self.it.next() orelse return ModuleError.InvalidSpirV;
|
const generator = self.it.next() catch return ModuleError.InvalidSpirV;
|
||||||
self.generator_id = @intCast((generator & 0xFFFF0000) >> 16);
|
self.generator_id = @intCast((generator & 0xFFFF0000) >> 16);
|
||||||
self.generator_version = @intCast(generator & 0x0000FFFF);
|
self.generator_version = @intCast(generator & 0x0000FFFF);
|
||||||
|
|
||||||
self.bound = self.it.next() orelse return ModuleError.InvalidSpirV;
|
self.bound = self.it.next() catch return ModuleError.InvalidSpirV;
|
||||||
self.results.resize(allocator, self.bound) catch return ModuleError.OutOfMemory;
|
self.results.resize(allocator, self.bound) catch return ModuleError.OutOfMemory;
|
||||||
for (self.results.items) |*result| {
|
for (self.results.items) |*result| {
|
||||||
result.* = Result.init();
|
result.* = Result.init();
|
||||||
@@ -181,7 +181,7 @@ fn checkEndiannessFromSpvMagic(magic: SpvWord) bool {
|
|||||||
fn pass(self: *Self, allocator: std.mem.Allocator, opcodes: std.EnumSet(spv.SpvOp)) ModuleError!void {
|
fn pass(self: *Self, allocator: std.mem.Allocator, opcodes: std.EnumSet(spv.SpvOp)) ModuleError!void {
|
||||||
var rt = Runtime.init(self);
|
var rt = Runtime.init(self);
|
||||||
defer rt.deinit();
|
defer rt.deinit();
|
||||||
while (rt.it.next()) |opcode_data| {
|
while (rt.it.nextOrNull()) |opcode_data| {
|
||||||
const word_count = ((opcode_data & (~spv.SpvOpCodeMask)) >> spv.SpvWordCountShift) - 1;
|
const word_count = ((opcode_data & (~spv.SpvOpCodeMask)) >> spv.SpvWordCountShift) - 1;
|
||||||
const opcode = (opcode_data & spv.SpvOpCodeMask);
|
const opcode = (opcode_data & spv.SpvOpCodeMask);
|
||||||
|
|
||||||
|
|||||||
@@ -6,20 +6,36 @@ const SpvByte = spv.SpvByte;
|
|||||||
const SpvWord = spv.SpvWord;
|
const SpvWord = spv.SpvWord;
|
||||||
const SpvBool = spv.SpvBool;
|
const SpvBool = spv.SpvBool;
|
||||||
|
|
||||||
const RType = enum {
|
const Type = enum {
|
||||||
None,
|
None,
|
||||||
String,
|
String,
|
||||||
Extension,
|
Extension,
|
||||||
Function_type,
|
FunctionType,
|
||||||
Type,
|
Type,
|
||||||
Variable,
|
Variable,
|
||||||
Constant,
|
Constant,
|
||||||
Function,
|
Function,
|
||||||
Access_chain,
|
AccessChain,
|
||||||
Function_parameter,
|
FunctionParameter,
|
||||||
Label,
|
Label,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ValueType = enum {
|
||||||
|
Void,
|
||||||
|
Bool,
|
||||||
|
Int,
|
||||||
|
Float,
|
||||||
|
Vector,
|
||||||
|
Matrix,
|
||||||
|
Array,
|
||||||
|
RuntimeArray,
|
||||||
|
Structure,
|
||||||
|
Image,
|
||||||
|
Sampler,
|
||||||
|
SampledImage,
|
||||||
|
Pointer,
|
||||||
|
};
|
||||||
|
|
||||||
const ImageInfo = struct {
|
const ImageInfo = struct {
|
||||||
dim: spv.SpvDim,
|
dim: spv.SpvDim,
|
||||||
depth: SpvByte,
|
depth: SpvByte,
|
||||||
@@ -33,16 +49,14 @@ const ImageInfo = struct {
|
|||||||
const Decoration = struct {
|
const Decoration = struct {
|
||||||
rtype: spv.SpvDecoration,
|
rtype: spv.SpvDecoration,
|
||||||
literal_1: SpvWord,
|
literal_1: SpvWord,
|
||||||
literal_2: SpvWord,
|
literal_2: ?SpvWord,
|
||||||
index: SpvWord,
|
index: SpvWord,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
name: ?[]const u8,
|
name: ?[]const u8,
|
||||||
ptr: SpvWord,
|
|
||||||
|
|
||||||
storage_class: spv.SpvStorageClass,
|
|
||||||
parent: ?*const Self,
|
parent: ?*const Self,
|
||||||
|
|
||||||
member_names: std.ArrayList([]const u8),
|
member_names: std.ArrayList([]const u8),
|
||||||
@@ -50,20 +64,66 @@ members: std.ArrayList(spv.SpvMember),
|
|||||||
|
|
||||||
decorations: std.ArrayList(Decoration),
|
decorations: std.ArrayList(Decoration),
|
||||||
|
|
||||||
/// Only for functions
|
res_type: Type,
|
||||||
|
type_data: union(Type) {
|
||||||
|
None: struct {},
|
||||||
|
String: []const u8,
|
||||||
|
Extension: struct {},
|
||||||
|
FunctionType: struct {
|
||||||
return_type: SpvWord,
|
return_type: SpvWord,
|
||||||
|
},
|
||||||
rtype: RType,
|
Type: struct {
|
||||||
|
value_type: ValueType,
|
||||||
|
data: union(ValueType) {
|
||||||
|
Void: struct {},
|
||||||
|
Bool: struct {},
|
||||||
|
Int: struct {
|
||||||
|
bit_length: SpvWord,
|
||||||
|
is_signed: bool,
|
||||||
|
},
|
||||||
|
Float: struct {
|
||||||
|
bit_length: SpvWord,
|
||||||
|
},
|
||||||
|
Vector: struct {
|
||||||
|
components_type: ValueType,
|
||||||
|
},
|
||||||
|
Matrix: struct {
|
||||||
|
column_type: ValueType,
|
||||||
|
},
|
||||||
|
Array: struct {},
|
||||||
|
RuntimeArray: struct {},
|
||||||
|
Structure: struct {},
|
||||||
|
Image: struct {},
|
||||||
|
Sampler: struct {},
|
||||||
|
SampledImage: struct {},
|
||||||
|
Pointer: struct {
|
||||||
|
storage_class: spv.SpvStorageClass,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
member_count: SpvWord = 0,
|
||||||
|
id: SpvWord = 0,
|
||||||
|
},
|
||||||
|
Variable: struct {},
|
||||||
|
Constant: struct {},
|
||||||
|
Function: struct {
|
||||||
|
/// Allocated array
|
||||||
|
params: []SpvWord,
|
||||||
|
},
|
||||||
|
AccessChain: struct {},
|
||||||
|
FunctionParameter: struct {},
|
||||||
|
Label: struct {},
|
||||||
|
},
|
||||||
|
|
||||||
pub fn init() Self {
|
pub fn init() Self {
|
||||||
return std.mem.zeroInit(Self, .{
|
return .{
|
||||||
.name = null,
|
.name = null,
|
||||||
.parent = null,
|
.parent = null,
|
||||||
.member_names = std.ArrayList([]const u8).empty,
|
.member_names = .empty,
|
||||||
.members = std.ArrayList(spv.SpvMember).empty,
|
.members = .empty,
|
||||||
.decorations = std.ArrayList(Decoration).empty,
|
.decorations = .empty,
|
||||||
.rtype = RType.None,
|
.res_type = .None,
|
||||||
});
|
.type_data = undefined,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
|
pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
|
||||||
@@ -73,6 +133,11 @@ pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
|
|||||||
for (self.member_names.items) |name| {
|
for (self.member_names.items) |name| {
|
||||||
allocator.free(name);
|
allocator.free(name);
|
||||||
}
|
}
|
||||||
|
// FIXME
|
||||||
|
//switch (self.type_data) {
|
||||||
|
// .Function => |data| allocator.free(data.params),
|
||||||
|
// else => {},
|
||||||
|
//}
|
||||||
self.member_names.deinit(allocator);
|
self.member_names.deinit(allocator);
|
||||||
self.members.deinit(allocator);
|
self.members.deinit(allocator);
|
||||||
self.decorations.deinit(allocator);
|
self.decorations.deinit(allocator);
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const spv = @import("spv.zig");
|
const spv = @import("spv.zig");
|
||||||
|
|
||||||
|
const RuntimeError = @import("Runtime.zig").RuntimeError;
|
||||||
|
|
||||||
const SpvWord = spv.SpvWord;
|
const SpvWord = spv.SpvWord;
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
@@ -15,16 +17,22 @@ pub fn init(buffer: []const SpvWord) Self {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next(self: *Self) ?SpvWord {
|
pub fn nextOrNull(self: *Self) ?SpvWord {
|
||||||
const word = self.peek() orelse return null;
|
const word = self.peek() orelse return null;
|
||||||
self.index += 1;
|
self.index += 1;
|
||||||
return word;
|
return word;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nextAs(self: *Self, comptime E: type) ?E {
|
pub inline fn nextAsOrNull(self: *Self, comptime E: type) ?E {
|
||||||
const word = self.peek() orelse return null;
|
return if (self.nextOrNull()) |word| std.enums.fromInt(E, word) else null;
|
||||||
self.index += 1;
|
}
|
||||||
return std.enums.fromInt(E, word);
|
|
||||||
|
pub inline fn next(self: *Self) RuntimeError!SpvWord {
|
||||||
|
return self.nextOrNull() orelse return RuntimeError.InvalidSpirV;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nextAs(self: *Self, comptime E: type) RuntimeError!E {
|
||||||
|
return self.nextAsOrNull(E) orelse return RuntimeError.InvalidSpirV;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn peek(self: *const Self) ?SpvWord {
|
pub fn peek(self: *const Self) ?SpvWord {
|
||||||
|
|||||||
231
src/opcodes.zig
231
src/opcodes.zig
@@ -14,15 +14,8 @@ const SpvWord = spv.SpvWord;
|
|||||||
const SpvBool = spv.SpvBool;
|
const SpvBool = spv.SpvBool;
|
||||||
|
|
||||||
// DUMB INDEV OPCODES TODO :
|
// DUMB INDEV OPCODES TODO :
|
||||||
// OpDecorate X
|
|
||||||
// OpMemberDecorate X
|
|
||||||
// OpTypeVoid X
|
|
||||||
// OpTypeFunction X
|
// OpTypeFunction X
|
||||||
// OpTypeFloat X
|
|
||||||
// OpTypeVector X
|
|
||||||
// OpTypePointer X
|
|
||||||
// OpTypeStruct X
|
// OpTypeStruct X
|
||||||
// OpTypeInt X
|
|
||||||
// OpConstant X
|
// OpConstant X
|
||||||
// OpVariable X
|
// OpVariable X
|
||||||
// OpFunction X
|
// OpFunction X
|
||||||
@@ -41,26 +34,90 @@ pub const SetupDispatcher = block: {
|
|||||||
@setEvalBranchQuota(65535);
|
@setEvalBranchQuota(65535);
|
||||||
break :block std.EnumMap(spv.SpvOp, OpCodeFunc).init(.{
|
break :block std.EnumMap(spv.SpvOp, OpCodeFunc).init(.{
|
||||||
.Capability = opCapability,
|
.Capability = opCapability,
|
||||||
|
.Decorate = opDecorate,
|
||||||
.EntryPoint = opEntryPoint,
|
.EntryPoint = opEntryPoint,
|
||||||
.ExecutionMode = opExecutionMode,
|
.ExecutionMode = opExecutionMode,
|
||||||
.MemoryModel = opMemoryModel,
|
.MemberDecorate = opDecorateMember,
|
||||||
.MemberName = opMemberName,
|
.MemberName = opMemberName,
|
||||||
|
.MemoryModel = opMemoryModel,
|
||||||
.Name = opName,
|
.Name = opName,
|
||||||
.Source = opSource,
|
.Source = opSource,
|
||||||
.SourceExtension = opSourceExtension,
|
.SourceExtension = opSourceExtension,
|
||||||
|
.TypeVoid = opTypeVoid,
|
||||||
|
.TypeBool = opTypeBool,
|
||||||
|
.TypeInt = opTypeInt,
|
||||||
|
.TypeFloat = opTypeFloat,
|
||||||
|
.TypeVector = opTypeVector,
|
||||||
|
.TypeMatrix = opTypeMatrix,
|
||||||
|
.TypePointer = opTypePointer,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
fn opCapability(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
fn opCapability(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
if (rt.it.nextAs(spv.SpvCapability)) |capability| {
|
rt.mod.capabilities.insert(try rt.it.nextAs(spv.SpvCapability));
|
||||||
rt.mod.capabilities.insert(capability);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn addDecoration(allocator: std.mem.Allocator, rt: *Runtime, target: SpvWord, decoration_type: spv.SpvDecoration, member: ?SpvWord) RuntimeError!void {
|
||||||
|
var decoration = rt.mod.results.items[target].decorations.addOne(allocator) catch return RuntimeError.OutOfMemory;
|
||||||
|
decoration.rtype = decoration_type;
|
||||||
|
decoration.index = if (member) |memb| memb else 0;
|
||||||
|
|
||||||
|
switch (decoration_type) {
|
||||||
|
.SpecId,
|
||||||
|
.ArrayStride,
|
||||||
|
.MatrixStride,
|
||||||
|
.BuiltIn,
|
||||||
|
.UniformId,
|
||||||
|
.Stream,
|
||||||
|
.Location,
|
||||||
|
.Component,
|
||||||
|
.Index,
|
||||||
|
.Binding,
|
||||||
|
.DescriptorSet,
|
||||||
|
.Offset,
|
||||||
|
.XfbBuffer,
|
||||||
|
.XfbStride,
|
||||||
|
.FuncParamAttr,
|
||||||
|
.FPRoundingMode,
|
||||||
|
.FPFastMathMode,
|
||||||
|
.InputAttachmentIndex,
|
||||||
|
.Alignment,
|
||||||
|
.MaxByteOffset,
|
||||||
|
.AlignmentId,
|
||||||
|
.MaxByteOffsetId,
|
||||||
|
.SecondaryViewportRelativeNV,
|
||||||
|
.CounterBuffer,
|
||||||
|
.UserSemantic,
|
||||||
|
.UserTypeGOOGLE,
|
||||||
|
=> {
|
||||||
|
decoration.literal_1 = try rt.it.next();
|
||||||
|
decoration.literal_2 = null;
|
||||||
|
},
|
||||||
|
.LinkageAttributes => {
|
||||||
|
decoration.literal_1 = try rt.it.next();
|
||||||
|
decoration.literal_2 = try rt.it.next();
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn opDecorate(allocator: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
|
const target = try rt.it.next();
|
||||||
|
const decoration_type = try rt.it.nextAs(spv.SpvDecoration);
|
||||||
|
try addDecoration(allocator, rt, target, decoration_type, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn opDecorateMember(allocator: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
|
const target = try rt.it.next();
|
||||||
|
const member = try rt.it.next();
|
||||||
|
const decoration_type = try rt.it.nextAs(spv.SpvDecoration);
|
||||||
|
try addDecoration(allocator, rt, target, decoration_type, member);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn opEntryPoint(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
fn opEntryPoint(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
const entry = rt.mod.entry_points.addOne(allocator) catch return RuntimeError.OutOfMemory;
|
const entry = rt.mod.entry_points.addOne(allocator) catch return RuntimeError.OutOfMemory;
|
||||||
entry.exec_model = rt.it.nextAs(spv.SpvExecutionModel) orelse return RuntimeError.InvalidSpirV;
|
entry.exec_model = try rt.it.nextAs(spv.SpvExecutionModel);
|
||||||
entry.id = rt.it.next() orelse return RuntimeError.InvalidSpirV;
|
entry.id = try rt.it.next();
|
||||||
entry.name = try readString(allocator, &rt.it);
|
entry.name = try readString(allocator, &rt.it);
|
||||||
|
|
||||||
var interface_count = word_count - @divExact(entry.name.len, 4) - 2;
|
var interface_count = word_count - @divExact(entry.name.len, 4) - 2;
|
||||||
@@ -68,7 +125,7 @@ fn opEntryPoint(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime)
|
|||||||
if (interface_count != 0) {
|
if (interface_count != 0) {
|
||||||
var interface_index: u32 = 0;
|
var interface_index: u32 = 0;
|
||||||
while (interface_count != 0) {
|
while (interface_count != 0) {
|
||||||
entry.globals[interface_index] = rt.it.next() orelse return RuntimeError.InvalidSpirV;
|
entry.globals[interface_index] = try rt.it.next();
|
||||||
interface_index += 1;
|
interface_index += 1;
|
||||||
interface_count -= 1;
|
interface_count -= 1;
|
||||||
}
|
}
|
||||||
@@ -77,16 +134,16 @@ fn opEntryPoint(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime)
|
|||||||
|
|
||||||
fn opExecutionMode(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
fn opExecutionMode(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
_ = rt.it.skip();
|
_ = rt.it.skip();
|
||||||
const mode = rt.it.nextAs(spv.SpvExecutionMode) orelse return RuntimeError.InvalidSpirV;
|
const mode = try rt.it.nextAs(spv.SpvExecutionMode);
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
.LocalSize => {
|
.LocalSize => {
|
||||||
rt.mod.local_size_x = rt.it.next() orelse return RuntimeError.InvalidSpirV;
|
rt.mod.local_size_x = try rt.it.next();
|
||||||
rt.mod.local_size_y = rt.it.next() orelse return RuntimeError.InvalidSpirV;
|
rt.mod.local_size_y = try rt.it.next();
|
||||||
rt.mod.local_size_z = rt.it.next() orelse return RuntimeError.InvalidSpirV;
|
rt.mod.local_size_z = try rt.it.next();
|
||||||
},
|
},
|
||||||
.Invocations => rt.mod.geometry_invocations = rt.it.next() orelse return RuntimeError.InvalidSpirV,
|
.Invocations => rt.mod.geometry_invocations = try rt.it.next(),
|
||||||
.OutputVertices => rt.mod.geometry_output_count = rt.it.next() orelse return RuntimeError.InvalidSpirV,
|
.OutputVertices => rt.mod.geometry_output_count = try rt.it.next(),
|
||||||
.InputPoints, .InputLines, .Triangles, .InputLinesAdjacency, .InputTrianglesAdjacency => rt.mod.geometry_input = @intFromEnum(mode),
|
.InputPoints, .InputLines, .Triangles, .InputLinesAdjacency, .InputTrianglesAdjacency => rt.mod.geometry_input = @intFromEnum(mode),
|
||||||
.OutputPoints, .OutputLineStrip, .OutputTriangleStrip => rt.mod.geometry_output = @intFromEnum(mode),
|
.OutputPoints, .OutputLineStrip, .OutputTriangleStrip => rt.mod.geometry_output = @intFromEnum(mode),
|
||||||
else => {},
|
else => {},
|
||||||
@@ -94,8 +151,8 @@ fn opExecutionMode(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn opMemberName(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
fn opMemberName(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
const id = rt.it.next() orelse return RuntimeError.InvalidSpirV;
|
const id = try rt.it.next();
|
||||||
const memb = rt.it.next() orelse return RuntimeError.InvalidSpirV;
|
const memb = try rt.it.next();
|
||||||
|
|
||||||
var result = &rt.mod.results.items[id];
|
var result = &rt.mod.results.items[id];
|
||||||
|
|
||||||
@@ -108,12 +165,12 @@ fn opMemberName(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn opMemoryModel(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
fn opMemoryModel(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
rt.mod.addressing = rt.it.nextAs(spv.SpvAddressingModel) orelse return RuntimeError.InvalidSpirV;
|
rt.mod.addressing = try rt.it.nextAs(spv.SpvAddressingModel);
|
||||||
rt.mod.memory_model = rt.it.nextAs(spv.SpvMemoryModel) orelse return RuntimeError.InvalidSpirV;
|
rt.mod.memory_model = try rt.it.nextAs(spv.SpvMemoryModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn opName(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
fn opName(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
const id = rt.it.next() orelse return RuntimeError.InvalidSpirV;
|
const id = try rt.it.next();
|
||||||
if (id >= rt.mod.results.items.len) return RuntimeError.InvalidSpirV;
|
if (id >= rt.mod.results.items.len) return RuntimeError.InvalidSpirV;
|
||||||
var result = &rt.mod.results.items[id];
|
var result = &rt.mod.results.items[id];
|
||||||
result.* = Result.init();
|
result.* = Result.init();
|
||||||
@@ -122,17 +179,17 @@ fn opName(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) Runti
|
|||||||
|
|
||||||
fn opSource(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
fn opSource(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
var file = rt.mod.files.addOne(allocator) catch return RuntimeError.OutOfMemory;
|
var file = rt.mod.files.addOne(allocator) catch return RuntimeError.OutOfMemory;
|
||||||
file.lang = rt.it.nextAs(spv.SpvSourceLanguage) orelse return RuntimeError.InvalidSpirV;
|
file.lang = try rt.it.nextAs(spv.SpvSourceLanguage);
|
||||||
file.lang_version = rt.it.next() orelse return RuntimeError.InvalidSpirV;
|
file.lang_version = try rt.it.next();
|
||||||
if (word_count > 2) {
|
if (word_count > 2) {
|
||||||
const id = rt.it.next() orelse return RuntimeError.InvalidSpirV;
|
const id = try rt.it.next();
|
||||||
if (id >= rt.mod.results.items.len) return RuntimeError.InvalidSpirV;
|
if (id >= rt.mod.results.items.len) return RuntimeError.InvalidSpirV;
|
||||||
if (rt.mod.results.items[id].name) |name| {
|
if (rt.mod.results.items[id].name) |name| {
|
||||||
file.file_name = name;
|
file.file_name = name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (word_count > 3) {
|
if (word_count > 3) {
|
||||||
const id = rt.it.next() orelse return RuntimeError.InvalidSpirV;
|
const id = try rt.it.next();
|
||||||
if (id >= rt.mod.results.items.len) return RuntimeError.InvalidSpirV;
|
if (id >= rt.mod.results.items.len) return RuntimeError.InvalidSpirV;
|
||||||
if (rt.mod.results.items[id].name) |name| {
|
if (rt.mod.results.items[id].name) |name| {
|
||||||
file.source = name;
|
file.source = name;
|
||||||
@@ -144,9 +201,123 @@ fn opSourceExtension(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Run
|
|||||||
rt.mod.extensions.append(allocator, try readStringN(allocator, &rt.it, word_count)) catch return RuntimeError.OutOfMemory;
|
rt.mod.extensions.append(allocator, try readStringN(allocator, &rt.it, word_count)) catch return RuntimeError.OutOfMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn opTypeVoid(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
|
const id = try rt.it.next();
|
||||||
|
rt.mod.results.items[id].res_type = .Type;
|
||||||
|
rt.mod.results.items[id].type_data = .{
|
||||||
|
.Type = .{
|
||||||
|
.value_type = .Void,
|
||||||
|
.data = .{
|
||||||
|
.Void = .{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn opTypeBool(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
|
const id = try rt.it.next();
|
||||||
|
rt.mod.results.items[id].res_type = .Type;
|
||||||
|
rt.mod.results.items[id].type_data = .{
|
||||||
|
.Type = .{
|
||||||
|
.value_type = .Bool,
|
||||||
|
.data = .{
|
||||||
|
.Bool = .{},
|
||||||
|
},
|
||||||
|
.member_count = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn opTypeInt(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
|
const id = try rt.it.next();
|
||||||
|
rt.mod.results.items[id].res_type = .Type;
|
||||||
|
rt.mod.results.items[id].type_data = .{
|
||||||
|
.Type = .{
|
||||||
|
.value_type = .Int,
|
||||||
|
.data = .{
|
||||||
|
.Int = .{
|
||||||
|
.bit_length = try rt.it.next(),
|
||||||
|
.is_signed = if (try rt.it.next() != 0) true else false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.member_count = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn opTypeFloat(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
|
const id = try rt.it.next();
|
||||||
|
rt.mod.results.items[id].res_type = .Type;
|
||||||
|
rt.mod.results.items[id].type_data = .{
|
||||||
|
.Type = .{
|
||||||
|
.value_type = .Float,
|
||||||
|
.data = .{
|
||||||
|
.Float = .{
|
||||||
|
.bit_length = try rt.it.next(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.member_count = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn opTypeVector(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
|
const id = try rt.it.next();
|
||||||
|
rt.mod.results.items[id].res_type = .Type;
|
||||||
|
rt.mod.results.items[id].type_data = .{
|
||||||
|
.Type = .{
|
||||||
|
.value_type = .Vector,
|
||||||
|
.data = .{
|
||||||
|
.Vector = .{
|
||||||
|
.components_type = switch (rt.mod.results.items[try rt.it.next()].type_data) {
|
||||||
|
.Type => |data| data.value_type,
|
||||||
|
else => return RuntimeError.InvalidSpirV,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.member_count = try rt.it.next(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn opTypeMatrix(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
|
const id = try rt.it.next();
|
||||||
|
rt.mod.results.items[id].res_type = .Type;
|
||||||
|
rt.mod.results.items[id].type_data = .{
|
||||||
|
.Type = .{
|
||||||
|
.value_type = .Matrix,
|
||||||
|
.data = .{
|
||||||
|
.Matrix = .{
|
||||||
|
.column_type = switch (rt.mod.results.items[try rt.it.next()].type_data) {
|
||||||
|
.Type => |data| data.value_type,
|
||||||
|
else => return RuntimeError.InvalidSpirV,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.member_count = try rt.it.next(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn opTypePointer(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {
|
||||||
|
const id = try rt.it.next();
|
||||||
|
rt.mod.results.items[id].res_type = .Type;
|
||||||
|
rt.mod.results.items[id].type_data = .{
|
||||||
|
.Type = .{
|
||||||
|
.value_type = .Pointer,
|
||||||
|
.data = .{
|
||||||
|
.Pointer = .{
|
||||||
|
.storage_class = try rt.it.nextAs(spv.SpvStorageClass),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.id = try rt.it.next(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn readString(allocator: std.mem.Allocator, it: *WordIterator) RuntimeError![]const u8 {
|
fn readString(allocator: std.mem.Allocator, it: *WordIterator) RuntimeError![]const u8 {
|
||||||
var str: std.ArrayList(u8) = .empty;
|
var str: std.ArrayList(u8) = .empty;
|
||||||
while (it.next()) |word| {
|
while (it.nextOrNull()) |word| {
|
||||||
(str.addOne(allocator) catch return RuntimeError.OutOfMemory).* = @truncate(word & 0x000000FF);
|
(str.addOne(allocator) catch return RuntimeError.OutOfMemory).* = @truncate(word & 0x000000FF);
|
||||||
(str.addOne(allocator) catch return RuntimeError.OutOfMemory).* = @truncate((word & 0x0000FF00) >> 8);
|
(str.addOne(allocator) catch return RuntimeError.OutOfMemory).* = @truncate((word & 0x0000FF00) >> 8);
|
||||||
(str.addOne(allocator) catch return RuntimeError.OutOfMemory).* = @truncate((word & 0x00FF0000) >> 16);
|
(str.addOne(allocator) catch return RuntimeError.OutOfMemory).* = @truncate((word & 0x00FF0000) >> 16);
|
||||||
@@ -161,7 +332,7 @@ fn readString(allocator: std.mem.Allocator, it: *WordIterator) RuntimeError![]co
|
|||||||
fn readStringN(allocator: std.mem.Allocator, it: *WordIterator, n: usize) RuntimeError![]const u8 {
|
fn readStringN(allocator: std.mem.Allocator, it: *WordIterator, n: usize) RuntimeError![]const u8 {
|
||||||
var str = std.ArrayList(u8).initCapacity(allocator, n * 4) catch return RuntimeError.OutOfMemory;
|
var str = std.ArrayList(u8).initCapacity(allocator, n * 4) catch return RuntimeError.OutOfMemory;
|
||||||
for (0..n) |_| {
|
for (0..n) |_| {
|
||||||
if (it.next()) |word| {
|
if (it.nextOrNull()) |word| {
|
||||||
str.addOneAssumeCapacity().* = @truncate(word & 0x000000FF);
|
str.addOneAssumeCapacity().* = @truncate(word & 0x000000FF);
|
||||||
str.addOneAssumeCapacity().* = @truncate((word & 0x0000FF00) >> 8);
|
str.addOneAssumeCapacity().* = @truncate((word & 0x0000FF00) >> 8);
|
||||||
str.addOneAssumeCapacity().* = @truncate((word & 0x00FF0000) >> 16);
|
str.addOneAssumeCapacity().* = @truncate((word & 0x00FF0000) >> 16);
|
||||||
|
|||||||
Reference in New Issue
Block a user