yum-mirror/slang

Making it easier to work with shaders

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

Theresa FoleyAdd an example for reflection of parameter blocks (#6161)31bb5eaa0

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