diff --git a/projects/bindless_textures/resources/shaders/shader.frag b/projects/bindless_textures/resources/shaders/shader.frag
index c855eb407944c415dc4055716aa64a531c830ef3..c78bee41cd2efa5cdc6fb6101e9f187c80c34050 100644
--- a/projects/bindless_textures/resources/shaders/shader.frag
+++ b/projects/bindless_textures/resources/shaders/shader.frag
@@ -8,8 +8,8 @@ layout(location = 2) in flat int passTextureIndex;
 
 layout(location = 0) out vec3 outColor;
 
-layout(set=0, binding=0) uniform sampler    textureSampler;
-layout(set=0, binding=1) uniform texture2D  materialTextures[];
+layout(set=0, binding=1) uniform sampler    textureSampler;
+layout(set=0, binding=2) uniform texture2D  materialTextures[];
 
 void main()	{
 	outColor =  texture(sampler2D(materialTextures[nonuniformEXT(passTextureIndex)], textureSampler), passUV).rgb;
diff --git a/projects/bindless_textures/resources/shaders/shader.vert b/projects/bindless_textures/resources/shaders/shader.vert
index 6bc918c6a186dcfb965719cd1e08cb448a49b44e..46dee752d74134a3fd744056d9566d0e686bb147 100644
--- a/projects/bindless_textures/resources/shaders/shader.vert
+++ b/projects/bindless_textures/resources/shaders/shader.vert
@@ -1,9 +1,16 @@
 #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;
+struct vertex_t {
+    vec3 position;
+    float u;
+    vec3 normal;
+    float v;
+};
+
+layout(std430, set=0, binding=0) buffer buffer_vertexBuffer {
+    vertex_t vertices [];
+};
 
 layout(location = 0) out vec3 passNormal;
 layout(location = 1) out vec2 passUV;
@@ -15,9 +22,9 @@ layout( push_constant ) uniform constants{
 
 void main()
 {
-	gl_Position = mvp * vec4(inPosition, 1.0);
-	passNormal  = inNormal;
-    passUV      = inUV;
+	gl_Position = mvp * vec4(vertices[gl_VertexIndex].position, 1.0);
+	passNormal  = vertices[gl_VertexIndex].normal;
+    passUV      = vec2(vertices[gl_VertexIndex].u, vertices[gl_VertexIndex].v);
 
     passTextureIndex = (gl_VertexIndex / 4);
 
diff --git a/projects/bindless_textures/src/main.cpp b/projects/bindless_textures/src/main.cpp
index 811e1162588fa699b4d74045504dc9c3d4de4f4c..dbd37a624ef1e3343e72114b450b5eea3d320698 100644
--- a/projects/bindless_textures/src/main.cpp
+++ b/projects/bindless_textures/src/main.cpp
@@ -6,6 +6,11 @@
 #include <vkcv/asset/asset_loader.hpp>
 #include <vkcv/shader/GLSLCompiler.hpp>
 
+struct vertex_t {
+	float positionU [4];
+	float normalV [4];
+};
+
 int main(int argc, const char** argv) {
 	const char* applicationName = "Bindless Textures";
 
@@ -79,13 +84,51 @@ int main(int argc, const char** argv) {
 	}
 
 	assert(!mesh.vertexGroups.empty());
-	auto vertexBuffer = core.createBuffer<uint8_t>(
-			vkcv::BufferType::VERTEX,
-			mesh.vertexGroups[0].vertexBuffer.data.size(),
+	auto vertexBuffer = core.createBuffer<vertex_t>(
+			vkcv::BufferType::STORAGE,
+			mesh.vertexGroups[0].numVertices,
 			vkcv::BufferMemoryType::DEVICE_LOCAL
 	);
 	
-	vertexBuffer.fill(mesh.vertexGroups[0].vertexBuffer.data);
+	std::vector<vertex_t> vertices;
+	vertices.reserve(vertexBuffer.getCount());
+	
+	for (const auto& attribute : mesh.vertexGroups[0].vertexBuffer.attributes) {
+		if (attribute.componentType != vkcv::asset::ComponentType::FLOAT32) {
+			continue;
+		}
+		
+		size_t offset = attribute.offset;
+		
+		for (size_t i = 0; i < vertexBuffer.getCount(); i++) {
+			const auto *data = reinterpret_cast<const float*>(
+					mesh.vertexGroups[0].vertexBuffer.data.data() + offset
+			);
+			
+			switch (attribute.type) {
+				case vkcv::asset::PrimitiveType::POSITION:
+					memcpy(vertices[i].positionU, data, sizeof(float) * attribute.componentCount);
+					break;
+				case vkcv::asset::PrimitiveType::NORMAL:
+					memcpy(vertices[i].normalV, data, sizeof(float) * attribute.componentCount);
+					break;
+				case vkcv::asset::PrimitiveType::TEXCOORD_0:
+					if (attribute.componentCount != 2) {
+						break;
+					}
+					
+					vertices[i].positionU[3] = data[0];
+					vertices[i].normalV[3] = data[1];
+					break;
+				default:
+					break;
+			}
+			
+			offset += attribute.stride;
+		}
+	}
+	
+	vertexBuffer.fill(vertices);
 
 	auto indexBuffer = core.createBuffer<uint8_t>(
 			vkcv::BufferType::INDEX,
@@ -123,24 +166,11 @@ int main(int argc, const char** argv) {
 		{ vkcv::ShaderStage::VERTEX, "resources/shaders/shader.vert" },
 		{ vkcv::ShaderStage::FRAGMENT, "resources/shaders/shader.frag" }
 	}, nullptr);
- 
-	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::createVertexBinding(i, { vertexAttachments[i] }));
-	}
 	
-	const vkcv::VertexLayout firstMeshLayout { bindings };
-	const std::unordered_map<uint32_t, vkcv::DescriptorBinding> &descriptorBindings = firstMeshProgram.getReflectedDescriptors().at(0);
+	const vkcv::DescriptorBindings &descriptorBindings = firstMeshProgram.getReflectedDescriptors().at(0);
 
-    std::unordered_map<uint32_t, vkcv::DescriptorBinding> adjustedBindings = descriptorBindings;
-    adjustedBindings[1].descriptorCount = 6;
+    vkcv::DescriptorBindings adjustedBindings = descriptorBindings;
+    adjustedBindings[2].descriptorCount = 6;
 
     vkcv::DescriptorSetLayoutHandle descriptorSetLayout = core.createDescriptorSetLayout(adjustedBindings);
 	vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorSetLayout);
@@ -150,7 +180,6 @@ int main(int argc, const char** argv) {
         UINT32_MAX,
         UINT32_MAX,
         firstMeshPass,
-        {firstMeshLayout},
 		{ descriptorSetLayout },
 		true
 	};
@@ -188,18 +217,13 @@ int main(int argc, const char** argv) {
 		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.writeStorageBuffer(0, vertexBuffer.getHandle());
 	
 	for(uint32_t i = 0; i < 6; i++)
 	{
-		
 		setWrites.writeSampledImage(
-				1,
+				2,
 				texturesArray[i].getHandle(),
 				0,
 				false,
@@ -207,7 +231,7 @@ int main(int argc, const char** argv) {
 		);
 	}
 
-	setWrites.writeSampler(0, sampler);
+	setWrites.writeSampler(1, sampler);
 
 	core.writeDescriptorSet(descriptorSet, setWrites);
 
@@ -215,7 +239,7 @@ int main(int argc, const char** argv) {
 
 	const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
 
-	const vkcv::Mesh renderMesh(vertexBufferBindings, indexBuffer.getVulkanHandle(), mesh.vertexGroups[0].numIndices);
+	const vkcv::Mesh renderMesh(indexBuffer.getVulkanHandle(), mesh.vertexGroups[0].numIndices);
 
 	vkcv::DescriptorSetUsage    descriptorUsage(0, descriptorSet);
 	vkcv::DrawcallInfo          drawcall(renderMesh, { descriptorUsage },1);
diff --git a/projects/first_mesh/assets/shaders/shader.vert b/projects/first_mesh/assets/shaders/shader.vert
index 76855152253b48b7400f016d063ed4f0e507435e..94829b60f6841ab2d985df79a16932e6b16e8850 100644
--- a/projects/first_mesh/assets/shaders/shader.vert
+++ b/projects/first_mesh/assets/shaders/shader.vert
@@ -1,9 +1,16 @@
 #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;
+struct vertex_t {
+    vec3 position;
+    float u;
+    vec3 normal;
+    float v;
+};
+
+layout(std430, set=0, binding=2) buffer buffer_vertexBuffer {
+    vertex_t vertices [];
+};
 
 layout(location = 0) out vec3 passNormal;
 layout(location = 1) out vec2 passUV;
@@ -13,7 +20,7 @@ layout( push_constant ) uniform constants{
 };
 
 void main()	{
-	gl_Position = mvp * vec4(inPosition, 1.0);
-	passNormal  = inNormal;
-    passUV      = inUV;
+	gl_Position = mvp * vec4(vertices[gl_VertexIndex].position, 1.0);
+	passNormal  = vertices[gl_VertexIndex].normal;
+    passUV      = vec2(vertices[gl_VertexIndex].u, vertices[gl_VertexIndex].v);
 }
\ No newline at end of file
diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp
index fa671a5507a7621586497048128e8959f72cdf08..7da84c6d8d226f65c601ce39d08cb7df78c27e14 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -5,6 +5,11 @@
 #include <vkcv/asset/asset_loader.hpp>
 #include <vkcv/shader/GLSLCompiler.hpp>
 
+struct vertex_t {
+	float positionU [4];
+	float normalV [4];
+};
+
 int main(int argc, const char** argv) {
 	const char* applicationName = "First Mesh";
 
@@ -30,13 +35,51 @@ int main(int argc, const char** argv) {
 	}
 
 	assert(!mesh.vertexGroups.empty());
-	auto vertexBuffer = core.createBuffer<uint8_t>(
-			vkcv::BufferType::VERTEX,
-			mesh.vertexGroups[0].vertexBuffer.data.size(),
+	auto vertexBuffer = core.createBuffer<vertex_t>(
+			vkcv::BufferType::STORAGE,
+			mesh.vertexGroups[0].numVertices,
 			vkcv::BufferMemoryType::DEVICE_LOCAL
 	);
 	
-	vertexBuffer.fill(mesh.vertexGroups[0].vertexBuffer.data);
+	std::vector<vertex_t> vertices;
+	vertices.reserve(vertexBuffer.getCount());
+	
+	for (const auto& attribute : mesh.vertexGroups[0].vertexBuffer.attributes) {
+		if (attribute.componentType != vkcv::asset::ComponentType::FLOAT32) {
+			continue;
+		}
+		
+		size_t offset = attribute.offset;
+		
+		for (size_t i = 0; i < vertexBuffer.getCount(); i++) {
+			const auto *data = reinterpret_cast<const float*>(
+					mesh.vertexGroups[0].vertexBuffer.data.data() + offset
+			);
+			
+			switch (attribute.type) {
+				case vkcv::asset::PrimitiveType::POSITION:
+					memcpy(vertices[i].positionU, data, sizeof(float) * attribute.componentCount);
+					break;
+				case vkcv::asset::PrimitiveType::NORMAL:
+					memcpy(vertices[i].normalV, data, sizeof(float) * attribute.componentCount);
+					break;
+				case vkcv::asset::PrimitiveType::TEXCOORD_0:
+					if (attribute.componentCount != 2) {
+						break;
+					}
+					
+					vertices[i].positionU[3] = data[0];
+					vertices[i].normalV[3] = data[1];
+					break;
+				default:
+					break;
+			}
+			
+			offset += attribute.stride;
+		}
+	}
+	
+	vertexBuffer.fill(vertices);
 
 	auto indexBuffer = core.createBuffer<uint8_t>(
 			vkcv::BufferType::INDEX,
@@ -78,20 +121,6 @@ int main(int argc, const char** argv) {
 		{ vkcv::ShaderStage::VERTEX, "assets/shaders/shader.vert" },
 		{ vkcv::ShaderStage::FRAGMENT, "assets/shaders/shader.frag" }
 	}, nullptr);
- 
-	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::createVertexBinding(i, { vertexAttachments[i] }));
-	}
-	
-	const vkcv::VertexLayout firstMeshLayout { bindings };
 
 	// since we only use one descriptor set (namely, desc set 0), directly address it
 	// recreate copies of the bindings and the handles (to check whether they are properly reused instead of actually recreated)
@@ -108,7 +137,6 @@ int main(int argc, const char** argv) {
         UINT32_MAX,
         UINT32_MAX,
         firstMeshPass,
-        {firstMeshLayout},
 		{ setLayoutHandle },
 		true
 	};
@@ -141,14 +169,10 @@ int main(int argc, const char** argv) {
 		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.writeSampledImage(0, texture.getHandle());
 	setWrites.writeSampler(1, sampler);
+	setWrites.writeStorageBuffer(2, vertexBuffer.getHandle());
 
 	core.writeDescriptorSet(descriptorSet, setWrites);
 	
@@ -156,7 +180,7 @@ int main(int argc, const char** argv) {
 
 	const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
 
-	const vkcv::Mesh renderMesh(vertexBufferBindings, indexBuffer.getVulkanHandle(), mesh.vertexGroups[0].numIndices);
+	const vkcv::Mesh renderMesh(indexBuffer.getVulkanHandle(), mesh.vertexGroups[0].numIndices);
 
 	vkcv::DescriptorSetUsage    descriptorUsage(0, descriptorSet);
 	vkcv::DrawcallInfo          drawcall(renderMesh, { descriptorUsage },1);
diff --git a/projects/first_scene/assets/shaders/shader.frag b/projects/first_scene/assets/shaders/shader.frag
index b5494bea7d6497e2e3dcd8559606864a71adb74e..f07d2b19d90cb2440eaf75810e1ef0ea365a9973 100644
--- a/projects/first_scene/assets/shaders/shader.frag
+++ b/projects/first_scene/assets/shaders/shader.frag
@@ -6,8 +6,8 @@ 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;
+layout(set=1, binding=0) uniform texture2D  meshTexture;
+layout(set=1, binding=1) uniform sampler    textureSampler;
 
 void main()	{
 	outColor = texture(sampler2D(meshTexture, textureSampler), passUV).rgb;
diff --git a/projects/first_scene/assets/shaders/shader.vert b/projects/first_scene/assets/shaders/shader.vert
index 76855152253b48b7400f016d063ed4f0e507435e..40305d215c71e45d02cb3872d2b8cbb6a0a2d698 100644
--- a/projects/first_scene/assets/shaders/shader.vert
+++ b/projects/first_scene/assets/shaders/shader.vert
@@ -1,9 +1,16 @@
 #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;
+struct vertex_t {
+    vec3 position;
+    float u;
+    vec3 normal;
+    float v;
+};
+
+layout(std430, set=0, binding=0) buffer buffer_vertexBuffer {
+    vertex_t vertices [];
+};
 
 layout(location = 0) out vec3 passNormal;
 layout(location = 1) out vec2 passUV;
@@ -13,7 +20,7 @@ layout( push_constant ) uniform constants{
 };
 
 void main()	{
-	gl_Position = mvp * vec4(inPosition, 1.0);
-	passNormal  = inNormal;
-    passUV      = inUV;
+	gl_Position = mvp * vec4(vertices[gl_VertexIndex].position, 1.0);
+	passNormal  = vertices[gl_VertexIndex].normal;
+    passUV      = vec2(vertices[gl_VertexIndex].u, vertices[gl_VertexIndex].v);
 }
\ No newline at end of file
diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp
index b09943e4b9432ac09c6eaaa5bbe06b0b28b59ab3..68f478a8ca10920fecd5893b9bccbcea1757c29b 100644
--- a/projects/first_scene/src/main.cpp
+++ b/projects/first_scene/src/main.cpp
@@ -80,14 +80,6 @@ int main(int argc, const char** argv) {
 		{ vkcv::ShaderStage::FRAGMENT, "assets/shaders/shader.frag" }
 	}, nullptr);
 
-	const std::vector<vkcv::VertexAttachment> vertexAttachments = sceneShaderProgram.getVertexAttachments();
-	std::vector<vkcv::VertexBinding> bindings;
-	
-	for (size_t i = 0; i < vertexAttachments.size(); i++) {
-		bindings.push_back(vkcv::createVertexBinding(i, { vertexAttachments[i] }));
-	}
-
-	const vkcv::VertexLayout sceneLayout { bindings };
 	const auto& material0 = scene.getMaterial(0);
 
 	const vkcv::GraphicsPipelineConfig scenePipelineDefinition{
@@ -95,10 +87,10 @@ int main(int argc, const char** argv) {
 		UINT32_MAX,
 		UINT32_MAX,
 		scenePass,
-		{sceneLayout},
-		{ material0.getDescriptorSetLayout() },
+		{ scene.getDescriptorSetLayout(), material0.getDescriptorSetLayout() },
 		true
 	};
+	
 	vkcv::GraphicsPipelineHandle scenePipeline = core.createGraphicsPipeline(scenePipelineDefinition);
 	
 	if (!scenePipeline) {
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index c2d8bf817dd1d6b2c7cc069f2037ee090abc4415..c27eba46fcf0a685f6928560eb4ef0278239a60d 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -58,7 +58,6 @@ int main(int argc, const char** argv) {
 		UINT32_MAX,
 		trianglePass,
 		{},
-		{},
 		true
 	};
 
@@ -74,7 +73,7 @@ int main(int argc, const char** argv) {
 	
 	auto start = std::chrono::system_clock::now();
 
-	const vkcv::Mesh renderMesh({}, triangleIndexBuffer.getVulkanHandle(), 3);
+	const vkcv::Mesh renderMesh(triangleIndexBuffer.getVulkanHandle(), 3);
 	vkcv::DrawcallInfo drawcall(renderMesh, {},1);
 
 	const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
diff --git a/projects/head_demo/assets/shaders/shader.geom b/projects/head_demo/assets/shaders/shader.geom
index 275b300ee3466e117876aa46a6ea1cde11f6f17d..a3911174d853d85b38e4b32c48a87bc175ef97ed 100644
--- a/projects/head_demo/assets/shaders/shader.geom
+++ b/projects/head_demo/assets/shaders/shader.geom
@@ -9,7 +9,7 @@ layout(location = 0) in vec3 geomNormal[];
 
 layout(location = 0) out vec3 passNormal;
 
-layout(set=1, binding=0) uniform clipBuffer {
+layout(set=2, binding=0) uniform clipBuffer {
     float clipLimit;
     float clipX;
     float clipY;
diff --git a/projects/head_demo/assets/shaders/shader.vert b/projects/head_demo/assets/shaders/shader.vert
index 26e43e9c89dc2ffb2355d60be8288fa9832f8baa..5cd93b82cad681d346b8de4e28445f897e4a612f 100644
--- a/projects/head_demo/assets/shaders/shader.vert
+++ b/projects/head_demo/assets/shaders/shader.vert
@@ -1,12 +1,20 @@
 #version 450
 #extension GL_ARB_separate_shader_objects : enable
 
-layout(location = 0) in vec3 inPosition;
-layout(location = 1) in vec3 inNormal;
+struct vertex_t {
+	vec3 position;
+	float u;
+	vec3 normal;
+	float v;
+};
+
+layout(std430, set=0, binding=0) buffer buffer_vertexBuffer {
+	vertex_t vertices [];
+};
 
 layout(location = 0) out vec3 geomNormal;
 
 void main()	{
-	gl_Position = vec4(inPosition, 1.0);
-	geomNormal  = inNormal;
+	gl_Position = vec4(vertices[gl_VertexIndex].position, 1.0);
+	geomNormal  = vertices[gl_VertexIndex].normal;
 }
\ No newline at end of file
diff --git a/projects/head_demo/assets/shaders/wired.geom b/projects/head_demo/assets/shaders/wired.geom
index 689e073dde7fd993d164cfea0b7ca777d79f8508..69065b6ec422ecc0f4d49253fb7ed28d4311df91 100644
--- a/projects/head_demo/assets/shaders/wired.geom
+++ b/projects/head_demo/assets/shaders/wired.geom
@@ -10,7 +10,7 @@ layout(location = 0) in vec3 geomNormal[];
 layout(location = 0) out vec3 passNormal;
 layout(location = 1) out vec3 passEdge;
 
-layout(set=1, binding=0) uniform clipBuffer {
+layout(set=2, binding=0) uniform clipBuffer {
     float clipLimit;
     float clipX;
     float clipY;
diff --git a/projects/head_demo/src/main.cpp b/projects/head_demo/src/main.cpp
index 89fb5e08d1c4a5ceec8c43f3c4043f8978d5d404..ab8881e25abe4fb0af2d078b8e276a3e0384b0cf 100644
--- a/projects/head_demo/src/main.cpp
+++ b/projects/head_demo/src/main.cpp
@@ -101,14 +101,7 @@ int main(int argc, const char** argv) {
 			{ vkcv::ShaderStage::FRAGMENT, "assets/shaders/red.frag" }
 	}, nullptr);
 	
-	const std::vector<vkcv::VertexAttachment> vertexAttachments = sceneShaderProgram.getVertexAttachments();
-	std::vector<vkcv::VertexBinding> bindings;
-	
-	for (size_t i = 0; i < vertexAttachments.size(); i++) {
-		bindings.push_back(vkcv::createVertexBinding(i, { vertexAttachments[i] }));
-	}
-	
-	const auto& clipBindings = sceneShaderProgram.getReflectedDescriptors().at(1);
+	const auto& clipBindings = sceneShaderProgram.getReflectedDescriptors().at(2);
 	
 	auto clipDescriptorSetLayout = core.createDescriptorSetLayout(clipBindings);
 	auto clipDescriptorSet = core.createDescriptorSet(clipDescriptorSetLayout);
@@ -148,7 +141,6 @@ int main(int argc, const char** argv) {
 		}
 	});
 	
-	const vkcv::VertexLayout sceneLayout { bindings };
 	const auto& material0 = scene.getMaterial(0);
 	
 	const vkcv::GraphicsPipelineConfig scenePipelineDefinition{
@@ -156,8 +148,11 @@ int main(int argc, const char** argv) {
 			UINT32_MAX,
 			UINT32_MAX,
 			scenePass,
-			{sceneLayout},
-			{ material0.getDescriptorSetLayout(), clipDescriptorSetLayout },
+			{
+				scene.getDescriptorSetLayout(),
+				material0.getDescriptorSetLayout(),
+				clipDescriptorSetLayout
+			},
 			true
 	};
 	
@@ -166,8 +161,11 @@ int main(int argc, const char** argv) {
 			UINT32_MAX,
 			UINT32_MAX,
 			linePass,
-			{sceneLayout},
-			{ material0.getDescriptorSetLayout(), clipDescriptorSetLayout },
+			{
+					scene.getDescriptorSetLayout(),
+					material0.getDescriptorSetLayout(),
+					clipDescriptorSetLayout
+			},
 			true
 	};
 	
@@ -241,7 +239,7 @@ int main(int argc, const char** argv) {
 							 vkcv::DrawcallInfo& drawcallInfo) {
 			pushConstants.appendDrawcall(MVP);
 			drawcallInfo.descriptorSets.push_back(
-					vkcv::DescriptorSetUsage(1, clipDescriptorSet)
+					vkcv::DescriptorSetUsage(2, clipDescriptorSet)
 			);
 		};