1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
// vk-api.cpp
#include "vk-api.h"
#include "core/slang-list.h"
namespace gfx
{
using namespace Slang;
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! VulkanApi !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#define VK_API_CHECK_FUNCTION(x) &&hasFunction(#x, (void*)x)
#define VK_API_CHECK_FUNCTIONS(FUNCTION_LIST) true FUNCTION_LIST(VK_API_CHECK_FUNCTION)
static bool hasFunction(const char* name, void* ptr)
{
if (ptr)
return true;
#if 0
fprintf(stderr, "Missing required Vulkan function: %s\n", name);
#endif
return false;
}
bool VulkanApi::areDefined(ProcType type) const
{
switch (type)
{
case ProcType::Global:
return VK_API_CHECK_FUNCTIONS(VK_API_ALL_GLOBAL_PROCS);
case ProcType::Instance:
return VK_API_CHECK_FUNCTIONS(VK_API_ALL_INSTANCE_PROCS) &&
VK_API_CHECK_FUNCTIONS(VK_API_INSTANCE_KHR_PROCS);
case ProcType::Device:
return VK_API_CHECK_FUNCTIONS(VK_API_DEVICE_PROCS);
default:
{
assert(!"Unhandled type");
return false;
}
}
}
Slang::Result VulkanApi::initGlobalProcs(const VulkanModule& module)
{
#define VK_API_GET_GLOBAL_PROC(x) x = (PFN_##x)module.getFunction(#x);
// Initialize all the global functions
VK_API_ALL_GLOBAL_PROCS(VK_API_GET_GLOBAL_PROC)
if (!areDefined(ProcType::Global))
{
return SLANG_FAIL;
}
m_module = &module;
return SLANG_OK;
}
Slang::Result VulkanApi::initInstanceProcs(VkInstance instance)
{
assert(instance && vkGetInstanceProcAddr != nullptr);
#define VK_API_GET_INSTANCE_PROC(x) x = (PFN_##x)vkGetInstanceProcAddr(instance, #x);
VK_API_ALL_INSTANCE_PROCS(VK_API_GET_INSTANCE_PROC)
// Get optional
VK_API_INSTANCE_PROCS_OPT(VK_API_GET_INSTANCE_PROC)
if (!areDefined(ProcType::Instance))
{
return SLANG_FAIL;
}
m_instance = instance;
return SLANG_OK;
}
Slang::Result VulkanApi::initPhysicalDevice(VkPhysicalDevice physicalDevice)
{
assert(m_physicalDevice == VK_NULL_HANDLE);
m_physicalDevice = physicalDevice;
vkGetPhysicalDeviceProperties(m_physicalDevice, &m_deviceProperties);
vkGetPhysicalDeviceFeatures(m_physicalDevice, &m_deviceFeatures);
vkGetPhysicalDeviceMemoryProperties(m_physicalDevice, &m_deviceMemoryProperties);
return SLANG_OK;
}
Slang::Result VulkanApi::initDeviceProcs(VkDevice device)
{
assert(m_instance && device && vkGetDeviceProcAddr != nullptr);
#define VK_API_GET_DEVICE_PROC(x) x = (PFN_##x)vkGetDeviceProcAddr(device, #x);
VK_API_ALL_DEVICE_PROCS(VK_API_GET_DEVICE_PROC)
if (!areDefined(ProcType::Device))
{
return SLANG_FAIL;
}
if (!vkGetBufferDeviceAddressKHR && vkGetBufferDeviceAddressEXT)
vkGetBufferDeviceAddressKHR = vkGetBufferDeviceAddressEXT;
if (!vkGetBufferDeviceAddress && vkGetBufferDeviceAddressKHR)
vkGetBufferDeviceAddress = vkGetBufferDeviceAddressKHR;
if (!vkGetSemaphoreCounterValue && vkGetSemaphoreCounterValueKHR)
vkGetSemaphoreCounterValue = vkGetSemaphoreCounterValueKHR;
if (!vkSignalSemaphore && vkSignalSemaphoreKHR)
vkSignalSemaphore = vkSignalSemaphoreKHR;
m_device = device;
return SLANG_OK;
}
int VulkanApi::findMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties) const
{
assert(typeBits);
const int numMemoryTypes = int(m_deviceMemoryProperties.memoryTypeCount);
// bit holds current test bit against typeBits. Ie bit == 1 << typeBits
uint32_t bit = 1;
for (int i = 0; i < numMemoryTypes; ++i, bit += bit)
{
auto const& memoryType = m_deviceMemoryProperties.memoryTypes[i];
if ((typeBits & bit) && (memoryType.propertyFlags & properties) == properties)
{
return i;
}
}
// assert(!"failed to find a usable memory type");
return -1;
}
int VulkanApi::findQueue(VkQueueFlags reqFlags) const
{
assert(m_physicalDevice != VK_NULL_HANDLE);
uint32_t numQueueFamilies = 0;
vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &numQueueFamilies, nullptr);
Slang::List<VkQueueFamilyProperties> queueFamilies;
queueFamilies.setCount(numQueueFamilies);
vkGetPhysicalDeviceQueueFamilyProperties(
m_physicalDevice,
&numQueueFamilies,
queueFamilies.getBuffer());
// Find a queue that can service our needs
// VkQueueFlags reqQueueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
int queueFamilyIndex = -1;
for (int i = 0; i < int(numQueueFamilies); ++i)
{
if ((queueFamilies[i].queueFlags & reqFlags) == reqFlags)
{
return i;
}
}
return -1;
}
} // namespace gfx
|