yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie Hermaszewskaformatf65d756bf

master
8.3 KiB267 linesraw
1#include "vulkan-api.h"
2
3#include "slang.h"
4
5#include <assert.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <vector>
10
11#if SLANG_WINDOWS_FAMILY
12#include <windows.h>
13#else
14#include <dlfcn.h>
15#endif
16
17#if _DEBUG
18#define ENABLE_VALIDATION_LAYER 1
19#endif
20
21VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageCallback(
22    VkDebugReportFlagsEXT /*flags*/,
23    VkDebugReportObjectTypeEXT /*objType*/,
24    uint64_t /*srcObject*/,
25    size_t /*location*/,
26    int32_t /*msgCode*/,
27    const char* pLayerPrefix,
28    const char* pMsg,
29    void* /*pUserData*/
30)
31{
32    printf("[%s]: %s\n", pLayerPrefix, pMsg);
33    return 1;
34}
35
36int initializeVulkanDevice(VulkanAPI& api)
37{
38    // Load vulkan library.
39    const char* dynamicLibraryName = "Unknown";
40
41#if SLANG_WINDOWS_FAMILY
42    dynamicLibraryName = "vulkan-1.dll";
43    HMODULE module = ::LoadLibraryA(dynamicLibraryName);
44    api.vulkanLibraryHandle = (void*)module;
45#define VK_API_GET_GLOBAL_PROC(x) api.x = (PFN_##x)GetProcAddress(module, #x);
46#elif SLANG_APPLE_FAMILY
47    dynamicLibraryName = "libvulkan.dylib";
48    api.vulkanLibraryHandle = dlopen(dynamicLibraryName, RTLD_NOW);
49#define VK_API_GET_GLOBAL_PROC(x) api.x = (PFN_##x)dlsym(api.vulkanLibraryHandle, #x);
50#else
51    dynamicLibraryName = "libvulkan.so.1";
52    api.vulkanLibraryHandle = dlopen(dynamicLibraryName, RTLD_NOW);
53#define VK_API_GET_GLOBAL_PROC(x) api.x = (PFN_##x)dlsym(api.vulkanLibraryHandle, #x);
54#endif
55
56    // Initialize all the global functions.
57    VK_API_ALL_GLOBAL_PROCS(VK_API_GET_GLOBAL_PROC)
58    if (!api.vkCreateInstance)
59        return -1;
60
61    // Enable validation layer if available.
62    std::vector<const char*> layers;
63#ifdef ENABLE_VALIDATION_LAYER
64    uint32_t propertyCount;
65    if (api.vkEnumerateInstanceLayerProperties(&propertyCount, nullptr) != 0)
66        return -1;
67    std::vector<VkLayerProperties> properties(propertyCount);
68    if (api.vkEnumerateInstanceLayerProperties(&propertyCount, properties.data()) != 0)
69        return -1;
70    for (const auto& p : properties)
71    {
72        if (strcmp(p.layerName, "VK_LAYER_KHRONOS_validation") == 0)
73        {
74            layers.push_back("VK_LAYER_KHRONOS_validation");
75        }
76    }
77#endif
78
79    // Create Vulkan Instance.
80    VkApplicationInfo applicationInfo = {VK_STRUCTURE_TYPE_APPLICATION_INFO};
81    applicationInfo.pApplicationName = "slang-hello-world";
82    applicationInfo.pEngineName = "slang-hello-world";
83    applicationInfo.apiVersion = VK_API_VERSION_1_2;
84    applicationInfo.engineVersion = 1;
85    applicationInfo.applicationVersion = 1;
86    const char* instanceExtensions[] = {
87#if SLANG_APPLE_FAMILY
88        VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
89#endif
90        VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
91        VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
92    };
93    VkInstanceCreateInfo instanceCreateInfo = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO};
94#if SLANG_APPLE_FAMILY
95    instanceCreateInfo.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
96#endif
97    instanceCreateInfo.pApplicationInfo = &applicationInfo;
98    instanceCreateInfo.enabledExtensionCount = SLANG_COUNT_OF(instanceExtensions);
99    instanceCreateInfo.ppEnabledExtensionNames = &instanceExtensions[0];
100    if (layers.size())
101    {
102        instanceCreateInfo.ppEnabledLayerNames = &layers[0];
103        instanceCreateInfo.enabledLayerCount = (uint32_t)layers.size();
104    }
105    if (api.vkCreateInstance(&instanceCreateInfo, nullptr, &api.instance) != 0)
106        return -1;
107
108    // Load instance functions.
109    api.initInstanceProcs();
110
111    // Create debug report callback.
112    if (api.vkCreateDebugReportCallbackEXT)
113    {
114        VkDebugReportFlagsEXT debugFlags =
115            VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
116
117        VkDebugReportCallbackCreateInfoEXT debugCreateInfo = {
118            VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT};
119        debugCreateInfo.pfnCallback = &debugMessageCallback;
120        debugCreateInfo.pUserData = nullptr;
121        debugCreateInfo.flags = debugFlags;
122
123        RETURN_ON_FAIL(api.vkCreateDebugReportCallbackEXT(
124            api.instance,
125            &debugCreateInfo,
126            nullptr,
127            &api.debugReportCallback));
128    }
129
130    // Enumerate physical devices.
131    uint32_t numPhysicalDevices = 0;
132    RETURN_ON_FAIL(api.vkEnumeratePhysicalDevices(api.instance, &numPhysicalDevices, nullptr));
133    std::vector<VkPhysicalDevice> physicalDevices;
134    physicalDevices.resize(numPhysicalDevices);
135    RETURN_ON_FAIL(
136        api.vkEnumeratePhysicalDevices(api.instance, &numPhysicalDevices, &physicalDevices[0]));
137
138    // We will use device 0.
139    api.initPhysicalDevice(physicalDevices[0]);
140
141    VkDeviceCreateInfo deviceCreateInfo = {VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO};
142    deviceCreateInfo.queueCreateInfoCount = 1;
143    deviceCreateInfo.pEnabledFeatures = &api.deviceFeatures;
144
145    // Find proper queue family index.
146    uint32_t numQueueFamilies = 0;
147    api.vkGetPhysicalDeviceQueueFamilyProperties(api.physicalDevice, &numQueueFamilies, nullptr);
148
149    std::vector<VkQueueFamilyProperties> queueFamilies;
150    queueFamilies.resize(numQueueFamilies);
151    api.vkGetPhysicalDeviceQueueFamilyProperties(
152        api.physicalDevice,
153        &numQueueFamilies,
154        &queueFamilies[0]);
155
156    // Find a queue that can service our needs.
157    auto requiredQueueFlags = VK_QUEUE_COMPUTE_BIT;
158    for (int i = 0; i < int(numQueueFamilies); ++i)
159    {
160        if ((queueFamilies[i].queueFlags & requiredQueueFlags) == requiredQueueFlags)
161        {
162            api.queueFamilyIndex = i;
163            break;
164        }
165    }
166    if (api.queueFamilyIndex == -1)
167        return -1;
168
169#if SLANG_APPLE_FAMILY
170    const char* deviceExtensions[] = {
171        "VK_KHR_portability_subset",
172    };
173#endif
174
175    VkDeviceQueueCreateInfo queueCreateInfo = {VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO};
176    float queuePriority = 0.0f;
177    queueCreateInfo.queueFamilyIndex = api.queueFamilyIndex;
178    queueCreateInfo.queueCount = 1;
179    queueCreateInfo.pQueuePriorities = &queuePriority;
180    deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
181#if SLANG_APPLE_FAMILY
182    deviceCreateInfo.enabledExtensionCount = SLANG_COUNT_OF(deviceExtensions);
183    deviceCreateInfo.ppEnabledExtensionNames = &deviceExtensions[0];
184#endif
185    RETURN_ON_FAIL(api.vkCreateDevice(api.physicalDevice, &deviceCreateInfo, nullptr, &api.device));
186
187    // Load device functions.
188    api.initDeviceProcs();
189
190    return 0;
191}
192
193int VulkanAPI::initInstanceProcs()
194{
195    assert(instance && vkGetInstanceProcAddr != nullptr);
196
197#define VK_API_GET_INSTANCE_PROC(x) x = (PFN_##x)vkGetInstanceProcAddr(instance, #x);
198
199    VK_API_ALL_INSTANCE_PROCS(VK_API_GET_INSTANCE_PROC)
200    // Get optional
201    VK_API_INSTANCE_PROCS_OPT(VK_API_GET_INSTANCE_PROC)
202
203#undef VK_API_GET_INSTANCE_PROC
204
205    return 0;
206}
207
208int VulkanAPI::initPhysicalDevice(VkPhysicalDevice inPhysicalDevice)
209{
210    assert(physicalDevice == VK_NULL_HANDLE);
211    physicalDevice = inPhysicalDevice;
212
213    vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
214    vkGetPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
215    vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties);
216
217    return 0;
218}
219
220int VulkanAPI::initDeviceProcs()
221{
222    assert(instance && device && vkGetDeviceProcAddr != nullptr);
223
224#define VK_API_GET_DEVICE_PROC(x) x = (PFN_##x)vkGetDeviceProcAddr(device, #x);
225    VK_API_DEVICE_PROCS(VK_API_GET_DEVICE_PROC)
226#undef VK_API_GET_DEVICE_PROC
227
228    return 0;
229}
230
231int VulkanAPI::findMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties)
232{
233    assert(typeBits);
234
235    const int numMemoryTypes = int(deviceMemoryProperties.memoryTypeCount);
236
237    // bit holds current test bit against typeBits. Ie bit == 1 << typeBits
238
239    uint32_t bit = 1;
240    for (int i = 0; i < numMemoryTypes; ++i, bit += bit)
241    {
242        auto const& memoryType = deviceMemoryProperties.memoryTypes[i];
243        if ((typeBits & bit) && (memoryType.propertyFlags & properties) == properties)
244        {
245            return i;
246        }
247    }
248
249    // assert(!"failed to find a usable memory type");
250    return -1;
251}
252
253VulkanAPI::~VulkanAPI()
254{
255    if (vkDestroyDevice)
256    {
257        vkDestroyDevice(device, nullptr);
258    }
259    if (vkDestroyDebugReportCallbackEXT)
260    {
261        vkDestroyDebugReportCallbackEXT(instance, debugReportCallback, nullptr);
262    }
263    if (vkDestroyInstance)
264    {
265        vkDestroyInstance(instance, nullptr);
266    }
267}