+#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