yum-mirror/VkFFT
git clone https://git.yummers.dev/yum-mirror/VkFFT
5f7df3f
develop
1//general parts 2#include <stdio.h> 3#include <vector> 4#include <memory> 5#include <string.h> 6#include <chrono> 7#include <thread> 8#include <iostream> 9#ifndef __STDC_FORMAT_MACROS 10#define __STDC_FORMAT_MACROS 11#endif 12#include <inttypes.h> 13 14#if (VKFFT_BACKEND == 0 ) 15#include "vulkan/vulkan.h" 16#include "glslang/Include/glslang_c_interface.h" 17#elif (VKFFT_BACKEND == 1 ) 18#include <cuda.h> 19#include <cuda_runtime.h> 20#include <nvrtc.h> 21#include <cuda_runtime_api.h> 22#include <cuComplex.h> 23#elif (VKFFT_BACKEND == 2 ) 24#ifndef __HIP_PLATFORM_HCC__ 25#define __HIP_PLATFORM_HCC__ 26#endif 27#include <hip/hip_runtime.h> 28#include <hip/hiprtc.h> 29#include <hip/hip_runtime_api.h> 30#include <hip/hip_complex.h> 31#elif (VKFFT_BACKEND == 3 ) 32#ifndef CL_USE_DEPRECATED_OPENCL_1_2_APIS 33#define CL_USE_DEPRECATED_OPENCL_1_2_APIS 34#endif 35#ifdef __APPLE__ 36#include <OpenCL/opencl.h> 37#else 38#include <CL/cl.h> 39#endif 40#elif (VKFFT_BACKEND == 4 ) 41#include <ze_api.h> 42#elif (VKFFT_BACKEND == 5 ) 43#include "Foundation/Foundation.hpp" 44#include "QuartzCore/QuartzCore.hpp" 45#include "Metal/Metal.hpp" 46#endif 47#include "vkFFT.h" 48#include "utils_VkFFT.h" 49#if (VKFFT_BACKEND == 0 ) 50 51VkResult CreateDebugUtilsMessengerEXT (VkGPU * vkGPU ,const VkDebugUtilsMessengerCreateInfoEXT * pCreateInfo ,const VkAllocationCallbacks * pAllocator ,VkDebugUtilsMessengerEXT * pDebugMessenger ) { 52//pointer to the function, as it is not part of the core. Function creates debugging messenger 53PFN_vkCreateDebugUtilsMessengerEXT func = (PFN_vkCreateDebugUtilsMessengerEXT )vkGetInstanceProcAddr (vkGPU -> instance ,"vkCreateDebugUtilsMessengerEXT" ); 54if (func != NULL ) { 55return func (vkGPU -> instance ,pCreateInfo ,pAllocator ,pDebugMessenger ); 56 } 57else { 58return VK_ERROR_EXTENSION_NOT_PRESENT ; 59 } 60} 61void DestroyDebugUtilsMessengerEXT (VkGPU * vkGPU ,const VkAllocationCallbacks * pAllocator ) { 62//pointer to the function, as it is not part of the core. Function destroys debugging messenger 63PFN_vkDestroyDebugUtilsMessengerEXT func = (PFN_vkDestroyDebugUtilsMessengerEXT )vkGetInstanceProcAddr (vkGPU -> instance ,"vkDestroyDebugUtilsMessengerEXT" ); 64if (func != NULL ) { 65func (vkGPU -> instance ,vkGPU -> debugMessenger ,pAllocator ); 66 } 67} 68static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity ,VkDebugUtilsMessageTypeFlagsEXT messageType ,const VkDebugUtilsMessengerCallbackDataEXT * pCallbackData ,void * pUserData ) { 69printf ("validation layer: %s\n" ,pCallbackData -> pMessage ); 70return VK_FALSE ; 71} 72 73 74VkResult setupDebugMessenger (VkGPU * vkGPU ) { 75//function that sets up the debugging messenger 76if (vkGPU -> enableValidationLayers == 0 )return VK_SUCCESS ; 77 78VkDebugUtilsMessengerCreateInfoEXT createInfo = {VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT }; 79createInfo .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT ; 80createInfo .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT ; 81createInfo .pfnUserCallback = debugCallback ; 82 83if (CreateDebugUtilsMessengerEXT (vkGPU ,& createInfo ,NULL ,& vkGPU -> debugMessenger )!= VK_SUCCESS ) { 84return VK_ERROR_INITIALIZATION_FAILED ; 85 } 86return VK_SUCCESS ; 87} 88VkResult checkValidationLayerSupport () { 89//check if validation layers are supported when an instance is created 90uint32_t layerCount ; 91vkEnumerateInstanceLayerProperties (& layerCount ,NULL ); 92 93VkLayerProperties * availableLayers = (VkLayerProperties * )malloc (sizeof (VkLayerProperties )* layerCount ); 94if (!availableLayers )return VK_INCOMPLETE ; 95vkEnumerateInstanceLayerProperties (& layerCount ,availableLayers ); 96if (availableLayers ) { 97for (uint64_t i = 0 ;i < layerCount ;i ++ ) { 98if (strcmp ("VK_LAYER_KHRONOS_validation" ,availableLayers [i ].layerName )== 0 ) { 99free (availableLayers ); 100return VK_SUCCESS ; 101 } 102 } 103free (availableLayers ); 104 } 105else { 106return VK_INCOMPLETE ; 107 } 108return VK_ERROR_LAYER_NOT_PRESENT ; 109} 110 111std::vector < const char *> getRequiredExtensions (VkGPU * vkGPU ,uint64_t sample_id ) { 112 std::vector < const char *> extensions ; 113 114if (vkGPU -> enableValidationLayers ) { 115extensions .push_back (VK_EXT_DEBUG_UTILS_EXTENSION_NAME ); 116 } 117#if (VK_API_VERSION > 10 ) 118extensions .push_back ("VK_KHR_get_physical_device_properties2" ); 119#endif 120 121return extensions ; 122} 123 124VkResult createInstance (VkGPU * vkGPU ,uint64_t sample_id ) { 125//create instance - a connection between the application and the Vulkan library 126VkResult res = VK_SUCCESS ; 127//check if validation layers are supported 128if (vkGPU -> enableValidationLayers == 1 ) { 129res = checkValidationLayerSupport (); 130if (res != VK_SUCCESS )return res ; 131 } 132 133VkApplicationInfo applicationInfo = {VK_STRUCTURE_TYPE_APPLICATION_INFO }; 134applicationInfo .pApplicationName = "VkFFT" ; 135applicationInfo .applicationVersion = (uint32_t )VkFFTGetVersion (); 136applicationInfo .pEngineName = "VkFFT" ; 137applicationInfo .engineVersion = 1 ; 138#if (VK_API_VERSION >=12 ) 139applicationInfo .apiVersion = VK_API_VERSION_1_2 ; 140#elif (VK_API_VERSION == 11 ) 141applicationInfo .apiVersion = VK_API_VERSION_1_1 ; 142#else 143applicationInfo .apiVersion = VK_API_VERSION_1_0 ; 144#endif 145 146VkInstanceCreateInfo createInfo = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO }; 147createInfo .flags = 0 ; 148createInfo .pApplicationInfo = & applicationInfo ; 149 150auto extensions = getRequiredExtensions (vkGPU ,sample_id ); 151createInfo .enabledExtensionCount = (uint32_t )(extensions .size ()); 152createInfo .ppEnabledExtensionNames = extensions .data (); 153 154VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo = {VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT }; 155if (vkGPU -> enableValidationLayers ) { 156//query for the validation layer support in the instance 157createInfo .enabledLayerCount = 1 ; 158const char * validationLayers = "VK_LAYER_KHRONOS_validation" ; 159createInfo .ppEnabledLayerNames = & validationLayers ; 160debugCreateInfo .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT ; 161debugCreateInfo .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT ; 162debugCreateInfo .pfnUserCallback = debugCallback ; 163createInfo .pNext = (VkDebugUtilsMessengerCreateInfoEXT * )& debugCreateInfo ; 164 } 165else { 166createInfo .enabledLayerCount = 0 ; 167 168createInfo .pNext = nullptr ; 169 } 170 171res = vkCreateInstance (& createInfo ,NULL ,& vkGPU -> instance ); 172if (res != VK_SUCCESS )return res ; 173 174return res ; 175} 176 177VkResult findPhysicalDevice (VkGPU * vkGPU ) { 178//check if there are GPUs that support Vulkan and select one 179VkResult res = VK_SUCCESS ; 180uint32_t deviceCount ; 181res = vkEnumeratePhysicalDevices (vkGPU -> instance ,& deviceCount ,NULL ); 182if (res != VK_SUCCESS )return res ; 183if (deviceCount == 0 ) { 184return VK_ERROR_DEVICE_LOST ; 185 } 186 187VkPhysicalDevice * devices = (VkPhysicalDevice * )malloc (sizeof (VkPhysicalDevice )* deviceCount ); 188if (!devices )return VK_INCOMPLETE ; 189res = vkEnumeratePhysicalDevices (vkGPU -> instance ,& deviceCount ,devices ); 190if (res != VK_SUCCESS )return res ; 191if (devices ) { 192vkGPU -> physicalDevice = devices [vkGPU -> device_id ]; 193free (devices ); 194return VK_SUCCESS ; 195 } 196else 197return VK_INCOMPLETE ; 198} 199VkResult getComputeQueueFamilyIndex (VkGPU * vkGPU ) { 200//find a queue family for a selected GPU, select the first available for use 201uint32_t queueFamilyCount ; 202vkGetPhysicalDeviceQueueFamilyProperties (vkGPU -> physicalDevice ,& queueFamilyCount ,NULL ); 203 204VkQueueFamilyProperties * queueFamilies = (VkQueueFamilyProperties * )malloc (sizeof (VkQueueFamilyProperties )* queueFamilyCount ); 205if (!queueFamilies )return VK_INCOMPLETE ; 206if (queueFamilies ) { 207vkGetPhysicalDeviceQueueFamilyProperties (vkGPU -> physicalDevice ,& queueFamilyCount ,queueFamilies ); 208uint64_t i = 0 ; 209for (;i < queueFamilyCount ;i ++ ) { 210VkQueueFamilyProperties props = queueFamilies [i ]; 211 212if (props .queueCount > 0 && (props .queueFlags & VK_QUEUE_COMPUTE_BIT )) { 213break ; 214 } 215 } 216free (queueFamilies ); 217if (i == queueFamilyCount ) { 218return VK_ERROR_INITIALIZATION_FAILED ; 219 } 220vkGPU -> queueFamilyIndex = i ; 221return VK_SUCCESS ; 222 } 223else 224return VK_INCOMPLETE ; 225} 226 227VkResult createDevice (VkGPU * vkGPU ,uint64_t sample_id ) { 228//create logical device representation 229VkResult res = VK_SUCCESS ; 230VkDeviceQueueCreateInfo queueCreateInfo = {VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO }; 231res = getComputeQueueFamilyIndex (vkGPU ); 232if (res != VK_SUCCESS )return res ; 233queueCreateInfo .queueFamilyIndex = (uint32_t )vkGPU -> queueFamilyIndex ; 234queueCreateInfo .queueCount = 1 ; 235float queuePriorities = 1.0 ; 236queueCreateInfo .pQueuePriorities = & queuePriorities ; 237VkDeviceCreateInfo deviceCreateInfo = {VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; 238VkPhysicalDeviceFeatures deviceFeatures = {}; 239#if (VK_API_VERSION > 10 ) 240VkPhysicalDeviceFeatures2 deviceFeatures2 = {}; 241deviceFeatures2 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 ; 242void ** current_pNext = & deviceFeatures2 .pNext ; 243#endif 244switch (sample_id ) { 245case 1 :case 9 :case 12 :case 17 :case 18 :case 19 :case 101 :case 201 :case 203 :case 1001 :case 1004 : { 246deviceFeatures .shaderFloat64 = true; 247 } 248#if (VK_API_VERSION > 10 ) 249case 2 :case 13 :case 102 :case 202 :case 1002 : { 250VkPhysicalDevice16BitStorageFeatures shaderFloat16 = {}; 251shaderFloat16 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES ; 252shaderFloat16 .storageBuffer16BitAccess = true; 253/*VkPhysicalDeviceShaderFloat16Int8Features shaderFloat16 = {}; 254shaderFloat16.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES; 255shaderFloat16.shaderFloat16 = true; 256shaderFloat16.shaderInt8 = true;*/ 257current_pNext [0 ]= & shaderFloat16 ; 258current_pNext = & shaderFloat16 .pNext ; 259vkGPU -> enabledDeviceExtensions .push_back ("VK_KHR_16bit_storage" ); 260break ; 261 } 262#endif 263 } 264 265#if (VK_API_VERSION > 10 ) 266VkPhysicalDevicePushDescriptorPropertiesKHR pushDescriptorProperties = {}; 267pushDescriptorProperties .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR ; 268VkPhysicalDeviceProperties2KHR deviceProperties = {}; 269deviceProperties .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR ; 270deviceProperties .pNext = & pushDescriptorProperties ; 271vkGetPhysicalDeviceProperties2 (vkGPU -> physicalDevice ,& deviceProperties ); 272 273if (pushDescriptorProperties .maxPushDescriptors >=8 ) { 274current_pNext [0 ]= & pushDescriptorProperties ; 275current_pNext = & pushDescriptorProperties .pNext ; 276vkGPU -> enabledDeviceExtensions .push_back ("VK_KHR_push_descriptor" ); 277 } 278deviceFeatures2 .features = deviceFeatures ; 279vkGetPhysicalDeviceFeatures2 (vkGPU -> physicalDevice ,& deviceFeatures2 ); 280deviceCreateInfo .pNext = & deviceFeatures2 ; 281#endif 282 283deviceCreateInfo .enabledExtensionCount = (uint32_t )vkGPU -> enabledDeviceExtensions .size (); 284deviceCreateInfo .ppEnabledExtensionNames = vkGPU -> enabledDeviceExtensions .data (); 285deviceCreateInfo .pQueueCreateInfos = & queueCreateInfo ; 286deviceCreateInfo .queueCreateInfoCount = 1 ; 287#if (VK_API_VERSION == 10 ) 288deviceCreateInfo .pEnabledFeatures = & deviceFeatures ; 289#endif 290res = vkCreateDevice (vkGPU -> physicalDevice ,& deviceCreateInfo ,NULL ,& vkGPU -> device ); 291if (res != VK_SUCCESS )return res ; 292vkGetDeviceQueue (vkGPU -> device , (uint32_t )vkGPU -> queueFamilyIndex ,0 ,& vkGPU -> queue ); 293return res ; 294} 295VkResult createFence (VkGPU * vkGPU ) { 296//create fence for synchronization 297VkResult res = VK_SUCCESS ; 298VkFenceCreateInfo fenceCreateInfo = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO }; 299fenceCreateInfo .flags = 0 ; 300res = vkCreateFence (vkGPU -> device ,& fenceCreateInfo ,NULL ,& vkGPU -> fence ); 301return res ; 302} 303VkResult createCommandPool (VkGPU * vkGPU ) { 304//create a place, command buffer memory is allocated from 305VkResult res = VK_SUCCESS ; 306VkCommandPoolCreateInfo commandPoolCreateInfo = {VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO }; 307commandPoolCreateInfo .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT ; 308commandPoolCreateInfo .queueFamilyIndex = (uint32_t )vkGPU -> queueFamilyIndex ; 309res = vkCreateCommandPool (vkGPU -> device ,& commandPoolCreateInfo ,NULL ,& vkGPU -> commandPool ); 310return res ; 311} 312 313VkFFTResult findMemoryType (VkGPU * vkGPU ,uint64_t memoryTypeBits ,uint64_t memorySize ,VkMemoryPropertyFlags properties ,uint32_t * memoryTypeIndex ) { 314VkPhysicalDeviceMemoryProperties memoryProperties = {0 }; 315 316vkGetPhysicalDeviceMemoryProperties (vkGPU -> physicalDevice ,& memoryProperties ); 317 318for (uint64_t i = 0 ;i < memoryProperties .memoryTypeCount ;++ i ) { 319if ((memoryTypeBits & ((uint64_t )1 <<i ))&& ((memoryProperties .memoryTypes [i ].propertyFlags & properties )== properties )&& (memoryProperties .memoryHeaps [memoryProperties .memoryTypes [i ].heapIndex ].size >=memorySize )) 320 { 321memoryTypeIndex [0 ]= (uint32_t )i ; 322return VKFFT_SUCCESS ; 323 } 324 } 325return VKFFT_ERROR_FAILED_TO_FIND_MEMORY ; 326} 327 328VkFFTResult allocateBuffer (VkGPU * vkGPU ,VkBuffer * buffer ,VkDeviceMemory * deviceMemory ,VkBufferUsageFlags usageFlags ,VkMemoryPropertyFlags propertyFlags ,uint64_t size ) { 329//allocate the buffer used by the GPU with specified properties 330VkFFTResult resFFT = VKFFT_SUCCESS ; 331VkResult res = VK_SUCCESS ; 332uint32_t queueFamilyIndices ; 333VkBufferCreateInfo bufferCreateInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; 334bufferCreateInfo .sharingMode = VK_SHARING_MODE_EXCLUSIVE ; 335bufferCreateInfo .queueFamilyIndexCount = 1 ; 336bufferCreateInfo .pQueueFamilyIndices = & queueFamilyIndices ; 337bufferCreateInfo .size = size ; 338bufferCreateInfo .usage = usageFlags ; 339res = vkCreateBuffer (vkGPU -> device ,& bufferCreateInfo ,NULL ,buffer ); 340if (res != VK_SUCCESS )return VKFFT_ERROR_FAILED_TO_CREATE_BUFFER ; 341VkMemoryRequirements memoryRequirements = {0 }; 342vkGetBufferMemoryRequirements (vkGPU -> device ,buffer [0 ],& memoryRequirements ); 343VkMemoryAllocateInfo memoryAllocateInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; 344memoryAllocateInfo .allocationSize = memoryRequirements .size ; 345resFFT = findMemoryType (vkGPU ,memoryRequirements .memoryTypeBits ,memoryRequirements .size ,propertyFlags ,& memoryAllocateInfo .memoryTypeIndex ); 346if (resFFT != VKFFT_SUCCESS )return resFFT ; 347res = vkAllocateMemory (vkGPU -> device ,& memoryAllocateInfo ,NULL ,deviceMemory ); 348if (res != VK_SUCCESS )return VKFFT_ERROR_FAILED_TO_ALLOCATE_MEMORY ; 349res = vkBindBufferMemory (vkGPU -> device ,buffer [0 ],deviceMemory [0 ],0 ); 350if (res != VK_SUCCESS )return VKFFT_ERROR_FAILED_TO_BIND_BUFFER_MEMORY ; 351return resFFT ; 352} 353#endif 354VkFFTResult allocateMemoryGPU (VkGPU * vkGPU ,void ** buffer ,void ** deviceMemoryVulkan ,uint64_t bufferSize ) { 355VkFFTResult resFFT = VKFFT_SUCCESS ; 356#if (VKFFT_BACKEND == 0 ) 357VkResult res = VK_SUCCESS ; 358#elif (VKFFT_BACKEND == 1 ) 359cudaError_t res = cudaSuccess ; 360#elif (VKFFT_BACKEND == 2 ) 361hipError_t res = hipSuccess ; 362#elif (VKFFT_BACKEND == 3 ) 363cl_int res = CL_SUCCESS ; 364#elif (VKFFT_BACKEND == 4 ) 365ze_result_t res = ZE_RESULT_SUCCESS ; 366#elif (VKFFT_BACKEND == 5 ) 367#endif 368#if (VKFFT_BACKEND == 0 ) 369resFFT = allocateBuffer (vkGPU , (VkBuffer * )buffer , (VkDeviceMemory * )deviceMemoryVulkan ,VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |VK_BUFFER_USAGE_TRANSFER_SRC_BIT |VK_BUFFER_USAGE_TRANSFER_DST_BIT ,VK_MEMORY_HEAP_DEVICE_LOCAL_BIT ,bufferSize ); 370if (resFFT != VKFFT_SUCCESS )return resFFT ; 371#elif (VKFFT_BACKEND == 1 ) 372res = cudaMalloc ((void ** )buffer ,bufferSize ); 373if (res != cudaSuccess )return VKFFT_ERROR_FAILED_TO_ALLOCATE ; 374#elif (VKFFT_BACKEND == 2 ) 375res = hipMalloc ((void ** )buffer ,bufferSize ); 376if (res != hipSuccess )return VKFFT_ERROR_FAILED_TO_ALLOCATE ; 377#elif (VKFFT_BACKEND == 3 ) 378cl_mem * buffer_ref = (cl_mem * )buffer ; 379buffer_ref [0 ]= clCreateBuffer (vkGPU -> context ,CL_MEM_READ_WRITE ,bufferSize ,0 ,& res ); 380if (res != CL_SUCCESS )return VKFFT_ERROR_FAILED_TO_ALLOCATE ; 381#elif (VKFFT_BACKEND == 4 ) 382ze_device_mem_alloc_desc_t device_desc = {}; 383device_desc .stype = ZE_STRUCTURE_TYPE_DEVICE_MEM_ALLOC_DESC ; 384res = zeMemAllocDevice (vkGPU -> context ,& device_desc ,bufferSize ,sizeof (float ),vkGPU -> device ,buffer ); 385if (res != ZE_RESULT_SUCCESS )return VKFFT_ERROR_FAILED_TO_ALLOCATE ; 386#elif (VKFFT_BACKEND == 5 ) 387MTL ::Buffer ** buffer_ref = (MTL ::Buffer ** )buffer ; 388buffer_ref [0 ]= vkGPU -> device -> newBuffer (bufferSize ,MTL ::ResourceStorageModePrivate ); 389#endif 390return VKFFT_SUCCESS ; 391} 392VkFFTResult transferDataToCPU (VkGPU * vkGPU ,void * cpu_arr ,void * output_buffer ,uint64_t transferSize ) { 393//a function that transfers data from the GPU to the CPU using staging buffer, because the GPU memory is not host-coherent 394VkFFTResult resFFT = VKFFT_SUCCESS ; 395#if (VKFFT_BACKEND == 0 ) 396VkResult res = VK_SUCCESS ; 397VkBuffer * buffer = (VkBuffer * )output_buffer ; 398uint64_t stagingBufferSize = transferSize ; 399VkBuffer * stagingBuffer = {0 }; 400VkDeviceMemory * stagingBufferMemory = {0 }; 401if (!vkGPU -> stagingBuffer ){ 402stagingBuffer = (VkBuffer * )calloc (1 ,sizeof (VkBuffer )); 403stagingBufferMemory = (VkDeviceMemory * )calloc (1 ,sizeof (VkDeviceMemory )); 404resFFT = allocateBuffer (vkGPU ,stagingBuffer ,stagingBufferMemory ,VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |VK_BUFFER_USAGE_TRANSFER_SRC_BIT |VK_BUFFER_USAGE_TRANSFER_DST_BIT ,VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ,stagingBufferSize ); 405if (resFFT != VKFFT_SUCCESS )return resFFT ; 406 }else { 407stagingBuffer = vkGPU -> stagingBuffer ; 408stagingBufferMemory = vkGPU -> stagingBufferMemory ; 409 } 410VkCommandBufferAllocateInfo commandBufferAllocateInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; 411commandBufferAllocateInfo .commandPool = vkGPU -> commandPool ; 412commandBufferAllocateInfo .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY ; 413commandBufferAllocateInfo .commandBufferCount = 1 ; 414VkCommandBuffer commandBuffer = {0 }; 415res = vkAllocateCommandBuffers (vkGPU -> device ,& commandBufferAllocateInfo ,& commandBuffer ); 416if (res != VK_SUCCESS )return VKFFT_ERROR_FAILED_TO_ALLOCATE_COMMAND_BUFFERS ; 417VkCommandBufferBeginInfo commandBufferBeginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; 418commandBufferBeginInfo .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT ; 419res = vkBeginCommandBuffer (commandBuffer ,& commandBufferBeginInfo ); 420if (res != VK_SUCCESS )return VKFFT_ERROR_FAILED_TO_BEGIN_COMMAND_BUFFER ; 421VkBufferCopy copyRegion = {0 }; 422copyRegion .srcOffset = 0 ; 423copyRegion .dstOffset = 0 ; 424copyRegion .size = stagingBufferSize ; 425vkCmdCopyBuffer (commandBuffer ,buffer [0 ],stagingBuffer [0 ],1 ,& copyRegion ); 426res = vkEndCommandBuffer (commandBuffer ); 427if (res != VK_SUCCESS )return VKFFT_ERROR_FAILED_TO_END_COMMAND_BUFFER ; 428VkSubmitInfo submitInfo = {VK_STRUCTURE_TYPE_SUBMIT_INFO }; 429submitInfo .commandBufferCount = 1 ; 430submitInfo .pCommandBuffers = & commandBuffer ; 431res = vkQueueSubmit (vkGPU -> queue ,1 ,& submitInfo ,vkGPU -> fence ); 432if (res != VK_SUCCESS )return VKFFT_ERROR_FAILED_TO_SUBMIT_QUEUE ; 433res = vkWaitForFences (vkGPU -> device ,1 ,& vkGPU -> fence ,VK_TRUE ,100000000000 ); 434if (res != VK_SUCCESS )return VKFFT_ERROR_FAILED_TO_WAIT_FOR_FENCES ; 435res = vkResetFences (vkGPU -> device ,1 ,& vkGPU -> fence ); 436if (res != VK_SUCCESS )return VKFFT_ERROR_FAILED_TO_RESET_FENCES ; 437vkFreeCommandBuffers (vkGPU -> device ,vkGPU -> commandPool ,1 ,& commandBuffer ); 438void * data ; 439res = vkMapMemory (vkGPU -> device ,stagingBufferMemory [0 ],0 ,stagingBufferSize ,0 ,& data ); 440if (resFFT != VKFFT_SUCCESS )return resFFT ; 441memcpy (cpu_arr ,data ,stagingBufferSize ); 442vkUnmapMemory (vkGPU -> device ,stagingBufferMemory [0 ]); 443if (!vkGPU -> stagingBuffer ){ 444vkDestroyBuffer (vkGPU -> device ,stagingBuffer [0 ],0 ); 445vkFreeMemory (vkGPU -> device ,stagingBufferMemory [0 ],0 ); 446free (stagingBuffer ); 447free (stagingBufferMemory ); 448 } 449#elif (VKFFT_BACKEND == 1 ) 450cudaError_t res = cudaSuccess ; 451void * buffer = ((void ** )output_buffer )[0 ]; 452res = cudaMemcpy (cpu_arr ,buffer ,transferSize ,cudaMemcpyDeviceToHost ); 453if (res != cudaSuccess ) { 454return VKFFT_ERROR_FAILED_TO_COPY ; 455 } 456#elif (VKFFT_BACKEND == 2 ) 457hipError_t res = hipSuccess ; 458void * buffer = ((void ** )output_buffer )[0 ]; 459res = hipMemcpy (cpu_arr ,buffer ,transferSize ,hipMemcpyDeviceToHost ); 460if (res != hipSuccess ) { 461return VKFFT_ERROR_FAILED_TO_COPY ; 462 } 463#elif (VKFFT_BACKEND == 3 ) 464cl_int res = CL_SUCCESS ; 465cl_mem * buffer = (cl_mem * )output_buffer ; 466cl_command_queue commandQueue = clCreateCommandQueue (vkGPU -> context ,vkGPU -> device ,0 ,& res ); 467if (res != CL_SUCCESS )return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_QUEUE ; 468res = clEnqueueReadBuffer (commandQueue ,buffer [0 ],CL_TRUE ,0 ,transferSize ,cpu_arr ,0 ,NULL ,NULL ); 469if (res != CL_SUCCESS ) { 470return VKFFT_ERROR_FAILED_TO_COPY ; 471 } 472res = clReleaseCommandQueue (commandQueue ); 473if (res != CL_SUCCESS )return VKFFT_ERROR_FAILED_TO_RELEASE_COMMAND_QUEUE ; 474#elif (VKFFT_BACKEND == 4 ) 475ze_result_t res = ZE_RESULT_SUCCESS ; 476void * buffer = ((void ** )output_buffer )[0 ]; 477ze_command_queue_desc_t commandQueueCopyDesc = { 478ZE_STRUCTURE_TYPE_COMMAND_QUEUE_DESC , 4790 , 480vkGPU -> commandQueueID , 4810 ,// index 4820 ,// flags 483ZE_COMMAND_QUEUE_MODE_DEFAULT , 484ZE_COMMAND_QUEUE_PRIORITY_NORMAL 485 }; 486ze_command_list_handle_t copyCommandList ; 487res = zeCommandListCreateImmediate (vkGPU -> context ,vkGPU -> device ,& commandQueueCopyDesc ,& copyCommandList ); 488if (res != ZE_RESULT_SUCCESS ) { 489return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_LIST ; 490 } 491res = zeCommandListAppendMemoryCopy (copyCommandList ,cpu_arr ,buffer ,transferSize ,0 ,0 ,0 ); 492if (res != ZE_RESULT_SUCCESS ) { 493return VKFFT_ERROR_FAILED_TO_COPY ; 494 } 495res = zeCommandQueueSynchronize (vkGPU -> commandQueue ,UINT32_MAX ); 496if (res != ZE_RESULT_SUCCESS ) { 497return VKFFT_ERROR_FAILED_TO_SYNCHRONIZE ; 498 } 499#elif (VKFFT_BACKEND == 5 ) 500MTL ::Buffer * stagingBuffer = vkGPU -> device -> newBuffer (transferSize ,MTL ::ResourceStorageModeShared ); 501MTL ::CommandBuffer * copyCommandBuffer = vkGPU -> queue -> commandBuffer (); 502if (copyCommandBuffer == 0 )return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_LIST ; 503MTL ::BlitCommandEncoder * blitCommandEncoder = copyCommandBuffer -> blitCommandEncoder (); 504if (blitCommandEncoder == 0 )return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_LIST ; 505MTL ::Buffer * buffer = ((MTL ::Buffer ** )output_buffer )[0 ]; 506blitCommandEncoder -> copyFromBuffer ((MTL ::Buffer * )buffer ,0 , (MTL ::Buffer * )stagingBuffer ,0 ,transferSize ); 507blitCommandEncoder -> endEncoding (); 508copyCommandBuffer -> commit (); 509copyCommandBuffer -> waitUntilCompleted (); 510blitCommandEncoder -> release (); 511copyCommandBuffer -> release (); 512memcpy (cpu_arr ,stagingBuffer -> contents (),transferSize ); 513stagingBuffer -> release (); 514#endif 515return resFFT ; 516} 517VkFFTResult transferDataFromCPU (VkGPU * vkGPU ,void * cpu_arr ,void * input_buffer ,uint64_t transferSize ) { 518VkFFTResult resFFT = VKFFT_SUCCESS ; 519#if (VKFFT_BACKEND == 0 ) 520VkResult res = VK_SUCCESS ; 521VkBuffer * buffer = (VkBuffer * )input_buffer ; 522uint64_t stagingBufferSize = transferSize ; 523VkBuffer * stagingBuffer = {0 }; 524VkDeviceMemory * stagingBufferMemory = {0 }; 525if (!vkGPU -> stagingBuffer ){ 526stagingBuffer = (VkBuffer * )calloc (1 ,sizeof (VkBuffer )); 527stagingBufferMemory = (VkDeviceMemory * )calloc (1 ,sizeof (VkDeviceMemory )); 528resFFT = allocateBuffer (vkGPU ,stagingBuffer ,stagingBufferMemory ,VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |VK_BUFFER_USAGE_TRANSFER_SRC_BIT |VK_BUFFER_USAGE_TRANSFER_DST_BIT ,VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ,stagingBufferSize ); 529if (resFFT != VKFFT_SUCCESS )return resFFT ; 530 }else { 531stagingBuffer = vkGPU -> stagingBuffer ; 532stagingBufferMemory = vkGPU -> stagingBufferMemory ; 533 } 534void * data ; 535res = vkMapMemory (vkGPU -> device ,stagingBufferMemory [0 ],0 ,stagingBufferSize ,0 ,& data ); 536if (resFFT != VKFFT_SUCCESS )return resFFT ; 537memcpy (data ,cpu_arr ,stagingBufferSize ); 538vkUnmapMemory (vkGPU -> device ,stagingBufferMemory [0 ]); 539VkCommandBufferAllocateInfo commandBufferAllocateInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; 540commandBufferAllocateInfo .commandPool = vkGPU -> commandPool ; 541commandBufferAllocateInfo .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY ; 542commandBufferAllocateInfo .commandBufferCount = 1 ; 543VkCommandBuffer commandBuffer = {0 }; 544res = vkAllocateCommandBuffers (vkGPU -> device ,& commandBufferAllocateInfo ,& commandBuffer ); 545if (res != VK_SUCCESS )return VKFFT_ERROR_FAILED_TO_ALLOCATE_COMMAND_BUFFERS ; 546VkCommandBufferBeginInfo commandBufferBeginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; 547commandBufferBeginInfo .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT ; 548res = vkBeginCommandBuffer (commandBuffer ,& commandBufferBeginInfo ); 549if (res != VK_SUCCESS )return VKFFT_ERROR_FAILED_TO_BEGIN_COMMAND_BUFFER ; 550VkBufferCopy copyRegion = {0 }; 551copyRegion .srcOffset = 0 ; 552copyRegion .dstOffset = 0 ; 553copyRegion .size = stagingBufferSize ; 554vkCmdCopyBuffer (commandBuffer ,stagingBuffer [0 ],buffer [0 ],1 ,& copyRegion ); 555res = vkEndCommandBuffer (commandBuffer ); 556if (res != VK_SUCCESS )return VKFFT_ERROR_FAILED_TO_END_COMMAND_BUFFER ; 557VkSubmitInfo submitInfo = {VK_STRUCTURE_TYPE_SUBMIT_INFO }; 558submitInfo .commandBufferCount = 1 ; 559submitInfo .pCommandBuffers = & commandBuffer ; 560res = vkQueueSubmit (vkGPU -> queue ,1 ,& submitInfo ,vkGPU -> fence ); 561if (res != VK_SUCCESS )return VKFFT_ERROR_FAILED_TO_SUBMIT_QUEUE ; 562res = vkWaitForFences (vkGPU -> device ,1 ,& vkGPU -> fence ,VK_TRUE ,100000000000 ); 563if (res != VK_SUCCESS )return VKFFT_ERROR_FAILED_TO_WAIT_FOR_FENCES ; 564res = vkResetFences (vkGPU -> device ,1 ,& vkGPU -> fence ); 565if (res != VK_SUCCESS )return VKFFT_ERROR_FAILED_TO_RESET_FENCES ; 566vkFreeCommandBuffers (vkGPU -> device ,vkGPU -> commandPool ,1 ,& commandBuffer ); 567if (!vkGPU -> stagingBuffer ){ 568vkDestroyBuffer (vkGPU -> device ,stagingBuffer [0 ],0 ); 569vkFreeMemory (vkGPU -> device ,stagingBufferMemory [0 ],0 ); 570free (stagingBuffer ); 571free (stagingBufferMemory ); 572 } 573return resFFT ; 574#elif (VKFFT_BACKEND == 1 ) 575cudaError_t res = cudaSuccess ; 576void * buffer = ((void ** )input_buffer )[0 ]; 577res = cudaMemcpy (buffer ,cpu_arr ,transferSize ,cudaMemcpyHostToDevice ); 578if (res != cudaSuccess ) { 579return VKFFT_ERROR_FAILED_TO_COPY ; 580 } 581#elif (VKFFT_BACKEND == 2 ) 582hipError_t res = hipSuccess ; 583void * buffer = ((void ** )input_buffer )[0 ]; 584res = hipMemcpy (buffer ,cpu_arr ,transferSize ,hipMemcpyHostToDevice ); 585if (res != hipSuccess ) { 586return VKFFT_ERROR_FAILED_TO_COPY ; 587 } 588#elif (VKFFT_BACKEND == 3 ) 589cl_int res = CL_SUCCESS ; 590cl_mem * buffer = (cl_mem * )input_buffer ; 591cl_command_queue commandQueue = clCreateCommandQueue (vkGPU -> context ,vkGPU -> device ,0 ,& res ); 592if (res != CL_SUCCESS )return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_QUEUE ; 593res = clEnqueueWriteBuffer (commandQueue ,buffer [0 ],CL_TRUE ,0 ,transferSize ,cpu_arr ,0 ,NULL ,NULL ); 594if (res != CL_SUCCESS ) { 595return VKFFT_ERROR_FAILED_TO_COPY ; 596 } 597res = clReleaseCommandQueue (commandQueue ); 598if (res != CL_SUCCESS )return VKFFT_ERROR_FAILED_TO_RELEASE_COMMAND_QUEUE ; 599#elif (VKFFT_BACKEND == 4 ) 600ze_result_t res = ZE_RESULT_SUCCESS ; 601void * buffer = ((void ** )input_buffer )[0 ]; 602ze_command_queue_desc_t commandQueueCopyDesc = { 603ZE_STRUCTURE_TYPE_COMMAND_QUEUE_DESC , 6040 , 605vkGPU -> commandQueueID , 6060 ,// index 6070 ,// flags 608ZE_COMMAND_QUEUE_MODE_DEFAULT , 609ZE_COMMAND_QUEUE_PRIORITY_NORMAL 610 }; 611ze_command_list_handle_t copyCommandList ; 612res = zeCommandListCreateImmediate (vkGPU -> context ,vkGPU -> device ,& commandQueueCopyDesc ,& copyCommandList ); 613if (res != ZE_RESULT_SUCCESS ) { 614return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_LIST ; 615 } 616res = zeCommandListAppendMemoryCopy (copyCommandList ,buffer ,cpu_arr ,transferSize ,0 ,0 ,0 ); 617if (res != ZE_RESULT_SUCCESS ) { 618return VKFFT_ERROR_FAILED_TO_COPY ; 619 } 620res = zeCommandQueueSynchronize (vkGPU -> commandQueue ,UINT32_MAX ); 621if (res != ZE_RESULT_SUCCESS ) { 622return VKFFT_ERROR_FAILED_TO_SYNCHRONIZE ; 623 } 624#elif (VKFFT_BACKEND == 5 ) 625MTL ::Buffer * stagingBuffer = vkGPU -> device -> newBuffer (cpu_arr ,transferSize ,MTL ::ResourceStorageModeShared ); 626MTL ::CommandBuffer * copyCommandBuffer = vkGPU -> queue -> commandBuffer (); 627if (copyCommandBuffer == 0 )return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_LIST ; 628MTL ::BlitCommandEncoder * blitCommandEncoder = copyCommandBuffer -> blitCommandEncoder (); 629if (blitCommandEncoder == 0 )return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_LIST ; 630MTL ::Buffer * buffer = ((MTL ::Buffer ** )input_buffer )[0 ]; 631blitCommandEncoder -> copyFromBuffer ((MTL ::Buffer * )stagingBuffer ,0 , (MTL ::Buffer * )buffer ,0 ,transferSize ); 632blitCommandEncoder -> endEncoding (); 633copyCommandBuffer -> commit (); 634copyCommandBuffer -> waitUntilCompleted (); 635blitCommandEncoder -> release (); 636copyCommandBuffer -> release (); 637stagingBuffer -> release (); 638#endif 639return resFFT ; 640} 641VkFFTResult devices_list () { 642//this function creates an instance and prints the list of available devices 643#if (VKFFT_BACKEND == 0 ) 644VkResult res = VK_SUCCESS ; 645VkInstance local_instance = {0 }; 646VkInstanceCreateInfo createInfo = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO }; 647createInfo .flags = 0 ; 648createInfo .pApplicationInfo = NULL ; 649VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo = {VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT }; 650createInfo .enabledLayerCount = 0 ; 651createInfo .enabledExtensionCount = 0 ; 652createInfo .pNext = NULL ; 653res = vkCreateInstance (& createInfo ,NULL ,& local_instance ); 654if (res != VK_SUCCESS )return VKFFT_ERROR_FAILED_TO_CREATE_INSTANCE ; 655 656uint32_t deviceCount ; 657res = vkEnumeratePhysicalDevices (local_instance ,& deviceCount ,NULL ); 658if (res != VK_SUCCESS )return VKFFT_ERROR_FAILED_TO_ENUMERATE_DEVICES ; 659 660VkPhysicalDevice * devices = (VkPhysicalDevice * )malloc (sizeof (VkPhysicalDevice )* deviceCount ); 661if (!devices )return VKFFT_ERROR_MALLOC_FAILED ; 662if (devices ) { 663res = vkEnumeratePhysicalDevices (local_instance ,& deviceCount ,devices ); 664if (res != VK_SUCCESS )return VKFFT_ERROR_FAILED_TO_ENUMERATE_DEVICES ; 665for (uint64_t i = 0 ;i < deviceCount ;i ++ ) { 666VkPhysicalDeviceProperties device_properties ; 667vkGetPhysicalDeviceProperties (devices [i ],& device_properties ); 668printf ("Device id: %" PRIu64 " name: %s API:%d.%d.%d\n" ,i ,device_properties .deviceName , (device_properties .apiVersion >>22 ), ((device_properties .apiVersion >>12 )& 0x3ff ), (device_properties .apiVersion & 0xfff )); 669 } 670free (devices ); 671 } 672else 673return VKFFT_ERROR_FAILED_TO_ENUMERATE_DEVICES ; 674vkDestroyInstance (local_instance ,NULL ); 675#elif (VKFFT_BACKEND == 1 ) 676CUresult res = CUDA_SUCCESS ; 677res = cuInit (0 ); 678if (res != CUDA_SUCCESS )return VKFFT_ERROR_FAILED_TO_INITIALIZE ; 679int numDevices ; 680res = cuDeviceGetCount (& numDevices ); 681if (res != CUDA_SUCCESS )return VKFFT_ERROR_FAILED_TO_SET_DEVICE_ID ; 682for (uint64_t i = 0 ;i < numDevices ;i ++ ) { 683char deviceName [256 ]; 684CUdevice device = {}; 685res = cuDeviceGet (& device , (int )i ); 686if (res != CUDA_SUCCESS )return VKFFT_ERROR_FAILED_TO_GET_DEVICE ; 687res = cuDeviceGetName (deviceName ,256 ,device ); 688if (res != CUDA_SUCCESS )return VKFFT_ERROR_FAILED_TO_GET_DEVICE ; 689printf ("Device id: %" PRIu64 " name: %s\n" ,i ,deviceName ); 690 } 691#elif (VKFFT_BACKEND == 2 ) 692hipError_t res = hipSuccess ; 693res = hipInit (0 ); 694if (res != hipSuccess )return VKFFT_ERROR_FAILED_TO_INITIALIZE ; 695int numDevices ; 696res = hipGetDeviceCount (& numDevices ); 697if (res != hipSuccess )return VKFFT_ERROR_FAILED_TO_SET_DEVICE_ID ; 698for (uint64_t i = 0 ;i < numDevices ;i ++ ) { 699char deviceName [256 ]; 700hipDevice_t device = {}; 701res = hipDeviceGet (& device ,i ); 702if (res != hipSuccess )return VKFFT_ERROR_FAILED_TO_GET_DEVICE ; 703res = hipDeviceGetName (deviceName ,256 ,device ); 704if (res != hipSuccess )return VKFFT_ERROR_FAILED_TO_GET_DEVICE ; 705printf ("Device id: %" PRIu64 " name: %s\n" ,i ,deviceName ); 706 } 707#elif (VKFFT_BACKEND == 3 ) 708cl_int res = CL_SUCCESS ; 709cl_uint numPlatforms ; 710res = clGetPlatformIDs (0 ,0 ,& numPlatforms ); 711if (res != CL_SUCCESS )return VKFFT_ERROR_FAILED_TO_INITIALIZE ; 712cl_platform_id * platforms = (cl_platform_id * )malloc (sizeof (cl_platform_id )* numPlatforms ); 713if (!platforms )return VKFFT_ERROR_MALLOC_FAILED ; 714res = clGetPlatformIDs (numPlatforms ,platforms ,0 ); 715if (res != CL_SUCCESS )return VKFFT_ERROR_FAILED_TO_INITIALIZE ; 716uint64_t k = 0 ; 717for (uint64_t j = 0 ;j < numPlatforms ;j ++ ) { 718cl_uint numDevices ; 719res = clGetDeviceIDs (platforms [j ],CL_DEVICE_TYPE_ALL ,0 ,0 ,& numDevices ); 720cl_device_id * deviceList = (cl_device_id * )malloc (sizeof (cl_device_id )* numDevices ); 721if (!deviceList )return VKFFT_ERROR_MALLOC_FAILED ; 722res = clGetDeviceIDs (platforms [j ],CL_DEVICE_TYPE_ALL ,numDevices ,deviceList ,0 ); 723if (res != CL_SUCCESS )return VKFFT_ERROR_FAILED_TO_GET_DEVICE ; 724for (uint64_t i = 0 ;i < numDevices ;i ++ ) { 725char deviceName [256 ]; 726char apiVersion [256 ]; 727res = clGetDeviceInfo (deviceList [i ],CL_DEVICE_NAME ,256 * sizeof (char ),deviceName ,0 ); 728if (res != CL_SUCCESS )return VKFFT_ERROR_FAILED_TO_ENUMERATE_DEVICES ; 729res = clGetDeviceInfo (deviceList [i ],CL_DEVICE_VERSION ,256 * sizeof (char ),apiVersion ,0 ); 730if (res != CL_SUCCESS )return VKFFT_ERROR_FAILED_TO_ENUMERATE_DEVICES ; 731printf ("Platform id: %" PRIu64 " Device id: %" PRIu64 " name: %s API:%s\n" ,j ,k ,deviceName ,apiVersion ); 732k ++ ; 733 } 734free (deviceList ); 735 } 736free (platforms ); 737#elif (VKFFT_BACKEND == 4 ) 738ze_result_t res = ZE_RESULT_SUCCESS ; 739res = zeInit (0 ); 740if (res != ZE_RESULT_SUCCESS )return VKFFT_ERROR_FAILED_TO_INITIALIZE ; 741uint32_t numDrivers = 0 ; 742res = zeDriverGet (& numDrivers ,0 ); 743if (res != ZE_RESULT_SUCCESS )return VKFFT_ERROR_FAILED_TO_INITIALIZE ; 744ze_driver_handle_t * drivers = (ze_driver_handle_t * )malloc (numDrivers * sizeof (ze_driver_handle_t )); 745if (!drivers )return VKFFT_ERROR_MALLOC_FAILED ; 746res = zeDriverGet (& numDrivers ,drivers ); 747if (res != ZE_RESULT_SUCCESS )return VKFFT_ERROR_FAILED_TO_INITIALIZE ; 748uint64_t k = 0 ; 749for (uint64_t j = 0 ;j < numDrivers ;j ++ ) { 750uint32_t numDevices = 0 ; 751res = zeDeviceGet (drivers [j ],& numDevices ,nullptr ); 752if (res != ZE_RESULT_SUCCESS )return VKFFT_ERROR_FAILED_TO_GET_DEVICE ; 753ze_device_handle_t * deviceList = (ze_device_handle_t * )malloc (numDevices * sizeof (ze_device_handle_t )); 754if (!deviceList )return VKFFT_ERROR_MALLOC_FAILED ; 755res = zeDeviceGet (drivers [j ],& numDevices ,deviceList ); 756if (res != ZE_RESULT_SUCCESS )return VKFFT_ERROR_FAILED_TO_GET_DEVICE ; 757for (uint64_t i = 0 ;i < numDevices ;i ++ ) { 758ze_device_properties_t device_properties ; 759res = zeDeviceGetProperties (deviceList [i ],& device_properties ); 760if (res != ZE_RESULT_SUCCESS )return VKFFT_ERROR_FAILED_TO_ENUMERATE_DEVICES ; 761printf ("Driver id: %" PRIu64 " Device id: %" PRIu64 " name: %s\n" ,j ,k ,device_properties .name ); 762k ++ ; 763 } 764 765free (deviceList ); 766 } 767free (drivers ); 768#elif (VKFFT_BACKEND == 5 ) 769NS ::Array * devices = MTL ::CopyAllDevices (); 770for (uint64_t i = 0 ;i < devices -> count ();i ++ ) { 771MTL ::Device * loc_device = (MTL ::Device * )devices -> object (i ); 772printf ("Device id: %" PRIu64 " name: %s\n" ,i ,loc_device -> name ()-> cString (NS ::UTF8StringEncoding )); 773 } 774#endif 775return VKFFT_SUCCESS ; 776} 777VkFFTResult performVulkanFFT (VkGPU * vkGPU ,VkFFTApplication * app ,VkFFTLaunchParams * launchParams ,int inverse ,uint64_t num_iter ) { 778VkFFTResult resFFT = VKFFT_SUCCESS ; 779#if (VKFFT_BACKEND == 0 ) 780VkResult res = VK_SUCCESS ; 781VkCommandBufferAllocateInfo commandBufferAllocateInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; 782commandBufferAllocateInfo .commandPool = vkGPU -> commandPool ; 783commandBufferAllocateInfo .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY ; 784commandBufferAllocateInfo .commandBufferCount = 1 ; 785VkCommandBuffer commandBuffer = {}; 786res = vkAllocateCommandBuffers (vkGPU -> device ,& commandBufferAllocateInfo ,& commandBuffer ); 787if (res != 0 )return VKFFT_ERROR_FAILED_TO_ALLOCATE_COMMAND_BUFFERS ; 788VkCommandBufferBeginInfo commandBufferBeginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; 789commandBufferBeginInfo .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT ; 790res = vkBeginCommandBuffer (commandBuffer ,& commandBufferBeginInfo ); 791if (res != 0 )return VKFFT_ERROR_FAILED_TO_BEGIN_COMMAND_BUFFER ; 792launchParams -> commandBuffer = & commandBuffer ; 793//Record commands num_iter times. Allows to perform multiple convolutions/transforms in one submit. 794for (uint64_t i = 0 ;i < num_iter ;i ++ ) { 795resFFT = VkFFTAppend (app ,inverse ,launchParams ); 796if (resFFT != VKFFT_SUCCESS )return resFFT ; 797launchParams -> buffer = launchParams -> kernel ; 798//resFFT = VkFFTAppend(app, inverse, launchParams); 799if (resFFT != VKFFT_SUCCESS )return resFFT ; 800 } 801res = vkEndCommandBuffer (commandBuffer ); 802if (res != 0 )return VKFFT_ERROR_FAILED_TO_END_COMMAND_BUFFER ; 803VkSubmitInfo submitInfo = {VK_STRUCTURE_TYPE_SUBMIT_INFO }; 804submitInfo .commandBufferCount = 1 ; 805submitInfo .pCommandBuffers = & commandBuffer ; 806 std::chrono::steady_clock::time_point timeSubmit = std::chrono::steady_clock::now (); 807res = vkQueueSubmit (vkGPU -> queue ,1 ,& submitInfo ,vkGPU -> fence ); 808if (res != 0 )return VKFFT_ERROR_FAILED_TO_SUBMIT_QUEUE ; 809res = vkWaitForFences (vkGPU -> device ,1 ,& vkGPU -> fence ,VK_TRUE ,100000000000 ); 810if (res != 0 )return VKFFT_ERROR_FAILED_TO_WAIT_FOR_FENCES ; 811 std::chrono::steady_clock::time_point timeEnd = std::chrono::steady_clock::now (); 812double totTime = std::chrono::duration_cast < std::chrono::microseconds > (timeEnd - timeSubmit ).count ()* 0.001 ; 813//printf("Pure submit execution time per num_iter: %.3f ms\n", totTime / num_iter); 814res = vkResetFences (vkGPU -> device ,1 ,& vkGPU -> fence ); 815if (res != 0 )return VKFFT_ERROR_FAILED_TO_RESET_FENCES ; 816vkFreeCommandBuffers (vkGPU -> device ,vkGPU -> commandPool ,1 ,& commandBuffer ); 817#elif (VKFFT_BACKEND == 1 ) 818cudaError_t res = cudaSuccess ; 819 std::chrono::steady_clock::time_point timeSubmit = std::chrono::steady_clock::now (); 820for (uint64_t i = 0 ;i < num_iter ;i ++ ) { 821resFFT = VkFFTAppend (app ,inverse ,launchParams ); 822if (resFFT != VKFFT_SUCCESS )return resFFT ; 823 } 824res = cudaDeviceSynchronize (); 825if (res != cudaSuccess )return VKFFT_ERROR_FAILED_TO_SYNCHRONIZE ; 826 std::chrono::steady_clock::time_point timeEnd = std::chrono::steady_clock::now (); 827double totTime = std::chrono::duration_cast < std::chrono::microseconds > (timeEnd - timeSubmit ).count ()* 0.001 ; 828#elif (VKFFT_BACKEND == 2 ) 829hipError_t res = hipSuccess ; 830 std::chrono::steady_clock::time_point timeSubmit = std::chrono::steady_clock::now (); 831for (uint64_t i = 0 ;i < num_iter ;i ++ ) { 832resFFT = VkFFTAppend (app ,inverse ,launchParams ); 833if (resFFT != VKFFT_SUCCESS )return resFFT ; 834 } 835res = hipDeviceSynchronize (); 836if (res != hipSuccess )return VKFFT_ERROR_FAILED_TO_SYNCHRONIZE ; 837 std::chrono::steady_clock::time_point timeEnd = std::chrono::steady_clock::now (); 838double totTime = std::chrono::duration_cast < std::chrono::microseconds > (timeEnd - timeSubmit ).count ()* 0.001 ; 839#elif (VKFFT_BACKEND == 3 ) 840cl_int res = CL_SUCCESS ; 841launchParams -> commandQueue = & vkGPU -> commandQueue ; 842 std::chrono::steady_clock::time_point timeSubmit = std::chrono::steady_clock::now (); 843for (uint64_t i = 0 ;i < num_iter ;i ++ ) { 844resFFT = VkFFTAppend (app ,inverse ,launchParams ); 845if (resFFT != VKFFT_SUCCESS )return resFFT ; 846 } 847res = clFinish (vkGPU -> commandQueue ); 848if (res != CL_SUCCESS )return VKFFT_ERROR_FAILED_TO_SYNCHRONIZE ; 849 std::chrono::steady_clock::time_point timeEnd = std::chrono::steady_clock::now (); 850double totTime = std::chrono::duration_cast < std::chrono::microseconds > (timeEnd - timeSubmit ).count ()* 0.001 ; 851#elif (VKFFT_BACKEND == 4 ) 852ze_result_t res = ZE_RESULT_SUCCESS ; 853ze_command_list_desc_t commandListDescription = {}; 854commandListDescription .stype = ZE_STRUCTURE_TYPE_COMMAND_LIST_DESC ; 855ze_command_list_handle_t commandList = {}; 856res = zeCommandListCreate (vkGPU -> context ,vkGPU -> device ,& commandListDescription ,& commandList ); 857if (res != ZE_RESULT_SUCCESS )return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_LIST ; 858 859launchParams -> commandList = & commandList ; 860//Record commands num_iter times. Allows to perform multiple convolutions/transforms in one submit. 861for (uint64_t i = 0 ;i < num_iter ;i ++ ) { 862resFFT = VkFFTAppend (app ,inverse ,launchParams ); 863if (resFFT != VKFFT_SUCCESS )return resFFT ; 864 } 865res = zeCommandListClose (commandList ); 866if (res != 0 )return VKFFT_ERROR_FAILED_TO_END_COMMAND_BUFFER ; 867 868 std::chrono::steady_clock::time_point timeSubmit = std::chrono::steady_clock::now (); 869res = zeCommandQueueExecuteCommandLists (vkGPU -> commandQueue ,1 ,& commandList ,0 ); 870if (res != 0 )return VKFFT_ERROR_FAILED_TO_SUBMIT_QUEUE ; 871res = zeCommandQueueSynchronize (vkGPU -> commandQueue ,UINT32_MAX ); 872if (res != 0 )return VKFFT_ERROR_FAILED_TO_WAIT_FOR_FENCES ; 873 874 std::chrono::steady_clock::time_point timeEnd = std::chrono::steady_clock::now (); 875double totTime = std::chrono::duration_cast < std::chrono::microseconds > (timeEnd - timeSubmit ).count ()* 0.001 ; 876//printf("Pure submit execution time per num_iter: %.3f ms\n", totTime / num_iter); 877res = zeCommandListDestroy (commandList ); 878if (res != 0 )return VKFFT_ERROR_FAILED_TO_DESTROY_COMMAND_LIST ; 879#elif (VKFFT_BACKEND == 5 ) 880MTL ::CommandBuffer * commandBuffer = vkGPU -> queue -> commandBuffer (); 881if (commandBuffer == 0 )return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_LIST ; 882launchParams -> commandBuffer = commandBuffer ; 883MTL ::ComputeCommandEncoder * commandEncoder = commandBuffer -> computeCommandEncoder (); 884if (commandEncoder == 0 )return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_LIST ; 885launchParams -> commandEncoder = commandEncoder ; 886for (uint64_t i = 0 ;i < num_iter ;i ++ ) { 887resFFT = VkFFTAppend (app ,inverse ,launchParams ); 888if (resFFT != VKFFT_SUCCESS )return resFFT ; 889 } 890commandEncoder -> endEncoding (); 891 892 std::chrono::steady_clock::time_point timeSubmit = std::chrono::steady_clock::now (); 893commandBuffer -> commit (); 894commandBuffer -> waitUntilCompleted (); 895 std::chrono::steady_clock::time_point timeEnd = std::chrono::steady_clock::now (); 896double totTime = std::chrono::duration_cast < std::chrono::microseconds > (timeEnd - timeSubmit ).count ()* 0.001 ; 897 898commandEncoder -> release (); 899commandBuffer -> release (); 900#endif 901return resFFT ; 902} 903VkFFTResult performVulkanFFTiFFT (VkGPU * vkGPU ,VkFFTApplication * app ,VkFFTLaunchParams * launchParams ,uint64_t num_iter ,double * time_result ) { 904VkFFTResult resFFT = VKFFT_SUCCESS ; 905#if (VKFFT_BACKEND == 0 ) 906VkResult res = VK_SUCCESS ; 907VkCommandBufferAllocateInfo commandBufferAllocateInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; 908commandBufferAllocateInfo .commandPool = vkGPU -> commandPool ; 909commandBufferAllocateInfo .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY ; 910commandBufferAllocateInfo .commandBufferCount = 1 ; 911VkCommandBuffer commandBuffer = {}; 912res = vkAllocateCommandBuffers (vkGPU -> device ,& commandBufferAllocateInfo ,& commandBuffer ); 913if (res != 0 )return VKFFT_ERROR_FAILED_TO_ALLOCATE_COMMAND_BUFFERS ; 914VkCommandBufferBeginInfo commandBufferBeginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; 915commandBufferBeginInfo .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT ; 916res = vkBeginCommandBuffer (commandBuffer ,& commandBufferBeginInfo ); 917if (res != 0 )return VKFFT_ERROR_FAILED_TO_BEGIN_COMMAND_BUFFER ; 918launchParams -> commandBuffer = & commandBuffer ; 919for (uint64_t i = 0 ;i < num_iter ;i ++ ) { 920resFFT = VkFFTAppend (app ,-1 ,launchParams ); 921if (resFFT != VKFFT_SUCCESS )return resFFT ; 922resFFT = VkFFTAppend (app ,1 ,launchParams ); 923if (resFFT != VKFFT_SUCCESS )return resFFT ; 924 } 925res = vkEndCommandBuffer (commandBuffer ); 926if (res != 0 )return VKFFT_ERROR_FAILED_TO_END_COMMAND_BUFFER ; 927VkSubmitInfo submitInfo = {VK_STRUCTURE_TYPE_SUBMIT_INFO }; 928submitInfo .commandBufferCount = 1 ; 929submitInfo .pCommandBuffers = & commandBuffer ; 930 std::chrono::steady_clock::time_point timeSubmit = std::chrono::steady_clock::now (); 931res = vkQueueSubmit (vkGPU -> queue ,1 ,& submitInfo ,vkGPU -> fence ); 932if (res != 0 )return VKFFT_ERROR_FAILED_TO_SUBMIT_QUEUE ; 933res = vkWaitForFences (vkGPU -> device ,1 ,& vkGPU -> fence ,VK_TRUE ,100000000000 ); 934if (res != 0 )return VKFFT_ERROR_FAILED_TO_WAIT_FOR_FENCES ; 935 std::chrono::steady_clock::time_point timeEnd = std::chrono::steady_clock::now (); 936double totTime = std::chrono::duration_cast < std::chrono::microseconds > (timeEnd - timeSubmit ).count ()* 0.001 ; 937time_result [0 ]= totTime /num_iter ; 938res = vkResetFences (vkGPU -> device ,1 ,& vkGPU -> fence ); 939if (res != 0 )return VKFFT_ERROR_FAILED_TO_RESET_FENCES ; 940vkFreeCommandBuffers (vkGPU -> device ,vkGPU -> commandPool ,1 ,& commandBuffer ); 941#elif (VKFFT_BACKEND == 1 ) 942cudaError_t res = cudaSuccess ; 943 std::chrono::steady_clock::time_point timeSubmit = std::chrono::steady_clock::now (); 944for (uint64_t i = 0 ;i < num_iter ;i ++ ) { 945resFFT = VkFFTAppend (app ,-1 ,launchParams ); 946if (resFFT != VKFFT_SUCCESS )return resFFT ; 947resFFT = VkFFTAppend (app ,1 ,launchParams ); 948if (resFFT != VKFFT_SUCCESS )return resFFT ; 949 } 950res = cudaDeviceSynchronize (); 951if (res != cudaSuccess )return VKFFT_ERROR_FAILED_TO_SYNCHRONIZE ; 952 std::chrono::steady_clock::time_point timeEnd = std::chrono::steady_clock::now (); 953double totTime = std::chrono::duration_cast < std::chrono::microseconds > (timeEnd - timeSubmit ).count ()* 0.001 ; 954time_result [0 ]= totTime /num_iter ; 955#elif (VKFFT_BACKEND == 2 ) 956hipError_t res = hipSuccess ; 957 std::chrono::steady_clock::time_point timeSubmit = std::chrono::steady_clock::now (); 958for (uint64_t i = 0 ;i < num_iter ;i ++ ) { 959resFFT = VkFFTAppend (app ,-1 ,launchParams ); 960if (resFFT != VKFFT_SUCCESS )return resFFT ; 961resFFT = VkFFTAppend (app ,1 ,launchParams ); 962if (resFFT != VKFFT_SUCCESS )return resFFT ; 963 } 964res = hipDeviceSynchronize (); 965if (res != hipSuccess )return VKFFT_ERROR_FAILED_TO_SYNCHRONIZE ; 966 std::chrono::steady_clock::time_point timeEnd = std::chrono::steady_clock::now (); 967double totTime = std::chrono::duration_cast < std::chrono::microseconds > (timeEnd - timeSubmit ).count ()* 0.001 ; 968time_result [0 ]= totTime /num_iter ; 969#elif (VKFFT_BACKEND == 3 ) 970cl_int res = CL_SUCCESS ; 971launchParams -> commandQueue = & vkGPU -> commandQueue ; 972 std::chrono::steady_clock::time_point timeSubmit = std::chrono::steady_clock::now (); 973for (uint64_t i = 0 ;i < num_iter ;i ++ ) { 974resFFT = VkFFTAppend (app ,-1 ,launchParams ); 975if (resFFT != VKFFT_SUCCESS )return resFFT ; 976resFFT = VkFFTAppend (app ,1 ,launchParams ); 977if (resFFT != VKFFT_SUCCESS )return resFFT ; 978 } 979res = clFinish (vkGPU -> commandQueue ); 980if (res != CL_SUCCESS )return VKFFT_ERROR_FAILED_TO_SYNCHRONIZE ; 981 std::chrono::steady_clock::time_point timeEnd = std::chrono::steady_clock::now (); 982double totTime = std::chrono::duration_cast < std::chrono::microseconds > (timeEnd - timeSubmit ).count ()* 0.001 ; 983time_result [0 ]= totTime /num_iter ; 984#elif (VKFFT_BACKEND == 4 ) 985ze_result_t res = ZE_RESULT_SUCCESS ; 986ze_command_list_desc_t commandListDescription = {}; 987commandListDescription .stype = ZE_STRUCTURE_TYPE_COMMAND_LIST_DESC ; 988ze_command_list_handle_t commandList = {}; 989res = zeCommandListCreate (vkGPU -> context ,vkGPU -> device ,& commandListDescription ,& commandList ); 990if (res != ZE_RESULT_SUCCESS )return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_LIST ; 991 992launchParams -> commandList = & commandList ; 993for (uint64_t i = 0 ;i < num_iter ;i ++ ) { 994resFFT = VkFFTAppend (app ,-1 ,launchParams ); 995if (resFFT != VKFFT_SUCCESS )return resFFT ; 996resFFT = VkFFTAppend (app ,1 ,launchParams ); 997if (resFFT != VKFFT_SUCCESS )return resFFT ; 998 } 999res = zeCommandListClose (commandList ); 1000if (res != 0 )return VKFFT_ERROR_FAILED_TO_END_COMMAND_BUFFER ; 1001 1002 std::chrono::steady_clock::time_point timeSubmit = std::chrono::steady_clock::now (); 1003res = zeCommandQueueExecuteCommandLists (vkGPU -> commandQueue ,1 ,& commandList ,0 ); 1004if (res != 0 )return VKFFT_ERROR_FAILED_TO_SUBMIT_QUEUE ; 1005res = zeCommandQueueSynchronize (vkGPU -> commandQueue ,UINT32_MAX ); 1006if (res != 0 )return VKFFT_ERROR_FAILED_TO_WAIT_FOR_FENCES ; 1007 1008 std::chrono::steady_clock::time_point timeEnd = std::chrono::steady_clock::now (); 1009double totTime = std::chrono::duration_cast < std::chrono::microseconds > (timeEnd - timeSubmit ).count ()* 0.001 ; 1010time_result [0 ]= totTime /num_iter ; 1011res = zeCommandListDestroy (commandList ); 1012if (res != 0 )return VKFFT_ERROR_FAILED_TO_DESTROY_COMMAND_LIST ; 1013#elif (VKFFT_BACKEND == 5 ) 1014MTL ::CommandBuffer * commandBuffer = vkGPU -> queue -> commandBuffer (); 1015if (commandBuffer == 0 )return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_LIST ; 1016launchParams -> commandBuffer = commandBuffer ; 1017MTL ::ComputeCommandEncoder * commandEncoder = commandBuffer -> computeCommandEncoder (); 1018if (commandEncoder == 0 )return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_LIST ; 1019launchParams -> commandEncoder = commandEncoder ; 1020for (uint64_t i = 0 ;i < num_iter ;i ++ ) { 1021resFFT = VkFFTAppend (app ,-1 ,launchParams ); 1022if (resFFT != VKFFT_SUCCESS )return resFFT ; 1023resFFT = VkFFTAppend (app ,1 ,launchParams ); 1024if (resFFT != VKFFT_SUCCESS )return resFFT ; 1025 } 1026commandEncoder -> endEncoding (); 1027 1028 std::chrono::steady_clock::time_point timeSubmit = std::chrono::steady_clock::now (); 1029commandBuffer -> commit (); 1030commandBuffer -> waitUntilCompleted (); 1031 std::chrono::steady_clock::time_point timeEnd = std::chrono::steady_clock::now (); 1032double totTime = std::chrono::duration_cast < std::chrono::microseconds > (timeEnd - timeSubmit ).count ()* 0.001 ; 1033time_result [0 ]= totTime /num_iter ; 1034commandEncoder -> release (); 1035commandBuffer -> release (); 1036#endif 1037return resFFT ; 1038}