|
2 | 2 | #define __NBL_C_SURFACE_VULKAN_H_INCLUDED__
|
3 | 3 |
|
4 | 4 | #include "nbl/video/surface/ISurface.h"
|
5 |
| -#include "nbl/video/CVulkanCommon.h" |
6 |
| -#include "nbl/video/CVulkanPhysicalDevice.h" |
7 | 5 | #include "nbl/video/CVulkanConnection.h"
|
8 | 6 |
|
9 | 7 | #include "nbl/ui/IWindowAndroid.h"
|
10 | 8 |
|
11 | 9 | namespace nbl::video
|
12 | 10 | {
|
13 | 11 |
|
14 |
| -class CVulkanConnection; |
15 |
| -class CVulkanPhysicalDevice; |
16 | 12 |
|
17 |
| -template <typename Window> |
18 |
| -class CSurfaceVulkan final : public CSurface<Window> |
| 13 | +#include "volk.h" |
| 14 | + |
| 15 | +class ISurfaceVulkan : public ISurface |
19 | 16 | {
|
| 17 | + using base_t = ISurface; |
20 | 18 | public:
|
21 |
| - using this_t = CSurfaceVulkan<Window>; |
22 |
| - using base_t = CSurface<Window>; |
| 19 | + bool isSupportedForPhysicalDevice(const IPhysicalDevice* dev, uint32_t _queueFamIx) const override; |
| 20 | + void getAvailableFormatsForPhysicalDevice(const IPhysicalDevice* physicalDevice, uint32_t& formatCount, ISurface::SFormat* formats) const override; |
| 21 | + E_PRESENT_MODE getAvailablePresentModesForPhysicalDevice(const IPhysicalDevice* physicalDevice) const override; |
| 22 | + bool getSurfaceCapabilitiesForPhysicalDevice(const IPhysicalDevice* physicalDevice, ISurface::SCapabilities& capabilities) const override; |
23 | 23 |
|
24 |
| - static inline core::smart_refctd_ptr<this_t> create(core::smart_refctd_ptr<video::CVulkanConnection>&& api, core::smart_refctd_ptr<Window>&& window) |
25 |
| - { |
26 |
| - if (!api || !window) |
27 |
| - return nullptr; |
| 24 | + inline VkSurfaceKHR getInternalObject() const { return m_vkSurfaceKHR; } |
28 | 25 |
|
29 |
| - #ifdef _NBL_PLATFORM_WINDOWS_ |
30 |
| - // This needs to know what ui::IWindowWin32 is! Won't work on other platforms! |
31 |
| - if constexpr (std::is_same_v<Window, ui::IWindowWin32>) |
32 |
| - { |
33 |
| - VkWin32SurfaceCreateInfoKHR createInfo = { VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR }; |
34 |
| - createInfo.pNext = nullptr; // pNext must be NULL |
35 |
| - createInfo.flags = static_cast<VkWin32SurfaceCreateFlagsKHR>(0); |
36 |
| - createInfo.hinstance = GetModuleHandle(NULL); |
37 |
| - createInfo.hwnd = (static_cast<HWND>(window->getNativeHandle())); |
| 26 | +protected: |
| 27 | + explicit ISurfaceVulkan(core::smart_refctd_ptr<video::IAPIConnection>&& api, VkSurfaceKHR vk_surface) : base_t(std::move(api)), m_vkSurfaceKHR(vk_surface) {} |
| 28 | + virtual ~ISurfaceVulkan() = default; |
38 | 29 |
|
39 |
| - VkSurfaceKHR vk_surface; |
40 |
| - if (vkCreateWin32SurfaceKHR(api->getInternalObject(), &createInfo, nullptr, |
41 |
| - &vk_surface) == VK_SUCCESS) |
42 |
| - { |
43 |
| - auto retval = new this_t(std::move(api), std::move(window), vk_surface); |
44 |
| - return core::smart_refctd_ptr<this_t>(retval, core::dont_grab); |
45 |
| - } |
46 |
| - else |
47 |
| - { |
48 |
| - return nullptr; |
49 |
| - } |
50 |
| - } |
51 |
| - #else |
52 |
| - return nullptr; |
53 |
| - #endif |
54 |
| - } |
| 30 | + VkSurfaceKHR m_vkSurfaceKHR = VK_NULL_HANDLE; |
| 31 | +}; |
55 | 32 |
|
56 |
| - inline bool isSupportedForPhysicalDevice(const IPhysicalDevice* dev, uint32_t _queueFamIx) const override |
| 33 | +#ifdef _NBL_PLATFORM_WINDOWS_ |
| 34 | +class CSurfaceVulkanWin32 final : public CSurface<ui::IWindowWin32, ISurfaceVulkan> |
| 35 | +{ |
| 36 | + using this_t = CSurfaceVulkanWin32; |
| 37 | + using base_t = CSurface<ui::IWindowWin32, ISurfaceVulkan>; |
| 38 | +public: |
| 39 | + CSurfaceVulkanWin32(core::smart_refctd_ptr<ui::IWindowWin32>&& window, core::smart_refctd_ptr<IAPIConnection>&& api, VkSurfaceKHR surf) : |
| 40 | + base_t(std::move(window), std::move(api), surf) |
57 | 41 | {
|
58 |
| - if (dev->getAPIType() != EAT_VULKAN) |
59 |
| - return false; |
60 |
| - |
61 |
| - VkPhysicalDevice vk_physicalDevice = static_cast<const CVulkanPhysicalDevice*>(dev)->getInternalObject(); |
62 |
| - |
63 |
| - VkBool32 supported; |
64 |
| - if (vkGetPhysicalDeviceSurfaceSupportKHR(vk_physicalDevice, _queueFamIx, m_vkSurfaceKHR, &supported) == VK_SUCCESS) |
65 |
| - { |
66 |
| - return static_cast<bool>(supported); |
67 |
| - } |
68 |
| - else |
69 |
| - { |
70 |
| - return false; |
71 |
| - } |
72 | 42 | }
|
73 |
| - |
74 |
| - inline void getAvailableFormatsForPhysicalDevice(const IPhysicalDevice* physicalDevice, uint32_t& formatCount, ISurface::SFormat* formats) const override |
| 43 | + static inline core::smart_refctd_ptr<this_t> create(core::smart_refctd_ptr<video::CVulkanConnection>&& api, core::smart_refctd_ptr<ui::IWindowWin32>&& window) |
75 | 44 | {
|
76 |
| - constexpr uint32_t MAX_SURFACE_FORMAT_COUNT = 1000u; |
77 |
| - |
78 |
| - if (physicalDevice && physicalDevice->getAPIType() != EAT_VULKAN) |
79 |
| - return; |
80 |
| - |
81 |
| - VkPhysicalDevice vk_physicalDevice = static_cast<const CVulkanPhysicalDevice*>(physicalDevice)->getInternalObject(); |
82 |
| - |
83 |
| - VkResult retval = vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physicalDevice, m_vkSurfaceKHR, |
84 |
| - &formatCount, nullptr); |
85 |
| - |
86 |
| - if ((retval != VK_SUCCESS) && (retval != VK_INCOMPLETE)) |
87 |
| - { |
88 |
| - formatCount = 0u; |
89 |
| - return; |
90 |
| - } |
91 |
| - |
92 |
| - if (!formats) |
93 |
| - return; |
94 |
| - |
95 |
| - VkSurfaceFormatKHR vk_formats[MAX_SURFACE_FORMAT_COUNT]; |
96 |
| - retval = vkGetPhysicalDeviceSurfaceFormatsKHR(vk_physicalDevice, m_vkSurfaceKHR, |
97 |
| - &formatCount, vk_formats); |
| 45 | + if (!api || !window) |
| 46 | + return nullptr; |
98 | 47 |
|
99 |
| - if ((retval != VK_SUCCESS) && (retval != VK_INCOMPLETE)) |
100 |
| - { |
101 |
| - formatCount = 0u; |
102 |
| - formats = nullptr; |
103 |
| - return; |
104 |
| - } |
| 48 | + VkWin32SurfaceCreateInfoKHR createInfo = { VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR }; |
| 49 | + createInfo.pNext = nullptr; // pNext must be NULL |
| 50 | + createInfo.flags = static_cast<VkWin32SurfaceCreateFlagsKHR>(0); |
| 51 | + createInfo.hinstance = GetModuleHandle(NULL); |
| 52 | + createInfo.hwnd = static_cast<HWND>(window->getNativeHandle()); |
105 | 53 |
|
106 |
| - for (uint32_t i = 0u; i < formatCount; ++i) |
| 54 | + VkSurfaceKHR vk_surface; |
| 55 | + // `vkCreateWin32SurfaceKHR` is taken from `volk` (cause it uses `extern` globals like a n00b) |
| 56 | + if (vkCreateWin32SurfaceKHR(api->getInternalObject(), &createInfo, nullptr, &vk_surface) == VK_SUCCESS) |
107 | 57 | {
|
108 |
| - formats[i].format = getFormatFromVkFormat(vk_formats[i].format); |
109 |
| - formats[i].colorSpace = getColorSpaceFromVkColorSpaceKHR(vk_formats[i].colorSpace); |
| 58 | + auto retval = new this_t(std::move(window), std::move(api), vk_surface); |
| 59 | + return core::smart_refctd_ptr<this_t>(retval, core::dont_grab); |
110 | 60 | }
|
111 |
| - } |
112 |
| - |
113 |
| - inline ISurface::E_PRESENT_MODE getAvailablePresentModesForPhysicalDevice(const IPhysicalDevice* physicalDevice) const override |
114 |
| - { |
115 |
| - constexpr uint32_t MAX_PRESENT_MODE_COUNT = 4u; |
116 |
| - |
117 |
| - ISurface::E_PRESENT_MODE result = ISurface::EPM_UNKNOWN; |
118 |
| - |
119 |
| - if (physicalDevice && physicalDevice->getAPIType() != EAT_VULKAN) |
120 |
| - return result; |
121 |
| - |
122 |
| - VkPhysicalDevice vk_physicalDevice = static_cast<const CVulkanPhysicalDevice*>(physicalDevice)->getInternalObject(); |
123 |
| - |
124 |
| - uint32_t count = 0u; |
125 |
| - VkResult retval = vkGetPhysicalDeviceSurfacePresentModesKHR(vk_physicalDevice, m_vkSurfaceKHR, |
126 |
| - &count, nullptr); |
127 |
| - |
128 |
| - if ((retval != VK_SUCCESS) && (retval != VK_INCOMPLETE)) |
129 |
| - return result; |
130 |
| - |
131 |
| - assert(count <= MAX_PRESENT_MODE_COUNT); |
132 |
| - |
133 |
| - VkPresentModeKHR vk_presentModes[MAX_PRESENT_MODE_COUNT]; |
134 |
| - retval = vkGetPhysicalDeviceSurfacePresentModesKHR(vk_physicalDevice, m_vkSurfaceKHR, |
135 |
| - &count, vk_presentModes); |
136 |
| - |
137 |
| - if ((retval != VK_SUCCESS) && (retval != VK_INCOMPLETE)) |
138 |
| - return result; |
139 |
| - |
140 |
| - for (uint32_t i = 0u; i < count; ++i) |
141 |
| - result = static_cast<ISurface::E_PRESENT_MODE>(result | getPresentModeFromVkPresentModeKHR(vk_presentModes[i])); |
142 |
| - |
143 |
| - return result; |
144 |
| - } |
145 |
| - |
146 |
| - inline bool getSurfaceCapabilitiesForPhysicalDevice(const IPhysicalDevice* physicalDevice, ISurface::SCapabilities& capabilities) const override |
147 |
| - { |
148 |
| - if (physicalDevice && physicalDevice->getAPIType() != EAT_VULKAN) |
149 |
| - return false; |
150 |
| - |
151 |
| - VkPhysicalDevice vk_physicalDevice = static_cast<const CVulkanPhysicalDevice*>(physicalDevice)->getInternalObject(); |
152 |
| - |
153 |
| - VkSurfaceCapabilitiesKHR vk_surfaceCapabilities; |
154 |
| - if (vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk_physicalDevice, m_vkSurfaceKHR, |
155 |
| - &vk_surfaceCapabilities) != VK_SUCCESS) |
| 61 | + else |
156 | 62 | {
|
157 |
| - return false; |
| 63 | + return nullptr; |
158 | 64 | }
|
159 |
| - |
160 |
| - capabilities.minImageCount = vk_surfaceCapabilities.minImageCount; |
161 |
| - capabilities.maxImageCount = (vk_surfaceCapabilities.maxImageCount == 0u) ? ~0u : vk_surfaceCapabilities.maxImageCount; |
162 |
| - capabilities.currentExtent = vk_surfaceCapabilities.currentExtent; |
163 |
| - capabilities.minImageExtent = vk_surfaceCapabilities.minImageExtent; |
164 |
| - capabilities.maxImageExtent = vk_surfaceCapabilities.maxImageExtent; |
165 |
| - capabilities.maxImageArrayLayers = vk_surfaceCapabilities.maxImageArrayLayers; |
166 |
| - capabilities.supportedTransforms = static_cast<ISurface::E_SURFACE_TRANSFORM_FLAGS>(vk_surfaceCapabilities.supportedTransforms); |
167 |
| - capabilities.currentTransform = static_cast<ISurface::E_SURFACE_TRANSFORM_FLAGS>(vk_surfaceCapabilities.currentTransform); |
168 |
| - capabilities.supportedCompositeAlpha = static_cast<ISurface::E_COMPOSITE_ALPHA>(vk_surfaceCapabilities.supportedCompositeAlpha); |
169 |
| - capabilities.supportedUsageFlags = static_cast<asset::IImage::E_USAGE_FLAGS>(vk_surfaceCapabilities.supportedUsageFlags); |
170 |
| - |
171 |
| - return true; |
172 |
| - } |
173 |
| - |
174 |
| - inline VkSurfaceKHR getInternalObject() const { return m_vkSurfaceKHR; } |
175 |
| - |
176 |
| -protected: |
177 |
| - explicit CSurfaceVulkan(core::smart_refctd_ptr<video::CVulkanConnection>&& api, |
178 |
| - core::smart_refctd_ptr<Window>&& window, VkSurfaceKHR vk_surface) |
179 |
| - : base_t(std::move(api), std::move(window)), m_vkSurfaceKHR(vk_surface) |
180 |
| - {} |
181 |
| - |
182 |
| - inline ~CSurfaceVulkan() |
183 |
| - { |
184 |
| - VkInstance vk_instance = static_cast<const CVulkanConnection*>(base_t::m_api.get())->getInternalObject(); |
185 |
| - vkDestroySurfaceKHR(vk_instance, m_vkSurfaceKHR, nullptr); |
186 | 65 | }
|
187 |
| - |
188 |
| - VkSurfaceKHR m_vkSurfaceKHR = VK_NULL_HANDLE; |
189 | 66 | };
|
190 |
| - |
191 |
| -#ifdef _NBL_PLATFORM_WINDOWS_ |
192 |
| -using CSurfaceVulkanWin32 = CSurfaceVulkan<ui::IWindowWin32>; |
193 | 67 | #elif defined _NBL_PLATFORM_LINUX_
|
194 |
| -using CSurfaceVulkanX11 = CSurfaceVulkan<ui::IWindowX11>; |
| 68 | +// TODO: later, not this week |
195 | 69 | #elif defined _NBL_PLATFORM_ANDROID_
|
196 |
| -using CSurfaceVulkanAndroid = CSurfaceVulkan<ui::IWindowAndroid>; |
| 70 | +// TODO: later, not this week |
197 | 71 | #endif
|
198 | 72 | }
|
199 | 73 |
|
|
0 commit comments