diff --git a/projects/CMakeLists.txt b/projects/CMakeLists.txt
index c4fde45438e5c8446c6a1d50ceec16f830e8ebfd..8af45df24a4f0541144952a2d326abd6e041ab8d 100644
--- a/projects/CMakeLists.txt
+++ b/projects/CMakeLists.txt
@@ -6,3 +6,5 @@ add_subdirectory(first_scene)
 add_subdirectory(particle_simulation)
 add_subdirectory(voxelization)
 add_subdirectory(mesh_shader)
+add_subdirectory(draw_indirect)
+add_subdirectory(bindless_textures)
diff --git a/projects/bindless_textures/.gitignore b/projects/bindless_textures/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..cd45650aee8ab49ad568556452dde2d9d51d5f13
--- /dev/null
+++ b/projects/bindless_textures/.gitignore
@@ -0,0 +1 @@
+bindless_textures
\ No newline at end of file
diff --git a/projects/bindless_textures/CMakeLists.txt b/projects/bindless_textures/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..08cc636af2495afa3bb69cc7b652cc20eb4fa117
--- /dev/null
+++ b/projects/bindless_textures/CMakeLists.txt
@@ -0,0 +1,28 @@
+cmake_minimum_required(VERSION 3.16)
+project(bindless_textures)
+
+# setting c++ standard for the project
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+# this should fix the execution path to load local files from the project
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+
+# adding source files to the project
+add_executable(bindless_textures src/main.cpp)
+
+# this should fix the execution path to load local files from the project (for MSVC)
+if(MSVC)
+	set_target_properties(bindless_textures PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
+	set_target_properties(bindless_textures PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
+    
+    # in addition to setting the output directory, the working directory has to be set
+	# by default visual studio sets the working directory to the build directory, when using the debugger
+	set_target_properties(bindless_textures PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
+endif()
+
+# including headers of dependencies and the VkCV framework
+target_include_directories(bindless_textures SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_asset_loader_include} ${vkcv_camera_include} ${vkcv_shader_compiler_include})
+
+# linking with libraries from all dependencies and the VkCV framework
+target_link_libraries(bindless_textures vkcv ${vkcv_libraries} vkcv_asset_loader ${vkcv_asset_loader_libraries} vkcv_camera vkcv_shader_compiler)
diff --git a/projects/bindless_textures/resources/Szene/Szene.bin b/projects/bindless_textures/resources/Szene/Szene.bin
new file mode 100644
index 0000000000000000000000000000000000000000..c87d27637516b0bbf864251dd162773f5cc53e06
--- /dev/null
+++ b/projects/bindless_textures/resources/Szene/Szene.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ee4742718f720d589a2a03f5d879f8c50ba9057718d191a43b046eaa9071080d
+size 70328
diff --git a/projects/bindless_textures/resources/Szene/Szene.gltf b/projects/bindless_textures/resources/Szene/Szene.gltf
new file mode 100644
index 0000000000000000000000000000000000000000..e5a32b29af5d0a2ac5f497e60b4b92c1873e1df9
--- /dev/null
+++ b/projects/bindless_textures/resources/Szene/Szene.gltf
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:75ba834118792ebbacf528a1690c7d04df4b4c8122b9f99a9aa9a9d075d2c86a
+size 7421
diff --git a/projects/bindless_textures/resources/Szene/boards2_vcyc.jpg b/projects/bindless_textures/resources/Szene/boards2_vcyc.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..2636039e272289c0fba3fa2d88a060b857501248
--- /dev/null
+++ b/projects/bindless_textures/resources/Szene/boards2_vcyc.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:cca33a6e58ddd1b37a6e6853a9aa0e7b15ca678937119194752393dd2a0a0564
+size 1192476
diff --git a/projects/bindless_textures/resources/Szene/boards2_vcyc_jpg.jpg b/projects/bindless_textures/resources/Szene/boards2_vcyc_jpg.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..2636039e272289c0fba3fa2d88a060b857501248
--- /dev/null
+++ b/projects/bindless_textures/resources/Szene/boards2_vcyc_jpg.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:cca33a6e58ddd1b37a6e6853a9aa0e7b15ca678937119194752393dd2a0a0564
+size 1192476
diff --git a/projects/bindless_textures/resources/cube/boards2_vcyc_jpg.jpg b/projects/bindless_textures/resources/cube/boards2_vcyc_jpg.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..2636039e272289c0fba3fa2d88a060b857501248
--- /dev/null
+++ b/projects/bindless_textures/resources/cube/boards2_vcyc_jpg.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:cca33a6e58ddd1b37a6e6853a9aa0e7b15ca678937119194752393dd2a0a0564
+size 1192476
diff --git a/projects/bindless_textures/resources/cube/cube.bin b/projects/bindless_textures/resources/cube/cube.bin
new file mode 100644
index 0000000000000000000000000000000000000000..3303cd8635848bee18e10ab8754d5e4e7218db92
--- /dev/null
+++ b/projects/bindless_textures/resources/cube/cube.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9bb9b6b8bbe50a0aaa517057f245ee844f80afa7426dacb2aed4128f71629ce4
+size 840
diff --git a/projects/bindless_textures/resources/cube/cube.blend b/projects/bindless_textures/resources/cube/cube.blend
new file mode 100644
index 0000000000000000000000000000000000000000..62ccb2c742094bcfb5ed194ab905bffae86bfd65
--- /dev/null
+++ b/projects/bindless_textures/resources/cube/cube.blend
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a6c1e245f259c610528c9485db6688928faac0ab2addee9e3c2dde7740e4dd09
+size 774920
diff --git a/projects/bindless_textures/resources/cube/cube.blend1 b/projects/bindless_textures/resources/cube/cube.blend1
new file mode 100644
index 0000000000000000000000000000000000000000..13f21dcca218d7bc7a07a8a9682b5e1d9e607736
--- /dev/null
+++ b/projects/bindless_textures/resources/cube/cube.blend1
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f4496f423569b8ca81f3b3a55fad00f925557e0193fb9dbe6cdce7e71fb48f7b
+size 774920
diff --git a/projects/bindless_textures/resources/cube/cube.glb b/projects/bindless_textures/resources/cube/cube.glb
new file mode 100644
index 0000000000000000000000000000000000000000..66a42c65e71dcf375e04cc378256024dd3c7834d
--- /dev/null
+++ b/projects/bindless_textures/resources/cube/cube.glb
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:198568b715f397d78f7c358c0f709a419e7fd677e54cdec7c19f71b5ed264897
+size 1194508
diff --git a/projects/bindless_textures/resources/cube/cube.gltf b/projects/bindless_textures/resources/cube/cube.gltf
new file mode 100644
index 0000000000000000000000000000000000000000..428176144843dd06c78fe1d11a6392a0ea02b22d
--- /dev/null
+++ b/projects/bindless_textures/resources/cube/cube.gltf
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f82f455647a84ca6242882ae26a79a499d3ce594f8de317ab89488c5b79721ac
+size 2823
diff --git a/projects/bindless_textures/resources/shaders/shader.frag b/projects/bindless_textures/resources/shaders/shader.frag
new file mode 100644
index 0000000000000000000000000000000000000000..71a1de69c57c0d7b7d4665095410e7acaf8dbd62
--- /dev/null
+++ b/projects/bindless_textures/resources/shaders/shader.frag
@@ -0,0 +1,14 @@
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(location = 0) in vec3 passNormal;
+layout(location = 1) in vec2 passUV;
+
+layout(location = 0) out vec3 outColor;
+
+layout(set=0, binding=0) uniform texture2D  meshTexture;
+layout(set=0, binding=1) uniform sampler    textureSampler;
+
+void main()	{
+	outColor = texture(sampler2D(meshTexture, textureSampler), passUV).rgb;
+}
\ No newline at end of file
diff --git a/projects/bindless_textures/resources/shaders/shader.vert b/projects/bindless_textures/resources/shaders/shader.vert
new file mode 100644
index 0000000000000000000000000000000000000000..76855152253b48b7400f016d063ed4f0e507435e
--- /dev/null
+++ b/projects/bindless_textures/resources/shaders/shader.vert
@@ -0,0 +1,19 @@
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(location = 0) in vec3 inPosition;
+layout(location = 1) in vec3 inNormal;
+layout(location = 2) in vec2 inUV;
+
+layout(location = 0) out vec3 passNormal;
+layout(location = 1) out vec2 passUV;
+
+layout( push_constant ) uniform constants{
+    mat4 mvp;
+};
+
+void main()	{
+	gl_Position = mvp * vec4(inPosition, 1.0);
+	passNormal  = inNormal;
+    passUV      = inUV;
+}
\ No newline at end of file
diff --git a/projects/bindless_textures/resources/triangle/Triangle.bin b/projects/bindless_textures/resources/triangle/Triangle.bin
new file mode 100644
index 0000000000000000000000000000000000000000..57f26ad96592b64377e6aa93823d96a94e6c5022
--- /dev/null
+++ b/projects/bindless_textures/resources/triangle/Triangle.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:412ebd5f7242c266b4957e7e26be13aa331dbcb7bbb854ab334a2437ae8ed959
+size 104
diff --git a/projects/bindless_textures/resources/triangle/Triangle.blend b/projects/bindless_textures/resources/triangle/Triangle.blend
new file mode 100644
index 0000000000000000000000000000000000000000..2421dc5e1bb029d73a9ec09cc4530c5196851fd7
--- /dev/null
+++ b/projects/bindless_textures/resources/triangle/Triangle.blend
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:387e544df173219fbf292a64a6656d1d782bbf71a5a9e9fdef0a308f47b05477
+size 758144
diff --git a/projects/bindless_textures/resources/triangle/Triangle.glb b/projects/bindless_textures/resources/triangle/Triangle.glb
new file mode 100644
index 0000000000000000000000000000000000000000..4148620cd6af0dadbc791aa1c52bb5431a40884b
--- /dev/null
+++ b/projects/bindless_textures/resources/triangle/Triangle.glb
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f4be087a605212d139416b5352a018283b26b99260cbcddb7013a1beeb331227
+size 980
diff --git a/projects/bindless_textures/resources/triangle/Triangle.gltf b/projects/bindless_textures/resources/triangle/Triangle.gltf
new file mode 100644
index 0000000000000000000000000000000000000000..a188e6ee16a5e8486cf307c7bda8cfd99bdbeea6
--- /dev/null
+++ b/projects/bindless_textures/resources/triangle/Triangle.gltf
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d5fc354e040f79cff329e919677b194c75e3a522c6406f75c1108ad9575f12ec
+size 2202
diff --git a/projects/bindless_textures/src/main.cpp b/projects/bindless_textures/src/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..731d3e56975ff0cd2d8e6d503a19d56de1b922fe
--- /dev/null
+++ b/projects/bindless_textures/src/main.cpp
@@ -0,0 +1,219 @@
+#include <iostream>
+#include <vkcv/Core.hpp>
+#include <GLFW/glfw3.h>
+#include <vkcv/camera/CameraManager.hpp>
+#include <chrono>
+#include <vkcv/asset/asset_loader.hpp>
+#include <vkcv/shader/GLSLCompiler.hpp>
+
+int main(int argc, const char** argv) {
+	const char* applicationName = "First Mesh";
+
+	uint32_t windowWidth = 800;
+	uint32_t windowHeight = 600;
+
+	vkcv::Window window = vkcv::Window::create(
+		applicationName,
+		windowWidth,
+		windowHeight,
+		true
+	);
+
+	vkcv::Core core = vkcv::Core::create(
+		window,
+		applicationName,
+		VK_MAKE_VERSION(0, 0, 1),
+		{ vk::QueueFlagBits::eGraphics ,vk::QueueFlagBits::eCompute , vk::QueueFlagBits::eTransfer },
+		{},
+		{ "VK_KHR_swapchain" }
+	);
+
+	vkcv::asset::Scene mesh;
+
+	const char* path = argc > 1 ? argv[1] : "resources/cube/cube.gltf";
+	int result = vkcv::asset::loadScene(path, mesh);
+
+	if (result == 1) {
+		std::cout << "Mesh loading successful!" << std::endl;
+	} else {
+		std::cerr << "Mesh loading failed: " << result << std::endl;
+		return 1;
+	}
+
+	assert(!mesh.vertexGroups.empty());
+	auto vertexBuffer = core.createBuffer<uint8_t>(
+			vkcv::BufferType::VERTEX,
+			mesh.vertexGroups[0].vertexBuffer.data.size(),
+			vkcv::BufferMemoryType::DEVICE_LOCAL
+	);
+	
+	vertexBuffer.fill(mesh.vertexGroups[0].vertexBuffer.data);
+
+	auto indexBuffer = core.createBuffer<uint8_t>(
+			vkcv::BufferType::INDEX,
+			mesh.vertexGroups[0].indexBuffer.data.size(),
+			vkcv::BufferMemoryType::DEVICE_LOCAL
+	);
+	
+	indexBuffer.fill(mesh.vertexGroups[0].indexBuffer.data);
+
+	// an example attachment for passes that output to the window
+	const vkcv::AttachmentDescription present_color_attachment(
+		vkcv::AttachmentOperation::STORE,
+		vkcv::AttachmentOperation::CLEAR,
+		core.getSwapchain().getFormat()
+	);
+	
+	const vkcv::AttachmentDescription depth_attachment(
+			vkcv::AttachmentOperation::STORE,
+			vkcv::AttachmentOperation::CLEAR,
+			vk::Format::eD32Sfloat
+	);
+
+	vkcv::PassConfig firstMeshPassDefinition({ present_color_attachment, depth_attachment });
+	vkcv::PassHandle firstMeshPass = core.createPass(firstMeshPassDefinition);
+
+	if (!firstMeshPass) {
+		std::cerr << "Error. Could not create renderpass. Exiting." << std::endl;
+		return EXIT_FAILURE;
+	}
+
+	vkcv::ShaderProgram firstMeshProgram;
+	vkcv::shader::GLSLCompiler compiler;
+	
+	compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("resources/shaders/shader.vert"),
+					 [&firstMeshProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
+		firstMeshProgram.addShader(shaderStage, path);
+	});
+	
+	compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("resources/shaders/shader.frag"),
+					 [&firstMeshProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
+		firstMeshProgram.addShader(shaderStage, path);
+	});
+ 
+	auto& attributes = mesh.vertexGroups[0].vertexBuffer.attributes;
+
+	
+	std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) {
+		return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type);
+	});
+
+    const std::vector<vkcv::VertexAttachment> vertexAttachments = firstMeshProgram.getVertexAttachments();
+	std::vector<vkcv::VertexBinding> bindings;
+	for (size_t i = 0; i < vertexAttachments.size(); i++) {
+		bindings.push_back(vkcv::VertexBinding(i, { vertexAttachments[i] }));
+	}
+	
+	const vkcv::VertexLayout firstMeshLayout (bindings);
+
+	uint32_t setID = 0;
+	std::vector<vkcv::DescriptorBinding> descriptorBindings = { firstMeshProgram.getReflectedDescriptors()[setID] };
+	vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorBindings);
+
+	const vkcv::PipelineConfig firstMeshPipelineConfig {
+        firstMeshProgram,
+        UINT32_MAX,
+        UINT32_MAX,
+        firstMeshPass,
+        {firstMeshLayout},
+		{ core.getDescriptorSet(descriptorSet).layout },
+		true
+	};
+	vkcv::PipelineHandle firstMeshPipeline = core.createGraphicsPipeline(firstMeshPipelineConfig);
+	
+	if (!firstMeshPipeline) {
+		std::cerr << "Error. Could not create graphics pipeline. Exiting." << std::endl;
+		return EXIT_FAILURE;
+	}
+	
+	if (mesh.textures.empty()) {
+		std::cerr << "Error. No textures found. Exiting." << std::endl;
+		return EXIT_FAILURE;
+	}
+	
+	vkcv::asset::Texture &tex = mesh.textures[0];
+	vkcv::Image texture = core.createImage(vk::Format::eR8G8B8A8Srgb, tex.w, tex.h);
+	texture.fill(tex.data.data());
+	texture.generateMipChainImmediate();
+	texture.switchLayout(vk::ImageLayout::eShaderReadOnlyOptimal);
+
+	vkcv::SamplerHandle sampler = core.createSampler(
+		vkcv::SamplerFilterType::LINEAR,
+		vkcv::SamplerFilterType::LINEAR,
+		vkcv::SamplerMipmapMode::LINEAR,
+		vkcv::SamplerAddressMode::REPEAT
+	);
+
+	const std::vector<vkcv::VertexBufferBinding> vertexBufferBindings = {
+		vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[0].offset), vertexBuffer.getVulkanHandle()),
+		vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[1].offset), vertexBuffer.getVulkanHandle()),
+		vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[2].offset), vertexBuffer.getVulkanHandle()) };
+
+	vkcv::DescriptorWrites 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, 1, false).getHandle();
+
+	const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
+
+	const vkcv::Mesh renderMesh(vertexBufferBindings, indexBuffer.getVulkanHandle(), mesh.vertexGroups[0].numIndices);
+
+	vkcv::DescriptorSetUsage    descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle);
+	vkcv::DrawcallInfo          drawcall(renderMesh, { descriptorUsage },1);
+
+    vkcv::camera::CameraManager cameraManager(window);
+    uint32_t camIndex0 = cameraManager.addCamera(vkcv::camera::ControllerType::PILOT);
+	uint32_t camIndex1 = cameraManager.addCamera(vkcv::camera::ControllerType::TRACKBALL);
+	
+	cameraManager.getCamera(camIndex0).setPosition(glm::vec3(0, 0, -3));
+
+    auto start = std::chrono::system_clock::now();
+    
+	while (window.isWindowOpen()) {
+        vkcv::Window::pollEvents();
+		
+		if(window.getHeight() == 0 || window.getWidth() == 0)
+			continue;
+		
+		uint32_t swapchainWidth, swapchainHeight;
+		if (!core.beginFrame(swapchainWidth, swapchainHeight)) {
+			continue;
+		}
+		
+		if ((swapchainWidth != windowWidth) || ((swapchainHeight != windowHeight))) {
+			depthBuffer = core.createImage(vk::Format::eD32Sfloat, swapchainWidth, swapchainHeight).getHandle();
+			
+			windowWidth = swapchainWidth;
+			windowHeight = swapchainHeight;
+		}
+  
+		auto end = std::chrono::system_clock::now();
+		auto deltatime = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
+		
+		start = end;
+		cameraManager.update(0.000001 * static_cast<double>(deltatime.count()));
+        glm::mat4 mvp = cameraManager.getActiveCamera().getMVP();
+
+		vkcv::PushConstants pushConstants (sizeof(glm::mat4));
+		pushConstants.appendDrawcall(mvp);
+
+		const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer };
+		auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
+
+		core.recordDrawcallsToCmdStream(
+			cmdStream,
+			firstMeshPass,
+			firstMeshPipeline,
+			pushConstants,
+			{ drawcall },
+			renderTargets);
+		core.prepareSwapchainImageForPresent(cmdStream);
+		core.submitCommandStream(cmdStream);
+		core.endFrame();
+	}
+	
+	return 0;
+}
diff --git a/projects/draw_indirect/.gitignore b/projects/draw_indirect/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..071dd05c8a5ba569a5a5676358e67166f94790ff
--- /dev/null
+++ b/projects/draw_indirect/.gitignore
@@ -0,0 +1 @@
+draw_indirect
\ No newline at end of file
diff --git a/projects/draw_indirect/CMakeLists.txt b/projects/draw_indirect/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..01f95ccbcfb40cffc96d6d8272494f695192cced
--- /dev/null
+++ b/projects/draw_indirect/CMakeLists.txt
@@ -0,0 +1,28 @@
+cmake_minimum_required(VERSION 3.16)
+project(draw_indirect)
+
+# setting c++ standard for the project
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+# this should fix the execution path to load local files from the project
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+
+# adding source files to the project
+add_executable(draw_indirect src/main.cpp)
+
+# this should fix the execution path to load local files from the project (for MSVC)
+if(MSVC)
+	set_target_properties(draw_indirect PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
+	set_target_properties(draw_indirect PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
+    
+    # in addition to setting the output directory, the working directory has to be set
+	# by default visual studio sets the working directory to the build directory, when using the debugger
+	set_target_properties(draw_indirect PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
+endif()
+
+# including headers of dependencies and the VkCV framework
+target_include_directories(draw_indirect SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_asset_loader_include} ${vkcv_camera_include} ${vkcv_shader_compiler_include})
+
+# linking with libraries from all dependencies and the VkCV framework
+target_link_libraries(draw_indirect vkcv ${vkcv_libraries} vkcv_asset_loader ${vkcv_asset_loader_libraries} vkcv_camera vkcv_shader_compiler)
diff --git a/projects/draw_indirect/resources/Szene/Szene.bin b/projects/draw_indirect/resources/Szene/Szene.bin
new file mode 100644
index 0000000000000000000000000000000000000000..c87d27637516b0bbf864251dd162773f5cc53e06
--- /dev/null
+++ b/projects/draw_indirect/resources/Szene/Szene.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ee4742718f720d589a2a03f5d879f8c50ba9057718d191a43b046eaa9071080d
+size 70328
diff --git a/projects/draw_indirect/resources/Szene/Szene.gltf b/projects/draw_indirect/resources/Szene/Szene.gltf
new file mode 100644
index 0000000000000000000000000000000000000000..e5a32b29af5d0a2ac5f497e60b4b92c1873e1df9
--- /dev/null
+++ b/projects/draw_indirect/resources/Szene/Szene.gltf
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:75ba834118792ebbacf528a1690c7d04df4b4c8122b9f99a9aa9a9d075d2c86a
+size 7421
diff --git a/projects/draw_indirect/resources/Szene/boards2_vcyc.jpg b/projects/draw_indirect/resources/Szene/boards2_vcyc.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..2636039e272289c0fba3fa2d88a060b857501248
--- /dev/null
+++ b/projects/draw_indirect/resources/Szene/boards2_vcyc.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:cca33a6e58ddd1b37a6e6853a9aa0e7b15ca678937119194752393dd2a0a0564
+size 1192476
diff --git a/projects/draw_indirect/resources/Szene/boards2_vcyc_jpg.jpg b/projects/draw_indirect/resources/Szene/boards2_vcyc_jpg.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..2636039e272289c0fba3fa2d88a060b857501248
--- /dev/null
+++ b/projects/draw_indirect/resources/Szene/boards2_vcyc_jpg.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:cca33a6e58ddd1b37a6e6853a9aa0e7b15ca678937119194752393dd2a0a0564
+size 1192476
diff --git a/projects/draw_indirect/resources/cube/boards2_vcyc_jpg.jpg b/projects/draw_indirect/resources/cube/boards2_vcyc_jpg.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..2636039e272289c0fba3fa2d88a060b857501248
--- /dev/null
+++ b/projects/draw_indirect/resources/cube/boards2_vcyc_jpg.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:cca33a6e58ddd1b37a6e6853a9aa0e7b15ca678937119194752393dd2a0a0564
+size 1192476
diff --git a/projects/draw_indirect/resources/cube/cube.bin b/projects/draw_indirect/resources/cube/cube.bin
new file mode 100644
index 0000000000000000000000000000000000000000..3303cd8635848bee18e10ab8754d5e4e7218db92
--- /dev/null
+++ b/projects/draw_indirect/resources/cube/cube.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9bb9b6b8bbe50a0aaa517057f245ee844f80afa7426dacb2aed4128f71629ce4
+size 840
diff --git a/projects/draw_indirect/resources/cube/cube.blend b/projects/draw_indirect/resources/cube/cube.blend
new file mode 100644
index 0000000000000000000000000000000000000000..62ccb2c742094bcfb5ed194ab905bffae86bfd65
--- /dev/null
+++ b/projects/draw_indirect/resources/cube/cube.blend
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a6c1e245f259c610528c9485db6688928faac0ab2addee9e3c2dde7740e4dd09
+size 774920
diff --git a/projects/draw_indirect/resources/cube/cube.blend1 b/projects/draw_indirect/resources/cube/cube.blend1
new file mode 100644
index 0000000000000000000000000000000000000000..13f21dcca218d7bc7a07a8a9682b5e1d9e607736
--- /dev/null
+++ b/projects/draw_indirect/resources/cube/cube.blend1
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f4496f423569b8ca81f3b3a55fad00f925557e0193fb9dbe6cdce7e71fb48f7b
+size 774920
diff --git a/projects/draw_indirect/resources/cube/cube.glb b/projects/draw_indirect/resources/cube/cube.glb
new file mode 100644
index 0000000000000000000000000000000000000000..66a42c65e71dcf375e04cc378256024dd3c7834d
--- /dev/null
+++ b/projects/draw_indirect/resources/cube/cube.glb
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:198568b715f397d78f7c358c0f709a419e7fd677e54cdec7c19f71b5ed264897
+size 1194508
diff --git a/projects/draw_indirect/resources/cube/cube.gltf b/projects/draw_indirect/resources/cube/cube.gltf
new file mode 100644
index 0000000000000000000000000000000000000000..428176144843dd06c78fe1d11a6392a0ea02b22d
--- /dev/null
+++ b/projects/draw_indirect/resources/cube/cube.gltf
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f82f455647a84ca6242882ae26a79a499d3ce594f8de317ab89488c5b79721ac
+size 2823
diff --git a/projects/draw_indirect/resources/shaders/shader.frag b/projects/draw_indirect/resources/shaders/shader.frag
new file mode 100644
index 0000000000000000000000000000000000000000..71a1de69c57c0d7b7d4665095410e7acaf8dbd62
--- /dev/null
+++ b/projects/draw_indirect/resources/shaders/shader.frag
@@ -0,0 +1,14 @@
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(location = 0) in vec3 passNormal;
+layout(location = 1) in vec2 passUV;
+
+layout(location = 0) out vec3 outColor;
+
+layout(set=0, binding=0) uniform texture2D  meshTexture;
+layout(set=0, binding=1) uniform sampler    textureSampler;
+
+void main()	{
+	outColor = texture(sampler2D(meshTexture, textureSampler), passUV).rgb;
+}
\ No newline at end of file
diff --git a/projects/draw_indirect/resources/shaders/shader.vert b/projects/draw_indirect/resources/shaders/shader.vert
new file mode 100644
index 0000000000000000000000000000000000000000..76855152253b48b7400f016d063ed4f0e507435e
--- /dev/null
+++ b/projects/draw_indirect/resources/shaders/shader.vert
@@ -0,0 +1,19 @@
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(location = 0) in vec3 inPosition;
+layout(location = 1) in vec3 inNormal;
+layout(location = 2) in vec2 inUV;
+
+layout(location = 0) out vec3 passNormal;
+layout(location = 1) out vec2 passUV;
+
+layout( push_constant ) uniform constants{
+    mat4 mvp;
+};
+
+void main()	{
+	gl_Position = mvp * vec4(inPosition, 1.0);
+	passNormal  = inNormal;
+    passUV      = inUV;
+}
\ No newline at end of file
diff --git a/projects/draw_indirect/resources/triangle/Triangle.bin b/projects/draw_indirect/resources/triangle/Triangle.bin
new file mode 100644
index 0000000000000000000000000000000000000000..57f26ad96592b64377e6aa93823d96a94e6c5022
--- /dev/null
+++ b/projects/draw_indirect/resources/triangle/Triangle.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:412ebd5f7242c266b4957e7e26be13aa331dbcb7bbb854ab334a2437ae8ed959
+size 104
diff --git a/projects/draw_indirect/resources/triangle/Triangle.blend b/projects/draw_indirect/resources/triangle/Triangle.blend
new file mode 100644
index 0000000000000000000000000000000000000000..2421dc5e1bb029d73a9ec09cc4530c5196851fd7
--- /dev/null
+++ b/projects/draw_indirect/resources/triangle/Triangle.blend
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:387e544df173219fbf292a64a6656d1d782bbf71a5a9e9fdef0a308f47b05477
+size 758144
diff --git a/projects/draw_indirect/resources/triangle/Triangle.glb b/projects/draw_indirect/resources/triangle/Triangle.glb
new file mode 100644
index 0000000000000000000000000000000000000000..4148620cd6af0dadbc791aa1c52bb5431a40884b
--- /dev/null
+++ b/projects/draw_indirect/resources/triangle/Triangle.glb
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f4be087a605212d139416b5352a018283b26b99260cbcddb7013a1beeb331227
+size 980
diff --git a/projects/draw_indirect/resources/triangle/Triangle.gltf b/projects/draw_indirect/resources/triangle/Triangle.gltf
new file mode 100644
index 0000000000000000000000000000000000000000..a188e6ee16a5e8486cf307c7bda8cfd99bdbeea6
--- /dev/null
+++ b/projects/draw_indirect/resources/triangle/Triangle.gltf
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d5fc354e040f79cff329e919677b194c75e3a522c6406f75c1108ad9575f12ec
+size 2202
diff --git a/projects/draw_indirect/src/main.cpp b/projects/draw_indirect/src/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..731d3e56975ff0cd2d8e6d503a19d56de1b922fe
--- /dev/null
+++ b/projects/draw_indirect/src/main.cpp
@@ -0,0 +1,219 @@
+#include <iostream>
+#include <vkcv/Core.hpp>
+#include <GLFW/glfw3.h>
+#include <vkcv/camera/CameraManager.hpp>
+#include <chrono>
+#include <vkcv/asset/asset_loader.hpp>
+#include <vkcv/shader/GLSLCompiler.hpp>
+
+int main(int argc, const char** argv) {
+	const char* applicationName = "First Mesh";
+
+	uint32_t windowWidth = 800;
+	uint32_t windowHeight = 600;
+
+	vkcv::Window window = vkcv::Window::create(
+		applicationName,
+		windowWidth,
+		windowHeight,
+		true
+	);
+
+	vkcv::Core core = vkcv::Core::create(
+		window,
+		applicationName,
+		VK_MAKE_VERSION(0, 0, 1),
+		{ vk::QueueFlagBits::eGraphics ,vk::QueueFlagBits::eCompute , vk::QueueFlagBits::eTransfer },
+		{},
+		{ "VK_KHR_swapchain" }
+	);
+
+	vkcv::asset::Scene mesh;
+
+	const char* path = argc > 1 ? argv[1] : "resources/cube/cube.gltf";
+	int result = vkcv::asset::loadScene(path, mesh);
+
+	if (result == 1) {
+		std::cout << "Mesh loading successful!" << std::endl;
+	} else {
+		std::cerr << "Mesh loading failed: " << result << std::endl;
+		return 1;
+	}
+
+	assert(!mesh.vertexGroups.empty());
+	auto vertexBuffer = core.createBuffer<uint8_t>(
+			vkcv::BufferType::VERTEX,
+			mesh.vertexGroups[0].vertexBuffer.data.size(),
+			vkcv::BufferMemoryType::DEVICE_LOCAL
+	);
+	
+	vertexBuffer.fill(mesh.vertexGroups[0].vertexBuffer.data);
+
+	auto indexBuffer = core.createBuffer<uint8_t>(
+			vkcv::BufferType::INDEX,
+			mesh.vertexGroups[0].indexBuffer.data.size(),
+			vkcv::BufferMemoryType::DEVICE_LOCAL
+	);
+	
+	indexBuffer.fill(mesh.vertexGroups[0].indexBuffer.data);
+
+	// an example attachment for passes that output to the window
+	const vkcv::AttachmentDescription present_color_attachment(
+		vkcv::AttachmentOperation::STORE,
+		vkcv::AttachmentOperation::CLEAR,
+		core.getSwapchain().getFormat()
+	);
+	
+	const vkcv::AttachmentDescription depth_attachment(
+			vkcv::AttachmentOperation::STORE,
+			vkcv::AttachmentOperation::CLEAR,
+			vk::Format::eD32Sfloat
+	);
+
+	vkcv::PassConfig firstMeshPassDefinition({ present_color_attachment, depth_attachment });
+	vkcv::PassHandle firstMeshPass = core.createPass(firstMeshPassDefinition);
+
+	if (!firstMeshPass) {
+		std::cerr << "Error. Could not create renderpass. Exiting." << std::endl;
+		return EXIT_FAILURE;
+	}
+
+	vkcv::ShaderProgram firstMeshProgram;
+	vkcv::shader::GLSLCompiler compiler;
+	
+	compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("resources/shaders/shader.vert"),
+					 [&firstMeshProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
+		firstMeshProgram.addShader(shaderStage, path);
+	});
+	
+	compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("resources/shaders/shader.frag"),
+					 [&firstMeshProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
+		firstMeshProgram.addShader(shaderStage, path);
+	});
+ 
+	auto& attributes = mesh.vertexGroups[0].vertexBuffer.attributes;
+
+	
+	std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) {
+		return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type);
+	});
+
+    const std::vector<vkcv::VertexAttachment> vertexAttachments = firstMeshProgram.getVertexAttachments();
+	std::vector<vkcv::VertexBinding> bindings;
+	for (size_t i = 0; i < vertexAttachments.size(); i++) {
+		bindings.push_back(vkcv::VertexBinding(i, { vertexAttachments[i] }));
+	}
+	
+	const vkcv::VertexLayout firstMeshLayout (bindings);
+
+	uint32_t setID = 0;
+	std::vector<vkcv::DescriptorBinding> descriptorBindings = { firstMeshProgram.getReflectedDescriptors()[setID] };
+	vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorBindings);
+
+	const vkcv::PipelineConfig firstMeshPipelineConfig {
+        firstMeshProgram,
+        UINT32_MAX,
+        UINT32_MAX,
+        firstMeshPass,
+        {firstMeshLayout},
+		{ core.getDescriptorSet(descriptorSet).layout },
+		true
+	};
+	vkcv::PipelineHandle firstMeshPipeline = core.createGraphicsPipeline(firstMeshPipelineConfig);
+	
+	if (!firstMeshPipeline) {
+		std::cerr << "Error. Could not create graphics pipeline. Exiting." << std::endl;
+		return EXIT_FAILURE;
+	}
+	
+	if (mesh.textures.empty()) {
+		std::cerr << "Error. No textures found. Exiting." << std::endl;
+		return EXIT_FAILURE;
+	}
+	
+	vkcv::asset::Texture &tex = mesh.textures[0];
+	vkcv::Image texture = core.createImage(vk::Format::eR8G8B8A8Srgb, tex.w, tex.h);
+	texture.fill(tex.data.data());
+	texture.generateMipChainImmediate();
+	texture.switchLayout(vk::ImageLayout::eShaderReadOnlyOptimal);
+
+	vkcv::SamplerHandle sampler = core.createSampler(
+		vkcv::SamplerFilterType::LINEAR,
+		vkcv::SamplerFilterType::LINEAR,
+		vkcv::SamplerMipmapMode::LINEAR,
+		vkcv::SamplerAddressMode::REPEAT
+	);
+
+	const std::vector<vkcv::VertexBufferBinding> vertexBufferBindings = {
+		vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[0].offset), vertexBuffer.getVulkanHandle()),
+		vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[1].offset), vertexBuffer.getVulkanHandle()),
+		vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[2].offset), vertexBuffer.getVulkanHandle()) };
+
+	vkcv::DescriptorWrites 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, 1, false).getHandle();
+
+	const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
+
+	const vkcv::Mesh renderMesh(vertexBufferBindings, indexBuffer.getVulkanHandle(), mesh.vertexGroups[0].numIndices);
+
+	vkcv::DescriptorSetUsage    descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle);
+	vkcv::DrawcallInfo          drawcall(renderMesh, { descriptorUsage },1);
+
+    vkcv::camera::CameraManager cameraManager(window);
+    uint32_t camIndex0 = cameraManager.addCamera(vkcv::camera::ControllerType::PILOT);
+	uint32_t camIndex1 = cameraManager.addCamera(vkcv::camera::ControllerType::TRACKBALL);
+	
+	cameraManager.getCamera(camIndex0).setPosition(glm::vec3(0, 0, -3));
+
+    auto start = std::chrono::system_clock::now();
+    
+	while (window.isWindowOpen()) {
+        vkcv::Window::pollEvents();
+		
+		if(window.getHeight() == 0 || window.getWidth() == 0)
+			continue;
+		
+		uint32_t swapchainWidth, swapchainHeight;
+		if (!core.beginFrame(swapchainWidth, swapchainHeight)) {
+			continue;
+		}
+		
+		if ((swapchainWidth != windowWidth) || ((swapchainHeight != windowHeight))) {
+			depthBuffer = core.createImage(vk::Format::eD32Sfloat, swapchainWidth, swapchainHeight).getHandle();
+			
+			windowWidth = swapchainWidth;
+			windowHeight = swapchainHeight;
+		}
+  
+		auto end = std::chrono::system_clock::now();
+		auto deltatime = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
+		
+		start = end;
+		cameraManager.update(0.000001 * static_cast<double>(deltatime.count()));
+        glm::mat4 mvp = cameraManager.getActiveCamera().getMVP();
+
+		vkcv::PushConstants pushConstants (sizeof(glm::mat4));
+		pushConstants.appendDrawcall(mvp);
+
+		const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer };
+		auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
+
+		core.recordDrawcallsToCmdStream(
+			cmdStream,
+			firstMeshPass,
+			firstMeshPipeline,
+			pushConstants,
+			{ drawcall },
+			renderTargets);
+		core.prepareSwapchainImageForPresent(cmdStream);
+		core.submitCommandStream(cmdStream);
+		core.endFrame();
+	}
+	
+	return 0;
+}