yes
This commit is contained in:
@@ -157,9 +157,10 @@ inline fn run(data: RunData) !void {
|
||||
continue;
|
||||
}
|
||||
|
||||
try setupWorkgroupBuiltins(data.self, rt, group_count_vec, group_id_vec);
|
||||
|
||||
for (0..data.invocations_per_workgroup) |i| {
|
||||
rt.resetInvocation(allocator);
|
||||
try setupWorkgroupBuiltins(data.self, rt, group_count_vec, group_id_vec);
|
||||
|
||||
const invocation_index = data.self.invocation_index.fetchAdd(1, .monotonic);
|
||||
|
||||
try setupSubgroupBuiltins(data.self, rt, .{
|
||||
@@ -202,6 +203,7 @@ fn runBarrierWorkgroup(
|
||||
const allocator = data.self.device.device_allocator.allocator();
|
||||
|
||||
for (runtimes, 0..) |*rt, i| {
|
||||
rt.resetInvocation(allocator);
|
||||
try ExecutionDevice.writeDescriptorSets(data.self.state, rt);
|
||||
try setupWorkgroupBuiltins(data.self, rt, group_count, group_id);
|
||||
try setupSubgroupBuiltins(data.self, rt, group_id, i);
|
||||
|
||||
+48
-10
@@ -19,10 +19,12 @@ const Self = @This();
|
||||
|
||||
pub const GRAPHICS_PIPELINE_STATE = 0;
|
||||
pub const COMPUTE_PIPELINE_STATE = 1;
|
||||
pub const MAX_DYNAMIC_DESCRIPTORS_PER_SET = 64;
|
||||
|
||||
pub const PipelineState = struct {
|
||||
pipeline: ?*SoftPipeline,
|
||||
sets: [base.VULKAN_MAX_DESCRIPTOR_SETS]?*SoftDescriptorSet,
|
||||
dynamic_offsets: [base.VULKAN_MAX_DESCRIPTOR_SETS][MAX_DYNAMIC_DESCRIPTORS_PER_SET]u32,
|
||||
push_constant_blob: [lib.PUSH_CONSTANT_SIZE]u8,
|
||||
data: union {
|
||||
compute: struct {},
|
||||
@@ -45,6 +47,7 @@ pub fn setup(self: *Self, device: *SoftDevice) void {
|
||||
state.* = .{
|
||||
.pipeline = null,
|
||||
.sets = [_]?*SoftDescriptorSet{null} ** base.VULKAN_MAX_DESCRIPTOR_SETS,
|
||||
.dynamic_offsets = [_][MAX_DYNAMIC_DESCRIPTORS_PER_SET]u32{[_]u32{0} ** MAX_DYNAMIC_DESCRIPTORS_PER_SET} ** base.VULKAN_MAX_DESCRIPTOR_SETS,
|
||||
.push_constant_blob = @splat(0),
|
||||
.data = switch (i) {
|
||||
GRAPHICS_PIPELINE_STATE => .{
|
||||
@@ -71,37 +74,66 @@ pub fn writeDescriptorSets(state: *PipelineState, rt: *spv.Runtime) !void {
|
||||
switch (binding) {
|
||||
.buffer => |buffer_data_array| for (buffer_data_array, 0..) |buffer_data, descriptor_index| {
|
||||
if (buffer_data.object) |buffer| {
|
||||
const map = buffer.mapAsSliceWithAddedOffset(u8, buffer_data.offset, buffer_data.size) catch continue :bindings;
|
||||
try rt.writeDescriptorSet(
|
||||
const binding_layout = set.?.interface.layout.bindings[binding_index];
|
||||
const dynamic_offset: vk.DeviceSize = switch (binding_layout.descriptor_type) {
|
||||
.uniform_buffer_dynamic, .storage_buffer_dynamic => state.dynamic_offsets[set_index][binding_layout.dynamic_index + descriptor_index],
|
||||
else => 0,
|
||||
};
|
||||
const map = buffer.mapAsSliceWithAddedOffset(u8, buffer_data.offset + dynamic_offset, buffer_data.size) catch continue :bindings;
|
||||
rt.writeDescriptorSet(
|
||||
map,
|
||||
@as(u32, @intCast(set_index)),
|
||||
@as(u32, @intCast(binding_index)),
|
||||
@as(u32, @intCast(descriptor_index)),
|
||||
);
|
||||
) catch |err| switch (err) {
|
||||
error.NotFound => {},
|
||||
else => return err,
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
.image => |image_data_array| for (image_data_array, 0..) |image_data, descriptor_index| {
|
||||
if (image_data.object) |image_view| {
|
||||
const addr: usize = @intFromPtr(image_view);
|
||||
try rt.writeDescriptorSet(
|
||||
rt.writeDescriptorSet(
|
||||
std.mem.asBytes(&addr),
|
||||
@as(u32, @intCast(set_index)),
|
||||
@as(u32, @intCast(binding_index)),
|
||||
@as(u32, @intCast(descriptor_index)),
|
||||
);
|
||||
) catch |err| switch (err) {
|
||||
error.NotFound => {},
|
||||
else => return err,
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
.sampler => |sampler_data_array| for (sampler_data_array, 0..) |sampler_data, descriptor_index| {
|
||||
if (sampler_data.object) |sampler| {
|
||||
const addr: usize = @intFromPtr(sampler);
|
||||
rt.writeDescriptorSet(
|
||||
std.mem.asBytes(&addr),
|
||||
@as(u32, @intCast(set_index)),
|
||||
@as(u32, @intCast(binding_index)),
|
||||
@as(u32, @intCast(descriptor_index)),
|
||||
) catch |err| switch (err) {
|
||||
error.NotFound => {},
|
||||
else => return err,
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
.texel_buffer => |texel_data_array| for (texel_data_array, 0..) |texel_data, descriptor_index| {
|
||||
if (texel_data.object) |buffer_view| {
|
||||
const addr: usize = @intFromPtr(buffer_view);
|
||||
try rt.writeDescriptorSet(
|
||||
rt.writeDescriptorSet(
|
||||
std.mem.asBytes(&addr),
|
||||
@as(u32, @intCast(set_index)),
|
||||
@as(u32, @intCast(binding_index)),
|
||||
@as(u32, @intCast(descriptor_index)),
|
||||
);
|
||||
) catch |err| switch (err) {
|
||||
error.NotFound => {},
|
||||
else => return err,
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
@@ -111,7 +143,10 @@ pub fn writeDescriptorSets(state: *PipelineState, rt: *spv.Runtime) !void {
|
||||
sampler: usize,
|
||||
};
|
||||
|
||||
var data: SampledImage = undefined;
|
||||
var data: SampledImage = .{
|
||||
.image = 0,
|
||||
.sampler = 0,
|
||||
};
|
||||
|
||||
if (texture_data.view) |image_view| {
|
||||
const addr: usize = @intFromPtr(image_view);
|
||||
@@ -122,12 +157,15 @@ pub fn writeDescriptorSets(state: *PipelineState, rt: *spv.Runtime) !void {
|
||||
data.sampler = addr;
|
||||
}
|
||||
|
||||
try rt.writeDescriptorSet(
|
||||
rt.writeDescriptorSet(
|
||||
std.mem.asBytes(&data),
|
||||
@as(u32, @intCast(set_index)),
|
||||
@as(u32, @intCast(binding_index)),
|
||||
@as(u32, @intCast(descriptor_index)),
|
||||
);
|
||||
) catch |err| switch (err) {
|
||||
error.NotFound => {},
|
||||
else => return err,
|
||||
};
|
||||
},
|
||||
|
||||
else => {},
|
||||
|
||||
@@ -50,6 +50,7 @@ pub const Vertex = struct {
|
||||
outputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS]?struct {
|
||||
interpolation_type: enum { smooth, flat, noperspective },
|
||||
blob: []u8,
|
||||
size: usize,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ const Renderer = @import("Renderer.zig");
|
||||
const Vertex = Renderer.Vertex;
|
||||
|
||||
const VkError = base.VkError;
|
||||
const INTERFACE_BLOB_PADDING = @sizeOf(F32x4);
|
||||
|
||||
const ClipPlane = enum {
|
||||
Left,
|
||||
@@ -142,9 +143,10 @@ fn isVertexInsidePlane(vertex: *const Vertex, plane: ClipPlane) bool {
|
||||
return clipDistance(vertex.position, plane) >= 0.0;
|
||||
}
|
||||
|
||||
fn interpolateBlob(allocator: std.mem.Allocator, a: []const u8, b: []const u8, t: f32) VkError![]u8 {
|
||||
const len = @min(a.len, b.len);
|
||||
const result = allocator.alloc(u8, len) catch return VkError.OutOfDeviceMemory;
|
||||
fn interpolateBlob(allocator: std.mem.Allocator, a: []const u8, b: []const u8, size: usize, t: f32) VkError![]u8 {
|
||||
const len = @min(size, a.len, b.len);
|
||||
const result = allocator.alloc(u8, len + INTERFACE_BLOB_PADDING) catch return VkError.OutOfDeviceMemory;
|
||||
@memset(result, 0);
|
||||
|
||||
var byte_index: usize = 0;
|
||||
while (byte_index + @sizeOf(F32x4) <= len) : (byte_index += @sizeOf(F32x4)) {
|
||||
@@ -160,7 +162,7 @@ fn interpolateBlob(allocator: std.mem.Allocator, a: []const u8, b: []const u8, t
|
||||
}
|
||||
|
||||
if (byte_index < len)
|
||||
@memcpy(result[byte_index..], a[byte_index..len]);
|
||||
@memcpy(result[byte_index..len], a[byte_index..len]);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -182,7 +184,8 @@ fn interpolateVertexForClipping(allocator: std.mem.Allocator, a: *const Vertex,
|
||||
.blob = if (out_a.interpolation_type == .flat)
|
||||
allocator.dupe(u8, out_a.blob) catch return VkError.OutOfDeviceMemory
|
||||
else
|
||||
try interpolateBlob(allocator, out_a.blob, out_b.blob, t),
|
||||
try interpolateBlob(allocator, out_a.blob, out_b.blob, @min(out_a.size, out_b.size), t),
|
||||
.size = @min(out_a.size, out_b.size),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ const SoftImage = @import("../SoftImage.zig");
|
||||
|
||||
const VkError = base.VkError;
|
||||
const SpvRuntimeError = spv.Runtime.RuntimeError;
|
||||
const INTERFACE_BLOB_PADDING = @sizeOf(zm.F32x4);
|
||||
|
||||
pub fn shaderInvocation(
|
||||
allocator: std.mem.Allocator,
|
||||
@@ -19,9 +20,11 @@ pub fn shaderInvocation(
|
||||
position: zm.F32x4,
|
||||
inputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolation,
|
||||
) SpvRuntimeError![spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(zm.F32x4)]u8 {
|
||||
var fragment_inputs = inputs;
|
||||
errdefer freeOwnedInputs(allocator, fragment_inputs);
|
||||
|
||||
const io = draw_call.renderer.device.interface.io();
|
||||
|
||||
_ = position;
|
||||
const pipeline = draw_call.renderer.state.pipeline orelse return undefined;
|
||||
|
||||
const shader = pipeline.stages.getPtr(.fragment) orelse return undefined;
|
||||
@@ -32,7 +35,12 @@ pub fn shaderInvocation(
|
||||
mutex.lock(io) catch return SpvRuntimeError.Unknown;
|
||||
defer mutex.unlock(io);
|
||||
|
||||
rt.resetInvocation(allocator);
|
||||
try rt.populatePushConstants(draw_call.renderer.state.push_constant_blob[0..]);
|
||||
rt.writeBuiltIn(std.mem.asBytes(&position), .FragCoord) catch |err| switch (err) {
|
||||
SpvRuntimeError.NotFound => {},
|
||||
else => return err,
|
||||
};
|
||||
|
||||
const entry = try rt.getEntryPointByName(shader.entry);
|
||||
|
||||
@@ -41,9 +49,23 @@ pub fn shaderInvocation(
|
||||
SpvRuntimeError.NotFound => continue,
|
||||
else => return err,
|
||||
};
|
||||
try rt.writeInput(inputs[location].blob, result_word);
|
||||
if (inputs[location].free_responsability)
|
||||
allocator.free(inputs[location].blob);
|
||||
|
||||
var input = fragment_inputs[location];
|
||||
if (input.blob.len == 0) {
|
||||
const memory_size = try rt.getResultMemorySize(result_word);
|
||||
const zeroes = allocator.alloc(u8, memory_size + INTERFACE_BLOB_PADDING) catch return SpvRuntimeError.OutOfMemory;
|
||||
@memset(zeroes, 0);
|
||||
fragment_inputs[location] = .{
|
||||
.blob = zeroes,
|
||||
.size = memory_size,
|
||||
.free_responsability = true,
|
||||
};
|
||||
input = fragment_inputs[location];
|
||||
}
|
||||
|
||||
if (input.blob.len != 0) {
|
||||
try rt.writeInput(input.blob, result_word);
|
||||
}
|
||||
}
|
||||
|
||||
rt.callEntryPoint(allocator, entry) catch |err| switch (err) {
|
||||
@@ -66,6 +88,14 @@ pub fn shaderInvocation(
|
||||
}
|
||||
|
||||
try rt.flushDescriptorSets(allocator);
|
||||
freeOwnedInputs(allocator, fragment_inputs);
|
||||
|
||||
return outputs;
|
||||
}
|
||||
|
||||
fn freeOwnedInputs(allocator: std.mem.Allocator, inputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolation) void {
|
||||
for (inputs) |input| {
|
||||
if (input.free_responsability)
|
||||
allocator.free(input.blob);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
const base = @import("base");
|
||||
const zm = base.zm;
|
||||
|
||||
const clip = @import("clip.zig");
|
||||
|
||||
const bresenham = @import("rasterizer/bresenham.zig");
|
||||
const edge_function = @import("rasterizer/edge_function.zig");
|
||||
const common = @import("rasterizer/common.zig");
|
||||
const fragment = @import("fragment.zig");
|
||||
const blitter = @import("blitter.zig");
|
||||
|
||||
const Renderer = @import("Renderer.zig");
|
||||
const Vertex = Renderer.Vertex;
|
||||
@@ -21,7 +24,7 @@ pub fn processThenFragmentStage(renderer: *Renderer, allocator: std.mem.Allocato
|
||||
const pipeline_data = (renderer.state.pipeline orelse return VkError.InvalidHandleDrv).interface.mode.graphics;
|
||||
const topology = pipeline_data.input_assembly.topology;
|
||||
|
||||
const color_attachments = draw_call.render_pass.interface.subpasses[renderer.subpass_index].color_attachments orelse return VkError.InvalidAttachmentDrv;
|
||||
const color_attachments = draw_call.render_pass.interface.subpasses[renderer.subpass_index].color_attachments orelse &.{};
|
||||
const color_attachment_access = allocator.alloc(?common.RenderTargetAccess, color_attachments.len) catch return VkError.OutOfDeviceMemory;
|
||||
@memset(color_attachment_access, null);
|
||||
|
||||
@@ -76,6 +79,15 @@ pub fn processThenFragmentStage(renderer: *Renderer, allocator: std.mem.Allocato
|
||||
};
|
||||
|
||||
switch (topology) {
|
||||
.point_list => for (draw_call.vertices) |*vertex| {
|
||||
try clipTransformAndRasterizePoint(
|
||||
allocator,
|
||||
draw_call,
|
||||
vertex,
|
||||
color_attachment_access,
|
||||
if (depth_attachment_access) |*access| access else null,
|
||||
);
|
||||
},
|
||||
.triangle_list => for (0..@divTrunc(draw_call.vertices.len, 3)) |triangle_index| {
|
||||
const first_vertex = triangle_index * 3;
|
||||
const v0 = &draw_call.vertices[first_vertex + 0];
|
||||
@@ -177,6 +189,61 @@ pub fn processThenFragmentStage(renderer: *Renderer, allocator: std.mem.Allocato
|
||||
draw_call.rasterizer_wait_group.await(io) catch return VkError.DeviceLost;
|
||||
}
|
||||
|
||||
fn clipTransformAndRasterizePoint(
|
||||
allocator: std.mem.Allocator,
|
||||
draw_call: *DrawCall,
|
||||
vertex: *Vertex,
|
||||
color_attachment_access: []const ?common.RenderTargetAccess,
|
||||
depth_attachment_access: ?*common.RenderTargetAccess,
|
||||
) VkError!void {
|
||||
const x, const y, const z, const w = vertex.position;
|
||||
if (w == 0.0 or x < -w or x > w or y < -w or y > w or z < 0.0 or z > w)
|
||||
return;
|
||||
|
||||
var transformed = vertex.*;
|
||||
clip.viewportTransformVertex(draw_call.viewport, &transformed);
|
||||
|
||||
const point_size = 1.0;
|
||||
const min_x: i32 = @intFromFloat(@floor(transformed.position[0] - (point_size / 2.0)));
|
||||
const max_x: i32 = @intFromFloat(@ceil(transformed.position[0] + (point_size / 2.0)) - 1.0);
|
||||
const min_y: i32 = @intFromFloat(@floor(transformed.position[1] - (point_size / 2.0)));
|
||||
const max_y: i32 = @intFromFloat(@ceil(transformed.position[1] + (point_size / 2.0)) - 1.0);
|
||||
|
||||
var py = min_y;
|
||||
while (py <= max_y) : (py += 1) {
|
||||
var px = min_x;
|
||||
while (px <= max_x) : (px += 1) {
|
||||
if (!common.scissorContainsPixel(draw_call.scissor, px, py))
|
||||
continue;
|
||||
|
||||
if (depth_attachment_access) |depth| {
|
||||
const offset = @as(usize, @intCast(px)) * depth.texel_size + @as(usize, @intCast(py)) * depth.row_pitch;
|
||||
const depth_value = blitter.readFloat4(depth.base[offset..], depth.format);
|
||||
if (transformed.position[2] >= depth_value[0])
|
||||
continue;
|
||||
}
|
||||
|
||||
const outputs = fragment.shaderInvocation(
|
||||
allocator,
|
||||
draw_call,
|
||||
0,
|
||||
zm.f32x4(@floatFromInt(px), @floatFromInt(py), transformed.position[2], 1.0),
|
||||
try common.interpolateVertexOutputs(allocator, &transformed, &transformed, &transformed, 1.0, 0.0, 0.0),
|
||||
) catch |err| {
|
||||
std.log.scoped(.@"Fragment stage").err("catched a '{s}'", .{@errorName(err)});
|
||||
if (comptime base.config.logs == .verbose) {
|
||||
if (@errorReturnTrace()) |trace| {
|
||||
std.debug.dumpErrorReturnTrace(trace);
|
||||
}
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
try common.writeToTargets(outputs, draw_call, color_attachment_access, depth_attachment_access, @intCast(px), @intCast(py), transformed.position[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn clipTransformAndRasterizeLine(
|
||||
allocator: std.mem.Allocator,
|
||||
draw_call: *DrawCall,
|
||||
|
||||
@@ -21,6 +21,7 @@ pub const RenderTargetAccess = struct {
|
||||
|
||||
pub const VertexInterpolation = struct {
|
||||
blob: []const u8,
|
||||
size: usize,
|
||||
free_responsability: bool,
|
||||
};
|
||||
|
||||
@@ -49,20 +50,25 @@ pub fn interpolateVertexOutputs(
|
||||
b1: f32,
|
||||
b2: f32,
|
||||
) VkError![spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolation {
|
||||
var inputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolation = undefined;
|
||||
var inputs = [_]VertexInterpolation{.{
|
||||
.blob = &.{},
|
||||
.size = 0,
|
||||
.free_responsability = false,
|
||||
}} ** spv.SPIRV_MAX_OUTPUT_LOCATIONS;
|
||||
|
||||
for (0..spv.SPIRV_MAX_OUTPUT_LOCATIONS) |location| {
|
||||
const out0 = v0.outputs[location] orelse continue;
|
||||
const out1 = v1.outputs[location] orelse continue;
|
||||
const out2 = v2.outputs[location] orelse continue;
|
||||
|
||||
if (out0.interpolation_type == .flat or out0.blob.len == 0) {
|
||||
inputs[location] = .{ .blob = out0.blob, .free_responsability = false };
|
||||
if (out0.interpolation_type == .flat or out0.size == 0) {
|
||||
inputs[location] = .{ .blob = out0.blob, .size = out0.size, .free_responsability = false };
|
||||
continue;
|
||||
}
|
||||
|
||||
const len = @min(out0.blob.len, out1.blob.len, out2.blob.len);
|
||||
const input = allocator.alloc(u8, len) catch return VkError.OutOfDeviceMemory;
|
||||
const len = @min(out0.size, out1.size, out2.size);
|
||||
const input = allocator.alloc(u8, len + @sizeOf(F32x4)) catch return VkError.OutOfDeviceMemory;
|
||||
@memset(input, 0);
|
||||
|
||||
var byte_index: usize = 0;
|
||||
while (byte_index + @sizeOf(F32x4) <= len) : (byte_index += @sizeOf(F32x4)) {
|
||||
@@ -80,9 +86,9 @@ pub fn interpolateVertexOutputs(
|
||||
}
|
||||
|
||||
if (byte_index < len)
|
||||
@memcpy(input[byte_index..], out0.blob[byte_index..len]);
|
||||
@memcpy(input[byte_index..len], out0.blob[byte_index..len]);
|
||||
|
||||
inputs[location] = .{ .blob = input, .free_responsability = true };
|
||||
inputs[location] = .{ .blob = input, .size = len, .free_responsability = true };
|
||||
}
|
||||
|
||||
return inputs;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
const std = @import("std");
|
||||
const spv = @import("spv");
|
||||
const base = @import("base");
|
||||
const vk = @import("vulkan");
|
||||
|
||||
const F32x4 = Renderer.F32x4;
|
||||
const F32x4 = base.zm.F32x4;
|
||||
|
||||
const SpvRuntimeError = spv.Runtime.RuntimeError;
|
||||
|
||||
@@ -10,6 +11,7 @@ const Renderer = @import("Renderer.zig");
|
||||
const SoftPipeline = @import("../SoftPipeline.zig");
|
||||
|
||||
const VkError = base.VkError;
|
||||
const INTERFACE_BLOB_PADDING = @sizeOf(F32x4);
|
||||
|
||||
pub const RunData = struct {
|
||||
allocator: std.mem.Allocator,
|
||||
@@ -38,12 +40,14 @@ pub fn runWrapper(data: RunData) void {
|
||||
inline fn run(data: RunData) !void {
|
||||
const shader = data.pipeline.stages.getPtrAssertContains(.vertex);
|
||||
const rt = &shader.runtimes[data.batch_id].rt;
|
||||
try rt.populatePushConstants(data.draw_call.renderer.state.push_constant_blob[0..]);
|
||||
|
||||
const entry = try rt.getEntryPointByName(shader.entry);
|
||||
|
||||
var invocation_index: usize = data.batch_id;
|
||||
while (invocation_index < data.vertex_count) : (invocation_index += data.batch_size) {
|
||||
rt.resetInvocation(data.allocator);
|
||||
try rt.populatePushConstants(data.draw_call.renderer.state.push_constant_blob[0..]);
|
||||
|
||||
const vertex_index: usize = if (data.indices) |indices| @intCast(indices[invocation_index]) else data.first_vertex + invocation_index;
|
||||
const instance_index = data.first_instance + data.instance_index;
|
||||
|
||||
@@ -54,8 +58,6 @@ inline fn run(data: RunData) !void {
|
||||
|
||||
if (data.pipeline.interface.mode.graphics.input_assembly.attribute_description) |attributes| {
|
||||
for (attributes) |attribute| {
|
||||
const location_result = try rt.getResultByLocation(attribute.location, .input);
|
||||
|
||||
const binding_info = (data.pipeline.interface.mode.graphics.input_assembly.binding_description orelse return)[attribute.binding];
|
||||
|
||||
const vertex_buffer = data.draw_call.renderer.state.data.graphics.vertex_buffers[attribute.binding];
|
||||
@@ -66,7 +68,7 @@ inline fn run(data: RunData) !void {
|
||||
|
||||
const buffer_memory_map: []u8 = try buffer_memory.map(offset, buffer_memory_size);
|
||||
|
||||
try rt.writeInput(buffer_memory_map, location_result);
|
||||
try writeVertexInput(rt, data.allocator, buffer_memory_map, attribute.format, attribute.location);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,10 +88,13 @@ inline fn run(data: RunData) !void {
|
||||
SpvRuntimeError.NotFound => continue,
|
||||
else => return err,
|
||||
};
|
||||
const memory_size = try rt.getResultMemorySize(result_word);
|
||||
output.outputs[location] = .{
|
||||
.interpolation_type = if (rt.hasResultDecoration(result_word, .Flat)) .flat else .smooth, // TODO : handle noperspective
|
||||
.blob = data.allocator.alloc(u8, try rt.getResultMemorySize(result_word)) catch return VkError.OutOfDeviceMemory,
|
||||
.blob = data.allocator.alloc(u8, memory_size + INTERFACE_BLOB_PADDING) catch return VkError.OutOfDeviceMemory,
|
||||
.size = memory_size,
|
||||
};
|
||||
@memset(output.outputs[location].?.blob, 0);
|
||||
try rt.readOutput(output.outputs[location].?.blob, result_word);
|
||||
}
|
||||
|
||||
@@ -104,3 +109,45 @@ fn setupBuiltins(rt: *spv.Runtime, vertex_index: usize, instance_index: usize) !
|
||||
try rt.writeBuiltIn(std.mem.asBytes(&vertex_index_u32), .VertexIndex);
|
||||
try rt.writeBuiltIn(std.mem.asBytes(&instance_index_u32), .InstanceIndex);
|
||||
}
|
||||
|
||||
fn writeVertexInput(
|
||||
rt: *spv.Runtime,
|
||||
allocator: std.mem.Allocator,
|
||||
raw_input: []const u8,
|
||||
format: vk.Format,
|
||||
location: u32,
|
||||
) !void {
|
||||
const input_memory_size = try rt.getInputLocationMemorySize(location);
|
||||
|
||||
if (raw_input.len >= input_memory_size) {
|
||||
try rt.writeInputLocation(raw_input[0..input_memory_size], location);
|
||||
return;
|
||||
}
|
||||
|
||||
const input = allocator.alloc(u8, input_memory_size) catch return VkError.OutOfDeviceMemory;
|
||||
defer allocator.free(input);
|
||||
|
||||
@memset(input, 0);
|
||||
@memcpy(input[0..raw_input.len], raw_input);
|
||||
|
||||
fillMissingVertexComponents(input, raw_input.len, format);
|
||||
try rt.writeInputLocation(input, location);
|
||||
}
|
||||
|
||||
fn fillMissingVertexComponents(input: []u8, raw_input_size: usize, format: vk.Format) void {
|
||||
if (input.len < @sizeOf(F32x4) or raw_input_size > 3 * @sizeOf(f32))
|
||||
return;
|
||||
|
||||
const component_count = base.format.componentCount(format);
|
||||
if (component_count >= 4)
|
||||
return;
|
||||
|
||||
const alpha_offset = 3 * @sizeOf(f32);
|
||||
if (base.format.isUnnormalizedInteger(format)) {
|
||||
const one: u32 = 1;
|
||||
@memcpy(input[alpha_offset .. alpha_offset + @sizeOf(u32)], std.mem.asBytes(&one));
|
||||
} else {
|
||||
const one: f32 = 1.0;
|
||||
@memcpy(input[alpha_offset .. alpha_offset + @sizeOf(f32)], std.mem.asBytes(&one));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user