diff --git a/projects/saf_r/shaders/shader.frag b/projects/saf_r/shaders/shader.frag
index 080678beb011afe4b03aed3bf7ae7148b77932dc..2403928a386ab981dc6f511500e00482df6b3276 100644
--- a/projects/saf_r/shaders/shader.frag
+++ b/projects/saf_r/shaders/shader.frag
@@ -2,8 +2,14 @@
 #extension GL_ARB_separate_shader_objects : enable
 
 layout(location = 0) in vec3 fragColor;
-layout(location = 0) out vec4 outColor;
+layout(location = 1) in vec2 texCoord;
+
+layout(location = 0) out vec3 outColor;
+
+layout(set=0, binding=0) uniform texture2D  tex;
+layout(set=0, binding=1) uniform sampler    textureSampler;
 
 void main() {
-	outColor = vec4(fragColor, 1.0);
+	outColor = fragColor;
+	outColor = texture(sampler2D(tex, textureSampler), texCoord).rgb;
 }
\ No newline at end of file
diff --git a/projects/saf_r/shaders/shader.vert b/projects/saf_r/shaders/shader.vert
index 3bcc38fba3c5ff8ba32a806c860d7197d8726520..1faa9080db858944e6390bf111e996f0707b4b04 100644
--- a/projects/saf_r/shaders/shader.vert
+++ b/projects/saf_r/shaders/shader.vert
@@ -2,6 +2,7 @@
 #extension GL_ARB_separate_shader_objects : enable
 
 layout(location = 0) out vec3 fragColor;
+layout(location = 1) out vec2 texCoord;
 
 layout( push_constant ) uniform constants{
     mat4 mvp;
@@ -11,7 +12,7 @@ void main()	{
     vec3 positions[3] = {
         vec3(-1, -1, -1),
         vec3( 3, -1, -1),
-        vec3(-1, 3, -1),
+        vec3(-1, 3, -1)
     };
     
     vec3 colors[3] = {
@@ -20,6 +21,11 @@ void main()	{
         vec3(0, 0, 1)
     };
 
-	gl_Position = mvp * vec4(positions[gl_VertexIndex], 1.0);
+    vec4 position = mvp * vec4(positions[gl_VertexIndex], 1.0);
+	gl_Position = position;
+
+    texCoord.x = (position.x + 1.0) * 0.5;
+    texCoord.y = (position.y + 1.0) * 0.5;
+
 	fragColor = colors[gl_VertexIndex];
 }
\ No newline at end of file
diff --git a/projects/saf_r/src/main.cpp b/projects/saf_r/src/main.cpp
index 97de405f5fdbd6ac73cc1a3278ca5fb0d1c191d4..2116af98aad88512c6a4db3d218d3c4d9229f643 100644
--- a/projects/saf_r/src/main.cpp
+++ b/projects/saf_r/src/main.cpp
@@ -153,12 +153,43 @@ int main(int argc, const char** argv) {
             { "VK_KHR_swapchain" }
     );
 
+    vkcv::ShaderProgram triangleShaderProgram;
+    vkcv::shader::GLSLCompiler compiler;
+
+    compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("shaders/shader.vert"),
+                     [&triangleShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
+                         triangleShaderProgram.addShader(shaderStage, path);
+                     });
+
+    compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("shaders/shader.frag"),
+                     [&triangleShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
+                         triangleShaderProgram.addShader(shaderStage, path);
+                     });
+
+    uint32_t setID = 0;
+    std::vector<vkcv::DescriptorBinding> descriptorBindings = { triangleShaderProgram.getReflectedDescriptors()[setID] };
+    vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorBindings);
+
     vkcv::asset::TextureData texData = vkcv::asset::loadTexture("textures/texture.png");
     vkcv::Image texture = core.createImage(vk::Format::eR8G8B8A8Srgb, 800, 600);
     texture.fill( texData.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
+    );
+
+
+    vkcv::DescriptorWrites setWrites;
+    setWrites.sampledImageWrites	= { vkcv::SampledImageDescriptorWrite(0, texture.getHandle()) };
+    setWrites.samplerWrites			= { vkcv::SamplerDescriptorWrite(1, sampler) };
+
+    core.writeDescriptorSet(descriptorSet, setWrites);
+
     const auto& context = core.getContext();
 
     auto triangleIndexBuffer = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 3, vkcv::BufferMemoryType::DEVICE_LOCAL);
@@ -180,18 +211,7 @@ int main(int argc, const char** argv) {
         return EXIT_FAILURE;
     }
 
-    vkcv::ShaderProgram triangleShaderProgram;
-    vkcv::shader::GLSLCompiler compiler;
 
-    compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("shaders/shader.vert"),
-                     [&triangleShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
-                         triangleShaderProgram.addShader(shaderStage, path);
-                     });
-
-    compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("shaders/shader.frag"),
-                     [&triangleShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
-                         triangleShaderProgram.addShader(shaderStage, path);
-                     });
 
     const vkcv::PipelineConfig trianglePipelineDefinition {
             triangleShaderProgram,
@@ -199,7 +219,7 @@ int main(int argc, const char** argv) {
             (uint32_t)windowHeight,
             trianglePass,
             {},
-            {},
+            { core.getDescriptorSet(descriptorSet).layout },
             false
     };
 
@@ -214,7 +234,8 @@ int main(int argc, const char** argv) {
     auto start = std::chrono::system_clock::now();
 
     const vkcv::Mesh renderMesh({}, triangleIndexBuffer.getVulkanHandle(), 3);
-    vkcv::DrawcallInfo drawcall(renderMesh, {},1);
+    vkcv::DescriptorSetUsage    descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle);
+    vkcv::DrawcallInfo drawcall(renderMesh, { descriptorUsage },1);
 
     const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();