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