From 51760f30f1b46e1349afa8056623d374994b6525 Mon Sep 17 00:00:00 2001 From: zomseffen <steffen@tom.bi> Date: Mon, 28 Apr 2025 11:03:19 +0200 Subject: [PATCH] adds sparse oct_tree generation in compute --- build.rs | 4 +- shaders/compile.bat | 2 +- shaders/compile.sh | 2 +- shaders/compiled/rt_compute_combine.spv | Bin 5128 -> 0 bytes shaders/compiled/rt_compute_grow_one.spv | Bin 7116 -> 4744 bytes shaders/compiled/rt_compute_grow_three.spv | Bin 11192 -> 4852 bytes shaders/compiled/rt_compute_grow_two.spv | Bin 9304 -> 4852 bytes shaders/compiled/rt_compute_mempos.spv | Bin 0 -> 45852 bytes shaders/compiled/rt_compute_rasterize.spv | Bin 39216 -> 23524 bytes shaders/rt_compute_combine.comp | 51 --- shaders/rt_compute_grow_one.comp | 35 +-- shaders/rt_compute_grow_three.comp | 55 +--- shaders/rt_compute_grow_two.comp | 48 +-- shaders/rt_compute_mempos.comp | 349 +++++++++++++++++++++ shaders/rt_compute_rasterize.comp | 2 +- src/app_data.rs | 7 +- src/buffer.rs | 58 +++- src/command_buffer.rs | 37 ++- src/main.rs | 29 +- src/scene/generators.rs | 4 +- src/scene/mod.rs | 7 + src/scene/volumetrics/mod.rs | 22 +- 22 files changed, 498 insertions(+), 214 deletions(-) delete mode 100644 shaders/compiled/rt_compute_combine.spv create mode 100644 shaders/compiled/rt_compute_mempos.spv delete mode 100644 shaders/rt_compute_combine.comp create mode 100644 shaders/rt_compute_mempos.comp diff --git a/build.rs b/build.rs index 3a366b4..67aaf3a 100644 --- a/build.rs +++ b/build.rs @@ -18,7 +18,7 @@ fn main() { println!("cargo::rerun-if-changed=shaders/rt_compute_grow_one.comp"); println!("cargo::rerun-if-changed=shaders/rt_compute_grow_two.comp"); println!("cargo::rerun-if-changed=shaders/rt_compute_grow_three.comp"); - println!("cargo::rerun-if-changed=shaders/rt_compute_combine.comp"); + println!("cargo::rerun-if-changed=shaders/rt_compute_mempos.comp"); std::fs::remove_file("shaders/compiled/geo_cube.spv").unwrap_or(()); std::fs::remove_file("shaders/compiled/frag_cube.spv").unwrap_or(()); @@ -32,7 +32,7 @@ fn main() { std::fs::remove_file("shaders/compiled/rt_compute_grow_one.spv").unwrap_or(()); std::fs::remove_file("shaders/compiled/rt_compute_grow_two.spv").unwrap_or(()); std::fs::remove_file("shaders/compiled/rt_compute_grow_three.spv").unwrap_or(()); - std::fs::remove_file("shaders/compiled/rt_compute_combine.spv").unwrap_or(()); + std::fs::remove_file("shaders/compiled/rt_compute_mempos.spv").unwrap_or(()); if std::env::consts::OS == "windows" { let mut command = Command::new("./shaders/compile.bat"); diff --git a/shaders/compile.bat b/shaders/compile.bat index bb4fe6a..7717e6c 100644 --- a/shaders/compile.bat +++ b/shaders/compile.bat @@ -13,4 +13,4 @@ C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/rt_compute_rasterize.comp -o shader C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/rt_compute_grow_one.comp -o shaders/compiled/rt_compute_grow_one.spv C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/rt_compute_grow_two.comp -o shaders/compiled/rt_compute_grow_two.spv C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/rt_compute_grow_three.comp -o shaders/compiled/rt_compute_grow_three.spv -C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/rt_compute_combine.comp -o shaders/compiled/rt_compute_combine.spv \ No newline at end of file +C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/rt_compute_mempos.comp -o shaders/compiled/rt_compute_mempos.spv \ No newline at end of file diff --git a/shaders/compile.sh b/shaders/compile.sh index 88be158..9507c17 100755 --- a/shaders/compile.sh +++ b/shaders/compile.sh @@ -14,4 +14,4 @@ glslc shaders/rt_compute_rasterize.comp -o shaders/compiled/rt_compute_rasterize glslc shaders/rt_compute_grow_one.comp -o shaders/compiled/rt_compute_grow_one.spv glslc shaders/rt_compute_grow_two.comp -o shaders/compiled/rt_compute_grow_two.spv glslc shaders/rt_compute_grow_three.comp -o shaders/compiled/rt_compute_grow_three.spv -glslc shaders/rt_compute_combine.comp -o shaders/compiled/rt_compute_combine.spv \ No newline at end of file +glslc shaders/rt_compute_mempos.comp -o shaders/compiled/rt_compute_mempos.spv \ No newline at end of file diff --git a/shaders/compiled/rt_compute_combine.spv b/shaders/compiled/rt_compute_combine.spv deleted file mode 100644 index 61fd2eede649f37bb5eeab8520360a7cb2ee79f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5128 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 YXgt>aBiNW{c#>KEzibZwtLJ3@2k>IUEdT%j diff --git a/shaders/compiled/rt_compute_grow_one.spv b/shaders/compiled/rt_compute_grow_one.spv index 82ea0be971467cc84c96ddcbd851106015f6c56c..23863abd403c5b111fbfab3367c669fdc790a780 100644 GIT binary patch literal 4744 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 literal 7116 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 b>d}V_z|n`+^bXXF^$y}Z9q;FoPQ(5W=mDDN diff --git a/shaders/compiled/rt_compute_grow_three.spv b/shaders/compiled/rt_compute_grow_three.spv index 1a326caea5fc67c7b274178dab385db84aee2961..625eb4ba9966b3720f7f14f1a68c5358ae1f5679 100644 GIT binary patch literal 4852 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 literal 11192 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 T*YhFYy7ONe^Z5Tk=QaKYr<yo7 diff --git a/shaders/compiled/rt_compute_grow_two.spv b/shaders/compiled/rt_compute_grow_two.spv index 136cf1cc67e27c903ca67e60b97961589a257a90..5d56e66caf168269f4509489428ae5c815dcfeab 100644 GIT binary patch literal 4852 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 literal 9304 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 diff --git a/shaders/compiled/rt_compute_mempos.spv b/shaders/compiled/rt_compute_mempos.spv new file mode 100644 index 0000000000000000000000000000000000000000..891a76f8bbc50dd19122341f24f594e8c8404310 GIT binary patch literal 45852 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 AkpKVy literal 0 HcmV?d00001 diff --git a/shaders/compiled/rt_compute_rasterize.spv b/shaders/compiled/rt_compute_rasterize.spv index 9ad3d50fe254abd45e6798f712cf9e2c61881ecb..fc8e3b052d2ac700e2fdfc121aea111a5f5debd9 100644 GIT binary patch literal 23524 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 bi-Dbw?U`|}(c-j0G~@Ku{v+2%-D~-Oo#WPn literal 39216 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 XO>@E3>w20So|?>SO=|k)@9X{_BoJC} diff --git a/shaders/rt_compute_combine.comp b/shaders/rt_compute_combine.comp deleted file mode 100644 index c70c19e..0000000 --- a/shaders/rt_compute_combine.comp +++ /dev/null @@ -1,51 +0,0 @@ -#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 CompoundBuffer { - uint compounds[]; -}; - -layout(binding = 4) readonly buffer ColorBuffer { - uint grid_in[]; -}; - -layout(binding = 9) readonly buffer TransparentBuffer { - bool transparent_grid[]; -}; - -layout(binding = 8) buffer SizeBuffer3D { - uint grid_size_in[]; -}; - -layout (local_size_x = 16, local_size_y = 1, local_size_z = 1) in; - -void main() { - uint index = gl_GlobalInvocationID.x; - uint output_offset = 0; - uint compound_start = 0; - // iterate over the compounds and find the work index inside of it - while (index > compounds[compound_start] * compounds[compound_start]) { - output_offset += compounds[compound_start] * compounds[compound_start] * compounds[compound_start] * 2; - index -= compounds[compound_start] * compounds[compound_start]; - compound_start = compounds[compound_start + 2]; - } - // grid pos in the task - uint compound_grid_size = compounds[compound_start]; - float compound_scale = uintBitsToFloat(compounds[compound_start + 1]); - vec3 mid_offset = vec3(compound_scale * 0.5, compound_scale * 0.5, compound_scale * 0.5); - uint x = index % compound_grid_size; - uint y = ((index) % (compound_grid_size * compound_grid_size) - x) / (compound_grid_size); - uint z = (index - x - y * compound_grid_size) / (compound_grid_size * compound_grid_size); - - uint size_x = grid_size_in[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + z) * 3]; - uint size_y = grid_size_in[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + z) * 3 + 1]; - uint size_z = grid_size_in[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + z) * 3 + 2]; -} \ No newline at end of file diff --git a/shaders/rt_compute_grow_one.comp b/shaders/rt_compute_grow_one.comp index f4161f4..27e27eb 100644 --- a/shaders/rt_compute_grow_one.comp +++ b/shaders/rt_compute_grow_one.comp @@ -43,40 +43,11 @@ void main() { vec3 mid_offset = vec3(compound_scale * 0.5, compound_scale * 0.5, compound_scale * 0.5); uint y = index % compound_grid_size; uint z = (index - y) / compound_grid_size; - vec3 compound_pos = vec3(uintBitsToFloat(compounds[compound_start + 5]), uintBitsToFloat(compounds[compound_start + 6]), uintBitsToFloat(compounds[compound_start + 7])); // iterate upwards along the x axis - bool seen_empty = false; - uint start = 0; - uint last_col = 0; + uint sum = 0; for (uint x=0; x < compound_grid_size; x++) { uint color_val = grid_in[output_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z]; - bool transparent = transparent_grid[output_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z]; - grid_out[output_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z] = 0; - // check if we need to stop a volume - if (color_val != 0 && !transparent) { - // check if we are in a volume right now - if (seen_empty) { - // close the current volume - grid_out[output_offset + start * compound_grid_size * compound_grid_size + y * compound_grid_size + z] = x - start; - seen_empty = false; - last_col = 0; - } - } else { - // check if transparency changed - if (seen_empty && transparent && last_col != color_val) { - // if we switch colors close the current volume and prepare for a new one - grid_out[output_offset + start * compound_grid_size * compound_grid_size + y * compound_grid_size + z] = x - start; - seen_empty = false; - } - // start a new volume if we are not in one right now - if (!seen_empty) { - seen_empty = true; - start = x; - last_col = color_val; - } - } - } - if (seen_empty) { - grid_out[output_offset + start * compound_grid_size * compound_grid_size + y * compound_grid_size + z] = compound_grid_size - start; + sum += uint(color_val != 0); + grid_out[output_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z] = sum; } } \ No newline at end of file diff --git a/shaders/rt_compute_grow_three.comp b/shaders/rt_compute_grow_three.comp index 0460631..2127584 100644 --- a/shaders/rt_compute_grow_three.comp +++ b/shaders/rt_compute_grow_three.comp @@ -37,7 +37,7 @@ void main() { uint compound_start = 0; // iterate over the compounds and find the work index inside of it while (index > compounds[compound_start] * compounds[compound_start]) { - output_offset += compounds[compound_start] * compounds[compound_start] * compounds[compound_start] * 2; + output_offset += compounds[compound_start] * compounds[compound_start] * compounds[compound_start]; index -= compounds[compound_start] * compounds[compound_start]; compound_start = compounds[compound_start + 2]; } @@ -47,55 +47,10 @@ void main() { vec3 mid_offset = vec3(compound_scale * 0.5, compound_scale * 0.5, compound_scale * 0.5); uint x = index % compound_grid_size; uint y = (index - x) / compound_grid_size; - vec3 compound_pos = vec3(uintBitsToFloat(compounds[compound_start + 5]), uintBitsToFloat(compounds[compound_start + 6]), uintBitsToFloat(compounds[compound_start + 7])); - // iterate upwards along the x axis - bool seen_empty = false; - uint start = 0; - uint start_x_size = 0; - uint start_y_size = 0; - uint last_col = 0; + // iterate upwards along the z axis + uint sum = 0; for (uint z=0; z < compound_grid_size; z++) { - uint color_val = grid_in[output_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z]; - bool transparent = transparent_grid[output_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z]; - uint current_x_size = grid_size_in[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + z) * 2]; - uint current_y_size = grid_size_in[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + z) * 2 + 1]; - - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + z) * 3] = 0; - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + z) * 3 + 1] = 0; - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + z) * 3 + 2] = 0; - // check if we need to stop a volume - if (color_val != 0 && !transparent) { - // check if we are in a volume right now - if (seen_empty) { - // close the current volume - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + start) * 3] = start_x_size; - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + start) * 3 + 1] = start_y_size; - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + start) * 3 + 2] = z - start; - seen_empty = false; - last_col = 0; - } - } else { - // check if transparency changed - if (seen_empty && ((transparent && last_col != color_val) || (start_x_size != current_x_size) || (start_y_size != current_y_size))) { - // if we switch colors or size close the current volume and prepare for a new one - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + start) * 3] = start_x_size; - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + start) * 3 + 1] = start_y_size; - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + start) * 3 + 2] = z - start; - seen_empty = false; - } - // start a new volume if we are not in one right now - if (!seen_empty && current_x_size != 0 && current_y_size != 0) { - seen_empty = true; - start = z; - start_x_size = current_x_size; - start_y_size = current_y_size; - last_col = color_val; - } - } - } - if (seen_empty) { - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + start) * 3] = start_x_size; - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + start) * 3 + 1] = start_y_size; - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + start) * 3 + 2] = compound_grid_size - start; + sum += grid_size_in[output_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z]; + grid_out[output_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z] = sum; } } \ No newline at end of file diff --git a/shaders/rt_compute_grow_two.comp b/shaders/rt_compute_grow_two.comp index c2ec2f6..0631b0c 100644 --- a/shaders/rt_compute_grow_two.comp +++ b/shaders/rt_compute_grow_two.comp @@ -37,7 +37,7 @@ void main() { uint compound_start = 0; // iterate over the compounds and find the work index inside of it while (index > compounds[compound_start] * compounds[compound_start]) { - output_offset += compounds[compound_start] * compounds[compound_start] * compounds[compound_start] * 2; + output_offset += compounds[compound_start] * compounds[compound_start] * compounds[compound_start]; index -= compounds[compound_start] * compounds[compound_start]; compound_start = compounds[compound_start + 2]; } @@ -47,48 +47,10 @@ void main() { vec3 mid_offset = vec3(compound_scale * 0.5, compound_scale * 0.5, compound_scale * 0.5); uint x = index % compound_grid_size; uint z = (index - x) / compound_grid_size; - vec3 compound_pos = vec3(uintBitsToFloat(compounds[compound_start + 5]), uintBitsToFloat(compounds[compound_start + 6]), uintBitsToFloat(compounds[compound_start + 7])); - // iterate upwards along the x axis - bool seen_empty = false; - uint start = 0; - uint start_x_size = 0; - uint last_col = 0; + // iterate upwards along the y axis + uint sum = 0; for (uint y=0; y < compound_grid_size; y++) { - uint color_val = grid_in[output_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z]; - bool transparent = transparent_grid[output_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z]; - uint current_x_size = grid_size_in[output_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z]; - - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + z) * 2] = 0; - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + y * compound_grid_size + z) * 2 + 1] = 0; - // check if we need to stop a volume - if (color_val != 0 && !transparent) { - // check if we are in a volume right now - if (seen_empty) { - // close the current volume - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + start * compound_grid_size + z) * 2] = start_x_size; - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + start * compound_grid_size + z) * 2 + 1] = y - start; - seen_empty = false; - last_col = 0; - } - } else { - // check if transparency changed - if (seen_empty && ((transparent && last_col != color_val) || (start_x_size != current_x_size))) { - // if we switch colors or size close the current volume and prepare for a new one - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + start * compound_grid_size + z) * 2] = start_x_size; - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + start * compound_grid_size + z) * 2 + 1] = y - start; - seen_empty = false; - } - // start a new volume if we are not in one right now - if (!seen_empty && current_x_size != 0) { - seen_empty = true; - start = y; - start_x_size = current_x_size; - last_col = color_val; - } - } - } - if (seen_empty) { - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + start * compound_grid_size + z) * 2] = start_x_size; - grid_out[output_offset + (x * compound_grid_size * compound_grid_size + start * compound_grid_size + z) * 2 + 1] = compound_grid_size - start; + sum += grid_size_in[output_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z]; + grid_out[output_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z] = sum; } } \ No newline at end of file diff --git a/shaders/rt_compute_mempos.comp b/shaders/rt_compute_mempos.comp new file mode 100644 index 0000000..25c5a63 --- /dev/null +++ b/shaders/rt_compute_mempos.comp @@ -0,0 +1,349 @@ +#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 CompoundBuffer { + uint compounds[]; +}; + +layout(binding = 4) readonly buffer ColorBuffer { + uint grid_in[]; +}; + +layout(binding = 9) readonly buffer TransparentBuffer { + bool transparent_grid[]; +}; + +layout(binding = 8) readonly buffer SizeBuffer3D { + uint grid_size_in[]; +}; + +layout(binding = 10) buffer OutMemory { + uint out_memory[]; +}; + +layout(binding = 2) readonly buffer SceneInfoBuffer{ + uint infos[]; +} scene_info; + +uint max_num_lights = scene_info.infos[0]; + +layout (local_size_x = 16, local_size_y = 1, local_size_z = 1) in; + +uint num_nodes(uint size) { + uint nodes = 0; + uint add_size = 1; + while (size >= 2) { + nodes += add_size; + add_size = add_size * 8; + size = size / 2; + } + + return nodes; +} + +layout(binding = 5) buffer SizedVertices { + float vertices[]; +}; + +layout(binding = 6) buffer Indices { + uint indices[]; +}; + +vec3 unpack_color(uint val) { + // left most 8 bits first + uint val1 = (val >> 24); + uint val2 = (val << 8) >> 24; + uint val3 = (val << 16) >> 24; + uint val4 = (val << 24) >> 24; + + return vec3(val4 / 255.0, val3 / 255.0, val2 / 255.0); +} + +void add_cube(uint cube_num, float scale, vec3 pos, vec3 color) { + // add node info for the cube + //vertice 0 + vertices[(cube_num * 8 + 0) * 11 + 0] = pos.x - 0.5 * scale; + vertices[(cube_num * 8 + 0) * 11 + 1] = pos.y + 0.5 * scale; + vertices[(cube_num * 8 + 0) * 11 + 2] = pos.z + 0.5 * scale; + + vertices[(cube_num * 8 + 0) * 11 + 3] = color.x; + vertices[(cube_num * 8 + 0) * 11 + 4] = color.y; + vertices[(cube_num * 8 + 0) * 11 + 5] = color.z; + + //vertice 1 + vertices[(cube_num * 8 + 1) * 11 + 0] = pos.x + 0.5 * scale; + vertices[(cube_num * 8 + 1) * 11 + 1] = pos.y + 0.5 * scale; + vertices[(cube_num * 8 + 1) * 11 + 2] = pos.z + 0.5 * scale; + + vertices[(cube_num * 8 + 1) * 11 + 3] = color.x; + vertices[(cube_num * 8 + 1) * 11 + 4] = color.y; + vertices[(cube_num * 8 + 1) * 11 + 5] = color.z; + + //vertice 2 + vertices[(cube_num * 8 + 2) * 11 + 0] = pos.x - 0.5 * scale; + vertices[(cube_num * 8 + 2) * 11 + 1] = pos.y - 0.5 * scale; + vertices[(cube_num * 8 + 2) * 11 + 2] = pos.z + 0.5 * scale; + + vertices[(cube_num * 8 + 2) * 11 + 3] = color.x; + vertices[(cube_num * 8 + 2) * 11 + 4] = color.y; + vertices[(cube_num * 8 + 2) * 11 + 5] = color.z; + + //vertice 3 + vertices[(cube_num * 8 + 3) * 11 + 0] = pos.x + 0.5 * scale; + vertices[(cube_num * 8 + 3) * 11 + 1] = pos.y - 0.5 * scale; + vertices[(cube_num * 8 + 3) * 11 + 2] = pos.z + 0.5 * scale; + + vertices[(cube_num * 8 + 3) * 11 + 3] = color.x; + vertices[(cube_num * 8 + 3) * 11 + 4] = color.y; + vertices[(cube_num * 8 + 3) * 11 + 5] = color.z; + + //vertice 4 + vertices[(cube_num * 8 + 4) * 11 + 0] = pos.x - 0.5 * scale; + vertices[(cube_num * 8 + 4) * 11 + 1] = pos.y + 0.5 * scale; + vertices[(cube_num * 8 + 4) * 11 + 2] = pos.z - 0.5 * scale; + + vertices[(cube_num * 8 + 4) * 11 + 3] = color.x; + vertices[(cube_num * 8 + 4) * 11 + 4] = color.y; + vertices[(cube_num * 8 + 4) * 11 + 5] = color.z; + + //vertice 5 + vertices[(cube_num * 8 + 5) * 11 + 0] = pos.x + 0.5 * scale; + vertices[(cube_num * 8 + 5) * 11 + 1] = pos.y + 0.5 * scale; + vertices[(cube_num * 8 + 5) * 11 + 2] = pos.z - 0.5 * scale; + + vertices[(cube_num * 8 + 5) * 11 + 3] = color.x; + vertices[(cube_num * 8 + 5) * 11 + 4] = color.y; + vertices[(cube_num * 8 + 5) * 11 + 5] = color.z; + + //vertice 6 + vertices[(cube_num * 8 + 6) * 11 + 0] = pos.x - 0.5 * scale; + vertices[(cube_num * 8 + 6) * 11 + 1] = pos.y - 0.5 * scale; + vertices[(cube_num * 8 + 6) * 11 + 2] = pos.z - 0.5 * scale; + + vertices[(cube_num * 8 + 6) * 11 + 3] = color.x; + vertices[(cube_num * 8 + 6) * 11 + 4] = color.y; + vertices[(cube_num * 8 + 6) * 11 + 5] = color.z; + + //vertice 7 + vertices[(cube_num * 8 + 7) * 11 + 0] = pos.x + 0.5 * scale; + vertices[(cube_num * 8 + 7) * 11 + 1] = pos.y - 0.5 * scale; + vertices[(cube_num * 8 + 7) * 11 + 2] = pos.z - 0.5 * scale; + + vertices[(cube_num * 8 + 7) * 11 + 3] = color.x; + vertices[(cube_num * 8 + 7) * 11 + 4] = color.y; + vertices[(cube_num * 8 + 7) * 11 + 5] = color.z; + + //add indices for the cube + //top + indices[cube_num * 36 + 0] = cube_num * 8 + 3; + indices[cube_num * 36 + 1] = cube_num * 8 + 0; + indices[cube_num * 36 + 2] = cube_num * 8 + 2; + + indices[cube_num * 36 + 3] = cube_num * 8 + 3; + indices[cube_num * 36 + 4] = cube_num * 8 + 1; + indices[cube_num * 36 + 5] = cube_num * 8 + 0; + + //bottom + indices[cube_num * 36 + 6] = cube_num * 8 + 6; + indices[cube_num * 36 + 7] = cube_num * 8 + 4; + indices[cube_num * 36 + 8] = cube_num * 8 + 7; + + indices[cube_num * 36 + 9] = cube_num * 8 + 4; + indices[cube_num * 36 + 10] = cube_num * 8 + 5; + indices[cube_num * 36 + 11] = cube_num * 8 + 7; + + //left + indices[cube_num * 36 + 12] = cube_num * 8 + 0; + indices[cube_num * 36 + 13] = cube_num * 8 + 4; + indices[cube_num * 36 + 14] = cube_num * 8 + 2; + + indices[cube_num * 36 + 15] = cube_num * 8 + 6; + indices[cube_num * 36 + 16] = cube_num * 8 + 2; + indices[cube_num * 36 + 17] = cube_num * 8 + 4; + + //right + indices[cube_num * 36 + 18] = cube_num * 8 + 1; + indices[cube_num * 36 + 19] = cube_num * 8 + 3; + indices[cube_num * 36 + 20] = cube_num * 8 + 5; + + indices[cube_num * 36 + 21] = cube_num * 8 + 5; + indices[cube_num * 36 + 22] = cube_num * 8 + 3; + indices[cube_num * 36 + 23] = cube_num * 8 + 7; + + //near + indices[cube_num * 36 + 24] = cube_num * 8 + 6; + indices[cube_num * 36 + 25] = cube_num * 8 + 3; + indices[cube_num * 36 + 26] = cube_num * 8 + 2; + + indices[cube_num * 36 + 27] = cube_num * 8 + 3; + indices[cube_num * 36 + 28] = cube_num * 8 + 6; + indices[cube_num * 36 + 29] = cube_num * 8 + 7; + + //far + indices[cube_num * 36 + 30] = cube_num * 8 + 0; + indices[cube_num * 36 + 31] = cube_num * 8 + 1; + indices[cube_num * 36 + 32] = cube_num * 8 + 4; + + indices[cube_num * 36 + 33] = cube_num * 8 + 5; + indices[cube_num * 36 + 34] = cube_num * 8 + 4; + indices[cube_num * 36 + 35] = cube_num * 8 + 1; + +} + +void main() { + uint index = gl_GlobalInvocationID.x; + uint output_offset = 1; + uint input_offset = 0; + uint compound_start = 0; + + uint nodes = num_nodes(compounds[compound_start]); + // iterate over the compounds and find the work index inside of it + while (index > nodes) { + output_offset += nodes * 9; + input_offset += compounds[compound_start] * compounds[compound_start] * compounds[compound_start]; + index -= nodes; + compound_start = compounds[compound_start + 2]; + nodes = num_nodes(compounds[compound_start]); + } + + uint compound_grid_size = compounds[compound_start]; + uint parent_start = 0; + uint cohort_start = 0; + uint cohort_index = index; + uint size = compounds[compound_start]; + nodes = 0; + uint add_size = 1; + while (cohort_index >= add_size) { + nodes += add_size; + cohort_index -= add_size; + parent_start = cohort_start; + cohort_start = nodes * 9; + add_size *= 8; + size = size / 2; + } + + uint parent = parent_start + ((cohort_index - cohort_index % 8) / 8) * 9; + uint start = cohort_start + 9 * cohort_index; + uint steps = compounds[compound_start] / size; + + float compound_scale = uintBitsToFloat(compounds[compound_start + 1]); + vec3 mid_offset = vec3(compound_scale * 0.5, compound_scale * 0.5, compound_scale * 0.5); + + uint x = (cohort_index % steps) * size; + uint y = (((cohort_index - (cohort_index % steps)) % (steps * steps)) / (steps)) * size; + uint z = (((cohort_index - (cohort_index % (steps * steps)))) / (steps * steps)) * size; + + // plus one size offset, since we want to place the nodes at the far end. This aligns with the iteration directions in the previous shaders + x = x + (size - 1); + y = y + (size - 1); + z = z + (size - 1); + + // sum of all elements with coordinates lower than x, y, z + uint contained_entries = grid_size_in[input_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z]; + if (z > size) { + // remove contained from z neighbor + contained_entries = contained_entries - grid_size_in[input_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z - size]; + } + + if (y > size) { + if (z > size) { + // add back the section we will remove twice + contained_entries = contained_entries + int(grid_size_in[input_offset + x * compound_grid_size * compound_grid_size + (y - size) * compound_grid_size + z - size]); + } + // remove contained from y neighbor + contained_entries = contained_entries - int(grid_size_in[input_offset + x * compound_grid_size * compound_grid_size + (y - size) * compound_grid_size + z]); + } + + if (x > size) { + if (z > size) { + // add the portion already removed through the z neighbor + contained_entries = contained_entries + grid_size_in[input_offset + (x - size) * compound_grid_size * compound_grid_size + y * compound_grid_size + z - size]; + } + + if (y > size) { + // add the portion already removed by the y neighbor + contained_entries = contained_entries + grid_size_in[input_offset + (x - size) * compound_grid_size * compound_grid_size + (y - size) * compound_grid_size + z]; + + if (z > size) { + // remove the portion already added through the z neighbor + contained_entries = contained_entries - grid_size_in[input_offset + (x - size) * compound_grid_size * compound_grid_size + (y - size) * compound_grid_size + z - size]; + } + } + + // remove contained from x neighbor + contained_entries = contained_entries - grid_size_in[input_offset + (x - size) * compound_grid_size * compound_grid_size + y * compound_grid_size + z]; + } + + if (contained_entries > 0) { + out_memory[output_offset + cohort_start + cohort_index * 9 + 0] = parent * uint(size != 64); + + if (size > 2) { + // add child node reference + uint cohort_end = cohort_start + 9 * add_size; + out_memory[output_offset + cohort_start + cohort_index * 9 + 1] = cohort_end + cohort_index * 9 + 9 * 0; // xyz + out_memory[output_offset + cohort_start + cohort_index * 9 + 2] = cohort_end + cohort_index * 9 + 9 * 1; // Xyz + out_memory[output_offset + cohort_start + cohort_index * 9 + 3] = cohort_end + cohort_index * 9 + 9 * 2; // xYz + out_memory[output_offset + cohort_start + cohort_index * 9 + 4] = cohort_end + cohort_index * 9 + 9 * 3; // XYz + out_memory[output_offset + cohort_start + cohort_index * 9 + 5] = cohort_end + cohort_index * 9 + 9 * 4; // xyZ + out_memory[output_offset + cohort_start + cohort_index * 9 + 6] = cohort_end + cohort_index * 9 + 9 * 5; // XyZ + out_memory[output_offset + cohort_start + cohort_index * 9 + 7] = cohort_end + cohort_index * 9 + 9 * 6; // xYZ + out_memory[output_offset + cohort_start + cohort_index * 9 + 8] = cohort_end + cohort_index * 9 + 9 * 7; // XYZ + + } else { + // copy color values and add cubes to rendering + out_memory[output_offset + cohort_start + cohort_index * 9 + 1] = grid_in[input_offset + (x - 1) * compound_grid_size * compound_grid_size + (y - 1) * compound_grid_size + (z - 1)]; // xyz + out_memory[output_offset + cohort_start + cohort_index * 9 + 2] = grid_in[input_offset + (x - 0) * compound_grid_size * compound_grid_size + (y - 1) * compound_grid_size + (z - 1)]; // Xyz + out_memory[output_offset + cohort_start + cohort_index * 9 + 3] = grid_in[input_offset + (x - 1) * compound_grid_size * compound_grid_size + (y - 0) * compound_grid_size + (z - 1)]; // xYz + out_memory[output_offset + cohort_start + cohort_index * 9 + 4] = grid_in[input_offset + (x - 0) * compound_grid_size * compound_grid_size + (y - 0) * compound_grid_size + (z - 1)]; // XYz + out_memory[output_offset + cohort_start + cohort_index * 9 + 5] = grid_in[input_offset + (x - 1) * compound_grid_size * compound_grid_size + (y - 1) * compound_grid_size + (z - 0)]; // xyZ + out_memory[output_offset + cohort_start + cohort_index * 9 + 6] = grid_in[input_offset + (x - 0) * compound_grid_size * compound_grid_size + (y - 1) * compound_grid_size + (z - 0)]; // XyZ + out_memory[output_offset + cohort_start + cohort_index * 9 + 7] = grid_in[input_offset + (x - 1) * compound_grid_size * compound_grid_size + (y - 0) * compound_grid_size + (z - 0)]; // xYZ + out_memory[output_offset + cohort_start + cohort_index * 9 + 8] = grid_in[input_offset + (x - 0) * compound_grid_size * compound_grid_size + (y - 0) * compound_grid_size + (z - 0)]; // XYZ + + vec3 compound_pos = vec3(uintBitsToFloat(compounds[compound_start + 5]), uintBitsToFloat(compounds[compound_start + 6]), uintBitsToFloat(compounds[compound_start + 7])); + vec3 check_pos = compound_pos + vec3(float(x) * compound_scale, float(y) * compound_scale, float(z) * compound_scale) + mid_offset; + if (out_memory[output_offset + cohort_start + cohort_index * 9 + 1] != 0) { + add_cube(input_offset + (z - 1) * compound_grid_size * compound_grid_size + (y - 1) * compound_grid_size + (x - 1), compound_scale, check_pos - vec3(1.0, 1.0, 1.0) * compound_scale, unpack_color(out_memory[output_offset + cohort_start + cohort_index * 9 + 1])); + } + if (out_memory[output_offset + cohort_start + cohort_index * 9 + 2] != 0) { + add_cube(input_offset + (z - 1) * compound_grid_size * compound_grid_size + (y - 1) * compound_grid_size + (x - 0), compound_scale, check_pos - vec3(0.0, 1.0, 1.0) * compound_scale, unpack_color(out_memory[output_offset + cohort_start + cohort_index * 9 + 2])); + } + if (out_memory[output_offset + cohort_start + cohort_index * 9 + 3] != 0) { + add_cube(input_offset + (z - 1) * compound_grid_size * compound_grid_size + (y - 0) * compound_grid_size + (x - 1), compound_scale, check_pos - vec3(1.0, 0.0, 1.0) * compound_scale, unpack_color(out_memory[output_offset + cohort_start + cohort_index * 9 + 3])); + } + if (out_memory[output_offset + cohort_start + cohort_index * 9 + 4] != 0) { + add_cube(input_offset + (z - 1) * compound_grid_size * compound_grid_size + (y - 0) * compound_grid_size + (x - 0), compound_scale, check_pos - vec3(0.0, 0.0, 1.0) * compound_scale, unpack_color(out_memory[output_offset + cohort_start + cohort_index * 9 + 4])); + } + if (out_memory[output_offset + cohort_start + cohort_index * 9 + 5] != 0) { + add_cube(input_offset + (z - 0) * compound_grid_size * compound_grid_size + (y - 1) * compound_grid_size + (x - 1), compound_scale, check_pos - vec3(1.0, 1.0, 0.0) * compound_scale, unpack_color(out_memory[output_offset + cohort_start + cohort_index * 9 + 5])); + } + if (out_memory[output_offset + cohort_start + cohort_index * 9 + 6] != 0) { + add_cube(input_offset + (z - 0) * compound_grid_size * compound_grid_size + (y - 1) * compound_grid_size + (x - 0), compound_scale, check_pos - vec3(0.0, 1.0, 0.0) * compound_scale, unpack_color(out_memory[output_offset + cohort_start + cohort_index * 9 + 6])); + } + if (out_memory[output_offset + cohort_start + cohort_index * 9 + 7] != 0) { + add_cube(input_offset + (z - 0) * compound_grid_size * compound_grid_size + (y - 0) * compound_grid_size + (x - 1), compound_scale, check_pos - vec3(1.0, 0.0, 0.0) * compound_scale, unpack_color(out_memory[output_offset + cohort_start + cohort_index * 9 + 7])); + } + if (out_memory[output_offset + cohort_start + cohort_index * 9 + 8] != 0) { + add_cube(input_offset + (z - 0) * compound_grid_size * compound_grid_size + (y - 0) * compound_grid_size + (x - 0), compound_scale, check_pos - vec3(0.0, 0.0, 0.0) * compound_scale, unpack_color(out_memory[output_offset + cohort_start + cohort_index * 9 + 8])); + } + } + } else { + out_memory[output_offset + cohort_start + cohort_index * 9 + 0] = 0; + out_memory[output_offset + cohort_start + cohort_index * 9 + 1] = 0; + out_memory[output_offset + cohort_start + cohort_index * 9 + 2] = 0; + out_memory[output_offset + cohort_start + cohort_index * 9 + 3] = 0; + out_memory[output_offset + cohort_start + cohort_index * 9 + 4] = 0; + out_memory[output_offset + cohort_start + cohort_index * 9 + 5] = 0; + out_memory[output_offset + cohort_start + cohort_index * 9 + 6] = 0; + out_memory[output_offset + cohort_start + cohort_index * 9 + 7] = 0; + out_memory[output_offset + cohort_start + cohort_index * 9 + 8] = 0; + } +} \ No newline at end of file diff --git a/shaders/rt_compute_rasterize.comp b/shaders/rt_compute_rasterize.comp index 8603805..67912b2 100644 --- a/shaders/rt_compute_rasterize.comp +++ b/shaders/rt_compute_rasterize.comp @@ -349,7 +349,7 @@ void main() { if (render) { grid[output_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z] = color_int; transparent_grid[output_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z] = transparent; - add_cube(output_offset + index * compound_grid_size + z, compound_scale, check_pos, color); + //add_cube(output_offset + index * compound_grid_size + z, compound_scale, check_pos, color); } else { grid[output_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z] = 0; transparent_grid[output_offset + x * compound_grid_size * compound_grid_size + y * compound_grid_size + z] = false; diff --git a/src/app_data.rs b/src/app_data.rs index 0dafc31..bfacaf4 100644 --- a/src/app_data.rs +++ b/src/app_data.rs @@ -27,7 +27,7 @@ pub struct AppData { pub pipeline_compute_grow_one: vk::Pipeline, pub pipeline_compute_grow_two: vk::Pipeline, pub pipeline_compute_grow_three: vk::Pipeline, - pub pipeline_compute_combine: vk::Pipeline, + pub pipeline_compute_mempos: vk::Pipeline, pub framebuffers: Vec<vk::Framebuffer>, pub command_pool: vk::CommandPool, @@ -60,6 +60,9 @@ pub struct AppData { pub compute_out_storage_buffers_size_three: Vec<vk::Buffer>, pub compute_out_storage_buffers_memory_size_three: Vec<vk::DeviceMemory>, + pub compute_out_storage_buffers_oct_tree: Vec<vk::Buffer>, + pub compute_out_storage_buffers_memory_oct_tree: Vec<vk::DeviceMemory>, + pub compute_out_cuboid_buffers: Vec<vk::Buffer>, pub compute_out_cuboid_buffers_memory: Vec<vk::DeviceMemory>, @@ -92,6 +95,8 @@ pub struct AppData { pub compute_task_one_size: usize, pub compute_task_one_out_buffer_size: u64, pub compute_task_one_out_size: u64, + pub compute_task_oct_tree_size: u64, + pub compute_task_oct_tree_nodes: u64, // values passed to shader pub num_lights_per_volume: u32, pub min_light_weight: f32, diff --git a/src/buffer.rs b/src/buffer.rs index 8374162..c2b7572 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -206,7 +206,7 @@ pub unsafe fn create_descriptor_set_layout( .binding(2) .descriptor_type(vk::DescriptorType::STORAGE_BUFFER) .descriptor_count(1) - .stage_flags(vk::ShaderStageFlags::FRAGMENT); + .stage_flags(vk::ShaderStageFlags::FRAGMENT | vk::ShaderStageFlags::COMPUTE); let storage_binding_compute_in = vk::DescriptorSetLayoutBinding::builder() .binding(3) @@ -250,7 +250,13 @@ pub unsafe fn create_descriptor_set_layout( .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_color, storage_binding_compute_cuboid_out, storage_binding_compute_cuboid_index_out, storage_binding_compute_out_size_two, storage_binding_compute_out_size_three, storage_binding_compute_out_size_transparent]; + let storage_binding_compute_out_oct_tree = vk::DescriptorSetLayoutBinding::builder() + .binding(10) + .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_color, storage_binding_compute_cuboid_out, storage_binding_compute_cuboid_index_out, storage_binding_compute_out_size_two, storage_binding_compute_out_size_three, storage_binding_compute_out_size_transparent, storage_binding_compute_out_oct_tree]; let info = vk::DescriptorSetLayoutCreateInfo::builder() .bindings(bindings); @@ -311,6 +317,9 @@ pub unsafe fn create_storage_buffers( data.compute_out_cuboid_index_buffers.clear(); data.compute_out_cuboid_index_buffers_memory.clear(); + data.compute_out_storage_buffers_oct_tree.clear(); + data.compute_out_storage_buffers_memory_oct_tree.clear(); + for _ in 0..data.swapchain_images.len() { let (storage_buffer, storage_buffer_memory) = create_buffer( instance, @@ -363,7 +372,7 @@ pub unsafe fn create_storage_buffers( instance, device, data, - (size_of::<u32>() * 2) as u64 * data.compute_task_one_out_buffer_size.max(1), + (size_of::<u32>()) as u64 * data.compute_task_one_out_buffer_size.max(1), vk::BufferUsageFlags::STORAGE_BUFFER, vk::MemoryPropertyFlags::DEVICE_LOCAL, )?; @@ -375,7 +384,7 @@ pub unsafe fn create_storage_buffers( instance, device, data, - (size_of::<u32>() * 3) as u64 * data.compute_task_one_out_buffer_size.max(1), + (size_of::<u32>()) as u64 * data.compute_task_one_out_buffer_size.max(1), vk::BufferUsageFlags::STORAGE_BUFFER, vk::MemoryPropertyFlags::DEVICE_LOCAL, )?; @@ -383,6 +392,18 @@ pub unsafe fn create_storage_buffers( data.compute_out_storage_buffers_size_three.push(storage_buffer); data.compute_out_storage_buffers_memory_size_three.push(storage_buffer_memory); + let (storage_buffer, storage_buffer_memory) = create_buffer( + instance, + device, + data, + (size_of::<u32>()) as u64 * data.compute_task_oct_tree_size.max(1), + vk::BufferUsageFlags::STORAGE_BUFFER, + vk::MemoryPropertyFlags::DEVICE_LOCAL, + )?; + + data.compute_out_storage_buffers_oct_tree.push(storage_buffer); + data.compute_out_storage_buffers_memory_oct_tree.push(storage_buffer_memory); + let (storage_buffer, storage_buffer_memory) = create_buffer( instance, device, @@ -551,8 +572,12 @@ pub unsafe fn create_descriptor_pool(device: &Device, data: &mut app_data::AppDa let compute_out_storage_transparent_size = vk::DescriptorPoolSize::builder() .type_(vk::DescriptorType::STORAGE_BUFFER) .descriptor_count(data.swapchain_images.len() as u32); + + let compute_out_storage_oct_tree = vk::DescriptorPoolSize::builder() + .type_(vk::DescriptorType::STORAGE_BUFFER) + .descriptor_count(data.swapchain_images.len() as u32); - let pool_sizes = &[ubo_size, sampler_size, render_storage_size, compute_in_storage_size, compute_out_storage_color_size, compute_out_cuboid_size, compute_out_cuboid_index_size, compute_out_storage_size_two_size, compute_out_storage_size_three_size, compute_out_storage_transparent_size]; + let pool_sizes = &[ubo_size, sampler_size, render_storage_size, compute_in_storage_size, compute_out_storage_color_size, compute_out_cuboid_size, compute_out_cuboid_index_size, compute_out_storage_size_two_size, compute_out_storage_size_three_size, compute_out_storage_transparent_size, compute_out_storage_oct_tree]; let info = vk::DescriptorPoolCreateInfo::builder() .pool_sizes(pool_sizes) .max_sets(data.swapchain_images.len() as u32); @@ -625,7 +650,7 @@ pub unsafe fn create_descriptor_sets(device: &Device, data: &mut app_data::AppDa let info = vk::DescriptorBufferInfo::builder() .buffer(data.compute_out_storage_buffers_color[i]) .offset(0) - .range((size_of::<u32>() * 3) as u64 * data.compute_task_one_out_buffer_size.max(1)); + .range((size_of::<u32>()) as u64 * data.compute_task_one_out_buffer_size.max(1)); let storage_info = &[info]; let storage_write_compute_out_color = vk::WriteDescriptorSet::builder() @@ -638,7 +663,7 @@ pub unsafe fn create_descriptor_sets(device: &Device, data: &mut app_data::AppDa let info = vk::DescriptorBufferInfo::builder() .buffer(data.compute_out_storage_buffers_size_two[i]) .offset(0) - .range((size_of::<u32>() * 2) as u64 * data.compute_task_one_out_buffer_size.max(1)); + .range((size_of::<u32>()) as u64 * data.compute_task_one_out_buffer_size.max(1)); let storage_info = &[info]; let storage_write_compute_out_size_two = vk::WriteDescriptorSet::builder() @@ -651,7 +676,7 @@ pub unsafe fn create_descriptor_sets(device: &Device, data: &mut app_data::AppDa let info = vk::DescriptorBufferInfo::builder() .buffer(data.compute_out_storage_buffers_size_three[i]) .offset(0) - .range((size_of::<u32>() * 3) as u64 * data.compute_task_one_out_buffer_size.max(1)); + .range((size_of::<u32>()) as u64 * data.compute_task_one_out_buffer_size.max(1)); let storage_info = &[info]; let storage_write_compute_out_size_three = vk::WriteDescriptorSet::builder() @@ -664,7 +689,7 @@ pub unsafe fn create_descriptor_sets(device: &Device, data: &mut app_data::AppDa let info = vk::DescriptorBufferInfo::builder() .buffer(data.compute_out_storage_buffers_transparent[i]) .offset(0) - .range((size_of::<bool>() * 3) as u64 * data.compute_task_one_out_buffer_size.max(1)); + .range((size_of::<bool>()) as u64 * data.compute_task_one_out_buffer_size.max(1)); let storage_info = &[info]; let storage_write_compute_out_transparent = vk::WriteDescriptorSet::builder() @@ -674,6 +699,19 @@ pub unsafe fn create_descriptor_sets(device: &Device, data: &mut app_data::AppDa .descriptor_type(vk::DescriptorType::STORAGE_BUFFER) .buffer_info(storage_info); + let info = vk::DescriptorBufferInfo::builder() + .buffer(data.compute_out_storage_buffers_oct_tree[i]) + .offset(0) + .range((size_of::<u32>()) as u64 * data.compute_task_oct_tree_size.max(1)); + let storage_info = &[info]; + + let storage_write_compute_out_oct_tree = vk::WriteDescriptorSet::builder() + .dst_set(data.descriptor_sets[i]) + .dst_binding(10) + .dst_array_element(0) + .descriptor_type(vk::DescriptorType::STORAGE_BUFFER) + .buffer_info(storage_info); + let info = vk::DescriptorBufferInfo::builder() .buffer(data.compute_out_cuboid_buffers[i]) .offset(0) @@ -702,7 +740,7 @@ pub unsafe fn create_descriptor_sets(device: &Device, data: &mut app_data::AppDa device.update_descriptor_sets( - &[ubo_write, sampler_write, storage_write_render, storage_write_compute_in, storage_write_compute_out_color, storage_write_compute_cuboid_out, storage_write_compute_cuboid_index_out, storage_write_compute_out_size_two, storage_write_compute_out_size_three, storage_write_compute_out_transparent], + &[ubo_write, sampler_write, storage_write_render, storage_write_compute_in, storage_write_compute_out_color, storage_write_compute_cuboid_out, storage_write_compute_cuboid_index_out, storage_write_compute_out_size_two, storage_write_compute_out_size_three, storage_write_compute_out_transparent, storage_write_compute_out_oct_tree], &[] as &[vk::CopyDescriptorSet], ); } diff --git a/src/command_buffer.rs b/src/command_buffer.rs index e477391..7b6289b 100644 --- a/src/command_buffer.rs +++ b/src/command_buffer.rs @@ -156,6 +156,13 @@ pub unsafe fn create_command_buffers(device: &Device, data: &mut app_data::AppDa &[]); device.cmd_dispatch(*command_buffer, (data.compute_task_one_size as f64 / 16.0).ceil() as u32, 1, 1); + + let buffer_memory_barrier_in = vk::BufferMemoryBarrier::builder() + .buffer(data.compute_out_storage_buffers_size_three[i]) + .src_access_mask(vk::AccessFlags::SHADER_READ) + .dst_access_mask(vk::AccessFlags::SHADER_WRITE) + .size(vk::WHOLE_SIZE as u64) + .build(); let buffer_memory_barrier_out = vk::BufferMemoryBarrier::builder() .buffer(data.compute_out_storage_buffers_size_two[i]) @@ -169,7 +176,7 @@ pub unsafe fn create_command_buffers(device: &Device, data: &mut app_data::AppDa vk::PipelineStageFlags::COMPUTE_SHADER, vk::DependencyFlags::DEVICE_GROUP, &[] as &[vk::MemoryBarrier], - &[buffer_memory_barrier_out], + &[buffer_memory_barrier_in, buffer_memory_barrier_out], &[] as &[vk::ImageMemoryBarrier]); // grow z axis @@ -185,6 +192,13 @@ pub unsafe fn create_command_buffers(device: &Device, data: &mut app_data::AppDa &[]); device.cmd_dispatch(*command_buffer, (data.compute_task_one_size as f64 / 16.0).ceil() as u32, 1, 1); + + let buffer_memory_barrier_in = vk::BufferMemoryBarrier::builder() + .buffer(data.compute_out_storage_buffers_size_two[i]) + .src_access_mask(vk::AccessFlags::SHADER_READ) + .dst_access_mask(vk::AccessFlags::SHADER_WRITE) + .size(vk::WHOLE_SIZE as u64) + .build(); let buffer_memory_barrier_out = vk::BufferMemoryBarrier::builder() .buffer(data.compute_out_storage_buffers_size_three[i]) @@ -198,12 +212,12 @@ pub unsafe fn create_command_buffers(device: &Device, data: &mut app_data::AppDa vk::PipelineStageFlags::COMPUTE_SHADER, vk::DependencyFlags::DEVICE_GROUP, &[] as &[vk::MemoryBarrier], - &[buffer_memory_barrier_out], + &[buffer_memory_barrier_in, buffer_memory_barrier_out], &[] as &[vk::ImageMemoryBarrier]); - // combine element + // calculate mem size device.cmd_bind_pipeline( - *command_buffer, vk::PipelineBindPoint::COMPUTE, data.pipeline_compute_combine); + *command_buffer, vk::PipelineBindPoint::COMPUTE, data.pipeline_compute_mempos); device.cmd_bind_descriptor_sets( *command_buffer, @@ -213,10 +227,17 @@ pub unsafe fn create_command_buffers(device: &Device, data: &mut app_data::AppDa &[data.descriptor_sets[i]], &[]); - device.cmd_dispatch(*command_buffer, (data.compute_task_one_size as f64 / 16.0).ceil() as u32, 1, 1); + device.cmd_dispatch(*command_buffer, data.compute_task_oct_tree_nodes as u32, 1, 1); + + let buffer_memory_barrier_in = vk::BufferMemoryBarrier::builder() + .buffer(data.compute_out_storage_buffers_size_three[i]) + .src_access_mask(vk::AccessFlags::SHADER_READ) + .dst_access_mask(vk::AccessFlags::SHADER_WRITE) + .size(vk::WHOLE_SIZE as u64) + .build(); let buffer_memory_barrier_out = vk::BufferMemoryBarrier::builder() - .buffer(data.render_storage_buffers[i]) + .buffer(data.compute_out_storage_buffers_size_two[i]) .src_access_mask(vk::AccessFlags::SHADER_WRITE) .dst_access_mask(vk::AccessFlags::SHADER_READ) .size(vk::WHOLE_SIZE as u64) @@ -224,10 +245,10 @@ pub unsafe fn create_command_buffers(device: &Device, data: &mut app_data::AppDa device.cmd_pipeline_barrier(*command_buffer, vk::PipelineStageFlags::COMPUTE_SHADER, - vk::PipelineStageFlags::FRAGMENT_SHADER, + vk::PipelineStageFlags::COMPUTE_SHADER, vk::DependencyFlags::DEVICE_GROUP, &[] as &[vk::MemoryBarrier], - &[buffer_memory_barrier_out], + &[buffer_memory_barrier_in, buffer_memory_barrier_out], &[] as &[vk::ImageMemoryBarrier]); } // start render pass diff --git a/src/main.rs b/src/main.rs index 1b2714e..d5905b4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -441,13 +441,20 @@ impl App { .iter() .for_each(|m| self.device.free_memory(*m, None)); - self.data.compute_out_storage_buffers_size_three + self.data.compute_out_storage_buffers_size_three .iter() .for_each(|b| self.device.destroy_buffer(*b, None)); self.data.compute_out_storage_buffers_memory_size_three .iter() .for_each(|m| self.device.free_memory(*m, None)); + self.data.compute_out_storage_buffers_oct_tree + .iter() + .for_each(|b| self.device.destroy_buffer(*b, None)); + self.data.compute_out_storage_buffers_memory_oct_tree + .iter() + .for_each(|m| self.device.free_memory(*m, None)); + self.data.compute_out_cuboid_buffers .iter() .for_each(|b| self.device.destroy_buffer(*b, None)); @@ -474,7 +481,7 @@ impl App { self.device.destroy_pipeline(self.data.pipeline_compute_grow_one, None); self.device.destroy_pipeline(self.data.pipeline_compute_grow_two, None); self.device.destroy_pipeline(self.data.pipeline_compute_grow_three, None); - self.device.destroy_pipeline(self.data.pipeline_compute_combine, None); + self.device.destroy_pipeline(self.data.pipeline_compute_mempos, None); self.device.destroy_pipeline_layout(self.data.pipeline_layout, None); self.device.destroy_render_pass(self.data.render_pass, None); @@ -897,13 +904,13 @@ unsafe fn create_pipeline(device: &Device, data: &mut app_data::AppData) -> Resu .name(b"main\0"); // load the byte data - let compute_bytes = include_bytes!("../shaders/compiled/rt_compute_combine.spv"); + let compute_bytes = include_bytes!("../shaders/compiled/rt_compute_mempos.spv"); // create the shaders - let compute_shader_module_combine = create_shader_module(device, &compute_bytes[..])?; + let compute_shader_module_mempos = create_shader_module(device, &compute_bytes[..])?; //create the shader stage for the compute shader - let compute_stage_combine = vk::PipelineShaderStageCreateInfo::builder() + let compute_stage_mempos = vk::PipelineShaderStageCreateInfo::builder() .stage(vk::ShaderStageFlags::COMPUTE) - .module(compute_shader_module_combine) + .module(compute_shader_module_mempos) .name(b"main\0"); // define input assembly and object type. This is altered when using geometry shader @@ -1062,11 +1069,11 @@ unsafe fn create_pipeline(device: &Device, data: &mut app_data::AppData) -> Resu .stage(compute_stage_grow_three) .layout(data.pipeline_layout); - let info_compute_combine = vk::ComputePipelineCreateInfo::builder() - .stage(compute_stage_combine) + let info_compute_mempos = vk::ComputePipelineCreateInfo::builder() + .stage(compute_stage_mempos) .layout(data.pipeline_layout); - let compute_pipelines = device.create_compute_pipelines(vk::PipelineCache::null(), &[info_compute_rasterize, info_compute_grow_one, info_compute_grow_two, info_compute_grow_three, info_compute_combine], None)?.0; + let compute_pipelines = device.create_compute_pipelines(vk::PipelineCache::null(), &[info_compute_rasterize, info_compute_grow_one, info_compute_grow_two, info_compute_grow_three, info_compute_mempos], None)?.0; data.pipeline_cube = pipelines[0]; data.pipeline_cuboid = pipelines[1]; @@ -1076,7 +1083,7 @@ unsafe fn create_pipeline(device: &Device, data: &mut app_data::AppData) -> Resu data.pipeline_compute_grow_one = compute_pipelines[1]; data.pipeline_compute_grow_two = compute_pipelines[2]; data.pipeline_compute_grow_three = compute_pipelines[3]; - data.pipeline_compute_combine = compute_pipelines[4]; + data.pipeline_compute_mempos = compute_pipelines[4]; device.destroy_shader_module(vert_shader_module_cube, None); device.destroy_shader_module(geo_shader_module_cube, None); @@ -1093,7 +1100,7 @@ unsafe fn create_pipeline(device: &Device, data: &mut app_data::AppData) -> Resu device.destroy_shader_module(compute_shader_module_grow_one, None); device.destroy_shader_module(compute_shader_module_grow_two, None); device.destroy_shader_module(compute_shader_module_grow_three, None); - device.destroy_shader_module(compute_shader_module_combine, None); + device.destroy_shader_module(compute_shader_module_mempos, None); Ok(()) } diff --git a/src/scene/generators.rs b/src/scene/generators.rs index 3b7f372..c628790 100644 --- a/src/scene/generators.rs +++ b/src/scene/generators.rs @@ -127,12 +127,12 @@ pub fn generate_test_scene(scene: &mut Scene, data: &mut AppData) -> Result<(Poi let mut comp = ShapeComposition::new(64); comp.included_shapes.push(Rc::new(RefCell::new(Cone::new(Vector3 { x: 20.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 }, 0.0, 2.5, Vector3 { x: 0.0, y: 10.0, z: 0.0 },Vector3 { x: 0, y: 255, z: 0 }, 64, false)))); comp.excluded_shapes.push(Rc::new(RefCell::new(Cone::new(Vector3 { x: 20.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 }, 0.0, 1.5, Vector3 { x: 0.0, y: 10.0, z: 0.0 },Vector3 { x: 0, y: 255, z: 0 }, 64, false)))); - scene.volumetrics.push(Rc::new(RefCell::new(comp))); + //scene.volumetrics.push(Rc::new(RefCell::new(comp))); let mut comp = ShapeComposition::new(64); comp.included_shapes.push(Rc::new(RefCell::new(Rect::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 }, Vector3 { x: 5.0, y: 10.0, z: 2.0 },Vector3 { x: 0, y: 0, z: 255 }, 64, false)))); comp.excluded_shapes.push(Rc::new(RefCell::new(Rect::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 }, Vector3 { x: 3.0, y: 8.0, z: 2.0 },Vector3 { x: 0, y: 0, z: 255 }, 64, false)))); - scene.volumetrics.push(Rc::new(RefCell::new(comp))); + //scene.volumetrics.push(Rc::new(RefCell::new(comp))); Ok((cgmath::point3(5.0, 5.0, 10.0))) } diff --git a/src/scene/mod.rs b/src/scene/mod.rs index 6fc3b0c..924bed0 100644 --- a/src/scene/mod.rs +++ b/src/scene/mod.rs @@ -227,7 +227,12 @@ impl Scene { let mut compute_task_one_size = 0; let mut compute_task_one_out_size = 0; + let mut target_index = 1; + let mut node_count = 0; for compound in &self.volumetrics { + compound.borrow_mut().target_memory_start = target_index; + target_index += compound.borrow().get_target_buffer_mem_size(); + node_count += compound.borrow().get_num_nodes(); volumetrics_memory = compound.borrow_mut().insert_into_memory(volumetrics_memory, data, &self); compute_task_one_size += compound.borrow().size.pow(2) as usize; compute_task_one_out_size += compound.borrow().size.pow(3) as usize; @@ -238,6 +243,8 @@ impl Scene { data.compute_task_one_size = compute_task_one_size; data.compute_task_one_out_buffer_size = (compute_task_one_out_size * 4) as u64; data.compute_task_one_out_size = compute_task_one_out_size as u64; + data.compute_task_oct_tree_size = target_index as u64; + data.compute_task_oct_tree_nodes = node_count as u64; } pub unsafe fn destroy(&mut self, device: &vulkanalia::Device) { diff --git a/src/scene/volumetrics/mod.rs b/src/scene/volumetrics/mod.rs index 8e7ade9..8797cc3 100644 --- a/src/scene/volumetrics/mod.rs +++ b/src/scene/volumetrics/mod.rs @@ -31,6 +31,7 @@ enum ShapeTypes { #[derive(Clone, Debug)] pub struct ShapeComposition { memory_start: usize, + pub target_memory_start: u32, prev_memory_size: u32, pub size: u32, pub included_shapes: Vec<Rc<RefCell<dyn Volumetrics>>>, @@ -40,7 +41,7 @@ pub struct ShapeComposition { 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 } + Self { memory_start: 0, target_memory_start: 0, prev_memory_size: 0, size: size, included_shapes: vec![], excluded_shapes: vec![], dirty: true } } } @@ -142,6 +143,25 @@ impl Memorizable for ShapeComposition { } } +impl ShapeComposition { + pub fn get_num_nodes(&self) -> u32 { + let mut nodes = 0; + let mut add_size = 1; + let mut size = self.size; + while size >= 2 { + nodes += add_size; + add_size *= 8; + size /= 2; + } + + nodes + } + + pub fn get_target_buffer_mem_size(&self) -> u32 { + self.get_num_nodes() * 9 + } +} + #[derive(Clone, Debug, PartialEq)] pub struct Sphere { pos: Vector3<f32>,