From 1547aceaafd181e0b832a31b4137f4a8f75df996 Mon Sep 17 00:00:00 2001
From: Tobias Frisch <tfrisch@uni-koblenz.de>
Date: Wed, 31 Aug 2022 14:29:45 +0200
Subject: [PATCH] Simplified sampler creation further

Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de>
---
 config/Sources.cmake                          |  3 +
 include/vkcv/Core.hpp                         |  2 +-
 include/vkcv/Image.hpp                        |  1 -
 include/vkcv/Sampler.hpp                      | 55 +++++--------------
 include/vkcv/SamplerTypes.hpp                 | 51 +++++++++++++++++
 .../src/vkcv/effects/BloomAndFlaresEffect.cpp | 16 +-----
 .../material/src/vkcv/material/Material.cpp   | 38 +++----------
 modules/scene/src/vkcv/scene/Scene.cpp        |  9 +--
 projects/bindless_textures/src/main.cpp       | 11 ++--
 projects/fire_works/src/main.cpp              |  8 +--
 projects/first_mesh/src/main.cpp              | 11 ++--
 projects/indirect_dispatch/src/App.cpp        | 12 ++--
 projects/indirect_dispatch/src/MotionBlur.cpp | 11 ++--
 projects/indirect_draw/src/main.cpp           |  9 +--
 projects/saf_r/src/main.cpp                   | 14 ++---
 projects/voxelization/src/main.cpp            | 22 ++------
 src/vkcv/Sampler.cpp                          | 28 ++++++++++
 17 files changed, 140 insertions(+), 161 deletions(-)
 create mode 100644 include/vkcv/SamplerTypes.hpp
 create mode 100644 src/vkcv/Sampler.cpp

diff --git a/config/Sources.cmake b/config/Sources.cmake
index 0b111a15..d714857c 100644
--- a/config/Sources.cmake
+++ b/config/Sources.cmake
@@ -124,7 +124,10 @@ set(vkcv_sources
 		${vkcv_include}/vkcv/BlitDownsampler.hpp
 		${vkcv_source}/vkcv/BlitDownsampler.cpp
 		
+		${vkcv_include}/vkcv/SamplerTypes.hpp
+		
 		${vkcv_include}/vkcv/Sampler.hpp
+		${vkcv_source}/vkcv/Sampler.cpp
 		
 		${vkcv_include}/vkcv/Result.hpp
 )
diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index 73939037..83524865 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -18,7 +18,7 @@
 #include "GraphicsPipelineConfig.hpp"
 #include "ComputePipelineConfig.hpp"
 #include "Result.hpp"
-#include "Sampler.hpp"
+#include "SamplerTypes.hpp"
 #include "DescriptorWrites.hpp"
 #include "Event.hpp"
 #include "DrawcallRecording.hpp"
diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp
index 8b738b07..542658ae 100644
--- a/include/vkcv/Image.hpp
+++ b/include/vkcv/Image.hpp
@@ -15,7 +15,6 @@
 namespace vkcv {
 	
 	class Downsampler;
-	class ImageManager;
 
 	/**
 	 * @brief Returns whether an image format is usable as depth buffer.
diff --git a/include/vkcv/Sampler.hpp b/include/vkcv/Sampler.hpp
index c65ef821..601370c7 100644
--- a/include/vkcv/Sampler.hpp
+++ b/include/vkcv/Sampler.hpp
@@ -2,50 +2,21 @@
 /**
  * @authors Tobias Frisch
  * @file vkcv/Sampler.hpp
- * @brief Enums for different sampler attributes.
+ * @brief Support functions for basic sampler creation.
  */
 
-namespace vkcv {
-
-    /**
-     * @brief Enum class to specify a samplers type to filter during access.
-     */
-	enum class SamplerFilterType {
-		NEAREST = 1,
-		LINEAR = 2
-	};
-
-    /**
-     * @brief Enum class to specify a samplers mode to access mipmaps.
-     */
-	enum class SamplerMipmapMode {
-		NEAREST = 1,
-		LINEAR = 2
-	};
+#include "Core.hpp"
+#include "SamplerTypes.hpp"
+#include "Handles.hpp"
 
-    /**
-     * @brief Enum class to specify a samplers mode to access via address space.
-     */
-	enum class SamplerAddressMode {
-		REPEAT = 1,
-		MIRRORED_REPEAT = 2,
-		CLAMP_TO_EDGE = 3,
-		MIRROR_CLAMP_TO_EDGE = 4,
-		CLAMP_TO_BORDER = 5
-	};
-
-    /**
-     * @brief Enum class to specify a samplers color beyond a textures border.
-     */
-	enum class SamplerBorderColor {
-		INT_ZERO_OPAQUE = 1,
-		INT_ZERO_TRANSPARENT = 2,
-		
-		FLOAT_ZERO_OPAQUE = 3,
-		FLOAT_ZERO_TRANSPARENT = 4,
-		
-		INT_ONE_OPAQUE = 5,
-		FLOAT_ONE_OPAQUE = 6
-	};
+namespace vkcv {
+	
+	[[nodiscard]]
+	SamplerHandle samplerLinear(Core &core,
+								bool clampToEdge = false);
+	
+	[[nodiscard]]
+	SamplerHandle samplerNearest(Core &core,
+								 bool clampToEdge = false);
 
 }
diff --git a/include/vkcv/SamplerTypes.hpp b/include/vkcv/SamplerTypes.hpp
new file mode 100644
index 00000000..4dc68930
--- /dev/null
+++ b/include/vkcv/SamplerTypes.hpp
@@ -0,0 +1,51 @@
+#pragma once
+/**
+ * @authors Tobias Frisch
+ * @file vkcv/SamplerTypes.hpp
+ * @brief Enums for different sampler attributes.
+ */
+
+namespace vkcv {
+	
+	/**
+     * @brief Enum class to specify a samplers type to filter during access.
+     */
+	enum class SamplerFilterType {
+		NEAREST = 1,
+		LINEAR = 2
+	};
+	
+	/**
+	 * @brief Enum class to specify a samplers mode to access mipmaps.
+	 */
+	enum class SamplerMipmapMode {
+		NEAREST = 1,
+		LINEAR = 2
+	};
+	
+	/**
+	 * @brief Enum class to specify a samplers mode to access via address space.
+	 */
+	enum class SamplerAddressMode {
+		REPEAT = 1,
+		MIRRORED_REPEAT = 2,
+		CLAMP_TO_EDGE = 3,
+		MIRROR_CLAMP_TO_EDGE = 4,
+		CLAMP_TO_BORDER = 5
+	};
+	
+	/**
+	 * @brief Enum class to specify a samplers color beyond a textures border.
+	 */
+	enum class SamplerBorderColor {
+		INT_ZERO_OPAQUE = 1,
+		INT_ZERO_TRANSPARENT = 2,
+		
+		FLOAT_ZERO_OPAQUE = 3,
+		FLOAT_ZERO_TRANSPARENT = 4,
+		
+		INT_ONE_OPAQUE = 5,
+		FLOAT_ONE_OPAQUE = 6
+	};
+	
+}
diff --git a/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp b/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp
index fbfa20fb..07987c13 100644
--- a/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp
+++ b/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp
@@ -4,6 +4,7 @@
 #include <vkcv/DrawcallRecording.hpp>
 #include <vkcv/PushConstants.hpp>
 #include <vkcv/Image.hpp>
+#include <vkcv/Sampler.hpp>
 
 #include <vkcv/shader/GLSLCompiler.hpp>
 #include <vkcv/asset/asset_loader.hpp>
@@ -190,12 +191,7 @@ namespace vkcv::effects {
 	m_blurImage(),
 	m_flaresImage(),
 	
-	m_linearSampler(m_core.createSampler(
-			vkcv::SamplerFilterType::LINEAR,
-			vkcv::SamplerFilterType::LINEAR,
-			vkcv::SamplerMipmapMode::LINEAR,
-			vkcv::SamplerAddressMode::CLAMP_TO_EDGE
-	)),
+	m_linearSampler(samplerLinear(m_core, true)),
 	
 	m_radialLutSampler(),
 	
@@ -238,13 +234,7 @@ namespace vkcv::effects {
 		);
 		
 		if (m_advanced) {
-			m_radialLutSampler = m_core.createSampler(
-					vkcv::SamplerFilterType::LINEAR,
-					vkcv::SamplerFilterType::LINEAR,
-					vkcv::SamplerMipmapMode::LINEAR,
-					vkcv::SamplerAddressMode::REPEAT
-			);
-			
+			m_radialLutSampler = samplerLinear(m_core);
 			m_radialLut = loadTexture(m_core, "assets/RadialLUT.png");
 			m_lensDirt = loadTexture(m_core, "assets/lensDirt.jpg");
 		}
diff --git a/modules/material/src/vkcv/material/Material.cpp b/modules/material/src/vkcv/material/Material.cpp
index 6ee280a0..8187b5de 100644
--- a/modules/material/src/vkcv/material/Material.cpp
+++ b/modules/material/src/vkcv/material/Material.cpp
@@ -1,7 +1,8 @@
 
 #include "vkcv/material/Material.hpp"
 
-#include "vkcv/Image.hpp"
+#include <vkcv/Image.hpp>
+#include <vkcv/Sampler.hpp>
 
 namespace vkcv::material {
 	
@@ -149,48 +150,23 @@ namespace vkcv::material {
 		}
 		
 		if (!colorSmp) {
-			samplers[0] = core.createSampler(
-					vkcv::SamplerFilterType::LINEAR,
-					vkcv::SamplerFilterType::LINEAR,
-					vkcv::SamplerMipmapMode::LINEAR,
-					vkcv::SamplerAddressMode::REPEAT
-			);
+			samplers[0] = samplerLinear(core);
 		}
 		
 		if (!normalSmp) {
-			samplers[1] = core.createSampler(
-					vkcv::SamplerFilterType::LINEAR,
-					vkcv::SamplerFilterType::LINEAR,
-					vkcv::SamplerMipmapMode::LINEAR,
-					vkcv::SamplerAddressMode::REPEAT
-			);
+			samplers[1] = samplerLinear(core);
 		}
 		
 		if (!metRoughSmp) {
-			samplers[2] = core.createSampler(
-					vkcv::SamplerFilterType::LINEAR,
-					vkcv::SamplerFilterType::LINEAR,
-					vkcv::SamplerMipmapMode::LINEAR,
-					vkcv::SamplerAddressMode::REPEAT
-			);
+			samplers[2] = samplerLinear(core);
 		}
 		
 		if (!occlusionSmp) {
-			samplers[3] = core.createSampler(
-					vkcv::SamplerFilterType::LINEAR,
-					vkcv::SamplerFilterType::LINEAR,
-					vkcv::SamplerMipmapMode::LINEAR,
-					vkcv::SamplerAddressMode::REPEAT
-			);
+			samplers[3] = samplerLinear(core);
 		}
 		
 		if (!emissiveSmp) {
-			samplers[4] = core.createSampler(
-					vkcv::SamplerFilterType::LINEAR,
-					vkcv::SamplerFilterType::LINEAR,
-					vkcv::SamplerMipmapMode::LINEAR,
-					vkcv::SamplerAddressMode::REPEAT
-			);
+			samplers[4] = samplerLinear(core);
 		}
 		
 		Material material;
diff --git a/modules/scene/src/vkcv/scene/Scene.cpp b/modules/scene/src/vkcv/scene/Scene.cpp
index f702aa34..6ecfe34a 100644
--- a/modules/scene/src/vkcv/scene/Scene.cpp
+++ b/modules/scene/src/vkcv/scene/Scene.cpp
@@ -3,6 +3,7 @@
 
 #include <vkcv/Image.hpp>
 #include <vkcv/Logger.hpp>
+#include <vkcv/Sampler.hpp>
 #include <vkcv/asset/asset_loader.hpp>
 
 #include <vkcv/algorithm/SinglePassDownsampler.hpp>
@@ -236,7 +237,6 @@ namespace vkcv::scene {
 				minFilter,
 				mipmapMode,
 				addressMode,
-				
 				mipLodBias
 		);
 	}
@@ -338,12 +338,7 @@ namespace vkcv::scene {
 			scene.getNode(root).loadMesh(asset_scene, mesh);
 		}
 		
-		vkcv::SamplerHandle sampler = core.createSampler(
-				vkcv::SamplerFilterType::LINEAR,
-				vkcv::SamplerFilterType::LINEAR,
-				vkcv::SamplerMipmapMode::LINEAR,
-				vkcv::SamplerAddressMode::REPEAT
-		);
+		vkcv::SamplerHandle sampler = samplerLinear(core);
 		
 		const vkcv::FeatureManager& featureManager = core.getContext().getFeatureManager();
 		
diff --git a/projects/bindless_textures/src/main.cpp b/projects/bindless_textures/src/main.cpp
index 43247f69..c4e18699 100644
--- a/projects/bindless_textures/src/main.cpp
+++ b/projects/bindless_textures/src/main.cpp
@@ -3,6 +3,7 @@
 #include <vkcv/Core.hpp>
 #include <vkcv/Image.hpp>
 #include <vkcv/Pass.hpp>
+#include <vkcv/Sampler.hpp>
 #include <GLFW/glfw3.h>
 #include <vkcv/camera/CameraManager.hpp>
 #include <chrono>
@@ -180,17 +181,13 @@ int main(int argc, const char** argv) {
 	
 	core.submitCommandStream(downsampleStream, false);
 
-	vkcv::SamplerHandle sampler = core.createSampler(
-		vkcv::SamplerFilterType::LINEAR,
-		vkcv::SamplerFilterType::LINEAR,
-		vkcv::SamplerMipmapMode::LINEAR,
-		vkcv::SamplerAddressMode::REPEAT
-	);
+	vkcv::SamplerHandle sampler = vkcv::samplerLinear(core);
 
 	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::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[2].offset), vertexBuffer.getVulkanHandle())
+	};
 
 	vkcv::DescriptorWrites setWrites;
 	
diff --git a/projects/fire_works/src/main.cpp b/projects/fire_works/src/main.cpp
index 91c044e6..ffef4cd4 100644
--- a/projects/fire_works/src/main.cpp
+++ b/projects/fire_works/src/main.cpp
@@ -5,6 +5,7 @@
 #include <vkcv/Core.hpp>
 #include <vkcv/Image.hpp>
 #include <vkcv/Pass.hpp>
+#include <vkcv/Sampler.hpp>
 #include <vkcv/DrawcallRecording.hpp>
 
 #include <vkcv/camera/CameraManager.hpp>
@@ -786,12 +787,7 @@ int main(int argc, const char **argv) {
 			1, false, true
    	);
 	
-	vkcv::SamplerHandle voxelSampler = core.createSampler(
-		vkcv::SamplerFilterType::LINEAR,
-		vkcv::SamplerFilterType::LINEAR,
-		vkcv::SamplerMipmapMode::LINEAR,
-		vkcv::SamplerAddressMode::CLAMP_TO_EDGE
-	);
+	vkcv::SamplerHandle voxelSampler = vkcv::samplerLinear(core, true);
 	
 	vkcv::ShaderProgram voxelClearShader;
 	compiler.compile(vkcv::ShaderStage::COMPUTE, "shaders/clear.comp", [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp
index db985425..489fe0ad 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -3,6 +3,7 @@
 #include <vkcv/Core.hpp>
 #include <vkcv/Image.hpp>
 #include <vkcv/Pass.hpp>
+#include <vkcv/Sampler.hpp>
 #include <vkcv/camera/CameraManager.hpp>
 #include <vkcv/asset/asset_loader.hpp>
 #include <vkcv/shader/GLSLCompiler.hpp>
@@ -123,17 +124,13 @@ int main(int argc, const char** argv) {
 		core.submitCommandStream(cmdStream, false);
 	}
 
-	vkcv::SamplerHandle sampler = core.createSampler(
-		vkcv::SamplerFilterType::LINEAR,
-		vkcv::SamplerFilterType::LINEAR,
-		vkcv::SamplerMipmapMode::LINEAR,
-		vkcv::SamplerAddressMode::REPEAT
-	);
+	vkcv::SamplerHandle sampler = vkcv::samplerLinear(core);
 
 	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::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[2].offset), vertexBuffer.getVulkanHandle())
+	};
 
 	vkcv::DescriptorWrites setWrites;
 	setWrites.writeSampledImage(0, texture.getHandle());
