first step for compute task
This commit is contained in:
parent
579820334d
commit
c02522b6c2
16 changed files with 470 additions and 32 deletions
12
build.rs
12
build.rs
|
@ -6,21 +6,15 @@ fn main() {
|
|||
println!("cargo::rerun-if-changed=shaders/cube.frag");
|
||||
println!("cargo::rerun-if-changed=shaders/cube.geom");
|
||||
println!("cargo::rerun-if-changed=shaders/cube.vert");
|
||||
println!("cargo::rerun-if-changed=shaders/compiled/geo_cube.spv");
|
||||
println!("cargo::rerun-if-changed=shaders/compiled/frag_cube.spv");
|
||||
println!("cargo::rerun-if-changed=shaders/compiled/vert_cube.spv");
|
||||
|
||||
println!("cargo::rerun-if-changed=shaders/cuboid.frag");
|
||||
println!("cargo::rerun-if-changed=shaders/cuboid.geom");
|
||||
println!("cargo::rerun-if-changed=shaders/cuboid.vert");
|
||||
println!("cargo::rerun-if-changed=shaders/compiled/geo_cuboid.spv");
|
||||
println!("cargo::rerun-if-changed=shaders/compiled/frag_cuboid.spv");
|
||||
println!("cargo::rerun-if-changed=shaders/compiled/vert_cuboid.spv");
|
||||
|
||||
println!("cargo::rerun-if-changed=shaders/rt_quad.vert");
|
||||
println!("cargo::rerun-if-changed=shaders/compiled/vert_rt_quad.spv");
|
||||
println!("cargo::rerun-if-changed=shaders/rt_quad.frag");
|
||||
println!("cargo::rerun-if-changed=shaders/compiled/frag_rt_quad.spv");
|
||||
|
||||
println!("cargo::rerun-if-changed=shaders/rt_compute.comp");
|
||||
|
||||
#[allow(unused_must_use)]
|
||||
std::fs::remove_file("shaders/compiled/geo_cube.spv");
|
||||
|
@ -38,6 +32,8 @@ fn main() {
|
|||
std::fs::remove_file("shaders/compiled/vert_rt_quad.spv");
|
||||
#[warn(unused_must_use)]
|
||||
std::fs::remove_file("shaders/compiled/frag_rt_quad.spv");
|
||||
#[warn(unused_must_use)]
|
||||
std::fs::remove_file("shaders/compiled/rt_compute.spv");
|
||||
|
||||
if std::env::consts::OS == "windows" {
|
||||
let mut command = Command::new("./shaders/compile.bat");
|
||||
|
|
|
@ -7,4 +7,6 @@ C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/cuboid.frag -o shaders/compiled/fra
|
|||
C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/cuboid.geom -o shaders/compiled/geo_cuboid.spv
|
||||
|
||||
C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/rt_quad.vert -o shaders/compiled/vert_rt_quad.spv
|
||||
C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/rt_quad.frag -o shaders/compiled/frag_rt_quad.spv
|
||||
C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/rt_quad.frag -o shaders/compiled/frag_rt_quad.spv
|
||||
|
||||
C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/rt_compute.comp -o shaders/compiled/rt_compute.spv
|
Binary file not shown.
BIN
shaders/compiled/rt_compute.spv
Normal file
BIN
shaders/compiled/rt_compute.spv
Normal file
Binary file not shown.
27
shaders/rt_compute.comp
Normal file
27
shaders/rt_compute.comp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#version 450
|
||||
|
||||
|
||||
layout(binding = 0) uniform UniformBufferObject {
|
||||
mat4 model;
|
||||
mat4 geom_rot;
|
||||
mat4 view;
|
||||
mat4 proj;
|
||||
vec3 camera_pos;
|
||||
bool[16] use_geom_shader;
|
||||
} ubo;
|
||||
|
||||
layout(binding = 3) readonly buffer SceneInfoBuffer {
|
||||
uint gridsIn[];
|
||||
};
|
||||
|
||||
layout(binding = 4) buffer SceneInfoBuffer2 {
|
||||
uint volumes[];
|
||||
};
|
||||
|
||||
layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
void main() {
|
||||
uint index = gl_GlobalInvocationID.x;
|
||||
|
||||
volumes[index] = gridsIn[index];
|
||||
}
|
|
@ -24,9 +24,13 @@ layout(binding = 0) uniform UniformBufferObject {
|
|||
// 3 - diffuse raster size (float, needs to be decoded)
|
||||
// 4 - max recursive rays
|
||||
// 5 - diffuse rays per hit
|
||||
layout(binding = 2) buffer SceneInfoBuffer{
|
||||
layout(binding = 2) readonly buffer SceneInfoBuffer{
|
||||
uint infos[];
|
||||
} scene_info;
|
||||
|
||||
layout(binding = 4) buffer SceneInfoBuffer2 {
|
||||
uint infos[];
|
||||
} scene_info2;
|
||||
uint max_num_lights = scene_info.infos[0];
|
||||
uint max_iterations_per_light = scene_info.infos[1];
|
||||
// diffuse raytracing using a quadratic raster of rays
|
||||
|
|
|
@ -22,6 +22,9 @@ pub struct AppData {
|
|||
pub pipeline_cube: vk::Pipeline,
|
||||
pub pipeline_cuboid: vk::Pipeline,
|
||||
pub pipeline_quad: vk::Pipeline,
|
||||
|
||||
pub pipeline_compute: vk::Pipeline,
|
||||
|
||||
pub framebuffers: Vec<vk::Framebuffer>,
|
||||
pub command_pool: vk::CommandPool,
|
||||
pub command_buffers: Vec<vk::CommandBuffer>,
|
||||
|
@ -35,8 +38,14 @@ pub struct AppData {
|
|||
pub uniform_buffers: Vec<vk::Buffer>,
|
||||
pub uniform_buffers_memory: Vec<vk::DeviceMemory>,
|
||||
|
||||
pub storage_buffers: Vec<vk::Buffer>,
|
||||
pub storage_buffers_memory: Vec<vk::DeviceMemory>,
|
||||
pub render_storage_buffers: Vec<vk::Buffer>,
|
||||
pub render_storage_buffers_memory: Vec<vk::DeviceMemory>,
|
||||
|
||||
pub compute_in_storage_buffers: Vec<vk::Buffer>,
|
||||
pub compute_in_storage_buffers_memory: Vec<vk::DeviceMemory>,
|
||||
|
||||
pub compute_out_storage_buffers: Vec<vk::Buffer>,
|
||||
pub compute_out_storage_buffers_memory: Vec<vk::DeviceMemory>,
|
||||
|
||||
pub descriptor_pool: vk::DescriptorPool,
|
||||
pub descriptor_sets: Vec<vk::DescriptorSet>,
|
||||
|
@ -60,6 +69,8 @@ pub struct AppData {
|
|||
pub topology: vk::PrimitiveTopology,
|
||||
|
||||
pub scene_rt_memory_size: u64,
|
||||
pub scene_rt_volumetric_size: u64,
|
||||
pub compute_task_one_size: usize,
|
||||
// values passed to shader
|
||||
pub num_lights_per_volume: u32,
|
||||
pub min_light_weight: f32,
|
||||
|
|
130
src/buffer.rs
130
src/buffer.rs
|
@ -200,13 +200,25 @@ pub unsafe fn create_descriptor_set_layout(
|
|||
.descriptor_count(1)
|
||||
.stage_flags(vk::ShaderStageFlags::FRAGMENT);
|
||||
|
||||
let storage_binding = vk::DescriptorSetLayoutBinding::builder()
|
||||
let storage_binding_render = vk::DescriptorSetLayoutBinding::builder()
|
||||
.binding(2)
|
||||
.descriptor_type(vk::DescriptorType::STORAGE_BUFFER)
|
||||
.descriptor_count(1)
|
||||
.stage_flags(vk::ShaderStageFlags::FRAGMENT);
|
||||
|
||||
let storage_binding_compute_in = vk::DescriptorSetLayoutBinding::builder()
|
||||
.binding(3)
|
||||
.descriptor_type(vk::DescriptorType::STORAGE_BUFFER)
|
||||
.descriptor_count(1)
|
||||
.stage_flags(vk::ShaderStageFlags::COMPUTE);
|
||||
|
||||
let bindings = &[ubo_binding, sampler_binding, storage_binding];
|
||||
let storage_binding_compute_out = vk::DescriptorSetLayoutBinding::builder()
|
||||
.binding(4)
|
||||
.descriptor_type(vk::DescriptorType::STORAGE_BUFFER)
|
||||
.descriptor_count(1)
|
||||
.stage_flags(vk::ShaderStageFlags::FRAGMENT | vk::ShaderStageFlags::COMPUTE);
|
||||
|
||||
let bindings = &[ubo_binding, sampler_binding, storage_binding_render, storage_binding_compute_in, storage_binding_compute_out];
|
||||
let info = vk::DescriptorSetLayoutCreateInfo::builder()
|
||||
.bindings(bindings);
|
||||
|
||||
|
@ -245,8 +257,13 @@ pub unsafe fn create_storage_buffers(
|
|||
device: &Device,
|
||||
data: &mut app_data::AppData,
|
||||
) -> Result<()> {
|
||||
data.storage_buffers.clear();
|
||||
data.storage_buffers_memory.clear();
|
||||
data.render_storage_buffers.clear();
|
||||
data.render_storage_buffers_memory.clear();
|
||||
|
||||
data.compute_in_storage_buffers.clear();
|
||||
data.compute_in_storage_buffers_memory.clear();
|
||||
data.compute_out_storage_buffers.clear();
|
||||
data.compute_out_storage_buffers_memory.clear();
|
||||
|
||||
for _ in 0..data.swapchain_images.len() {
|
||||
let (storage_buffer, storage_buffer_memory) = create_buffer(
|
||||
|
@ -257,21 +274,45 @@ pub unsafe fn create_storage_buffers(
|
|||
vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::STORAGE_BUFFER,
|
||||
vk::MemoryPropertyFlags::DEVICE_LOCAL,
|
||||
)?;
|
||||
data.render_storage_buffers.push(storage_buffer);
|
||||
data.render_storage_buffers_memory.push(storage_buffer_memory);
|
||||
|
||||
data.storage_buffers.push(storage_buffer);
|
||||
data.storage_buffers_memory.push(storage_buffer_memory);
|
||||
let (storage_buffer, storage_buffer_memory) = create_buffer(
|
||||
instance,
|
||||
device,
|
||||
data,
|
||||
data.scene_rt_volumetric_size.max(1),
|
||||
vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::STORAGE_BUFFER,
|
||||
vk::MemoryPropertyFlags::DEVICE_LOCAL,
|
||||
)?;
|
||||
|
||||
data.compute_in_storage_buffers.push(storage_buffer);
|
||||
data.compute_in_storage_buffers_memory.push(storage_buffer_memory);
|
||||
|
||||
let (storage_buffer, storage_buffer_memory) = create_buffer(
|
||||
instance,
|
||||
device,
|
||||
data,
|
||||
data.scene_rt_memory_size.max(1),
|
||||
vk::BufferUsageFlags::TRANSFER_DST | vk::BufferUsageFlags::STORAGE_BUFFER,
|
||||
vk::MemoryPropertyFlags::DEVICE_LOCAL,
|
||||
)?;
|
||||
|
||||
data.compute_out_storage_buffers.push(storage_buffer);
|
||||
data.compute_out_storage_buffers_memory.push(storage_buffer_memory);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub unsafe fn update_storage_buffer(
|
||||
pub unsafe fn update_render_storage_buffer(
|
||||
instance: &Instance,
|
||||
device: &Device,
|
||||
data: &app_data::AppData,
|
||||
image_index: usize,
|
||||
scene_handler: &scene::Scene,
|
||||
) -> Result<()> {
|
||||
// rt scene buffer
|
||||
let (staging_buffer, staging_buffer_memory) = create_buffer(
|
||||
instance,
|
||||
device,
|
||||
|
@ -292,11 +333,38 @@ pub unsafe fn update_storage_buffer(
|
|||
|
||||
device.unmap_memory(staging_buffer_memory);
|
||||
|
||||
copy_buffer(device, data, staging_buffer, data.storage_buffers[image_index], data.scene_rt_memory_size)?;
|
||||
copy_buffer(device, data, staging_buffer, data.render_storage_buffers[image_index], data.scene_rt_memory_size)?;
|
||||
|
||||
device.destroy_buffer(staging_buffer, None);
|
||||
device.free_memory(staging_buffer_memory, None);
|
||||
|
||||
// rt compute buffer
|
||||
if scene_handler.volumetrics.len() > 0 {
|
||||
let (staging_buffer, staging_buffer_memory) = create_buffer(
|
||||
instance,
|
||||
device,
|
||||
data,
|
||||
data.scene_rt_volumetric_size,
|
||||
vk::BufferUsageFlags::TRANSFER_SRC,
|
||||
vk::MemoryPropertyFlags::HOST_COHERENT | vk::MemoryPropertyFlags::HOST_VISIBLE,
|
||||
)?;
|
||||
|
||||
let memory = device.map_memory(
|
||||
staging_buffer_memory,
|
||||
0,
|
||||
data.scene_rt_volumetric_size,
|
||||
vk::MemoryMapFlags::empty(),
|
||||
)?;
|
||||
|
||||
memcpy(scene_handler.volumetrics_memory.as_ptr(), memory.cast(), scene_handler.volumetrics_memory.len());
|
||||
|
||||
device.unmap_memory(staging_buffer_memory);
|
||||
|
||||
copy_buffer(device, data, staging_buffer, data.compute_in_storage_buffers[image_index], data.scene_rt_volumetric_size)?;
|
||||
|
||||
device.destroy_buffer(staging_buffer, None);
|
||||
device.free_memory(staging_buffer_memory, None);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -309,11 +377,19 @@ pub unsafe fn create_descriptor_pool(device: &Device, data: &mut app_data::AppDa
|
|||
.type_(vk::DescriptorType::COMBINED_IMAGE_SAMPLER)
|
||||
.descriptor_count(data.swapchain_images.len() as u32);
|
||||
|
||||
let storage_size = vk::DescriptorPoolSize::builder()
|
||||
let render_storage_size = vk::DescriptorPoolSize::builder()
|
||||
.type_(vk::DescriptorType::STORAGE_BUFFER)
|
||||
.descriptor_count(data.swapchain_images.len() as u32);
|
||||
|
||||
let compute_in_storage_size = vk::DescriptorPoolSize::builder()
|
||||
.type_(vk::DescriptorType::STORAGE_BUFFER)
|
||||
.descriptor_count(data.swapchain_images.len() as u32);
|
||||
|
||||
let compute_out_storage_size = vk::DescriptorPoolSize::builder()
|
||||
.type_(vk::DescriptorType::STORAGE_BUFFER)
|
||||
.descriptor_count(data.swapchain_images.len() as u32);
|
||||
|
||||
let pool_sizes = &[ubo_size, sampler_size, storage_size];
|
||||
let pool_sizes = &[ubo_size, sampler_size, render_storage_size, compute_in_storage_size, compute_out_storage_size];
|
||||
let info = vk::DescriptorPoolCreateInfo::builder()
|
||||
.pool_sizes(pool_sizes)
|
||||
.max_sets(data.swapchain_images.len() as u32);
|
||||
|
@ -357,20 +433,48 @@ pub unsafe fn create_descriptor_sets(device: &Device, data: &mut app_data::AppDa
|
|||
.image_info(image_info);
|
||||
|
||||
let info = vk::DescriptorBufferInfo::builder()
|
||||
.buffer(data.storage_buffers[i])
|
||||
.buffer(data.render_storage_buffers[i])
|
||||
.offset(0)
|
||||
.range(data.scene_rt_memory_size);
|
||||
let storage_info = &[info];
|
||||
|
||||
let storage_write = vk::WriteDescriptorSet::builder()
|
||||
let storage_write_render = vk::WriteDescriptorSet::builder()
|
||||
.dst_set(data.descriptor_sets[i])
|
||||
.dst_binding(2)
|
||||
.dst_array_element(0)
|
||||
.descriptor_type(vk::DescriptorType::STORAGE_BUFFER)
|
||||
.buffer_info(storage_info);
|
||||
|
||||
|
||||
let info = vk::DescriptorBufferInfo::builder()
|
||||
.buffer(data.compute_in_storage_buffers[i])
|
||||
.offset(0)
|
||||
.range(data.scene_rt_volumetric_size.max(1));
|
||||
let storage_info = &[info];
|
||||
|
||||
let storage_write_compute_in = vk::WriteDescriptorSet::builder()
|
||||
.dst_set(data.descriptor_sets[i])
|
||||
.dst_binding(3)
|
||||
.dst_array_element(0)
|
||||
.descriptor_type(vk::DescriptorType::STORAGE_BUFFER)
|
||||
.buffer_info(storage_info);
|
||||
|
||||
let info = vk::DescriptorBufferInfo::builder()
|
||||
.buffer(data.compute_out_storage_buffers[i])
|
||||
.offset(0)
|
||||
.range(data.scene_rt_memory_size);
|
||||
let storage_info = &[info];
|
||||
|
||||
let storage_write_compute_out = vk::WriteDescriptorSet::builder()
|
||||
.dst_set(data.descriptor_sets[i])
|
||||
.dst_binding(4)
|
||||
.dst_array_element(0)
|
||||
.descriptor_type(vk::DescriptorType::STORAGE_BUFFER)
|
||||
.buffer_info(storage_info);
|
||||
|
||||
|
||||
device.update_descriptor_sets(
|
||||
&[ubo_write, sampler_write, storage_write],
|
||||
&[ubo_write, sampler_write, storage_write_render, storage_write_compute_in, storage_write_compute_out],
|
||||
&[] as &[vk::CopyDescriptorSet],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -57,6 +57,22 @@ pub unsafe fn create_command_buffers(device: &Device, data: &mut app_data::AppDa
|
|||
},
|
||||
};
|
||||
|
||||
// define the compute load before going into the render pass
|
||||
if scene_handler.volumetrics.len() != 0 {
|
||||
device.cmd_bind_pipeline(
|
||||
*command_buffer, vk::PipelineBindPoint::COMPUTE, data.pipeline_compute); //todo build own pipeline
|
||||
|
||||
device.cmd_bind_descriptor_sets(
|
||||
*command_buffer,
|
||||
vk::PipelineBindPoint::COMPUTE,
|
||||
data.pipeline_layout,
|
||||
0,
|
||||
&[data.descriptor_sets[i]],
|
||||
&[]);
|
||||
|
||||
device.cmd_dispatch(*command_buffer, (data.compute_task_one_size as f64 / 256.0).ceil() as u32, 1, 1);
|
||||
}
|
||||
// start render pass
|
||||
let clear_values = &[color_clear_value, depth_clear_value];
|
||||
let info = vk::RenderPassBeginInfo::builder()
|
||||
.render_pass(data.render_pass)
|
||||
|
|
46
src/main.rs
46
src/main.rs
|
@ -280,14 +280,14 @@ impl App {
|
|||
|
||||
self.update_uniform_buffer(image_index)?;
|
||||
let time = self.appstart.elapsed().as_secs_f32() / 1.0;
|
||||
self.scene_handler.point_lights[0].borrow_mut().set_pos(cgmath::vec3((10.0 + 64.0) as f32 + time.sin(), (10.0 + 64.0) as f32 + time.cos(), 11.0));
|
||||
self.scene_handler.point_lights[0].borrow_mut().set_pos(cgmath::vec3((10.0 + 64.0) as f32 + time.sin() * 2.0, (10.0 + 64.0) as f32 + time.cos() * 2.0, 11.0));
|
||||
self.synchronized = 0;
|
||||
|
||||
if self.synchronized < MAX_FRAMES_IN_FLIGHT {
|
||||
if self.scene_handler.is_dirty() {
|
||||
self.scene_handler.update_memory(&mut self.data, true)
|
||||
}
|
||||
buffer::update_storage_buffer(&self.instance, &self.device, &self.data, image_index, &self.scene_handler)?;
|
||||
buffer::update_render_storage_buffer(&self.instance, &self.device, &self.data, image_index, &self.scene_handler)?;
|
||||
self.synchronized += 1
|
||||
}
|
||||
|
||||
|
@ -404,10 +404,24 @@ impl App {
|
|||
self.data.uniform_buffers_memory
|
||||
.iter()
|
||||
.for_each(|m| self.device.free_memory(*m, None));
|
||||
self.data.storage_buffers
|
||||
self.data.render_storage_buffers
|
||||
.iter()
|
||||
.for_each(|b| self.device.destroy_buffer(*b, None));
|
||||
self.data.storage_buffers_memory
|
||||
self.data.render_storage_buffers_memory
|
||||
.iter()
|
||||
.for_each(|m| self.device.free_memory(*m, None));
|
||||
|
||||
self.data.compute_in_storage_buffers
|
||||
.iter()
|
||||
.for_each(|b| self.device.destroy_buffer(*b, None));
|
||||
self.data.compute_in_storage_buffers_memory
|
||||
.iter()
|
||||
.for_each(|m| self.device.free_memory(*m, None));
|
||||
|
||||
self.data.compute_out_storage_buffers
|
||||
.iter()
|
||||
.for_each(|b| self.device.destroy_buffer(*b, None));
|
||||
self.data.compute_out_storage_buffers_memory
|
||||
.iter()
|
||||
.for_each(|m| self.device.free_memory(*m, None));
|
||||
|
||||
|
@ -418,6 +432,9 @@ impl App {
|
|||
self.device.destroy_pipeline(self.data.pipeline_cube, None);
|
||||
self.device.destroy_pipeline(self.data.pipeline_cuboid, None);
|
||||
self.device.destroy_pipeline(self.data.pipeline_quad, None);
|
||||
|
||||
self.device.destroy_pipeline(self.data.pipeline_compute, None);
|
||||
|
||||
self.device.destroy_pipeline_layout(self.data.pipeline_layout, None);
|
||||
self.device.destroy_render_pass(self.data.render_pass, None);
|
||||
self.data.swapchain_image_views
|
||||
|
@ -796,6 +813,17 @@ unsafe fn create_pipeline(device: &Device, data: &mut app_data::AppData) -> Resu
|
|||
let vertex_input_state_quad = vk::PipelineVertexInputStateCreateInfo::builder()
|
||||
.vertex_binding_descriptions(binding_descriptions_quad)
|
||||
.vertex_attribute_descriptions(&attribute_descriptions_quad);
|
||||
|
||||
// set up compute shader
|
||||
// load the byte data
|
||||
let compute_bytes = include_bytes!("../shaders/compiled/rt_compute.spv");
|
||||
// create the shaders
|
||||
let compute_shader_module = create_shader_module(device, &compute_bytes[..])?;
|
||||
//create the shader stage for the compute shader
|
||||
let compute_stage = vk::PipelineShaderStageCreateInfo::builder()
|
||||
.stage(vk::ShaderStageFlags::COMPUTE)
|
||||
.module(compute_shader_module)
|
||||
.name(b"main\0");
|
||||
|
||||
// define input assembly and object type. This is altered when using geometry shader
|
||||
let mut topology = vk::PrimitiveTopology::TRIANGLE_LIST;
|
||||
|
@ -937,10 +965,18 @@ unsafe fn create_pipeline(device: &Device, data: &mut app_data::AppData) -> Resu
|
|||
// create the pipeline
|
||||
let pipelines = device.create_graphics_pipelines(vk::PipelineCache::null(), &[info_cube, info_cuboid, info_quad], None)?.0;
|
||||
|
||||
let info_compute = vk::ComputePipelineCreateInfo::builder()
|
||||
.stage(compute_stage)
|
||||
.layout(data.pipeline_layout);
|
||||
|
||||
let compute_pipelines = device.create_compute_pipelines(vk::PipelineCache::null(), &[info_compute], None)?.0;
|
||||
|
||||
data.pipeline_cube = pipelines[0];
|
||||
data.pipeline_cuboid = pipelines[1];
|
||||
data.pipeline_quad = pipelines[2];
|
||||
|
||||
data.pipeline_compute = compute_pipelines[0];
|
||||
|
||||
device.destroy_shader_module(vert_shader_module_cube, None);
|
||||
device.destroy_shader_module(geo_shader_module_cube, None);
|
||||
device.destroy_shader_module(frag_shader_module_cube, None);
|
||||
|
@ -952,6 +988,8 @@ unsafe fn create_pipeline(device: &Device, data: &mut app_data::AppData) -> Resu
|
|||
device.destroy_shader_module(vert_shader_module_quad, None);
|
||||
device.destroy_shader_module(frag_shader_module_quad, None);
|
||||
|
||||
device.destroy_shader_module(compute_shader_module, None);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use vulkanalia::prelude::v1_0::*;
|
||||
use cgmath::{vec3, ElementWise, Vector2};
|
||||
use cgmath::{vec3, ElementWise};
|
||||
use crate::vertex::{self, Facing};
|
||||
use crate::scene::Scene;
|
||||
use crate::primitives::drawable::Drawable;
|
||||
|
|
|
@ -25,7 +25,7 @@ impl QueueFamilyIndices {
|
|||
|
||||
let graphics = properties
|
||||
.iter()
|
||||
.position(|p| p.queue_flags.contains(vk::QueueFlags::GRAPHICS))
|
||||
.position(|p| p.queue_flags.contains(vk::QueueFlags::GRAPHICS) && p.queue_flags.contains(vk::QueueFlags::COMPUTE))
|
||||
.map(|i| i as u32);
|
||||
|
||||
let mut present = None;
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::primitives::cube::Cube;
|
|||
use crate::primitives::rec_cuboid::Cuboid;
|
||||
use crate::primitives::drawable::Drawable;
|
||||
use crate::app_data::AppData;
|
||||
use super::volumetrics::{ShapeComposition, Sphere};
|
||||
|
||||
extern crate rand;
|
||||
use rand::Rng;
|
||||
|
@ -117,6 +118,10 @@ pub fn generate_test_scene(scene: &mut Scene, data: &mut AppData) -> Result<(Poi
|
|||
let tree_ref_two = Rc::new(RefCell::new(oct_tree2.clone()));
|
||||
scene.oct_trees = vec![vec![vec![tree_ref_two.clone(), tree_ref_two.clone(), tree_ref_two.clone()], vec![tree_ref_two.clone(), tree_ref_one.clone(), tree_ref_two.clone()], vec![tree_ref_two.clone(), tree_ref_two.clone(), tree_ref_two.clone()]], vec![vec![tree_ref_two.clone(), tree_ref_two.clone(), tree_ref_two.clone()], vec![tree_ref_two.clone(), tree_ref_one.clone(), tree_ref_two.clone()], vec![tree_ref_two.clone(), tree_ref_two.clone(), tree_ref_two.clone()]]];
|
||||
|
||||
let mut comp = ShapeComposition::new(64);
|
||||
comp.included_shapes.push(Rc::new(RefCell::new(Sphere::new(Vector3 { x: 5.0 + grid_size as f32, y: 5.0 + grid_size as f32, z: 10.0 }, Vector3 { x: 0.0, y: 0.0, z: 0.0 }, 2.5, Vector3 { x: 255, y: 0, z: 0 }, 64))));
|
||||
scene.volumetrics.push(Rc::new(RefCell::new(comp)));
|
||||
|
||||
Ok((cgmath::point3(5.0, 5.0, 10.0)))
|
||||
}
|
||||
|
||||
|
|
|
@ -9,4 +9,8 @@ pub trait Memorizable: core::fmt::Debug {
|
|||
fn insert_into_memory(&mut self, v: Vec<u32>, data: &AppData, scene: &Scene) -> Vec<u32>;
|
||||
fn get_memory_start(&self) -> usize;
|
||||
fn set_memory_start(&mut self, memory_start: usize);
|
||||
}
|
||||
|
||||
pub trait CompoundMemorizable: Memorizable {
|
||||
fn get_compound_buffer_mem_size(&self, data: &AppData) -> u32;
|
||||
}
|
|
@ -3,6 +3,7 @@ mod empty_volume;
|
|||
mod light;
|
||||
mod memorizable;
|
||||
pub mod generators;
|
||||
pub mod volumetrics;
|
||||
|
||||
use anyhow::Ok;
|
||||
use light::{DirectionalLight, LightSource, PointLight};
|
||||
|
@ -14,7 +15,7 @@ use cgmath::{vec2, vec3, Vector3};
|
|||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::scene::memorizable::Memorizable;
|
||||
use crate::scene::memorizable::{Memorizable, CompoundMemorizable};
|
||||
use crate::app_data::AppData;
|
||||
use crate::buffer;
|
||||
use crate::primitives::rec_cuboid::Cuboid;
|
||||
|
@ -63,6 +64,10 @@ pub struct Scene {
|
|||
pub directional_lights: Vec<Rc<RefCell<DirectionalLight>>>,
|
||||
|
||||
pub memorizables: Vec<Rc<RefCell<dyn Memorizable>>>,
|
||||
|
||||
pub volumetrics: Vec<Rc<RefCell<volumetrics::ShapeComposition>>>,
|
||||
|
||||
pub volumetrics_memory: Vec<u32>,
|
||||
}
|
||||
|
||||
impl Scene {
|
||||
|
@ -212,6 +217,24 @@ impl Scene {
|
|||
|
||||
self.rt_memory = volume_vec;
|
||||
data.scene_rt_memory_size = (self.rt_memory.len() * 4) as u64; // size of the needed buffer size in bytes
|
||||
|
||||
let mut data_len = 0;
|
||||
for compound in &self.volumetrics {
|
||||
compound.borrow_mut().set_memory_start(data_len);
|
||||
data_len += compound.borrow().get_compound_buffer_mem_size(data) as usize;
|
||||
}
|
||||
let mut volumetrics_memory = vec![0; data_len];
|
||||
|
||||
let mut compute_task_one_size = 0;
|
||||
for compound in &self.volumetrics {
|
||||
volumetrics_memory = compound.borrow_mut().insert_into_memory(volumetrics_memory, data, &self);
|
||||
compute_task_one_size += compound.borrow().size.pow(2) as usize;
|
||||
}
|
||||
|
||||
self.volumetrics_memory = volumetrics_memory;
|
||||
data.scene_rt_volumetric_size = (self.volumetrics_memory.len() * 4) as u64; // size of the needed buffer size in bytes
|
||||
data.compute_task_one_size = compute_task_one_size;
|
||||
|
||||
}
|
||||
|
||||
pub unsafe fn destroy(&mut self, device: &vulkanalia::Device) {
|
||||
|
|
208
src/scene/volumetrics/mod.rs
Normal file
208
src/scene/volumetrics/mod.rs
Normal file
|
@ -0,0 +1,208 @@
|
|||
use crate::app_data::AppData;
|
||||
|
||||
use super::{memorizable::Memorizable, Scene, memorizable::CompoundMemorizable};
|
||||
use cgmath::Vector3;
|
||||
use winit::dpi::Size;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub trait Volumetrics: Memorizable {
|
||||
fn get_pos(&self) -> Vector3<f32>;
|
||||
fn set_pos(&mut self, p: Vector3<f32>);
|
||||
|
||||
fn get_rot(&self) -> Vector3<f32>;
|
||||
fn set_rot(&mut self, p: Vector3<f32>);
|
||||
|
||||
fn get_bbox(&self) -> (Vector3<f32>,Vector3<f32>);
|
||||
}
|
||||
|
||||
enum ShapeTypes {
|
||||
SPHERE,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ShapeComposition {
|
||||
memory_start: usize,
|
||||
prev_memory_size: u32,
|
||||
pub size: u32,
|
||||
pub included_shapes: Vec<Rc<RefCell<dyn Volumetrics>>>,
|
||||
pub excluded_shapes: Vec<Rc<RefCell<dyn Volumetrics>>>,
|
||||
dirty: bool,
|
||||
}
|
||||
|
||||
impl ShapeComposition {
|
||||
pub fn new(size: u32) -> Self {
|
||||
Self { memory_start: 0, prev_memory_size: 0, size: size, included_shapes: vec![], excluded_shapes: vec![], dirty: true }
|
||||
}
|
||||
}
|
||||
|
||||
impl CompoundMemorizable for ShapeComposition {
|
||||
fn get_compound_buffer_mem_size(&self, data: &AppData) -> u32 {
|
||||
let mut size = self.get_buffer_mem_size(data);
|
||||
for volumetric in &self.included_shapes {
|
||||
size += volumetric.borrow().get_buffer_mem_size(data);
|
||||
}
|
||||
for volumetric in &self.excluded_shapes {
|
||||
size += volumetric.borrow().get_buffer_mem_size(data);
|
||||
}
|
||||
|
||||
size
|
||||
}
|
||||
}
|
||||
|
||||
impl Memorizable for ShapeComposition {
|
||||
fn get_buffer_mem_size(&self, data: &AppData) -> u32 {
|
||||
//size, scale, memory_end, num_included, num_excluded, pos, included_address, excluded_address
|
||||
1 + 1 + 1 + 1 + 1 + 3 + self.included_shapes.len() as u32 + self.excluded_shapes.len() as u32
|
||||
}
|
||||
|
||||
fn get_prev_buffer_mem_size(&self) -> u32 {
|
||||
self.prev_memory_size
|
||||
}
|
||||
|
||||
fn is_dirty(&self) -> bool {
|
||||
self.dirty
|
||||
}
|
||||
|
||||
fn insert_into_memory(&mut self, mut v: Vec<u32>, data: &AppData, scene: &Scene) -> Vec<u32> {
|
||||
v[self.memory_start] = self.size;
|
||||
|
||||
let mut shapes_memory = 0;
|
||||
let shapes_index = self.memory_start + self.get_buffer_mem_size(data) as usize;
|
||||
let mut bbox_low = Vector3 {x: f32::INFINITY, y: f32::INFINITY, z: f32::INFINITY};
|
||||
let mut bbox_high = Vector3 {x: f32::NEG_INFINITY, y: f32::NEG_INFINITY, z: f32::NEG_INFINITY};
|
||||
|
||||
let mut element_offset = 8;
|
||||
for volumetric in &self.included_shapes {
|
||||
// create bbox for scale calculation. Only the included elements matter for the scale, as exclusion does not need to be fully included in the grid
|
||||
let (l, h) = volumetric.borrow().get_bbox();
|
||||
bbox_low = Vector3 {x: bbox_low.x.min(l.x), y: bbox_low.y.min(l.y), z: bbox_low.z.min(l.z)};
|
||||
bbox_high = Vector3 {x: bbox_high.x.max(h.x), y: bbox_high.y.max(h.y), z: bbox_high.z.max(h.z)};
|
||||
|
||||
volumetric.borrow_mut().set_memory_start(shapes_index + shapes_memory);
|
||||
shapes_memory += volumetric.borrow().get_buffer_mem_size(data) as usize;
|
||||
|
||||
// write the volumetric to memory
|
||||
v = volumetric.borrow_mut().insert_into_memory(v, data, scene);
|
||||
// add the reference
|
||||
v[self.memory_start + element_offset] = volumetric.borrow().get_memory_start() as u32;
|
||||
element_offset += 1;
|
||||
}
|
||||
|
||||
for volumetric in &self.excluded_shapes {
|
||||
volumetric.borrow_mut().set_memory_start(shapes_index + shapes_memory);
|
||||
shapes_memory += volumetric.borrow().get_buffer_mem_size(data) as usize;
|
||||
|
||||
// write the volumetric to memory
|
||||
v = volumetric.borrow_mut().insert_into_memory(v, data, scene);
|
||||
// add the reference
|
||||
v[self.memory_start + element_offset] = volumetric.borrow().get_memory_start() as u32;
|
||||
element_offset += 1;
|
||||
}
|
||||
|
||||
v[self.memory_start + 1] = u32::from_ne_bytes((bbox_high.x.max(bbox_high.y.max(bbox_high.z)) - bbox_low.x.min(bbox_low.y.min(bbox_low.z)) / (self.size as f32)).to_ne_bytes());
|
||||
v[self.memory_start + 2] = (shapes_index + shapes_memory) as u32;
|
||||
v[self.memory_start + 3] = self.included_shapes.len() as u32;
|
||||
v[self.memory_start + 4] = self.excluded_shapes.len() as u32;
|
||||
v[self.memory_start + 5] = u32::from_ne_bytes(bbox_low.x.to_ne_bytes());
|
||||
v[self.memory_start + 6] = u32::from_ne_bytes(bbox_low.y.to_ne_bytes());
|
||||
v[self.memory_start + 7] = u32::from_ne_bytes(bbox_low.z.to_ne_bytes());
|
||||
|
||||
self.prev_memory_size = self.get_compound_buffer_mem_size(data);
|
||||
self.dirty = false;
|
||||
v
|
||||
}
|
||||
|
||||
fn get_memory_start(&self) -> usize {
|
||||
self.memory_start
|
||||
}
|
||||
|
||||
fn set_memory_start(&mut self, memory_start: usize) {
|
||||
self.memory_start = memory_start;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Sphere {
|
||||
pos: Vector3<f32>,
|
||||
rot: Vector3<f32>, // rotation will only matter once textures are implemented, till then it is a holdover
|
||||
radius: f32,
|
||||
color: Vector3<u8>, // color, either as pure color or texture modifier
|
||||
roughness: u8,
|
||||
memory_start: usize,
|
||||
dirty: bool
|
||||
}
|
||||
|
||||
impl Sphere {
|
||||
pub fn new(
|
||||
pos: Vector3<f32>,
|
||||
rot: Vector3<f32>,
|
||||
radius: f32,
|
||||
color: Vector3<u8>,
|
||||
roughness: u8) -> Self {
|
||||
Self { pos: pos, rot: rot, radius: radius, color: color, roughness: roughness, memory_start: 0, dirty: true }
|
||||
}
|
||||
}
|
||||
|
||||
impl Memorizable for Sphere {
|
||||
fn get_buffer_mem_size(&self, data: &AppData) -> u32 {
|
||||
// type, pos, rot, radius, (color + roughness)
|
||||
1 + 3 + 3 + 1 + 1
|
||||
}
|
||||
|
||||
fn get_prev_buffer_mem_size(&self) -> u32 {
|
||||
// constant memory size
|
||||
1 + 3 + 3 + 1 + 1
|
||||
}
|
||||
fn is_dirty(&self) -> bool {
|
||||
self.dirty
|
||||
}
|
||||
fn insert_into_memory(&mut self, mut v: Vec<u32>, data: &AppData, scene: &Scene) -> Vec<u32> {
|
||||
v[self.memory_start] = ShapeTypes::SPHERE as u32;
|
||||
v[self.memory_start + 1] = u32::from_ne_bytes(self.pos.x.to_ne_bytes());
|
||||
v[self.memory_start + 2] = u32::from_ne_bytes(self.pos.y.to_ne_bytes());
|
||||
v[self.memory_start + 3] = u32::from_ne_bytes(self.pos.z.to_ne_bytes());
|
||||
|
||||
v[self.memory_start + 4] = u32::from_ne_bytes(self.rot.x.to_ne_bytes());
|
||||
v[self.memory_start + 5] = u32::from_ne_bytes(self.rot.y.to_ne_bytes());
|
||||
v[self.memory_start + 6] = u32::from_ne_bytes(self.rot.z.to_ne_bytes());
|
||||
|
||||
v[self.memory_start + 7] = u32::from_ne_bytes(self.radius.to_ne_bytes());
|
||||
|
||||
v[self.memory_start + 8] = u32::from_ne_bytes([self.color.x, self.color.y, self.color.z, self.roughness]);
|
||||
|
||||
v
|
||||
}
|
||||
|
||||
fn get_memory_start(&self) -> usize {
|
||||
self.memory_start
|
||||
}
|
||||
fn set_memory_start(&mut self, memory_start: usize) {
|
||||
self.memory_start = memory_start;
|
||||
}
|
||||
}
|
||||
|
||||
impl Volumetrics for Sphere {
|
||||
fn get_pos(&self) -> Vector3<f32> {
|
||||
self.pos
|
||||
}
|
||||
|
||||
fn set_pos(&mut self, p: Vector3<f32>) {
|
||||
self.pos = p;
|
||||
}
|
||||
|
||||
fn get_rot(&self) -> Vector3<f32> {
|
||||
self.rot
|
||||
}
|
||||
|
||||
fn set_rot(&mut self, p: Vector3<f32>) {
|
||||
self.rot = p;
|
||||
}
|
||||
|
||||
fn get_bbox(&self) -> (Vector3<f32>, Vector3<f32>) {
|
||||
let rad_vec = Vector3 {x: self.radius, y: self.radius, z: self.radius};
|
||||
(self.pos - rad_vec, self.pos + rad_vec)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue