From 8902c2a0e36e0eab7156b91f5aa61438c4fff654 Mon Sep 17 00:00:00 2001
From: zomseffen <steffen@tom.bi>
Date: Thu, 17 Apr 2025 15:47:35 +0200
Subject: [PATCH] grow compute shaders

---
 build.rs                                      |  34 ++---
 shaders/compile.bat                           |   5 +-
 shaders/compile.sh                            |   7 +-
 shaders/compiled/rt_compute.spv               | Bin 37920 -> 0 bytes
 shaders/compiled/rt_compute_grow_one.spv      | Bin 0 -> 7116 bytes
 shaders/compiled/rt_compute_grow_three.spv    | Bin 0 -> 11192 bytes
 shaders/compiled/rt_compute_grow_two.spv      | Bin 0 -> 9304 bytes
 shaders/compiled/rt_compute_rasterize.spv     | Bin 0 -> 39216 bytes
 shaders/rt_compute_grow_one.comp              |  82 +++++++++++
 shaders/rt_compute_grow_three.comp            | 101 +++++++++++++
 shaders/rt_compute_grow_two.comp              |  94 ++++++++++++
 ...compute.comp => rt_compute_rasterize.comp} |  22 +--
 src/app_data.rs                               |  18 ++-
 src/buffer.rs                                 | 135 ++++++++++++++++--
 src/command_buffer.rs                         | 110 +++++++++++++-
 src/main.rs                                   |  96 +++++++++++--
 16 files changed, 648 insertions(+), 56 deletions(-)
 delete mode 100644 shaders/compiled/rt_compute.spv
 create mode 100644 shaders/compiled/rt_compute_grow_one.spv
 create mode 100644 shaders/compiled/rt_compute_grow_three.spv
 create mode 100644 shaders/compiled/rt_compute_grow_two.spv
 create mode 100644 shaders/compiled/rt_compute_rasterize.spv
 create mode 100644 shaders/rt_compute_grow_one.comp
 create mode 100644 shaders/rt_compute_grow_three.comp
 create mode 100644 shaders/rt_compute_grow_two.comp
 rename shaders/{rt_compute.comp => rt_compute_rasterize.comp} (94%)

