diff --git a/config/Sources.cmake b/config/Sources.cmake
index 80fa3a09d163edf3277eb69f91e7b10e57b72c5d..d98c51c1bfd3372e2b1767e01626fcfe84dd2081 100644
--- a/config/Sources.cmake
+++ b/config/Sources.cmake
@@ -7,6 +7,9 @@ set(vkcv_sources
 		${vkcv_include}/vkcv/Core.hpp
 		${vkcv_source}/vkcv/Core.cpp
 
+		${vkcv_include}/vkcv/Renderpass.hpp
+		${vkcv_source}/vkcv/Renderpass.cpp
+
 		${vkcv_include}/vkcv/Handles.hpp
 		${vkcv_source}/vkcv/Handles.cpp
 
diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index 7a7f3be7d61995462da1f65bd58af098b1dd1f4e..475099ab68b18556065698579dc13b5d5d7682d4 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -6,6 +6,7 @@
 
 #include <vulkan/vulkan.hpp>
 #include "vkcv/Context.hpp"
+#include "vkcv/Renderpass.hpp"
 #include "vkcv/Handles.hpp"
 
 namespace vkcv
@@ -29,11 +30,15 @@ namespace vkcv
         Core() = delete;
 
         Context m_Context;
+
+        uint64_t m_NextPassId;
+        std::vector<vk::RenderPass> m_Renderpasses;
+
     public:
         /**
          * Destructor of #Core destroys the Vulkan objects contained in the core's context.
          */
-        ~Core() noexcept = default;
+        ~Core() noexcept;
 
         /**
          * Copy-constructor of #Core is deleted!
@@ -93,7 +98,11 @@ namespace vkcv
 
         // TODO:
         BufferHandle createBuffer(const Buffer &buf);
-        PassHandle createRenderPass(const Renderpass &pass) ;
+
+        [[nodiscard]]
+        bool createRenderpass(const Renderpass &pass, RenderpassHandle &handle);
+
+        // TODO:
         PipelineHandle createPipeline(const Pipeline &pipeline);
 
     };
diff --git a/include/vkcv/Handles.hpp b/include/vkcv/Handles.hpp
index 4ec2bc058409e9119695700b2b727be9426c2bcd..0d8e4a89124c82d986a51e3175e311dd7b10c21e 100644
--- a/include/vkcv/Handles.hpp
+++ b/include/vkcv/Handles.hpp
@@ -11,6 +11,6 @@ namespace vkcv
 {
     // Handle returned for any buffer created with the core/context objects
     struct BufferHandle     {uint64_t id;};
-    struct PassHandle       {uint64_t id;};
+    struct RenderpassHandle       {uint64_t id;};
     struct PipelineHandle   {uint64_t id;};
 }
diff --git a/include/vkcv/Renderpass.hpp b/include/vkcv/Renderpass.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..7f2ad91caca9468b32f19b5e4cebebcaa7807364
--- /dev/null
+++ b/include/vkcv/Renderpass.hpp
@@ -0,0 +1,54 @@
+#pragma once
+
+#include <vector>
+
+namespace vkcv
+{
+    enum class AttachmentLayout
+    {
+        UNDEFINED,
+        GENERAL,
+
+        COLOR_ATTACHMENT,
+        SHADER_READ_ONLY,
+
+        DEPTH_STENCIL_ATTACHMENT,
+        DEPTH_STENCIL_READ_ONLY,
+
+        TRANSFER_SRC,
+        TRANSFER_DST,
+
+        PRESENTATION
+    };
+
+    enum class AttachmentOperation
+    {
+        LOAD,
+        CLEAR,
+        STORE,
+        DONT_CARE
+    };
+
+    struct AttachmentDescription
+    {
+        AttachmentDescription() = delete;
+        AttachmentDescription(AttachmentLayout initial,
+                              AttachmentLayout in_pass,
+                              AttachmentLayout final,
+                              AttachmentOperation store_op,
+                              AttachmentOperation load_op) noexcept;
+
+        AttachmentLayout layout_initial;
+        AttachmentLayout layout_in_pass;
+        AttachmentLayout layout_final;
+
+        AttachmentOperation store_operation;
+        AttachmentOperation load_operation;
+    };
+
+    struct Renderpass
+    {
+        Renderpass() noexcept = default;
+        std::vector<AttachmentDescription> attachments{};
+    };
+}
\ No newline at end of file
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index 0c981a25dc52db4363d2bc7835df3c3c9d7c49fa..87a7d11e5e05e0c367d46fe36db1a161ee8398bd 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -33,6 +33,38 @@ int main(int argc, const char** argv) {
 		default: std::cout << "Unknown GPU vendor?! Either you're on an exotic system or your driver is broken..." << std::endl;
 	}
 
+    // an example attachment for passes that output to the window
+	vkcv::AttachmentDescription present_color_attachment(vkcv::AttachmentLayout::UNDEFINED,
+                                                    vkcv::AttachmentLayout::COLOR_ATTACHMENT,
+                                                    vkcv::AttachmentLayout::PRESENTATION,
+                                                    vkcv::AttachmentOperation::STORE,
+                                                    vkcv::AttachmentOperation::CLEAR);
+    // an example attachment for passes that output to a depth buffer
+	vkcv::AttachmentDescription present_depth_attachment(vkcv::AttachmentLayout::UNDEFINED,
+                                                    vkcv::AttachmentLayout::DEPTH_STENCIL_ATTACHMENT,
+                                                    vkcv::AttachmentLayout::DEPTH_STENCIL_READ_ONLY,
+                                                    vkcv::AttachmentOperation::STORE,
+                                                    vkcv::AttachmentOperation::CLEAR);
+
+	// this pass will output to the window, and produce a depth buffer
+	vkcv::Renderpass test_pass{};
+	test_pass.attachments.push_back(present_color_attachment);
+	test_pass.attachments.push_back(present_depth_attachment);
+
+	std::vector<vkcv::RenderpassHandle> test_handles{};
+    // render pass creation test
+    for(uint32_t i = 0; i < 1000; i++)
+    {
+        vkcv::RenderpassHandle tmp_handle{};
+        if(!core.createRenderpass(test_pass, tmp_handle))
+        {
+            std::cout << "Oops. Something went wrong in the renderpass creation. Exiting." << std::endl;
+            return EXIT_FAILURE;
+        }
+        test_handles.push_back(tmp_handle);
+    }
+    std::cout << "Wow. You just made 1000 render passes. (That are all identical, though...)" << std::endl;
+
 	/*
 	 * BufferHandle triangleVertices = core.createBuffer(vertices);
 	 * BufferHandle triangleIndices = core.createBuffer(indices);
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index 0c32f4e42d1a232a9b66d42e6a16f0c1eda06bbb..4ba377d953366c0b49f2f97d7b7fd4268e97abb2 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -8,6 +8,51 @@
 
 namespace vkcv
 {
+    static vk::ImageLayout getVkLayoutFromAttachLayout(AttachmentLayout layout)
+    {
+        switch(layout)
+        {
+            case AttachmentLayout::GENERAL:
+                return vk::ImageLayout::eGeneral;
+            case AttachmentLayout::COLOR_ATTACHMENT:
+                return vk::ImageLayout::eColorAttachmentOptimal;
+            case AttachmentLayout::SHADER_READ_ONLY:
+                return vk::ImageLayout::eShaderReadOnlyOptimal;
+            case AttachmentLayout::DEPTH_STENCIL_ATTACHMENT:
+                return vk::ImageLayout::eDepthStencilAttachmentOptimal;
+            case AttachmentLayout::DEPTH_STENCIL_READ_ONLY:
+                return vk::ImageLayout::eDepthStencilReadOnlyOptimal;
+            case AttachmentLayout::PRESENTATION:
+                return vk::ImageLayout::ePresentSrcKHR;
+            default:
+                return vk::ImageLayout::eUndefined;
+        }
+    }
+
+    static vk::AttachmentStoreOp getVkStoreOpFromAttachOp(AttachmentOperation op)
+    {
+        switch(op)
+        {
+            case AttachmentOperation::STORE:
+                return vk::AttachmentStoreOp::eStore;
+            default:
+                return vk::AttachmentStoreOp::eDontCare;
+        }
+    }
+
+    static vk::AttachmentLoadOp getVKLoadOpFromAttachOp(AttachmentOperation op)
+    {
+        switch(op)
+        {
+            case AttachmentOperation::LOAD:
+                return vk::AttachmentLoadOp::eLoad;
+            case AttachmentOperation::CLEAR:
+                return vk::AttachmentLoadOp::eClear;
+            default:
+                return vk::AttachmentLoadOp::eDontCare;
+        }
+    }
+
     /**
      * @brief The physical device is evaluated by three categories:
      * discrete GPU vs. integrated GPU, amount of queues and its abilities, and VRAM.physicalDevice.
@@ -268,6 +313,85 @@ namespace vkcv
     }
 
     Core::Core(Context &&context) noexcept :
-            m_Context(std::move(context))
+            m_Context(std::move(context)),
+            m_NextPassId(0),
+            m_Renderpasses{}
     {}
+
+    Core::~Core() noexcept
+    {
+        for(const auto &pass : m_Renderpasses)
+            m_Context.m_Device.destroy(pass);
+        m_Renderpasses.clear();
+        m_NextPassId = 0;
+    }
+
+    bool Core::createRenderpass(const Renderpass &pass, RenderpassHandle &handle)
+    {
+        // description of all {color, input, depth/stencil} attachments of the render pass
+        std::vector<vk::AttachmentDescription> attachmentDescriptions{};
+
+        // individual references to color attachments (of a subpass)
+        std::vector<vk::AttachmentReference> colorAttachmentReferences{};
+        // individual reference to depth attachment (of a subpass)
+        vk::AttachmentReference depthAttachmentReference{};
+
+        for(uint32_t i = 0; i < pass.attachments.size(); i++)
+        {
+            // TODO: Renderpass struct should hold proper format information
+            vk::Format format;
+
+            if(pass.attachments[i].layout_in_pass == AttachmentLayout::DEPTH_STENCIL_ATTACHMENT)
+            {
+                format = vk::Format::eD16Unorm; // depth attachments;
+
+                depthAttachmentReference.attachment = i;
+                depthAttachmentReference.layout = getVkLayoutFromAttachLayout(pass.attachments[i].layout_in_pass);
+            }
+            else
+            {
+                format = vk::Format::eB8G8R8A8Srgb; // color attachments, compatible with swapchain
+                vk::AttachmentReference attachmentRef(i, getVkLayoutFromAttachLayout(pass.attachments[i].layout_in_pass));
+                colorAttachmentReferences.push_back(attachmentRef);
+            }
+
+            vk::AttachmentDescription attachmentDesc({},
+                                                     format,
+                                                     vk::SampleCountFlagBits::e1,
+                                                     getVKLoadOpFromAttachOp(pass.attachments[i].load_operation),
+                                                     getVkStoreOpFromAttachOp(pass.attachments[i].load_operation),
+                                                     vk::AttachmentLoadOp::eDontCare,
+                                                     vk::AttachmentStoreOp::eDontCare,
+                                                     getVkLayoutFromAttachLayout(pass.attachments[i].layout_initial),
+                                                     getVkLayoutFromAttachLayout(pass.attachments[i].layout_final));
+            attachmentDescriptions.push_back(attachmentDesc);
+        }
+
+        vk::SubpassDescription subpassDescription({},
+                                           vk::PipelineBindPoint::eGraphics,
+                                           0,
+                                           {},
+                                           static_cast<uint32_t>(colorAttachmentReferences.size()),
+                                           colorAttachmentReferences.data(),
+                                           {},
+                                           &depthAttachmentReference,
+                                           0,
+                                           {});
+
+        vk::RenderPassCreateInfo passInfo({},
+                                          static_cast<uint32_t>(attachmentDescriptions.size()),
+                                          attachmentDescriptions.data(),
+                                          1,
+                                          &subpassDescription,
+                                          0,
+                                          {});
+
+        vk::RenderPass vkObject{nullptr};
+        if(m_Context.m_Device.createRenderPass(&passInfo, nullptr, &vkObject) != vk::Result::eSuccess)
+            return false;
+
+        m_Renderpasses.push_back(vkObject);
+        handle.id = m_NextPassId++;
+        return true;
+    }
 }
diff --git a/src/vkcv/Renderpass.cpp b/src/vkcv/Renderpass.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e9f2459b241d43c69b131ff93eb61bd94fd6e6c7
--- /dev/null
+++ b/src/vkcv/Renderpass.cpp
@@ -0,0 +1,16 @@
+#include "vkcv/Renderpass.hpp"
+
+namespace vkcv
+{
+    AttachmentDescription::AttachmentDescription(AttachmentLayout initial,
+                                                 AttachmentLayout in_pass,
+                                                 AttachmentLayout final,
+                                                 AttachmentOperation store_op,
+                                                 AttachmentOperation load_op) noexcept :
+    layout_initial{initial},
+    layout_in_pass{in_pass},
+    layout_final{final},
+    store_operation{store_op},
+    load_operation{load_op}
+    {};
+}
\ No newline at end of file