adding point rasterization

This commit is contained in:
2026-06-19 00:42:46 +02:00
parent b8367ac2bb
commit aaf6653b3f
8 changed files with 105 additions and 71 deletions
+2 -2
View File
@@ -32,8 +32,8 @@
// Soft dependencies
.SPIRV_Interpreter = .{
.url = "git+https://git.kbz8.me/kbz_8/SPIRV-Interpreter#42554a5cc1069e8174b377e95ce2ac2d802a44ff",
.hash = "SPIRV_Interpreter-0.0.1-ajmpn0GXBwD01BnmV_Kf8EeNqTDoyuq7UvHVaq-WoBP0",
.url = "git+https://github.com/Kbz-8/SPIRV-Interpreter#391f4415d9a77d15455f4d7efab65fc8cc931bc5",
.hash = "SPIRV_Interpreter-0.0.1-ajmpn6mrBwDO21UuGIRs3iP-0Z9GyhivF3N8V_X4tLzX",
.lazy = true,
},
//.SPIRV_Interpreter = .{
+2
View File
@@ -55,6 +55,7 @@ pub const DynamicState = struct {
pub const Vertex = struct {
primitive_restart: bool,
position: F32x4,
point_size: f32,
outputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS][4]?struct {
interpolation_type: enum { smooth, flat, noperspective },
blob: []u8,
@@ -106,6 +107,7 @@ pub const DrawCall = struct {
for (self.vertices) |*vertex| {
vertex.primitive_restart = false;
vertex.point_size = 1.0;
for (&vertex.outputs) |*location| {
@memset(location, null);
}
+1
View File
@@ -171,6 +171,7 @@ fn interpolateVertexForClipping(allocator: std.mem.Allocator, a: *const Vertex,
var result: Vertex = .{
.primitive_restart = false,
.position = a.position + ((b.position - a.position) * zm.f32x4s(t)),
.point_size = a.point_size + ((b.point_size - a.point_size) * t),
.outputs = undefined,
};
+7
View File
@@ -23,6 +23,7 @@ pub fn shaderInvocation(
draw_call: *Renderer.DrawCall,
batch_id: usize,
position: zm.F32x4,
point_coord: ?@Vector(2, f32),
front_face: bool,
inputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolationLocation,
derivative_inputs: ?DerivativeInputs,
@@ -54,6 +55,12 @@ pub fn shaderInvocation(
SpvRuntimeError.NotFound => {},
else => return err,
};
if (point_coord) |coord| {
rt.writeBuiltIn(std.mem.asBytes(&coord), .PointCoord) catch |err| switch (err) {
SpvRuntimeError.NotFound => {},
else => return err,
};
}
rt.writeBuiltIn(std.mem.asBytes(&front_face), .FrontFacing) catch |err| switch (err) {
SpvRuntimeError.NotFound => {},
else => return err,
+12 -2
View File
@@ -323,11 +323,13 @@ fn clipTransformAndRasterizePoint(
var transformed = vertex.*;
clip.viewportTransformVertex(draw_call.viewport, &transformed);
const point_size = 1.0;
const point_size = transformed.point_size;
const min_x: i32 = @intFromFloat(@ceil(transformed.position[0] - (point_size / 2.0) - 0.5));
const max_x: i32 = @intFromFloat(@ceil(transformed.position[0] + (point_size / 2.0) - 0.5) - 1.0);
const min_y: i32 = @intFromFloat(@ceil(transformed.position[1] - (point_size / 2.0) - 0.5));
const max_y: i32 = @intFromFloat(@ceil(transformed.position[1] + (point_size / 2.0) - 0.5) - 1.0);
const point_min_x = transformed.position[0] - (point_size / 2.0);
const point_min_y = transformed.position[1] - (point_size / 2.0);
const pipeline = draw_call.renderer.state.pipeline orelse return;
const has_fragment_shader = pipeline.stages.getPtr(.fragment) != null;
@@ -340,11 +342,19 @@ fn clipTransformAndRasterizePoint(
var outputs = std.mem.zeroes([spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(zm.F32x4)]u8);
if (has_fragment_shader) {
const frag_x = @as(f32, @floatFromInt(px)) + 0.5;
const frag_y = @as(f32, @floatFromInt(py)) + 0.5;
const point_coord = @Vector(2, f32){
(frag_x - point_min_x) / point_size,
(frag_y - point_min_y) / point_size,
};
outputs = fragment.shaderInvocation(
allocator,
draw_call,
0,
zm.f32x4(@floatFromInt(px), @floatFromInt(py), transformed.position[2], 1.0),
zm.f32x4(frag_x, frag_y, transformed.position[2], 1.0 / transformed.position[3]),
point_coord,
true,
try common.interpolateVertexOutputs(allocator, &transformed, &transformed, &transformed, 1.0, 0.0, 0.0),
null,
+6 -4
View File
@@ -45,9 +45,9 @@ pub fn drawLine(
const io = draw_call.renderer.device.interface.io();
var x0: i32 = @intFromFloat(v0.position[0]);
var y0: i32 = @intFromFloat(v0.position[1]);
var y0: i32 = @intFromFloat(@floor(v0.position[1] - 0.5));
var x1: i32 = @intFromFloat(v1.position[0]);
var y1: i32 = @intFromFloat(v1.position[1]);
var y1: i32 = @intFromFloat(@floor(v1.position[1] - 0.5));
const steep = blk: {
if (@abs(y1 - y0) > @abs(x1 - x0)) {
@@ -76,7 +76,7 @@ pub fn drawLine(
if (runtimes_count == 0)
return;
const step_count: usize = @as(usize, @intCast(d_x)) + 1;
const step_count: usize = if (d_x == 0) 1 else @intCast(d_x);
const runs_count = @min(runtimes_count, step_count);
const steps_per_run = @divTrunc(step_count + runs_count - 1, runs_count);
@@ -151,6 +151,7 @@ inline fn run(data: RunData) !void {
const t = @as(f32, @floatFromInt(step)) / @as(f32, @floatFromInt(@max(data.d_x, 1)));
const z = ((1.0 - t) * data.start_vertex.position[2]) + (t * data.end_vertex.position[2]);
const frag_w = ((1.0 - t) / data.start_vertex.position[3]) + (t / data.end_vertex.position[3]);
var outputs = std.mem.zeroes([spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(F32x4)]u8);
if (data.has_fragment_shader) {
@@ -158,7 +159,8 @@ inline fn run(data: RunData) !void {
data.allocator,
data.draw_call,
data.batch_id,
zm.f32x4(@floatFromInt(pixel_x), @floatFromInt(pixel_y), z, 1.0),
zm.f32x4(@as(f32, @floatFromInt(pixel_x)) + 0.5, @as(f32, @floatFromInt(pixel_y)) + 0.5, z, frag_w),
null,
true,
try common.interpolateLineOutputs(data.allocator, data.start_vertex, data.end_vertex, t),
null,
@@ -177,6 +177,7 @@ inline fn run(data: RunData) !void {
const b1 = w1 / data.area;
const b2 = w2 / data.area;
const z = (b0 * data.v0.position[2]) + (b1 * data.v1.position[2]) + (b2 * data.v2.position[2]);
const frag_w = (b0 / data.v0.position[3]) + (b1 / data.v1.position[3]) + (b2 / data.v2.position[3]);
var outputs = std.mem.zeroes([spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(F32x4)]u8);
if (data.has_fragment_shader) {
@@ -218,7 +219,8 @@ inline fn run(data: RunData) !void {
data.allocator,
data.draw_call,
data.batch_id,
zm.f32x4(@floatFromInt(x), @floatFromInt(y), z, 1.0),
zm.f32x4(@as(f32, @floatFromInt(x)) + 0.5, @as(f32, @floatFromInt(y)) + 0.5, z, frag_w),
null,
data.front_face,
inputs,
derivative_inputs,
+10
View File
@@ -107,6 +107,7 @@ inline fn run(data: RunData) !void {
};
try readPosition(rt, std.mem.asBytes(&output.position));
try readPointSize(rt, &output.point_size);
for (0..spv.SPIRV_MAX_OUTPUT_LOCATIONS) |location| {
for (0..4) |component| {
@@ -187,6 +188,15 @@ fn readPosition(rt: *spv.Runtime, output: []u8) !void {
return SpvRuntimeError.InvalidSpirV;
}
fn readPointSize(rt: *spv.Runtime, output: *f32) !void {
if (rt.readBuiltIn(std.mem.asBytes(output), .PointSize)) {
return;
} else |err| switch (err) {
SpvRuntimeError.InvalidSpirV, SpvRuntimeError.NotFound => {},
else => return err,
}
}
fn isConstantZero(rt: *spv.Runtime, result_word: spv.SpvWord) bool {
if (result_word >= rt.results.len)
return false;