added per-output centroid flag to vertex outputs
This commit is contained in:
@@ -73,6 +73,7 @@ pub const Vertex = struct {
|
||||
point_size: f32,
|
||||
outputs: [spv.SPIRV_MAX_OUTPUT_LOCATIONS][4]?struct {
|
||||
interpolation_type: InterpolationType,
|
||||
centroid: bool,
|
||||
blob: []u8,
|
||||
size: usize,
|
||||
},
|
||||
|
||||
@@ -187,6 +187,7 @@ fn interpolateVertexForClipping(allocator: std.mem.Allocator, a: *const Vertex,
|
||||
|
||||
result.outputs[location][component] = .{
|
||||
.interpolation_type = out_a.interpolation_type,
|
||||
.centroid = out_a.centroid,
|
||||
.blob = if (out_a.interpolation_type == .flat)
|
||||
allocator.dupe(u8, out_a.blob) catch return VkError.OutOfDeviceMemory
|
||||
else
|
||||
|
||||
@@ -477,7 +477,7 @@ fn rasterizeTransformedPoint(
|
||||
point_coord,
|
||||
null,
|
||||
true,
|
||||
try common.interpolateVertexOutputs(allocator, vertex, vertex, vertex, vertex, 1.0, 0.0, 0.0),
|
||||
try common.interpolateVertexOutputs(allocator, vertex, vertex, vertex, vertex, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0),
|
||||
null,
|
||||
) catch |err| {
|
||||
if (err == SpvRuntimeError.Killed)
|
||||
|
||||
@@ -262,6 +262,9 @@ pub fn interpolateVertexOutputs(
|
||||
b0: f32,
|
||||
b1: f32,
|
||||
b2: f32,
|
||||
centroid_b0: f32,
|
||||
centroid_b1: f32,
|
||||
centroid_b2: f32,
|
||||
) VkError![spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolationLocation {
|
||||
var inputs = [_]VertexInterpolationLocation{[_]VertexInterpolation{.{
|
||||
.blob = &.{},
|
||||
@@ -290,19 +293,23 @@ pub fn interpolateVertexOutputs(
|
||||
const input = allocator.alloc(u8, len + @sizeOf(F32x4)) catch return VkError.OutOfDeviceMemory;
|
||||
@memset(input, 0);
|
||||
|
||||
const input_b0 = if (out0.centroid) centroid_b0 else b0;
|
||||
const input_b1 = if (out0.centroid) centroid_b1 else b1;
|
||||
const input_b2 = if (out0.centroid) centroid_b2 else b2;
|
||||
|
||||
var byte_index: usize = 0;
|
||||
while (byte_index + @sizeOf(F32x4) <= len) : (byte_index += @sizeOf(F32x4)) {
|
||||
const value0 = std.mem.bytesToValue(F32x4, out0.blob[byte_index..]);
|
||||
const value1 = std.mem.bytesToValue(F32x4, out1.blob[byte_index..]);
|
||||
const value2 = std.mem.bytesToValue(F32x4, out2.blob[byte_index..]);
|
||||
base.utils.writePacked(F32x4, input[byte_index..], interpolateF32x4(out0.interpolation_type, value0, value1, value2, v0, v1, v2, b0, b1, b2));
|
||||
base.utils.writePacked(F32x4, input[byte_index..], interpolateF32x4(out0.interpolation_type, value0, value1, value2, v0, v1, v2, input_b0, input_b1, input_b2));
|
||||
}
|
||||
|
||||
while (byte_index + @sizeOf(f32) <= len) : (byte_index += @sizeOf(f32)) {
|
||||
const value0 = std.mem.bytesToValue(f32, out0.blob[byte_index..]);
|
||||
const value1 = std.mem.bytesToValue(f32, out1.blob[byte_index..]);
|
||||
const value2 = std.mem.bytesToValue(f32, out2.blob[byte_index..]);
|
||||
base.utils.writePacked(f32, input[byte_index..], interpolateF32(out0.interpolation_type, value0, value1, value2, v0, v1, v2, b0, b1, b2));
|
||||
base.utils.writePacked(f32, input[byte_index..], interpolateF32(out0.interpolation_type, value0, value1, value2, v0, v1, v2, input_b0, input_b1, input_b2));
|
||||
}
|
||||
|
||||
if (byte_index < len)
|
||||
@@ -322,7 +329,7 @@ pub fn interpolateLineOutputs(
|
||||
provoking_vertex: *const Renderer.Vertex,
|
||||
t: f32,
|
||||
) VkError![spv.SPIRV_MAX_OUTPUT_LOCATIONS]VertexInterpolationLocation {
|
||||
return interpolateVertexOutputs(allocator, v0, v1, v0, provoking_vertex, 1.0 - t, t, 0.0);
|
||||
return interpolateVertexOutputs(allocator, v0, v1, v0, provoking_vertex, 1.0 - t, t, 0.0, 1.0 - t, t, 0.0);
|
||||
}
|
||||
|
||||
pub fn interpolateVertexOutputDerivatives(
|
||||
|
||||
@@ -381,7 +381,7 @@ inline fn run(data: RunData) !void {
|
||||
if (early_depth.mask == 0)
|
||||
continue;
|
||||
|
||||
const interpolation_barycentrics = if (data.sample_count > 1 and data.fragment_uses_centroid) blk: {
|
||||
const centroid_barycentrics = if (data.sample_count > 1 and data.fragment_uses_centroid) blk: {
|
||||
const sample_pos = firstCoveredSamplePosition(data.sample_count, early_depth.mask);
|
||||
const centroid_p = zm.f32x4(
|
||||
@as(f32, @floatFromInt(x)) + sample_pos.x,
|
||||
@@ -398,9 +398,9 @@ inline fn run(data: RunData) !void {
|
||||
centroid_w2 / data.area,
|
||||
};
|
||||
} else .{ b0, b1, b2 };
|
||||
const input_b0 = interpolation_barycentrics[0];
|
||||
const input_b1 = interpolation_barycentrics[1];
|
||||
const input_b2 = interpolation_barycentrics[2];
|
||||
const centroid_b0 = centroid_barycentrics[0];
|
||||
const centroid_b1 = centroid_barycentrics[1];
|
||||
const centroid_b2 = centroid_barycentrics[2];
|
||||
|
||||
var fragment_result: fragment.InvocationResult = .{
|
||||
.outputs = std.mem.zeroes([spv.SPIRV_MAX_OUTPUT_LOCATIONS][@sizeOf(F32x4)]u8),
|
||||
@@ -417,7 +417,19 @@ inline fn run(data: RunData) !void {
|
||||
if ((early_depth.mask & sample_coverage_mask) == 0)
|
||||
continue;
|
||||
|
||||
const inputs = try common.interpolateVertexOutputs(data.allocator, &data.v0, &data.v1, &data.v2, &data.provoking_vertex, input_b0, input_b1, input_b2);
|
||||
const inputs = try common.interpolateVertexOutputs(
|
||||
data.allocator,
|
||||
&data.v0,
|
||||
&data.v1,
|
||||
&data.v2,
|
||||
&data.provoking_vertex,
|
||||
b0,
|
||||
b1,
|
||||
b2,
|
||||
centroid_b0,
|
||||
centroid_b1,
|
||||
centroid_b2,
|
||||
);
|
||||
const sample_result = fragment.shaderInvocation(
|
||||
data.allocator,
|
||||
data.draw_call,
|
||||
@@ -459,7 +471,19 @@ inline fn run(data: RunData) !void {
|
||||
continue;
|
||||
}
|
||||
if (data.has_fragment_shader) {
|
||||
const inputs = try common.interpolateVertexOutputs(data.allocator, &data.v0, &data.v1, &data.v2, &data.provoking_vertex, input_b0, input_b1, input_b2);
|
||||
const inputs = try common.interpolateVertexOutputs(
|
||||
data.allocator,
|
||||
&data.v0,
|
||||
&data.v1,
|
||||
&data.v2,
|
||||
&data.provoking_vertex,
|
||||
b0,
|
||||
b1,
|
||||
b2,
|
||||
centroid_b0,
|
||||
centroid_b1,
|
||||
centroid_b2,
|
||||
);
|
||||
const derivative_inputs: ?fragment.DerivativeInputs = if (data.fragment_uses_derivatives) blk: {
|
||||
var derivatives: fragment.DerivativeInputs = undefined;
|
||||
|
||||
|
||||
@@ -202,9 +202,10 @@ fn readVertexOutput(data: RunData, output: *Renderer.Vertex, rt: *spv.Runtime, l
|
||||
const value = try rt.results[result_word].getConstValue();
|
||||
const memory_size = try rt.getResultMemorySize(result_word);
|
||||
const interpolation_type = vertexOutputInterpolationType(data, rt, location, component, result_word);
|
||||
const centroid = fragmentInputHasDecoration(data, location, component, .Centroid);
|
||||
switch (value.*) {
|
||||
.Array, .Matrix => {
|
||||
try readVertexOutputAggregate(data, output, value, location, component, interpolation_type);
|
||||
try readVertexOutputAggregate(data, output, value, location, component, interpolation_type, centroid);
|
||||
return;
|
||||
},
|
||||
else => {},
|
||||
@@ -212,6 +213,7 @@ fn readVertexOutput(data: RunData, output: *Renderer.Vertex, rt: *spv.Runtime, l
|
||||
|
||||
output.outputs[location][component] = .{
|
||||
.interpolation_type = interpolation_type,
|
||||
.centroid = centroid,
|
||||
.blob = data.allocator.alloc(u8, memory_size + INTERFACE_BLOB_PADDING) catch return VkError.OutOfDeviceMemory,
|
||||
.size = memory_size,
|
||||
};
|
||||
@@ -226,22 +228,23 @@ fn readVertexOutputAggregate(
|
||||
location: usize,
|
||||
component: usize,
|
||||
interpolation_type: Renderer.InterpolationType,
|
||||
centroid: bool,
|
||||
) !void {
|
||||
var target_location = location;
|
||||
switch (value.*) {
|
||||
.Array => |array| {
|
||||
for (array.values) |*element| {
|
||||
try readVertexOutputAggregate(data, output, element, target_location, component, interpolation_type);
|
||||
try readVertexOutputAggregate(data, output, element, target_location, component, interpolation_type, centroid);
|
||||
target_location += vertexOutputValueLocationCount(element);
|
||||
}
|
||||
},
|
||||
.Matrix => |columns| {
|
||||
for (columns) |*column| {
|
||||
try writeVertexOutputValue(data, output, column, target_location, component, interpolation_type);
|
||||
try writeVertexOutputValue(data, output, column, target_location, component, interpolation_type, centroid);
|
||||
target_location += 1;
|
||||
}
|
||||
},
|
||||
else => try writeVertexOutputValue(data, output, value, location, component, interpolation_type),
|
||||
else => try writeVertexOutputValue(data, output, value, location, component, interpolation_type, centroid),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,6 +255,7 @@ fn writeVertexOutputValue(
|
||||
location: usize,
|
||||
component: usize,
|
||||
interpolation_type: Renderer.InterpolationType,
|
||||
centroid: bool,
|
||||
) !void {
|
||||
if (location >= spv.SPIRV_MAX_OUTPUT_LOCATIONS or component >= 4)
|
||||
return VkError.ValidationFailed;
|
||||
@@ -259,6 +263,7 @@ fn writeVertexOutputValue(
|
||||
const memory_size = try value.getPlainMemorySize();
|
||||
output.outputs[location][component] = .{
|
||||
.interpolation_type = interpolation_type,
|
||||
.centroid = centroid,
|
||||
.blob = data.allocator.alloc(u8, memory_size + INTERFACE_BLOB_PADDING) catch return VkError.OutOfDeviceMemory,
|
||||
.size = memory_size,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user