diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index 8a165adf43561b1204490a12afa00d2a3fabdbf4..4a51b24f5c978daebc5116e20b527252c8063d61 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -157,6 +157,19 @@ namespace vkcv
         [[nodiscard]]
         PipelineHandle createGraphicsPipeline(const PipelineConfig &config);
 
+        /**
+         * Creates a basic vulkan compute pipeline using @p shader program and returns it using the @p handle.
+         * Fixed Functions for pipeline are set with standard values.
+         *
+         * @param shader program that hold the compiles compute shader
+         * @param handle a handle to return the created vulkan handle
+         * @return True if pipeline creation was successful, False if not
+         */
+        [[nodiscard]]
+        PipelineHandle createComputePipeline(
+            const ShaderProgram &config, 
+            const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts);
+
         /**
          * Creates a basic vulkan render pass using @p config from the render pass config class and returns it using the @p handle.
          * Fixed Functions for pipeline are set with standard values.
@@ -211,7 +224,7 @@ namespace vkcv
          */
         [[nodiscard]]
         DescriptorSetHandle createDescriptorSet(const std::vector<DescriptorBinding> &bindings);
-		void writeResourceDescription(DescriptorSetHandle handle, size_t setIndex, const DescriptorWrites& writes);
+		void writeDescriptorSet(DescriptorSetHandle handle, const DescriptorWrites& writes);
 
 		DescriptorSet getDescriptorSet(const DescriptorSetHandle handle) const;
 
@@ -228,6 +241,13 @@ namespace vkcv
 			const std::vector<DrawcallInfo> &drawcalls,
 			const std::vector<ImageHandle>  &renderTargets);
 
+		void recordComputeDispatchToCmdStream(
+			CommandStreamHandle cmdStream,
+			PipelineHandle computePipeline,
+			const uint32_t dispatchCount[3],
+			const std::vector<DescriptorSetUsage> &descriptorSetUsages,
+			const PushConstantData& pushConstantData);
+
 		/**
 		 * @brief end recording and present image
 		*/
diff --git a/projects/cmd_sync_test/src/main.cpp b/projects/cmd_sync_test/src/main.cpp
index 3886a53d4127c983e7525c0f6e4ad467129f9ed0..2494793f3b4aff3dfa412ff9bbe27e4550ca8fe0 100644
--- a/projects/cmd_sync_test/src/main.cpp
+++ b/projects/cmd_sync_test/src/main.cpp
@@ -207,7 +207,7 @@ int main(int argc, const char** argv) {
         vkcv::SamplerDescriptorWrite(1, sampler), 
         vkcv::SamplerDescriptorWrite(4, shadowSampler) };
     setWrites.uniformBufferWrites   = { vkcv::UniformBufferDescriptorWrite(2, lightBuffer.getHandle()) };
-	core.writeResourceDescription(descriptorSet, 0, setWrites);
+	core.writeDescriptorSet(descriptorSet, setWrites);
 
 	auto start = std::chrono::system_clock::now();
 	const auto appStartTime = start;
diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp
index 00a77c761e8fe3d67b4724cd0f1ddfa28f3edcb3..15bb872ce21d9042a6e606e791daab54344d128d 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -130,9 +130,9 @@ int main(int argc, const char** argv) {
 	};
 
 	vkcv::DescriptorWrites setWrites;
-	setWrites.sampledImageWrites	= { vkcv::SampledImageDescriptorWrite(0, texture.getHandle()) };
-	setWrites.samplerWrites			= { vkcv::SamplerDescriptorWrite(1, sampler) };
-	core.writeResourceDescription(descriptorSet, 0, setWrites);
+	setWrites.sampledImageWrites    = { vkcv::SampledImageDescriptorWrite(0, texture.getHandle()) };
+	setWrites.samplerWrites         = { vkcv::SamplerDescriptorWrite(1, sampler) };
+	core.writeDescriptorSet(descriptorSet, setWrites);
 
 	vkcv::ImageHandle depthBuffer = core.createImage(vk::Format::eD32Sfloat, windowWidth, windowHeight).getHandle();
 
diff --git a/projects/first_triangle/shaders/comp.spv b/projects/first_triangle/shaders/comp.spv
new file mode 100644
index 0000000000000000000000000000000000000000..b414e36b2bea66dab00746298e536d029091e0fd
Binary files /dev/null and b/projects/first_triangle/shaders/comp.spv differ
diff --git a/projects/first_triangle/shaders/compile.bat b/projects/first_triangle/shaders/compile.bat
index b4521235c40fe5fb163bab874560c2f219b7517f..17743a7c49cdfc6e091c43a42a0adb755a731682 100644
--- a/projects/first_triangle/shaders/compile.bat
+++ b/projects/first_triangle/shaders/compile.bat
@@ -1,3 +1,4 @@
 %VULKAN_SDK%\Bin32\glslc.exe shader.vert -o vert.spv
 %VULKAN_SDK%\Bin32\glslc.exe shader.frag -o frag.spv