diff --git a/build.rs b/build.rs
index d21056e..532b465 100644
--- a/build.rs
+++ b/build.rs
@@ -14,26 +14,22 @@ fn main() {
     println!("cargo::rerun-if-changed=shaders/rt_quad.vert");
     println!("cargo::rerun-if-changed=shaders/rt_quad.frag");
 
-    println!("cargo::rerun-if-changed=shaders/rt_compute.comp");
+    println!("cargo::rerun-if-changed=shaders/rt_compute_rasterize.comp");
+    println!("cargo::rerun-if-changed=shaders/rt_compute_grow_one.comp");
+    println!("cargo::rerun-if-changed=shaders/rt_compute_grow_two.comp");
 
-    #[allow(unused_must_use)]
-    std::fs::remove_file("shaders/compiled/geo_cube.spv");
-    #[allow(unused_must_use)]
-    std::fs::remove_file("shaders/compiled/frag_cube.spv");
-    #[allow(unused_must_use)]
-    std::fs::remove_file("shaders/compiled/vert_cube.spv");
-    #[allow(unused_must_use)]
-    std::fs::remove_file("shaders/compiled/geo_cuboid.spv");
-    #[allow(unused_must_use)]
-    std::fs::remove_file("shaders/compiled/frag_cuboid.spv");
-    #[allow(unused_must_use)]
-    std::fs::remove_file("shaders/compiled/vert_cuboid.spv");
-    #[warn(unused_must_use)]
-    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");
+    std::fs::remove_file("shaders/compiled/geo_cube.spv").unwrap_or(());
+    std::fs::remove_file("shaders/compiled/frag_cube.spv").unwrap_or(());
+    std::fs::remove_file("shaders/compiled/vert_cube.spv").unwrap_or(());
+    std::fs::remove_file("shaders/compiled/geo_cuboid.spv").unwrap_or(());
+    std::fs::remove_file("shaders/compiled/frag_cuboid.spv").unwrap_or(());
+    std::fs::remove_file("shaders/compiled/vert_cuboid.spv").unwrap_or(());
+    std::fs::remove_file("shaders/compiled/vert_rt_quad.spv").unwrap_or(());
+    std::fs::remove_file("shaders/compiled/frag_rt_quad.spv").unwrap_or(());
+    std::fs::remove_file("shaders/compiled/rt_compute_rasterize.spv").unwrap_or(());
+    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(());
 
     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 400c217..50c3d62 100644
--- a/shaders/compile.bat
+++ b/shaders/compile.bat
@@ -9,4 +9,7 @@ C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/cuboid.geom -o shaders/compiled/geo
 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_compute.comp -o shaders/compiled/rt_compute.spv
\ No newline at end of file
+C:/VulkanSDK/1.3.280.0/Bin/glslc.exe shaders/rt_compute_rasterize.comp -o shaders/compiled/rt_compute_rasterize.spv
+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
\ No newline at end of file
diff --git a/shaders/compile.sh b/shaders/compile.sh
index 1b139d3..8f37a28 100755
--- a/shaders/compile.sh
+++ b/shaders/compile.sh
@@ -8,4 +8,9 @@ glslc shaders/cuboid.frag -o shaders/compiled/frag_cuboid.spv
 glslc shaders/cuboid.geom -o shaders/compiled/geo_cuboid.spv
 
 glslc shaders/rt_quad.vert -o shaders/compiled/vert_rt_quad.spv
-glslc shaders/rt_quad.frag -o shaders/compiled/frag_rt_quad.spv
\ No newline at end of file
+glslc shaders/rt_quad.frag -o shaders/compiled/frag_rt_quad.spv
+
+glslc shaders/rt_compute_rasterize.comp -o shaders/compiled/rt_compute_rasterize.spv
+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
\ No newline at end of file
diff --git a/shaders/compiled/rt_compute.spv b/shaders/compiled/rt_compute.spv
deleted file mode 100644
index 289f34304a9676a509af1ab4176ed618e2ec55c7..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 37920
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

diff --git a/shaders/compiled/rt_compute_grow_one.spv b/shaders/compiled/rt_compute_grow_one.spv
new file mode 100644
index 0000000000000000000000000000000000000000..82ea0be971467cc84c96ddcbd851106015f6c56c
GIT binary patch
literal 7116
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
b>d}V_z|n`+^bXXF^$y}Z9q;FoPQ(5W=mDDN

literal 0
HcmV?d00001

diff --git a/shaders/compiled/rt_compute_grow_three.spv b/shaders/compiled/rt_compute_grow_three.spv
new file mode 100644
index 0000000000000000000000000000000000000000..1a326caea5fc67c7b274178dab385db84aee2961
GIT binary patch
literal 11192
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
T*YhFYy7ONe^Z5Tk=QaKYr<yo7

literal 0
HcmV?d00001

diff --git a/shaders/compiled/rt_compute_grow_two.spv b/shaders/compiled/rt_compute_grow_two.spv
new file mode 100644
index 0000000000000000000000000000000000000000..136cf1cc67e27c903ca67e60b97961589a257a90
GIT binary patch
literal 9304
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

literal 0
HcmV?d00001

diff --git a/shaders/compiled/rt_compute_rasterize.spv b/shaders/compiled/rt_compute_rasterize.spv
new file mode 100644
index 0000000000000000000000000000000000000000..9ad3d50fe254abd45e6798f712cf9e2c61881ecb
GIT binary patch
literal 39216
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
XO>@E3>w20So|?>SO=|k)@9X{_BoJC}

literal 0
HcmV?d00001

diff --git a/shaders/rt_compute_grow_one.comp b/shaders/rt_compute_grow_one.comp
new file mode 100644
index 0000000..f4161f4
--- /dev/null
+++ b/shaders/rt_compute_grow_one.comp
@@ -0,0 +1,82 @@
+#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_out[];
+};
+
+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];
+        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 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;
+    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;
+    }
+}
\ No newline at end of file
diff --git a/shaders/rt_compute_grow_three.comp b/shaders/rt_compute_grow_three.comp
new file mode 100644
index 0000000..0460631
--- /dev/null
+++ b/shaders/rt_compute_grow_three.comp
@@ -0,0 +1,101 @@
+#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 = 7) readonly buffer SizeBuffer2D {
+   uint grid_size_in[];
+};
+
+layout(binding = 8) buffer SizeBuffer3D {
+   uint grid_out[];
+};
+
+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 - 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;
+    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;
+    }
+}
\ No newline at end of file
diff --git a/shaders/rt_compute_grow_two.comp b/shaders/rt_compute_grow_two.comp
new file mode 100644
index 0000000..c2ec2f6
--- /dev/null
+++ b/shaders/rt_compute_grow_two.comp
@@ -0,0 +1,94 @@
+#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 = 7) buffer SizeBuffer2D {
+   uint grid_out[];
+};
+
+layout(binding = 8) readonly 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 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;
+    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;
+    }
+}
\ No newline at end of file
diff --git a/shaders/rt_compute.comp b/shaders/rt_compute_rasterize.comp
similarity index 94%
rename from shaders/rt_compute.comp
rename to shaders/rt_compute_rasterize.comp
index f0ec353..8603805 100644
--- a/shaders/rt_compute.comp
+++ b/shaders/rt_compute_rasterize.comp
@@ -1,6 +1,5 @@
 #version 450
 
-
 layout(binding = 0) uniform UniformBufferObject {
     mat4 model;
     mat4 geom_rot;
@@ -15,7 +14,7 @@ layout(binding = 3) readonly buffer SceneInfoBuffer {
 };
 
 layout(binding = 4) buffer SceneInfoBuffer2 {
-   uint volumes[];
+   uint grid[];
 };
 
 layout(binding = 5) buffer SizedVertices {
@@ -26,6 +25,10 @@ layout(binding = 6) buffer Indices {
    uint indices[];
 };
 
+layout(binding = 9) buffer transparencies {
+   bool transparent_grid[];
+};
+
 layout (local_size_x = 16, local_size_y = 1, local_size_z = 1) in;
 
 uvec4 unpack_color(uint val) {
@@ -190,6 +193,7 @@ void main() {
     for (uint z=0; z < compound_grid_size; z++) {
         // iterate over the included shapes
         vec3 check_pos = compound_pos + vec3(float(x) * compound_scale, float(y) * compound_scale, float(z) * compound_scale) + mid_offset;
+        uint color_int;
         uvec4 color_roughness;
         bool render = false;
         vec3 color = vec3(0.0, 0.0, 1.0);
@@ -214,9 +218,10 @@ void main() {
                     vec3(0.0, 0.0, 1.0)
                 );
 
-            uvec4 component_color = unpack_color(compounds[component_index + 7]);
+            color_int = compounds[component_index + 7];
+            uvec4 component_color = unpack_color(color_int);
 
-            uint transparent = compounds[component_index + 8];
+            transparent = compounds[component_index + 8] != 0;
 
             if (component_type == 0) {
                 // handle sphere
@@ -292,8 +297,6 @@ void main() {
                 );
             uvec4 color = unpack_color(compounds[component_index + 7]);
 
-            uint transparent = compounds[component_index + 8];
-
             if (component_type == 0) {
                 // handle sphere
                 float radius = uintBitsToFloat(compounds[component_index + 9]);
@@ -344,9 +347,12 @@ 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);
+        } 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;
         }
     }
-
-    //volumes[index] = compounds[index];
 }
\ No newline at end of file
diff --git a/src/app_data.rs b/src/app_data.rs
index 3bcb10b..6469600 100644
--- a/src/app_data.rs
+++ b/src/app_data.rs
@@ -23,7 +23,10 @@ pub struct AppData {
     pub pipeline_cuboid: vk::Pipeline,
     pub pipeline_quad: vk::Pipeline,
 
-    pub pipeline_compute: vk::Pipeline,
+    pub pipeline_compute_rasterize: vk::Pipeline,
+    pub pipeline_compute_grow_one: vk::Pipeline,
+    pub pipeline_compute_grow_two: vk::Pipeline,
+    pub pipeline_compute_grow_three: vk::Pipeline,
 
     pub framebuffers: Vec<vk::Framebuffer>,
     pub command_pool: vk::CommandPool,
@@ -44,8 +47,17 @@ pub struct AppData {
     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 compute_out_storage_buffers_color: Vec<vk::Buffer>,
+    pub compute_out_storage_buffers_memory_color: Vec<vk::DeviceMemory>,
+
+    pub compute_out_storage_buffers_transparent: Vec<vk::Buffer>,
+    pub compute_out_storage_buffers_memory_transparent: Vec<vk::DeviceMemory>,
+
+    pub compute_out_storage_buffers_size_two: Vec<vk::Buffer>,
+    pub compute_out_storage_buffers_memory_size_two: Vec<vk::DeviceMemory>,
+
+    pub compute_out_storage_buffers_size_three: Vec<vk::Buffer>,
+    pub compute_out_storage_buffers_memory_size_three: Vec<vk::DeviceMemory>,
 
     pub compute_out_cuboid_buffers: Vec<vk::Buffer>,
     pub compute_out_cuboid_buffers_memory: Vec<vk::DeviceMemory>,
diff --git a/src/buffer.rs b/src/buffer.rs
index 61ce46d..8374162 100644
--- a/src/buffer.rs
+++ b/src/buffer.rs
@@ -214,7 +214,7 @@ pub unsafe fn create_descriptor_set_layout(
         .descriptor_count(1)
         .stage_flags(vk::ShaderStageFlags::COMPUTE);
     
-    let storage_binding_compute_out = vk::DescriptorSetLayoutBinding::builder()
+    let storage_binding_compute_out_color = vk::DescriptorSetLayoutBinding::builder()
         .binding(4)
         .descriptor_type(vk::DescriptorType::STORAGE_BUFFER)
         .descriptor_count(1)
@@ -232,7 +232,25 @@ pub unsafe fn create_descriptor_set_layout(
         .descriptor_count(1)
         .stage_flags(vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::COMPUTE);
 
-    let bindings = &[ubo_binding, sampler_binding, storage_binding_render, storage_binding_compute_in, storage_binding_compute_out, storage_binding_compute_cuboid_out, storage_binding_compute_cuboid_index_out];
+    let storage_binding_compute_out_size_two = vk::DescriptorSetLayoutBinding::builder()
+        .binding(7)
+        .descriptor_type(vk::DescriptorType::STORAGE_BUFFER)
+        .descriptor_count(1)
+        .stage_flags(vk::ShaderStageFlags::FRAGMENT | vk::ShaderStageFlags::COMPUTE);
+
+    let storage_binding_compute_out_size_three = vk::DescriptorSetLayoutBinding::builder()
+        .binding(8)
+        .descriptor_type(vk::DescriptorType::STORAGE_BUFFER)
+        .descriptor_count(1)
+        .stage_flags(vk::ShaderStageFlags::FRAGMENT | vk::ShaderStageFlags::COMPUTE);
+
+    let storage_binding_compute_out_size_transparent = vk::DescriptorSetLayoutBinding::builder()
+        .binding(9)
+        .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];
     let info = vk::DescriptorSetLayoutCreateInfo::builder()
         .bindings(bindings);
     
@@ -276,8 +294,16 @@ pub unsafe fn create_storage_buffers(
 
     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();
+    data.compute_out_storage_buffers_color.clear();
+    data.compute_out_storage_buffers_memory_color.clear();
+    data.compute_out_storage_buffers_transparent.clear();
+    data.compute_out_storage_buffers_memory_transparent.clear();
+
+    data.compute_out_storage_buffers_size_two.clear();
+    data.compute_out_storage_buffers_memory_size_two.clear();
+
+    data.compute_out_storage_buffers_size_three.clear();
+    data.compute_out_storage_buffers_memory_size_three.clear();
 
     data.compute_out_cuboid_buffers.clear();
     data.compute_out_cuboid_buffers_memory.clear();
@@ -318,8 +344,44 @@ pub unsafe fn create_storage_buffers(
             vk::MemoryPropertyFlags::DEVICE_LOCAL,
         )?;
 
-        data.compute_out_storage_buffers.push(storage_buffer);
-        data.compute_out_storage_buffers_memory.push(storage_buffer_memory);
+        data.compute_out_storage_buffers_color.push(storage_buffer);
+        data.compute_out_storage_buffers_memory_color.push(storage_buffer_memory);
+
+        let (storage_buffer, storage_buffer_memory) = create_buffer(
+            instance,
+            device,
+            data,
+            (size_of::<bool>() * 3) as u64 * data.compute_task_one_out_buffer_size.max(1),
+            vk::BufferUsageFlags::STORAGE_BUFFER,
+            vk::MemoryPropertyFlags::DEVICE_LOCAL,
+        )?;
+
+        data.compute_out_storage_buffers_transparent.push(storage_buffer);
+        data.compute_out_storage_buffers_memory_transparent.push(storage_buffer_memory);
+
+        let (storage_buffer, storage_buffer_memory) = create_buffer(
+            instance,
+            device,
+            data,
+            (size_of::<u32>() * 2) as u64 * data.compute_task_one_out_buffer_size.max(1),
+            vk::BufferUsageFlags::STORAGE_BUFFER,
+            vk::MemoryPropertyFlags::DEVICE_LOCAL,
+        )?;
+
+        data.compute_out_storage_buffers_size_two.push(storage_buffer);
+        data.compute_out_storage_buffers_memory_size_two.push(storage_buffer_memory);
+
+        let (storage_buffer, storage_buffer_memory) = create_buffer(
+            instance,
+            device,
+            data,
+            (size_of::<u32>() * 3) as u64 * data.compute_task_one_out_buffer_size.max(1),
+            vk::BufferUsageFlags::STORAGE_BUFFER,
+            vk::MemoryPropertyFlags::DEVICE_LOCAL,
+        )?;
+
+        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,
@@ -466,7 +528,7 @@ pub unsafe fn create_descriptor_pool(device: &Device, data: &mut app_data::AppDa
         .type_(vk::DescriptorType::STORAGE_BUFFER)
         .descriptor_count(data.swapchain_images.len() as u32);
 
-    let compute_out_storage_size = vk::DescriptorPoolSize::builder()
+    let compute_out_storage_color_size = vk::DescriptorPoolSize::builder()
         .type_(vk::DescriptorType::STORAGE_BUFFER)
         .descriptor_count(data.swapchain_images.len() as u32);
 
@@ -477,8 +539,20 @@ pub unsafe fn create_descriptor_pool(device: &Device, data: &mut app_data::AppDa
     let compute_out_cuboid_index_size = vk::DescriptorPoolSize::builder()
         .type_(vk::DescriptorType::STORAGE_BUFFER)
         .descriptor_count(data.swapchain_images.len() as u32);
+
+    let compute_out_storage_size_two_size = vk::DescriptorPoolSize::builder()
+        .type_(vk::DescriptorType::STORAGE_BUFFER)
+        .descriptor_count(data.swapchain_images.len() as u32);
+
+    let compute_out_storage_size_three_size = vk::DescriptorPoolSize::builder()
+        .type_(vk::DescriptorType::STORAGE_BUFFER)
+        .descriptor_count(data.swapchain_images.len() as u32);
+
+    let compute_out_storage_transparent_size = 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_size, compute_out_cuboid_size, compute_out_cuboid_index_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];
     let info = vk::DescriptorPoolCreateInfo::builder()
         .pool_sizes(pool_sizes)
         .max_sets(data.swapchain_images.len() as u32);
@@ -549,18 +623,57 @@ pub unsafe fn create_descriptor_sets(device: &Device, data: &mut app_data::AppDa
             .buffer_info(storage_info);
 
         let info = vk::DescriptorBufferInfo::builder()
-            .buffer(data.compute_out_storage_buffers[i])
+            .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));
         let storage_info = &[info];
 
-        let storage_write_compute_out = vk::WriteDescriptorSet::builder()
+        let storage_write_compute_out_color = 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);
 
+        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));
+        let storage_info = &[info];
+
+        let storage_write_compute_out_size_two = vk::WriteDescriptorSet::builder()
+            .dst_set(data.descriptor_sets[i])
+            .dst_binding(7)
+            .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_size_three[i])
+            .offset(0)
+            .range((size_of::<u32>() * 3) 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()
+            .dst_set(data.descriptor_sets[i])
+            .dst_binding(8)
+            .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_transparent[i])
+            .offset(0)
+            .range((size_of::<bool>() * 3) as u64 * data.compute_task_one_out_buffer_size.max(1));
+        let storage_info = &[info];
+
+        let storage_write_compute_out_transparent = vk::WriteDescriptorSet::builder()
+            .dst_set(data.descriptor_sets[i])
+            .dst_binding(9)
+            .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)
@@ -589,7 +702,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, storage_write_compute_cuboid_out, storage_write_compute_cuboid_index_out],
+            &[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],
             &[] as &[vk::CopyDescriptorSet],
         );
     }
diff --git a/src/command_buffer.rs b/src/command_buffer.rs
index 583f1e9..3a70d1f 100644
--- a/src/command_buffer.rs
+++ b/src/command_buffer.rs
@@ -60,7 +60,7 @@ 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
+                *command_buffer, vk::PipelineBindPoint::COMPUTE, data.pipeline_compute_rasterize); //todo build own pipeline
 
             device.cmd_bind_descriptor_sets(
                 *command_buffer, 
@@ -92,6 +92,114 @@ pub unsafe fn create_command_buffers(device: &Device, data: &mut app_data::AppDa
                 &[] as &[vk::MemoryBarrier],
                 &[buffer_memory_barrier_index, buffer_memory_barrier_vertex],
                 &[] as &[vk::ImageMemoryBarrier]);
+
+            // compute storage barrier
+            let buffer_memory_barrier_color = vk::BufferMemoryBarrier::builder()
+                .buffer(data.compute_out_storage_buffers_color[i])
+                .src_access_mask(vk::AccessFlags::SHADER_WRITE)
+                .dst_access_mask(vk::AccessFlags::SHADER_READ)
+                .size(vk::WHOLE_SIZE as u64)
+                .build();
+
+            let buffer_memory_barrier_transparent = vk::BufferMemoryBarrier::builder()
+                .buffer(data.compute_out_storage_buffers_transparent[i])
+                .src_access_mask(vk::AccessFlags::SHADER_WRITE)
+                .dst_access_mask(vk::AccessFlags::SHADER_READ)
+                .size(vk::WHOLE_SIZE as u64)
+                .build();
+
+            device.cmd_pipeline_barrier(*command_buffer,
+                vk::PipelineStageFlags::COMPUTE_SHADER,
+                vk::PipelineStageFlags::COMPUTE_SHADER,
+                vk::DependencyFlags::DEVICE_GROUP,
+                &[] as &[vk::MemoryBarrier],
+                &[buffer_memory_barrier_color, buffer_memory_barrier_transparent],
+                &[] as &[vk::ImageMemoryBarrier]);
+            // grow x axis
+            device.cmd_bind_pipeline(
+                *command_buffer, vk::PipelineBindPoint::COMPUTE, data.pipeline_compute_grow_one);
+
+            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 / 16.0).ceil() as u32, 1, 1);
+
+            let buffer_memory_barrier_out = vk::BufferMemoryBarrier::builder()
+                .buffer(data.compute_out_storage_buffers_size_three[i])
+                .src_access_mask(vk::AccessFlags::SHADER_WRITE)
+                .dst_access_mask(vk::AccessFlags::SHADER_READ)
+                .size(vk::WHOLE_SIZE as u64)
+                .build();
+
+            device.cmd_pipeline_barrier(*command_buffer,
+                vk::PipelineStageFlags::COMPUTE_SHADER,
+                vk::PipelineStageFlags::COMPUTE_SHADER,
+                vk::DependencyFlags::DEVICE_GROUP,
+                &[] as &[vk::MemoryBarrier],
+                &[buffer_memory_barrier_out],
+                &[] as &[vk::ImageMemoryBarrier]);
+            // grow y axis
+            device.cmd_bind_pipeline(
+                *command_buffer, vk::PipelineBindPoint::COMPUTE, data.pipeline_compute_grow_two);
+
+            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 / 16.0).ceil() as u32, 1, 1);
+
+            let buffer_memory_barrier_out = vk::BufferMemoryBarrier::builder()
+                .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)
+                .build();
+
+            device.cmd_pipeline_barrier(*command_buffer,
+                vk::PipelineStageFlags::COMPUTE_SHADER,
+                vk::PipelineStageFlags::COMPUTE_SHADER,
+                vk::DependencyFlags::DEVICE_GROUP,
+                &[] as &[vk::MemoryBarrier],
+                &[buffer_memory_barrier_out],
+                &[] as &[vk::ImageMemoryBarrier]);
+
+            // grow z axis
+            device.cmd_bind_pipeline(
+                *command_buffer, vk::PipelineBindPoint::COMPUTE, data.pipeline_compute_grow_three);
+
+            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 / 16.0).ceil() as u32, 1, 1);
+
+            let buffer_memory_barrier_out = vk::BufferMemoryBarrier::builder()
+                .buffer(data.compute_out_storage_buffers_size_three[i])
+                .src_access_mask(vk::AccessFlags::SHADER_WRITE)
+                .dst_access_mask(vk::AccessFlags::SHADER_READ)
+                .size(vk::WHOLE_SIZE as u64)
+                .build();
+
+            device.cmd_pipeline_barrier(*command_buffer,
+                vk::PipelineStageFlags::COMPUTE_SHADER,
+                vk::PipelineStageFlags::COMPUTE_SHADER,
+                vk::DependencyFlags::DEVICE_GROUP,
+                &[] as &[vk::MemoryBarrier],
+                &[buffer_memory_barrier_out],
+                &[] as &[vk::ImageMemoryBarrier]);
         }
         // start render pass
         let clear_values = &[color_clear_value, depth_clear_value];
diff --git a/src/main.rs b/src/main.rs
index 71bae1b..64de5c4 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -420,10 +420,31 @@ impl App {
             .iter()
             .for_each(|m| self.device.free_memory(*m, None));
 
-        self.data.compute_out_storage_buffers
+        self.data.compute_out_storage_buffers_color
             .iter()
             .for_each(|b| self.device.destroy_buffer(*b, None));
-        self.data.compute_out_storage_buffers_memory
+        self.data.compute_out_storage_buffers_memory_color
+            .iter()
+            .for_each(|m| self.device.free_memory(*m, None));
+
+        self.data.compute_out_storage_buffers_transparent
+            .iter()
+            .for_each(|b| self.device.destroy_buffer(*b, None));
+        self.data.compute_out_storage_buffers_memory_transparent
+            .iter()
+            .for_each(|m| self.device.free_memory(*m, None));
+
+        self.data.compute_out_storage_buffers_size_two
+            .iter()
+            .for_each(|b| self.device.destroy_buffer(*b, None));
+        self.data.compute_out_storage_buffers_memory_size_two
+            .iter()
+            .for_each(|m| self.device.free_memory(*m, None));
+
+            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));
 
@@ -449,7 +470,10 @@ impl App {
         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(self.data.pipeline_compute_rasterize, None);
+        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_layout(self.data.pipeline_layout, None);
         self.device.destroy_render_pass(self.data.render_pass, None);
@@ -832,13 +856,43 @@ unsafe fn create_pipeline(device: &Device, data: &mut app_data::AppData) -> Resu
     
     // set up compute shader
     // load the byte data
-    let compute_bytes = include_bytes!("../shaders/compiled/rt_compute.spv");
+    let compute_bytes = include_bytes!("../shaders/compiled/rt_compute_rasterize.spv");
     // create the shaders
-    let compute_shader_module = create_shader_module(device, &compute_bytes[..])?;
+    let compute_shader_module_rasterize = create_shader_module(device, &compute_bytes[..])?;
     //create the shader stage for the compute shader
-    let compute_stage = vk::PipelineShaderStageCreateInfo::builder()
+    let compute_stage_rasterize = vk::PipelineShaderStageCreateInfo::builder()
         .stage(vk::ShaderStageFlags::COMPUTE)
-        .module(compute_shader_module)
+        .module(compute_shader_module_rasterize)
+        .name(b"main\0");
+
+    // load the byte data
+    let compute_bytes = include_bytes!("../shaders/compiled/rt_compute_grow_one.spv");
+    // create the shaders
+    let compute_shader_module_grow_one = create_shader_module(device, &compute_bytes[..])?;
+    //create the shader stage for the compute shader
+    let compute_stage_grow_one = vk::PipelineShaderStageCreateInfo::builder()
+        .stage(vk::ShaderStageFlags::COMPUTE)
+        .module(compute_shader_module_grow_one)
+        .name(b"main\0");
+
+    // load the byte data
+    let compute_bytes = include_bytes!("../shaders/compiled/rt_compute_grow_two.spv");
+    // create the shaders
+    let compute_shader_module_grow_two = create_shader_module(device, &compute_bytes[..])?;
+    //create the shader stage for the compute shader
+    let compute_stage_grow_two = vk::PipelineShaderStageCreateInfo::builder()
+        .stage(vk::ShaderStageFlags::COMPUTE)
+        .module(compute_shader_module_grow_two)
+        .name(b"main\0");
+
+    // load the byte data
+    let compute_bytes = include_bytes!("../shaders/compiled/rt_compute_grow_three.spv");
+    // create the shaders
+    let compute_shader_module_grow_three = create_shader_module(device, &compute_bytes[..])?;
+    //create the shader stage for the compute shader
+    let compute_stage_grow_three = vk::PipelineShaderStageCreateInfo::builder()
+        .stage(vk::ShaderStageFlags::COMPUTE)
+        .module(compute_shader_module_grow_three)
         .name(b"main\0");
 
     // define input assembly and object type. This is altered when using geometry shader
@@ -981,17 +1035,32 @@ 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)
+    let info_compute_rasterize = vk::ComputePipelineCreateInfo::builder()
+        .stage(compute_stage_rasterize)
         .layout(data.pipeline_layout);
 
-    let compute_pipelines = device.create_compute_pipelines(vk::PipelineCache::null(), &[info_compute], None)?.0;
+    let info_compute_grow_one = vk::ComputePipelineCreateInfo::builder()
+        .stage(compute_stage_grow_one)
+        .layout(data.pipeline_layout);
+
+    let info_compute_grow_two = vk::ComputePipelineCreateInfo::builder()
+        .stage(compute_stage_grow_two)
+        .layout(data.pipeline_layout);
+
+    let info_compute_grow_three = vk::ComputePipelineCreateInfo::builder()
+        .stage(compute_stage_grow_three)
+        .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], None)?.0;
 
     data.pipeline_cube = pipelines[0];
     data.pipeline_cuboid = pipelines[1];
     data.pipeline_quad = pipelines[2];
 
-    data.pipeline_compute = compute_pipelines[0];
+    data.pipeline_compute_rasterize = compute_pipelines[0];
+    data.pipeline_compute_grow_one = compute_pipelines[1];
+    data.pipeline_compute_grow_two = compute_pipelines[2];
+    data.pipeline_compute_grow_three = compute_pipelines[3];
 
     device.destroy_shader_module(vert_shader_module_cube, None);
     device.destroy_shader_module(geo_shader_module_cube, None);
@@ -1004,7 +1073,10 @@ 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);
+    device.destroy_shader_module(compute_shader_module_rasterize, None);
+    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);
 
     Ok(())
 }