]> git.tdb.fi Git - libs/gl.git/blobdiff - source/backends/vulkan/sampler_backend.cpp
Implement textures and samplers for Vulkan
[libs/gl.git] / source / backends / vulkan / sampler_backend.cpp
index f4162ed0b2c7eb714f3a8da428b86c96a458802c..134be91b018ea052601aab04d14adeafae13053e 100644 (file)
+#include "destroyqueue.h"
+#include "device.h"
 #include "sampler.h"
 #include "sampler_backend.h"
+#include "vulkan.h"
 
 using namespace std;
 
 namespace Msp {
 namespace GL {
 
-VulkanSampler::VulkanSampler()
-{
-       throw logic_error("VulkanSampler is unimplemented");
-}
+VulkanSampler::VulkanSampler():
+       device(Device::get_current())
+{ }
 
 VulkanSampler::VulkanSampler(VulkanSampler &&other):
-       handle(other.handle)
+       device(other.device),
+       handle(other.handle),
+       debug_name(move(other.debug_name))
 {
        other.handle = 0;
 }
 
 VulkanSampler::~VulkanSampler()
-{ }
+{
+       if(handle)
+               device.get_destroy_queue().destroy(handle);
+}
 
 void VulkanSampler::update(unsigned) const
-{ }
+{
+       const Sampler &self = *static_cast<const Sampler *>(this);
+       const VulkanFunctions &vk = device.get_functions();
 
-void VulkanSampler::set_debug_name(const string &)
-{ }
+       if(handle)
+               device.get_destroy_queue().destroy(handle);
+
+       VkSamplerCreateInfo sampler_info = { };
+       sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
+       sampler_info.magFilter = static_cast<VkFilter>(get_vulkan_filter(self.mag_filter));
+       sampler_info.minFilter = static_cast<VkFilter>(get_vulkan_filter(self.min_filter));
+       sampler_info.mipmapMode = static_cast<VkSamplerMipmapMode>(get_vulkan_mipmap_mode(self.min_filter));
+       sampler_info.addressModeU = static_cast<VkSamplerAddressMode>(get_vulkan_address_mode(self.wrap_s));
+       sampler_info.addressModeV = static_cast<VkSamplerAddressMode>(get_vulkan_address_mode(self.wrap_t));
+       sampler_info.addressModeW = static_cast<VkSamplerAddressMode>(get_vulkan_address_mode(self.wrap_r));
+       sampler_info.anisotropyEnable = (self.max_anisotropy>1.0f);
+       sampler_info.maxAnisotropy = self.max_anisotropy;
+       sampler_info.compareEnable = self.compare;
+       sampler_info.compareOp = static_cast<VkCompareOp>(get_vulkan_predicate(self.cmp_func));
+       sampler_info.maxLod = VK_LOD_CLAMP_NONE;
+       // TODO Vulkan does not allow arbitrary border colors
+
+       vk.CreateSampler(sampler_info, handle);
+
+#ifdef DEBUG
+       if(!debug_name.empty())
+               set_vulkan_object_name();
+#endif
+}
+
+void VulkanSampler::set_debug_name(const string &name)
+{
+#ifdef DEBUG
+       debug_name = name;
+       if(handle)
+               set_vulkan_object_name();
+#else
+       (void)name;
+#endif
+}
+
+void VulkanSampler::set_vulkan_object_name() const
+{
+#ifdef DEBUG
+       const VulkanFunctions &vk = device.get_functions();
+
+       VkDebugUtilsObjectNameInfoEXT name_info = { };
+       name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+       name_info.objectType = VK_OBJECT_TYPE_SAMPLER;
+       name_info.objectHandle = reinterpret_cast<uint64_t>(handle);
+       name_info.pObjectName = debug_name.c_str();
+       vk.SetDebugUtilsObjectName(name_info);
+#endif
+}
+
+
+unsigned get_vulkan_filter(unsigned filter)
+{
+       switch(filter)
+       {
+       case NEAREST:
+       case NEAREST_MIPMAP_NEAREST:
+       case NEAREST_MIPMAP_LINEAR: return VK_FILTER_NEAREST;
+       case LINEAR:
+       case LINEAR_MIPMAP_NEAREST:
+       case LINEAR_MIPMAP_LINEAR: return VK_FILTER_LINEAR;
+       default: throw invalid_argument("get_vulkan_filter");
+       }
+}
+
+unsigned get_vulkan_mipmap_mode(unsigned filter)
+{
+       switch(filter)
+       {
+       case NEAREST:
+       case LINEAR: return VK_SAMPLER_MIPMAP_MODE_NEAREST;
+       case NEAREST_MIPMAP_NEAREST:
+       case NEAREST_MIPMAP_LINEAR:
+       case LINEAR_MIPMAP_NEAREST:
+       case LINEAR_MIPMAP_LINEAR: return VK_SAMPLER_MIPMAP_MODE_LINEAR;
+       default: throw invalid_argument("get_vulkan_mipmap_mode");
+       }
+}
+
+unsigned get_vulkan_address_mode(unsigned wrap)
+{
+       switch(wrap)
+       {
+       case REPEAT: return VK_SAMPLER_ADDRESS_MODE_REPEAT;
+       case CLAMP_TO_EDGE: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+       case CLAMP_TO_BORDER: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
+       case MIRRORED_REPEAT: return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
+       default: throw invalid_argument("get_vulkan_address_mode");
+       }
+}
 
 } // namespace GL
 } // namespace Msp