150 lines
4.9 KiB
Zig
150 lines
4.9 KiB
Zig
const std = @import("std");
|
|
const root = @import("root.zig");
|
|
const compileNzsl = root.compileNzsl;
|
|
const case = root.case;
|
|
|
|
const Operations = enum {
|
|
BitwiseAnd,
|
|
BitwiseOr,
|
|
BitwiseXor,
|
|
ShiftLeft,
|
|
ShiftRight,
|
|
ShiftRightArithmetic,
|
|
};
|
|
|
|
test "Bitwise primitives" {
|
|
const allocator = std.testing.allocator;
|
|
const types = [_]type{ i32, u32 };
|
|
var operations = std.EnumMap(Operations, []const u8).init(.{
|
|
.BitwiseAnd = "&",
|
|
.BitwiseOr = "|",
|
|
.BitwiseXor = "^",
|
|
.ShiftLeft = "<<",
|
|
.ShiftRight = ">>",
|
|
.ShiftRightArithmetic = ">>",
|
|
});
|
|
|
|
var it = operations.iterator();
|
|
while (it.next()) |op| {
|
|
inline for (types) |T| {
|
|
const op1: T = case.random(T);
|
|
const op2: T = @mod(case.random(T), @bitSizeOf(T));
|
|
const expected = switch (op.key) {
|
|
.BitwiseAnd => op1 & op2,
|
|
.BitwiseOr => op1 | op2,
|
|
.BitwiseXor => op1 ^ op2,
|
|
.ShiftLeft => op1 << @intCast(op2),
|
|
.ShiftRight, .ShiftRightArithmetic => op1 >> @intCast(op2),
|
|
};
|
|
|
|
const shader = try std.fmt.allocPrint(
|
|
allocator,
|
|
\\ [nzsl_version("1.1")]
|
|
\\ [feature(float64)]
|
|
\\ module;
|
|
\\
|
|
\\ struct FragOut
|
|
\\ {{
|
|
\\ [location(0)] color: vec4[{s}]
|
|
\\ }}
|
|
\\
|
|
\\ [entry(frag)]
|
|
\\ fn main() -> FragOut
|
|
\\ {{
|
|
\\ let op1: {s} = {d};
|
|
\\ let op2: {s} = {d};
|
|
\\ let color = op1 {s} op2;
|
|
\\
|
|
\\ let output: FragOut;
|
|
\\ output.color = vec4[{s}](color, color, color, color);
|
|
\\ return output;
|
|
\\ }}
|
|
,
|
|
.{
|
|
@typeName(T),
|
|
@typeName(T),
|
|
op1,
|
|
@typeName(T),
|
|
op2,
|
|
op.value.*,
|
|
@typeName(T),
|
|
},
|
|
);
|
|
defer allocator.free(shader);
|
|
const code = try compileNzsl(allocator, shader);
|
|
defer allocator.free(code);
|
|
try case.expectOutput(T, 4, code, "color", &.{ expected, expected, expected, expected });
|
|
}
|
|
}
|
|
}
|
|
|
|
test "Bitwise vectors" {
|
|
const allocator = std.testing.allocator;
|
|
const types = [_]type{ i32, u32 };
|
|
var operations = std.EnumMap(Operations, []const u8).init(.{
|
|
.BitwiseAnd = "&",
|
|
.BitwiseOr = "|",
|
|
.BitwiseXor = "^",
|
|
.ShiftLeft = "<<",
|
|
.ShiftRight = ">>",
|
|
.ShiftRightArithmetic = ">>",
|
|
});
|
|
|
|
var it = operations.iterator();
|
|
while (it.next()) |op| {
|
|
inline for (2..5) |L| {
|
|
inline for (types) |T| {
|
|
const op1: case.Vec(L, T) = .{ .val = case.random(@Vector(L, T)) };
|
|
var op2: case.Vec(L, T) = .{ .val = case.random(@Vector(L, T)) };
|
|
for (0..L) |i| op2.val[i] = @mod(op2.val[i], @bitSizeOf(T));
|
|
const expected = switch (op.key) {
|
|
.BitwiseAnd => op1.val & op2.val,
|
|
.BitwiseOr => op1.val | op2.val,
|
|
.BitwiseXor => op1.val ^ op2.val,
|
|
.ShiftLeft => op1.val << @intCast(op2.val),
|
|
.ShiftRight, .ShiftRightArithmetic => op1.val >> @intCast(op2.val),
|
|
};
|
|
|
|
const shader = try std.fmt.allocPrint(
|
|
allocator,
|
|
\\ [nzsl_version("1.1")]
|
|
\\ [feature(float64)]
|
|
\\ module;
|
|
\\
|
|
\\ struct FragOut
|
|
\\ {{
|
|
\\ [location(0)] color: vec{d}[{s}]
|
|
\\ }}
|
|
\\
|
|
\\ [entry(frag)]
|
|
\\ fn main() -> FragOut
|
|
\\ {{
|
|
\\ let op1 = vec{d}[{s}]({f});
|
|
\\ let op2 = vec{d}[{s}]({f});
|
|
\\
|
|
\\ let output: FragOut;
|
|
\\ output.color = op1 {s} op2;
|
|
\\ return output;
|
|
\\ }}
|
|
,
|
|
.{
|
|
L,
|
|
@typeName(T),
|
|
L,
|
|
@typeName(T),
|
|
op1,
|
|
L,
|
|
@typeName(T),
|
|
op2,
|
|
op.value.*,
|
|
},
|
|
);
|
|
defer allocator.free(shader);
|
|
const code = try compileNzsl(allocator, shader);
|
|
defer allocator.free(code);
|
|
try case.expectOutput(T, L, code, "color", &@as([L]T, expected));
|
|
}
|
|
}
|
|
}
|
|
}
|