yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
3822f9243
master
1// vk-device.cpp 2#include "vk-device.h" 3 4#include "core/slang-platform.h" 5#include "vk-buffer.h" 6#include "vk-command-queue.h" 7#include "vk-fence.h" 8#include "vk-helper-functions.h" 9#include "vk-pipeline-dump-layer.h" 10#include "vk-query.h" 11#include "vk-render-pass.h" 12#include "vk-resource-views.h" 13#include "vk-sampler.h" 14#include "vk-shader-object-layout.h" 15#include "vk-shader-object.h" 16#include "vk-shader-program.h" 17#include "vk-shader-table.h" 18#include "vk-swap-chain.h" 19#include "vk-transient-heap.h" 20#include "vk-vertex-layout.h" 21 22#ifdef GFX_NV_AFTERMATH 23#include "GFSDK_Aftermath.h" 24#include "GFSDK_Aftermath_Defines.h" 25#include "GFSDK_Aftermath_GpuCrashDump.h" 26#endif 27 28namespace gfx 29{ 30 31using namespace Slang ; 32 33namespace vk 34{ 35 36static bool shouldDumpPipeline () 37{ 38StringBuilder dumpPipelineSettings ; 39PlatformUtil ::getEnvironmentVariable (toSlice ("SLANG_GFX_DUMP_PIPELINE" ),dumpPipelineSettings ); 40return dumpPipelineSettings .produceString ()== "1" ; 41} 42 43DeviceImpl ::~DeviceImpl () 44{ 45if (shouldDumpPipeline ()) 46 { 47writePipelineDump (toSlice ("gfx-vk-pipeline-dump.bin" )); 48 } 49 50// Check the device queue is valid else, we can't wait on it.. 51if (m_deviceQueue .isValid ()) 52 { 53waitForGpu (); 54 } 55 56m_shaderObjectLayoutCache = decltype(m_shaderObjectLayoutCache )(); 57shaderCache .free (); 58m_deviceObjectsWithPotentialBackReferences .clearAndDeallocate (); 59 60if (m_api .vkDestroySampler ) 61 { 62m_api .vkDestroySampler (m_device ,m_defaultSampler ,nullptr ); 63 } 64 65m_deviceQueue .destroy (); 66 67descriptorSetAllocator .close (); 68 69m_emptyFramebuffer = nullptr ; 70 71if (m_device != VK_NULL_HANDLE ) 72 { 73if (m_desc .existingDeviceHandles .handles [2 ].handleValue == 0 ) 74m_api .vkDestroyDevice (m_device ,nullptr ); 75m_device = VK_NULL_HANDLE ; 76if (m_debugReportCallback != VK_NULL_HANDLE ) 77m_api .vkDestroyDebugReportCallbackEXT (m_api .m_instance ,m_debugReportCallback ,nullptr ); 78if (m_api .m_instance != VK_NULL_HANDLE && 79m_desc .existingDeviceHandles .handles [0 ].handleValue == 0 ) 80m_api .vkDestroyInstance (m_api .m_instance ,nullptr ); 81 } 82} 83 84// TODO: Is "location" still needed for this function? 85VkBool32 DeviceImpl ::handleDebugMessage ( 86VkDebugReportFlagsEXT flags , 87VkDebugReportObjectTypeEXT objType , 88uint64_t srcObject , 89Size location , 90int32_t msgCode , 91const char * pLayerPrefix , 92const char * pMsg ) 93{ 94DebugMessageType msgType = DebugMessageType ::Info ; 95 96char const * severity = "message" ; 97if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT ) 98 { 99severity = "warning" ; 100msgType = DebugMessageType ::Warning ; 101 } 102if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT ) 103 { 104severity = "error" ; 105msgType = DebugMessageType ::Error ; 106 } 107 108// pMsg can be really big (it can be assembler dump for example) 109// Use a dynamic buffer to store 110Size bufferSize = strlen (pMsg )+ 1 + 1024 ; 111List < char > bufferArray ; 112bufferArray .setCount (bufferSize ); 113char * buffer = bufferArray .getBuffer (); 114 115sprintf_s (buffer ,bufferSize ,"%s: %s %d: %s\n" ,pLayerPrefix ,severity ,msgCode ,pMsg ); 116 117getDebugCallback ()-> handleMessage (msgType ,DebugMessageSource ::Driver ,buffer ); 118return VK_FALSE ; 119} 120 121VKAPI_ATTR VkBool32 VKAPI_CALL DeviceImpl ::debugMessageCallback ( 122VkDebugReportFlagsEXT flags , 123VkDebugReportObjectTypeEXT objType , 124uint64_t srcObject , 125Size location , 126int32_t msgCode , 127const char * pLayerPrefix , 128const char * pMsg , 129void * pUserData ) 130{ 131return ((DeviceImpl * )pUserData ) 132-> handleDebugMessage (flags ,objType ,srcObject ,location ,msgCode ,pLayerPrefix ,pMsg ); 133} 134 135Result DeviceImpl ::getNativeDeviceHandles (InteropHandles * outHandles ) 136{ 137outHandles -> handles [0 ].handleValue = (uint64_t )m_api .m_instance ; 138outHandles -> handles [0 ].api = InteropHandleAPI ::Vulkan ; 139outHandles -> handles [1 ].handleValue = (uint64_t )m_api .m_physicalDevice ; 140outHandles -> handles [1 ].api = InteropHandleAPI ::Vulkan ; 141outHandles -> handles [2 ].handleValue = (uint64_t )m_api .m_device ; 142outHandles -> handles [2 ].api = InteropHandleAPI ::Vulkan ; 143return SLANG_OK ; 144} 145 146template < typename T > 147static bool _hasAnySetBits (const T & val ,size_t offset ) 148{ 149const uint8_t * ptr = reinterpret_cast < const uint8_t *> (& val ); 150for (size_t i = offset ;i < sizeof (val );i ++ ) 151if (ptr [i ]) 152return true; 153return false; 154} 155 156Result DeviceImpl ::initVulkanInstanceAndDevice ( 157const InteropHandle * handles , 158bool useValidationLayer ) 159{ 160m_features .clear (); 161 162m_queueAllocCount = 0 ; 163 164bool enableRayTracingValidation = false; 165 166// Read properties from extended device descriptions 167for (GfxIndex i = 0 ;i < m_desc .extendedDescCount ;i ++ ) 168 { 169StructType stype ; 170memcpy (& stype ,m_desc .extendedDescs [i ],sizeof (stype )); 171switch (stype ) 172 { 173case StructType ::RayTracingValidationDesc : 174enableRayTracingValidation = 175static_cast < RayTracingValidationDesc *> (m_desc .extendedDescs [i ]) 176-> enableRaytracingValidation ; 177break ; 178 } 179 } 180 181 182VkInstance instance = VK_NULL_HANDLE ; 183if (handles [0 ].handleValue == 0 ) 184 { 185VkApplicationInfo applicationInfo = {VK_STRUCTURE_TYPE_APPLICATION_INFO }; 186applicationInfo .pApplicationName = "slang-gfx" ; 187applicationInfo .pEngineName = "slang-gfx" ; 188applicationInfo .apiVersion = VK_API_VERSION_1_1 ; 189applicationInfo .engineVersion = 1 ; 190applicationInfo .applicationVersion = 1 ; 191 192Array < const char * ,7 > instanceExtensions ; 193 194#if SLANG_APPLE_FAMILY 195instanceExtensions .add (VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME ); 196#endif 197instanceExtensions .add (VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME ); 198instanceExtensions .add (VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME ); 199 200// Software (swiftshader) implementation currently does not support surface extension, 201// so only use it with a hardware implementation. 202if (!m_api .m_module -> isSoftware ()) 203 { 204instanceExtensions .add (VK_KHR_SURFACE_EXTENSION_NAME ); 205// Note: this extension is not yet supported by nvidia drivers, disable for now. 206// instanceExtensions.add("VK_GOOGLE_surfaceless_query"); 207#if SLANG_WINDOWS_FAMILY 208instanceExtensions .add (VK_KHR_WIN32_SURFACE_EXTENSION_NAME ); 209#elif SLANG_APPLE_FAMILY 210instanceExtensions .add (VK_EXT_METAL_SURFACE_EXTENSION_NAME ); 211#elif defined(SLANG_ENABLE_XLIB ) 212 213instanceExtensions .add (VK_KHR_XLIB_SURFACE_EXTENSION_NAME ); 214#endif 215 } 216 217gfxEnableDebugLayer (useValidationLayer ); 218if (isGfxDebugLayerEnabled ()) 219instanceExtensions .add (VK_EXT_DEBUG_REPORT_EXTENSION_NAME ); 220 221VkInstanceCreateInfo instanceCreateInfo = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO }; 222#if SLANG_APPLE_FAMILY 223instanceCreateInfo .flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR ; 224#endif 225instanceCreateInfo .pApplicationInfo = & applicationInfo ; 226instanceCreateInfo .enabledExtensionCount = (uint32_t )instanceExtensions .getCount (); 227instanceCreateInfo .ppEnabledExtensionNames = & instanceExtensions [0 ]; 228 229const char * layerNames []= {nullptr }; 230 231VkValidationFeaturesEXT validationFeatures = {}; 232VkValidationFeatureEnableEXT enabledValidationFeatures [1 ]= { 233VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT }; 234if (useValidationLayer ) 235 { 236// Depending on driver version, validation layer may or may not exist. 237// Newer drivers comes with "VK_LAYER_KHRONOS_validation", while older 238// drivers provide only the deprecated 239// "VK_LAYER_LUNARG_standard_validation" layer. 240// We will check what layers are available, and use the newer 241// "VK_LAYER_KHRONOS_validation" layer when possible. 242uint32_t layerCount ; 243m_api .vkEnumerateInstanceLayerProperties (& layerCount ,nullptr ); 244 245List < VkLayerProperties > availableLayers ; 246availableLayers .setCount (layerCount ); 247m_api .vkEnumerateInstanceLayerProperties (& layerCount ,availableLayers .getBuffer ()); 248 249for (auto & layer :availableLayers ) 250 { 251if (strncmp ( 252layer .layerName , 253"VK_LAYER_KHRONOS_validation" , 254sizeof ("VK_LAYER_KHRONOS_validation" ))== 0 ) 255 { 256layerNames [0 ]= "VK_LAYER_KHRONOS_validation" ; 257break ; 258 } 259 } 260// On older drivers, only "VK_LAYER_LUNARG_standard_validation" exists, 261// so we try to use it if we can't find "VK_LAYER_KHRONOS_validation". 262if (!layerNames [0 ]) 263 { 264for (auto & layer :availableLayers ) 265 { 266if (strncmp ( 267layer .layerName , 268"VK_LAYER_LUNARG_standard_validation" , 269sizeof ("VK_LAYER_LUNARG_standard_validation" ))== 0 ) 270 { 271layerNames [0 ]= "VK_LAYER_LUNARG_standard_validation" ; 272break ; 273 } 274 } 275 } 276if (layerNames [0 ]) 277 { 278instanceCreateInfo .enabledLayerCount = SLANG_COUNT_OF (layerNames ); 279instanceCreateInfo .ppEnabledLayerNames = layerNames ; 280 281// Include support for printf 282validationFeatures .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT ; 283validationFeatures .enabledValidationFeatureCount = 1 ; 284validationFeatures .pEnabledValidationFeatures = enabledValidationFeatures ; 285instanceCreateInfo .pNext = & validationFeatures ; 286 } 287 } 288uint32_t apiVersionsToTry []= {VK_API_VERSION_1_2 ,VK_API_VERSION_1_1 ,VK_API_VERSION_1_0 }; 289for (auto apiVersion :apiVersionsToTry ) 290 { 291applicationInfo .apiVersion = apiVersion ; 292// If r is VK_ERROR_LAYER_NOT_PRESENT, it's almost certainly 293// because the layer shared library failed to load (we check that 294// the layer is known earlier). It might, for example, be absent 295// from the system library search path, and not referenced with an 296// absolute path in VkLayer_khronos_validation.json. 297const auto r = m_api .vkCreateInstance (& instanceCreateInfo ,nullptr ,& instance ); 298if (r == VK_SUCCESS ) 299 { 300break ; 301 } 302 } 303 } 304else 305 { 306instance = (VkInstance )handles [0 ].handleValue ; 307 } 308if (!instance ) 309return SLANG_FAIL ; 310SLANG_RETURN_ON_FAIL (m_api .initInstanceProcs (instance )); 311 312if ((enableRayTracingValidation || useValidationLayer )&& m_api .vkCreateDebugReportCallbackEXT ) 313 { 314VkDebugReportFlagsEXT debugFlags = 315VK_DEBUG_REPORT_ERROR_BIT_EXT |VK_DEBUG_REPORT_WARNING_BIT_EXT ; 316 317VkDebugReportCallbackCreateInfoEXT debugCreateInfo = { 318VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT }; 319debugCreateInfo .pfnCallback = & debugMessageCallback ; 320debugCreateInfo .pUserData = this ; 321debugCreateInfo .flags = debugFlags ; 322 323SLANG_VK_RETURN_ON_FAIL (m_api .vkCreateDebugReportCallbackEXT ( 324instance , 325& debugCreateInfo , 326nullptr , 327& m_debugReportCallback )); 328 } 329 330VkPhysicalDevice physicalDevice = VK_NULL_HANDLE ; 331if (handles [1 ].handleValue == 0 ) 332 { 333uint32_t numPhysicalDevices = 0 ; 334SLANG_VK_RETURN_ON_FAIL ( 335m_api .vkEnumeratePhysicalDevices (instance ,& numPhysicalDevices ,nullptr )); 336 337List < VkPhysicalDevice > physicalDevices ; 338physicalDevices .setCount (numPhysicalDevices ); 339SLANG_VK_RETURN_ON_FAIL (m_api .vkEnumeratePhysicalDevices ( 340instance , 341& numPhysicalDevices , 342physicalDevices .getBuffer ())); 343 344// Use first physical device by default. 345Index selectedDeviceIndex = 0 ; 346 347// Search for requested adapter. 348if (m_desc .adapterLUID ) 349 { 350selectedDeviceIndex = -1 ; 351for (Index i = 0 ;i < physicalDevices .getCount ();++ i ) 352 { 353if (vk::getAdapterLUID (m_api ,physicalDevices [i ])== * m_desc .adapterLUID ) 354 { 355selectedDeviceIndex = i ; 356break ; 357 } 358 } 359if (selectedDeviceIndex < 0 ) 360return SLANG_E_NOT_FOUND ; 361 } 362 363if (selectedDeviceIndex >=physicalDevices .getCount ()) 364return SLANG_FAIL ; 365 366physicalDevice = physicalDevices [selectedDeviceIndex ]; 367 } 368else 369 { 370physicalDevice = (VkPhysicalDevice )handles [1 ].handleValue ; 371 } 372 373SLANG_RETURN_ON_FAIL (m_api .initPhysicalDevice (physicalDevice )); 374 375// Obtain the name of the selected adapter. 376 { 377VkPhysicalDeviceProperties basicProps = {}; 378m_api .vkGetPhysicalDeviceProperties (physicalDevice ,& basicProps ); 379m_adapterName = basicProps .deviceName ; 380m_info .adapterName = m_adapterName .begin (); 381 } 382 383// Query the available extensions 384uint32_t extensionCount = 0 ; 385m_api .vkEnumerateDeviceExtensionProperties (m_api .m_physicalDevice ,NULL ,& extensionCount ,NULL ); 386Slang ::List < VkExtensionProperties > extensions ; 387extensions .setCount (extensionCount ); 388m_api .vkEnumerateDeviceExtensionProperties ( 389m_api .m_physicalDevice , 390NULL , 391& extensionCount , 392extensions .getBuffer ()); 393HashSet < String > extensionNames ; 394for (const auto & e :extensions ) 395extensionNames .add (e .extensionName ); 396 397List < const char *> deviceExtensions ; 398deviceExtensions .add (VK_KHR_SWAPCHAIN_EXTENSION_NAME ); 399deviceExtensions .add (VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME ); 400#if SLANG_APPLE_FAMILY 401deviceExtensions .add ("VK_KHR_portability_subset" ); 402#endif 403 404VkDeviceCreateInfo deviceCreateInfo = {VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; 405deviceCreateInfo .queueCreateInfoCount = 1 ; 406deviceCreateInfo .pEnabledFeatures = & m_api .m_deviceFeatures ; 407 408// Get the device features (doesn't use, but useful when debugging) 409if (m_api .vkGetPhysicalDeviceFeatures2 ) 410 { 411VkPhysicalDeviceFeatures2 deviceFeatures2 = {}; 412deviceFeatures2 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 ; 413m_api .vkGetPhysicalDeviceFeatures2 (m_api .m_physicalDevice ,& deviceFeatures2 ); 414 } 415 416VkPhysicalDeviceProperties basicProps = {}; 417m_api .vkGetPhysicalDeviceProperties (m_api .m_physicalDevice ,& basicProps ); 418 419// Compute timestamp frequency. 420m_info .timestampFrequency = uint64_t (1e9 /basicProps .limits .timestampPeriod ); 421 422// Get device limits. 423 { 424DeviceLimits limits = {}; 425limits .maxTextureDimension1D = basicProps .limits .maxImageDimension1D ; 426limits .maxTextureDimension2D = basicProps .limits .maxImageDimension2D ; 427limits .maxTextureDimension3D = basicProps .limits .maxImageDimension3D ; 428limits .maxTextureDimensionCube = basicProps .limits .maxImageDimensionCube ; 429limits .maxTextureArrayLayers = basicProps .limits .maxImageArrayLayers ; 430 431limits .maxVertexInputElements = basicProps .limits .maxVertexInputAttributes ; 432limits .maxVertexInputElementOffset = basicProps .limits .maxVertexInputAttributeOffset ; 433limits .maxVertexStreams = basicProps .limits .maxVertexInputBindings ; 434limits .maxVertexStreamStride = basicProps .limits .maxVertexInputBindingStride ; 435 436limits .maxComputeThreadsPerGroup = basicProps .limits .maxComputeWorkGroupInvocations ; 437limits .maxComputeThreadGroupSize [0 ]= basicProps .limits .maxComputeWorkGroupSize [0 ]; 438limits .maxComputeThreadGroupSize [1 ]= basicProps .limits .maxComputeWorkGroupSize [1 ]; 439limits .maxComputeThreadGroupSize [2 ]= basicProps .limits .maxComputeWorkGroupSize [2 ]; 440limits .maxComputeDispatchThreadGroups [0 ]= basicProps .limits .maxComputeWorkGroupCount [0 ]; 441limits .maxComputeDispatchThreadGroups [1 ]= basicProps .limits .maxComputeWorkGroupCount [1 ]; 442limits .maxComputeDispatchThreadGroups [2 ]= basicProps .limits .maxComputeWorkGroupCount [2 ]; 443 444limits .maxViewports = basicProps .limits .maxViewports ; 445limits .maxViewportDimensions [0 ]= basicProps .limits .maxViewportDimensions [0 ]; 446limits .maxViewportDimensions [1 ]= basicProps .limits .maxViewportDimensions [1 ]; 447limits .maxFramebufferDimensions [0 ]= basicProps .limits .maxFramebufferWidth ; 448limits .maxFramebufferDimensions [1 ]= basicProps .limits .maxFramebufferHeight ; 449limits .maxFramebufferDimensions [2 ]= basicProps .limits .maxFramebufferLayers ; 450 451limits .maxShaderVisibleSamplers = basicProps .limits .maxPerStageDescriptorSamplers ; 452 453m_info .limits = limits ; 454 } 455 456// Get the API version 457const uint32_t majorVersion = VK_VERSION_MAJOR (basicProps .apiVersion ); 458const uint32_t minorVersion = VK_VERSION_MINOR (basicProps .apiVersion ); 459 460auto & extendedFeatures = m_api .m_extendedFeatures ; 461 462// API version check, can't use vkGetPhysicalDeviceProperties2 yet since this device might not 463// support it 464if (VK_MAKE_VERSION (majorVersion ,minorVersion ,0 ) >=VK_API_VERSION_1_1 && 465m_api .vkGetPhysicalDeviceProperties2 && m_api .vkGetPhysicalDeviceFeatures2 ) 466 { 467// Get device features 468VkPhysicalDeviceFeatures2 deviceFeatures2 = {}; 469deviceFeatures2 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 ; 470 471// Inline uniform block 472extendedFeatures .inlineUniformBlockFeatures .pNext = deviceFeatures2 .pNext ; 473deviceFeatures2 .pNext = & extendedFeatures .inlineUniformBlockFeatures ; 474 475// Ray query features 476extendedFeatures .rayQueryFeatures .pNext = deviceFeatures2 .pNext ; 477deviceFeatures2 .pNext = & extendedFeatures .rayQueryFeatures ; 478 479// Ray tracing pipeline features 480extendedFeatures .rayTracingPipelineFeatures .pNext = deviceFeatures2 .pNext ; 481deviceFeatures2 .pNext = & extendedFeatures .rayTracingPipelineFeatures ; 482 483// SER features. 484extendedFeatures .rayTracingInvocationReorderFeatures .pNext = deviceFeatures2 .pNext ; 485deviceFeatures2 .pNext = & extendedFeatures .rayTracingInvocationReorderFeatures ; 486 487// Acceleration structure features 488extendedFeatures .accelerationStructureFeatures .pNext = deviceFeatures2 .pNext ; 489deviceFeatures2 .pNext = & extendedFeatures .accelerationStructureFeatures ; 490 491// Variable pointer features. 492extendedFeatures .variablePointersFeatures .pNext = deviceFeatures2 .pNext ; 493deviceFeatures2 .pNext = & extendedFeatures .variablePointersFeatures ; 494 495// Compute shader derivative features. 496extendedFeatures .computeShaderDerivativeFeatures .pNext = deviceFeatures2 .pNext ; 497deviceFeatures2 .pNext = & extendedFeatures .computeShaderDerivativeFeatures ; 498 499// Extended dynamic states 500extendedFeatures .extendedDynamicStateFeatures .pNext = deviceFeatures2 .pNext ; 501deviceFeatures2 .pNext = & extendedFeatures .extendedDynamicStateFeatures ; 502 503// 16-bit storage 504extendedFeatures .storage16BitFeatures .pNext = deviceFeatures2 .pNext ; 505deviceFeatures2 .pNext = & extendedFeatures .storage16BitFeatures ; 506 507// robustness2 features 508extendedFeatures .robustness2Features .pNext = deviceFeatures2 .pNext ; 509deviceFeatures2 .pNext = & extendedFeatures .robustness2Features ; 510 511// clock features 512extendedFeatures .clockFeatures .pNext = deviceFeatures2 .pNext ; 513deviceFeatures2 .pNext = & extendedFeatures .clockFeatures ; 514 515// cooperative vector features 516extendedFeatures .cooperativeVectorFeatures .pNext = deviceFeatures2 .pNext ; 517deviceFeatures2 .pNext = & extendedFeatures .cooperativeVectorFeatures ; 518 519// Atomic Float 520// To detect atomic float we need 521// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkPhysicalDeviceShaderAtomicFloatFeaturesEXT.html 522 523extendedFeatures .atomicFloatFeatures .pNext = deviceFeatures2 .pNext ; 524deviceFeatures2 .pNext = & extendedFeatures .atomicFloatFeatures ; 525 526// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT.html 527extendedFeatures .atomicFloat2Features .pNext = deviceFeatures2 .pNext ; 528deviceFeatures2 .pNext = & extendedFeatures .atomicFloat2Features ; 529 530// Image Int64 Atomic 531// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT.html 532extendedFeatures .imageInt64AtomicFeatures .pNext = deviceFeatures2 .pNext ; 533deviceFeatures2 .pNext = & extendedFeatures .imageInt64AtomicFeatures ; 534 535// mesh shader features 536extendedFeatures .meshShaderFeatures .pNext = deviceFeatures2 .pNext ; 537deviceFeatures2 .pNext = & extendedFeatures .meshShaderFeatures ; 538 539// multiview features 540extendedFeatures .multiviewFeatures .pNext = deviceFeatures2 .pNext ; 541deviceFeatures2 .pNext = & extendedFeatures .multiviewFeatures ; 542 543// fragment shading rate features 544extendedFeatures .fragmentShadingRateFeatures .pNext = deviceFeatures2 .pNext ; 545deviceFeatures2 .pNext = & extendedFeatures .fragmentShadingRateFeatures ; 546 547// raytracing validation features 548extendedFeatures .rayTracingValidationFeatures .pNext = deviceFeatures2 .pNext ; 549deviceFeatures2 .pNext = & extendedFeatures .rayTracingValidationFeatures ; 550 551if (VK_MAKE_VERSION (majorVersion ,minorVersion ,0 ) >=VK_API_VERSION_1_2 ) 552 { 553extendedFeatures .vulkan12Features .pNext = deviceFeatures2 .pNext ; 554deviceFeatures2 .pNext = & extendedFeatures .vulkan12Features ; 555 } 556 557m_api .vkGetPhysicalDeviceFeatures2 (m_api .m_physicalDevice ,& deviceFeatures2 ); 558 559if (deviceFeatures2 .features .shaderResourceMinLod ) 560 { 561m_features .add ("shader-resource-min-lod" ); 562 } 563if (deviceFeatures2 .features .shaderFloat64 ) 564 { 565m_features .add ("double" ); 566 } 567if (deviceFeatures2 .features .shaderInt64 ) 568 { 569m_features .add ("int64" ); 570 } 571if (deviceFeatures2 .features .shaderInt16 ) 572 { 573m_features .add ("int16" ); 574 } 575// If we have float16 features then enable 576if (extendedFeatures .vulkan12Features .shaderFloat16 ) 577 { 578// We have half support 579m_features .add ("half" ); 580 } 581 582const auto addFeatureExtension = 583 [& ](const bool feature ,auto & featureStruct ,const char * extension = nullptr ) 584 { 585if (!feature ) 586return false; 587if (extension ) 588 { 589if (!extensionNames .contains (extension )) 590return false; 591deviceExtensions .add (extension ); 592 } 593featureStruct .pNext = (void * )deviceCreateInfo .pNext ; 594deviceCreateInfo .pNext = & featureStruct ; 595return true; 596 }; 597 598// SIMPLE_EXTENSION_FEATURE(struct, feature member name, extension 599// name, features...) will check for the presence of the boolean 600// feature member in struct and the availability of the extensions. If 601// they are both present then the extensions are added, the struct 602// linked into the deviceCreateInfo chain and the features added to the 603// supported features list. 604#define SIMPLE_EXTENSION_FEATURE (s ,m ,e , ...) \ 605 do \ 606 { \ 607 const static auto fs = {__VA_ARGS__}; \ 608 if (addFeatureExtension(s.m, s, e)) \ 609 for (const auto& p : fs) \ 610 m_features.add(p); \ 611 } while (0) 612 613SIMPLE_EXTENSION_FEATURE ( 614extendedFeatures .storage16BitFeatures , 615storageBuffer16BitAccess , 616VK_KHR_16BIT_STORAGE_EXTENSION_NAME , 617"16-bit-storage" ); 618 619SIMPLE_EXTENSION_FEATURE ( 620extendedFeatures .atomicFloatFeatures , 621shaderBufferFloat32Atomics , 622VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME , 623"atomic-float" ); 624 625SIMPLE_EXTENSION_FEATURE ( 626extendedFeatures .atomicFloat2Features , 627shaderBufferFloat16Atomics , 628VK_EXT_SHADER_ATOMIC_FLOAT_2_EXTENSION_NAME , 629"atomic-float-2" ); 630 631SIMPLE_EXTENSION_FEATURE ( 632extendedFeatures .imageInt64AtomicFeatures , 633shaderImageInt64Atomics , 634VK_EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME , 635"image-atomic-int64" ); 636 637SIMPLE_EXTENSION_FEATURE ( 638extendedFeatures .extendedDynamicStateFeatures , 639extendedDynamicState , 640VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME , 641"extended-dynamic-states" ); 642 643if (extendedFeatures .accelerationStructureFeatures .accelerationStructure && 644extensionNames .contains (VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME )&& 645extensionNames .contains (VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME )) 646 { 647extendedFeatures .accelerationStructureFeatures .pNext = (void * )deviceCreateInfo .pNext ; 648deviceCreateInfo .pNext = & extendedFeatures .accelerationStructureFeatures ; 649deviceExtensions .add (VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME ); 650deviceExtensions .add (VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME ); 651m_features .add ("acceleration-structure" ); 652 653// These both depend on VK_KHR_acceleration_structure 654 655SIMPLE_EXTENSION_FEATURE ( 656extendedFeatures .rayQueryFeatures , 657rayQuery , 658VK_KHR_RAY_QUERY_EXTENSION_NAME , 659"ray-query" , 660"ray-tracing" ); 661 662SIMPLE_EXTENSION_FEATURE ( 663extendedFeatures .rayTracingPipelineFeatures , 664rayTracingPipeline , 665VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME , 666"ray-tracing-pipeline" ); 667 } 668 669SIMPLE_EXTENSION_FEATURE ( 670extendedFeatures .inlineUniformBlockFeatures , 671inlineUniformBlock , 672VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME , 673"inline-uniform-block" ,); 674 675SIMPLE_EXTENSION_FEATURE ( 676extendedFeatures. robustness2Features , 677nullDescriptor, 678VK_EXT_ROBUSTNESS_2_EXTENSION_NAME , 679"robustness2" , ); 680 681SIMPLE_EXTENSION_FEATURE ( 682extendedFeatures. clockFeatures , 683shaderDeviceClock, 684VK_KHR_SHADER_CLOCK_EXTENSION_NAME , 685"realtime-clock" ); 686 687SIMPLE_EXTENSION_FEATURE ( 688extendedFeatures. meshShaderFeatures , 689meshShader, 690VK_EXT_MESH_SHADER_EXTENSION_NAME , 691"mesh-shader" ); 692 693SIMPLE_EXTENSION_FEATURE ( 694extendedFeatures. multiviewFeatures , 695multiview, 696VK_KHR_MULTIVIEW_EXTENSION_NAME , 697"multiview" ); 698 699SIMPLE_EXTENSION_FEATURE ( 700extendedFeatures. fragmentShadingRateFeatures , 701primitiveFragmentShadingRate, 702VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME , 703"fragment-shading-rate" ); 704 705SIMPLE_EXTENSION_FEATURE ( 706extendedFeatures. rayTracingInvocationReorderFeatures , 707rayTracingInvocationReorder, 708VK_NV_RAY_TRACING_INVOCATION_REORDER_EXTENSION_NAME , 709"shader-execution-reorder" ); 710 711SIMPLE_EXTENSION_FEATURE ( 712extendedFeatures. variablePointersFeatures , 713variablePointers, 714VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME , 715"variable-pointer" ); 716 717SIMPLE_EXTENSION_FEATURE ( 718extendedFeatures. computeShaderDerivativeFeatures , 719computeDerivativeGroupLinear, 720VK_KHR_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME , 721"computeDerivativeGroupLinear" ); 722 723// Only enable raytracing validation if both requested and supported 724if (enableRayTracingValidation && 725extendedFeatures. rayTracingValidationFeatures . rayTracingValidation ) 726{ 727SIMPLE_EXTENSION_FEATURE ( 728extendedFeatures. rayTracingValidationFeatures , 729rayTracingValidation, 730VK_NV_RAY_TRACING_VALIDATION_EXTENSION_NAME , 731"ray-tracing-validation" ); 732} 733 734SIMPLE_EXTENSION_FEATURE ( 735extendedFeatures. cooperativeVectorFeatures , 736cooperativeVector, 737VK_NV_COOPERATIVE_VECTOR_EXTENSION_NAME , 738"cooperative-vector" ); 739 740#undef SIMPLE_EXTENSION_FEATURE 741 742if (extendedFeatures. vulkan12Features . shaderBufferInt64Atomics ) 743m_features. add ( "atomic-int64" ); 744 745if (extendedFeatures. vulkan12Features . timelineSemaphore ) 746m_features. add ( "timeline-semaphore" ); 747 748if (extendedFeatures. vulkan12Features . shaderSubgroupExtendedTypes ) 749m_features. add ( "shader-subgroup-extended-types" ); 750 751if (extendedFeatures. vulkan12Features . bufferDeviceAddress ) 752m_features. add ( "buffer-device-address" ); 753 754if ( _hasAnySetBits ( 755extendedFeatures. vulkan12Features , 756offsetof( VkPhysicalDeviceVulkan12Features , pNext ) + sizeof ( void * ))) 757{ 758extendedFeatures. vulkan12Features . pNext = ( void * )deviceCreateInfo. pNext ; 759deviceCreateInfo. pNext = & extendedFeatures. vulkan12Features ; 760} 761 762VkPhysicalDeviceProperties2 extendedProps = { 763VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 }; 764VkPhysicalDeviceRayTracingPipelinePropertiesKHR rtProps = { 765VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR }; 766VkPhysicalDeviceSubgroupProperties subgroupProps = { 767VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES }; 768 769rtProps. pNext = extendedProps. pNext ; 770extendedProps. pNext = & rtProps; 771subgroupProps. pNext = extendedProps. pNext ; 772extendedProps. pNext = & subgroupProps; 773 774m_api. vkGetPhysicalDeviceProperties2 (m_api. m_physicalDevice , & extendedProps); 775m_api. m_rtProperties = rtProps; 776 777// Approximate DX12's WaveOps boolean 778if (subgroupProps. supportedOperations & 779( VK_SUBGROUP_FEATURE_BASIC_BIT | VK_SUBGROUP_FEATURE_VOTE_BIT | 780VK_SUBGROUP_FEATURE_ARITHMETIC_BIT | VK_SUBGROUP_FEATURE_BALLOT_BIT | 781VK_SUBGROUP_FEATURE_SHUFFLE_BIT | VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT | 782VK_SUBGROUP_FEATURE_CLUSTERED_BIT | VK_SUBGROUP_FEATURE_QUAD_BIT | 783VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV )) 784{ 785m_features. add ( "wave-ops" ); 786} 787 788if (extensionNames. contains ( "VK_KHR_external_memory" )) 789{ 790deviceExtensions. add ( VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME ); 791#if SLANG_WINDOWS_FAMILY 792if (extensionNames. contains ( "VK_KHR_external_memory_win32" )) 793{ 794deviceExtensions. add ( VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME ); 795} 796#else 797if (extensionNames. contains ( "VK_KHR_external_memory_fd" )) 798{ 799deviceExtensions. add ( VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME ); 800} 801#endif 802m_features. add ( "external-memory" ); 803} 804if (extensionNames. contains ( VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME )) 805{ 806deviceExtensions. add ( VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME ); 807#if SLANG_WINDOWS_FAMILY 808if (extensionNames. contains ( VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME )) 809{ 810deviceExtensions. add ( VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME ); 811} 812#else 813if (extensionNames. contains ( VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME )) 814{ 815deviceExtensions. add ( VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME ); 816} 817#endif 818m_features. add ( "external-semaphore" ); 819} 820if (extensionNames. contains ( VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME )) 821{ 822deviceExtensions. add ( VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME ); 823m_features. add ( "conservative-rasterization-3" ); 824m_features. add ( "conservative-rasterization-2" ); 825m_features. add ( "conservative-rasterization-1" ); 826} 827if (extensionNames. contains ( VK_EXT_DEBUG_REPORT_EXTENSION_NAME )) 828{ 829deviceExtensions. add ( VK_EXT_DEBUG_REPORT_EXTENSION_NAME ); 830if (extensionNames. contains ( VK_EXT_DEBUG_MARKER_EXTENSION_NAME )) 831{ 832deviceExtensions. add ( VK_EXT_DEBUG_MARKER_EXTENSION_NAME ); 833} 834} 835if (extensionNames. contains ( VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME )) 836{ 837deviceExtensions. add ( VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME ); 838} 839if (extensionNames. contains ( VK_NVX_BINARY_IMPORT_EXTENSION_NAME )) 840{ 841deviceExtensions. add ( VK_NVX_BINARY_IMPORT_EXTENSION_NAME ); 842m_features. add ( "nvx-binary-import" ); 843} 844if (extensionNames. contains ( VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME )) 845{ 846deviceExtensions. add ( VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME ); 847m_features. add ( "nvx-image-view-handle" ); 848} 849if (extensionNames. contains ( VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME )) 850{ 851deviceExtensions. add ( VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME ); 852m_features. add ( "push-descriptor" ); 853} 854if (extensionNames. contains ( VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME )) 855{ 856deviceExtensions. add ( VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME ); 857m_features. add ( "barycentrics" ); 858} 859if (extensionNames. contains ( VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME )) 860{ 861deviceExtensions. add ( VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME ); 862m_features. add ( "shader-subgroup-partitioned" ); 863} 864 865// Derive approximate DX12 shader model. 866const char * featureTable[] = { 867"sm_6_0" , 868"wave-ops" , 869"atomic-int64" , 870nullptr , 871"sm_6_1" , 872"barycentrics" , 873"multiview" , 874nullptr , 875"sm_6_2" , 876"half" , 877nullptr , 878"sm_6_3" , 879"ray-tracing-pipeline" , 880nullptr , 881"sm_6_4" , 882"fragment-shading-rate" , 883nullptr , 884"sm_6_5" , 885"ray-query" , 886"mesh-shader" , 887nullptr , 888"sm_6_6" , 889"wave-ops" , 890"atomic-float" , 891"atomic-int64" , 892nullptr , 893nullptr , 894}; 895 896int i = 0 ; 897while (i < SLANG_COUNT_OF (featureTable)) 898{ 899const char * sm = featureTable[i ++ ]; 900if (sm == nullptr ) 901{ 902break ; 903} 904bool hasAll = true; 905while (i < SLANG_COUNT_OF (featureTable)) 906{ 907const char * feature = featureTable[i ++ ]; 908if (feature == nullptr ) 909{ 910break ; 911} 912hasAll &= m_features. contains (feature); 913} 914if (hasAll) 915{ 916m_features. add (sm); 917} 918else 919{ 920break ; 921} 922} 923} 924if (m_api. m_module -> isSoftware ()) 925{ 926m_features. add ( "software-device" ); 927} 928else 929{ 930m_features. add ( "hardware-device" ); 931} 932 933m_queueFamilyIndex = m_api. findQueue ( VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT ); 934assert (m_queueFamilyIndex >= 0 ); 935 936#if defined( GFX_NV_AFTERMATH ) 937VkDeviceDiagnosticsConfigCreateInfoNV aftermathInfo = {}; 938 939{ 940// Enable NV_device_diagnostic_checkpoints extension to be able to 941// use Aftermath event markers. 942deviceExtensions. add ( VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME ); 943 944// Enable NV_device_diagnostics_config extension to configure Aftermath 945// features. 946deviceExtensions. add ( VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME ); 947 948// Set up device creation info for Aftermath feature flag configuration. 949VkDeviceDiagnosticsConfigFlagsNV aftermathFlags = 950VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV | // Enable automatic 951// call stack 952// checkpoints. 953VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV | // Enable tracking of 954// resources. 955VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV ; // Generate debug 956// information for 957// shaders. 958// Not available on the version of Vulkan currently building with. 959// VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_ERROR_REPORTING_BIT_NV; // Enable additional 960// runtime shader error reporting. 961 962aftermathInfo. sType = VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV ; 963aftermathInfo. flags = aftermathFlags; 964 965aftermathInfo. pNext = deviceCreateInfo. pNext ; 966deviceCreateInfo. pNext = & aftermathInfo; 967} 968#endif 969 970if (handles[ 2 ]. handleValue == 0 ) 971{ 972float queuePriority = 0.0f ; 973VkDeviceQueueCreateInfo queueCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO }; 974queueCreateInfo. queueFamilyIndex = m_queueFamilyIndex; 975queueCreateInfo. queueCount = 1 ; 976queueCreateInfo. pQueuePriorities = & queuePriority; 977 978deviceCreateInfo. pQueueCreateInfos = & queueCreateInfo; 979 980deviceCreateInfo. enabledExtensionCount = uint32_t (deviceExtensions. getCount ()); 981deviceCreateInfo. ppEnabledExtensionNames = deviceExtensions. getBuffer (); 982 983if (m_api. vkCreateDevice (m_api. m_physicalDevice , & deviceCreateInfo, nullptr , & m_device) != 984VK_SUCCESS ) 985return SLANG_FAIL ; 986} 987else 988{ 989m_device = ( VkDevice )handles[ 2 ]. handleValue ; 990} 991 992SLANG_RETURN_ON_FAIL (m_api. initDeviceProcs (m_device)); 993 994if ( shouldDumpPipeline ()) 995{ 996installPipelineDumpLayer (m_api); 997} 998 999return SLANG_OK ; 1000} 1001 1002SlangResult DeviceImpl :: initialize ( const Desc & desc) 1003{ 1004// Initialize device info. 1005{ 1006m_info. apiName = "Vulkan" ; 1007m_info. bindingStyle = BindingStyle ::Vulkan; 1008m_info. projectionStyle = ProjectionStyle ::Vulkan; 1009m_info. deviceType = DeviceType ::Vulkan; 1010static const float kIdentity[] = { 1 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 1 }; 1011:: memcpy (m_info. identityProjectionMatrix , kIdentity, sizeof (kIdentity)); 1012} 1013 1014m_desc = desc; 1015 1016SLANG_RETURN_ON_FAIL ( RendererBase :: initialize (desc)); 1017SlangResult initDeviceResult = SLANG_OK ; 1018 1019m_glslang. init (); 1020for ( int forceSoftware = 0 ; forceSoftware <= 1 ; forceSoftware ++ ) 1021{ 1022initDeviceResult = m_module. init (forceSoftware != 0 ); 1023if (initDeviceResult != SLANG_OK ) 1024continue ; 1025initDeviceResult = m_api. initGlobalProcs (m_module); 1026if (initDeviceResult != SLANG_OK ) 1027continue ; 1028descriptorSetAllocator. m_api = & m_api; 1029initDeviceResult = initVulkanInstanceAndDevice ( 1030desc. existingDeviceHandles . handles , 1031isGfxDebugLayerEnabled ()); 1032if (initDeviceResult == SLANG_OK ) 1033break ; 1034} 1035SLANG_RETURN_ON_FAIL (initDeviceResult); 1036 1037{ 1038VkQueue queue; 1039m_api. vkGetDeviceQueue (m_device, m_queueFamilyIndex, 0 , & queue); 1040SLANG_RETURN_ON_FAIL (m_deviceQueue. init (m_api, queue, m_queueFamilyIndex)); 1041} 1042 1043SLANG_RETURN_ON_FAIL (slangContext. initialize ( 1044desc. slang , 1045desc. extendedDescCount , 1046desc. extendedDescs , 1047SLANG_SPIRV , 1048"sm_5_1" , 1049makeArray (slang:: PreprocessorMacroDesc { "__VK__" , "1" }). getView ())); 1050 1051// Create default sampler. 1052{ 1053VkSamplerCreateInfo samplerInfo = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; 1054samplerInfo. magFilter = VK_FILTER_NEAREST ; 1055samplerInfo. minFilter = VK_FILTER_NEAREST ; 1056samplerInfo. addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER ; 1057samplerInfo. addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER ; 1058samplerInfo. addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER ; 1059samplerInfo. anisotropyEnable = VK_FALSE ; 1060samplerInfo. maxAnisotropy = 1 ; 1061samplerInfo. borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK ; 1062samplerInfo. unnormalizedCoordinates = VK_FALSE ; 1063samplerInfo. compareEnable = VK_FALSE ; 1064samplerInfo. compareOp = VK_COMPARE_OP_NEVER ; 1065samplerInfo. mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST ; 1066samplerInfo. minLod = 0.0f ; 1067samplerInfo. maxLod = 0.0f ; 1068SLANG_VK_RETURN_ON_FAIL ( 1069m_api. vkCreateSampler (m_device, & samplerInfo, nullptr , & m_defaultSampler)); 1070} 1071 1072// Create empty frame buffer. 1073{ 1074IFramebufferLayout :: Desc layoutDesc = {}; 1075layoutDesc. renderTargetCount = 0 ; 1076layoutDesc. depthStencil = nullptr ; 1077ComPtr < IFramebufferLayout > layout; 1078SLANG_RETURN_ON_FAIL ( createFramebufferLayout (layoutDesc, layout. writeRef ())); 1079IFramebuffer :: Desc desc = {}; 1080desc. layout = layout; 1081ComPtr < IFramebuffer > framebuffer; 1082SLANG_RETURN_ON_FAIL ( createFramebuffer (desc, framebuffer. writeRef ())); 1083m_emptyFramebuffer = static_cast < FramebufferImpl *> (framebuffer. get ()); 1084m_emptyFramebuffer -> m_renderer . breakStrongReference (); 1085} 1086 1087return SLANG_OK ; 1088} 1089 1090void DeviceImpl :: waitForGpu () 1091{ 1092m_deviceQueue. flushAndWait (); 1093} 1094 1095SLANG_NO_THROW const DeviceInfo & SLANG_MCALL DeviceImpl:: getDeviceInfo () const 1096{ 1097return m_info; 1098} 1099 1100Result DeviceImpl :: createTransientResourceHeap ( 1101const ITransientResourceHeap :: Desc & desc, 1102ITransientResourceHeap ** outHeap) 1103{ 1104RefPtr < TransientResourceHeapImpl > result = new TransientResourceHeapImpl (); 1105SLANG_RETURN_ON_FAIL (result -> init (desc, this)); 1106returnComPtr (outHeap, result); 1107return SLANG_OK ; 1108} 1109 1110Result DeviceImpl :: createCommandQueue ( const ICommandQueue :: Desc & desc, ICommandQueue ** outQueue) 1111{ 1112// Only support one queue for now. 1113if (m_queueAllocCount != 0 ) 1114return SLANG_FAIL ; 1115auto queueFamilyIndex = m_api. findQueue ( VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT ); 1116VkQueue vkQueue; 1117m_api. vkGetDeviceQueue (m_api. m_device , queueFamilyIndex, 0 , & vkQueue); 1118RefPtr < CommandQueueImpl > result = new CommandQueueImpl (); 1119result -> init (this, vkQueue, queueFamilyIndex); 1120returnComPtr (outQueue, result); 1121m_queueAllocCount ++ ; 1122return SLANG_OK ; 1123} 1124 1125Result DeviceImpl :: createSwapchain ( 1126const ISwapchain :: Desc & desc, 1127WindowHandle window, 1128ISwapchain ** outSwapchain) 1129{ 1130#if !defined( SLANG_ENABLE_XLIB ) 1131if (window. type == WindowHandle :: Type ::XLibHandle) 1132{ 1133return SLANG_FAIL ; 1134} 1135#endif 1136 1137RefPtr < SwapchainImpl > sc = new SwapchainImpl (); 1138SLANG_RETURN_ON_FAIL (sc -> init (this, desc, window)); 1139returnComPtr (outSwapchain, sc); 1140return SLANG_OK ; 1141} 1142 1143Result DeviceImpl :: createFramebufferLayout ( 1144const IFramebufferLayout :: Desc & desc, 1145IFramebufferLayout ** outLayout) 1146{ 1147RefPtr < FramebufferLayoutImpl > layout = new FramebufferLayoutImpl (); 1148SLANG_RETURN_ON_FAIL (layout -> init (this, desc)); 1149returnComPtr (outLayout, layout); 1150return SLANG_OK ; 1151} 1152 1153Result DeviceImpl :: createRenderPassLayout ( 1154const IRenderPassLayout :: Desc & desc, 1155IRenderPassLayout ** outRenderPassLayout) 1156{ 1157RefPtr < RenderPassLayoutImpl > result = new RenderPassLayoutImpl (); 1158SLANG_RETURN_ON_FAIL (result -> init (this, desc)); 1159returnComPtr (outRenderPassLayout, result); 1160return SLANG_OK ; 1161} 1162 1163Result DeviceImpl :: createFramebuffer ( const IFramebuffer :: Desc & desc, IFramebuffer ** outFramebuffer) 1164{ 1165RefPtr < FramebufferImpl > fb = new FramebufferImpl (); 1166SLANG_RETURN_ON_FAIL (fb -> init (this, desc)); 1167returnComPtr (outFramebuffer, fb); 1168return SLANG_OK ; 1169} 1170 1171SlangResult DeviceImpl :: readTextureResource ( 1172ITextureResource * texture, 1173ResourceState state, 1174ISlangBlob ** outBlob, 1175Size * outRowPitch, 1176Size * outPixelSize) 1177{ 1178auto textureImpl = static_cast < TextureResourceImpl *> (texture); 1179 1180List < uint8_t > blobData; 1181 1182auto desc = textureImpl -> getDesc (); 1183auto width = desc -> size . width ; 1184auto height = desc -> size . height ; 1185FormatInfo sizeInfo; 1186SLANG_RETURN_ON_FAIL ( gfxGetFormatInfo (desc -> format , & sizeInfo)); 1187Size pixelSize = sizeInfo. blockSizeInBytes / sizeInfo. pixelsPerBlock ; 1188Size rowPitch = width * pixelSize; 1189 1190List < TextureResource :: Extents > mipSizes; 1191 1192const int numMipMaps = desc -> numMipLevels ; 1193auto arraySize = calcEffectiveArraySize ( * desc); 1194 1195// Calculate how large the buffer has to be 1196Size bufferSize = 0 ; 1197// Calculate how large an array entry is 1198for ( int j = 0 ; j < numMipMaps; ++ j) 1199{ 1200const TextureResource :: Extents mipSize = calcMipSize (desc -> size , j); 1201 1202auto rowSizeInBytes = calcRowSize (desc -> format , mipSize. width ); 1203auto numRows = calcNumRows (desc -> format , mipSize. height ); 1204 1205mipSizes. add (mipSize); 1206 1207bufferSize += (rowSizeInBytes * numRows) * mipSize. depth ; 1208} 1209// Calculate the total size taking into account the array 1210bufferSize *= arraySize; 1211 1212blobData. setCount ( Count (bufferSize)); 1213 1214VKBufferHandleRAII staging; 1215SLANG_RETURN_ON_FAIL (staging. init ( 1216m_api, 1217bufferSize, 1218VK_BUFFER_USAGE_TRANSFER_DST_BIT , 1219VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT )); 1220 1221VkCommandBuffer commandBuffer = m_deviceQueue. getCommandBuffer (); 1222VkImage srcImage = textureImpl -> m_image ; 1223VkImageLayout srcImageLayout = VulkanUtil :: getImageLayoutFromState (state); 1224 1225Offset dstOffset = 0 ; 1226for ( int i = 0 ; i < arraySize; ++ i) 1227{ 1228for ( Index j = 0 ; j < mipSizes. getCount (); ++ j) 1229{ 1230const auto & mipSize = mipSizes[j]; 1231 1232auto rowSizeInBytes = calcRowSize (desc -> format , mipSize. width ); 1233auto numRows = calcNumRows (desc -> format , mipSize. height ); 1234 1235VkBufferImageCopy region = {}; 1236 1237region. bufferOffset = dstOffset; 1238region. bufferRowLength = 0 ; 1239region. bufferImageHeight = 0 ; 1240 1241region. imageSubresource . aspectMask = 1242getAspectMaskFromFormat ( VulkanUtil :: getVkFormat (desc -> format )); 1243region. imageSubresource . mipLevel = uint32_t (j); 1244region. imageSubresource . baseArrayLayer = i; 1245region. imageSubresource . layerCount = 1 ; 1246region. imageOffset = { 0 , 0 , 0 }; 1247region. imageExtent = { 1248uint32_t (mipSize. width ), 1249uint32_t (mipSize. height ), 1250uint32_t (mipSize. depth )}; 1251 1252m_api. vkCmdCopyImageToBuffer ( 1253commandBuffer, 1254srcImage, 1255srcImageLayout, 1256staging. m_buffer , 12571 , 1258& region); 1259 1260dstOffset += rowSizeInBytes * numRows * mipSize. depth ; 1261} 1262} 1263 1264m_deviceQueue. flushAndWait (); 1265 1266// Write out the data from the buffer 1267void * mappedData = nullptr ; 1268SLANG_RETURN_ON_FAIL ( 1269m_api. vkMapMemory (m_device, staging. m_memory , 0 , bufferSize, 0 , & mappedData)); 1270 1271:: memcpy (blobData. getBuffer (), mappedData, bufferSize); 1272m_api. vkUnmapMemory (m_device, staging. m_memory ); 1273 1274* outPixelSize = pixelSize; 1275* outRowPitch = rowPitch; 1276 1277auto blob = ListBlob :: moveCreate (blobData); 1278 1279returnComPtr (outBlob, blob); 1280return SLANG_OK ; 1281} 1282 1283SlangResult DeviceImpl :: readBufferResource ( 1284IBufferResource * inBuffer, 1285Offset offset, 1286Size size, 1287ISlangBlob ** outBlob) 1288{ 1289BufferResourceImpl * buffer = static_cast < BufferResourceImpl *> (inBuffer); 1290 1291List < uint8_t > blobData; 1292 1293blobData. setCount (size); 1294 1295// create staging buffer 1296VKBufferHandleRAII staging; 1297 1298SLANG_RETURN_ON_FAIL (staging. init ( 1299m_api, 1300size, 1301VK_BUFFER_USAGE_TRANSFER_DST_BIT , 1302VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT )); 1303 1304// Copy from real buffer to staging buffer 1305VkCommandBuffer commandBuffer = m_deviceQueue. getCommandBuffer (); 1306 1307VkBufferCopy copyInfo = {}; 1308copyInfo. size = size; 1309copyInfo. srcOffset = offset; 1310m_api. vkCmdCopyBuffer (commandBuffer, buffer -> m_buffer . m_buffer , staging. m_buffer , 1 , & copyInfo); 1311 1312m_deviceQueue. flushAndWait (); 1313 1314// Write out the data from the buffer 1315void * mappedData = nullptr ; 1316SLANG_RETURN_ON_FAIL (m_api. vkMapMemory (m_device, staging. m_memory , 0 , size, 0 , & mappedData)); 1317 1318:: memcpy (blobData. getBuffer (), mappedData, size); 1319m_api. vkUnmapMemory (m_device, staging. m_memory ); 1320 1321auto blob = ListBlob :: moveCreate (blobData); 1322 1323returnComPtr (outBlob, blob); 1324return SLANG_OK ; 1325} 1326 1327Result DeviceImpl :: getAccelerationStructurePrebuildInfo ( 1328const IAccelerationStructure :: BuildInputs & buildInputs, 1329IAccelerationStructure :: PrebuildInfo * outPrebuildInfo) 1330{ 1331if (!m_api. vkGetAccelerationStructureBuildSizesKHR ) 1332{ 1333return SLANG_E_NOT_AVAILABLE ; 1334} 1335VkAccelerationStructureBuildSizesInfoKHR sizeInfo = { 1336VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR }; 1337AccelerationStructureBuildGeometryInfoBuilder geomInfoBuilder; 1338SLANG_RETURN_ON_FAIL (geomInfoBuilder. build (buildInputs, getDebugCallback ())); 1339m_api. vkGetAccelerationStructureBuildSizesKHR ( 1340m_api. m_device , 1341VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR , 1342& geomInfoBuilder. buildInfo , 1343geomInfoBuilder. primitiveCounts . getBuffer (), 1344& sizeInfo); 1345outPrebuildInfo -> resultDataMaxSize = ( Size )sizeInfo. accelerationStructureSize ; 1346outPrebuildInfo -> scratchDataSize = ( Size )sizeInfo. buildScratchSize ; 1347outPrebuildInfo -> updateScratchDataSize = ( Size )sizeInfo. updateScratchSize ; 1348return SLANG_OK ; 1349} 1350 1351Result DeviceImpl :: createAccelerationStructure ( 1352const IAccelerationStructure :: CreateDesc & desc, 1353IAccelerationStructure ** outAS) 1354{ 1355if (!m_api. vkCreateAccelerationStructureKHR ) 1356{ 1357return SLANG_E_NOT_AVAILABLE ; 1358} 1359RefPtr < AccelerationStructureImpl > resultAS = new AccelerationStructureImpl (); 1360resultAS -> m_offset = desc. offset ; 1361resultAS -> m_size = desc. size ; 1362resultAS -> m_buffer = static_cast < BufferResourceImpl *> (desc. buffer ); 1363resultAS -> m_device = this; 1364resultAS -> m_desc . type = IResourceView :: Type ::AccelerationStructure; 1365VkAccelerationStructureCreateInfoKHR createInfo = { 1366VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR }; 1367createInfo. buffer = resultAS -> m_buffer -> m_buffer . m_buffer ; 1368createInfo. offset = desc. offset ; 1369createInfo. size = desc. size ; 1370switch (desc. kind ) 1371{ 1372case IAccelerationStructure :: Kind ::BottomLevel: 1373createInfo. type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR ; 1374break ; 1375case IAccelerationStructure :: Kind ::TopLevel: 1376createInfo. type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR ; 1377break ; 1378default : 1379getDebugCallback () -> handleMessage ( 1380DebugMessageType ::Error, 1381DebugMessageSource ::Layer, 1382"invalid value of IAccelerationStructure::Kind encountered in desc.kind" ); 1383return SLANG_E_INVALID_ARG ; 1384} 1385 1386SLANG_VK_RETURN_ON_FAIL (m_api. vkCreateAccelerationStructureKHR ( 1387m_api. m_device , 1388& createInfo, 1389nullptr , 1390& resultAS -> m_vkHandle )); 1391returnComPtr (outAS, resultAS); 1392return SLANG_OK ; 1393} 1394 1395void DeviceImpl :: _transitionImageLayout ( 1396VkCommandBuffer commandBuffer, 1397VkImage image, 1398VkFormat format, 1399const TextureResource :: Desc & desc, 1400VkImageLayout oldLayout, 1401VkImageLayout newLayout) 1402{ 1403if (oldLayout == newLayout) 1404return ; 1405 1406VkImageMemoryBarrier barrier = {}; 1407barrier. sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER ; 1408barrier. oldLayout = oldLayout; 1409barrier. newLayout = newLayout; 1410barrier. srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED ; 1411barrier. dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED ; 1412barrier. image = image; 1413 1414barrier. subresourceRange . aspectMask = getAspectMaskFromFormat (format); 1415 1416barrier. subresourceRange . baseMipLevel = 0 ; 1417barrier. subresourceRange . levelCount = desc. numMipLevels ; 1418barrier. subresourceRange . baseArrayLayer = 0 ; 1419barrier. subresourceRange . layerCount = VK_REMAINING_ARRAY_LAYERS ; 1420barrier. srcAccessMask = calcAccessFlagsFromImageLayout (oldLayout); 1421barrier. dstAccessMask = calcAccessFlagsFromImageLayout (newLayout); 1422 1423VkPipelineStageFlags sourceStage = calcPipelineStageFlagsFromImageLayout (oldLayout); 1424VkPipelineStageFlags destinationStage = calcPipelineStageFlagsFromImageLayout (newLayout); 1425 1426m_api. vkCmdPipelineBarrier ( 1427commandBuffer, 1428sourceStage, 1429destinationStage, 14300 , 14310 , 1432nullptr , 14330 , 1434nullptr , 14351 , 1436& barrier); 1437} 1438 1439uint32_t DeviceImpl :: getQueueFamilyIndex ( ICommandQueue :: QueueType queueType) 1440{ 1441switch (queueType) 1442{ 1443case ICommandQueue :: QueueType ::Graphics: 1444default : 1445return m_queueFamilyIndex; 1446} 1447} 1448 1449void DeviceImpl :: _transitionImageLayout ( 1450VkImage image, 1451VkFormat format, 1452const TextureResource :: Desc & desc, 1453VkImageLayout oldLayout, 1454VkImageLayout newLayout) 1455{ 1456VkCommandBuffer commandBuffer = m_deviceQueue. getCommandBuffer (); 1457_transitionImageLayout (commandBuffer, image, format, desc, oldLayout, newLayout); 1458} 1459 1460Result DeviceImpl :: getTextureAllocationInfo ( 1461const ITextureResource :: Desc & descIn, 1462Size * outSize, 1463Size * outAlignment) 1464{ 1465TextureResource :: Desc desc = fixupTextureDesc (descIn); 1466 1467const VkFormat format = VulkanUtil :: getVkFormat (desc. format ); 1468if (format == VK_FORMAT_UNDEFINED ) 1469{ 1470assert (! "Unhandled image format" ); 1471return SLANG_FAIL ; 1472} 1473const int arraySize = calcEffectiveArraySize (desc); 1474 1475VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; 1476switch (desc. type ) 1477{ 1478case IResource :: Type ::Texture1D: 1479{ 1480imageInfo. imageType = VK_IMAGE_TYPE_1D ; 1481imageInfo. extent = VkExtent3D { uint32_t (descIn. size . width ), 1 , 1 }; 1482break ; 1483} 1484case IResource :: Type ::Texture2D: 1485{ 1486imageInfo. imageType = VK_IMAGE_TYPE_2D ; 1487imageInfo. extent = 1488VkExtent3D { uint32_t (descIn. size . width ), uint32_t (descIn. size . height ), 1 }; 1489break ; 1490} 1491case IResource :: Type ::TextureCube: 1492{ 1493imageInfo. imageType = VK_IMAGE_TYPE_2D ; 1494imageInfo. extent = 1495VkExtent3D { uint32_t (descIn. size . width ), uint32_t (descIn. size . height ), 1 }; 1496imageInfo. flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT ; 1497break ; 1498} 1499case IResource :: Type ::Texture3D: 1500{ 1501// Can't have an array and 3d texture 1502assert (desc. arraySize <= 1 ); 1503 1504imageInfo. imageType = VK_IMAGE_TYPE_3D ; 1505imageInfo. extent = VkExtent3D { 1506uint32_t (descIn. size . width ), 1507uint32_t (descIn. size . height ), 1508uint32_t (descIn. size . depth )}; 1509break ; 1510} 1511default : 1512{ 1513assert (! "Unhandled type" ); 1514return SLANG_FAIL ; 1515} 1516} 1517 1518imageInfo. mipLevels = desc. numMipLevels ; 1519imageInfo. arrayLayers = arraySize; 1520 1521imageInfo. format = format; 1522 1523imageInfo. tiling = VK_IMAGE_TILING_OPTIMAL ; 1524imageInfo. usage = _calcImageUsageFlags (desc. allowedStates , desc. memoryType , nullptr ); 1525imageInfo. sharingMode = VK_SHARING_MODE_EXCLUSIVE ; 1526 1527imageInfo. samples = ( VkSampleCountFlagBits )desc. sampleDesc . numSamples ; 1528 1529VkImage image; 1530SLANG_VK_RETURN_ON_FAIL (m_api. vkCreateImage (m_device, & imageInfo, nullptr , & image)); 1531 1532VkMemoryRequirements memRequirements; 1533m_api. vkGetImageMemoryRequirements (m_device, image, & memRequirements); 1534 1535* outSize = ( Size )memRequirements. size ; 1536* outAlignment = ( Size )memRequirements. alignment ; 1537 1538m_api. vkDestroyImage (m_device, image, nullptr ); 1539return SLANG_OK ; 1540} 1541 1542Result DeviceImpl :: getTextureRowAlignment ( Size * outAlignment) 1543{ 1544* outAlignment = 1 ; 1545return SLANG_OK ; 1546} 1547 1548Result DeviceImpl :: getCooperativeVectorProperties ( 1549CooperativeVectorProperties * properties, 1550uint32_t * propertyCount) 1551{ 1552if (!m_api. m_extendedFeatures . cooperativeVectorFeatures . cooperativeVector || 1553!m_api. vkGetPhysicalDeviceCooperativeVectorPropertiesNV ) 1554return SLANG_E_NOT_AVAILABLE ; 1555 1556if (m_cooperativeVectorProperties. empty ()) 1557{ 1558uint32_t vkPropertyCount = 0 ; 1559m_api. vkGetPhysicalDeviceCooperativeVectorPropertiesNV ( 1560m_api. m_physicalDevice , 1561& vkPropertyCount, 1562nullptr ); 1563std:: vector < VkCooperativeVectorPropertiesNV > vkProperties ( vkPropertyCount ); 1564SLANG_VK_RETURN_ON_FAIL (m_api. vkGetPhysicalDeviceCooperativeVectorPropertiesNV ( 1565m_api. m_physicalDevice , 1566& vkPropertyCount, 1567vkProperties. data ())); 1568for ( const auto & vkProps : vkProperties) 1569{ 1570CooperativeVectorProperties props; 1571props. inputType = 1572VulkanUtil :: translateCooperativeVectorComponentType (vkProps. inputType ); 1573props. inputInterpretation = 1574VulkanUtil :: translateCooperativeVectorComponentType (vkProps. inputInterpretation ); 1575props. matrixInterpretation = 1576VulkanUtil :: translateCooperativeVectorComponentType (vkProps. matrixInterpretation ); 1577props. biasInterpretation = 1578VulkanUtil :: translateCooperativeVectorComponentType (vkProps. biasInterpretation ); 1579props. resultType = 1580VulkanUtil :: translateCooperativeVectorComponentType (vkProps. resultType ); 1581props. transpose = vkProps. transpose ; 1582m_cooperativeVectorProperties. push_back (props); 1583} 1584} 1585 1586return RendererBase :: getCooperativeVectorProperties (properties, propertyCount); 1587} 1588 1589Result DeviceImpl :: createTextureResource ( 1590const ITextureResource :: Desc & descIn, 1591const ITextureResource :: SubresourceData * initData, 1592ITextureResource ** outResource) 1593{ 1594TextureResource :: Desc desc = fixupTextureDesc (descIn); 1595 1596const VkFormat format = VulkanUtil :: getVkFormat (desc. format ); 1597if (format == VK_FORMAT_UNDEFINED ) 1598{ 1599assert (! "Unhandled image format" ); 1600return SLANG_FAIL ; 1601} 1602 1603const int arraySize = calcEffectiveArraySize (desc); 1604 1605RefPtr < TextureResourceImpl > texture( new TextureResourceImpl (desc, this)); 1606texture -> m_vkformat = format; 1607// Create the image 1608 1609VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; 1610switch (desc. type ) 1611{ 1612case IResource :: Type ::Texture1D: 1613{ 1614imageInfo. imageType = VK_IMAGE_TYPE_1D ; 1615imageInfo. extent = VkExtent3D { uint32_t (descIn. size . width ), 1 , 1 }; 1616break ; 1617} 1618case IResource :: Type ::Texture2D: 1619{ 1620imageInfo. imageType = VK_IMAGE_TYPE_2D ; 1621imageInfo. extent = 1622VkExtent3D { uint32_t (descIn. size . width ), uint32_t (descIn. size . height ), 1 }; 1623break ; 1624} 1625case IResource :: Type ::TextureCube: 1626{ 1627imageInfo. imageType = VK_IMAGE_TYPE_2D ; 1628imageInfo. extent = 1629VkExtent3D { uint32_t (descIn. size . width ), uint32_t (descIn. size . height ), 1 }; 1630imageInfo. flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT ; 1631break ; 1632} 1633case IResource :: Type ::Texture3D: 1634{ 1635// Can't have an array and 3d texture 1636assert (desc. arraySize <= 1 ); 1637 1638imageInfo. imageType = VK_IMAGE_TYPE_3D ; 1639imageInfo. extent = VkExtent3D { 1640uint32_t (descIn. size . width ), 1641uint32_t (descIn. size . height ), 1642uint32_t (descIn. size . depth )}; 1643break ; 1644} 1645default : 1646{ 1647assert (! "Unhandled type" ); 1648return SLANG_FAIL ; 1649} 1650} 1651 1652imageInfo. mipLevels = desc. numMipLevels ; 1653imageInfo. arrayLayers = arraySize; 1654 1655imageInfo. format = format; 1656 1657imageInfo. tiling = VK_IMAGE_TILING_OPTIMAL ; 1658imageInfo. usage = _calcImageUsageFlags (desc. allowedStates , desc. memoryType , initData); 1659imageInfo. sharingMode = VK_SHARING_MODE_EXCLUSIVE ; 1660 1661imageInfo. samples = ( VkSampleCountFlagBits )desc. sampleDesc . numSamples ; 1662 1663VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = { 1664VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO }; 1665VkExternalMemoryHandleTypeFlags extMemoryHandleType = 1666#if SLANG_WINDOWS_FAMILY 1667VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT ; 1668#else 1669VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ; 1670#endif 1671if (descIn. isShared ) 1672{ 1673externalMemoryImageCreateInfo. pNext = nullptr ; 1674externalMemoryImageCreateInfo. handleTypes = extMemoryHandleType; 1675imageInfo. pNext = & externalMemoryImageCreateInfo; 1676} 1677SLANG_VK_RETURN_ON_FAIL (m_api. vkCreateImage (m_device, & imageInfo, nullptr , & texture -> m_image )); 1678 1679VkMemoryRequirements memRequirements; 1680m_api. vkGetImageMemoryRequirements (m_device, texture -> m_image , & memRequirements); 1681 1682// Allocate the memory 1683VkMemoryPropertyFlags reqMemoryProperties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ; 1684int memoryTypeIndex = 1685m_api. findMemoryTypeIndex (memRequirements. memoryTypeBits , reqMemoryProperties); 1686assert (memoryTypeIndex >= 0 ); 1687 1688VkMemoryPropertyFlags actualMemoryProperites = 1689m_api. m_deviceMemoryProperties . memoryTypes [memoryTypeIndex]. propertyFlags ; 1690VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; 1691allocInfo. allocationSize = memRequirements. size ; 1692allocInfo. memoryTypeIndex = memoryTypeIndex; 1693#if SLANG_WINDOWS_FAMILY 1694VkExportMemoryWin32HandleInfoKHR exportMemoryWin32HandleInfo = { 1695VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR }; 1696#endif 1697VkExportMemoryAllocateInfoKHR exportMemoryAllocateInfo = { 1698VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR }; 1699if (descIn. isShared ) 1700{ 1701#if SLANG_WINDOWS_FAMILY 1702exportMemoryWin32HandleInfo. pNext = nullptr ; 1703exportMemoryWin32HandleInfo. pAttributes = nullptr ; 1704exportMemoryWin32HandleInfo. dwAccess = 1705DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE ; 1706exportMemoryWin32HandleInfo. name = NULL ; 1707 1708exportMemoryAllocateInfo. pNext = 1709extMemoryHandleType & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR 1710? & exportMemoryWin32HandleInfo 1711: nullptr ; 1712#endif 1713exportMemoryAllocateInfo. handleTypes = extMemoryHandleType; 1714allocInfo. pNext = & exportMemoryAllocateInfo; 1715} 1716SLANG_VK_RETURN_ON_FAIL ( 1717m_api. vkAllocateMemory (m_device, & allocInfo, nullptr , & texture -> m_imageMemory )); 1718 1719// Bind the memory to the image 1720m_api. vkBindImageMemory (m_device, texture -> m_image , texture -> m_imageMemory , 0 ); 1721 1722VKBufferHandleRAII uploadBuffer; 1723if (initData) 1724{ 1725List < TextureResource :: Extents > mipSizes; 1726 1727VkCommandBuffer commandBuffer = m_deviceQueue. getCommandBuffer (); 1728 1729const int numMipMaps = desc. numMipLevels ; 1730 1731// Calculate how large the buffer has to be 1732Size bufferSize = 0 ; 1733// Calculate how large an array entry is 1734for ( int j = 0 ; j < numMipMaps; ++ j) 1735{ 1736const TextureResource :: Extents mipSize = calcMipSize (desc. size , j); 1737 1738auto rowSizeInBytes = calcRowSize (desc. format , mipSize. width ); 1739auto numRows = calcNumRows (desc. format , mipSize. height ); 1740 1741mipSizes. add (mipSize); 1742 1743bufferSize += (rowSizeInBytes * numRows) * mipSize. depth ; 1744} 1745 1746// Calculate the total size taking into account the array 1747bufferSize *= arraySize; 1748 1749SLANG_RETURN_ON_FAIL (uploadBuffer. init ( 1750m_api, 1751bufferSize, 1752VK_BUFFER_USAGE_TRANSFER_SRC_BIT , 1753VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT )); 1754 1755assert (mipSizes. getCount () == numMipMaps); 1756 1757// Copy into upload buffer 1758{ 1759int subResourceCounter = 0 ; 1760 1761uint8_t * dstData; 1762m_api. vkMapMemory (m_device, uploadBuffer. m_memory , 0 , bufferSize, 0 , ( void ** ) & dstData); 1763uint8_t * dstDataStart; 1764dstDataStart = dstData; 1765 1766Offset dstSubresourceOffset = 0 ; 1767for ( int i = 0 ; i < arraySize; ++ i) 1768{ 1769for ( Index j = 0 ; j < mipSizes. getCount (); ++ j) 1770{ 1771const auto & mipSize = mipSizes[j]; 1772 1773int subResourceIndex = subResourceCounter ++ ; 1774auto initSubresource = initData[subResourceIndex]; 1775 1776const ptrdiff_t srcRowStride = ( ptrdiff_t )initSubresource. strideY ; 1777const ptrdiff_t srcLayerStride = ( ptrdiff_t )initSubresource. strideZ ; 1778 1779auto dstRowSizeInBytes = calcRowSize (desc. format , mipSize. width ); 1780auto numRows = calcNumRows (desc. format , mipSize. height ); 1781auto dstLayerSizeInBytes = dstRowSizeInBytes * numRows; 1782 1783const uint8_t * srcLayer = ( const uint8_t * )initSubresource. data ; 1784uint8_t * dstLayer = dstData + dstSubresourceOffset; 1785 1786for ( int k = 0 ; k < mipSize. depth ; k ++ ) 1787{ 1788const uint8_t * srcRow = srcLayer; 1789uint8_t * dstRow = dstLayer; 1790 1791for ( GfxCount l = 0 ; l < numRows; l ++ ) 1792{ 1793:: memcpy (dstRow, srcRow, dstRowSizeInBytes); 1794 1795dstRow += dstRowSizeInBytes; 1796srcRow += srcRowStride; 1797} 1798 1799dstLayer += dstLayerSizeInBytes; 1800srcLayer += srcLayerStride; 1801} 1802 1803dstSubresourceOffset += dstLayerSizeInBytes * mipSize. depth ; 1804} 1805} 1806 1807m_api. vkUnmapMemory (m_device, uploadBuffer. m_memory ); 1808} 1809 1810_transitionImageLayout ( 1811texture -> m_image , 1812format, 1813* texture -> getDesc (), 1814VK_IMAGE_LAYOUT_UNDEFINED , 1815VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ); 1816 1817if (desc. sampleDesc . numSamples != 1 ) 1818{ 1819// Handle senario where texture is sampled. We cannot use 1820// a simple buffer copy for sampled textures. ClearColorImage 1821// is not data accurate but it is fine for testing & works. 1822FormatInfo formatInfo; 1823gfxGetFormatInfo (desc. format , & formatInfo); 1824uint32_t data = 0 ; 1825VkClearColorValue clearColor; 1826switch (formatInfo. channelType ) 1827{ 1828case SLANG_SCALAR_TYPE_INT32 : 1829for ( int i = 0 ; i < 4 ; i ++ ) 1830clearColor. int32 [i] = 1831* reinterpret_cast < int32_t *> ( const_cast < void *> (initData -> data )); 1832break ; 1833case SLANG_SCALAR_TYPE_UINT32 : 1834for ( int i = 0 ; i < 4 ; i ++ ) 1835clearColor. uint32 [i] = 1836* reinterpret_cast < uint32_t *> ( const_cast < void *> (initData -> data )); 1837break ; 1838case SLANG_SCALAR_TYPE_INT64 : 1839{ 1840for ( int i = 0 ; i < 4 ; i ++ ) 1841clearColor. int32 [i] = 1842int32_t ( * reinterpret_cast < int64_t *> ( const_cast < void *> (initData -> data ))); 1843break ; 1844} 1845case SLANG_SCALAR_TYPE_UINT64 : 1846{ 1847for ( int i = 0 ; i < 4 ; i ++ ) 1848clearColor. uint32 [i] = uint32_t ( 1849* reinterpret_cast < uint64_t *> ( const_cast < void *> (initData -> data ))); 1850break ; 1851} 1852case SLANG_SCALAR_TYPE_FLOAT16 : 1853{ 1854for ( int i = 0 ; i < 4 ; i ++ ) 1855clearColor. float32 [i] = HalfToFloat ( 1856* reinterpret_cast < uint16_t *> ( const_cast < void *> (initData -> data ))); 1857break ; 1858} 1859case SLANG_SCALAR_TYPE_FLOAT32 : 1860{ 1861for ( int i = 0 ; i < 4 ; i ++ ) 1862clearColor. float32 [i] = 1863( * reinterpret_cast < float *> ( const_cast < void *> (initData -> data ))); 1864break ; 1865} 1866case SLANG_SCALAR_TYPE_FLOAT64 : 1867{ 1868for ( int i = 0 ; i < 4 ; i ++ ) 1869clearColor. float32 [i] = 1870float ( * reinterpret_cast < double *> ( const_cast < void *> (initData -> data ))); 1871break ; 1872} 1873case SLANG_SCALAR_TYPE_INT8 : 1874{ 1875for ( int i = 0 ; i < 4 ; i ++ ) 1876clearColor. int32 [i] = 1877int32_t ( * reinterpret_cast < int8_t *> ( const_cast < void *> (initData -> data ))); 1878break ; 1879} 1880case SLANG_SCALAR_TYPE_UINT8 : 1881{ 1882for ( int i = 0 ; i < 4 ; i ++ ) 1883clearColor. uint32 [i] = uint32_t ( 1884* reinterpret_cast < uint8_t *> ( const_cast < void *> (initData -> data ))); 1885break ; 1886} 1887case SLANG_SCALAR_TYPE_INT16 : 1888{ 1889for ( int i = 0 ; i < 4 ; i ++ ) 1890clearColor. int32 [i] = 1891int32_t ( * reinterpret_cast < int16_t *> ( const_cast < void *> (initData -> data ))); 1892break ; 1893} 1894case SLANG_SCALAR_TYPE_UINT16 : 1895{ 1896for ( int i = 0 ; i < 4 ; i ++ ) 1897clearColor. uint32 [i] = uint32_t ( 1898* reinterpret_cast < uint16_t *> ( const_cast < void *> (initData -> data ))); 1899break ; 1900} 1901}; 1902 1903VkImageSubresourceRange range{}; 1904range. aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ; 1905range. baseMipLevel = 0 ; 1906range. levelCount = VK_REMAINING_MIP_LEVELS ; 1907range. baseArrayLayer = 0 ; 1908range. layerCount = VK_REMAINING_ARRAY_LAYERS ; 1909 1910m_api. vkCmdClearColorImage ( 1911commandBuffer, 1912texture -> m_image , 1913VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL , 1914& clearColor, 19151 , 1916& range); 1917} 1918else 1919{ 1920Offset srcOffset = 0 ; 1921for ( int i = 0 ; i < arraySize; ++ i) 1922{ 1923for ( Index j = 0 ; j < mipSizes. getCount (); ++ j) 1924{ 1925const auto & mipSize = mipSizes[j]; 1926 1927auto rowSizeInBytes = calcRowSize (desc. format , mipSize. width ); 1928auto numRows = calcNumRows (desc. format , mipSize. height ); 1929 1930// https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkBufferImageCopy.html 1931// bufferRowLength and bufferImageHeight specify the data in buffer memory as a 1932// subregion of a larger two- or three-dimensional image, and control the 1933// addressing calculations of data in buffer memory. If either of these values 1934// is zero, that aspect of the buffer memory is considered to be tightly packed 1935// according to the imageExtent. 1936 1937VkBufferImageCopy region = {}; 1938 1939region. bufferOffset = srcOffset; 1940region. bufferRowLength = 0 ; // rowSizeInBytes; 1941region. bufferImageHeight = 0 ; 1942 1943region. imageSubresource . aspectMask = getAspectMaskFromFormat (format); 1944region. imageSubresource . mipLevel = uint32_t (j); 1945region. imageSubresource . baseArrayLayer = i; 1946region. imageSubresource . layerCount = 1 ; 1947region. imageOffset = { 0 , 0 , 0 }; 1948region. imageExtent = { 1949uint32_t (mipSize. width ), 1950uint32_t (mipSize. height ), 1951uint32_t (mipSize. depth )}; 1952 1953// Do the copy (do all depths in a single go) 1954m_api. vkCmdCopyBufferToImage ( 1955commandBuffer, 1956uploadBuffer. m_buffer , 1957texture -> m_image , 1958VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL , 19591 , 1960& region); 1961 1962// Next 1963srcOffset += rowSizeInBytes * numRows * mipSize. depth ; 1964} 1965} 1966} 1967auto defaultLayout = VulkanUtil :: getImageLayoutFromState (desc. defaultState ); 1968_transitionImageLayout ( 1969texture -> m_image , 1970format, 1971* texture -> getDesc (), 1972VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL , 1973defaultLayout); 1974} 1975else 1976{ 1977auto defaultLayout = VulkanUtil :: getImageLayoutFromState (desc. defaultState ); 1978if (defaultLayout != VK_IMAGE_LAYOUT_UNDEFINED ) 1979{ 1980_transitionImageLayout ( 1981texture -> m_image , 1982format, 1983* texture -> getDesc (), 1984VK_IMAGE_LAYOUT_UNDEFINED , 1985defaultLayout); 1986} 1987} 1988m_deviceQueue. flushAndWait (); 1989returnComPtr (outResource, texture); 1990return SLANG_OK ; 1991} 1992 1993Result DeviceImpl :: createBufferResource ( 1994const IBufferResource :: Desc & descIn, 1995const void * initData, 1996IBufferResource ** outResource) 1997{ 1998return createBufferResourceImpl (descIn, 0 , initData, outResource); 1999} 2000 2001Result DeviceImpl :: createBufferResourceImpl ( 2002const IBufferResource :: Desc & descIn, 2003VkBufferUsageFlags additionalUsageFlag, 2004const void * initData, 2005IBufferResource ** outResource) 2006{ 2007BufferResource :: Desc desc = fixupBufferDesc (descIn); 2008 2009const Size bufferSize = desc. sizeInBytes ; 2010 2011VkMemoryPropertyFlags reqMemoryProperties = 0 ; 2012 2013VkBufferUsageFlags usage = _calcBufferUsageFlags (desc. allowedStates ) | additionalUsageFlag; 2014if (m_api. m_extendedFeatures . vulkan12Features . bufferDeviceAddress ) 2015{ 2016usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT ; 2017} 2018if (desc. allowedStates . contains ( ResourceState ::ShaderResource) && 2019m_api. m_extendedFeatures . accelerationStructureFeatures . accelerationStructure ) 2020{ 2021usage |= VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR ; 2022} 2023if (initData) 2024{ 2025usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT ; 2026} 2027 2028if (desc. allowedStates . contains ( ResourceState ::ConstantBuffer) || 2029desc. memoryType == MemoryType ::Upload || desc. memoryType == MemoryType ::ReadBack) 2030{ 2031reqMemoryProperties = 2032VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ; 2033} 2034else 2035{ 2036reqMemoryProperties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ; 2037} 2038 2039RefPtr < BufferResourceImpl > buffer( new BufferResourceImpl (desc, this)); 2040if (desc. isShared ) 2041{ 2042VkExternalMemoryHandleTypeFlagsKHR extMemHandleType 2043#if SLANG_WINDOWS_FAMILY 2044= VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT ; 2045#else 2046= VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ; 2047#endif 2048SLANG_RETURN_ON_FAIL (buffer -> m_buffer . init ( 2049m_api, 2050desc. sizeInBytes , 2051usage, 2052reqMemoryProperties, 2053desc. isShared , 2054extMemHandleType)); 2055} 2056else 2057{ 2058SLANG_RETURN_ON_FAIL ( 2059buffer -> m_buffer . init (m_api, desc. sizeInBytes , usage, reqMemoryProperties)); 2060} 2061 2062if (initData) 2063{ 2064if (desc. memoryType == MemoryType ::DeviceLocal) 2065{ 2066SLANG_RETURN_ON_FAIL (buffer -> m_uploadBuffer . init ( 2067m_api, 2068bufferSize, 2069VK_BUFFER_USAGE_TRANSFER_SRC_BIT , 2070VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT )); 2071// Copy into staging buffer 2072void * mappedData = nullptr ; 2073SLANG_VK_CHECK (m_api. vkMapMemory ( 2074m_device, 2075buffer -> m_uploadBuffer . m_memory , 20760 , 2077bufferSize, 20780 , 2079& mappedData)); 2080:: memcpy (mappedData, initData, bufferSize); 2081m_api. vkUnmapMemory (m_device, buffer -> m_uploadBuffer . m_memory ); 2082 2083// Copy from staging buffer to real buffer 2084VkCommandBuffer commandBuffer = m_deviceQueue. getCommandBuffer (); 2085 2086VkBufferCopy copyInfo = {}; 2087copyInfo. size = bufferSize; 2088m_api. vkCmdCopyBuffer ( 2089commandBuffer, 2090buffer -> m_uploadBuffer . m_buffer , 2091buffer -> m_buffer . m_buffer , 20921 , 2093& copyInfo); 2094m_deviceQueue. flush (); 2095} 2096else 2097{ 2098// Copy into mapped buffer directly 2099void * mappedData = nullptr ; 2100SLANG_VK_CHECK (m_api. vkMapMemory ( 2101m_device, 2102buffer -> m_buffer . m_memory , 21030 , 2104bufferSize, 21050 , 2106& mappedData)); 2107:: memcpy (mappedData, initData, bufferSize); 2108m_api. vkUnmapMemory (m_device, buffer -> m_buffer . m_memory ); 2109} 2110} 2111 2112returnComPtr (outResource, buffer); 2113return SLANG_OK ; 2114} 2115 2116Result DeviceImpl :: createBufferFromNativeHandle ( 2117InteropHandle handle, 2118const IBufferResource :: Desc & srcDesc, 2119IBufferResource ** outResource) 2120{ 2121RefPtr < BufferResourceImpl > buffer( new BufferResourceImpl (srcDesc, this)); 2122 2123if (handle. api == InteropHandleAPI ::Vulkan) 2124{ 2125buffer -> m_buffer . m_buffer = ( VkBuffer )handle. handleValue ; 2126} 2127else 2128{ 2129return SLANG_FAIL ; 2130} 2131 2132returnComPtr (outResource, buffer); 2133return SLANG_OK ; 2134} 2135 2136Result DeviceImpl :: createSamplerState ( ISamplerState :: Desc const & desc, ISamplerState ** outSampler) 2137{ 2138VkSamplerCreateInfo samplerInfo = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; 2139 2140samplerInfo. magFilter = VulkanUtil :: translateFilterMode (desc. magFilter ); 2141samplerInfo. minFilter = VulkanUtil :: translateFilterMode (desc. minFilter ); 2142 2143samplerInfo. addressModeU = VulkanUtil :: translateAddressingMode (desc. addressU ); 2144samplerInfo. addressModeV = VulkanUtil :: translateAddressingMode (desc. addressV ); 2145samplerInfo. addressModeW = VulkanUtil :: translateAddressingMode (desc. addressW ); 2146 2147samplerInfo. anisotropyEnable = desc. maxAnisotropy > 1 ; 2148samplerInfo. maxAnisotropy = ( float )desc. maxAnisotropy ; 2149 2150// TODO: support translation of border color... 2151samplerInfo. borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK ; 2152 2153samplerInfo. unnormalizedCoordinates = VK_FALSE ; 2154samplerInfo. compareEnable = desc. reductionOp == TextureReductionOp ::Comparison; 2155samplerInfo. compareOp = VulkanUtil :: translateComparisonFunc (desc. comparisonFunc ); 2156samplerInfo. mipmapMode = VulkanUtil :: translateMipFilterMode (desc. mipFilter ); 2157samplerInfo. minLod = Math :: Max ( 0.0f , desc. minLOD ); 2158samplerInfo. maxLod = Math :: Clamp (desc. maxLOD , samplerInfo. minLod , VK_LOD_CLAMP_NONE ); 2159 2160VkSamplerReductionModeCreateInfo reductionInfo = { 2161VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO }; 2162reductionInfo. reductionMode = VulkanUtil :: translateReductionOp (desc. reductionOp ); 2163samplerInfo. pNext = & reductionInfo; 2164 2165VkSampler sampler; 2166SLANG_VK_RETURN_ON_FAIL (m_api. vkCreateSampler (m_device, & samplerInfo, nullptr , & sampler)); 2167 2168RefPtr < SamplerStateImpl > samplerImpl = new SamplerStateImpl (this); 2169samplerImpl -> m_sampler = sampler; 2170returnComPtr (outSampler, samplerImpl); 2171return SLANG_OK ; 2172} 2173 2174Result DeviceImpl :: createTextureView ( 2175ITextureResource * texture, 2176IResourceView :: Desc const & desc, 2177IResourceView ** outView) 2178{ 2179auto resourceImpl = static_cast < TextureResourceImpl *> (texture); 2180RefPtr < TextureResourceViewImpl > view = new TextureResourceViewImpl (this); 2181view -> m_texture = resourceImpl; 2182view -> m_desc = desc; 2183if (!texture) 2184{ 2185view -> m_view = VK_NULL_HANDLE ; 2186returnComPtr (outView, view); 2187return SLANG_OK ; 2188} 2189 2190bool isArray = resourceImpl -> getDesc () -> arraySize > 1 ; 2191VkImageViewCreateInfo createInfo = {}; 2192createInfo. sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO ; 2193createInfo. flags = 0 ; 2194createInfo. format = gfxIsTypelessFormat (texture -> getDesc () -> format ) 2195? VulkanUtil :: getVkFormat (desc. format ) 2196: resourceImpl -> m_vkformat ; 2197createInfo. image = resourceImpl -> m_image ; 2198createInfo. components = VkComponentMapping { 2199VK_COMPONENT_SWIZZLE_R , 2200VK_COMPONENT_SWIZZLE_G , 2201VK_COMPONENT_SWIZZLE_B , 2202VK_COMPONENT_SWIZZLE_A }; 2203switch (resourceImpl -> getType ()) 2204{ 2205case IResource :: Type ::Texture1D: 2206createInfo. viewType = isArray ? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_1D ; 2207break ; 2208case IResource :: Type ::Texture2D: 2209createInfo. viewType = isArray ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D ; 2210break ; 2211case IResource :: Type ::Texture3D: 2212createInfo. viewType = VK_IMAGE_VIEW_TYPE_3D ; 2213break ; 2214case IResource :: Type ::TextureCube: 2215createInfo. viewType = isArray ? VK_IMAGE_VIEW_TYPE_CUBE_ARRAY : VK_IMAGE_VIEW_TYPE_CUBE ; 2216break ; 2217default : 2218SLANG_UNIMPLEMENTED_X ( "Unknown Texture type." ); 2219break ; 2220} 2221 2222createInfo. subresourceRange . aspectMask = getAspectMaskFromFormat (resourceImpl -> m_vkformat ); 2223 2224createInfo. subresourceRange . baseArrayLayer = desc. subresourceRange . baseArrayLayer ; 2225createInfo. subresourceRange . baseMipLevel = desc. subresourceRange . mipLevel ; 2226createInfo. subresourceRange . layerCount = desc. subresourceRange . layerCount ; 2227if (createInfo. subresourceRange . layerCount == 0 ) 2228{ 2229createInfo. subresourceRange . layerCount = isArray ? VK_REMAINING_ARRAY_LAYERS : 1 ; 2230if (createInfo. viewType == VK_IMAGE_VIEW_TYPE_CUBE ) 2231{ 2232createInfo. subresourceRange . layerCount = 6 ; 2233} 2234} 2235createInfo. subresourceRange . levelCount = desc. subresourceRange . mipLevelCount == 0 2236? VK_REMAINING_MIP_LEVELS 2237: desc. subresourceRange . mipLevelCount ; 2238switch (desc. type ) 2239{ 2240case IResourceView :: Type ::DepthStencil: 2241view -> m_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ; 2242createInfo. subresourceRange . levelCount = 1 ; 2243break ; 2244case IResourceView :: Type ::RenderTarget: 2245view -> m_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ; 2246createInfo. subresourceRange . levelCount = 1 ; 2247break ; 2248case IResourceView :: Type ::ShaderResource: 2249view -> m_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ; 2250break ; 2251case IResourceView :: Type ::UnorderedAccess: 2252view -> m_layout = VK_IMAGE_LAYOUT_GENERAL ; 2253break ; 2254default : 2255SLANG_UNIMPLEMENTED_X ( "Unknown TextureViewDesc type." ); 2256break ; 2257} 2258m_api. vkCreateImageView (m_device, & createInfo, nullptr , & view -> m_view ); 2259returnComPtr (outView, view); 2260return SLANG_OK ; 2261} 2262 2263Result DeviceImpl :: getFormatSupportedResourceStates ( Format format, ResourceStateSet * outStates) 2264{ 2265// TODO: Add variables to VkDevice to track supported surface presentable formats 2266 2267VkFormat vkFormat = VulkanUtil :: getVkFormat (format); 2268 2269VkFormatProperties supportedProperties = {}; 2270m_api. vkGetPhysicalDeviceFormatProperties ( 2271m_api. m_physicalDevice , 2272vkFormat, 2273& supportedProperties); 2274 2275HashSet < VkFormat > presentableFormats; 2276// TODO: enable this once we have VK_GOOGLE_surfaceless_query. 2277#if 0 2278List < VkSurfaceFormatKHR > surfaceFormats; 2279 2280uint32_t surfaceFormatCount = 0 ; 2281m_api. vkGetPhysicalDeviceSurfaceFormatsKHR ( 2282m_api. m_physicalDevice , VK_NULL_HANDLE , & surfaceFormatCount, nullptr ); 2283 2284surfaceFormats. setCount (surfaceFormatCount); 2285m_api. vkGetPhysicalDeviceSurfaceFormatsKHR (m_api. m_physicalDevice , VK_NULL_HANDLE , & surfaceFormatCount, surfaceFormats. getBuffer ()); 2286for ( auto surfaceFormat : surfaceFormats) 2287{ 2288presentableFormats. add (surfaceFormat. format ); 2289} 2290#else 2291// Until we have a solution to query presentable formats without needing a surface, 2292// hard code presentable formats that is supported by most drivers. 2293presentableFormats. add ( VK_FORMAT_R8G8B8A8_UNORM ); 2294presentableFormats. add ( VK_FORMAT_B8G8R8A8_UNORM ); 2295presentableFormats. add ( VK_FORMAT_R8G8B8A8_SRGB ); 2296presentableFormats. add ( VK_FORMAT_B8G8R8A8_SRGB ); 2297#endif 2298 2299ResourceStateSet allowedStates; 2300// TODO: Currently only supports VK_IMAGE_TILING_OPTIMAL 2301auto imageFeatures = supportedProperties. optimalTilingFeatures ; 2302auto bufferFeatures = supportedProperties. bufferFeatures ; 2303// PreInitialized - Only supported for VK_IMAGE_TILING_LINEAR 2304// VertexBuffer 2305if (bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT ) 2306allowedStates. add ( ResourceState ::VertexBuffer); 2307// IndexBuffer - Without extensions, Vulkan only supports two formats for index buffers. 2308switch (format) 2309{ 2310case Format :: R32_UINT : 2311case Format :: R16_UINT : 2312allowedStates. add ( ResourceState ::IndexBuffer); 2313break ; 2314default : 2315break ; 2316} 2317// ConstantBuffer 2318allowedStates. add ( ResourceState ::ConstantBuffer); 2319// StreamOutput - TODO: Requires VK_EXT_transform_feedback 2320// ShaderResource 2321if (imageFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT ) 2322allowedStates. add ( ResourceState ::ShaderResource); 2323if (bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT ) 2324allowedStates. add ( ResourceState ::ShaderResource); 2325// UnorderedAccess 2326if (imageFeatures & 2327( VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT )) 2328allowedStates. add ( ResourceState ::UnorderedAccess); 2329if (bufferFeatures & ( VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | 2330VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT )) 2331allowedStates. add ( ResourceState ::UnorderedAccess); 2332// RenderTarget 2333if (imageFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ) 2334allowedStates. add ( ResourceState ::RenderTarget); 2335// DepthRead, DepthWrite 2336if (imageFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT ) 2337{ 2338allowedStates. add ( ResourceState ::DepthRead); 2339allowedStates. add ( ResourceState ::DepthWrite); 2340} 2341// Present 2342if (presentableFormats. contains (vkFormat)) 2343allowedStates. add ( ResourceState ::Present); 2344// IndirectArgument 2345allowedStates. add ( ResourceState ::IndirectArgument); 2346// CopySource, ResolveSource 2347if (imageFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT ) 2348{ 2349allowedStates. add ( ResourceState ::CopySource); 2350allowedStates. add ( ResourceState ::ResolveSource); 2351} 2352// CopyDestination, ResolveDestination 2353if (imageFeatures & VK_FORMAT_FEATURE_TRANSFER_DST_BIT ) 2354{ 2355allowedStates. add ( ResourceState ::CopyDestination); 2356allowedStates. add ( ResourceState ::ResolveDestination); 2357} 2358// AccelerationStructure 2359if (bufferFeatures & VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR ) 2360{ 2361allowedStates. add ( ResourceState ::AccelerationStructure); 2362allowedStates. add ( ResourceState ::AccelerationStructureBuildInput); 2363} 2364 2365* outStates = allowedStates; 2366return SLANG_OK ; 2367} 2368 2369Result DeviceImpl :: createBufferView ( 2370IBufferResource * buffer, 2371IBufferResource * counterBuffer, 2372IResourceView :: Desc const & desc, 2373IResourceView ** outView) 2374{ 2375auto resourceImpl = ( BufferResourceImpl * )buffer; 2376 2377VkDeviceSize offset = ( VkDeviceSize )desc. bufferRange . offset ; 2378VkDeviceSize size = desc. bufferRange . size == 0 2379? (buffer ? resourceImpl -> getDesc () -> sizeInBytes : 0 ) 2380: ( VkDeviceSize )desc. bufferRange . size ; 2381 2382// There are two different cases we need to think about for buffers. 2383// 2384// One is when we have a "uniform texel buffer" or "storage texel buffer," 2385// in which case we need to construct a `VkBufferView` to represent the 2386// formatting that is applied to the buffer. This case would correspond 2387// to a `textureBuffer` or `imageBuffer` in GLSL, and more or less to 2388// `Buffer<..>` or `RWBuffer<...>` in HLSL. 2389// 2390// The other case is a `storage buffer` which is the catch-all for any 2391// non-formatted R/W access to a buffer. In GLSL this is a `buffer { ... }` 2392// declaration, while in HLSL it covers a bunch of different `RW*Buffer` 2393// cases. In these cases we do *not* need a `VkBufferView`, but in 2394// order to be compatible with other APIs that require views for any 2395// potentially writable access, we will have to create one anyway. 2396// 2397// We will distinguish the two cases by looking at whether the view 2398// is being requested with a format or not. 2399// 2400 2401switch (desc. type ) 2402{ 2403default : 2404assert (! "unhandled" ); 2405return SLANG_FAIL ; 2406 2407case IResourceView :: Type ::UnorderedAccess: 2408case IResourceView :: Type ::ShaderResource: 2409// Is this a formatted view? 2410// 2411if (desc. format == Format ::Unknown) 2412{ 2413// Buffer usage that doesn't involve formatting doesn't 2414// require a view in Vulkan. 2415RefPtr < PlainBufferResourceViewImpl > viewImpl = new PlainBufferResourceViewImpl (this); 2416viewImpl -> m_buffer = resourceImpl; 2417viewImpl -> offset = offset; 2418viewImpl -> size = size; 2419viewImpl -> m_desc = desc; 2420 2421returnComPtr (outView, viewImpl); 2422return SLANG_OK ; 2423} 2424// 2425// If the view is formatted, then we need to handle 2426// it just like we would for a "sampled" buffer: 2427// 2428// FALLTHROUGH 2429{ 2430VkBufferViewCreateInfo info = { VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO }; 2431 2432VkBufferView view = VK_NULL_HANDLE ; 2433 2434if (buffer) 2435{ 2436info. format = VulkanUtil :: getVkFormat (desc. format ); 2437info. buffer = resourceImpl -> m_buffer . m_buffer ; 2438info. offset = offset; 2439info. range = size; 2440VkBufferUsageFlags2CreateInfoKHR bufferViewUsage{}; 2441bufferViewUsage. sType = VK_STRUCTURE_TYPE_BUFFER_USAGE_FLAGS_2_CREATE_INFO_KHR ; 2442 2443if (desc. type == IResourceView :: Type ::UnorderedAccess) 2444{ 2445info. pNext = & bufferViewUsage; 2446bufferViewUsage. usage = VK_BUFFER_USAGE_2_STORAGE_TEXEL_BUFFER_BIT_KHR ; 2447} 2448else if (desc. type == IResourceView :: Type ::ShaderResource) 2449{ 2450info. pNext = & bufferViewUsage; 2451bufferViewUsage. usage = VK_BUFFER_USAGE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR ; 2452} 2453else 2454{ 2455assert (! "unhandled" ); 2456} 2457 2458SLANG_VK_RETURN_ON_FAIL (m_api. vkCreateBufferView (m_device, & info, nullptr , & view)); 2459} 2460 2461RefPtr < TexelBufferResourceViewImpl > viewImpl = new TexelBufferResourceViewImpl (this); 2462viewImpl -> m_buffer = resourceImpl; 2463viewImpl -> m_view = view; 2464viewImpl -> m_desc = desc; 2465 2466returnComPtr (outView, viewImpl); 2467return SLANG_OK ; 2468} 2469break ; 2470} 2471} 2472 2473Result DeviceImpl :: createInputLayout ( IInputLayout :: Desc const & desc, IInputLayout ** outLayout) 2474{ 2475RefPtr < InputLayoutImpl > layout( new InputLayoutImpl ); 2476 2477List < VkVertexInputAttributeDescription >& dstAttributes = layout -> m_attributeDescs ; 2478List < VkVertexInputBindingDescription >& dstStreams = layout -> m_streamDescs ; 2479 2480auto elements = desc. inputElements ; 2481Int numElements = desc. inputElementCount ; 2482 2483auto srcVertexStreams = desc. vertexStreams ; 2484Int vertexStreamCount = desc. vertexStreamCount ; 2485 2486dstAttributes. setCount (numElements); 2487dstStreams. setCount (vertexStreamCount); 2488 2489for ( Int i = 0 ; i < vertexStreamCount; i ++ ) 2490{ 2491auto & dstStream = dstStreams[i]; 2492auto & srcStream = srcVertexStreams[i]; 2493dstStream. stride = ( uint32_t )srcStream. stride ; 2494dstStream. binding = ( uint32_t )i; 2495dstStream. inputRate = (srcStream. slotClass == InputSlotClass ::PerInstance) 2496? VK_VERTEX_INPUT_RATE_INSTANCE 2497: VK_VERTEX_INPUT_RATE_VERTEX ; 2498} 2499 2500for ( Int i = 0 ; i < numElements; ++ i) 2501{ 2502const InputElementDesc & srcDesc = elements[i]; 2503auto streamIndex = srcDesc. bufferSlotIndex ; 2504 2505VkVertexInputAttributeDescription & dstDesc = dstAttributes[i]; 2506 2507dstDesc. location = uint32_t (i); 2508dstDesc. binding = ( uint32_t )streamIndex; 2509dstDesc. format = VulkanUtil :: getVkFormat (srcDesc. format ); 2510if (dstDesc. format == VK_FORMAT_UNDEFINED ) 2511{ 2512return SLANG_FAIL ; 2513} 2514 2515dstDesc. offset = uint32_t (srcDesc. offset ); 2516} 2517 2518// Work out the overall size 2519returnComPtr (outLayout, layout); 2520return SLANG_OK ; 2521} 2522 2523Result DeviceImpl :: createProgram ( 2524const IShaderProgram :: Desc & desc, 2525IShaderProgram ** outProgram, 2526ISlangBlob ** outDiagnosticBlob) 2527{ 2528RefPtr < ShaderProgramImpl > shaderProgram = new ShaderProgramImpl (this); 2529shaderProgram -> init (desc); 2530 2531m_deviceObjectsWithPotentialBackReferences. add (shaderProgram); 2532 2533RootShaderObjectLayout :: create ( 2534this, 2535shaderProgram -> linkedProgram , 2536shaderProgram -> linkedProgram -> getLayout (), 2537shaderProgram -> m_rootObjectLayout . writeRef ()); 2538 2539if (!shaderProgram -> isSpecializable ()) 2540{ 2541SLANG_RETURN_ON_FAIL (shaderProgram -> compileShaders (this)); 2542} 2543 2544returnComPtr (outProgram, shaderProgram); 2545return SLANG_OK ; 2546} 2547 2548Result DeviceImpl :: createShaderObjectLayout ( 2549slang:: ISession * session, 2550slang:: TypeLayoutReflection * typeLayout, 2551ShaderObjectLayoutBase ** outLayout) 2552{ 2553RefPtr < ShaderObjectLayoutImpl > layout; 2554SLANG_RETURN_ON_FAIL ( 2555ShaderObjectLayoutImpl :: createForElementType (this, session, typeLayout, layout. writeRef ())); 2556returnRefPtrMove (outLayout, layout); 2557return SLANG_OK ; 2558} 2559 2560Result DeviceImpl :: createShaderObject ( ShaderObjectLayoutBase * layout, IShaderObject ** outObject) 2561{ 2562RefPtr < ShaderObjectImpl > shaderObject; 2563SLANG_RETURN_ON_FAIL ( ShaderObjectImpl :: create ( 2564this, 2565static_cast < ShaderObjectLayoutImpl *> (layout), 2566shaderObject. writeRef ())); 2567returnComPtr (outObject, shaderObject); 2568return SLANG_OK ; 2569} 2570 2571Result DeviceImpl :: createMutableShaderObject ( 2572ShaderObjectLayoutBase * layout, 2573IShaderObject ** outObject) 2574{ 2575auto layoutImpl = static_cast < ShaderObjectLayoutImpl *> (layout); 2576 2577RefPtr < ShaderObjectImpl > result; 2578SLANG_RETURN_ON_FAIL ( ShaderObjectImpl :: create (this, layoutImpl, result. writeRef ())); 2579returnComPtr (outObject, result); 2580 2581return SLANG_OK ; 2582} 2583 2584Result DeviceImpl :: createMutableRootShaderObject ( IShaderProgram * program, IShaderObject ** outObject) 2585{ 2586RefPtr < MutableRootShaderObjectImpl > result = new MutableRootShaderObjectImpl (); 2587auto programImpl = static_cast < ShaderProgramImpl *> (program); 2588SLANG_RETURN_ON_FAIL (result -> init (this, programImpl -> m_rootObjectLayout )); 2589returnComPtr (outObject, result); 2590return SLANG_OK ; 2591} 2592 2593Result DeviceImpl :: createShaderTable ( const IShaderTable :: Desc & desc, IShaderTable ** outShaderTable) 2594{ 2595RefPtr < ShaderTableImpl > result = new ShaderTableImpl (); 2596result -> m_device = this; 2597result -> init (desc); 2598returnComPtr (outShaderTable, result); 2599return SLANG_OK ; 2600} 2601 2602Result DeviceImpl :: createGraphicsPipelineState ( 2603const GraphicsPipelineStateDesc & inDesc, 2604IPipelineState ** outState) 2605{ 2606GraphicsPipelineStateDesc desc = inDesc; 2607RefPtr < PipelineStateImpl > pipelineStateImpl = new PipelineStateImpl (this); 2608pipelineStateImpl -> init (desc); 2609pipelineStateImpl -> establishStrongDeviceReference (); 2610m_deviceObjectsWithPotentialBackReferences. add (pipelineStateImpl); 2611returnComPtr (outState, pipelineStateImpl); 2612 2613return SLANG_OK ; 2614} 2615 2616Result DeviceImpl :: createComputePipelineState ( 2617const ComputePipelineStateDesc & inDesc, 2618IPipelineState ** outState) 2619{ 2620ComputePipelineStateDesc desc = inDesc; 2621RefPtr < PipelineStateImpl > pipelineStateImpl = new PipelineStateImpl (this); 2622pipelineStateImpl -> init (desc); 2623m_deviceObjectsWithPotentialBackReferences. add (pipelineStateImpl); 2624pipelineStateImpl -> establishStrongDeviceReference (); 2625returnComPtr (outState, pipelineStateImpl); 2626return SLANG_OK ; 2627} 2628 2629Result DeviceImpl :: createRayTracingPipelineState ( 2630const RayTracingPipelineStateDesc & desc, 2631IPipelineState ** outState) 2632{ 2633RefPtr < RayTracingPipelineStateImpl > pipelineStateImpl = new RayTracingPipelineStateImpl (this); 2634pipelineStateImpl -> init (desc); 2635m_deviceObjectsWithPotentialBackReferences. add (pipelineStateImpl); 2636pipelineStateImpl -> establishStrongDeviceReference (); 2637returnComPtr (outState, pipelineStateImpl); 2638return SLANG_OK ; 2639} 2640 2641Result DeviceImpl :: createQueryPool ( const IQueryPool :: Desc & desc, IQueryPool ** outPool) 2642{ 2643RefPtr < QueryPoolImpl > result = new QueryPoolImpl (); 2644SLANG_RETURN_ON_FAIL (result -> init (desc, this)); 2645returnComPtr (outPool, result); 2646return SLANG_OK ; 2647} 2648 2649Result DeviceImpl :: createFence ( const IFence :: Desc & desc, IFence ** outFence) 2650{ 2651RefPtr < FenceImpl > fence = new FenceImpl (this); 2652SLANG_RETURN_ON_FAIL (fence -> init (desc)); 2653returnComPtr (outFence, fence); 2654return SLANG_OK ; 2655} 2656 2657Result DeviceImpl :: waitForFences ( 2658GfxCount fenceCount, 2659IFence ** fences, 2660uint64_t * fenceValues, 2661bool waitForAll, 2662uint64_t timeout) 2663{ 2664ShortList < VkSemaphore > semaphores; 2665for ( GfxIndex i = 0 ; i < fenceCount; ++ i) 2666{ 2667auto fenceImpl = static_cast < FenceImpl *> (fences[i]); 2668semaphores. add (fenceImpl -> m_semaphore ); 2669} 2670VkSemaphoreWaitInfo waitInfo; 2671waitInfo. sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO ; 2672waitInfo. pNext = NULL ; 2673waitInfo. flags = 0 ; 2674waitInfo. semaphoreCount = 1 ; 2675waitInfo. pSemaphores = semaphores. getArrayView (). getBuffer (); 2676waitInfo. pValues = fenceValues; 2677auto result = m_api. vkWaitSemaphores (m_api. m_device , & waitInfo, timeout); 2678if (result == VK_TIMEOUT ) 2679return SLANG_E_TIME_OUT ; 2680return result == VK_SUCCESS ? SLANG_OK : SLANG_FAIL ; 2681} 2682 2683} // namespace vk 2684} // namespace gfx