+%VULKAN_SDK%\Bin32\glslc.exe shader.comp -o comp.spv
 pause
\ No newline at end of file
diff --git a/projects/first_triangle/shaders/shader.comp b/projects/first_triangle/shaders/shader.comp
new file mode 100644
index 0000000000000000000000000000000000000000..fad6cd0815f2f09bf92dcc3171e2e3723f5466df
--- /dev/null
+++ b/projects/first_triangle/shaders/shader.comp
@@ -0,0 +1,25 @@
+#version 440
+
+layout(std430, binding = 0) buffer testBuffer
+{ 
+    float test1[10];
+    float test2[10];
+    float test3[10];
+};
+
+layout( push_constant ) uniform constants{
+    float pushConstant;
+};
+
+layout(local_size_x = 5) in;
+
+void main(){
+
+    if(gl_GlobalInvocationID.x >= 10){
+        return;
+    }
+
+    test1[gl_GlobalInvocationID.x] = gl_GlobalInvocationID.x;
+    test2[gl_GlobalInvocationID.x] = 69;  // nice!
+    test3[gl_GlobalInvocationID.x] = pushConstant;    
+}
\ No newline at end of file
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index 2ede653ff98e19159e0155b282cab1b309a13816..ca10434bb9e486649411bcaac54c432744a914bb 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -92,6 +92,7 @@ int main(int argc, const char** argv) {
 		return EXIT_FAILURE;
 	}
 
+	// Graphics Pipeline
 	vkcv::ShaderProgram triangleShaderProgram{};
 	triangleShaderProgram.addShader(vkcv::ShaderStage::VERTEX, std::filesystem::path("shaders/vert.spv"));
 	triangleShaderProgram.addShader(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("shaders/frag.spv"));
@@ -115,6 +116,30 @@ int main(int argc, const char** argv) {
 		return EXIT_FAILURE;
 	}
 
