yum-mirror/slang

Making it easier to work with shaders

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

Gangzheng TongEnable Windows full debug testsuite in CI (#7085)8f20632a0

master
20.0 KiB554 linesraw
1// vk-helper-functions.cpp
2#include "vk-helper-functions.h"
3
4#include "vk-device.h"
5#include "vk-util.h"
6
7namespace gfx
8{
9
10using namespace Slang;
11
12namespace vk
13{
14
15Size calcRowSize(Format format, int width)
16{
17    FormatInfo sizeInfo;
18    gfxGetFormatInfo(format, &sizeInfo);
19    return Size(
20        (width + sizeInfo.blockWidth - 1) / sizeInfo.blockWidth * sizeInfo.blockSizeInBytes);
21}
22
23GfxCount calcNumRows(Format format, int height)
24{
25    FormatInfo sizeInfo;
26    gfxGetFormatInfo(format, &sizeInfo);
27    return (GfxCount)(height + sizeInfo.blockHeight - 1) / sizeInfo.blockHeight;
28}
29
30VkAttachmentLoadOp translateLoadOp(IRenderPassLayout::TargetLoadOp loadOp)
31{
32    switch (loadOp)
33    {
34    case IRenderPassLayout::TargetLoadOp::Clear:
35        return VK_ATTACHMENT_LOAD_OP_CLEAR;
36    case IRenderPassLayout::TargetLoadOp::Load:
37        return VK_ATTACHMENT_LOAD_OP_LOAD;
38    default:
39        return VK_ATTACHMENT_LOAD_OP_DONT_CARE;
40    }
41}
42
43VkAttachmentStoreOp translateStoreOp(IRenderPassLayout::TargetStoreOp storeOp)
44{
45    switch (storeOp)
46    {
47    case IRenderPassLayout::TargetStoreOp::Store:
48        return VK_ATTACHMENT_STORE_OP_STORE;
49    default:
50        return VK_ATTACHMENT_STORE_OP_DONT_CARE;
51    }
52}
53
54VkPipelineCreateFlags translateRayTracingPipelineFlags(RayTracingPipelineFlags::Enum flags)
55{
56    VkPipelineCreateFlags vkFlags = 0;
57    if (flags & RayTracingPipelineFlags::Enum::SkipTriangles)
58        vkFlags |= VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR;
59    if (flags & RayTracingPipelineFlags::Enum::SkipProcedurals)
60        vkFlags |= VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR;
61
62    return vkFlags;
63}
64
65uint32_t getMipLevelSize(uint32_t mipLevel, uint32_t size)
66{
67    return Math::Max(1u, (size >> mipLevel));
68}
69
70VkImageLayout translateImageLayout(ResourceState state)
71{
72    switch (state)
73    {
74    case ResourceState::Undefined:
75        return VK_IMAGE_LAYOUT_UNDEFINED;
76    case ResourceState::PreInitialized:
77        return VK_IMAGE_LAYOUT_PREINITIALIZED;
78    case ResourceState::UnorderedAccess:
79        return VK_IMAGE_LAYOUT_GENERAL;
80    case ResourceState::RenderTarget:
81        return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
82    case ResourceState::DepthRead:
83        return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
84    case ResourceState::DepthWrite:
85        return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
86    case ResourceState::ShaderResource:
87    case ResourceState::NonPixelShaderResource:
88    case ResourceState::PixelShaderResource:
89        return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
90    case ResourceState::ResolveDestination:
91    case ResourceState::CopyDestination:
92        return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
93    case ResourceState::ResolveSource:
94    case ResourceState::CopySource:
95        return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
96    case ResourceState::Present:
97        return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
98    default:
99        assert(!"Unsupported");
100        return VK_IMAGE_LAYOUT_UNDEFINED;
101    }
102}
103
104VkAccessFlagBits calcAccessFlags(ResourceState state)
105{
106    switch (state)
107    {
108    case ResourceState::Undefined:
109    case ResourceState::Present:
110    case ResourceState::PreInitialized:
111        return VkAccessFlagBits(0);
112    case ResourceState::VertexBuffer:
113        return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
114    case ResourceState::ConstantBuffer:
115        return VK_ACCESS_UNIFORM_READ_BIT;
116    case ResourceState::IndexBuffer:
117        return VK_ACCESS_INDEX_READ_BIT;
118    case ResourceState::RenderTarget:
119        return VkAccessFlagBits(
120            VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
121    case ResourceState::ShaderResource:
122    case ResourceState::NonPixelShaderResource:
123    case ResourceState::PixelShaderResource:
124        return VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
125    case ResourceState::UnorderedAccess:
126        return VkAccessFlagBits(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
127    case ResourceState::DepthRead:
128        return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
129    case ResourceState::DepthWrite:
130        return VkAccessFlagBits(
131            VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
132            VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
133    case ResourceState::IndirectArgument:
134        return VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
135    case ResourceState::ResolveDestination:
136    case ResourceState::CopyDestination:
137        return VK_ACCESS_TRANSFER_WRITE_BIT;
138    case ResourceState::ResolveSource:
139    case ResourceState::CopySource:
140        return VK_ACCESS_TRANSFER_READ_BIT;
141    case ResourceState::AccelerationStructure:
142        return VkAccessFlagBits(
143            VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR |
144            VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR);
145    case ResourceState::AccelerationStructureBuildInput:
146        return VkAccessFlagBits(VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR);
147    case ResourceState::General:
148        return VkAccessFlagBits(VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT);
149    default:
150        assert(!"Unsupported");
151        return VkAccessFlagBits(0);
152    }
153}
154
155VkPipelineStageFlagBits calcPipelineStageFlags(ResourceState state, bool src)
156{
157    switch (state)
158    {
159    case ResourceState::Undefined:
160    case ResourceState::PreInitialized:
161        assert(src);
162        return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
163    case ResourceState::VertexBuffer:
164    case ResourceState::IndexBuffer:
165        return VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
166    case ResourceState::ConstantBuffer:
167    case ResourceState::UnorderedAccess:
168        return VkPipelineStageFlagBits(
169            VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
170            VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
171            VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
172            VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
173            VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
174    case ResourceState::ShaderResource:
175    case ResourceState::NonPixelShaderResource:
176    case ResourceState::PixelShaderResource:
177        return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
178    case ResourceState::RenderTarget:
179        return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
180    case ResourceState::DepthRead:
181    case ResourceState::DepthWrite:
182        return VkPipelineStageFlagBits(
183            VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
184    case ResourceState::IndirectArgument:
185        return VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
186    case ResourceState::CopySource:
187    case ResourceState::CopyDestination:
188    case ResourceState::ResolveSource:
189    case ResourceState::ResolveDestination:
190        return VK_PIPELINE_STAGE_TRANSFER_BIT;
191    case ResourceState::Present:
192        return src ? VkPipelineStageFlagBits(
193                         VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_ALL_COMMANDS_BIT)
194                   : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
195    case ResourceState::General:
196        return VkPipelineStageFlagBits(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
197    case ResourceState::AccelerationStructure:
198        return VkPipelineStageFlagBits(
199            VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
200            VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
201            VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
202            VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
203            VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR |
204            VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR);
205    case ResourceState::AccelerationStructureBuildInput:
206        return VkPipelineStageFlagBits(VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR);
207    default:
208        assert(!"Unsupported");
209        return VkPipelineStageFlagBits(0);
210    }
211}
212
213VkAccessFlags translateAccelerationStructureAccessFlag(AccessFlag access)
214{
215    VkAccessFlags result = 0;
216    if ((uint32_t)access & (uint32_t)AccessFlag::Read)
217        result |= VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_SHADER_READ_BIT;
218    if ((uint32_t)access & (uint32_t)AccessFlag::Write)
219        result |= VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR;
220    return result;
221}
222
223VkBufferUsageFlagBits _calcBufferUsageFlags(ResourceState state)
224{
225    switch (state)
226    {
227    case ResourceState::VertexBuffer:
228        return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
229    case ResourceState::IndexBuffer:
230        return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
231    case ResourceState::ConstantBuffer:
232        return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
233    case ResourceState::StreamOutput:
234        return VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
235    case ResourceState::RenderTarget:
236    case ResourceState::DepthRead:
237    case ResourceState::DepthWrite:
238        {
239            assert(!"Invalid resource state for buffer resource.");
240            return VkBufferUsageFlagBits(0);
241        }
242    case ResourceState::UnorderedAccess:
243        return (VkBufferUsageFlagBits)(VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT |
244                                       VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
245    case ResourceState::ShaderResource:
246    case ResourceState::NonPixelShaderResource:
247    case ResourceState::PixelShaderResource:
248        return (VkBufferUsageFlagBits)(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
249                                       VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
250    case ResourceState::CopySource:
251        return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
252    case ResourceState::CopyDestination:
253        return VK_BUFFER_USAGE_TRANSFER_DST_BIT;
254    case ResourceState::AccelerationStructure:
255        return VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR;
256    case ResourceState::IndirectArgument:
257        return VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
258    case ResourceState::AccelerationStructureBuildInput:
259        return VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR;
260    default:
261        return VkBufferUsageFlagBits(0);
262    }
263}
264
265VkBufferUsageFlagBits _calcBufferUsageFlags(ResourceStateSet states)
266{
267    int dstFlags = 0;
268    for (uint32_t i = 0; i < (uint32_t)ResourceState::_Count; i++)
269    {
270        auto state = (ResourceState)i;
271        if (states.contains(state))
272            dstFlags |= _calcBufferUsageFlags(state);
273    }
274    return VkBufferUsageFlagBits(dstFlags);
275}
276
277VkImageUsageFlagBits _calcImageUsageFlags(ResourceState state)
278{
279    switch (state)
280    {
281    case ResourceState::RenderTarget:
282        return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
283    case ResourceState::DepthWrite:
284        return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
285    case ResourceState::DepthRead:
286        return VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
287    case ResourceState::ShaderResource:
288    case ResourceState::NonPixelShaderResource:
289    case ResourceState::PixelShaderResource:
290        return VK_IMAGE_USAGE_SAMPLED_BIT;
291    case ResourceState::UnorderedAccess:
292        return VK_IMAGE_USAGE_STORAGE_BIT;
293    case ResourceState::CopySource:
294        return VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
295    case ResourceState::CopyDestination:
296        return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
297    case ResourceState::ResolveSource:
298        return VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
299    case ResourceState::ResolveDestination:
300        return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
301    case ResourceState::Present:
302        return VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
303    case ResourceState::Undefined:
304    case ResourceState::General:
305        return (VkImageUsageFlagBits)0;
306    default:
307        {
308            assert(!"Unsupported");
309            return VkImageUsageFlagBits(0);
310        }
311    }
312}
313
314VkImageViewType _calcImageViewType(ITextureResource::Type type, const ITextureResource::Desc& desc)
315{
316    switch (type)
317    {
318    case IResource::Type::Texture1D:
319        return desc.arraySize > 1 ? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_1D;
320    case IResource::Type::Texture2D:
321        return desc.arraySize > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D;
322    case IResource::Type::TextureCube:
323        return desc.arraySize > 1 ? VK_IMAGE_VIEW_TYPE_CUBE_ARRAY : VK_IMAGE_VIEW_TYPE_CUBE;
324    case IResource::Type::Texture3D:
325        {
326            // Can't have an array and 3d texture
327            assert(desc.arraySize <= 1);
328            if (desc.arraySize <= 1)
329            {
330                return VK_IMAGE_VIEW_TYPE_3D;
331            }
332            break;
333        }
334    default:
335        break;
336    }
337
338    return VK_IMAGE_VIEW_TYPE_MAX_ENUM;
339}
340
341VkImageUsageFlagBits _calcImageUsageFlags(ResourceStateSet states)
342{
343    int dstFlags = 0;
344    for (uint32_t i = 0; i < (uint32_t)ResourceState::_Count; i++)
345    {
346        auto state = (ResourceState)i;
347        if (states.contains(state))
348            dstFlags |= _calcImageUsageFlags(state);
349    }
350    return VkImageUsageFlagBits(dstFlags);
351}
352
353VkImageUsageFlags _calcImageUsageFlags(
354    ResourceStateSet states,
355    MemoryType memoryType,
356    const void* initData)
357{
358    VkImageUsageFlags usage = _calcImageUsageFlags(states);
359
360    if (memoryType == MemoryType::Upload || initData)
361    {
362        usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
363    }
364
365    return usage;
366}
367
368VkAccessFlags calcAccessFlagsFromImageLayout(VkImageLayout layout)
369{
370    switch (layout)
371    {
372    case VK_IMAGE_LAYOUT_UNDEFINED:
373    case VK_IMAGE_LAYOUT_GENERAL:
374    case VK_IMAGE_LAYOUT_PREINITIALIZED:
375    case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
376        return (VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT);
377    case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
378        return (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
379    case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
380    case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL:
381    case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL:
382    case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
383    case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
384        return (
385            VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
386            VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT);
387    case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
388    case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL:
389    case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL:
390        return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
391    case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
392        return VK_ACCESS_SHADER_READ_BIT;
393    case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
394        return VK_ACCESS_TRANSFER_READ_BIT;
395    case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
396        return VK_ACCESS_TRANSFER_WRITE_BIT;
397    default:
398        assert(!"Unsupported VkImageLayout");
399        return (VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT);
400    }
401}
402
403VkPipelineStageFlags calcPipelineStageFlagsFromImageLayout(VkImageLayout layout)
404{
405    switch (layout)
406    {
407    case VK_IMAGE_LAYOUT_UNDEFINED:
408    case VK_IMAGE_LAYOUT_PREINITIALIZED:
409    case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
410    case VK_IMAGE_LAYOUT_GENERAL:
411        return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
412    case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
413        return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
414    case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
415        return (VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
416    case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
417        return VK_PIPELINE_STAGE_TRANSFER_BIT;
418    case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
419        return VK_PIPELINE_STAGE_TRANSFER_BIT;
420    case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
421    case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
422    case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
423    case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
424    case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL:
425    case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL:
426    case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL:
427    case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL:
428        return (
429            VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
430    default:
431        assert(!"Unsupported VkImageLayout");
432        return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
433    }
434}
435
436VkImageAspectFlags getAspectMaskFromFormat(VkFormat format)
437{
438    switch (format)
439    {
440    case VK_FORMAT_D16_UNORM_S8_UINT:
441    case VK_FORMAT_D24_UNORM_S8_UINT:
442    case VK_FORMAT_D32_SFLOAT_S8_UINT:
443        return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
444    case VK_FORMAT_D16_UNORM:
445    case VK_FORMAT_D32_SFLOAT:
446    case VK_FORMAT_X8_D24_UNORM_PACK32:
447        return VK_IMAGE_ASPECT_DEPTH_BIT;
448    case VK_FORMAT_S8_UINT:
449        return VK_IMAGE_ASPECT_STENCIL_BIT;
450    default:
451        return VK_IMAGE_ASPECT_COLOR_BIT;
452    }
453}
454
455AdapterLUID getAdapterLUID(VulkanApi api, VkPhysicalDevice physicalDevice)
456{
457    AdapterLUID luid = {};
458
459    VkPhysicalDeviceIDPropertiesKHR idProps = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR};
460    VkPhysicalDeviceProperties2 props = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
461    props.pNext = &idProps;
462    SLANG_ASSERT(api.vkGetPhysicalDeviceFeatures2);
463    api.vkGetPhysicalDeviceProperties2(physicalDevice, &props);
464    if (idProps.deviceLUIDValid)
465    {
466        SLANG_ASSERT(sizeof(AdapterLUID) >= VK_LUID_SIZE);
467        memcpy(&luid, idProps.deviceLUID, VK_LUID_SIZE);
468    }
469    else
470    {
471        SLANG_ASSERT(sizeof(AdapterLUID) >= VK_UUID_SIZE);
472        memcpy(&luid, idProps.deviceUUID, VK_UUID_SIZE);
473    }
474
475    return luid;
476}
477
478} // namespace vk
479
480Result SLANG_MCALL getVKAdapters(List<AdapterInfo>& outAdapters)
481{
482    for (int forceSoftware = 0; forceSoftware <= 1; forceSoftware++)
483    {
484        VulkanModule module;
485        if (module.init(forceSoftware != 0) != SLANG_OK)
486            continue;
487        VulkanApi api;
488        if (api.initGlobalProcs(module) != SLANG_OK)
489            continue;
490
491        VkInstanceCreateInfo instanceCreateInfo = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO};
492        const char* instanceExtensions[] = {
493            VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
494#if SLANG_APPLE_FAMILY
495            VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
496#endif
497        };
498        instanceCreateInfo.enabledExtensionCount = SLANG_COUNT_OF(instanceExtensions);
499        instanceCreateInfo.ppEnabledExtensionNames = &instanceExtensions[0];
500#if SLANG_APPLE_FAMILY
501        instanceCreateInfo.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
502#endif
503        VkInstance instance;
504        SLANG_VK_RETURN_ON_FAIL(api.vkCreateInstance(&instanceCreateInfo, nullptr, &instance));
505
506        // This will fail due to not loading any extensions.
507        api.initInstanceProcs(instance);
508
509        // Make sure required functions for enumerating physical devices were loaded.
510        if (api.vkEnumeratePhysicalDevices || api.vkGetPhysicalDeviceProperties)
511        {
512            uint32_t numPhysicalDevices = 0;
513            SLANG_VK_RETURN_ON_FAIL(
514                api.vkEnumeratePhysicalDevices(instance, &numPhysicalDevices, nullptr));
515
516            List<VkPhysicalDevice> physicalDevices;
517            physicalDevices.setCount(numPhysicalDevices);
518            SLANG_VK_RETURN_ON_FAIL(api.vkEnumeratePhysicalDevices(
519                instance,
520                &numPhysicalDevices,
521                physicalDevices.getBuffer()));
522
523            for (const auto& physicalDevice : physicalDevices)
524            {
525                VkPhysicalDeviceProperties props;
526                api.vkGetPhysicalDeviceProperties(physicalDevice, &props);
527                AdapterInfo info = {};
528                memcpy(
529                    info.name,
530                    props.deviceName,
531                    Math::Min(strlen(props.deviceName), sizeof(AdapterInfo::name) - 1));
532                info.vendorID = props.vendorID;
533                info.deviceID = props.deviceID;
534                info.luid = vk::getAdapterLUID(api, physicalDevice);
535                outAdapters.add(info);
536            }
537        }
538
539        api.vkDestroyInstance(instance, nullptr);
540        module.destroy();
541    }
542
543    return SLANG_OK;
544}
545
546Result SLANG_MCALL createVKDevice(const IDevice::Desc* desc, IDevice** outRenderer)
547{
548    RefPtr<vk::DeviceImpl> result = new vk::DeviceImpl();
549    SLANG_RETURN_ON_FAIL(result->initialize(*desc));
550    returnComPtr(outRenderer, result);
551    return SLANG_OK;
552}
553
554} // namespace gfx