Entirely remove the rasteriser

This commit is contained in:
2026-02-02 22:46:48 +00:00
parent 20de48175a
commit 1c4fb0c130
17 changed files with 569 additions and 1566 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
vulkano = "0.35.1"
vulkano = "0.35.2"
vulkano-shaders = { version = "0.35.0", features = ["shaderc-debug"] }
winit = "0.30"
vulkano-util = "0.35.0"
@@ -1,31 +0,0 @@
#ifndef compute_prepass_include
#define compute_prepass_include
#extension GL_GOOGLE_include_directive:require
#include "include.glsl"
layout(set = 1, binding = 0) restrict buffer Object {
uvec4 enable[(SPEC_MAXIMUM_SUBDIVISION * SPEC_MAXIMUM_SUBDIVISION * SPEC_MAXIMUM_SUBDIVISION) / (4 * 32)];
vec3 dimensions;
vec3 lowest_corner;
uint material;
uint subdivision_log2;
float farplane;
vec3 colour;
float metallic;
float roughness;
} object_uniforms;
float scene(vec4 p) {
return 0.0;
}
vec2 interval_scene(vec4 pl, vec4 ph) {
return vec2(0.0);
}
vec4 gradient_scene(vec4 p) {
return vec4(0.0);
}
#endif
@@ -4,18 +4,6 @@
#extension GL_GOOGLE_include_directive:require
#include "include.glsl"
layout(set = 1, binding = 0) uniform Object {
uvec4 enable[(SPEC_MAXIMUM_SUBDIVISION * SPEC_MAXIMUM_SUBDIVISION * SPEC_MAXIMUM_SUBDIVISION) / (4 * 32)];
vec3 dimensions;
vec3 lowest_corner;
uint material;
uint subdivision_log2;
float farplane;
vec3 colour;
float metallic;
float roughness;
} object_uniforms;
float scene(vec4 p) {
return 0.0;
}
+95 -30
View File
@@ -16,11 +16,6 @@ layout(constant_id = 10) const bool SPEC_USE_CPU_ENABLE_GEN = false;
//layout(constant_id = 30) const uint SPEC_MAXIMUM_SUBDIVISION = 64;
const uint SPEC_MAXIMUM_SUBDIVISION = 64;
layout(push_constant) uniform PushConstantData {
mat4 world;
mat4 inv_world;
} pc;
layout(set = 0, binding = 0) uniform Lights {
vec4[32] pos;
vec4[32] col;
@@ -33,33 +28,103 @@ layout(set = 0, binding = 1) uniform Camera {
mat4 inv_proj;
mat4 inv_view;
vec4 campos_and_time;
float specular;
float specular_tint;
float sheen_tint;
float sheen;
float clear_coat_gloss;
float subsurface;
float clear_coat;
} camera_uniforms;
/*
struct RTGBuffer {
uint normal; // 1010102
uint base_color; //1010102
float t;
uint8_t roughness;
uint8_t specular;
uint8_t specular_tint;
uint8_t sheen_tint;
uint8_t metallic;
uint8_t sheen;
uint8_t clear_coat_gloss;
uint8_t subsurface;
uint8_t clear_coat;
struct OVertex {
vec4 pos;
vec4 normal;
};
layout(set = 0, binding = 2, std430) restrict readonly buffer Verts {
OVertex verts[];
} verts;
layout(set = 0, binding = 3, std430) restrict readonly buffer Indicies {
uint indicies[];
} indicies;
struct Object {
vec3 dimensions;
vec3 lowest_corner;
uint subdivision_log2;
vec4 colour_and_roughness;
float metallic;
float subsurface;
float specular;
float specular_tint;
float sheen;
float sheen_tint;
float clear_coat_gloss;
float clear_coat;
};
struct Mesh {
uint vert_offset;
uint index_offset;
vec4 colour_and_roughness;
float metallic;
float subsurface;
float specular;
float specular_tint;
float sheen;
float sheen_tint;
float clear_coat_gloss;
float clear_coat;
};
layout(set = 0, binding = 4, std430) restrict readonly buffer Meshes {
Mesh meshes[];
} meshes;
layout(set = 0, binding = 5, std430) restrict readonly buffer Objects {
Object objects[];
} objects;
struct TenTenTenTwo {
uint data;
};
uint single_t_compress(float inp) {
uint t = uint(clamp(abs(inp), 0.0, 1.0) * float(0x1FF));
if (inp < 0.) {
t |= 0x200;
}
return t;
}
float single_t_uncompress(uint inp) {
float t = float(inp & 0x1FF) / float(0x1FF);
if ((inp & 0x200) > 0) {
t = -t;
}
return t;
}
TenTenTenTwo tttt_compress(vec3 inp) {
TenTenTenTwo outp;
outp.data = single_t_compress(inp.x);
outp.data |= (single_t_compress(inp.y) << 10);
outp.data |= (single_t_compress(inp.z) << 20);
return outp;
}
vec3 tttt_uncompress(TenTenTenTwo inp) {
vec3 outp;
outp.x = single_t_uncompress(inp.data);
outp.y = (single_t_uncompress(inp.data >> 10));
outp.z = (single_t_uncompress(inp.data >> 20));
return outp;
}
struct RTGBuffer {
TenTenTenTwo normal;
TenTenTenTwo base_color;
TenTenTenTwo roughness_specular_specular_tint;
TenTenTenTwo sheen_tint_metallic_sheen;
TenTenTenTwo clear_coat_gloss_subsurface_clear_coat;
float t;
};
*/
#endif
@@ -1,17 +0,0 @@
#version 460
#extension GL_GOOGLE_include_directive:require
#include "include.glsl"
layout(location = 0) out vec2 v_pos;
const vec2 full_screen_triangle[3] = {
vec2(0., 0.),
vec2(0., 2.),
vec2(2, 0.)
};
void main() {
vec2 tri = (full_screen_triangle[gl_VertexIndex - gl_BaseVertex] * 2.0) - 1.0;
v_pos = tri;
gl_Position = vec4(v_pos, gl_BaseVertex / 65536.0, 1.0);
}
+4 -13
View File
@@ -6,24 +6,15 @@
layout(location = 0) rayPayloadInEXT vec3 hit_value;
hitAttributeEXT vec2 baryCoord;
struct OVertex {
vec4 pos;
vec4 normal;
};
layout(set = 3, binding = 0, std430) restrict readonly buffer Verts {
OVertex verts[];
} verts;
layout(set = 3, binding = 1, std430) restrict readonly buffer Indicies {
uint indicies[];
} indicies;
Mesh mesh;
OVertex load_vert(uint index) {
return verts.verts[indicies.indicies[index]];
return verts.verts[mesh.vert_offset + indicies.indicies[mesh.index_offset + index]];
}
void main() {
mesh = meshes.meshes[gl_InstanceID];
// get mesh vertex data in object space
OVertex v0 = load_vert((gl_PrimitiveID * 3) + 0);
OVertex v1 = load_vert((gl_PrimitiveID * 3) + 1);
-55
View File
@@ -1,55 +0,0 @@
#version 460
#extension GL_GOOGLE_include_directive:require
#include "include.glsl"
#include "implicit_include.glsl"
layout(location = 0) in vec3 position;
layout(location = 0) out vec4 pos;
void main() {
uint base_index = gl_InstanceIndex; //gl_BaseInstance;
if (SPEC_BRUTE_FORCE) {
if (base_index > 0) {
gl_Position = vec4(0.0 / 0.0);
return;
}
pos = vec4((position * object_uniforms.dimensions) + object_uniforms.lowest_corner, 1.);
} else {
vec3 internal_pos = vec3(
float((base_index >> (object_uniforms.subdivision_log2 * 2)) & ((1 << object_uniforms.subdivision_log2) - 1))
/ float(1 << object_uniforms.subdivision_log2),
float((base_index >> (object_uniforms.subdivision_log2 * 1)) & ((1 << object_uniforms.subdivision_log2) - 1))
/ float(1 << object_uniforms.subdivision_log2),
float((base_index >> (object_uniforms.subdivision_log2 * 0)) & ((1 << object_uniforms.subdivision_log2) - 1))
/ float(1 << object_uniforms.subdivision_log2)
);
bool enable;
switch ((base_index >> 5) & 3) {
default:
case 0:
enable = (object_uniforms.enable[base_index >> 7].x & (1 << (base_index & 31))) != 0;
break;
case 1:
enable = (object_uniforms.enable[base_index >> 7].y & (1 << (base_index & 31))) != 0;
break;
case 2:
enable = (object_uniforms.enable[base_index >> 7].z & (1 << (base_index & 31))) != 0;
break;
case 3:
enable = (object_uniforms.enable[base_index >> 7].w & (1 << (base_index & 31))) != 0;
break;
}
if (!enable) {
gl_Position = vec4(0.0 / 0.0);
return;
}
pos = vec4((((position / float(1 << object_uniforms.subdivision_log2)) + internal_pos)
* object_uniforms.dimensions) + object_uniforms.lowest_corner, 1.);
}
gl_Position = camera_uniforms.proj_view * pc.world * pos;
}
@@ -1,6 +1,6 @@
#version 460
#extension GL_GOOGLE_include_directive:require
#include "compute_prepass_include.glsl"
#include "implicit_include.glsl"
struct AABB {
float min_x;
@@ -11,36 +11,44 @@ struct AABB {
float max_z;
};
layout(set = 1, binding = 1, std430) restrict writeonly buffer AABBS {
layout(set = 1, binding = 0, std430) restrict writeonly buffer AABBS {
AABB aabbs[];
} aabbs;
layout(push_constant, std430) uniform PushConstantData {
uint object_index;
} pc;
layout(local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
const float NAN = 0.0 / 0.0;
Object object;
void main() {
if (SPEC_BRUTE_FORCE || SPEC_USE_CPU_ENABLE_GEN) {
if (SPEC_BRUTE_FORCE) {
return;
}
object = objects.objects[pc.object_index];
uvec3 total_invocations = gl_NumWorkGroups * gl_WorkGroupSize;
uint base_index = (gl_GlobalInvocationID.z * total_invocations.x * total_invocations.y) +
(gl_GlobalInvocationID.y * total_invocations.x) + gl_GlobalInvocationID.x;
vec3 internal_pos = vec3(
float((base_index >> (object_uniforms.subdivision_log2 * 2)) & ((1 << object_uniforms.subdivision_log2) - 1))
/ float(1 << object_uniforms.subdivision_log2),
float((base_index >> (object_uniforms.subdivision_log2 * 1)) & ((1 << object_uniforms.subdivision_log2) - 1))
/ float(1 << object_uniforms.subdivision_log2),
float((base_index >> (object_uniforms.subdivision_log2 * 0)) & ((1 << object_uniforms.subdivision_log2) - 1))
/ float(1 << object_uniforms.subdivision_log2)
float((base_index >> (object.subdivision_log2 * 2)) & ((1 << object.subdivision_log2) - 1))
/ float(1 << object.subdivision_log2),
float((base_index >> (object.subdivision_log2 * 1)) & ((1 << object.subdivision_log2) - 1))
/ float(1 << object.subdivision_log2),
float((base_index >> (object.subdivision_log2 * 0)) & ((1 << object.subdivision_log2) - 1))
/ float(1 << object.subdivision_log2)
);
vec3 low_corner = (((vec3(0.0) / float(1 << object_uniforms.subdivision_log2)) + internal_pos)
* object_uniforms.dimensions) + object_uniforms.lowest_corner;
vec3 high_corner = (((vec3(1.0) / float(1 << object_uniforms.subdivision_log2)) + internal_pos)
* object_uniforms.dimensions) + object_uniforms.lowest_corner;
vec3 low_corner = (((vec3(0.0) / float(1 << object.subdivision_log2)) + internal_pos)
* object.dimensions) + object.lowest_corner;
vec3 high_corner = (((vec3(1.0) / float(1 << object.subdivision_log2)) + internal_pos)
* object.dimensions) + object.lowest_corner;
vec2 interval = interval_scene(
vec4(low_corner, camera_uniforms.campos_and_time.w),
@@ -59,36 +67,4 @@ void main() {
} else {
aabbs.aabbs[base_index].min_x = NAN;
}
switch ((base_index >> 5) & 3) {
default:
case 0:
if (enable) {
atomicOr(object_uniforms.enable[base_index >> 7].x, (1 << (base_index & 31)));
} else {
atomicAnd(object_uniforms.enable[base_index >> 7].x, (~(1 << (base_index & 31))));
}
break;
case 1:
if (enable) {
atomicOr(object_uniforms.enable[base_index >> 7].y, (1 << (base_index & 31)));
} else {
atomicAnd(object_uniforms.enable[base_index >> 7].y, (~(1 << (base_index & 31))));
}
break;
case 2:
if (enable) {
atomicOr(object_uniforms.enable[base_index >> 7].z, (1 << (base_index & 31)));
} else {
atomicAnd(object_uniforms.enable[base_index >> 7].z, (~(1 << (base_index & 31))));
}
break;
case 3:
if (enable) {
atomicOr(object_uniforms.enable[base_index >> 7].w, (1 << (base_index & 31)));
} else {
atomicAnd(object_uniforms.enable[base_index >> 7].w, (~(1 << (base_index & 31))));
}
break;
}
}
@@ -1,43 +0,0 @@
#version 460
#extension GL_GOOGLE_include_directive:require
#include "include.glsl"
#include "implicit_include.glsl"
layout(location = 0) in vec4 pos;
layout(depth_greater) out float gl_FragDepth;
layout(location = 0) out uint material;
const float EPSILON = .001;
const uint MAX_STEPS = 50;
void main() {
if (SPEC_BOUNDING_BOXES) {
material = object_uniforms.material;
return;
}
vec3 raypos = pos.xyz;
vec3 raydir = normalize(raypos - (pc.inv_world * vec4(camera_uniforms.campos_and_time.xyz, 1)).xyz);
float farplane = SPEC_BRUTE_FORCE ? length(object_uniforms.dimensions) : object_uniforms.farplane;
vec3 p = raypos;
float total_dist = 0.;
for (uint i = 0; i < MAX_STEPS; i++) {
float dist = scene(vec4(p, camera_uniforms.campos_and_time.w));
total_dist += dist;
p = fma(raydir, vec3(total_dist), raypos);
if (abs(dist) < EPSILON) {
vec4 tpoint = camera_uniforms.proj_view * pc.world * vec4(p, 1);
gl_FragDepth = (tpoint.z / tpoint.w);
material = object_uniforms.material;
return;
} else if (total_dist > farplane) {
discard;
}
}
discard;
}
+10 -66
View File
@@ -1,27 +1,21 @@
use std::{sync::Arc, thread};
use std::thread;
use vulkano::{
buffer::{BufferContents, BufferWriteGuard, Subbuffer},
command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, CopyBufferInfo, PrimaryCommandBufferAbstract,
allocator::CommandBufferAllocator,
},
device::Queue,
sync::{AccessConflict, GpuFuture, HostAccessError},
sync::HostAccessError,
};
fn get_host_buffer_writer<'a, T>(host_visible: &'a Subbuffer<T>) -> BufferWriteGuard<'a, T>
fn get_host_buffer_writer<'a, T>(device_local: &'a Subbuffer<T>) -> BufferWriteGuard<'a, T>
where
T: BufferContents + ?Sized,
{
let mut writer = host_visible.write();
let mut writer = device_local.write();
'writerloop: loop {
match writer {
Err(HostAccessError::AccessConflict(AccessConflict::DeviceRead))
| Err(HostAccessError::AccessConflict(AccessConflict::DeviceWrite)) => {
Err(HostAccessError::AccessConflict(_)) => {
//warn!("WAITING FOR HOST BUFFER FREE");
thread::yield_now();
writer = host_visible.write();
writer = device_local.write();
},
_ => break 'writerloop,
}
@@ -29,72 +23,22 @@ where
writer.unwrap()
}
pub(crate) fn gpu_upload<T>(
input: T,
device_local: Subbuffer<T>,
host_visible: Subbuffer<T>,
command_allocator: Arc<dyn CommandBufferAllocator>,
transfer_queue: Arc<Queue>,
) -> Box<dyn GpuFuture + Send + Sync>
pub(crate) fn gpu_upload<T>(input: T, device_local: Subbuffer<T>)
where
T: BufferContents,
{
{
let mut writer = get_host_buffer_writer(&host_visible);
let mut writer = get_host_buffer_writer(&device_local);
*writer = input;
}
gpu_upload_command_buffer(
device_local,
host_visible,
command_allocator,
transfer_queue,
)
}
pub(crate) fn gpu_upload_slice<T>(
input: &[T],
device_local: Subbuffer<[T]>,
host_visible: Subbuffer<[T]>,
command_allocator: Arc<dyn CommandBufferAllocator>,
transfer_queue: Arc<Queue>,
) -> Box<dyn GpuFuture + Send + Sync>
pub(crate) fn gpu_upload_slice<T>(input: &[T], device_local: Subbuffer<[T]>)
where
T: BufferContents + Copy,
{
{
let mut writer = get_host_buffer_writer(&host_visible);
let mut writer = get_host_buffer_writer(&device_local);
writer.copy_from_slice(input);
}
gpu_upload_command_buffer(
device_local,
host_visible,
command_allocator,
transfer_queue,
)
}
fn gpu_upload_command_buffer<T>(
device_local: Subbuffer<T>,
host_visible: Subbuffer<T>,
command_allocator: Arc<dyn CommandBufferAllocator>,
transfer_queue: Arc<Queue>,
) -> Box<dyn GpuFuture + Send + Sync>
where
T: BufferContents + ?Sized,
{
let mut builder = AutoCommandBufferBuilder::primary(
command_allocator,
transfer_queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.copy_buffer(CopyBufferInfo::buffers(host_visible, device_local))
.unwrap();
let commands = builder.build().unwrap();
commands.execute(transfer_queue).unwrap().boxed_send_sync()
}
+35 -101
View File
@@ -1,12 +1,12 @@
use std::sync::{Arc, RwLock};
use egui::{Color32, Frame, Id};
use egui::{Color32, Frame, Id, Ui};
use egui_plot::{Line, Plot, PlotPoints};
use egui_winit_vulkano::Gui;
use crate::{
MAXIMUM_SUBDIVISION, MINUMUM_SUBDIVISION,
objects::{CSG, Light, Mesh},
objects::{CSG, Light, Material, Mesh, Position},
};
fn sized_text(ui: &mut egui::Ui, text: impl Into<String>, size: f32) {
@@ -44,14 +44,6 @@ pub(crate) struct GState {
pub(crate) debug: PreviousDebug,
pub(crate) subsurface: f32,
pub(crate) specular: f32,
pub(crate) specular_tint: f32,
pub(crate) sheen: f32,
pub(crate) sheen_tint: f32,
pub(crate) clear_coat_gloss: f32,
pub(crate) clear_coat: f32,
pub(crate) recreate_pipelines: bool,
pub(crate) reset_time: bool,
}
@@ -73,20 +65,41 @@ impl Default for GState {
debug: Default::default(),
specular: 0.73,
specular_tint: 0.,
sheen_tint: 0.,
sheen: 0.58,
clear_coat_gloss: 0.63,
subsurface: 0.,
clear_coat: 0.85,
recreate_pipelines: false,
reset_time: false,
}
}
}
fn draw_position(ui: &mut Ui, position: &mut Position) {
ui.heading("Position");
ui.add(egui::Slider::new(&mut position.pos.x, -100.0..=100.0).text("Position.x"));
ui.add(egui::Slider::new(&mut position.pos.y, -100.0..=100.0).text("Position.y"));
ui.add(egui::Slider::new(&mut position.pos.z, -100.0..=100.0).text("Position.z"));
ui.add(egui::Slider::new(&mut position.rot.x, 0.0..=360.0).text("Rotation.x"));
ui.add(egui::Slider::new(&mut position.rot.y, 0.0..=360.0).text("Rotation.y"));
ui.add(egui::Slider::new(&mut position.rot.z, 0.0..=360.0).text("Rotation.z"));
ui.add(egui::Slider::new(&mut position.scale.x, 0.0..=2.0).text("Scale.x"));
ui.add(egui::Slider::new(&mut position.scale.y, 0.0..=2.0).text("Scale.y"));
ui.add(egui::Slider::new(&mut position.scale.z, 0.0..=2.0).text("Scale.z"));
}
fn draw_material(ui: &mut Ui, material: &mut Material) {
ui.heading("Material");
ui.add(egui::Slider::new(&mut material.colour.x, 0.0..=1.0).text("Colour.r"));
ui.add(egui::Slider::new(&mut material.colour.y, 0.0..=1.0).text("Colour.g"));
ui.add(egui::Slider::new(&mut material.colour.z, 0.0..=1.0).text("Colour.b"));
ui.add(egui::Slider::new(&mut material.roughness, 0.0..=1.0).text("Roughness"));
ui.add(egui::Slider::new(&mut material.metallic, 0.0..=1.0).text("Metallic"));
ui.add(egui::Slider::new(&mut material.subsurface, 0.0..=1.0).text("Subsurface"));
ui.add(egui::Slider::new(&mut material.specular, 0.0..=1.0).text("Specular"));
ui.add(egui::Slider::new(&mut material.specular_tint, 0.0..=1.0).text("Specular tint"));
ui.add(egui::Slider::new(&mut material.sheen, 0.0..=1.0).text("Sheen"));
ui.add(egui::Slider::new(&mut material.sheen_tint, 0.0..=1.0).text("Sheen tint"));
ui.add(egui::Slider::new(&mut material.clear_coat, 0.0..=1.0).text("Clear Coat"));
ui.add(egui::Slider::new(&mut material.clear_coat_gloss, 0.0..=1.0).text("Clear Coat Gloss"));
}
pub(crate) fn gui_up(gui: &mut Gui, state: &mut GState) {
gui.immediate_ui(|gui| {
let ctx = gui.context();
@@ -109,26 +122,6 @@ pub(crate) fn gui_up(gui: &mut Gui, state: &mut GState) {
egui::Slider::new(&mut state.move_speed, 0.0..=2.0)
.text("Movement Speed"),
);
ui.heading("Material");
ui.add(
egui::Slider::new(&mut state.subsurface, 0.0..=1.0).text("Subsurface"),
);
ui.add(egui::Slider::new(&mut state.specular, 0.0..=1.0).text("Specular"));
ui.add(
egui::Slider::new(&mut state.specular_tint, 0.0..=1.0)
.text("Specular tint"),
);
ui.add(egui::Slider::new(&mut state.sheen, 0.0..=1.0).text("Sheen"));
ui.add(
egui::Slider::new(&mut state.sheen_tint, 0.0..=1.0).text("Sheen tint"),
);
ui.add(
egui::Slider::new(&mut state.clear_coat, 0.0..=1.0).text("Clear Coat"),
);
ui.add(
egui::Slider::new(&mut state.clear_coat_gloss, 0.0..=1.0)
.text("Clear Coat Gloss"),
);
let meshes_len = state.meshes.len();
let csg_len = state.csg.len();
ui.heading(format!("Meshes ({})", meshes_len));
@@ -138,30 +131,8 @@ pub(crate) fn gui_up(gui: &mut Gui, state: &mut GState) {
if meshes_len > 1 || csg_len > 0 {
meshdel.push(ui.small_button("remove mesh").clicked());
}
ui.add(
egui::Slider::new(&mut mesh.pos.x, -100.0..=100.0)
.text("Position.x"),
);
ui.add(
egui::Slider::new(&mut mesh.pos.y, -100.0..=100.0)
.text("Position.y"),
);
ui.add(
egui::Slider::new(&mut mesh.pos.z, -100.0..=100.0)
.text("Position.z"),
);
ui.add(
egui::Slider::new(&mut mesh.rot.x, 0.0..=360.0).text("Rotation.x"),
);
ui.add(
egui::Slider::new(&mut mesh.rot.y, 0.0..=360.0).text("Rotation.y"),
);
ui.add(
egui::Slider::new(&mut mesh.rot.z, 0.0..=360.0).text("Rotation.z"),
);
ui.add(egui::Slider::new(&mut mesh.scale.x, 0.0..=2.0).text("Scale.x"));
ui.add(egui::Slider::new(&mut mesh.scale.y, 0.0..=2.0).text("Scale.y"));
ui.add(egui::Slider::new(&mut mesh.scale.z, 0.0..=2.0).text("Scale.z"));
draw_position(ui, &mut mesh.position);
draw_material(ui, &mut mesh.material);
}
for i in meshdel
.into_iter()
@@ -178,45 +149,8 @@ pub(crate) fn gui_up(gui: &mut Gui, state: &mut GState) {
if meshes_len > 0 || csg_len > 1 {
csgdel.push(ui.small_button("remove csg").clicked());
}
ui.add(
egui::Slider::new(&mut csg.pos.x, -100.0..=100.0)
.text("Position.x"),
);
ui.add(
egui::Slider::new(&mut csg.pos.y, -100.0..=100.0)
.text("Position.y"),
);
ui.add(
egui::Slider::new(&mut csg.pos.z, -100.0..=100.0)
.text("Position.z"),
);
ui.add(
egui::Slider::new(&mut csg.rot.x, 0.0..=360.0).text("Rotation.x"),
);
ui.add(
egui::Slider::new(&mut csg.rot.y, 0.0..=360.0).text("Rotation.y"),
);
ui.add(
egui::Slider::new(&mut csg.rot.z, 0.0..=360.0).text("Rotation.z"),
);
ui.add(egui::Slider::new(&mut csg.scale.x, 0.0..=2.0).text("Scale.x"));
ui.add(egui::Slider::new(&mut csg.scale.y, 0.0..=2.0).text("Scale.y"));
ui.add(egui::Slider::new(&mut csg.scale.z, 0.0..=2.0).text("Scale.z"));
ui.add(
egui::Slider::new(&mut csg.colour.x, 0.0..=1.0).text("Colour.r"),
);
ui.add(
egui::Slider::new(&mut csg.colour.y, 0.0..=1.0).text("Colour.g"),
);
ui.add(
egui::Slider::new(&mut csg.colour.z, 0.0..=1.0).text("Colour.b"),
);
ui.add(
egui::Slider::new(&mut csg.roughness, 0.0..=1.0).text("Roughness"),
);
ui.add(
egui::Slider::new(&mut csg.metallic, 0.0..=1.0).text("Metallic"),
);
draw_position(ui, &mut csg.position);
draw_material(ui, &mut csg.material);
ui.horizontal(|ui| {
ui.label("Subdivision");
for x in MINUMUM_SUBDIVISION.ilog2()..=MAXIMUM_SUBDIVISION.ilog2() {
+168 -655
View File
File diff suppressed because it is too large Load Diff
+104 -69
View File
@@ -1,6 +1,9 @@
use std::{
io::Read,
sync::{Arc, RwLock},
sync::{
Arc, RwLock,
atomic::{AtomicU64, Ordering},
},
};
use bytemuck::{Pod, Zeroable};
@@ -8,16 +11,14 @@ use foldhash::{HashMap, HashMapExt};
use glam::{self, Vec3};
use obj::{LoadConfig, ObjData, ObjError};
use vulkano::{
buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer},
DeviceSize,
buffer::Subbuffer,
descriptor_set::DescriptorSet,
memory::allocator::{
AllocationCreateInfo, MemoryAllocatePreference, MemoryAllocator, MemoryTypeFilter,
},
pipeline::{ComputePipeline, GraphicsPipeline, graphics::vertex_input::Vertex},
pipeline::{ComputePipeline, graphics::vertex_input::Vertex},
shader::ShaderModule,
};
use crate::{ssa::SSATape, trace_vs::Object};
use crate::ssa::SSATape;
pub(crate) const PLATONIC_SOLIDS: [(&str, &[u8]); 1] =
[("Buny", include_bytes!("../data/bunny.obj"))];
@@ -32,46 +33,92 @@ pub(crate) struct OVertex {
normal: [f32; 4],
}
#[derive(Debug)]
pub(crate) struct Position {
pub(crate) pos: Vec3,
pub(crate) rot: Vec3,
pub(crate) scale: Vec3,
pub(crate) transform_offset: DeviceSize,
}
#[derive(Debug)]
pub(crate) struct Material {
pub(crate) colour: Vec3,
pub(crate) roughness: f32,
pub(crate) metallic: f32,
pub(crate) subsurface: f32,
pub(crate) specular: f32,
pub(crate) specular_tint: f32,
pub(crate) sheen: f32,
pub(crate) sheen_tint: f32,
pub(crate) clear_coat_gloss: f32,
pub(crate) clear_coat: f32,
}
#[derive(Debug)]
pub(crate) struct Mesh {
pub(crate) name: String,
pub(crate) vertices: Subbuffer<[OVertex]>,
pub(crate) indices: Subbuffer<[u32]>,
pub(crate) pos: Vec3,
pub(crate) rot: Vec3,
pub(crate) scale: Vec3,
pub(crate) name: String,
pub(crate) position: Position,
pub(crate) material: Material,
pub(crate) vert_offset: DeviceSize,
pub(crate) vert_len: DeviceSize,
pub(crate) index_offset: DeviceSize,
pub(crate) index_len: DeviceSize,
}
#[derive(Debug)]
pub(crate) struct CSG {
pub(crate) name: String,
pub(crate) _seed: u64,
pub(crate) parts: SSATape,
pub(crate) pos: Vec3,
pub(crate) rot: Vec3,
pub(crate) scale: Vec3,
pub(crate) colour: Vec3,
pub(crate) roughness: f32,
pub(crate) metallic: f32,
pub(crate) replacement_modules: Arc<RwLock<HashMap<String, Arc<ShaderModule>>>>,
pub(crate) trace_pipeline: Arc<GraphicsPipeline>,
pub(crate) normals_pipeline: Arc<GraphicsPipeline>,
pub(crate) fuzz_pipeline: Arc<ComputePipeline>,
pub(crate) enable_gen_pipeline: Arc<ComputePipeline>,
pub(crate) name: String,
pub(crate) position: Position,
pub(crate) material: Material,
pub(crate) parts: SSATape,
pub(crate) _seed: u64,
pub(crate) subdivision: u32,
pub(crate) enable_buffer: Vec<Subbuffer<Object>>,
pub(crate) enable_buffer_host_visible: Vec<Subbuffer<Object>>,
pub(crate) trace_descriptor_set: Vec<Arc<DescriptorSet>>,
pub(crate) normals_descriptor_set: Vec<Arc<DescriptorSet>>,
pub(crate) replacement_modules: Arc<RwLock<HashMap<String, Arc<ShaderModule>>>>,
pub(crate) fuzz_pipeline: Arc<ComputePipeline>,
pub(crate) enable_gen_pipeline: Arc<ComputePipeline>,
pub(crate) aabb_buffer: Vec<Subbuffer<[u8]>>,
pub(crate) enable_gen_descriptor_set: Vec<Arc<DescriptorSet>>,
pub(crate) aabb_buffer: Vec<Subbuffer<[u8]>>,
}
impl Default for Position {
fn default() -> Self {
Self {
pos: Vec3::ZERO,
rot: Vec3::ZERO,
scale: Vec3::ONE,
transform_offset: 0,
}
}
}
impl Default for Material {
fn default() -> Self {
Self {
colour: Vec3::ONE,
roughness: 1.0,
metallic: 0.67,
specular: 0.73,
specular_tint: 0.,
sheen_tint: 0.,
sheen: 0.58,
clear_coat_gloss: 0.63,
subsurface: 0.,
clear_coat: 0.85,
}
}
}
pub(crate) fn load_obj(
memory_allocator: &Arc<dyn MemoryAllocator>,
input: &mut dyn Read,
name: String,
additional_usage: BufferUsage,
vertex_buffer: Subbuffer<[OVertex]>,
vertex_buffer_pointer: Arc<AtomicU64>,
index_buffer: Subbuffer<[u32]>,
index_buffer_pointer: Arc<AtomicU64>,
transform_buffer_pointer: Arc<AtomicU64>,
) -> Result<Vec<Mesh>, ObjError> {
let object = ObjData::load_buf_with_config(input, LoadConfig::default())?;
@@ -108,45 +155,33 @@ pub(crate) fn load_obj(
}
}
let vertex_buffer = Buffer::from_iter(
memory_allocator.clone(),
BufferCreateInfo {
usage: BufferUsage::STORAGE_BUFFER | additional_usage,
..Default::default()
},
AllocationCreateInfo {
memory_type_filter: MemoryTypeFilter::PREFER_HOST
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
allocate_preference: MemoryAllocatePreference::AlwaysAllocate,
..Default::default()
},
vertices,
)
.unwrap();
let vertex_offset =
vertex_buffer_pointer.fetch_add(vertices.len() as u64, Ordering::Relaxed) as usize;
let index_offset =
index_buffer_pointer.fetch_add(indices.len() as u64, Ordering::Relaxed) as usize;
let transform_offset = transform_buffer_pointer.fetch_add(1, Ordering::Relaxed) as usize;
let index_buffer = Buffer::from_iter(
memory_allocator.clone(),
BufferCreateInfo {
usage: BufferUsage::STORAGE_BUFFER | additional_usage,
..Default::default()
},
AllocationCreateInfo {
memory_type_filter: MemoryTypeFilter::PREFER_HOST
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
allocate_preference: MemoryAllocatePreference::AlwaysAllocate,
..Default::default()
},
indices,
)
.unwrap();
{
let mut write = vertex_buffer.write().unwrap();
write[vertex_offset..(vertex_offset + vertices.len())].copy_from_slice(&vertices);
}
{
let mut write = index_buffer.write().unwrap();
write[index_offset..(index_offset + indices.len())].copy_from_slice(&indices);
}
Ok(vec![Mesh {
vertices: vertex_buffer,
indices: index_buffer,
pos: Vec3::ZERO,
rot: Vec3::ZERO,
scale: Vec3::ONE,
name,
position: Position {
transform_offset: transform_offset as _,
..Default::default()
},
material: Default::default(),
vert_offset: vertex_offset as _,
vert_len: vertices.len() as u64,
index_offset: index_offset as _,
index_len: indices.len() as u64,
}])
}
+80 -7
View File
@@ -4,8 +4,9 @@ use std::{
sync::{Arc, RwLock},
};
use glam::{EulerRot, Mat4};
use vulkano::{
Packed24_8,
DeviceSize, Packed24_8,
acceleration_structure::{
AccelerationStructure, AccelerationStructureBuildGeometryInfo,
AccelerationStructureBuildRangeInfo, AccelerationStructureBuildType,
@@ -22,7 +23,11 @@ use vulkano::{
memory::allocator::{AllocationCreateInfo, DeviceLayout, MemoryAllocator, MemoryTypeFilter},
};
use crate::objects::{CSG, Mesh, OVertex};
use crate::{
enable_gen_cs,
gpu_upload::gpu_upload,
objects::{CSG, Mesh, OVertex, Position},
};
pub struct Scene {
// The bottom-level acceleration structure is required to be kept alive
@@ -39,6 +44,10 @@ impl Scene {
memory_allocator: &Arc<dyn MemoryAllocator>,
meshes: &[Mesh],
csgs: &[Arc<RwLock<CSG>>],
vertex_buffer: &Subbuffer<[OVertex]>,
index_buffer: &Subbuffer<[u32]>,
transform_buffer: &Subbuffer<[[[f32; 4]; 3]]>,
mesh_buffer: &Subbuffer<[enable_gen_cs::Mesh]>,
image_index: usize,
) -> Self {
// Build the bottom-level acceleration structure and then the top-level
@@ -50,12 +59,18 @@ impl Scene {
// structure.
let mesh_blases: Vec<Arc<AccelerationStructure>> = meshes
.iter()
.map(|mesh| unsafe {
.enumerate()
.map(|(i, mesh)| unsafe {
build_acceleration_structure_triangles(
mesh,
vertex_buffer.clone(),
index_buffer.clone(),
transform_buffer.clone(),
mesh_buffer.clone(),
memory_allocator.clone(),
device.clone(),
builder,
i,
)
})
.collect();
@@ -110,6 +125,49 @@ impl Scene {
}
}
pub(crate) fn upload_transform(position: &Position, transform_buffer: Subbuffer<[[[f32; 4]; 3]]>) {
let world = Mat4::from_translation(position.pos * 0.01)
* Mat4::from_euler(
EulerRot::XYZ,
position.rot.x.to_radians(),
position.rot.y.to_radians(),
position.rot.z.to_radians(),
)
* Mat4::from_scale(position.scale * 2.0);
gpu_upload(
[
world.row(0).to_array(),
world.row(1).to_array(),
world.row(2).to_array(),
],
transform_buffer.index(position.transform_offset),
);
}
fn upload_mesh_data(mesh: &Mesh, mesh_buffer: Subbuffer<[enable_gen_cs::Mesh]>, index: DeviceSize) {
let mesh = enable_gen_cs::Mesh {
vert_offset: (mesh.vert_offset as u32).into(),
index_offset: (mesh.index_offset as u32).into(),
colour_and_roughness: [
mesh.material.colour[0],
mesh.material.colour[1],
mesh.material.colour[2],
mesh.material.roughness,
],
metallic: mesh.material.metallic,
subsurface: mesh.material.subsurface,
specular: mesh.material.specular,
specular_tint: mesh.material.specular_tint,
sheen: mesh.material.sheen,
sheen_tint: mesh.material.sheen_tint,
clear_coat_gloss: mesh.material.clear_coat_gloss,
clear_coat: mesh.material.clear_coat,
};
gpu_upload(mesh, mesh_buffer.index(index));
}
/// A helper function to build a acceleration structure and wait for its
/// completion.
///
@@ -207,16 +265,31 @@ unsafe fn build_acceleration_structure_common(
unsafe fn build_acceleration_structure_triangles(
mesh: &Mesh,
vertex_buffer: Subbuffer<[OVertex]>,
index_buffer: Subbuffer<[u32]>,
transform_buffer: Subbuffer<[[[f32; 4]; 3]]>,
mesh_buffer: Subbuffer<[enable_gen_cs::Mesh]>,
memory_allocator: Arc<dyn MemoryAllocator>,
device: Arc<Device>,
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
index: usize,
) -> Arc<AccelerationStructure> {
let primitive_count = (mesh.indices.len() / 3) as u32;
upload_transform(&mesh.position, transform_buffer.clone());
upload_mesh_data(&mesh, mesh_buffer, index as _);
let primitive_count = (mesh.index_len / 3) as u32;
let as_geometry_triangles_data = AccelerationStructureGeometryTrianglesData {
max_vertex: mesh.vertices.len() as _,
vertex_data: Some(mesh.vertices.clone().into_bytes()),
max_vertex: mesh.vert_len as _,
vertex_data: Some(
vertex_buffer
.slice(mesh.vert_offset..(mesh.vert_offset + mesh.vert_len))
.into_bytes(),
),
vertex_stride: size_of::<OVertex>() as _,
index_data: Some(IndexBuffer::U32(mesh.indices.clone())),
index_data: Some(IndexBuffer::U32(
index_buffer.slice(mesh.index_offset..(mesh.index_offset + mesh.index_len)),
)),
transform_data: Some(transform_buffer.index(mesh.position.transform_offset)),
..AccelerationStructureGeometryTrianglesData::new(Format::R32G32B32A32_SFLOAT)
};
+51 -421
View File
@@ -1,12 +1,12 @@
use std::{
fs::File,
io::Write,
simd::{StdFloat, cmp::SimdPartialOrd},
simd::StdFloat,
sync::{Arc, Mutex, RwLock, mpmc, mpsc},
time::Instant,
};
use foldhash::{HashMap, HashMapExt, HashSet};
use foldhash::{HashMap, HashMapExt};
use glam::{EulerRot, Mat4, Vec3};
use log::info;
use rand::{Rng, SeedableRng, rngs::SmallRng};
@@ -14,39 +14,24 @@ use rspirv::{binary::Assemble, dr::Module};
use tape_load::interpreters;
use vulkano::{
buffer::{Subbuffer, allocator::SubbufferAllocator},
command_buffer::allocator::CommandBufferAllocator,
descriptor_set::{DescriptorSet, WriteDescriptorSet, allocator::DescriptorSetAllocator},
device::{Device, Queue},
device::Device,
pipeline::{
ComputePipeline, DynamicState, GraphicsPipeline, Pipeline, PipelineCreateFlags,
PipelineLayout, PipelineShaderStageCreateInfo,
cache::PipelineCache,
compute::ComputePipelineCreateInfo,
graphics::{
GraphicsPipelineCreateInfo,
color_blend::{ColorBlendAttachmentState, ColorBlendState},
depth_stencil::{DepthState, DepthStencilState},
input_assembly::InputAssemblyState,
multisample::MultisampleState,
rasterization::{CullMode, FrontFace, PolygonMode, RasterizationState},
vertex_input::{Vertex, VertexDefinition, VertexInputState},
},
ComputePipeline, Pipeline, PipelineLayout, PipelineShaderStageCreateInfo,
cache::PipelineCache, compute::ComputePipelineCreateInfo,
layout::PipelineDescriptorSetLayoutCreateInfo,
},
render_pass::{RenderPass, Subpass},
shader::{ShaderModule, ShaderModuleCreateInfo},
sync::GpuFuture,
};
use crate::{
DUMP_SPV_TO_FILE, IVertex, MAXIMUM_SUBDIVISION, MINUMUM_SUBDIVISION, get_spec_constants,
DUMP_SPV_TO_FILE, MAXIMUM_SUBDIVISION, MINUMUM_SUBDIVISION, enable_gen_cs, get_spec_constants,
gpu_upload,
gui::PreviousDebug,
interpreters::{VALUE_0, interval::IntervalInterpreter, point::PointInterpreter},
interpreters::point::PointInterpreter,
objects::CSG,
scene::upload_transform,
ssa::{SSAInput, SSAOpcode, SSAOpcodeSized, SSATape},
trace_vs::{Object, PushConstantData},
types::Interval,
};
#[derive(Debug)]
@@ -54,13 +39,9 @@ pub enum WorkItem {
CreateCSG(
Arc<Device>,
Arc<RwLock<HashMap<String, Module>>>,
Arc<RenderPass>,
Arc<PipelineCache>,
Arc<RwLock<HashMap<String, Arc<ShaderModule>>>>,
PreviousDebug,
Arc<Mutex<SubbufferAllocator>>,
Arc<Mutex<SubbufferAllocator>>,
Arc<Mutex<SubbufferAllocator>>,
Arc<dyn DescriptorSetAllocator>,
u32,
u32,
@@ -70,10 +51,8 @@ pub enum WorkItem {
GetPushConstants(
Arc<RwLock<CSG>>,
f32,
usize,
Arc<dyn CommandBufferAllocator>,
Arc<Queue>,
bool,
Subbuffer<[[[f32; 4]; 3]]>,
Subbuffer<[enable_gen_cs::Object]>,
usize,
),
RecompileShaders(
@@ -85,9 +64,7 @@ pub enum WorkItem {
RecompilePipelines(
Arc<RwLock<CSG>>,
Arc<Device>,
Arc<RenderPass>,
Arc<PipelineCache>,
Arc<RwLock<HashMap<String, Arc<ShaderModule>>>>,
PreviousDebug,
usize,
),
@@ -95,7 +72,7 @@ pub enum WorkItem {
pub enum WorkComplete {
CreateCSG(Arc<RwLock<CSG>>, isize),
GetPushConstants(PushConstantData, Box<dyn GpuFuture + Send + Sync>, usize),
GetPushConstants(usize),
RecompileShaders(usize),
RecompilePipelines(usize),
}
@@ -106,13 +83,9 @@ pub fn thread_loop(recv: mpmc::Receiver<WorkItem>, send: mpsc::SyncSender<WorkCo
WorkItem::CreateCSG(
device,
replacement_modules,
render_pass,
cache,
normal_modules,
debug,
block_enable_allocator,
aabb_allocator,
host_visible_allocator,
descriptor_set_allocator,
frames,
subdivision,
@@ -132,34 +105,8 @@ pub fn thread_loop(recv: mpmc::Receiver<WorkItem>, send: mpsc::SyncSender<WorkCo
let replacement_modules = Arc::new(RwLock::new(new_replacement_modules));
let (trace_pipeline, normals_pipeline, fuzz_pipeline, enable_gen_pipeline) =
deferred_pipelines_recompile(
device,
render_pass,
cache,
normal_modules,
replacement_modules.clone(),
debug,
);
let enable_buffer: Vec<Subbuffer<Object>> = (0..frames)
.map(|_| {
block_enable_allocator
.lock()
.unwrap()
.allocate_sized()
.unwrap()
})
.collect();
let enable_buffer_host_visible: Vec<Subbuffer<Object>> = (0..frames)
.map(|_| {
host_visible_allocator
.lock()
.unwrap()
.allocate_sized()
.unwrap()
})
.collect();
let (fuzz_pipeline, enable_gen_pipeline) =
deferred_pipelines_recompile(device, cache, replacement_modules.clone(), debug);
let aabb_buffer: Vec<Subbuffer<[u8]>> = (0..frames)
.map(|_| {
@@ -175,48 +122,16 @@ pub fn thread_loop(recv: mpmc::Receiver<WorkItem>, send: mpsc::SyncSender<WorkCo
})
.collect();
let trace_layout = trace_pipeline.layout().set_layouts()[1].clone();
let trace_descriptor_set = (0..frames)
.map(|f| {
DescriptorSet::new(
descriptor_set_allocator.clone(),
trace_layout.clone(),
[WriteDescriptorSet::buffer(
0,
enable_buffer[f as usize].clone(),
)],
[],
)
.unwrap()
})
.collect();
let normals_layout = normals_pipeline.layout().set_layouts()[1].clone();
let normals_descriptor_set = (0..frames)
.map(|f| {
DescriptorSet::new(
descriptor_set_allocator.clone(),
normals_layout.clone(),
[WriteDescriptorSet::buffer(
0,
enable_buffer[f as usize].clone(),
)],
[],
)
.unwrap()
})
.collect();
let enable_gen_layout = enable_gen_pipeline.layout().set_layouts()[1].clone();
let enable_gen_descriptor_set = (0..frames)
.map(|f| {
DescriptorSet::new(
descriptor_set_allocator.clone(),
enable_gen_layout.clone(),
[
WriteDescriptorSet::buffer(0, enable_buffer[f as usize].clone()),
WriteDescriptorSet::buffer(1, aabb_buffer[f as usize].clone()),
],
[WriteDescriptorSet::buffer(
0,
aabb_buffer[f as usize].clone(),
)],
[],
)
.unwrap()
@@ -227,24 +142,14 @@ pub fn thread_loop(recv: mpmc::Receiver<WorkItem>, send: mpsc::SyncSender<WorkCo
name: "example".to_string(),
_seed: seed,
parts,
pos: Vec3::ZERO,
rot: Vec3::ZERO,
scale: Vec3::ONE,
position: Default::default(),
material: Default::default(),
replacement_modules,
trace_pipeline,
normals_pipeline,
fuzz_pipeline,
enable_gen_pipeline,
subdivision,
enable_buffer,
aabb_buffer,
enable_buffer_host_visible,
trace_descriptor_set,
normals_descriptor_set,
enable_gen_descriptor_set,
colour: Vec3::ONE,
roughness: 1.0,
metallic: 0.67,
}));
send.send(WorkComplete::CreateCSG(csg, index)).unwrap();
@@ -255,47 +160,14 @@ pub fn thread_loop(recv: mpmc::Receiver<WorkItem>, send: mpsc::SyncSender<WorkCo
(csg_end - csg_start).as_secs_f64() * 1000.0
);
},
WorkItem::GetPushConstants(
csg,
time,
frame_index,
command_allocator,
transfer_queue,
use_cpu_enable_gen,
index,
) => {
WorkItem::GetPushConstants(csg, time, transform_buffer, csg_buffer, index) => {
let csg = csg.read().unwrap();
let world = Mat4::from_translation(csg.pos * 0.01)
* Mat4::from_euler(
EulerRot::XYZ,
csg.rot.x.to_radians(),
csg.rot.y.to_radians(),
csg.rot.z.to_radians(),
)
* Mat4::from_scale(csg.scale * 2.0);
upload_transform(&csg.position, transform_buffer);
let push_constants = PushConstantData {
world: world.to_cols_array_2d(),
inv_world: world.inverse().to_cols_array_2d(),
};
interval_check(&csg, time, csg_buffer, index);
let future = interval_check(
&csg,
index as u32 + 1,
time,
frame_index,
command_allocator,
transfer_queue,
use_cpu_enable_gen,
);
send.send(WorkComplete::GetPushConstants(
push_constants,
future,
index,
))
.unwrap();
send.send(WorkComplete::GetPushConstants(index)).unwrap();
},
WorkItem::RecompileShaders(csg, device, replacement_modules, index) => {
let csg_start = Instant::now();
@@ -319,27 +191,12 @@ pub fn thread_loop(recv: mpmc::Receiver<WorkItem>, send: mpsc::SyncSender<WorkCo
(csg_end - csg_start).as_secs_f64() * 1000.0
);
},
WorkItem::RecompilePipelines(
csg,
device,
render_pass,
cache,
normal_modules,
debug,
index,
) => {
WorkItem::RecompilePipelines(csg, device, cache, debug, index) => {
let csg_start = Instant::now();
let mut csg = csg.write().unwrap();
(
csg.trace_pipeline,
csg.normals_pipeline,
csg.fuzz_pipeline,
csg.enable_gen_pipeline,
) = deferred_pipelines_recompile(
(csg.fuzz_pipeline, csg.enable_gen_pipeline) = deferred_pipelines_recompile(
device,
render_pass,
cache,
normal_modules,
csg.replacement_modules.clone(),
debug,
);
@@ -359,144 +216,14 @@ pub fn thread_loop(recv: mpmc::Receiver<WorkItem>, send: mpsc::SyncSender<WorkCo
fn deferred_pipelines_recompile(
device: Arc<Device>,
render_pass: Arc<RenderPass>,
cache: Arc<PipelineCache>,
shader_modules: Arc<RwLock<HashMap<String, Arc<ShaderModule>>>>,
replacement_modules: Arc<RwLock<HashMap<String, Arc<ShaderModule>>>>,
debug: PreviousDebug,
) -> (
Arc<GraphicsPipeline>,
Arc<GraphicsPipeline>,
Arc<ComputePipeline>,
Arc<ComputePipeline>,
) {
) -> (Arc<ComputePipeline>, Arc<ComputePipeline>) {
let specs = get_spec_constants(&debug);
let dynamic_state = [DynamicState::Viewport].into_iter().collect::<HashSet<_>>();
let shader_modules = shader_modules.read().unwrap();
let replacement_modules = replacement_modules.read().unwrap();
let trace_vs_entry = shader_modules["trace.vert"]
.specialize(specs.clone())
.unwrap()
.single_entry_point()
.unwrap();
let vertex_input_state = [IVertex::per_vertex()].definition(&trace_vs_entry).unwrap();
let trace_vs_info = PipelineShaderStageCreateInfo::new(trace_vs_entry);
let trace_fs_info = PipelineShaderStageCreateInfo::new(
replacement_modules["trace.frag"]
.specialize(specs.clone())
.unwrap()
.single_entry_point()
.unwrap(),
);
let layout = PipelineLayout::new(
device.clone(),
PipelineDescriptorSetLayoutCreateInfo::from_stages([&trace_vs_info, &trace_fs_info])
.into_pipeline_layout_create_info(device.clone())
.unwrap(),
)
.unwrap();
let stages = [trace_vs_info.clone(), trace_fs_info].into_iter().collect();
let trace_subpass = Subpass::from(render_pass.clone(), 0).unwrap();
let trace_pipeline = GraphicsPipeline::new(
device.clone(),
Some(cache.clone()),
GraphicsPipelineCreateInfo {
flags: PipelineCreateFlags::DISABLE_OPTIMIZATION,
stages,
vertex_input_state: Some(vertex_input_state.clone()),
input_assembly_state: Some(InputAssemblyState::default()),
dynamic_state: dynamic_state.clone(),
viewport_state: Some(Default::default()),
rasterization_state: Some(RasterizationState {
front_face: FrontFace::Clockwise,
cull_mode: CullMode::Back,
polygon_mode: PolygonMode::Fill,
..RasterizationState::default()
}),
depth_stencil_state: Some(DepthStencilState {
depth: Some(DepthState::reverse()),
..Default::default()
}),
multisample_state: Some(MultisampleState::default()),
color_blend_state: Some(ColorBlendState::with_attachment_states(
trace_subpass.num_color_attachments(),
ColorBlendAttachmentState::default(),
)),
subpass: Some(trace_subpass.into()),
..GraphicsPipelineCreateInfo::layout(layout.clone())
},
)
.unwrap();
let fullscreen_vs_entry = shader_modules["fullscreen.vert"]
.specialize(specs.clone())
.unwrap()
.single_entry_point()
.unwrap();
let vertex_input_state = VertexInputState::new();
let fullscreen_vs_info = PipelineShaderStageCreateInfo::new(fullscreen_vs_entry);
let normals_fs_info = PipelineShaderStageCreateInfo::new(
replacement_modules["normals.frag"]
.specialize(specs.clone())
.unwrap()
.single_entry_point()
.unwrap(),
);
let layout = PipelineLayout::new(
device.clone(),
PipelineDescriptorSetLayoutCreateInfo::from_stages([&fullscreen_vs_info, &normals_fs_info])
.into_pipeline_layout_create_info(device.clone())
.unwrap(),
)
.unwrap();
let stages = [fullscreen_vs_info.clone(), normals_fs_info]
.into_iter()
.collect();
let normals_subpass = Subpass::from(render_pass.clone(), 1).unwrap();
let normals_pipeline = GraphicsPipeline::new(
device.clone(),
Some(cache.clone()),
GraphicsPipelineCreateInfo {
flags: PipelineCreateFlags::DISABLE_OPTIMIZATION,
stages,
vertex_input_state: Some(vertex_input_state.clone()),
input_assembly_state: Some(InputAssemblyState::default()),
dynamic_state: dynamic_state.clone(),
viewport_state: Some(Default::default()),
rasterization_state: Some(RasterizationState {
front_face: FrontFace::Clockwise,
cull_mode: CullMode::Back,
polygon_mode: PolygonMode::Fill,
..RasterizationState::default()
}),
depth_stencil_state: None,
multisample_state: Some(MultisampleState::default()),
color_blend_state: Some(ColorBlendState::with_attachment_states(
normals_subpass.num_color_attachments(),
ColorBlendAttachmentState::default(),
)),
subpass: Some(normals_subpass.into()),
..GraphicsPipelineCreateInfo::layout(layout.clone())
},
)
.unwrap();
let fuzz_cs_info = PipelineShaderStageCreateInfo::new(
replacement_modules["fuzz.comp"]
.specialize(specs.clone())
@@ -515,7 +242,7 @@ fn deferred_pipelines_recompile(
let fuzz_pipeline = ComputePipeline::new(
device.clone(),
None,
Some(cache.clone()),
ComputePipelineCreateInfo::stage_layout(fuzz_cs_info, fuzz_pipeline_layout.clone()),
)
.expect("failed to create fuzz pipeline");
@@ -538,7 +265,7 @@ fn deferred_pipelines_recompile(
let enable_gen_pipeline = ComputePipeline::new(
device.clone(),
None,
Some(cache.clone()),
ComputePipelineCreateInfo::stage_layout(
enable_gen_cs_info,
enable_gen_pipeline_layout.clone(),
@@ -546,12 +273,7 @@ fn deferred_pipelines_recompile(
)
.expect("failed to create enable_gen pipeline");
(
trace_pipeline,
normals_pipeline,
fuzz_pipeline,
enable_gen_pipeline,
)
(fuzz_pipeline, enable_gen_pipeline)
}
fn create_csg(seed: u64) -> SSATape {
@@ -720,13 +442,10 @@ fn create_csg(seed: u64) -> SSATape {
fn interval_check(
csg: &CSG,
material: u32,
time: f32,
frame_index: usize,
command_allocator: Arc<dyn CommandBufferAllocator>,
transfer_queue: Arc<Queue>,
use_cpu_enable_gen: bool,
) -> Box<dyn GpuFuture + Send + Sync> {
csg_buffer: Subbuffer<[enable_gen_cs::Object]>,
index: usize,
) {
const INTERPRET_INPUT_X: interpreters::Value =
interpreters::Value::from_array([10000.0, 0.0, 0.0, -10000.0, 0.0, 0.0, 0.0, 0.0]);
const INTERPRET_INPUT_Y: interpreters::Value =
@@ -762,116 +481,27 @@ fn interval_check(
assert!(csg.subdivision <= MAXIMUM_SUBDIVISION);
assert!(csg.subdivision >= MINUMUM_SUBDIVISION);
let xdim = csg.subdivision as usize;
let ydim = csg.subdivision as usize;
let zdim = csg.subdivision as usize;
let mut obj = Object {
dimensions: (highest_corner - lowest_corner).to_array().into(),
lowest_corner: lowest_corner.into(),
enable: [[0; 4];
(MAXIMUM_SUBDIVISION * MAXIMUM_SUBDIVISION * MAXIMUM_SUBDIVISION) as usize / (32 * 4)],
material,
subdivision_log2: csg.subdivision.ilog2(),
farplane: ((highest_corner - lowest_corner).length() / csg.subdivision as f32).into(),
colour: csg.colour.to_array(),
roughness: csg.roughness,
metallic: csg.metallic,
let obj = enable_gen_cs::Object {
dimensions: (highest_corner - lowest_corner).to_array().into(),
lowest_corner: lowest_corner.into(),
subdivision_log2: csg.subdivision.ilog2(),
colour_and_roughness: [
csg.material.colour[0],
csg.material.colour[1],
csg.material.colour[2],
csg.material.roughness,
],
metallic: csg.material.metallic,
subsurface: csg.material.subsurface,
specular: csg.material.specular,
specular_tint: csg.material.specular_tint,
sheen: csg.material.sheen,
sheen_tint: csg.material.sheen_tint,
clear_coat_gloss: csg.material.clear_coat_gloss,
clear_coat: csg.material.clear_coat,
};
if use_cpu_enable_gen {
for x in 0..xdim {
for y in 0..ydim {
for z in 0..(zdim / 8) {
let interval_input_z: Interval = Interval::new_unchecked(
interpreters::Value::from_array([
((((8.0 / (zdim as f32)) * z as f32) + (0.0 / (zdim as f32)))
* obj.dimensions[2])
+ obj.lowest_corner[2],
((((8.0 / (zdim as f32)) * z as f32) + (1.0 / (zdim as f32)))
* obj.dimensions[2])
+ obj.lowest_corner[2],
((((8.0 / (zdim as f32)) * z as f32) + (2.0 / (zdim as f32)))
* obj.dimensions[2])
+ obj.lowest_corner[2],
((((8.0 / (zdim as f32)) * z as f32) + (3.0 / (zdim as f32)))
* obj.dimensions[2])
+ obj.lowest_corner[2],
((((8.0 / (zdim as f32)) * z as f32) + (4.0 / (zdim as f32)))
* obj.dimensions[2])
+ obj.lowest_corner[2],
((((8.0 / (zdim as f32)) * z as f32) + (5.0 / (zdim as f32)))
* obj.dimensions[2])
+ obj.lowest_corner[2],
((((8.0 / (zdim as f32)) * z as f32) + (6.0 / (zdim as f32)))
* obj.dimensions[2])
+ obj.lowest_corner[2],
((((8.0 / (zdim as f32)) * z as f32) + (7.0 / (zdim as f32)))
* obj.dimensions[2])
+ obj.lowest_corner[2],
]),
interpreters::Value::from_array([
((((8.0 / (zdim as f32)) * z as f32) + (1.0 / (zdim as f32)))
* obj.dimensions[2])
+ obj.lowest_corner[2],
((((8.0 / (zdim as f32)) * z as f32) + (2.0 / (zdim as f32)))
* obj.dimensions[2])
+ obj.lowest_corner[2],
((((8.0 / (zdim as f32)) * z as f32) + (3.0 / (zdim as f32)))
* obj.dimensions[2])
+ obj.lowest_corner[2],
((((8.0 / (zdim as f32)) * z as f32) + (4.0 / (zdim as f32)))
* obj.dimensions[2])
+ obj.lowest_corner[2],
((((8.0 / (zdim as f32)) * z as f32) + (5.0 / (zdim as f32)))
* obj.dimensions[2])
+ obj.lowest_corner[2],
((((8.0 / (zdim as f32)) * z as f32) + (6.0 / (zdim as f32)))
* obj.dimensions[2])
+ obj.lowest_corner[2],
((((8.0 / (zdim as f32)) * z as f32) + (7.0 / (zdim as f32)))
* obj.dimensions[2])
+ obj.lowest_corner[2],
((((8.0 / (zdim as f32)) * z as f32) + (8.0 / (zdim as f32)))
* obj.dimensions[2])
+ obj.lowest_corner[2],
]),
);
let mut interpreter = IntervalInterpreter::new(&csg.parts);
let output = interpreter.scene(
Interval::const_splat2(
(x as f32 / (xdim as f32)) * obj.dimensions[0] + obj.lowest_corner[0],
((x + 1) as f32 / (xdim as f32)) * obj.dimensions[0]
+ obj.lowest_corner[0],
),
Interval::const_splat2(
(y as f32 / (ydim as f32)) * obj.dimensions[1] + obj.lowest_corner[1],
((y + 1) as f32 / (ydim as f32)) * obj.dimensions[1]
+ obj.lowest_corner[1],
),
interval_input_z,
Interval::const_splat(time),
);
let total_index = (x * zdim * ydim) + (y * zdim) + (z * 8);
let output = ((output.lower().simd_le(VALUE_0)
& output.upper().simd_ge(VALUE_0))
.to_bitmask() as u32)
<< (total_index & 31);
obj.enable[total_index >> 7][(total_index >> 5) & 3] |= output;
}
}
}
}
gpu_upload(
obj,
csg.enable_buffer[frame_index].clone(),
csg.enable_buffer_host_visible[frame_index].clone(),
command_allocator,
transfer_queue,
)
gpu_upload(obj, csg_buffer.index(index as _))
}
fn sdf_specialize_module(