]> git.tdb.fi Git - libs/gl.git/blob - source/backends/vulkan/sampler_backend.cpp
Implement textures and samplers for Vulkan
[libs/gl.git] / source / backends / vulkan / sampler_backend.cpp
1 #include "destroyqueue.h"
2 #include "device.h"
3 #include "sampler.h"
4 #include "sampler_backend.h"
5 #include "vulkan.h"
6
7 using namespace std;
8
9 namespace Msp {
10 namespace GL {
11
12 VulkanSampler::VulkanSampler():
13         device(Device::get_current())
14 { }
15
16 VulkanSampler::VulkanSampler(VulkanSampler &&other):
17         device(other.device),
18         handle(other.handle),
19         debug_name(move(other.debug_name))
20 {
21         other.handle = 0;
22 }
23
24 VulkanSampler::~VulkanSampler()
25 {
26         if(handle)
27                 device.get_destroy_queue().destroy(handle);
28 }
29
30 void VulkanSampler::update(unsigned) const
31 {
32         const Sampler &self = *static_cast<const Sampler *>(this);
33         const VulkanFunctions &vk = device.get_functions();
34
35         if(handle)
36                 device.get_destroy_queue().destroy(handle);
37
38         VkSamplerCreateInfo sampler_info = { };
39         sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
40         sampler_info.magFilter = static_cast<VkFilter>(get_vulkan_filter(self.mag_filter));
41         sampler_info.minFilter = static_cast<VkFilter>(get_vulkan_filter(self.min_filter));
42         sampler_info.mipmapMode = static_cast<VkSamplerMipmapMode>(get_vulkan_mipmap_mode(self.min_filter));
43         sampler_info.addressModeU = static_cast<VkSamplerAddressMode>(get_vulkan_address_mode(self.wrap_s));
44         sampler_info.addressModeV = static_cast<VkSamplerAddressMode>(get_vulkan_address_mode(self.wrap_t));
45         sampler_info.addressModeW = static_cast<VkSamplerAddressMode>(get_vulkan_address_mode(self.wrap_r));
46         sampler_info.anisotropyEnable = (self.max_anisotropy>1.0f);
47         sampler_info.maxAnisotropy = self.max_anisotropy;
48         sampler_info.compareEnable = self.compare;
49         sampler_info.compareOp = static_cast<VkCompareOp>(get_vulkan_predicate(self.cmp_func));
50         sampler_info.maxLod = VK_LOD_CLAMP_NONE;
51         // TODO Vulkan does not allow arbitrary border colors
52
53         vk.CreateSampler(sampler_info, handle);
54
55 #ifdef DEBUG
56         if(!debug_name.empty())
57                 set_vulkan_object_name();
58 #endif
59 }
60
61 void VulkanSampler::set_debug_name(const string &name)
62 {
63 #ifdef DEBUG
64         debug_name = name;
65         if(handle)
66                 set_vulkan_object_name();
67 #else
68         (void)name;
69 #endif
70 }
71
72 void VulkanSampler::set_vulkan_object_name() const
73 {
74 #ifdef DEBUG
75         const VulkanFunctions &vk = device.get_functions();
76
77         VkDebugUtilsObjectNameInfoEXT name_info = { };
78         name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
79         name_info.objectType = VK_OBJECT_TYPE_SAMPLER;
80         name_info.objectHandle = reinterpret_cast<uint64_t>(handle);
81         name_info.pObjectName = debug_name.c_str();
82         vk.SetDebugUtilsObjectName(name_info);
83 #endif
84 }
85
86
87 unsigned get_vulkan_filter(unsigned filter)
88 {
89         switch(filter)
90         {
91         case NEAREST:
92         case NEAREST_MIPMAP_NEAREST:
93         case NEAREST_MIPMAP_LINEAR: return VK_FILTER_NEAREST;
94         case LINEAR:
95         case LINEAR_MIPMAP_NEAREST:
96         case LINEAR_MIPMAP_LINEAR: return VK_FILTER_LINEAR;
97         default: throw invalid_argument("get_vulkan_filter");
98         }
99 }
100
101 unsigned get_vulkan_mipmap_mode(unsigned filter)
102 {
103         switch(filter)
104         {
105         case NEAREST:
106         case LINEAR: return VK_SAMPLER_MIPMAP_MODE_NEAREST;
107         case NEAREST_MIPMAP_NEAREST:
108         case NEAREST_MIPMAP_LINEAR:
109         case LINEAR_MIPMAP_NEAREST:
110         case LINEAR_MIPMAP_LINEAR: return VK_SAMPLER_MIPMAP_MODE_LINEAR;
111         default: throw invalid_argument("get_vulkan_mipmap_mode");
112         }
113 }
114
115 unsigned get_vulkan_address_mode(unsigned wrap)
116 {
117         switch(wrap)
118         {
119         case REPEAT: return VK_SAMPLER_ADDRESS_MODE_REPEAT;
120         case CLAMP_TO_EDGE: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
121         case CLAMP_TO_BORDER: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
122         case MIRRORED_REPEAT: return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
123         default: throw invalid_argument("get_vulkan_address_mode");
124         }
125 }
126
127 } // namespace GL
128 } // namespace Msp