diff --git a/projects/indirect_dispatch/src/App.cpp b/projects/indirect_dispatch/src/App.cpp
index 44eb74f8..ef5afaf1 100644
--- a/projects/indirect_dispatch/src/App.cpp
+++ b/projects/indirect_dispatch/src/App.cpp
@@ -1,7 +1,10 @@
 #include "App.hpp"
 #include "AppConfig.hpp"
-#include <chrono>
+
+#include <vkcv/Sampler.hpp>
 #include <vkcv/gui/GUI.hpp>
+
+#include <chrono>
 #include <functional>
 
 const char* MotionVectorVisualisationModeLabels[6] = {
@@ -60,12 +63,7 @@ bool App::initialize() {
 	if (!m_motionBlur.initialize(&m_core, m_windowWidth, m_windowHeight))
 		return false;
 
-	m_linearSampler = m_core.createSampler(
-		vkcv::SamplerFilterType::LINEAR,
-		vkcv::SamplerFilterType::LINEAR,
-		vkcv::SamplerMipmapMode::LINEAR,
-		vkcv::SamplerAddressMode::CLAMP_TO_EDGE);
-
+	m_linearSampler = vkcv::samplerLinear(m_core, true);
 	m_renderTargets = createRenderTargets(m_core, m_windowWidth, m_windowHeight);
 
 	const int cameraIndex = m_cameraManager.addCamera(vkcv::camera::ControllerType::PILOT);
diff --git a/projects/indirect_dispatch/src/MotionBlur.cpp b/projects/indirect_dispatch/src/MotionBlur.cpp
index adffd1ea..d90171de 100644
--- a/projects/indirect_dispatch/src/MotionBlur.cpp
+++ b/projects/indirect_dispatch/src/MotionBlur.cpp
@@ -1,8 +1,11 @@
 #include "MotionBlur.hpp"
 #include "MotionBlurConfig.hpp"
 #include "MotionBlurSetup.hpp"
-#include <array>
+
 #include <vkcv/Buffer.hpp>
+#include <vkcv/Sampler.hpp>
+
+#include <array>
 
 bool MotionBlur::initialize(vkcv::Core* corePtr, const uint32_t targetWidth, const uint32_t targetHeight) {
 
@@ -76,11 +79,7 @@ bool MotionBlur::initialize(vkcv::Core* corePtr, const uint32_t targetWidth, con
 
 	m_renderTargets = MotionBlurSetup::createRenderTargets(targetWidth, targetHeight, *m_core);
 
-	m_nearestSampler = m_core->createSampler(
-		vkcv::SamplerFilterType::NEAREST,
-		vkcv::SamplerFilterType::NEAREST,
-		vkcv::SamplerMipmapMode::NEAREST,
-		vkcv::SamplerAddressMode::CLAMP_TO_EDGE);
+	m_nearestSampler = vkcv::samplerNearest(*m_core, true);
 	
 	return true;
 }
diff --git a/projects/indirect_draw/src/main.cpp b/projects/indirect_draw/src/main.cpp
index d975d0c1..2f1f0845 100644
--- a/projects/indirect_draw/src/main.cpp
+++ b/projects/indirect_draw/src/main.cpp
@@ -2,9 +2,9 @@
 #include <vkcv/Buffer.hpp>
 #include <vkcv/Core.hpp>
 #include <vkcv/Pass.hpp>
+#include <vkcv/Sampler.hpp>
 #include <vkcv/Image.hpp>
 #include <vkcv/camera/CameraManager.hpp>
-#include <chrono>
 #include <vkcv/gui/GUI.hpp>
 #include <vkcv/asset/asset_loader.hpp>
 #include <vkcv/shader/GLSLCompiler.hpp>
@@ -444,12 +444,7 @@ int main(int argc, const char** argv) {
 	vkcv::DescriptorSetLayoutHandle descriptorSetLayout = core.createDescriptorSetLayout(descriptorBindings);
 	vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorSetLayout);
 
-    vkcv::SamplerHandle standardSampler = core.createSampler(
-            vkcv::SamplerFilterType::LINEAR,
-            vkcv::SamplerFilterType::LINEAR,
-            vkcv::SamplerMipmapMode::LINEAR,
-            vkcv::SamplerAddressMode::REPEAT
-    );
+    vkcv::SamplerHandle standardSampler = vkcv::samplerLinear(core);
 	
 	vkcv::DescriptorWrites setWrites;
 	
diff --git a/projects/saf_r/src/main.cpp b/projects/saf_r/src/main.cpp
index 16149c1b..2ddbd0cf 100644
--- a/projects/saf_r/src/main.cpp
+++ b/projects/saf_r/src/main.cpp
@@ -2,14 +2,17 @@
 #include <vkcv/Core.hpp>
 #include <vkcv/Buffer.hpp>
 #include <vkcv/Pass.hpp>
-#include <GLFW/glfw3.h>
+#include <vkcv/Sampler.hpp>
+
 #include <vkcv/camera/CameraManager.hpp>
 #include <vkcv/asset/asset_loader.hpp>
 #include <vkcv/shader/GLSLCompiler.hpp>
-#include <chrono>
+
 #include <cmath>
 #include <vector>
 #include <cstring>
+#include <GLFW/glfw3.h>
+
 #include "safrScene.hpp"
 
 void createQuadraticLightCluster(std::vector<safrScene::Light>& lights, int countPerDimension, float dimension, float height, float intensity) {
@@ -114,12 +117,7 @@ int main(int argc, const char** argv) {
     */
     createQuadraticLightCluster(lights, 10, 2.5f, 20, 1.5f);
 	
-	vkcv::SamplerHandle sampler = core.createSampler(
-		vkcv::SamplerFilterType::LINEAR,
-		vkcv::SamplerFilterType::LINEAR,
-		vkcv::SamplerMipmapMode::LINEAR,
-		vkcv::SamplerAddressMode::REPEAT
-	);
+	vkcv::SamplerHandle sampler = vkcv::samplerLinear(core);
 	
 	//create Buffer for compute shader
 	vkcv::Buffer<safrScene::Light> lightsBuffer = vkcv::buffer<safrScene::Light>(
diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp
index 139f22fe..862ac3c2 100644
--- a/projects/voxelization/src/main.cpp
+++ b/projects/voxelization/src/main.cpp
@@ -1,6 +1,7 @@
 #include <iostream>
 #include <vkcv/Core.hpp>
 #include <vkcv/Pass.hpp>
+#include <vkcv/Sampler.hpp>
 #include <GLFW/glfw3.h>
 #include <vkcv/camera/CameraManager.hpp>
 #include <chrono>
@@ -244,12 +245,7 @@ int main(int argc, const char** argv) {
 	vkcv::PassHandle prepassPass = vkcv::passFormat(core, depthBufferFormat, true, msaa);
 
 	// create descriptor sets
-	vkcv::SamplerHandle colorSampler = core.createSampler(
-		vkcv::SamplerFilterType::LINEAR,
-		vkcv::SamplerFilterType::LINEAR,
-		vkcv::SamplerMipmapMode::LINEAR,
-		vkcv::SamplerAddressMode::REPEAT
-	);
+	vkcv::SamplerHandle colorSampler = vkcv::samplerLinear(core);
 
 	std::vector<vkcv::DescriptorSetLayoutHandle> materialDescriptorSetLayouts;
 	std::vector<vkcv::DescriptorSetHandle> materialDescriptorSets;
@@ -503,12 +499,7 @@ int main(int argc, const char** argv) {
 		{ resolveDescriptorSetLayout }
 	});
 
-	vkcv::SamplerHandle resolveSampler = core.createSampler(
-		vkcv::SamplerFilterType::NEAREST,
-		vkcv::SamplerFilterType::NEAREST,
-		vkcv::SamplerMipmapMode::NEAREST,
-		vkcv::SamplerAddressMode::CLAMP_TO_EDGE
-	);
+	vkcv::SamplerHandle resolveSampler = vkcv::samplerNearest(core, true);
 
 	// model matrices per mesh
 	std::vector<glm::mat4> modelMatrices;
@@ -539,12 +530,7 @@ int main(int argc, const char** argv) {
 			vkcv::DescriptorSetUsage(1, perMeshDescriptorSets[i]) }));
 	}
 
-	vkcv::SamplerHandle voxelSampler = core.createSampler(
-		vkcv::SamplerFilterType::LINEAR,
-		vkcv::SamplerFilterType::LINEAR,
-		vkcv::SamplerMipmapMode::LINEAR,
-		vkcv::SamplerAddressMode::CLAMP_TO_EDGE
-	);
+	vkcv::SamplerHandle voxelSampler = vkcv::samplerLinear(core, true);
 
 	ShadowMapping shadowMapping(&core, vertexLayout);
 
diff --git a/src/vkcv/Sampler.cpp b/src/vkcv/Sampler.cpp
new file mode 100644
index 00000000..f122608a
--- /dev/null
+++ b/src/vkcv/Sampler.cpp
@@ -0,0 +1,28 @@
+
+#include "vkcv/Sampler.hpp"
+
+namespace vkcv {
+	
+	SamplerHandle samplerLinear(Core &core, bool clampToEdge) {
+		return core.createSampler(
+				vkcv::SamplerFilterType::LINEAR,
+				vkcv::SamplerFilterType::LINEAR,
+				vkcv::SamplerMipmapMode::LINEAR,
+				clampToEdge?
+					vkcv::SamplerAddressMode::CLAMP_TO_EDGE :
+					vkcv::SamplerAddressMode::REPEAT
+		);
+	}
+	
+	SamplerHandle samplerNearest(Core &core, bool clampToEdge) {
+		return core.createSampler(
+				vkcv::SamplerFilterType::NEAREST,
+				vkcv::SamplerFilterType::NEAREST,
+				vkcv::SamplerMipmapMode::NEAREST,
+				clampToEdge?
+				vkcv::SamplerAddressMode::CLAMP_TO_EDGE :
+				vkcv::SamplerAddressMode::REPEAT
+		);
+	}
+	
+}
-- 
GitLab