+	// Compute Pipeline
+	vkcv::ShaderProgram computeShaderProgram{};
+	computeShaderProgram.addShader(vkcv::ShaderStage::COMPUTE, std::filesystem::path("shaders/comp.spv"));
+	computeShaderProgram.reflectShader(vkcv::ShaderStage::COMPUTE);
+
+	// take care, assuming shader has exactly one descriptor set
+	vkcv::DescriptorSetHandle computeDescriptorSet = core.createDescriptorSet(computeShaderProgram.getReflectedDescriptors()[0]);
+
+	vkcv::PipelineHandle computePipeline = core.createComputePipeline(
+		computeShaderProgram, 
+		{ core.getDescriptorSet(computeDescriptorSet).layout });
+
+	struct ComputeTestBuffer {
+		float test1[10];
+		float test2[10];
+		float test3[10];
+	};
+
+	vkcv::Buffer computeTestBuffer = core.createBuffer<ComputeTestBuffer>(vkcv::BufferType::STORAGE, 1);
+
+	vkcv::DescriptorWrites computeDescriptorWrites;
+	computeDescriptorWrites.storageBufferWrites = { vkcv::StorageBufferDescriptorWrite(0, computeTestBuffer.getHandle()) };
+	core.writeDescriptorSet(computeDescriptorSet, computeDescriptorWrites);
+
 	/*
 	 * BufferHandle triangleVertices = core.createBuffer(vertices);
 	 * BufferHandle triangleIndices = core.createBuffer(indices);
@@ -164,6 +189,17 @@ int main(int argc, const char** argv) {
 			pushConstantData,
 			{ drawcall },
 			{ swapchainInput });
+
+		const uint32_t dispatchSize[3] = { 2, 1, 1 };
+		const float theMeaningOfLife = 42;
+
+		core.recordComputeDispatchToCmdStream(
+			cmdStream,
+			computePipeline,
+			dispatchSize,
+			{ vkcv::DescriptorSetUsage(0, core.getDescriptorSet(computeDescriptorSet).vulkanHandle) },
+			vkcv::PushConstantData((void*)&theMeaningOfLife, sizeof(theMeaningOfLife)));
+
 		core.prepareSwapchainImageForPresent(cmdStream);
 		core.submitCommandStream(cmdStream);
 	    
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index cccf51946ba41ed17b4479d151892e946ff17844..44e7111e1f4941ef2f0f8114ac788d7db4a13b5a 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -103,6 +103,13 @@ namespace vkcv
         return m_PipelineManager->createPipeline(config, *m_PassManager);
     }
 
+    PipelineHandle Core::createComputePipeline(
+        const ShaderProgram &shaderProgram, 
+        const std::vector<vk::DescriptorSetLayout>& descriptorSetLayouts)
+    {
+        return m_PipelineManager->createComputePipeline(shaderProgram, descriptorSetLayouts);
+    }
+
 
     PassHandle Core::createPass(const PassConfig &config)
     {
@@ -300,6 +307,40 @@ namespace vkcv
 		recordCommandsToStream(cmdStreamHandle, submitFunction, finishFunction);
 	}
 
+	void Core::recordComputeDispatchToCmdStream(
+		CommandStreamHandle cmdStreamHandle,
+		PipelineHandle computePipeline,
+		const uint32_t dispatchCount[3],
+		const std::vector<DescriptorSetUsage>& descriptorSetUsages,
+		const PushConstantData& pushConstantData) {
+
+		auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) {
+
+			const auto pipelineLayout = m_PipelineManager->getVkPipelineLayout(computePipeline);
+
+			cmdBuffer.bindPipeline(vk::PipelineBindPoint::eCompute, m_PipelineManager->getVkPipeline(computePipeline));
+			for (const auto& usage : descriptorSetUsages) {
+				cmdBuffer.bindDescriptorSets(
+					vk::PipelineBindPoint::eCompute,
+					pipelineLayout,
+					usage.setLocation,
+					{ usage.vulkanHandle },
+					{});
+			}
+			if (pushConstantData.sizePerDrawcall > 0) {
+				cmdBuffer.pushConstants(
+					pipelineLayout,
+					vk::ShaderStageFlagBits::eCompute,
+					0,
+					pushConstantData.sizePerDrawcall,
+					pushConstantData.data);
+			}
+			cmdBuffer.dispatch(dispatchCount[0], dispatchCount[1], dispatchCount[2]);
+		};
+
+		recordCommandsToStream(cmdStreamHandle, submitFunction, nullptr);
+	}
+
 	void Core::endFrame() {
 		if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) {
 			return;
@@ -404,10 +445,9 @@ namespace vkcv
         return m_DescriptorManager->createDescriptorSet(bindings);
     }
 
-	void Core::writeResourceDescription(DescriptorSetHandle handle, size_t setIndex, const DescriptorWrites &writes) {
-		m_DescriptorManager->writeResourceDescription(
-			handle, 
-			setIndex, 
+	void Core::writeDescriptorSet(DescriptorSetHandle handle, const DescriptorWrites &writes) {
+		m_DescriptorManager->writeDescriptorSet(
+			handle,  
 			writes, 
 			*m_ImageManager, 
 			*m_BufferManager, 
diff --git a/src/vkcv/DescriptorManager.cpp b/src/vkcv/DescriptorManager.cpp
index b805e1367d334d6a2b02a0a19a5a351a5e2da1bf..f591daf90b47b57a758b2b24c7fa87b5c33e3c46 100644
--- a/src/vkcv/DescriptorManager.cpp
+++ b/src/vkcv/DescriptorManager.cpp
@@ -92,9 +92,8 @@ namespace vkcv
 		vk::DescriptorType type;
     };
 
-	void DescriptorManager::writeResourceDescription(
+	void DescriptorManager::writeDescriptorSet(
 		const DescriptorSetHandle	&handle,
-		size_t					setIndex,
 		const DescriptorWrites	&writes,
 		const ImageManager		&imageManager, 
 		const BufferManager		&bufferManager,
diff --git a/src/vkcv/DescriptorManager.hpp b/src/vkcv/DescriptorManager.hpp
index d8607b9312b25e71c7eb4af009efd92b834b40ec..d18be64f3b069af68cecce68f6fa623c81f8dfa4 100644
--- a/src/vkcv/DescriptorManager.hpp
+++ b/src/vkcv/DescriptorManager.hpp
@@ -23,9 +23,8 @@ namespace vkcv
 
         DescriptorSetHandle createDescriptorSet(const std::vector<DescriptorBinding> &descriptorBindings);
 
-		void writeResourceDescription(
+		void writeDescriptorSet(
 			const DescriptorSetHandle	&handle,
-			size_t					setIndex,
 			const DescriptorWrites  &writes,
 			const ImageManager      &imageManager,
 			const BufferManager     &bufferManager,
diff --git a/src/vkcv/PipelineManager.cpp b/src/vkcv/PipelineManager.cpp
index 6572145d34492204b2df1e55028d22c330802ca1..24ac7970d739d46ab7cecca7bb783bb0037c43cb 100644
--- a/src/vkcv/PipelineManager.cpp
+++ b/src/vkcv/PipelineManager.cpp
@@ -193,6 +193,7 @@ namespace vkcv
 			{},
 			(config.m_DescriptorLayouts),
 			(pushConstantRange));
+
         vk::PipelineLayout vkPipelineLayout{};
         if (m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &vkPipelineLayout) != vk::Result::eSuccess)
         {
@@ -325,4 +326,65 @@ namespace vkcv
         return m_Configs.at(id);
     }
 
+    PipelineHandle PipelineManager::createComputePipeline(
+        const ShaderProgram &shaderProgram, 
+        const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts) {
+
+        // Temporally handing over the Shader Program instead of a pipeline config
+        vk::ShaderModule computeModule{};
+        if (createShaderModule(computeModule, shaderProgram, ShaderStage::COMPUTE) != vk::Result::eSuccess)
+            return PipelineHandle();
+
+        vk::PipelineShaderStageCreateInfo pipelineComputeShaderStageInfo(
+                {},
+                vk::ShaderStageFlagBits::eCompute,
+                computeModule,
+                "main",
+                nullptr
+        );
+
+        vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo({}, descriptorSetLayouts);
+
+        const size_t pushConstantSize = shaderProgram.getPushConstantSize();
+        vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eCompute, 0, pushConstantSize);
+        if (pushConstantSize > 0) {
+            pipelineLayoutCreateInfo.setPushConstantRangeCount(1);
+            pipelineLayoutCreateInfo.setPPushConstantRanges(&pushConstantRange);
+        }
+
+        vk::PipelineLayout vkPipelineLayout{};
+        if (m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &vkPipelineLayout) != vk::Result::eSuccess)
+        {
+            m_Device.destroy(computeModule);
+            return PipelineHandle();
+        }
+
+        vk::ComputePipelineCreateInfo computePipelineCreateInfo{};
+        computePipelineCreateInfo.stage = pipelineComputeShaderStageInfo;
+        computePipelineCreateInfo.layout = vkPipelineLayout;
+
+        vk::Pipeline vkPipeline;
+        if (m_Device.createComputePipelines(nullptr, 1, &computePipelineCreateInfo, nullptr, &vkPipeline)!= vk::Result::eSuccess)
+        {
+            m_Device.destroy(computeModule);
+            return PipelineHandle();
+        }
+
+        m_Device.destroy(computeModule);
+
+        const uint64_t id = m_Pipelines.size();
+        m_Pipelines.push_back({ vkPipeline, vkPipelineLayout });
+
+        return PipelineHandle(id, [&](uint64_t id) { destroyPipelineById(id); });
+    }
+
+    // There is an issue for refactoring the Pipeline Manager.
+    // While including Compute Pipeline Creation, some private helper functions where introduced:
+
+    vk::Result PipelineManager::createShaderModule(vk::ShaderModule &module, const ShaderProgram &shaderProgram, const ShaderStage stage)
+    {
+        std::vector<char> code = shaderProgram.getShader(stage).shaderCode;
+        vk::ShaderModuleCreateInfo moduleInfo({}, code.size(), reinterpret_cast<uint32_t*>(code.data()));
+        return m_Device.createShaderModule(&moduleInfo, nullptr, &module);
+    }
 }
\ No newline at end of file
diff --git a/src/vkcv/PipelineManager.hpp b/src/vkcv/PipelineManager.hpp
index e243151f7248c07fa0287bb2eaf698e5080f7f61..634f5f4e6464532306e35fd10d9a1623df6ace16 100644
--- a/src/vkcv/PipelineManager.hpp
+++ b/src/vkcv/PipelineManager.hpp
@@ -21,7 +21,9 @@ namespace vkcv
         std::vector<PipelineConfig> m_Configs;
         
         void destroyPipelineById(uint64_t id);
-        
+
+        vk::Result createShaderModule(vk::ShaderModule &module, const ShaderProgram &shaderProgram, ShaderStage stage);
+
     public:
         PipelineManager() = delete; // no default ctor
         explicit PipelineManager(vk::Device device) noexcept; // ctor
@@ -35,6 +37,10 @@ namespace vkcv
 
         PipelineHandle createPipeline(const PipelineConfig &config, PassManager& passManager);
 
+        PipelineHandle createComputePipeline(
+            const ShaderProgram& shaderProgram,
+            const std::vector<vk::DescriptorSetLayout>& descriptorSetLayouts);
+
         [[nodiscard]]
         vk::Pipeline getVkPipeline(const PipelineHandle &handle) const;