yum-mirror/VkFFT

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

Tolmachev DmitriiVkFFT v1.3.3 released6f7ded

develop
196.2 KiB8650 linesraw
1#LyX 2.3 created this file. For more info see http://www.lyx.org/
2\lyxformat 544
3\begin_document
4\begin_header
5\save_transient_properties true
6\origin unavailable
7\textclass article
8\begin_preamble
9\usepackage{sourcecodepro}
10\usepackage[parfill]{parskip}
11\usepackage{enumitem}
12\setlist[itemize]{leftmargin=*}
13\usepackage{minted}
14\usepackage{mdframed}
15\definecolor{bg}{rgb}{0.95,0.95,0.95}
16\usepackage{hyperref}
17\hypersetup{
18    colorlinks,
19    citecolor=black,
20    filecolor=black,
21    linkcolor=black,
22    urlcolor=black
23}
24\end_preamble
25\use_default_options true
26\maintain_unincluded_children false
27\language english
28\language_package default
29\inputencoding auto
30\fontencoding global
31\font_roman "default" "default"
32\font_sans "default" "default"
33\font_typewriter "default" "default"
34\font_math "auto" "auto"
35\font_default_family default
36\use_non_tex_fonts true
37\font_sc false
38\font_osf false
39\font_sf_scale 100 100
40\font_tt_scale 100 100
41\use_microtype false
42\use_dash_ligatures true
43\graphics default
44\default_output_format default
45\output_sync 0
46\bibtex_command default
47\index_command default
48\paperfontsize 12
49\spacing single
50\use_hyperref false
51\papersize default
52\use_geometry true
53\use_package amsmath 1
54\use_package amssymb 1
55\use_package cancel 1
56\use_package esint 1
57\use_package mathdots 1
58\use_package mathtools 1
59\use_package mhchem 1
60\use_package stackrel 1
61\use_package stmaryrd 1
62\use_package undertilde 1
63\cite_engine basic
64\cite_engine_type default
65\biblio_style plain
66\use_bibtopic false
67\use_indices false
68\paperorientation portrait
69\suppress_date false
70\justification true
71\use_refstyle 1
72\use_minted 0
73\index Index
74\shortcut idx
75\color #008000
76\end_index
77\leftmargin 2.5cm
78\topmargin 2.5cm
79\rightmargin 2.5cm
80\bottommargin 2.5cm
81\secnumdepth 3
82\tocdepth 3
83\paragraph_separation indent
84\paragraph_indentation default
85\is_math_indent 0
86\math_numbering_side default
87\quotes_style english
88\dynamic_quotes 0
89\papercolumns 1
90\papersides 1
91\paperpagestyle default
92\tracking_changes false
93\output_changes false
94\html_math_output 0
95\html_css_as_file 0
96\html_be_strict false
97\end_header
98
99\begin_body
100
101\begin_layout Standard
102\begin_inset ERT
103status open
104
105\begin_layout Plain Layout
106
107
108\backslash
109UseRawInputEncoding
110\end_layout
111
112\begin_layout Plain Layout
113
114
115\backslash
116begin{titlepage} 	
117\end_layout
118
119\begin_layout Plain Layout
120
121
122\backslash
123centering 	
124\end_layout
125
126\begin_layout Plain Layout
127
128
129\backslash
130vspace{1cm} 	
131\end_layout
132
133\begin_layout Plain Layout
134
135{
136\backslash
137scshape
138\backslash
139LARGE VkFFT - Vulkan/CUDA/HIP/OpenCL/Level Zero/Metal Fast Fourier Transform
140 library 
141\backslash
142par} 		
143\end_layout
144
145\begin_layout Plain Layout
146
147
148\backslash
149vspace{1.5cm} 	
150\end_layout
151
152\begin_layout Plain Layout
153
154{
155\backslash
156huge
157\backslash
158bfseries API guide with examples
159\backslash
160par} 	
161\end_layout
162
163\begin_layout Plain Layout
164
165
166\backslash
167vspace{2cm} 	
168\end_layout
169
170\begin_layout Plain Layout
171
172{
173\backslash
174Large Dmitrii Tolmachev
175\backslash
176par} 	
177\end_layout
178
179\begin_layout Plain Layout
180
181	
182\end_layout
183
184\begin_layout Plain Layout
185
186
187\backslash
188vspace{1cm} 	
189\end_layout
190
191\begin_layout Plain Layout
192
193{
194\backslash
195large January 2024, version 1.3.3
196\backslash
197par} 
198\end_layout
199
200\begin_layout Plain Layout
201
202
203\backslash
204end{titlepage}
205\end_layout
206
207\end_inset
208
209
210\end_layout
211
212\begin_layout Standard
213\begin_inset Newpage newpage
214\end_inset
215
216
217\end_layout
218
219\begin_layout Standard
220\begin_inset CommandInset toc
221LatexCommand tableofcontents
222
223\end_inset
224
225
226\end_layout
227
228\begin_layout Standard
229\begin_inset Newpage newpage
230\end_inset
231
232
233\end_layout
234
235\begin_layout Section
236Introduction
237\end_layout
238
239\begin_layout Standard
240This document describes VkFFT - Vulkan/CUDA/HIP/OpenCL/Level Zero/Metal
241 Fast Fourier Transform library.
242 It describes the features and current limitations of VkFFT, explains the
243 API and compares it to other FFT libraries (like FFTW and cuFFT) on the
244 set of examples.
245 It is by no means the final version, so if there is something unclear -
246 feel free to contact me (dtolm96@gmail.com), so I can update it.
247 
248\end_layout
249
250\begin_layout Standard
251\begin_inset Newpage newpage
252\end_inset
253
254
255\end_layout
256
257\begin_layout Section
258Using the VkFFT API
259\end_layout
260
261\begin_layout Standard
262This chapter will cover the basics of VkFFT.
263 Fourier transform of a sequence is called Discrete Fourier Transform (DFT).
264 It is defined by the following formula:
265\begin_inset Formula 
266\begin{equation}
267X_{k}=\stackrel[n=0]{N-1}{\sum}x_{n}e^{-\frac{2\pi i}{N}nk}=\mathrm{DFT}{}_{N}(x_{n},k),\label{eq:dft}
268\end{equation}
269
270\end_inset
271
272
273\end_layout
274
275\begin_layout Standard
276where 
277\begin_inset Formula $x_{n}$
278\end_inset
279
280is the input sequence, 
281\begin_inset Formula $N$
282\end_inset
283
284 is the length of the input sequence and 
285\begin_inset Formula $k\in[0,N-1],k\in\mathbb{Z}$
286\end_inset
287
288is the output index, corresponding to frequency in Fourier space.
289 Corresponding to that, inverse DFT is defined as following:
290\begin_inset Formula 
291\begin{equation}
292x_{n}=\stackrel[k=0]{\mathrm{N-1}}{\sum}X_{k}e^{\frac{2\pi i}{N}nk}=\mathrm{IDFT}{}_{N}(X_{k},n)
293\end{equation}
294
295\end_inset
296
297
298\end_layout
299
300\begin_layout Standard
301VkFFT follows the same definitions as FFTW and cuFFT - forward FFT has the
302 exponent sign 
303\begin_inset Formula $-1$
304\end_inset
305
306, while the inverse has the exponent sign 
307\begin_inset Formula $1$
308\end_inset
309
310.
311 Note, that inverse transform by default is unnormalized, so to get the
312 input sequence after FFT + iFFT, the user has to divide the result by 
313\begin_inset Formula $N$
314\end_inset
315
316.
317\end_layout
318
319\begin_layout Subsection
320Installing VkFFT
321\end_layout
322
323\begin_layout Standard
324VkFFT is distributed as a header-only library (strating from the version
325 1.3, it is no longer a single header).
326 The installation process consists of the following steps:
327\end_layout
328
329\begin_layout Enumerate
330\noindent
331\align left
332Copy vkFFT.h file and vkFFT directory into one of the directories included
333 in the user's project.
334\end_layout
335
336\begin_layout Enumerate
337\noindent
338Define VKFFT_BACKEND as a number corresponding to the API used in the user's
339 project: 0 - Vulkan, 1 - CUDA, 2 - HIP, 3 - OpenCL, 4 - Level Zero, 5 -
340 Metal.
341 Definition is done like:
342\begin_inset ERT
343status open
344
345\begin_layout Plain Layout
346
347
348\backslash
349begin{mdframed}[backgroundcolor=bg]
350\end_layout
351
352\begin_layout Plain Layout
353
354
355\backslash
356begin{minted}[tabsize=4,obeytabs,breaklines]{make}
357\end_layout
358
359\begin_layout Plain Layout
360
361-DVKFFT_BACKEND=X
362\end_layout
363
364\begin_layout Plain Layout
365
366
367\backslash
368end{minted}
369\end_layout
370
371\begin_layout Plain Layout
372
373
374\backslash
375end{mdframed}
376\end_layout
377
378\end_inset
379
380 in GCC or as 
381\begin_inset ERT
382status open
383
384\begin_layout Plain Layout
385
386
387\backslash
388begin{mdframed}[backgroundcolor=bg]
389\end_layout
390
391\begin_layout Plain Layout
392
393
394\backslash
395begin{minted}[tabsize=4,obeytabs,breaklines]{cmake}
396\end_layout
397
398\begin_layout Plain Layout
399
400set(VKFFT_BACKEND 1 CACHE STRING "0 - Vulkan, 1 - CUDA, 2 - HIP, 3 - OpenCL,
401 4 - Level Zero, 5 - Metal")
402\end_layout
403
404\begin_layout Plain Layout
405
406
407\backslash
408end{minted}
409\end_layout
410
411\begin_layout Plain Layout
412
413
414\backslash
415end{mdframed}
416\end_layout
417
418\end_inset
419
420in CMake.
421\end_layout
422
423\begin_layout Enumerate
424Define VKFFT_MAX_FFT_DIMENSIONS as the number of max dimensions to be supported
425 by VkFFT.
426 Default is 4.
427\end_layout
428
429\begin_layout Enumerate
430Depending on the API backend, the project must use additional libraries
431 for run-time compilation:
432\end_layout
433
434\begin_deeper
435\begin_layout Enumerate
436Vulkan API: SPIRV, glslang and Vulkan.
437 Define VK_API_VERSION to the available Vulkan version.
438 Sample CMakeLists can look like this:
439\begin_inset ERT
440status open
441
442\begin_layout Plain Layout
443
444
445\backslash
446begin{mdframed}[backgroundcolor=bg]
447\end_layout
448
449\begin_layout Plain Layout
450
451
452\backslash
453begin{minted}[tabsize=4,obeytabs,breaklines]{cmake}
454\end_layout
455
456\begin_layout Plain Layout
457
458find_package(Vulkan REQUIRED)
459\end_layout
460
461\begin_layout Plain Layout
462
463target_compile_definitions(${PROJECT_NAME} PUBLIC -DVK_API_VERSION=11)#10
464 - Vulkan 1.0, 11 - Vulkan 1.1, 12 - Vulkan 1.2 
465\end_layout
466
467\begin_layout Plain Layout
468
469target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/gl
470slang-main/glslang/Include/) 
471\end_layout
472
473\begin_layout Plain Layout
474
475add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/glslang-main)
476\end_layout
477
478\begin_layout Plain Layout
479
480\end_layout
481
482\begin_layout Plain Layout
483
484target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/vk
485FFT/)
486\end_layout
487
488\begin_layout Plain Layout
489
490add_library(VkFFT INTERFACE)
491\end_layout
492
493\begin_layout Plain Layout
494
495target_compile_definitions(VkFFT INTERFACE -DVKFFT_BACKEND=0)
496\end_layout
497
498\begin_layout Plain Layout
499
500\end_layout
501
502\begin_layout Plain Layout
503
504target_link_libraries(${PROJECT_NAME} PUBLIC SPIRV glslang Vulkan::Vulkan
505 VkFFT)
506\end_layout
507
508\begin_layout Plain Layout
509
510
511\backslash
512end{minted}
513\end_layout
514
515\begin_layout Plain Layout
516
517
518\backslash
519end{mdframed}
520\end_layout
521
522\end_inset
523
524
525\end_layout
526
527\begin_layout Enumerate
528CUDA API: CUDA and NVRTC.
529 Sample CMakeLists can look like this: 
530\begin_inset ERT
531status open
532
533\begin_layout Plain Layout
534
535
536\backslash
537begin{mdframed}[backgroundcolor=bg]
538\end_layout
539
540\begin_layout Plain Layout
541
542
543\backslash
544begin{minted}[tabsize=4,obeytabs,breaklines]{cmake}
545\end_layout
546
547\begin_layout Plain Layout
548
549find_package(CUDA 9.0 REQUIRED) 	
550\end_layout
551
552\begin_layout Plain Layout
553
554enable_language(CUDA) 	
555\end_layout
556
557\begin_layout Plain Layout
558
559set_property(TARGET ${PROJECT_NAME} PROPERTY CUDA_ARCHITECTURESs 60 70 75
560 80 86) 	
561\end_layout
562
563\begin_layout Plain Layout
564
565target_compile_options(${PROJECT_NAME} PUBLIC "$<$<COMPILE_LANGUAGE:CUDA>:SHELL:
566 	
567\end_layout
568
569\begin_layout Plain Layout
570
571	-DVKFFT_BACKEND=${VKFFT_BACKEND} 	
572\end_layout
573
574\begin_layout Plain Layout
575
576	-gencode arch=compute_60,code=compute_60
577\end_layout
578
579\begin_layout Plain Layout
580
581	-gencode arch=compute_70,code=compute_70
582\end_layout
583
584\begin_layout Plain Layout
585
586	-gencode arch=compute_75,code=compute_75
587\end_layout
588
589\begin_layout Plain Layout
590
591	-gencode arch=compute_80,code=compute_80
592\end_layout
593
594\begin_layout Plain Layout
595
596	-gencode arch=compute_86,code=compute_86>")
597\end_layout
598
599\begin_layout Plain Layout
600
601set_target_properties(${PROJECT_NAME} PROPERTIES CUDA_SEPARABLE_COMPILATION
602 ON)
603\end_layout
604
605\begin_layout Plain Layout
606
607set_target_properties(${PROJECT_NAME} PROPERTIES CUDA_RESOLVE_DEVICE_SYMBOLS
608 ON)
609\end_layout
610
611\begin_layout Plain Layout
612
613\end_layout
614
615\begin_layout Plain Layout
616
617find_library(CUDA_NVRTC_LIB libnvrtc nvrtc HINTS "${CUDA_TOOLKIT_ROOT_DIR}/lib64
618" "${LIBNVRTC_LIBRARY_DIR}" "${CUDA_TOOLKIT_ROOT_DIR}/lib/x64" /usr/lib64
619 /usr/local/cuda/lib64)
620\end_layout
621
622\begin_layout Plain Layout
623
624add_definitions(-DCUDA_TOOLKIT_ROOT_DIR="${CUDA_TOOLKIT_ROOT_DIR}")
625\end_layout
626
627\begin_layout Plain Layout
628
629\end_layout
630
631\begin_layout Plain Layout
632
633target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/vk
634FFT/)
635\end_layout
636
637\begin_layout Plain Layout
638
639add_library(VkFFT INTERFACE)
640\end_layout
641
642\begin_layout Plain Layout
643
644target_compile_definitions(VkFFT INTERFACE -DVKFFT_BACKEND=1)
645\end_layout
646
647\begin_layout Plain Layout
648
649\end_layout
650
651\begin_layout Plain Layout
652
653target_link_libraries(${PROJECT_NAME} PUBLIC ${CUDA_LIBRARIES} cuda ${CUDA_NVRTC
654_LIB} VkFFT)
655\end_layout
656
657\begin_layout Plain Layout
658
659
660\backslash
661end{minted}
662\end_layout
663
664\begin_layout Plain Layout
665
666
667\backslash
668end{mdframed}
669\end_layout
670
671\end_inset
672
673
674\end_layout
675
676\begin_layout Enumerate
677HIP API: HIP and HIPRTC.
678 Sample CMakeLists can look like this:
679\begin_inset ERT
680status open
681
682\begin_layout Plain Layout
683
684
685\backslash
686begin{mdframed}[backgroundcolor=bg]
687\end_layout
688
689\begin_layout Plain Layout
690
691
692\backslash
693begin{minted}[tabsize=4,obeytabs,breaklines]{cmake}
694\end_layout
695
696\begin_layout Plain Layout
697
698list(APPEND CMAKE_PREFIX_PATH /opt/rocm/hip /opt/rocm)
699\end_layout
700
701\begin_layout Plain Layout
702
703find_package(hip)
704\end_layout
705
706\begin_layout Plain Layout
707
708\end_layout
709
710\begin_layout Plain Layout
711
712target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/vk
713FFT/)
714\end_layout
715
716\begin_layout Plain Layout
717
718add_library(VkFFT INTERFACE)
719\end_layout
720
721\begin_layout Plain Layout
722
723target_compile_definitions(VkFFT INTERFACE -DVKFFT_BACKEND=2)
724\end_layout
725
726\begin_layout Plain Layout
727
728#target_compile_definitions(${PROJECT_NAME} PUBLIC -DVKFFT_OLD_ROCM) #ROCm
729 versions before 4.5 needed kernel include of hiprtc
730\end_layout
731
732\begin_layout Plain Layout
733
734\end_layout
735
736\begin_layout Plain Layout
737
738target_link_libraries(${PROJECT_NAME} PUBLIC hip::host VkFFT)
739\end_layout
740
741\begin_layout Plain Layout
742
743
744\backslash
745end{minted}
746\end_layout
747
748\begin_layout Plain Layout
749
750
751\backslash
752end{mdframed}
753\end_layout
754
755\end_inset
756
757
758\end_layout
759
760\begin_layout Enumerate
761OpenCL API: OpenCL.
762 Sample CMakeLists can look like this:
763\begin_inset ERT
764status open
765
766\begin_layout Plain Layout
767
768
769\backslash
770begin{mdframed}[backgroundcolor=bg]
771\end_layout
772
773\begin_layout Plain Layout
774
775
776\backslash
777begin{minted}[tabsize=4,obeytabs,breaklines]{cmake}
778\end_layout
779
780\begin_layout Plain Layout
781
782find_package(OpenCL REQUIRED)
783\end_layout
784
785\begin_layout Plain Layout
786
787\end_layout
788
789\begin_layout Plain Layout
790
791target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/vk
792FFT/)
793\end_layout
794
795\begin_layout Plain Layout
796
797add_library(VkFFT INTERFACE)
798\end_layout
799
800\begin_layout Plain Layout
801
802target_compile_definitions(VkFFT INTERFACE -DVKFFT_BACKEND=3)
803\end_layout
804
805\begin_layout Plain Layout
806
807\end_layout
808
809\begin_layout Plain Layout
810
811target_link_libraries(${PROJECT_NAME} PUBLIC OpenCL::OpenCL VkFFT)
812\end_layout
813
814\begin_layout Plain Layout
815
816
817\backslash
818end{minted}
819\end_layout
820
821\begin_layout Plain Layout
822
823
824\backslash
825end{mdframed}
826\end_layout
827
828\end_inset
829
830
831\end_layout
832
833\begin_layout Enumerate
834Level Zero API: Level Zero; Clang and llvm-spirv must be in the system path
835 (for kernel compilation).
836 Sample CMakeLists can look like this:
837\begin_inset ERT
838status open
839
840\begin_layout Plain Layout
841
842
843\backslash
844begin{mdframed}[backgroundcolor=bg]
845\end_layout
846
847\begin_layout Plain Layout
848
849
850\backslash
851begin{minted}[tabsize=4,obeytabs,breaklines]{cmake}
852\end_layout
853
854\begin_layout Plain Layout
855
856set(LevelZero_LIBRARY "/usr/lib/x86_64-linux-gnu/")
857\end_layout
858
859\begin_layout Plain Layout
860
861set(LevelZero_INCLUDE_DIR "/usr/include/")
862\end_layout
863
864\begin_layout Plain Layout
865
866find_library(
867\end_layout
868
869\begin_layout Plain Layout
870
871	LevelZero_LIB
872\end_layout
873
874\begin_layout Plain Layout
875
876	NAMES "ze_loader"
877\end_layout
878
879\begin_layout Plain Layout
880
881	PATHS ${LevelZero_LIBRARY}
882\end_layout
883
884\begin_layout Plain Layout
885
886	PATH_SUFFIXES "lib" "lib64"
887\end_layout
888
889\begin_layout Plain Layout
890
891	NO_DEFAULT_PATH
892\end_layout
893
894\begin_layout Plain Layout
895
896  )
897\end_layout
898
899\begin_layout Plain Layout
900
901find_path(
902\end_layout
903
904\begin_layout Plain Layout
905
906	LevelZero_INCLUDES
907\end_layout
908
909\begin_layout Plain Layout
910
911	NAMES "ze_api.h"
912\end_layout
913
914\begin_layout Plain Layout
915
916	PATHS ${LevelZero_INCLUDE_DIR}
917\end_layout
918
919\begin_layout Plain Layout
920
921	PATH_SUFFIXES "include" 
922\begin_inset Quotes eld
923\end_inset
924
925level_zero
926\begin_inset Quotes erd
927\end_inset
928
929
930\end_layout
931
932\begin_layout Plain Layout
933
934	NO_DEFAULT_PATH
935\end_layout
936
937\begin_layout Plain Layout
938
939  )
940\end_layout
941
942\begin_layout Plain Layout
943
944target_include_directories(${PROJECT_NAME} PUBLIC ${LevelZero_INCLUDES})
945\end_layout
946
947\begin_layout Plain Layout
948
949add_library(VkFFT INTERFACE)
950\end_layout
951
952\begin_layout Plain Layout
953
954target_compile_definitions(VkFFT INTERFACE -DVKFFT_BACKEND=4)
955\end_layout
956
957\begin_layout Plain Layout
958
959\end_layout
960
961\begin_layout Plain Layout
962
963target_link_libraries(${PROJECT_NAME} PUBLIC LevelZero VkFFT)
964\end_layout
965
966\begin_layout Plain Layout
967
968
969\backslash
970end{minted}
971\end_layout
972
973\begin_layout Plain Layout
974
975
976\backslash
977end{mdframed}
978\end_layout
979
980\end_inset
981
982
983\end_layout
984
985\begin_layout Enumerate
986Metal API: Metal.
987 Sample CMakeLists can look like this:
988\begin_inset ERT
989status open
990
991\begin_layout Plain Layout
992
993
994\backslash
995begin{mdframed}[backgroundcolor=bg]
996\end_layout
997
998\begin_layout Plain Layout
999
1000
1001\backslash
1002begin{minted}[tabsize=4,obeytabs,breaklines]{cmake}
1003\end_layout
1004
1005\begin_layout Plain Layout
1006
1007add_compile_options(-WMTL_IGNORE_WARNINGS)
1008\end_layout
1009
1010\begin_layout Plain Layout
1011
1012find_library(FOUNDATION_LIB Foundation REQUIRED)
1013\end_layout
1014
1015\begin_layout Plain Layout
1016
1017find_library(QUARTZ_CORE_LIB QuartzCore REQUIRED)	
1018\end_layout
1019
1020\begin_layout Plain Layout
1021
1022find_library(METAL_LIB Metal REQUIRED)
1023\end_layout
1024
1025\begin_layout Plain Layout
1026
1027target_include_directories(${PROJECT_NAME} PUBLIC "metal-cpp/")
1028\end_layout
1029
1030\begin_layout Plain Layout
1031
1032\end_layout
1033
1034\begin_layout Plain Layout
1035
1036target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/vk
1037FFT/)
1038\end_layout
1039
1040\begin_layout Plain Layout
1041
1042add_library(VkFFT INTERFACE)
1043\end_layout
1044
1045\begin_layout Plain Layout
1046
1047target_compile_definitions(VkFFT INTERFACE -DVKFFT_BACKEND=5)
1048\end_layout
1049
1050\begin_layout Plain Layout
1051
1052\end_layout
1053
1054\begin_layout Plain Layout
1055
1056target_link_libraries(${PROJECT_NAME} PUBLIC ${FOUNDATION_LIB} ${QUARTZ_CORE_LIB
1057} ${METAL_LIB} VkFFT)
1058\end_layout
1059
1060\begin_layout Plain Layout
1061
1062
1063\backslash
1064end{minted}
1065\end_layout
1066
1067\begin_layout Plain Layout
1068
1069
1070\backslash
1071end{mdframed}
1072\end_layout
1073
1074\end_inset
1075
1076
1077\end_layout
1078
1079\end_deeper
1080\begin_layout Subsection
1081Fourier Transform Setup
1082\end_layout
1083
1084\begin_layout Standard
1085VkFFT follows a plan structure like FFTW/cuFFT with a notable difference
1086 - there is a unified interface to all transforms.
1087 This means that there are no separate functions like fftPlan1D/fftPlan2D/fftPla
1088nMany/etc.
1089 The initialization is done through a single configuration struct - VkFFTConfigu
1090ration.
1091 Each parameter of it will be covered in detail in this document.
1092 Plans in VkFFT are called VkFFTApplication and they are created with a
1093 unified initializeVkFFT call.
1094 
1095\end_layout
1096
1097\begin_layout Standard
1098As the code is written in C, don't forget to zero-initialize used structs!
1099\end_layout
1100
1101\begin_layout Standard
1102During the initializeVkFFT(VkFFTApplication* app, VkFFTConfiguration inputLaunch
1103Configuration) call VkFFT performs kernel generation and compilation from
1104 scratch (kernel reuse may be added later).
1105 The overall process of initialization looks like this:
1106\end_layout
1107
1108\begin_layout Enumerate
1109Get device parameters, perform default initialization of internal copy of
1110 configuration struct inside the VkFFTApplication, then fill in user-defined
1111 parameters from inputLaunchConfiguration.
1112\begin_inset space ~
1113\end_inset
1114
1115VkFFTApplication is passed as a pointer, so initializeVkFFT modifies the
1116 user-provided application.
1117\end_layout
1118
1119\begin_layout Enumerate
1120By default, there are two internal FFT plans created - inverse and forward.
1121 Multidimensional FFT is done as a combination of 1D FFTs in each axis direction.
1122 For each axis, the VkFFTPlanAxis function is called.
1123\end_layout
1124
1125\begin_layout Enumerate
1126VkFFTPlanAxis configures parameters for each axis.
1127 It may perform additional memory allocations (see: memory allocated by
1128 VkFFT).
1129\end_layout
1130
1131\begin_layout Enumerate
1132shaderGenVkFFT generates corresponding to the axis code in a char buffer
1133 (each axis may require more than one kernel: see Four-step FFT, Bluestein's
1134 algorithm for FFT).
1135 
1136\end_layout
1137
1138\begin_layout Enumerate
1139Code is then compiled with the run-time compiler of the specified backend.
1140\end_layout
1141
1142\begin_layout Standard
1143Once the plan is no longer need, a call to the deleteVkFFT function frees
1144 all the allocated resources.
1145 There are no processes launched that continue to work outside of the VkFFT
1146 related function calls.
1147\end_layout
1148
1149\begin_layout Subsection
1150Fourier Transform types and their definitions
1151\end_layout
1152
1153\begin_layout Standard
1154VkFFT supports commonly used Complex to complex (C2C), real to complex (R2C),
1155 complex to real (C2R) transformations and real to real (R2R) Discrete Cosine/Si
1156ne Transformations of types I, II, III and IV.
1157 VkFFT uses the same definitions as FFTW, except for the multidimensional
1158 FFT axis ordering: in FFTW dimensions are ordered with the decrease in
1159 consecutive elements stride, while VkFFT does the opposite - the first
1160 axis is the non-strided axis (the one that has elements located consecutively
1161 in memory with no gaps, usually named as the X-axis).
1162 So, in FFTW dimensions are specified as ZYX and in VkFFT as XYZ.
1163 This felt more logical to me - no matter if there are 1, 2, 3 or more dimension
1164s, the user can always find the axis with the same stride at the same position.
1165 This choice doesn't require any modification in the user's data management
1166 - just provide the FFT dimensions in the reverse order to VkFFT.
1167 
1168\end_layout
1169
1170\begin_layout Standard
1171The 1.3 version of VkFFT supports arbitrary number of dimensions, defined
1172 as VKFFT_MAX_FFT_DIMENSIONS compile constant.
1173 VkFFT also supports two forms of batching: the number of coordinates and
1174 the number of systems.
1175 The choice of two distinct batching ways is made to support matrix-vector
1176 convolutions, where the kernel is presented as a matrix.
1177 Overall, the layout of VkFFT can be described as WHD+CN - width, height,
1178 depth, other dimensions, coordinate and number of systems (in order of
1179 increasing strides, starting with 1 for width).
1180 Often, the coordinate part of the layout is not used, so the main batching
1181 is done by specifying N.
1182\end_layout
1183
1184\begin_layout Standard
1185VkFFT assumes that complex numbers are stored consecutively in memory: RIRIRI...
1186 where R denotes the real part of the complex number and I denotes the imaginary
1187 part.
1188 There is no difference between using a float2/double2/half2 container or
1189 access memory as float/double/half/double-double as long as the byte order
1190 remains the same.
1191\end_layout
1192
1193\begin_layout Standard
1194This section and the next one will cover the basics of VkFFT data layouts
1195 and memory management.
1196 
1197\end_layout
1198
1199\begin_layout Subsubsection
1200C2C transforms
1201\end_layout
1202
1203\begin_layout Standard
1204The base FFT algorithm - C2C in VkFFT has the same definition as FFTW.
1205 Forward FFT has the exponent sign 
1206\begin_inset Formula $-1$
1207\end_inset
1208
1209, while the inverse has the exponent sign 
1210\begin_inset Formula $1$
1211\end_inset
1212
1213.
1214 By default, the inverse transform is unnormalized.
1215 
1216\begin_inset Formula $N_{x}N_{y}N_{z}$
1217\end_inset
1218
1219 complex numbers map to 
1220\begin_inset Formula $N_{x}N_{y}N_{z}$
1221\end_inset
1222
1223 complex numbers and no additional padding is required.
1224 The resulting data order will be the same as in FFTW/cuFFT, unless special
1225 parameters are provided in configuration (see: advanced memory management)
1226\end_layout
1227
1228\begin_layout Subsubsection
1229R2C/C2R transforms
1230\end_layout
1231
1232\begin_layout Standard
1233R2C/C2R transforms can be explained as C2C transforms with imaginary part
1234 set to zero.
1235 They exploit Hermitian symmetry of the result: 
1236\begin_inset Formula $X_{k}=X_{N-k}^{*}$
1237\end_inset
1238
1239 on the non-strided axis (the one that has elements located consecutively
1240 in memory with no gaps).
1241 This results in s reduction of required memory to store the complex result
1242 - we may only store 
1243\begin_inset Formula $floor(\frac{N_{x}}{2})+1$
1244\end_inset
1245
1246 complex numbers instead of 
1247\begin_inset Formula $N_{x}$
1248\end_inset
1249
1250.
1251 However, this results in memory requirements mismatch between input and
1252 output in R2C: 
1253\begin_inset Formula $floor(\frac{N_{x}}{2})+1$
1254\end_inset
1255
1256 complex elements will require 
1257\begin_inset Formula $N_{x}+2$
1258\end_inset
1259
1260 real numbers worth of memory for even 
1261\begin_inset Formula $N_{x}$
1262\end_inset
1263
1264 and 
1265\begin_inset Formula $N_{x}+1$
1266\end_inset
1267
1268 real numbers worth of memory for odd 
1269\begin_inset Formula $N_{x}$
1270\end_inset
1271
1272.
1273 For C2R the situation is reversed.
1274 There are two approaches to this problem: pad each sequence of the non-strided
1275 axis with zeros to the required length or use out-of-place mode.
1276 More information on how to do this will be given in the next section.
1277\end_layout
1278
1279\begin_layout Subsubsection
1280R2R (DCT) transforms
1281\end_layout
1282
1283\begin_layout Standard
1284R2R transforms in VkFFT are implemented in the form of Discrete cosine transform
1285s and Discrete sine transforms of types I, II, III and IV.
1286 Their definitions and transforms results match FFTW:
1287\end_layout
1288
1289\begin_layout Enumerate
1290DCT-I: 
1291\begin_inset Formula $X_{k}=x_{0}+(-1)^{k}x_{N-1}+2\stackrel[n=1]{N-2}{\sum}x_{n}cos(\frac{\pi}{N-1}nk)$
1292\end_inset
1293
1294, inverse of DCT-I (itself)
1295\end_layout
1296
1297\begin_layout Enumerate
1298DCT-II: 
1299\begin_inset Formula $X_{k}=2\stackrel[n=0]{N-1}{\sum}x_{n}cos(\frac{\pi}{N}(n+\frac{1}{2})k)$
1300\end_inset
1301
1302, inverse of DCT-III
1303\end_layout
1304
1305\begin_layout Enumerate
1306DCT-III: 
1307\begin_inset Formula $X_{k}=x_{0}+2\stackrel[n=1]{N-1}{\sum}x_{n}cos(\frac{\pi}{N}n(k+\frac{1}{2}))$
1308\end_inset
1309
1310, inverse of DCT-II
1311\end_layout
1312
1313\begin_layout Enumerate
1314DCT-IV: 
1315\begin_inset Formula $X_{k}=2\stackrel[n=0]{N-1}{\sum}x_{n}cos(\frac{\pi}{N}(n+\frac{1}{2})(k+\frac{1}{2}))$
1316\end_inset
1317
1318, inverse of DCT-IV (itself)
1319\end_layout
1320
1321\begin_layout Enumerate
1322DST-I: 
1323\begin_inset Formula $X_{k}=2\stackrel[n=0]{N-1}{\sum}x_{n}sin(\frac{\pi}{N+1}(n+1)(k+1))$
1324\end_inset
1325
1326, inverse of DST-I (itself)
1327\end_layout
1328
1329\begin_layout Enumerate
1330DST-II: 
1331\begin_inset Formula $X_{k}=2\stackrel[n=0]{N-1}{\sum}x_{n}sin(\frac{\pi}{N}(n+\frac{1}{2})(k+1))$
1332\end_inset
1333
1334, inverse of DST-III
1335\end_layout
1336
1337\begin_layout Enumerate
1338DST-III: 
1339\begin_inset Formula $X_{k}=(-1)^{k}x_{N-1}+2\stackrel[n=0]{N-2}{\sum}x_{n}sin(\frac{\pi}{N}(n+1)(k+\frac{1}{2}))$
1340\end_inset
1341
1342, inverse of DST-II
1343\end_layout
1344
1345\begin_layout Enumerate
1346DST-IV: 
1347\begin_inset Formula $X_{k}=2\stackrel[n=0]{N-1}{\sum}x_{n}sin(\frac{\pi}{N}(n+\frac{1}{2})(k+\frac{1}{2}))$
1348\end_inset
1349
1350, inverse of DST-IV (itself)
1351\end_layout
1352
1353\begin_layout Standard
1354R2R transforms are performed by redefinition of them to the C2C transforms
1355 (internal C2C sequence length can be different from the input R2R sequence
1356 length).
1357 R2R transform performs a one-to-one mapping between real numbers, so they
1358 don't require stride management, unlike R2C/C2R.
1359\end_layout
1360
1361\begin_layout Subsection
1362Memory management, data layouts for different transforms
1363\end_layout
1364
1365\begin_layout Subsubsection
1366VkFFT buffers
1367\end_layout
1368
1369\begin_layout Standard
1370VkFFT allows for explicit control over the data flow, which makes both in-place
1371 and out-of-place transforms possible.
1372 Buffers are passed to VkFFT as VkBuffer pointer in Vulkan, as double void
1373 pointers in CUDA/HIP/Level Zero, as cl_mem pointer in OpenCL and as MTL::Buffer
1374 pointer in Metal.
1375 This is done to maintain a uniform data pattern because some of the buffers
1376 can be allocated automatically.
1377 
1378\end_layout
1379
1380\begin_layout Standard
1381The main buffer is called buffer and it always has to be provided, either
1382 during the plan creation or when the plan is executed.
1383 All calculations are performed in this buffer and it is always overwritten.
1384 To do calculations out-of-place, VkFFT provides an option to specify inputBuffe
1385r/outputBuffer buffer.
1386 The logic behind their usage is fairly simple - the user specifies inputBuffer
1387 if the input data has to be read from a buffer, different from the main
1388 buffer.
1389 As the data is read only once and nothing is written back to the inputBuffer,
1390 this allows doing truly out-of-place transformations.
1391 The same logic applies to outputBuffer with the difference that it is responsib
1392le for the absolute last write of the VkFFT.
1393 It is possible to use all three buffers to create complex data management
1394 paths.
1395\end_layout
1396
1397\begin_layout Standard
1398It must be noted, that sometimes FFT can not be done inside one buffer (see:
1399 Four-Step FFT algorithm, Bluestein's algorithm).
1400 To compute FFT in these cases, there exists tempBuffer buffer and data
1401 is transferred between the main buffer and tempBuffer during the FFT execution.
1402 The ordering of transfers between the main buffer and tempBuffer is done
1403 in such a way, so the initial data read and final data write are obeying
1404 the configuration from the previous paragraph.
1405 Users can allocate tempBuffer themselves of some memory that does not have
1406 any useful information at the time of FFT execution (the tempBuffer size
1407 can depend on the configuration, so this is a rather advanced operation
1408 - read more in the advanced memory management section) or allow VkFFT to
1409 manage tempBuffer allocation itself (tempBuffer will be freed at the deleteVkFF
1410T call).
1411\end_layout
1412
1413\begin_layout Standard
1414To compute convolutions and cross-correlations, a kernel buffer has to be
1415 specified.
1416 It must have the same layout as the result of the FFT transform.
1417\end_layout
1418
1419\begin_layout Subsubsection
1420VkFFT buffers strides.
1421 A special case of R2C/C2R transforms
1422\end_layout
1423
1424\begin_layout Standard
1425To have better control of memory, the user can specify the strides between
1426 consecutive elements of different axes.
1427 The W (width) stride is fixed to be 1, so to achieve innermost batching,
1428 user needs to initialize an N+1 dimension FFT and omit the innermost dimension
1429 using omitDimension[0] = 1 parameter.
1430 N (number of systems) stride will be consecutive of C in memory if C is
1431 used, otherwise N will propagate the previous non-uniform stride multiplied
1432 by the corresponding axis length).
1433 Strides are specified not in bytes, but in the element type used - similar
1434 to the way how the user would access the corresponding element in the array.
1435 If all elements are consecutive in C2C, stride for H will be equal to the
1436 FFT length of W axis, stride for D will be multiplication of first two
1437 FFT axis lengths and so on, stride for C will be multiplication of all
1438 FFT axes lengths, etc.
1439 These are the default values of C2C and R2R strides if they are not explicitly
1440 specified.
1441\end_layout
1442
1443\begin_layout Standard
1444One of the main use-cases of strides comes to solve the R2C/C2R Hermitian
1445 symmetry H stride mismatch - for real space, it is equal to 
1446\begin_inset Formula $N_{x}$
1447\end_inset
1448
1449 real elements and for the frequency space it is equal to 
1450\begin_inset Formula $floor(\frac{N_{x}}{2})+1$
1451\end_inset
1452
1453 complex numbers.
1454 So, with strides it is possible to use a buffer, padded to 
1455\begin_inset Formula $2\cdot(floor(\frac{N_{x}}{2})+1)$
1456\end_inset
1457
1458 real elements in H stride (all elements between 
1459\begin_inset Formula $N_{x}$
1460\end_inset
1461
1462 and 
1463\begin_inset Formula $2\cdot(floor(\frac{N_{x}}{2})+1)$
1464\end_inset
1465
1466 will not be read so it does not matter what data is there before the write
1467 stage).
1468 All other strides are done as a multiplication between the previous stride
1469 and the number of elements in the previous axis.
1470 These are the default values of R2C/C2R strides if they are not explicitly
1471 specified.
1472\end_layout
1473
1474\begin_layout Standard
1475It is possible to specify separate sets of strides for all user-defined
1476 buffers: bufferStride for the main buffer, inputStride for input buffer,
1477 outputStride for output buffer (kernel stride is assumed to be the same
1478 as bufferStride, tempBuffer strides are configured automatically).
1479 
1480\end_layout
1481
1482\begin_layout Standard
1483For an out-of-place R2C FFT, there is no need to pad buffer with real numbers,
1484 but user must specify H stride there (as it differs to default one) - 
1485\begin_inset Formula $N_{x}$
1486\end_inset
1487
1488 real elements for real space and 
1489\begin_inset Formula $floor(\frac{N_{x}}{2})+1$
1490\end_inset
1491
1492 complex numbers for the frequency space.
1493 
1494\end_layout
1495
1496\begin_layout Standard
1497An out-of-place C2R FFT is a more tricky transform.
1498 In the multidimensional case, the main buffer will be written to and read
1499 from multiple times.
1500 The intermediate stores have a complex layout, which requires more space
1501 than the output real layout, so in order not to modify the input data,
1502 there exist two options.
1503 First, pad the real data layout has to 
1504\begin_inset Formula $2\cdot(floor(\frac{N_{x}}{2})+1)$
1505\end_inset
1506
1507 real elements in H stride (complex buffer will be used as inputBuffer,
1508 real buffer as buffer).
1509 Second, use the third buffer, so both input and output buffers have their
1510 original layouts (complex buffer will be used as inputBuffer, the main
1511 buffer for calculations is buffer and output real buffer as outputBuffer).
1512 If you use inverseReturnToInputBuffer option, where R2C is configured to
1513 read from input buffer and C2R is configured to write to the input buffer;
1514 C2R will modify the buffer it reads from in some cases (see issue 
1515\begin_inset CommandInset href
1516LatexCommand href
1517name "#58"
1518target "https://github.com/DTolm/VkFFT/issues/58#issuecomment-1007205682"
1519literal "false"
1520
1521\end_inset
1522
1523)
1524\end_layout
1525
1526\begin_layout Standard
1527By default, R2C/C2R will assume the complex-padded real strides in the in-place
1528 mode and non-padded real strides in out-of-place mode.
1529\end_layout
1530
1531\begin_layout Subsection
1532VkFFT algorithms
1533\end_layout
1534
1535\begin_layout Standard
1536VkFFT implements a wide range of algorithms to compute different types of
1537 FFTs but all of them can be reduced to a mixed-radix Cooley-Tukey FFT algorithm
1538 in the Stockham autosort form.
1539 The main idea behind it is to decompose the sequence as a set of primes,
1540 for each of which FFT can be written down exactly.
1541 As of now, VkFFT has radix implementations for primes up to 13, so all
1542 C2C sequences decomposable into a multiplication of such primes will be
1543 done purely with the Stockham algorithm.
1544 Below additional algorithms and their use-cases are described.
1545\end_layout
1546
1547\begin_layout Subsubsection
1548Bluestein's algorithm
1549\end_layout
1550
1551\begin_layout Standard
1552A complex algorithm that is used in cases where the sequence is not decomposable
1553 with implemented radix butterflies (currently - primes up to 13).
1554 It is derived by replacing 
1555\begin_inset Formula $nk=\left(n^{2}+k^{2}-(n-k)^{2}\right)/2$
1556\end_inset
1557
1558 in 
1559\begin_inset CommandInset ref
1560LatexCommand ref
1561reference "eq:dft"
1562plural "false"
1563caps "false"
1564noprefix "false"
1565
1566\end_inset
1567
1568:
1569\end_layout
1570
1571\begin_layout Standard
1572\begin_inset Formula 
1573\begin{align}
1574X_{k} & =\left(e^{-\pi i\frac{k^{2}}{N}}\right)\stackrel[n=0]{N-1}{\sum}\left(x_{n}e^{-\pi i\frac{n^{2}}{N}}\right)\left(e^{\pi i\frac{\left(k-n\right)^{2}}{N}}\right)=b_{k}^{\ast}\stackrel[n=0]{N-1}{\sum}a_{n}b_{k-n}\label{eq:dft-1}\\
1575a_{n} & =x_{n}b_{n}^{\ast}\\
1576b_{n} & =e^{\pi i\frac{n^{2}}{N}}
1577\end{align}
1578
1579\end_inset
1580
1581
1582\end_layout
1583
1584\begin_layout Standard
1585Here FFT is represented as a convolution between two sequences: 
1586\begin_inset Formula $a_{n}$
1587\end_inset
1588
1589 and 
1590\begin_inset Formula $b_{n}$
1591\end_inset
1592
1593, which can be performed by the means of convolution theorem:
1594\end_layout
1595
1596\begin_layout Standard
1597\begin_inset Formula 
1598\begin{equation}
1599F\{a\ast b\}=F\{a\}\cdot F\{b\}
1600\end{equation}
1601
1602\end_inset
1603
1604
1605\end_layout
1606
1607\begin_layout Standard
1608By padding 
1609\begin_inset Formula $a_{n}$
1610\end_inset
1611
1612 and 
1613\begin_inset Formula $b_{n}$
1614\end_inset
1615
1616 to a sequence length decomposable with implemented radix butterflies with
1617 a size of at least 
1618\begin_inset Formula $2N-1$
1619\end_inset
1620
1621 (because the length of 
1622\begin_inset Formula $b_{n}$
1623\end_inset
1624
1625 is 
1626\begin_inset Formula $2N-1$
1627\end_inset
1628
1629), we can perform FFT of any length.
1630 FFT of 
1631\begin_inset Formula $b_{n}$
1632\end_inset
1633
1634 can be precomputed, so overall this algorithm requires at least 4x the
1635 computations and more memory transfers.
1636 This algorithm can be combined with all other algorithms implemented in
1637 VkFFT.
1638 If an FFT can not be done in a single upload, a tempBuffer has to be allocated
1639 (because the logical FFT buffer size is bigger than the original system).
1640\end_layout
1641
1642\begin_layout Subsubsection
1643The Four-Step FFT algorithm
1644\end_layout
1645
1646\begin_layout Standard
1647GPUs and CPUs have a hierarchical memory model - the closer memory to the
1648 unit that performs the computations, the faster its speed and the lower
1649 the size.
1650 So it is advantageous to split FFTs, not to the lowest primes, but to some
1651 bigger multiplication of those primes, then upload this subsequence to
1652 the closest cache level to the cores and do the final prime split there.
1653 The absolute lowest level is the register file, however, it does not allow
1654 for thread communications outside the warp.
1655 For this purpose, modern GPUs employ shared memory - a fast memory with
1656 a bank structure that is visible to all threads in a thread block.
1657 The usual sizes of it change on a scale from 16KB to 192KB and it is often
1658 beneficial to use it fully.
1659 However, if the full sequence can not fit inside the shared memory, FFT
1660 has to be done in multiple uploads - with the Four Step FFT algorithm.
1661 The main idea behind it is to represent a big 1D sequence as a 2D (or 3D
1662 for the three-upload scheme) FFT - we first do FFT along the columns, then
1663 the rows, then transpose the result and multiply by a special set of phase
1664 vectors.
1665 Similar decomposition idea as the main Cooley-Tukey algorithm.
1666 However, performing transpositions in-place is a complicated task - especially
1667 for a non-trivial ratio between dimensions.
1668 It will also require an additional read/write stage, as it can not be merged
1669 with the last write of the FFT algorithm.
1670 The easiest and the most performant solution is to use a tempBuffer (it
1671 is the main reason for having this functionality, actually) and store intermedi
1672ate FFT results out-of-place.
1673 This way the last transposition step can be merged with the write step,
1674 as we can overwrite the output buffer without losing data.
1675\end_layout
1676
1677\begin_layout Standard
1678To estimate if your sequence size is single upload or not, divide the amount
1679 of available shared memory (48KB - Nvidia GPUs with Vulkan/OpenCL API,
1680 64KB - AMD GPUs, 100KB - Nvidia GPUs in CUDA API) by the complex size used
1681 for calculations (4 byte - half precision, 8 byte - single precision, 16
1682 byte - double precision, 32 byte - double-double).
1683 For 64KB of shared memory, we get 8192 as max single upload single-precision
1684 non-strided FFT, 4096 for double precision.
1685 For strided axes (H and D parts of the layout) these numbers have to be
1686 divided by 4 and 2 respectively to achieve coalescing, resulting in 2048
1687 length for single upload in both precisions.
1688 For more information on coalescing see: coalescing API reference.
1689\end_layout
1690
1691\begin_layout Standard
1692In the case of the Four-Step FFT algorithm, tempBuffer size has to be at
1693 least the same as the default main buffer size.
1694 It does not matter how many uploads are in the Four Step FFT algorithm
1695 - only a single tempBuffer is required.
1696 In this document, all systems that can fit in the shared memory entirely
1697 and be done without the Four Step FFT algorithm (and multiple uploads)
1698 are called single upload systems.
1699\end_layout
1700
1701\begin_layout Standard
1702If the last transposition is not required (the output data is allowed to
1703 be in not unshuffled form) it can be disabled during the configuration
1704 phase.
1705 This way tempBuffer will not be needed and all computations will be done
1706 in-place (unless Bluestein's algorithm is used).
1707 An example use-case of this is convolutions - if the kernel is computed
1708 with the same operation ordering, point-wise multiplication in the frequency
1709 domain is not dependent on the correct data ordering and the inverse FFT
1710 will restore the original layout.
1711\end_layout
1712
1713\begin_layout Subsubsection
1714R2C/C2R FFTs
1715\end_layout
1716
1717\begin_layout Standard
1718A typical approach to a single upload R2C/C2R system is to just set the
1719 imaginary part to zero inside the shared memory and do a simple C2C transform.
1720 This doesn't affect the amount of memory transferred from VRAM and is not
1721 a bad approach as FFT is a memory-bound algorithm, however, this can be
1722 improved in multidimensional (in HDCN part of the layout) case by the compositi
1723on of a single C2C sequence from two real sequences and some write for R2C/read
1724 for C2R post-processing.
1725 Both of these algorithms are implemented in VkFFT.
1726 Note, that R2C/C2R only affects the non-strided axis (W).
1727 All strided axes are still done as C2C.
1728\end_layout
1729
1730\begin_layout Subsubsection
1731R2C/C2R multi-upload FFT algorithm
1732\end_layout
1733
1734\begin_layout Standard
1735For even sequences there exists an easy mapping between R2C/C2R FFTs and
1736 the C2C of half the size.
1737 In this case, all even indices (starting from 0) are read as the real values
1738 of a complex number and all odd indices are read as the imaginary values.
1739 This C2C sequence can be done with the help of the Four-Step FFT algorithm.
1740 When FFT is done, separate post-processing for R2C/pre-processing for C2R
1741 is applied.
1742\end_layout
1743
1744\begin_layout Standard
1745VkFFt also implements a general R2C/C2R algorithm that computes R2C as a
1746 C2C of the same length with imaginary part set to zero.
1747 The memory layout of it is optimized to reduce memory footprint.
1748\end_layout
1749
1750\begin_layout Subsubsection
1751R2R Discrete Cosine/Sine Transforms
1752\end_layout
1753
1754\begin_layout Standard
1755There exist many different mappings between DCT and FFT.
1756 DSTs are reformulated as DCTs inside the VkFFT, so they use the same algorithms.
1757 As of now, VkFFT has the following algorithms implemented (both single
1758 and multiple uploads):
1759\end_layout
1760
1761\begin_layout Itemize
1762DCT-I - mapping between R2R and C2C of the 
1763\begin_inset Formula $2N-2$
1764\end_inset
1765
1766 length.
1767 For non-strided axis can use an optimization similar to the R2C/C2R multidimens
1768ional case (setting the imaginary part to the next FFT sequence).
1769\end_layout
1770
1771\begin_layout Itemize
1772DCT-II/DCT-III - mapping between R2R and C2C of the same length.
1773 For non-strided axis can use an optimization similar to the R2C/C2R multidimens
1774ional case (setting the imaginary part to the next FFT sequence).
1775\end_layout
1776
1777\begin_layout Itemize
1778DCT-IV - for even sizes, mapping between R2R and C2C sequence of half-length.
1779 For odd sizes mapping to the FFT of the same length (for non-strided axis
1780 can use an optimization similar to the R2C/C2R multidimensional case (setting
1781 the imaginary part to the next FFT sequence)).
1782\end_layout
1783
1784\begin_layout Standard
1785The single upload versions (that can fit in shared memory) of these algorithms
1786 have all mappings done in shared memory of the compute unit.
1787 For multiple upload sequence sizes, special callback versions of these
1788 algorithms are created that work similar to callbacks in CUDA (though more
1789 sophisticated as these algorithms can use multiple input values).
1790 The callback functionality has not been yet exposed to the user for general
1791 applications and its design is open to discussion.
1792\end_layout
1793
1794\begin_layout Subsubsection
1795Register overutilization
1796\end_layout
1797
1798\begin_layout Standard
1799Not an FFT algorithm by itself, but an optimization to do bigger sequences
1800 in a single upload instead of switching to the Four Step FFT algorithm.
1801 The main idea behind it is to use a register file (which is often bigger
1802 than the amount of shared memory) to store the sequence and use shared
1803 memory only as a communication buffer.
1804 This is useful in Vulkan and OpenCL APIs on Nvidia GPU, as they are only
1805 allowed to allocate 48KB of shared memory with a register file having the
1806 size of 256KB.
1807\end_layout
1808
1809\begin_layout Subsubsection
1810Zero padding
1811\end_layout
1812
1813\begin_layout Standard
1814Not an FFT algorithm by itself, but a memory management optimization.
1815 If the user's system has parts that are known to be zero - for example,
1816 when an open system is modeled, to avoid a circular part of the FFT system
1817 has to be padded with zeros up to 2x in each direction.
1818 VkFFT can omit sequences full of zeros and don't perform the corresponding
1819 memory transfers and computations, as the output result will be zero.
1820 This way it is possible to get up to two times speed increase in the 2D
1821 case and up to 3x increase in the 3D case.
1822 
1823\end_layout
1824
1825\begin_layout Subsubsection
1826Convolution and cross-correlation support
1827\end_layout
1828
1829\begin_layout Standard
1830With the help of the Convolution theorem, which states that the Fourier
1831 transform of a convolution is the pointwise product of signals Fourier
1832 transforms, it is possible to perform convolution with 
1833\begin_inset Formula $NlogN$
1834\end_inset
1835
1836 complexity, compared to 
1837\begin_inset Formula $N^{2}$
1838\end_inset
1839
1840 complexity of the simple multiplication approach.
1841 This is extremely useful for kernels spanning more than 50 elements in
1842 size.
1843 VkFFT can merge the last step FFT, kernel multiplication in the Fourier
1844 domain and the first step of inverse FFT to provide substantial memory
1845 transfer savings.
1846 Moreover, FFTs of big sequences can be performed without data reordering,
1847 which results in a better locality.
1848 
1849\end_layout
1850
1851\begin_layout Subsection
1852VkFFT accuracy
1853\end_layout
1854
1855\begin_layout Standard
1856To measure how VkFFT (single/double/half/double-double precision) results
1857 compare to cuFFT/rocFFT (single/double/half precision) and FFTW (double/quad
1858 precision), multiple sets of systems covering full supported C2C/R2C+C2R/R2R
1859 FFT range are filled with random complex data on the scale of [-1,1] and
1860 one transform was performed on each system.
1861 Samples 11(single), 12(double), 13(half), 14(non-power of 2 C2C, single),
1862 15(R2C+C2R, single), 16(DCT-I/II/III/IV, single), 17(DCT-I/II/III/IV, double),
1863 18(non-power of 2 C2C, double), 19(double-double emulation of quad precision,
1864 C2C) are available in VkFFT Benchmark Suite to perform VkFFT verification
1865 on any of the target platforms.
1866 Overall, the Cooley-Tukey algorithm (Stockham autosort) exhibits logarithmic
1867 relative error scaling, similar to those of other GPU FFT libraries.
1868 Typically, the more computationally expensive algorithm is - the worse
1869 its precision is.
1870 So, Bluestein's algorithm has lower accuracy than Stockham autosort algorithm.
1871\end_layout
1872
1873\begin_layout Standard
1874Single precision in VkFFT supports two modes of calculation - by using the
1875 on-chip Special Function Units that can compute sines and cosines on the
1876 go or by using the precomputed on CPU look-up tables.
1877 For Nvidia and AMD GPUs, SFU provide great precision, while Intel iGPUs
1878 and mobile GPUs must use LUT to perform FFTs correctly.
1879\end_layout
1880
1881\begin_layout Standard
1882Double precision in VkFFT also supports two modes of calculation - by using
1883 polynomial sincos approximation and computing them on-chip or by using
1884 precomputed LUT as well.
1885 The second option is the better one, as polynomial sincos approximation
1886 is too compute-heavy for modern GPUs.
1887 It is selected by default on all devices.
1888\end_layout
1889
1890\begin_layout Standard
1891Half precision is supported in all backends.
1892 Half precision is implemented only as a memory trick - all on-chip computations
1893 are done in single precision.
1894 Half precision can use SFU or LUT as well.
1895\end_layout
1896
1897\begin_layout Standard
1898Double-double emulation of quad precision uses precomputed on CPU in quad
1899 precision twiddle factors and implements only additions and multiplications
1900 on GPU (for now).
1901\end_layout
1902
1903\begin_layout Standard
1904VkFFT also supports mixed-precision operations, where memory storing is
1905 done at lower precision, compared to the on-chip calculations.
1906 For example, it is possible to read data in single precision, do calculations
1907 in double and store data back in single precision.
1908 
1909\end_layout
1910
1911\begin_layout Subsection
1912VkFFT additional memory allocations
1913\end_layout
1914
1915\begin_layout Standard
1916In this section, all GPU memory allocations that are done by VkFFT are described.
1917 There are up to three situations when VkFFT allocates memory.
1918 All of the VkFFT allocated memory is freed at the deleteVkFFT call.
1919\end_layout
1920
1921\begin_layout Subsubsection
1922LUT allocations
1923\end_layout
1924
1925\begin_layout Standard
1926This memory is used to store precomputed twiddle factors and phase vectors
1927 used during the computation.
1928 This buffer can have:
1929\end_layout
1930
1931\begin_layout Itemize
1932twiddle factors for each radix stage of Stockham FFT calculation
1933\end_layout
1934
1935\begin_layout Itemize
1936phase vectors used in the Four Step FFT algorithm between stages
1937\end_layout
1938
1939\begin_layout Itemize
1940phase vectors used in DCT/DST-II/III/IV to perform a mapping between R2R
1941 and C2C
1942\end_layout
1943
1944\begin_layout Itemize
1945phase vectors used in post-processing for R2C/pre-processing for C2R for
1946 even length sequences as C2C of half size
1947\end_layout
1948
1949\begin_layout Standard
1950VkFFT manages LUT allocations by itself and they are performed during the
1951 initializeVkFFT call.
1952 LUT are allocated per axis, though some of them can be reused if the axes
1953 have the same LUT.
1954 Inverse and forward FFT plans share the same LUT (conjugation is performed
1955 on-chip).
1956\end_layout
1957
1958\begin_layout Subsubsection
1959The Four-Step FFT algorithm - tempBuffer allocation
1960\end_layout
1961
1962\begin_layout Standard
1963To perform the merging of the transposition with the last upload of an axis,
1964 VkFFT requires additional memory to mimic an out-of-place execution.
1965 This memory is located in tempBuffer and has to be of at least the same
1966 size as the main buffer.
1967 It is possible for the users to allocate it themselves, though if this
1968 is not done, VkFFT can do the allocation automatically (the size of the
1969 tempBuffer will be the same as the main buffer, unless the logical dimensions
1970 of FFT are bigger than user-defined - then, it will allocate the system
1971 with the minimal size, that can cover maximal logical system size used
1972 in any of the axes - see next subsection).
1973\end_layout
1974
1975\begin_layout Subsubsection
1976Bluestein's buffers allocation
1977\end_layout
1978
1979\begin_layout Standard
1980To do Bluestein's FFT algorithm, precomputed sequences 
1981\begin_inset Formula $b_{n}=e^{\pi i\frac{n^{2}}{N}}$
1982\end_inset
1983
1984, 
1985\begin_inset Formula $FFT(b_{n})$
1986\end_inset
1987
1988 and 
1989\begin_inset Formula $iFFT(b_{n})$
1990\end_inset
1991
1992 are required.
1993 For each axis, they can be different and are computed separately (unless
1994 VkFFT can determine that they match, then the buffers are allocated only
1995 once).
1996 Notably, as Bluestein's algorithm pads the sequence length to at least
1997 
1998\begin_inset Formula $2N-1$
1999\end_inset
2000
2001, if it can not be done in a single upload and the Four Step algorithm has
2002 to be used, the intermediate storage required will be bigger than the main
2003 buffer size.
2004 In this case, tempBuffer must always be allocated.
2005 As the padded sequence can be different for each of the dimensions, the
2006 required size of the tempBuffer will also vary.
2007 VkFFT determines the biggest size needed among axes and allocated tempBuffer
2008 of this size.
2009\end_layout
2010
2011\begin_layout Subsection
2012VkFFT support for double-double emulation of quad precision
2013\end_layout
2014
2015\begin_layout Standard
2016Since VkFFT 1.3.2 experimental support for double-double emulation of quad
2017 precision has been added.
2018 Double-double number is defined as an unevaluated sum of two double numbers,
2019 second one being on the order of ~1 ULP of the first one (like 1 and 1e-16).
2020 This boosts the significand from 53 to 106 bits and leaves the exponent
2021 the same (11bits).
2022 For example, true quad precision would have 15 bits of exponent and 113
2023 bits significand.
2024 The range of double-double stays the same as in double precision (1e308
2025 vs 1e4932), while precision boosts from ~1e-16 to ~1e-32 (vs ~1e-34 of
2026 true quad precision).
2027 The double-double format of VkFFT is equivalent to __ibm128 type in gcc.
2028 VkFFT uses quadmath library to precompute twiddle factors and initialize
2029 kernels for double-double in the true quad precision.
2030 Currently, conversion between quad and double-double is only possible on
2031 CPU in true quad (GPU can only do operations on data in double-double format).
2032 This will be changed later.
2033\end_layout
2034
2035\begin_layout Standard
2036To enable double-double support, link against quadmath and set VkFFT_use_FP128_d
2037ouble_double compile flag to true.
2038\end_layout
2039
2040\begin_layout Standard
2041The performance impact is rather harsh - the code becomes compute-bound
2042 even on modern HPC clusters.
2043 The simple radix algorithms work well and are usable (~2x impact compared
2044 to double precision), while Bluestein and big primes Rader algorithms incur
2045 a high toll on operations count.
2046 This can be improved in the future, but probably not to the extent of being
2047 VRAM bandwidth-bound on modern accelerators.
2048\end_layout
2049
2050\begin_layout Standard
2051The main usage for the double-double precision should be mixed-precision
2052 calculations, where most of the time is spent in regular FP64 and only
2053 some parts that hit precision boundaries are calculated in double-double.
2054 For example, in VkFFT it is possible to perform a double precision FFT
2055 with all on-chip calculations done in double-double.
2056 This way the final errors should be on the scale of 1 ULP.
2057\end_layout
2058
2059\begin_layout Standard
2060
2061\end_layout
2062
2063\begin_layout Standard
2064\begin_inset Newpage newpage
2065\end_inset
2066
2067
2068\end_layout
2069
2070\begin_layout Section
2071Runtime code optimization platform
2072\begin_inset CommandInset label
2073LatexCommand label
2074name "sec:Modern-GPU-architecture."
2075
2076\end_inset
2077
2078
2079\end_layout
2080
2081\begin_layout Subsection
2082Platform for GPU code generation
2083\end_layout
2084
2085\begin_layout Standard
2086While GPUs show extraordinary performance, they are harder to program for
2087 compared to regular CPUs.
2088 Firstly, the algorithms must be optimized for SIMT (single instruction,
2089 multiple threads) execution, which is the soul of the GPU model.
2090 Secondly, rapid GPU development makes all vendor architectures (Nvidia,
2091 AMD, Intel) largely different.
2092 Below we will list some examples:
2093\end_layout
2094
2095\begin_layout Itemize
2096Shared memory size.
2097 If your code uses the full 64KB of shared memory on AMD MI250X, it won't
2098 be optimal on Nvidia H100 which has 256KB of it.
2099 The same goes for L2/L3 cache size.
2100\end_layout
2101
2102\begin_layout Itemize
2103Warp size.
2104 If your code uses 32 core warps (usual on Nvidia), it will not work or
2105 work inefficiently for 64 core warps of AMD CDNA.
2106\end_layout
2107
2108\begin_layout Itemize
2109Coalesced memory.
2110 For Nvidia and AMD we have to coalesce 32-byte memory requests, for Intel,
2111 it is equal to 64 bytes.
2112 Multiple of these requests are then combined into 128-byte transactions
2113 to the chip.
2114 However, this is a big simplification.
2115 There exist undocumented issues for Nvidia and AMD, when bandwidth drops
2116 when code tries to do distant, but coalesced memory accesses, i.e.
2117 data are still grouped in 32-byte transactions but target addresses with
2118 > 2^18 bytes between them (and the bigger the distance - the bigger the
2119 drop).
2120 The load-store unit (LSU) can not group 32-byte transactions.
2121 It is possible to regain full bandwidth by switching to 128-byte memory
2122 coalescing on Nvidia, while on AMD memory management follows different
2123 rules and these requests just happen to hit the same physical memory pin
2124 and thus be serialized.
2125 All this information is usually never shared by vendors, so programmers
2126 have to find solutions by trial and error.
2127\end_layout
2128
2129\begin_layout Itemize
2130Compute unit composition.
2131 Some compute units have special function units that can evaluate single
2132 precision sines and cosines in one cycle (AMD and Nvidia).
2133 On Intel GPUs, they are often imprecise.
2134 The ratio between FP32 and FP64 units also imposes limitations on the algorithm
2135 - compute units with low FP64 core count will benefit from data precomputation
2136 in the lookup tables more.
2137 Some compute units have tensor cores for accelerated matrix products.
2138\end_layout
2139
2140\begin_layout Itemize
2141There are many other nuanced differences (like the number of supported by
2142 hardware queues/streams, support for CUDA MPS execution model, register
2143 spilling control) which result in some complicated kernels being unpredictable
2144 in performance before you try.
2145 So having an option to tweak some of its parameters loosely related to
2146 hardware is a huge benefit.
2147 
2148\end_layout
2149
2150\begin_layout Standard
2151This brings us to a big obstacle: all vendors have their own computing platforms.
2152 CUDA for Nvidia, HIP for AMD, Level Zero for Intel, Metal for Apple.
2153 To facilitate the development of code for all these different in details
2154 but similar in SIMD nature GPUs, I used all the knowledge obtained via
2155 numerous experiments with VkFFT to generalize GPU programming as much as
2156 possible - and create a unified platform for GPU code generation.
2157 
2158\end_layout
2159
2160\begin_layout Subsection
2161Platform structure
2162\end_layout
2163
2164\begin_layout Standard
2165The project structure is split into four main parts:
2166\end_layout
2167
2168\begin_layout Itemize
2169Application manager.
2170 We use a container-based model of management - the user fills out the configura
2171tion struct and then initializes the application with only one initializer
2172 function.
2173 So this part of the platform performs initial configuration management,
2174 pass of the parameters to the corresponding to the particular subprogram
2175 plan initializer, binary load/store for future reuse and resources deallocation.
2176 Here we have application dispatch handlers, which abstract the actual applicati
2177on-dependent code dispatch handlers in the same way as we have one function
2178 for initialization.
2179\end_layout
2180
2181\begin_layout Itemize
2182Plan manager.
2183 After configuration propagation, the plan manager performs extensive configurat
2184ion of parameters for a particular task code generation.
2185 It also performs general API-dependent parameter initialization for supported
2186 backends.
2187 The plan manager also performs code compilation using supported by the
2188 target API runtime compiler (NVRTC by Nvidia CUDA, HIPRTC by AMD HIP, glslang
2189 by Vulkan, native OpenCL, clang and llvm-spirv for Intel Level Zero).
2190 It manages additional memory allocations and backend-specific memory management.
2191 Finally, it has plan-specific dispatch routines and a plan resource deallocatio
2192n manager.
2193\end_layout
2194
2195\begin_layout Itemize
2196Code manager.
2197 This part of the platform is solely responsible for GPU code generation.
2198 It takes a special input configuration structure created from user configuratio
2199n and API-derived parameters and produces a char array containing code to
2200 be executed.
2201 The code manager has a block structure that developers can use.
2202 This allows reusing parts of code between kernels.
2203 The block structure has the following designations:
2204\end_layout
2205
2206\begin_deeper
2207\begin_layout Itemize
2208Level 2 kernels: problem-specific kernels and layout configuration.
2209 These functions are called by the plan manager and they are intended to
2210 have a clear description of what is going on in the function.
2211 There is no pure code here - only calls to append lower-level functions
2212 code to the kernel code and additional inlining constants configuration
2213 that can be performed by the propagated from the plan manager information.
2214 This kernel also performs calls to additional kernel configuration routines
2215 like shared memory and register inlining inside a kernel and overall kernel
2216 decoration (like calls to inlining structure definitions, calls to kernel
2217 name inlining) - these routines are defined in lower kernels levels.
2218\end_layout
2219
2220\begin_layout Itemize
2221Level 1 kernels: less abstract simple routine kernels, like matrix-vector
2222 products, copy kernels, radix components of FFT, read/write managers.
2223 All of them must have a specified structure so they can be reused, for
2224 example, considering all input data to be in shared memory with a specific
2225 layout - then level 2 kernels will have a simple job of providing data
2226 to level 1 kernels in a specified manner and get the output in an also
2227 specified manner.
2228\end_layout
2229
2230\begin_layout Itemize
2231Level 0 kernels: memory management kernels.
2232 Here we have the absolute simplest kernel blocks, like memory data transfer
2233 request calls, synchronization, inlining of register/shared memory initializati
2234on code, etc.
2235 Many APIs have their own definitions for particular math operations, so
2236 we can define functions for inlining additions multiplications and other
2237 basic arithmetics here as well.
2238 The target of this level is to provide level 1 and 2 kernels with an easy
2239 way to reuse things that can be generalized between the widest range of
2240 math algorithms.
2241 
2242\end_layout
2243
2244\begin_layout Standard
2245All of the different level kernels have full access to the target GPU hardware
2246 parameters - hence (depending on the quality of implemented kernels) it
2247 is possible to autotune the algorithm at run-time and simplify the compiler
2248 job as much as possible.
2249 This involves loop unrolling, constants inlining, etc.
2250 Having an additional level (level 1) dedicated to the simple algorithms
2251 allows for kernel merging.
2252 
2253\end_layout
2254
2255\end_deeper
2256\begin_layout Itemize
2257Structs definitions.
2258 Here we define all structs used by the platform.
2259 It also contains some helper structs that can be used to manage GPU with
2260 different APIs and collect generated applications in a library struct for
2261 easier access through a map key (if the user's code uses many applications,
2262 this turns out to be extremely helpful).
2263\end_layout
2264
2265\begin_layout Subsection
2266Container abstractions
2267\end_layout
2268
2269\begin_layout Standard
2270The main design improvement that enables the platform functionality and
2271 greatly expands its usability are container abstractions.
2272 The code generator now operates on special data containers (implemented
2273 as C-unions), that can hold integer/float/complex numbers either as known
2274 during the plan creation values or as strings of variable names - no more
2275 sprintf calls with big chunks of unreadable code.
2276 
2277\end_layout
2278
2279\begin_layout Standard
2280An example operation that uses containers is a MUL operation that performs
2281 a multiplication A equals B multiplied by C.
2282 If all containers have known values, A can be precomputed during plan creation.
2283 If A , B and C are, for example, register names, we print to the kernel
2284 an operation of multiplication.
2285 Each operation like MUL has its own representation for all supported APIs
2286 in the vkFFT_MathUtils.h file.
2287 An important distinction is that it is not a full compiler, but a simple
2288 tool that unifies syntaxis of different APIs and supports JIT optimizations.
2289 However, as the code manager outputs code that resembles binary, one of
2290 the future exploration possibilities it may be interesting to try to make
2291 level 0 and 1 kernels output assembly without additional compilation by
2292 the plan manager.
2293 
2294\end_layout
2295
2296\begin_layout Standard
2297Usage of container abstractions brings exciting opportunities to code creation.
2298 Behaving as multi-API templates it will be possible to implement double-double
2299 FP128 mathematics support on GPU without modifying any of the already written
2300 algorithm code.
2301 Another big benefit is automatic type casting between precisions and option
2302 to perform precomputation in higher precision than the GPU code executes
2303 in.
2304 
2305\end_layout
2306
2307\begin_layout Standard
2308I have also explored other ways to implement these container abstractions
2309 - including switching to C++ from C99 and using templates and operator
2310 overloading, however this turned out to be just a syntactic sugar, as if
2311 it did not reduce number of lines of code and did not increase readibility.
2312 So the code is still C with almost instant compilations as a bonus.
2313 All this is subject to change in the future if people present convincing
2314 arguments.
2315 
2316\end_layout
2317
2318\begin_layout Standard
2319VkFFT supports two base number modes (used for all FP calculations on CPU)
2320 - long double or quad (__float128).
2321 The latter is needed to calculate the twiddle factors in double-double
2322 emulation of quad precision.
2323\end_layout
2324
2325\begin_layout Standard
2326\begin_inset Newpage newpage
2327\end_inset
2328
2329
2330\end_layout
2331
2332\begin_layout Section
2333VkFFT API Reference
2334\end_layout
2335
2336\begin_layout Standard
2337This section covers error codes, API functions that can be used by the user
2338 and configuration parameters.
2339\end_layout
2340
2341\begin_layout Subsection
2342Return value VkFFTResult
2343\end_layout
2344
2345\begin_layout Standard
2346All VkFFT Library return values except for VKFFT_SUCCESS are used in case
2347 of a failure and provide information on what has gone wrong.
2348 VkFFTResult is unified among different backends, though some of its values
2349 may not be used in specific backends.
2350 Possible return values of VkFFTResult are defined as following:
2351\end_layout
2352
2353\begin_layout Standard
2354\begin_inset ERT
2355status open
2356
2357\begin_layout Plain Layout
2358
2359
2360\backslash
2361begin{mdframed}[backgroundcolor=bg]
2362\end_layout
2363
2364\begin_layout Plain Layout
2365
2366
2367\backslash
2368begin{minted}[tabsize=4,obeytabs,breaklines]{C}
2369\end_layout
2370
2371\begin_layout Plain Layout
2372
2373typedef enum VkFFTResult { 	
2374\end_layout
2375
2376\begin_layout Plain Layout
2377
2378VKFFT_SUCCESS = 0,	// The VkFFT operation was successful
2379\end_layout
2380
2381\begin_layout Plain Layout
2382
2383VKFFT_ERROR_MALLOC_FAILED = 1,	// Some malloc call inside VkFFT has failed.
2384 Report this to the GitHub repo
2385\end_layout
2386
2387\begin_layout Plain Layout
2388
2389VKFFT_ERROR_INSUFFICIENT_CODE_BUFFER = 2,	// Generated kernel is bigger
2390 than default kernel array.
2391 Increase it with maxCodeLength parameter of configuration.
2392\end_layout
2393
2394\begin_layout Plain Layout
2395
2396VKFFT_ERROR_INSUFFICIENT_TEMP_BUFFER = 3,	// Temporary string used in kernel
2397 generation is bigger than default temporary string array.
2398 Increase it with maxTempLength parameter of configuration.
2399\end_layout
2400
2401\begin_layout Plain Layout
2402
2403VKFFT_ERROR_PLAN_NOT_INITIALIZED = 4,	// Code attempts to use uninitialized
2404 plan (it is zero inside VkFFTApplication)		
2405\end_layout
2406
2407\begin_layout Plain Layout
2408
2409VKFFT_ERROR_NULL_TEMP_PASSED = 5,	// Internal kernel generation error
2410\end_layout
2411
2412\begin_layout Plain Layout
2413
2414VKFFT_ERROR_MATH_FAILED = 6,	// Math instruction in code generator failed
2415     
2416\end_layout
2417
2418\begin_layout Plain Layout
2419
2420VKFFT_ERROR_FFTdim_GT_MAX_FFT_DIMENSIONS = 7,	// User specified a number
2421 of dimensions higher than the code is compiled to handle with VKFFT_MAX_FFT_DIM
2422ENSIONS
2423\end_layout
2424
2425\begin_layout Plain Layout
2426
2427VKFFT_ERROR_NONZERO_APP_INITIALIZATION = 8,	// The app pointer is not pointing
2428 to the zero-filled memory block
2429\end_layout
2430
2431\begin_layout Plain Layout
2432
2433VKFFT_ERROR_INVALID_PHYSICAL_DEVICE = 1001,	// No physical device is provided
2434 (Vulkan API)
2435\end_layout
2436
2437\begin_layout Plain Layout
2438
2439VKFFT_ERROR_INVALID_DEVICE = 1002,	// No device is provided (All APIs)
2440\end_layout
2441
2442\begin_layout Plain Layout
2443
2444VKFFT_ERROR_INVALID_QUEUE = 1003,	// No queue is provided (Vulkan API)
2445\end_layout
2446
2447\begin_layout Plain Layout
2448
2449VKFFT_ERROR_INVALID_COMMAND_POOL = 1004,	// No command pool is provided
2450 (Vulkan API)
2451\end_layout
2452
2453\begin_layout Plain Layout
2454
2455VKFFT_ERROR_INVALID_FENCE = 1005,	// No fence is provided (Vulkan API)
2456\end_layout
2457
2458\begin_layout Plain Layout
2459
2460VKFFT_ERROR_ONLY_FORWARD_FFT_INITIALIZED = 1006,	// VkFFT tries to access
2461 inverse FFT plan, when appliction is created with makeForwardPlanOnly flag
2462\end_layout
2463
2464\begin_layout Plain Layout
2465
2466VKFFT_ERROR_ONLY_INVERSE_FFT_INITIALIZED = 1007,	// VkFFT tries to access
2467 forward FFT plan, when appliction is created with makeInversePlanOnly flag
2468\end_layout
2469
2470\begin_layout Plain Layout
2471
2472VKFFT_ERROR_INVALID_CONTEXT = 1008,	// No context is provided (OpenCL API)
2473\end_layout
2474
2475\begin_layout Plain Layout
2476
2477VKFFT_ERROR_INVALID_PLATFORM = 1009,	// No platform is provided (OpenCL
2478 API)
2479\end_layout
2480
2481\begin_layout Plain Layout
2482
2483VKFFT_ERROR_EMPTY_FILE = 1011,
2484\end_layout
2485
2486\begin_layout Plain Layout
2487
2488VKFFT_ERROR_EMPTY_FFTdim = 2001,	// Number of dimensions is not provided
2489 in the configuration
2490\end_layout
2491
2492\begin_layout Plain Layout
2493
2494VKFFT_ERROR_EMPTY_size = 2002,	// Array of dimensions is not provided in
2495 the configuration
2496\end_layout
2497
2498\begin_layout Plain Layout
2499
2500VKFFT_ERROR_EMPTY_bufferSize = 2003,	// Buffer size has to be provided during
2501 the application creation
2502\end_layout
2503
2504\begin_layout Plain Layout
2505
2506VKFFT_ERROR_EMPTY_buffer = 2004,	// Buffer has te be specified either at
2507 the application creation stage or during launch through VkFFTLaunchParams
2508 struct
2509\end_layout
2510
2511\begin_layout Plain Layout
2512
2513VKFFT_ERROR_EMPTY_tempBufferSize = 2005,	// Same error as VKFFT_ERROR_EMPTY_buff
2514erSize if userTempBuffer is enabled
2515\end_layout
2516
2517\begin_layout Plain Layout
2518
2519VKFFT_ERROR_EMPTY_tempBuffer = 2006,	// Same error as VKFFT_ERROR_EMPTY_buffer
2520 if userTempBuffer is enabled
2521\end_layout
2522
2523\begin_layout Plain Layout
2524
2525VKFFT_ERROR_EMPTY_inputBufferSize = 2007,	// Same error as VKFFT_ERROR_EMPTY_buf
2526ferSize if isInputFormatted is enabled
2527\end_layout
2528
2529\begin_layout Plain Layout
2530
2531VKFFT_ERROR_EMPTY_inputBuffer = 2008,	// Same error as VKFFT_ERROR_EMPTY_buffer
2532 if isInputFormatted is enabled
2533\end_layout
2534
2535\begin_layout Plain Layout
2536
2537VKFFT_ERROR_EMPTY_outputBufferSize = 2009,	// Same error as VKFFT_ERROR_EMPTY_bu
2538fferSize if isOutputFormatted is enabled
2539\end_layout
2540
2541\begin_layout Plain Layout
2542
2543VKFFT_ERROR_EMPTY_outputBuffer = 2010,	// Same error as VKFFT_ERROR_EMPTY_buffer
2544 if isOutputFormatted is enabled
2545\end_layout
2546
2547\begin_layout Plain Layout
2548
2549VKFFT_ERROR_EMPTY_kernelSize = 2011,	// Same error as VKFFT_ERROR_EMPTY_bufferSi
2550ze if performConvolution is enabled
2551\end_layout
2552
2553\begin_layout Plain Layout
2554
2555VKFFT_ERROR_EMPTY_kernel = 2012,	// Same error as VKFFT_ERROR_EMPTY_buffer
2556 if performConvolution is enabled
2557\end_layout
2558
2559\begin_layout Plain Layout
2560
2561VKFFT_ERROR_EMPTY_applicationString = 2013,	// loadApplicationString is
2562 zero when loadApplicationFromString is enabled
2563\end_layout
2564
2565\begin_layout Plain Layout
2566
2567VKFFT_ERROR_EMPRY_useCustomBluesteinPaddingPattern_arrays = 2014,	// pointers
2568 to primeSizes or paddedSizes arrays are zero when useCustomBluesteinPaddingPatt
2569ern is enabled	
2570\end_layout
2571
2572\begin_layout Plain Layout
2573
2574VKFFT_ERROR_EMPTY_app = 2015,	// app pointer is zero
2575\end_layout
2576
2577\begin_layout Plain Layout
2578
2579VKFFT_ERROR_INVALID_user_tempBuffer_too_small = 2016,	// user provided tempBuffe
2580r is not sufficient for VkFFT intermediate calculations
2581\end_layout
2582
2583\begin_layout Plain Layout
2584
2585VKFFT_ERROR_UNSUPPORTED_RADIX = 3001,	// VkFFT has encountered unsupported
2586 radix (more than 13) during decomposition and Bluestein's FFT fallback
2587 did not work
2588\end_layout
2589
2590\begin_layout Plain Layout
2591
2592VKFFT_ERROR_UNSUPPORTED_FFT_LENGTH = 3002,	// VkFFT can not do this sequence
2593 length currently - it requires mor than three-upload Four step FFT
2594\end_layout
2595
2596\begin_layout Plain Layout
2597
2598VKFFT_ERROR_UNSUPPORTED_FFT_LENGTH_R2C = 3003,	// VkFFT can not do this
2599 sequence length currently - should no longer be thrown
2600\end_layout
2601
2602\begin_layout Plain Layout
2603
2604VKFFT_ERROR_UNSUPPORTED_FFT_LENGTH_R2R = 3004,	// VkFFT can not do this
2605 sequence length currently - should no longer be thrown
2606\end_layout
2607
2608\begin_layout Plain Layout
2609
2610VKFFT_ERROR_UNSUPPORTED_FFT_OMIT = 3005,	// VkFFT can not omit sequences
2611 in convolution calculations and R2C/C2R case
2612\end_layout
2613
2614\begin_layout Plain Layout
2615
2616VKFFT_ERROR_FAILED_TO_ALLOCATE = 4001,	// VkFFT failed to allocate GPU memory
2617\end_layout
2618
2619\begin_layout Plain Layout
2620
2621VKFFT_ERROR_FAILED_TO_MAP_MEMORY = 4002,	// 4002-4052 are handlers for errors
2622 of used backend APIs.
2623 They may indicate a driver failure.
2624 If they are thrown - report to the GitHub repo
2625\end_layout
2626
2627\begin_layout Plain Layout
2628
2629VKFFT_ERROR_FAILED_TO_ALLOCATE_COMMAND_BUFFERS = 4003,
2630\end_layout
2631
2632\begin_layout Plain Layout
2633
2634VKFFT_ERROR_FAILED_TO_BEGIN_COMMAND_BUFFER = 4004,
2635\end_layout
2636
2637\begin_layout Plain Layout
2638
2639VKFFT_ERROR_FAILED_TO_END_COMMAND_BUFFER = 4005,
2640\end_layout
2641
2642\begin_layout Plain Layout
2643
2644VKFFT_ERROR_FAILED_TO_SUBMIT_QUEUE = 4006,
2645\end_layout
2646
2647\begin_layout Plain Layout
2648
2649VKFFT_ERROR_FAILED_TO_WAIT_FOR_FENCES = 4007,
2650\end_layout
2651
2652\begin_layout Plain Layout
2653
2654VKFFT_ERROR_FAILED_TO_RESET_FENCES = 4008,
2655\end_layout
2656
2657\begin_layout Plain Layout
2658
2659VKFFT_ERROR_FAILED_TO_CREATE_DESCRIPTOR_POOL = 4009,
2660\end_layout
2661
2662\begin_layout Plain Layout
2663
2664VKFFT_ERROR_FAILED_TO_CREATE_DESCRIPTOR_SET_LAYOUT = 4010,
2665\end_layout
2666
2667\begin_layout Plain Layout
2668
2669VKFFT_ERROR_FAILED_TO_ALLOCATE_DESCRIPTOR_SETS = 4011,
2670\end_layout
2671
2672\begin_layout Plain Layout
2673
2674VKFFT_ERROR_FAILED_TO_CREATE_PIPELINE_LAYOUT = 4012,
2675\end_layout
2676
2677\begin_layout Plain Layout
2678
2679VKFFT_ERROR_FAILED_SHADER_PREPROCESS = 4013,
2680\end_layout
2681
2682\begin_layout Plain Layout
2683
2684VKFFT_ERROR_FAILED_SHADER_PARSE = 4014,
2685\end_layout
2686
2687\begin_layout Plain Layout
2688
2689VKFFT_ERROR_FAILED_SHADER_LINK = 4015,
2690\end_layout
2691
2692\begin_layout Plain Layout
2693
2694VKFFT_ERROR_FAILED_SPIRV_GENERATE = 4016,
2695\end_layout
2696
2697\begin_layout Plain Layout
2698
2699VKFFT_ERROR_FAILED_TO_CREATE_SHADER_MODULE = 4017,
2700\end_layout
2701
2702\begin_layout Plain Layout
2703
2704VKFFT_ERROR_FAILED_TO_CREATE_INSTANCE = 4018,
2705\end_layout
2706
2707\begin_layout Plain Layout
2708
2709VKFFT_ERROR_FAILED_TO_SETUP_DEBUG_MESSENGER = 4019,
2710\end_layout
2711
2712\begin_layout Plain Layout
2713
2714VKFFT_ERROR_FAILED_TO_FIND_PHYSICAL_DEVICE = 4020,
2715\end_layout
2716
2717\begin_layout Plain Layout
2718
2719VKFFT_ERROR_FAILED_TO_CREATE_DEVICE = 4021,
2720\end_layout
2721
2722\begin_layout Plain Layout
2723
2724VKFFT_ERROR_FAILED_TO_CREATE_FENCE = 4022,
2725\end_layout
2726
2727\begin_layout Plain Layout
2728
2729VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_POOL = 4023,
2730\end_layout
2731
2732\begin_layout Plain Layout
2733
2734VKFFT_ERROR_FAILED_TO_CREATE_BUFFER = 4024,
2735\end_layout
2736
2737\begin_layout Plain Layout
2738
2739VKFFT_ERROR_FAILED_TO_ALLOCATE_MEMORY = 4025,
2740\end_layout
2741
2742\begin_layout Plain Layout
2743
2744VKFFT_ERROR_FAILED_TO_BIND_BUFFER_MEMORY = 4026,
2745\end_layout
2746
2747\begin_layout Plain Layout
2748
2749VKFFT_ERROR_FAILED_TO_FIND_MEMORY = 4027,
2750\end_layout
2751
2752\begin_layout Plain Layout
2753
2754VKFFT_ERROR_FAILED_TO_SYNCHRONIZE = 4028,
2755\end_layout
2756
2757\begin_layout Plain Layout
2758
2759VKFFT_ERROR_FAILED_TO_COPY = 4029,
2760\end_layout
2761
2762\begin_layout Plain Layout
2763
2764VKFFT_ERROR_FAILED_TO_CREATE_PROGRAM = 4030,
2765\end_layout
2766
2767\begin_layout Plain Layout
2768
2769VKFFT_ERROR_FAILED_TO_COMPILE_PROGRAM = 4031, 
2770\end_layout
2771
2772\begin_layout Plain Layout
2773
2774VKFFT_ERROR_FAILED_TO_GET_CODE_SIZE = 4032,
2775\end_layout
2776
2777\begin_layout Plain Layout
2778
2779VKFFT_ERROR_FAILED_TO_GET_CODE = 4033,
2780\end_layout
2781
2782\begin_layout Plain Layout
2783
2784VKFFT_ERROR_FAILED_TO_DESTROY_PROGRAM = 4034,
2785\end_layout
2786
2787\begin_layout Plain Layout
2788
2789VKFFT_ERROR_FAILED_TO_LOAD_MODULE = 4035,
2790\end_layout
2791
2792\begin_layout Plain Layout
2793
2794VKFFT_ERROR_FAILED_TO_GET_FUNCTION = 4036,
2795\end_layout
2796
2797\begin_layout Plain Layout
2798
2799VKFFT_ERROR_FAILED_TO_SET_DYNAMIC_SHARED_MEMORY = 4037,
2800\end_layout
2801
2802\begin_layout Plain Layout
2803
2804VKFFT_ERROR_FAILED_TO_MODULE_GET_GLOBAL = 4038,
2805\end_layout
2806
2807\begin_layout Plain Layout
2808
2809VKFFT_ERROR_FAILED_TO_LAUNCH_KERNEL = 4039,
2810\end_layout
2811
2812\begin_layout Plain Layout
2813
2814VKFFT_ERROR_FAILED_TO_EVENT_RECORD = 4040,
2815\end_layout
2816
2817\begin_layout Plain Layout
2818
2819VKFFT_ERROR_FAILED_TO_ADD_NAME_EXPRESSION = 4041,
2820\end_layout
2821
2822\begin_layout Plain Layout
2823
2824VKFFT_ERROR_FAILED_TO_INITIALIZE = 4042,
2825\end_layout
2826
2827\begin_layout Plain Layout
2828
2829VKFFT_ERROR_FAILED_TO_SET_DEVICE_ID = 4043,
2830\end_layout
2831
2832\begin_layout Plain Layout
2833
2834VKFFT_ERROR_FAILED_TO_GET_DEVICE = 4044,
2835\end_layout
2836
2837\begin_layout Plain Layout
2838
2839VKFFT_ERROR_FAILED_TO_CREATE_CONTEXT = 4045,
2840\end_layout
2841
2842\begin_layout Plain Layout
2843
2844VKFFT_ERROR_FAILED_TO_CREATE_PIPELINE = 4046,
2845\end_layout
2846
2847\begin_layout Plain Layout
2848
2849VKFFT_ERROR_FAILED_TO_SET_KERNEL_ARG = 4047,
2850\end_layout
2851
2852\begin_layout Plain Layout
2853
2854VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_QUEUE = 4048,
2855\end_layout
2856
2857\begin_layout Plain Layout
2858
2859VKFFT_ERROR_FAILED_TO_RELEASE_COMMAND_QUEUE = 4049,
2860\end_layout
2861
2862\begin_layout Plain Layout
2863
2864VKFFT_ERROR_FAILED_TO_ENUMERATE_DEVICES = 4050,
2865\end_layout
2866
2867\begin_layout Plain Layout
2868
2869VKFFT_ERROR_FAILED_TO_GET_ATTRIBUTE = 4051,
2870\end_layout
2871
2872\begin_layout Plain Layout
2873
2874VKFFT_ERROR_FAILED_TO_CREATE_EVENT = 4052,
2875\end_layout
2876
2877\begin_layout Plain Layout
2878
2879VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_LIST = 4053,
2880\end_layout
2881
2882\begin_layout Plain Layout
2883
2884VKFFT_ERROR_FAILED_TO_DESTROY_COMMAND_LIST = 4054,
2885\end_layout
2886
2887\begin_layout Plain Layout
2888
2889VKFFT_ERROR_FAILED_TO_SUBMIT_BARRIER = 4055
2890\end_layout
2891
2892\begin_layout Plain Layout
2893
2894} VkFFTResult;
2895\end_layout
2896
2897\begin_layout Plain Layout
2898
2899
2900\backslash
2901end{minted}
2902\end_layout
2903
2904\begin_layout Plain Layout
2905
2906
2907\backslash
2908end{mdframed}
2909\end_layout
2910
2911\end_inset
2912
2913
2914\end_layout
2915
2916\begin_layout Subsection
2917VkFFT application management functions
2918\end_layout
2919
2920\begin_layout Standard
2921VkFFT has a unified plan management model - all different transform types/
2922 dimensionalities/ precision use the same calls with configuration done
2923 through VkFFTConfiguration struct.
2924 This section shows how to initialize/use/free VkFFT with this unified model,
2925 while the next one will go into how to configure VkFFTConfiguration correctly.
2926 All of the functions operate on VkFFTApplication and VkFFTConfiguration
2927 assuming they have been zero-initialized before usage, so do not forget
2928 to do this when initializing (otherwise VkFFT will throw an error):
2929\end_layout
2930
2931\begin_layout Standard
2932\begin_inset ERT
2933status open
2934
2935\begin_layout Plain Layout
2936
2937
2938\backslash
2939begin{mdframed}[backgroundcolor=bg]
2940\end_layout
2941
2942\begin_layout Plain Layout
2943
2944
2945\backslash
2946begin{minted}[tabsize=4,obeytabs,breaklines]{C}
2947\end_layout
2948
2949\begin_layout Plain Layout
2950
2951VkFFTConfiguration configuration = {};
2952\end_layout
2953
2954\begin_layout Plain Layout
2955
2956VkFFTApplication app = {};
2957\end_layout
2958
2959\begin_layout Plain Layout
2960
2961
2962\backslash
2963end{minted}
2964\end_layout
2965
2966\begin_layout Plain Layout
2967
2968
2969\backslash
2970end{mdframed}
2971\end_layout
2972
2973\end_inset
2974
2975
2976\end_layout
2977
2978\begin_layout Subsubsection
2979Function initializeVkFFT()
2980\end_layout
2981
2982\begin_layout Standard
2983\begin_inset ERT
2984status open
2985
2986\begin_layout Plain Layout
2987
2988
2989\backslash
2990begin{mdframed}[backgroundcolor=bg]
2991\end_layout
2992
2993\begin_layout Plain Layout
2994
2995
2996\backslash
2997begin{minted}[tabsize=4,obeytabs,breaklines]{C}
2998\end_layout
2999
3000\begin_layout Plain Layout
3001
3002VkFFTResult initializeVkFFT(VkFFTApplication* app, VkFFTConfiguration inputLaunc
3003hConfiguration)
3004\end_layout
3005
3006\begin_layout Plain Layout
3007
3008
3009\backslash
3010end{minted}
3011\end_layout
3012
3013\begin_layout Plain Layout
3014
3015
3016\backslash
3017end{mdframed}
3018\end_layout
3019
3020\end_inset
3021
3022
3023\end_layout
3024
3025\begin_layout Standard
3026Creates an FFT application (collection of forward and inverse plans).
3027 As forward and inverse FFTs may have different memory layouts, can have
3028 different normalizations - they are done as separate internal plans inside
3029 VkFFTApplication.
3030 This call assumes the application to be zero-initialized, so can be only
3031 done once on a particular application, until it is deleted.
3032\end_layout
3033
3034\begin_layout Standard
3035If the initializeVkFFT call fails, it frees all allocated by VkFFT CPU/GPU
3036 resources and sets the application to zero.
3037 VkFFTResult is returned with an error code corresponding to what went wrong.
3038\end_layout
3039
3040\begin_layout Standard
3041In case of success, VkFFTApplication will contain initialized plans with
3042 compiled kernels ready for execution with VKFFT_SUCCESS returned.
3043\end_layout
3044
3045\begin_layout Subsubsection
3046Function VkFFTAppend()
3047\end_layout
3048
3049\begin_layout Standard
3050\begin_inset ERT
3051status open
3052
3053\begin_layout Plain Layout
3054
3055
3056\backslash
3057begin{mdframed}[backgroundcolor=bg]
3058\end_layout
3059
3060\begin_layout Plain Layout
3061
3062
3063\backslash
3064begin{minted}[tabsize=4,obeytabs,breaklines]{C}
3065\end_layout
3066
3067\begin_layout Plain Layout
3068
3069VkFFTResult VkFFTAppend(VkFFTApplication* app, int inverse, VkFFTLaunchParams*
3070 launchParams)
3071\end_layout
3072
3073\begin_layout Plain Layout
3074
3075
3076\backslash
3077end{minted}
3078\end_layout
3079
3080\begin_layout Plain Layout
3081
3082
3083\backslash
3084end{mdframed}
3085\end_layout
3086
3087\end_inset
3088
3089
3090\end_layout
3091
3092\begin_layout Standard
3093Performs FFT in the int inverse direction (-1 for forward FFT, 1 for inverse
3094 FFT).
3095 FFT plans are selected from the VkFFTApplication collection automatically.
3096 VkFFTApplication must be initialized with initializeVkFFT call before.
3097 VkFFTLaunchParams struct allows for pre-launch configuration of some parameters
3098, namely:
3099\end_layout
3100
3101\begin_layout Itemize
3102buffer - similar to how FFTW/cuFFT expects input/output data pointers in
3103 *execC2C (and other) function calls, VkFFT allows specifying memory used
3104 for computations at launch.
3105 It must have the same size/layout/strides as defined during the application
3106 creation.
3107\end_layout
3108
3109\begin_layout Itemize
3110inputBuffer/outputBuffer/tempBuffer/kernel - other buffers can also be specified
3111 at launch.
3112 In addition to them having the same size/layout/strides as defined during
3113 the application creation, the application must be created with flags enabling
3114 the corresponding buffer usage: isInputFormatted/isOutputFormatted/userTempBuff
3115er/performConvolution respectively.
3116\end_layout
3117
3118\begin_layout Itemize
3119bufferOffset/tempBufferOffset/inputBufferOffset/outputBufferOffset/kernelOffset
3120 - specify if VkFFT has to offset the first element position inside the
3121 corresponding buffer.
3122 In bytes.
3123 Default 0.
3124 specifyOffsetsAtLaunch parameter must be enabled during the initializeVkFFT
3125 call before.
3126 
3127\end_layout
3128
3129\begin_layout Standard
3130Depending on the API, the execution model may vary and require additional
3131 information at launch:
3132\end_layout
3133
3134\begin_layout Itemize
3135Vulkan API: VkFFT appends a sequence of vkCmdDispatch calls to the user-defined
3136 VkCommandBuffer (with respective push constants/descriptor sets/pipelines/memor
3137y barriers bindings).
3138 VkCommandBuffer must be provided as a pointer in VkFFTLaunchParams.
3139 VkCommandBuffer must be in the writing stage, started with vkBeginCommandBuffer
3140 call.
3141 After VkFFTAppend has finished, provided VkCommandBuffer will contain a
3142 sequence of operations performing FFT.
3143 The first call of the sequence has no input memory barrier, the last call
3144 has one, ensuring FFT has finished execution.
3145\end_layout
3146
3147\begin_layout Itemize
3148CUDA/HIP API: if the user wants to use streams, they have to be provided
3149 during the application configuration stage.
3150 VkFFTAppend performs a series of cuLaunchKernel, which are sequential if
3151 appended to one stream and synchronized if appended to multiple streams.
3152\end_layout
3153
3154\begin_layout Itemize
3155OpenCL API: similar to Vulkan, VkFFT appends a sequence of clEnqueueNDRangeKerne
3156l calls to user-defined cl_command_queue.
3157 Currently, they are all assumed to be sequential.
3158 cl_command_queue must be provided as a pointer in VkFFTLaunchParams.
3159 
3160\end_layout
3161
3162\begin_layout Itemize
3163Level Zero API: similar to Vulkan, VkFFT appends a sequence of zeCommandListAppe
3164ndLaunchKernel calls to user-defined command list ze_command_list_handle_t.
3165 They have execution barriers between.
3166 ze_command_list_handle_t must be provided as a pointer in VkFFTLaunchParams.
3167 
3168\end_layout
3169
3170\begin_layout Itemize
3171Metal API: similar to Vulkan, VkFFT appends a sequence of dispatchThreads
3172 calls to user-defined command encoder MTL::ComputeCommandEncoder.
3173 MTL::ComputeCommandEncoder and its MTL::CommandBuffer must be provided
3174 as a pointer in VkFFTLaunchParams.
3175 
3176\end_layout
3177
3178\begin_layout Standard
3179If VkFFT fails during the VkFFTAppend call, it will not free the application
3180 and allocated there resources - use a separate call for that.
3181\end_layout
3182
3183\begin_layout Subsubsection
3184Function deleteVkFFT()
3185\end_layout
3186
3187\begin_layout Standard
3188\begin_inset ERT
3189status open
3190
3191\begin_layout Plain Layout
3192
3193
3194\backslash
3195begin{mdframed}[backgroundcolor=bg]
3196\end_layout
3197
3198\begin_layout Plain Layout
3199
3200
3201\backslash
3202begin{minted}[tabsize=4,obeytabs,breaklines]{C}
3203\end_layout
3204
3205\begin_layout Plain Layout
3206
3207void deleteVkFFT(VkFFTApplication* app)
3208\end_layout
3209
3210\begin_layout Plain Layout
3211
3212
3213\backslash
3214end{minted}
3215\end_layout
3216
3217\begin_layout Plain Layout
3218
3219
3220\backslash
3221end{mdframed}
3222\end_layout
3223
3224\end_inset
3225
3226
3227\end_layout
3228
3229\begin_layout Standard
3230Performs deallocation of resources used in the provided application.
3231 Returns application to the zero-initialized state.
3232\end_layout
3233
3234\begin_layout Subsubsection
3235Function VkFFTGetVersion()
3236\end_layout
3237
3238\begin_layout Standard
3239\begin_inset ERT
3240status open
3241
3242\begin_layout Plain Layout
3243
3244
3245\backslash
3246begin{mdframed}[backgroundcolor=bg]
3247\end_layout
3248
3249\begin_layout Plain Layout
3250
3251
3252\backslash
3253begin{minted}[tabsize=4,obeytabs,breaklines]{C}
3254\end_layout
3255
3256\begin_layout Plain Layout
3257
3258int VkFFTGetVersion()
3259\end_layout
3260
3261\begin_layout Plain Layout
3262
3263
3264\backslash
3265end{minted}
3266\end_layout
3267
3268\begin_layout Plain Layout
3269
3270
3271\backslash
3272end{mdframed}
3273\end_layout
3274
3275\end_inset
3276
3277
3278\end_layout
3279
3280\begin_layout Standard
3281Returns the version of the VkFFT library in the X.XX.XX format (without dots).
3282\end_layout
3283
3284\begin_layout Subsection
3285VkFFT configuration
3286\end_layout
3287
3288\begin_layout Standard
3289This section will cover all the parameters that can be specified in the
3290 VkFFTConfiguration struct.
3291 It will start with a short description of the struct (intended to be used
3292 as a cheat sheet), then go for each field in detail.
3293 Here pfUINT and pfINT are defined as uint64_t and int64_t respectively.
3294\end_layout
3295
3296\begin_layout Standard
3297\begin_inset ERT
3298status open
3299
3300\begin_layout Plain Layout
3301
3302
3303\backslash
3304begin{mdframed}[backgroundcolor=bg]
3305\end_layout
3306
3307\begin_layout Plain Layout
3308
3309
3310\backslash
3311begin{minted}[tabsize=4,obeytabs,breaklines]{C}
3312\end_layout
3313
3314\begin_layout Plain Layout
3315
3316typedef struct {
3317\end_layout
3318
3319\begin_layout Plain Layout
3320
3321// Required parameters: 	
3322\end_layout
3323
3324\begin_layout Plain Layout
3325
3326pfUINT FFTdim;	// FFT dimensionality (1, 2 or 3)
3327\end_layout
3328
3329\begin_layout Plain Layout
3330
3331pfUINT size[VKFFT_MAX_FFT_DIMENSIONS];	// WHD+ - system dimensions
3332\end_layout
3333
3334\begin_layout Plain Layout
3335
3336#if(VKFFT_BACKEND==0) //Vulkan API
3337\end_layout
3338
3339\begin_layout Plain Layout
3340
3341VkPhysicalDevice* physicalDevice;	// Pointer to Vulkan physical device,
3342 obtained from vkEnumeratePhysicalDevices
3343\end_layout
3344
3345\begin_layout Plain Layout
3346
3347VkDevice* device;	// Pointer to Vulkan device, created with vkCreateDevice
3348\end_layout
3349
3350\begin_layout Plain Layout
3351
3352VkQueue* queue;	// Pointer to Vulkan queue, created with vkGetDeviceQueue
3353\end_layout
3354
3355\begin_layout Plain Layout
3356
3357VkCommandPool* commandPool;	// Pointer to Vulkan command pool, created with
3358 vkCreateCommandPool
3359\end_layout
3360
3361\begin_layout Plain Layout
3362
3363VkFence* fence;	// Pointer to Vulkan fence, created with vkCreateFence
3364\end_layout
3365
3366\begin_layout Plain Layout
3367
3368pfUINT isCompilerInitialized;	// Specify if glslang compiler has been intialized
3369 before (0 - off, 1 - on).
3370 Default 0 
3371\end_layout
3372
3373\begin_layout Plain Layout
3374
3375#elif(VKFFT_BACKEND==1) //CUDA API
3376\end_layout
3377
3378\begin_layout Plain Layout
3379
3380CUdevice* device;	// Pointer to CUDA device, obtained from cuDeviceGet
3381\end_layout
3382
3383\begin_layout Plain Layout
3384
3385cudaStream_t* stream;	// Pointer to streams (can be more than 1), where
3386 to execute the kernels.
3387 Deafult 0
3388\end_layout
3389
3390\begin_layout Plain Layout
3391
3392pfUINT num_streams;	// Try to submit CUDA kernels in multiple streams for
3393 asynchronous execution.
3394 Default 0, set to >=1 if you pass values in the stream pointer.
3395  
3396\end_layout
3397
3398\begin_layout Plain Layout
3399
3400#elif(VKFFT_BACKEND==2) //HIP API
3401\end_layout
3402
3403\begin_layout Plain Layout
3404
3405hipDevice_t* device;	// Pointer to HIP device, obtained from hipDeviceGet
3406\end_layout
3407
3408\begin_layout Plain Layout
3409
3410hipStream_t* stream;	// Pointer to streams (can be more than 1), where to
3411 execute the kernels.
3412 Deafult 0
3413\end_layout
3414
3415\begin_layout Plain Layout
3416
3417pfUINT num_streams;	// Try to submit HIP kernels in multiple streams for
3418 asynchronous execution.
3419 Default 0, set to >=1 if you pass values in the stream pointer.
3420\end_layout
3421
3422\begin_layout Plain Layout
3423
3424#elif(VKFFT_BACKEND==3) //OpenCL API
3425\end_layout
3426
3427\begin_layout Plain Layout
3428
3429cl_platform_id* platform;	// NOT REQUIRED
3430\end_layout
3431
3432\begin_layout Plain Layout
3433
3434cl_device_id* device;	// Pointer to OpenCL device, obtained from clGetDeviceIDs
3435\end_layout
3436
3437\begin_layout Plain Layout
3438
3439cl_context* context;	// Pointer to OpenCL context, obtained from clCreateContext
3440\end_layout
3441
3442\begin_layout Plain Layout
3443
3444#elif(VKFFT_BACKEND==4) //Level Zero API
3445\end_layout
3446
3447\begin_layout Plain Layout
3448
3449ze_device_handle_t* device;	// Pointer to Level Zero device, obtained from
3450 zeDeviceGet
3451\end_layout
3452
3453\begin_layout Plain Layout
3454
3455ze_context_handle_t* context;	// Pointer to Level Zero context, obtained
3456 from zeContextCreate
3457\end_layout
3458
3459\begin_layout Plain Layout
3460
3461ze_command_queue_handle_t* commandQueue;	// Pointer to Level Zero command
3462 queue with compute and copy capabilities, obtained from zeCommandQueueCreate
3463\end_layout
3464
3465\begin_layout Plain Layout
3466
3467uint32_t commandQueueID;	// ID of the commandQueue with compute and copy
3468 capabilities
3469\end_layout
3470
3471\begin_layout Plain Layout
3472
3473#elif(VKFFT_BACKEND==5)
3474\end_layout
3475
3476\begin_layout Plain Layout
3477
3478MTL::Device* device;	// Pointer to Metal device, obtained from MTL::CopyAllDevic
3479es
3480\end_layout
3481
3482\begin_layout Plain Layout
3483
3484MTL::CommandQueue* queue;	// Pointer to Metal queue, obtained from device->newCo
3485mmandQueue()
3486\end_layout
3487
3488\begin_layout Plain Layout
3489
3490#endif
3491\end_layout
3492
3493\begin_layout Plain Layout
3494
3495\end_layout
3496
3497\begin_layout Plain Layout
3498
3499// Data parameters (buffers can be specified at launch):
3500\end_layout
3501
3502\begin_layout Plain Layout
3503
3504pfUINT userTempBuffer;	// Buffer allocated by app automatically if needed
3505 to reorder Four step algorithm.
3506 Setting to non zero value enables manual user allocation (0 - off, 1 -
3507 on)
3508\end_layout
3509
3510\begin_layout Plain Layout
3511
3512pfUINT bufferNum;	// Multiple buffer sequence storage is Vulkan only.
3513 Default 1
3514\end_layout
3515
3516\begin_layout Plain Layout
3517
3518pfUINT tempBufferNum;	// Multiple buffer sequence storage is Vulkan only.
3519 Default 1, buffer allocated by app automatically if needed to reorder Four
3520 step algorithm.
3521 Setting to non zero value enables manual user allocation 	
3522\end_layout
3523
3524\begin_layout Plain Layout
3525
3526pfUINT inputBufferNum;	// Multiple buffer sequence storage is Vulkan only.
3527 Default 1, if isInputFormatted is enabled 
3528\end_layout
3529
3530\begin_layout Plain Layout
3531
3532pfUINT outputBufferNum;	// Multiple buffer sequence storage is Vulkan only.
3533 Default 1, if isOutputFormatted is enabled 
3534\end_layout
3535
3536\begin_layout Plain Layout
3537
3538pfUINT kernelNum;	// Multiple buffer sequence storage is Vulkan only.
3539 Default 1, if performConvolution is enabled
3540\end_layout
3541
3542\begin_layout Plain Layout
3543
3544pfUINT* bufferSize;	// Array of buffers sizes in bytes
3545\end_layout
3546
3547\begin_layout Plain Layout
3548
3549pfUINT* tempBufferSize;	// Array of temp buffers sizes in bytes.
3550 Default set to bufferSize sum, buffer allocated by app automatically if
3551 needed to reorder Four step algorithm.
3552 Setting to non zero value enables manual user allocation 
3553\end_layout
3554
3555\begin_layout Plain Layout
3556
3557pfUINT* inputBufferSize;	// Array of input buffers sizes in bytes, if isInputFor
3558matted is enabled
3559\end_layout
3560
3561\begin_layout Plain Layout
3562
3563pfUINT* outputBufferSize;	// Array of output buffers sizes in bytes, if
3564 isOutputFormatted is enabled
3565\end_layout
3566
3567\begin_layout Plain Layout
3568
3569pfUINT* kernelSize;	// Array of kernel buffers sizes in bytes, if performConvolu
3570tion is enabled
3571\end_layout
3572
3573\begin_layout Plain Layout
3574
3575#if(VKFFT_BACKEND==0) //Vulkan API
3576\end_layout
3577
3578\begin_layout Plain Layout
3579
3580VkBuffer* buffer;	// Pointer to array of buffers (or one buffer) used for
3581 computations
3582\end_layout
3583
3584\begin_layout Plain Layout
3585
3586VkBuffer* tempBuffer;	// Needed if reorderFourStep is enabled to transpose
3587 the array.
3588 Same sum size or bigger as buffer (can be split in multiple).
3589 Default 0.
3590 Setting to non zero value enables manual user allocation
3591\end_layout
3592
3593\begin_layout Plain Layout
3594
3595VkBuffer* inputBuffer;	// Pointer to array of input buffers (or one buffer)
3596 used to read data from if isInputFormatted is enabled
3597\end_layout
3598
3599\begin_layout Plain Layout
3600
3601VkBuffer* outputBuffer;	// Pointer to array of output buffers (or one buffer)
3602 used to write data to if isOutputFormatted is enabled
3603\end_layout
3604
3605\begin_layout Plain Layout
3606
3607VkBuffer* kernel;	// Pointer to array of kernel buffers (or one buffer)
3608 used to read kernel data from if performConvolution is enabled
3609\end_layout
3610
3611\begin_layout Plain Layout
3612
3613#elif(VKFFT_BACKEND==1) //CUDA API
3614\end_layout
3615
3616\begin_layout Plain Layout
3617
3618void** buffer;	// Pointer to device buffer used for computations
3619\end_layout
3620
3621\begin_layout Plain Layout
3622
3623void** tempBuffer;	// Needed if reorderFourStep is enabled to transpose
3624 the array.
3625 Same size as buffer.
3626 Default 0.
3627 Setting to non zero value enables manual user allocation 
3628\end_layout
3629
3630\begin_layout Plain Layout
3631
3632void** inputBuffer;	// Pointer to device buffer used to read data from if
3633 isInputFormatted is enabled
3634\end_layout
3635
3636\begin_layout Plain Layout
3637
3638void** outputBuffer;	// Pointer to device buffer used to write data to if
3639 isOutputFormatted is enabled
3640\end_layout
3641
3642\begin_layout Plain Layout
3643
3644void** kernel;	// Pointer to device buffer used to read kernel data from
3645 if performConvolution is enabled 
3646\end_layout
3647
3648\begin_layout Plain Layout
3649
3650#elif(VKFFT_BACKEND==2) //HIP API
3651\end_layout
3652
3653\begin_layout Plain Layout
3654
3655void** buffer;	// Pointer to device buffer used for computations
3656\end_layout
3657
3658\begin_layout Plain Layout
3659
3660void** tempBuffer;	// Needed if reorderFourStep is enabled to transpose
3661 the array.
3662 Same size as buffer.
3663 Default 0.
3664 Setting to non zero value enables manual user allocation
3665\end_layout
3666
3667\begin_layout Plain Layout
3668
3669void** inputBuffer;	// Pointer to device buffer used to read data from if
3670 isInputFormatted is enabled
3671\end_layout
3672
3673\begin_layout Plain Layout
3674
3675void** outputBuffer;	// Pointer to device buffer used to write data to if
3676 isOutputFormatted is enabled
3677\end_layout
3678
3679\begin_layout Plain Layout
3680
3681void** kernel;	// Pointer to device buffer used to read kernel data from
3682 if performConvolution is enabled 
3683\end_layout
3684
3685\begin_layout Plain Layout
3686
3687#elif(VKFFT_BACKEND==3) //OpenCL API
3688\end_layout
3689
3690\begin_layout Plain Layout
3691
3692cl_mem* buffer;	// Pointer to device buffer used for computations
3693\end_layout
3694
3695\begin_layout Plain Layout
3696
3697cl_mem* tempBuffer;	// Needed if reorderFourStep is enabled to transpose
3698 the array.
3699 Same size as buffer.
3700 Default 0.
3701 Setting to non zero value enables manual user allocation
3702\end_layout
3703
3704\begin_layout Plain Layout
3705
3706cl_mem* inputBuffer;	// Pointer to device buffer used to read data from
3707 if isInputFormatted is enabled
3708\end_layout
3709
3710\begin_layout Plain Layout
3711
3712cl_mem* outputBuffer;	// Pointer to device buffer used to write data to
3713 if isOutputFormatted is enabled
3714\end_layout
3715
3716\begin_layout Plain Layout
3717
3718cl_mem* kernel;	// Pointer to device buffer used to read kernel data from
3719 if performConvolution is enabled
3720\end_layout
3721
3722\begin_layout Plain Layout
3723
3724#elif(VKFFT_BACKEND==4)
3725\end_layout
3726
3727\begin_layout Plain Layout
3728
3729void** buffer;	// Pointer to device buffer used for computations
3730\end_layout
3731
3732\begin_layout Plain Layout
3733
3734void** tempBuffer;	// Needed if reorderFourStep is enabled to transpose
3735 the array.
3736 Same size as buffer.
3737 Default 0.
3738 Setting to non zero value enables manual user allocation
3739\end_layout
3740
3741\begin_layout Plain Layout
3742
3743void** inputBuffer;	// Pointer to device buffer used to read data from if
3744 isInputFormatted is enabled
3745\end_layout
3746
3747\begin_layout Plain Layout
3748
3749void** outputBuffer;	// Pointer to device buffer used to read data from
3750 if isOutputFormatted is enabled
3751\end_layout
3752
3753\begin_layout Plain Layout
3754
3755void** kernel;	// Pointer to device buffer used to read kernel data from
3756 if performConvolution is enabled
3757\end_layout
3758
3759\begin_layout Plain Layout
3760
3761#elif(VKFFT_BACKEND==5)
3762\end_layout
3763
3764\begin_layout Plain Layout
3765
3766MTL::Buffer** buffer;	// Pointer to device buffer used for computations
3767\end_layout
3768
3769\begin_layout Plain Layout
3770
3771MTL::Buffer** tempBuffer;	// Needed if reorderFourStep is enabled to transpose
3772 the array.
3773 Same size as buffer.
3774 Default 0.
3775 Setting to non zero value enables manual user allocation
3776\end_layout
3777
3778\begin_layout Plain Layout
3779
3780MTL::Buffer** inputBuffer;	// Pointer to device buffer used to read data
3781 from if isInputFormatted is enabled
3782\end_layout
3783
3784\begin_layout Plain Layout
3785
3786MTL::Buffer** outputBuffer;	// Pointer to device buffer used to read data
3787 from if isOutputFormatted is enabled
3788\end_layout
3789
3790\begin_layout Plain Layout
3791
3792MTL::Buffer** kernel;	// Pointer to device buffer used to read kernel data
3793 from if performConvolution is enabled
3794\end_layout
3795
3796\begin_layout Plain Layout
3797
3798#endif
3799\end_layout
3800
3801\begin_layout Plain Layout
3802
3803pfUINT bufferOffset;	// Specify if VkFFT has to offset the first element
3804 position inside the buffer.
3805 In bytes.
3806 Default 0
3807\end_layout
3808
3809\begin_layout Plain Layout
3810
3811pfUINT tempBufferOffset;	// Specify if VkFFT has to offset the first element
3812 position inside the temp buffer.
3813 In bytes.
3814 Default 0
3815\end_layout
3816
3817\begin_layout Plain Layout
3818
3819pfUINT inputBufferOffset;	// Specify if VkFFT has to offset the first element
3820 position inside the input buffer.
3821 In bytes.
3822 Default 0
3823\end_layout
3824
3825\begin_layout Plain Layout
3826
3827pfUINT outputBufferOffset;	// Specify if VkFFT has to offset the first element
3828 position inside the output buffer.
3829 In bytes.
3830 Default 0
3831\end_layout
3832
3833\begin_layout Plain Layout
3834
3835pfUINT kernelOffset;	// Specify if VkFFT has to offset the first element
3836 position inside the kernel.
3837 In bytes.
3838 Default 0
3839\end_layout
3840
3841\begin_layout Plain Layout
3842
3843pfUINT specifyOffsetsAtLaunch;	// Specify if offsets will be selected with
3844 launch parameters VkFFTLaunchParams (0 - off, 1 - on).
3845 Default 0
3846\end_layout
3847
3848\begin_layout Plain Layout
3849
3850\end_layout
3851
3852\begin_layout Plain Layout
3853
3854// Optional: (default 0 if not stated otherwise)
3855\end_layout
3856
3857\begin_layout Plain Layout
3858
3859pfUINT coalescedMemory;	// In bytes, for Nvidia and AMD is equal to 32,
3860 Intel is equal 64, scaled for half precision.
3861 Going to work regardless, but if specified by user correctly, the performance
3862 will be higher.
3863\end_layout
3864
3865\begin_layout Plain Layout
3866
3867pfUINT aimThreads;	// Aim at this many threads per block.
3868 Default 128
3869\end_layout
3870
3871\begin_layout Plain Layout
3872
3873pfUINT numSharedBanks;	// How many banks shared memory has.
3874 Default 32
3875\end_layout
3876
3877\begin_layout Plain Layout
3878
3879pfUINT inverseReturnToInputBuffer;	// return data to the input buffer in
3880 inverse transform (0 - off, 1 - on).
3881 isInputFormatted must be enabled
3882\end_layout
3883
3884\begin_layout Plain Layout
3885
3886pfUINT numberBatches;	// N - used to perform multiple batches of initial
3887 data.
3888 Default 1
3889\end_layout
3890
3891\begin_layout Plain Layout
3892
3893pfUINT useUint64;	// Use 64-bit addressing mode in generated kernels
3894\end_layout
3895
3896\begin_layout Plain Layout
3897
3898pfUINT omitDimension[VKFFT_MAX_FFT_DIMENSIONS];	// Disable FFT for this
3899 dimension (0 - FFT enabled, 1 - FFT disabled).
3900 Default 0.
3901 Doesn't work for R2C first axis for now.
3902 Doesn't work with convolutions.
3903\end_layout
3904
3905\begin_layout Plain Layout
3906
3907int performBandwidthBoost; // Try to reduce coalsesced number by a factor
3908 of X to get bigger sequence in one upload for strided axes.
3909 Default: -1 for DCT/DST, 2 for Bluestein's algorithm (or -1 if DCT/DST),
3910 0 otherwise  
3911\end_layout
3912
3913\begin_layout Plain Layout
3914
3915\end_layout
3916
3917\begin_layout Plain Layout
3918
3919pfUINT doublePrecision;	// Perform calculations in double precision (0 -
3920 off, 1 - on).
3921\end_layout
3922
3923\begin_layout Plain Layout
3924
3925pfUINT quadDoubleDoublePrecision; // Perform calculations in double-double
3926 emulation of quad precision (0 - off, 1 - on).
3927\end_layout
3928
3929\begin_layout Plain Layout
3930
3931pfUINT quadDoubleDoublePrecisionDoubleMemory; // Perform calculations in
3932 double-double emulation of quad precision, while all memory storage is
3933 done in FP64.
3934\end_layout
3935
3936\begin_layout Plain Layout
3937
3938pfUINT halfPrecision;	// Perform calculations in half precision (0 - off,
3939 1 - on)
3940\end_layout
3941
3942\begin_layout Plain Layout
3943
3944pfUINT halfPrecisionMemoryOnly;	// Use half precision only as input/output
3945 buffer.
3946 Input/Output have to be allocated as half, buffer/tempBuffer have to be
3947 allocated as float (out-of-place mode only).
3948 Specify isInputFormatted and isOutputFormatted to use (0 - off, 1 - on)
3949\end_layout
3950
3951\begin_layout Plain Layout
3952
3953pfUINT doublePrecisionFloatMemory;	// Use FP64 precision for all calculations,
3954 while all memory storage is done in FP32.
3955\end_layout
3956
3957\begin_layout Plain Layout
3958
3959\end_layout
3960
3961\begin_layout Plain Layout
3962
3963pfUINT performR2C;	// Perform R2C/C2R decomposition (0 - off, 1 - on)
3964\end_layout
3965
3966\begin_layout Plain Layout
3967
3968pfUINT performDCT;	// Perform DCT transformation (X - DCT type, 1-4)
3969\end_layout
3970
3971\begin_layout Plain Layout
3972
3973pfUINT performDST;	// Perform DST transformation (X - DST type, 1-4)
3974\end_layout
3975
3976\begin_layout Plain Layout
3977
3978pfUINT disableMergeSequencesR2C;	// Disable merging of two real sequences
3979 to reduce calculations (0 - off, 1 - on)
3980\end_layout
3981
3982\begin_layout Plain Layout
3983
3984pfUINT forceCallbackVersionRealTransforms;	// Force callback version of
3985 R2C and R2R algorithms for all usecases (0 - off, 1 - on) 
3986\end_layout
3987
3988\begin_layout Plain Layout
3989
3990\end_layout
3991
3992\begin_layout Plain Layout
3993
3994pfUINT normalize;	// Normalize inverse transform (0 - off, 1 - on)
3995\end_layout
3996
3997\begin_layout Plain Layout
3998
3999pfUINT disableReorderFourStep;	// Disables unshuffling of Four step algorithm.
4000 Requires tempbuffer allocation (0 - off, 1 - on)
4001\end_layout
4002
4003\begin_layout Plain Layout
4004
4005pfINT useLUT;	// Switches from calculating sincos to using precomputed LUT
4006 tables (0 - off, 1 - on).
4007 Configured by initialization routine
4008\end_layout
4009
4010\begin_layout Plain Layout
4011
4012pfINT useLUT_4step; // Switches from calculating sincos to using precomputed
4013 LUT tables for intermediate roots of 1 in the Four-step FFT algorithm.
4014 (-1 - off, 0 - auto, 1 - on).
4015 Configured by initialization routine
4016\end_layout
4017
4018\begin_layout Plain Layout
4019
4020pfUINT makeForwardPlanOnly;	// Generate code only for forward FFT (0 - off,
4021 1 - on)
4022\end_layout
4023
4024\begin_layout Plain Layout
4025
4026pfUINT makeInversePlanOnly;	// Generate code only for inverse FFT (0 - off,
4027 1 - on)
4028\end_layout
4029
4030\begin_layout Plain Layout
4031
4032pfUINT bufferStride[VKFFT_MAX_FFT_DIMENSIONS];	// Buffer strides - default
4033 set to x - x*y - x*y*z values
4034\end_layout
4035
4036\begin_layout Plain Layout
4037
4038pfUINT isInputFormatted;	// Specify if input buffer is padded - 0 - padded,
4039 1 - not padded.
4040 For example if it is not padded for R2C if out-of-place mode is selected
4041 (only if numberBatches==1 and numberKernels==1)
4042\end_layout
4043
4044\begin_layout Plain Layout
4045
4046pfUINT isOutputFormatted;	// Specify if output buffer is padded - 0 - padded,
4047 1 - not padded.
4048 For example if it is not padded for R2C if out-of-place mode is selected
4049 (only if numberBatches==1 and numberKernels==1)
4050\end_layout
4051
4052\begin_layout Plain Layout
4053
4054pfUINT inputBufferStride[VKFFT_MAX_FFT_DIMENSIONS];	// Input buffer strides.
4055 Used if isInputFormatted is enabled.
4056 Default set to bufferStride values
4057\end_layout
4058
4059\begin_layout Plain Layout
4060
4061pfUINT outputBufferStride[VKFFT_MAX_FFT_DIMENSIONS];	// Output buffer strides.
4062 Used if isInputFormatted is enabled.
4063 Default set to bufferStride values
4064\end_layout
4065
4066\begin_layout Plain Layout
4067
4068pfUINT swapTo2Stage4Step; // Specify at which number to switch from 1 upload
4069 to 2 upload 4-step FFT, in case if making max sequence size lower than
4070 coalesced sequence helps to combat TLB misses.
4071 Default 0 - disabled.
4072 	
4073\end_layout
4074
4075\begin_layout Plain Layout
4076
4077pfUINT swapTo3Stage4Step;	// Specify at which power of 2 to switch from
4078 2 upload to 3 upload 4-step FFT, in case if making max sequence size lower
4079 than coalesced sequence helps to combat TLB misses.
4080 Default 0 - disabled.
4081 Must be at least 17
4082\end_layout
4083
4084\begin_layout Plain Layout
4085
4086pfUINT considerAllAxesStrided;	// Will create plan for non-strided axis
4087 similar as a strided axis - used with disableReorderFourStep to get the
4088 same layout for Bluestein kernel (0 - off, 1 - on)
4089\end_layout
4090
4091\begin_layout Plain Layout
4092
4093\end_layout
4094
4095\begin_layout Plain Layout
4096
4097pfUINT keepShaderCode;	// Will keep shader code and print all executed shaders
4098 during the plan execution in order (0 - off, 1 - on)
4099\end_layout
4100
4101\begin_layout Plain Layout
4102
4103pfUINT printMemoryLayout;	// Will print order of buffers used in shaders
4104 (0 - off, 1 - on) 
4105\end_layout
4106
4107\begin_layout Plain Layout
4108
4109\end_layout
4110
4111\begin_layout Plain Layout
4112
4113pfUINT saveApplicationToString;	// Will save all compiled binaries to VkFFTAppli
4114cation.saveApplicationString (will be allocated by VkFFT, deallocated with
4115 deleteVkFFT call).
4116 VkFFTApplication.applicationStringSize will contain size of binary in bytes.
4117 Currently disabled in Metal backend.
4118 (0 - off, 1 - on)
4119\end_layout
4120
4121\begin_layout Plain Layout
4122
4123pfUINT loadApplicationFromString;	// Will load all binaries from loadApplication
4124String instead of recompiling them (must be allocated by user, must contain
4125 what saveApplicationToString call generated previously in VkFFTApplication.saveA
4126pplicationString).
4127 Currently disabled in Metal backend.
4128 (0 - off, 1 - on).
4129 Mutually exclusive with saveApplicationToString
4130\end_layout
4131
4132\begin_layout Plain Layout
4133
4134void* loadApplicationString;	// Memory binary array through which user can
4135 load VkFFT binaries, must be provided by user if loadApplicationFromString
4136 = 1.
4137 Use rb/wb flags to load/save.
4138\end_layout
4139
4140\begin_layout Plain Layout
4141
4142\end_layout
4143
4144\begin_layout Plain Layout
4145
4146pfUINT disableSetLocale;	// disables all VkFFT attempts to set locale to
4147 C - user must ensure that VkFFT has C locale during the plan initialization.
4148 This option is needed for multithreading.
4149 Default 0.
4150 
4151\end_layout
4152
4153\begin_layout Plain Layout
4154
4155\end_layout
4156
4157\begin_layout Plain Layout
4158
4159// Optional Bluestein optimizations: (default 0 if not stated otherwise)
4160\end_layout
4161
4162\begin_layout Plain Layout
4163
4164pfUINT fixMaxRadixBluestein;	// controls the padding of sequences in Bluestein
4165 convolution.
4166 If specified, padded sequence will be made of up to fixMaxRadixBluestein
4167 primes.
4168 Default: 2 for CUDA and Vulkan/OpenCL/HIP up to 1048576 combined dimension
4169 FFT system, 7 for Vulkan/OpenCL/HIP past after.
4170 Min = 2, Max = 13.
4171\end_layout
4172
4173\begin_layout Plain Layout
4174
4175pfUINT forceBluesteinSequenceSize;	// force the sequence size to pad to
4176 in Bluestein's algorithm.
4177 Must be at least 2*N-1 and decomposable with primes 2-13.
4178\end_layout
4179
4180\begin_layout Plain Layout
4181
4182pfUINT useCustomBluesteinPaddingPattern;	// force the sequence sizes to
4183 pad to in Bluestein's algorithm, but on a range.
4184 This number specifies the number of elements in primeSizes and in paddedSizes
4185 arrays.
4186 primeSizes - array of non-decomposable as radix scheme sizes - 17, 23,
4187 31 etc.
4188 paddedSizes - array of lengths to pad to.
4189 paddedSizes[i] will be the padding size for all non-decomposable sequences
4190 from primeSizes[i] to primeSizes[i+1] (will use default scheme after last
4191 one) - 42, 60, 64 for primeSizes before and 37+ will use default scheme
4192 (for example).
4193 Default is vendor and API-based specified in autoCustomBluesteinPaddingPattern.
4194\end_layout
4195
4196\begin_layout Plain Layout
4197
4198pfUINT* primeSizes;	// described in useCustomBluesteinPaddingPattern
4199\end_layout
4200
4201\begin_layout Plain Layout
4202
4203pfUINT* paddedSizes;	// described in useCustomBluesteinPaddingPattern
4204\end_layout
4205
4206\begin_layout Plain Layout
4207
4208\end_layout
4209
4210\begin_layout Plain Layout
4211
4212pfUINT fixMinRaderPrimeMult;	// start direct multiplication Rader's algorithm
4213 for radix primes from this number.
4214 This means that VkFFT will inline custom Rader kernels if sequence is divisible
4215 by these primes.
4216 Default is 17, as VkFFT has kernels for 2-13.
4217 If you make it less than 13, VkFFT will switch from these kernels to Rader.
4218\end_layout
4219
4220\begin_layout Plain Layout
4221
4222pfUINT fixMaxRaderPrimeMult;	// switch from Mult Rader's algorithm for radix
4223 primes from this number.
4224 Current limitation for Rader is maxThreadNum/2+1, realistically you would
4225 want to switch somewhere on 30-100 range.
4226 Default is vendor-specific (currently ~40)
4227\end_layout
4228
4229\begin_layout Plain Layout
4230
4231\end_layout
4232
4233\begin_layout Plain Layout
4234
4235pfUINT fixMinRaderPrimeFFT;	// start FFT convolution version of Rader for
4236 radix primes from this number.
4237 Better than direct multiplication version for almost all primes (except
4238 small ones, like 17-23 on some GPUs).
4239 Must be bigger or equal to fixMinRaderPrimeMult.
4240 Deafult 29 on AMD and 17 on other GPUs.
4241 
4242\end_layout
4243
4244\begin_layout Plain Layout
4245
4246pfUINT fixMaxRaderPrimeFFT;	// switch to Bluestein's algorithm for radix
4247 primes from this number.
4248 Switch may happen earlier if prime can't fit in shared memory.
4249 Default is 16384, which is bigger than most current GPU's shared memory.
4250\end_layout
4251
4252\begin_layout Plain Layout
4253
4254\end_layout
4255
4256\begin_layout Plain Layout
4257
4258// Optional zero padding control parameters: (default 0 if not stated otherwise)
4259\end_layout
4260
4261\begin_layout Plain Layout
4262
4263pfUINT performZeropadding[VKFFT_MAX_FFT_DIMENSIONS];	// Don't read some
4264 data/perform computations if some input sequences are zeropadded for each
4265 axis (0 - off, 1 - on)
4266\end_layout
4267
4268\begin_layout Plain Layout
4269
4270pfUINT fft_zeropad_left[VKFFT_MAX_FFT_DIMENSIONS];	// Specify start boundary
4271 of zero block in the system for each axis
4272\end_layout
4273
4274\begin_layout Plain Layout
4275
4276pfUINT fft_zeropad_right[VKFFT_MAX_FFT_DIMENSIONS];	// Specify end boundary
4277 of zero block in the system for each axis
4278\end_layout
4279
4280\begin_layout Plain Layout
4281
4282pfUINT frequencyZeroPadding;	// Set to 1 if zeropadding of frequency domain,
4283 default 0 - spatial zeropadding
4284\end_layout
4285
4286\begin_layout Plain Layout
4287
4288\end_layout
4289
4290\begin_layout Plain Layout
4291
4292// Optional convolution control parameters: (default 0 if not stated otherwise)
4293\end_layout
4294
4295\begin_layout Plain Layout
4296
4297pfUINT performConvolution;	// Perform convolution in this application (0
4298 - off, 1 - on).
4299 Disables reorderFourStep parameter
4300\end_layout
4301
4302\begin_layout Plain Layout
4303
4304pfUINT coordinateFeatures;	// C - coordinate, or dimension of features vector.
4305 In matrix convolution - size of a vector
4306\end_layout
4307
4308\begin_layout Plain Layout
4309
4310pfUINT matrixConvolution;	// If equal to 2 perform 2x2, if equal to 3 perform
4311 3x3 matrix-vector convolution.
4312 Overrides coordinateFeatures
4313\end_layout
4314
4315\begin_layout Plain Layout
4316
4317pfUINT symmetricKernel;	// Specify if kernel in 2x2 or 3x3 matrix convolution
4318 is symmetric
4319\end_layout
4320
4321\begin_layout Plain Layout
4322
4323pfUINT numberKernels;	// N - only used in convolution step - specify how
4324 many kernels were initialized before.
4325 Expands one input to multiple (batched) output
4326\end_layout
4327
4328\begin_layout Plain Layout
4329
4330pfUINT kernelConvolution;	// Specify if this application is used to create
4331 kernel for convolution, so it has the same properties.
4332 performConvolution has to be set to 0 for kernel creation
4333\end_layout
4334
4335\begin_layout Plain Layout
4336
4337\end_layout
4338
4339\begin_layout Plain Layout
4340
4341// Register overutilization (experimental): (default 0 if not stated otherwise)
4342\end_layout
4343
4344\begin_layout Plain Layout
4345
4346pfUINT registerBoost;	// Specify if register file size is bigger than shared
4347 memory and can be used to extend it X times (on Nvidia 256KB register file
4348 can be used instead of 32KB of shared memory, set this constant to 4 to
4349 emulate 128KB of shared memory).
4350 Defaults: Nvidia - 4 in Vulkan/OpenCL, 1 in CUDA backend; AMD - 2 if shared
4351 memory >= 64KB, else 4 in Vulkan/OpenCL backend, 1 in HIP backend; Intel
4352 - 1 if shared memory >= 64KB, else 2 in Vulkan/OpenCL/Level Zero backends,
4353 1 in Metal; Default 1
4354\end_layout
4355
4356\begin_layout Plain Layout
4357
4358pfUINT registerBoostNonPow2;	// Specify if register overutilization should
4359 be used on non power of 2 sequences (0 - off, 1 - on)
4360\end_layout
4361
4362\begin_layout Plain Layout
4363
4364pfUINT registerBoost4Step;	// Specify if register file overutilization should
4365 be used in big sequences (>2^14), same definition as registerBoost.
4366 Default 1
4367\end_layout
4368
4369\begin_layout Plain Layout
4370
4371\end_layout
4372
4373\begin_layout Plain Layout
4374
4375//not used techniques:
4376\end_layout
4377
4378\begin_layout Plain Layout
4379
4380pfUINT devicePageSize;	// In KB, the size of a page on the GPU.
4381 Setting to 0 disables local buffer split in pages
4382\end_layout
4383
4384\begin_layout Plain Layout
4385
4386pfUINT localPageSize;	// In KB, the size to split page into if sequence
4387 spans multiple devicePageSize pages
4388\end_layout
4389
4390\begin_layout Plain Layout
4391
4392\end_layout
4393
4394\begin_layout Plain Layout
4395
4396// Automatically filled based on device info (still can be reconfigured
4397 by user):
4398\end_layout
4399
4400\begin_layout Plain Layout
4401
4402pfUINT computeCapabilityMajor;	// CUDA/HIP compute capability of the device
4403\end_layout
4404
4405\begin_layout Plain Layout
4406
4407pfUINT computeCapabilityMinor;	// CUDA/HIP compute capability of the device
4408 	
4409\end_layout
4410
4411\begin_layout Plain Layout
4412
4413pfUINT maxComputeWorkGroupCount[VKFFT_MAX_FFT_DIMENSIONS];	// maxComputeWorkGrou
4414pCount from VkPhysicalDeviceLimits
4415\end_layout
4416
4417\begin_layout Plain Layout
4418
4419pfUINT maxComputeWorkGroupSize[VKFFT_MAX_FFT_DIMENSIONS];	// maxComputeWorkGroup
4420Count from VkPhysicalDeviceLimits
4421\end_layout
4422
4423\begin_layout Plain Layout
4424
4425pfUINT maxThreadsNum;	// Max number of threads from VkPhysicalDeviceLimits
4426\end_layout
4427
4428\begin_layout Plain Layout
4429
4430pfUINT sharedMemorySizeStatic;	// Available for static allocation shared
4431 memory size, in bytes
4432\end_layout
4433
4434\begin_layout Plain Layout
4435
4436pfUINT sharedMemorySize;	// Available for allocation shared memory size,
4437 in bytes
4438\end_layout
4439
4440\begin_layout Plain Layout
4441
4442pfUINT sharedMemorySizePow2;	// Power of 2 which is less or equal to sharedMemor
4443ySize, in bytes
4444\end_layout
4445
4446\begin_layout Plain Layout
4447
4448pfUINT warpSize;	// Number of threads per warp/wavefront.
4449\end_layout
4450
4451\begin_layout Plain Layout
4452
4453pfUINT halfThreads;	// Intel fix
4454\end_layout
4455
4456\begin_layout Plain Layout
4457
4458pfUINT allocateTempBuffer;	// Buffer allocated by app automatically if needed
4459 to reorder Four step algorithm.
4460 Parameter to check if it has been allocated
4461\end_layout
4462
4463\begin_layout Plain Layout
4464
4465pfUINT reorderFourStep;	// Unshuffle Four step algorithm.
4466 Requires tempbuffer allocation (0 - off, 1 - on).
4467 Default 1.
4468\end_layout
4469
4470\begin_layout Plain Layout
4471
4472pfINT maxCodeLength;	// Specify how big can be buffer used for code generation
4473 (in char).
4474 Default 1000000 chars.
4475 
4476\end_layout
4477
4478\begin_layout Plain Layout
4479
4480pfINT maxTempLength;	// Specify how big can be buffer used for intermediate
4481 string sprintfs be (in char).
4482 Default 5000 chars.
4483 If code segfaults for some reason - try increasing this number.
4484\end_layout
4485
4486\begin_layout Plain Layout
4487
4488pfUINT autoCustomBluesteinPaddingPattern; // default value for useCustomBluestei
4489nPaddingPattern
4490\end_layout
4491
4492\begin_layout Plain Layout
4493
4494pfUINT useRaderUintLUT; // allocate additional LUT to store g_pow
4495\end_layout
4496
4497\begin_layout Plain Layout
4498
4499pfUINT vendorID; // vendorID 0x10DE - NVIDIA, 0x8086 - Intel, 0x1002 - AMD,
4500 etc
4501\end_layout
4502
4503\begin_layout Plain Layout
4504
4505#if(VKFFT_BACKEND==0) //Vulkan API
4506\end_layout
4507
4508\begin_layout Plain Layout
4509
4510VkDeviceMemory tempBufferDeviceMemory;	// Filled at app creation
4511\end_layout
4512
4513\begin_layout Plain Layout
4514
4515VkCommandBuffer* commandBuffer;	// Filled at app execution
4516\end_layout
4517
4518\begin_layout Plain Layout
4519
4520VkMemoryBarrier* memory_barrier;	// Filled at app creation
4521\end_layout
4522
4523\begin_layout Plain Layout
4524
4525#elif(VKFFT_BACKEND==1) //CUDA API
4526\end_layout
4527
4528\begin_layout Plain Layout
4529
4530cudaEvent_t* stream_event;	// Filled at app creation
4531\end_layout
4532
4533\begin_layout Plain Layout
4534
4535pfUINT streamCounter;	// Filled at app creation
4536\end_layout
4537
4538\begin_layout Plain Layout
4539
4540pfUINT streamID;	// Filled at app creation
4541\end_layout
4542
4543\begin_layout Plain Layout
4544
4545#elif(VKFFT_BACKEND==2) //HIP API
4546\end_layout
4547
4548\begin_layout Plain Layout
4549
4550hipEvent_t* stream_event;	// Filled at app creation
4551\end_layout
4552
4553\begin_layout Plain Layout
4554
4555pfUINT streamCounter;	// Filled at app creation
4556\end_layout
4557
4558\begin_layout Plain Layout
4559
4560pfUINT streamID;	// Filled at app creation
4561\end_layout
4562
4563\begin_layout Plain Layout
4564
4565#elif(VKFFT_BACKEND==3) //OpenCL API
4566\end_layout
4567
4568\begin_layout Plain Layout
4569
4570cl_command_queue* commandQueue;	// Filled at app creation
4571\end_layout
4572
4573\begin_layout Plain Layout
4574
4575#elif(VKFFT_BACKEND==4)
4576\end_layout
4577
4578\begin_layout Plain Layout
4579
4580ze_command_list_handle_t* commandList;	// Filled at app creation
4581\end_layout
4582
4583\begin_layout Plain Layout
4584
4585#elif(VKFFT_BACKEND==5)
4586\end_layout
4587
4588\begin_layout Plain Layout
4589
4590MTL::CommandBuffer* commandBuffer;	// Filled at app execution
4591\end_layout
4592
4593\begin_layout Plain Layout
4594
4595MTL::ComputeCommandEncoder* commandEncoder;	// Filled at app execution
4596\end_layout
4597
4598\begin_layout Plain Layout
4599
4600#endif
4601\end_layout
4602
4603\begin_layout Plain Layout
4604
4605} VkFFTConfiguration;
4606\end_layout
4607
4608\begin_layout Plain Layout
4609
4610
4611\backslash
4612end{minted}
4613\end_layout
4614
4615\begin_layout Plain Layout
4616
4617
4618\backslash
4619end{mdframed}
4620\end_layout
4621
4622\end_inset
4623
4624
4625\end_layout
4626
4627\begin_layout Subsubsection
4628Driver API parameters
4629\end_layout
4630
4631\begin_layout Standard
4632In order to work, VkFFT needs some structures that are provided by the driver.
4633 They are backend API-dependent.
4634 VkFFT will return corresponding VkFFTResult if one of these structures
4635 are not provided (value equal to zero) unless it is stated that there is
4636 a default value assigned.
4637 VkFFT will not modify provided values directly.
4638\end_layout
4639
4640\begin_layout Standard
4641Vulkan API will need the following information:
4642\end_layout
4643
4644\begin_layout Itemize
4645VkPhysicalDevice* physicalDevice - Pointer to Vulkan physical device, obtained
4646 from vkEnumeratePhysicalDevices()
4647\end_layout
4648
4649\begin_layout Itemize
4650VkDevice* device - Pointer to Vulkan device, created with vkCreateDevice()
4651\end_layout
4652
4653\begin_layout Itemize
4654VkQueue* queue - Pointer to Vulkan queue, created with vkGetDeviceQueue()
4655\end_layout
4656
4657\begin_layout Itemize
4658VkCommandPool* commandPool - Pointer to Vulkan command pool, created with
4659 vkCreateCommandPool()
4660\end_layout
4661
4662\begin_layout Itemize
4663VkFence* fence - Pointer to Vulkan fence, created with vkCreateFence()
4664\end_layout
4665
4666\begin_layout Itemize
4667uint64_t isCompilerInitialized - Specify if glslang compiler has been intialized
4668 before (0 - off, 1 - on).
4669 Default 0 - VkFFT will call glslang_initialize_process() at initializeVkFFT()
4670 and glslang_finialize_process() at deleteVkFFT() calls.
4671\end_layout
4672
4673\begin_layout Standard
4674CUDA API will need the following information:
4675\end_layout
4676
4677\begin_layout Itemize
4678CUdevice* device - Pointer to CUDA device, obtained from cuDeviceGet()
4679\end_layout
4680
4681\begin_layout Itemize
4682cudaStream_t* stream - Pointer to streams (can be more than 1), where to
4683 execute the kernels.
4684 Default 0.
4685 Streams must be associated with the provided device.
4686 There is no real benefit in having more than one, however.
4687 
4688\end_layout
4689
4690\begin_layout Itemize
4691uint64_t num_streams - Try to submit CUDA kernels in multiple streams for
4692 asynchronous execution.
4693 Default 0, set to >=1 if you pass values in the stream pointer.
4694 
4695\end_layout
4696
4697\begin_layout Standard
4698HIP API will need the following information:
4699\end_layout
4700
4701\begin_layout Itemize
4702hipDevice_t* device - Pointer to HIP device, obtained from hipDeviceGet()
4703\end_layout
4704
4705\begin_layout Itemize
4706hipStream_t* stream - Pointer to streams (can be more than 1), where to
4707 execute the kernels.
4708 Default 0.
4709 Streams must be associated with the provided device.
4710 There is no real benefit in having more than one, however.
4711 
4712\end_layout
4713
4714\begin_layout Itemize
4715uint64_t num_streams - Try to submit HIP kernels in multiple streams for
4716 asynchronous execution.
4717 Default 0, set to >=1 if you pass values in the stream pointer.
4718  
4719\end_layout
4720
4721\begin_layout Standard
4722OpenCL API will need the following information:
4723\end_layout
4724
4725\begin_layout Itemize
4726cl_device_id* device - Pointer to OpenCL device, obtained from clGetDeviceIDs()
4727\end_layout
4728
4729\begin_layout Itemize
4730cl_context* context - Pointer to OpenCL context, obtained from clCreateContext()
4731\end_layout
4732
4733\begin_layout Standard
4734Level Zero API will need the following information:
4735\end_layout
4736
4737\begin_layout Itemize
4738ze_device_handle_t* device - Pointer to Level Zero device, obtained from
4739 zeDeviceGet()
4740\end_layout
4741
4742\begin_layout Itemize
4743ze_context_handle_t* context - Pointer to Level Zero context, obtained from
4744 zeContextGet()
4745\end_layout
4746
4747\begin_layout Itemize
4748ze_command_queue_handle_t* commandQueue - Pointer to Level Zero command
4749 queuewith compute and copy capabilities, obtained from zeCommandQueueCreate()
4750\end_layout
4751
4752\begin_layout Itemize
4753uint32_t commandQueueID - ID of the commandQueue with compute and copy capabilit
4754ies
4755\end_layout
4756
4757\begin_layout Standard
4758Metal API will need the following information:
4759\end_layout
4760
4761\begin_layout Itemize
4762MTL::Device* device - Pointer to Metal device, obtained from MTL::CopyAllDevices
4763\end_layout
4764
4765\begin_layout Itemize
4766MTL::CommandQueue* queue - Pointer to Metal queue, obtained from device->newComm
4767andQueue()
4768\end_layout
4769
4770\begin_layout Subsubsection
4771Memory management parameters
4772\end_layout
4773
4774\begin_layout Standard
4775There are five buffer types user can provide to VkFFT: 
4776\end_layout
4777
4778\begin_layout Itemize
4779the main buffer (buffer)
4780\end_layout
4781
4782\begin_layout Itemize
4783temporary buffer used for calculations requiring out-of-place writes (tempBuffer
4784)
4785\end_layout
4786
4787\begin_layout Itemize
4788separate input buffer, from which initial read is performed (inputBuffer)
4789\end_layout
4790
4791\begin_layout Itemize
4792separate output buffer, to which final write is performed (outputBuffer)
4793\end_layout
4794
4795\begin_layout Itemize
4796kernel buffer, used for calculation of convolutions and cross-correlations
4797 (kernel)
4798\end_layout
4799
4800\begin_layout Standard
4801These buffers must be passed by a pointer: in Vulkan API they are provided
4802 as VkBuffer*, in CUDA, HIP and Level Zero they are provided as void**,
4803 in OpenCL they are provided as cl_mem*, in Metal they are provided as MTL::Buff
4804er*.
4805 Even though the underlying structure (VkBuffer, void*, cl_mem, MTL::Buffer*)
4806 is not a memory but just a number that the driver can use to access correspondi
4807ng allocated memory on the GPU, passing them by a pointer allows for the
4808 user to query multiple GPU allocated buffers for VkFFT to use.
4809 Currently, it is only supported in Vulkan API - each of five buffer types
4810 can be made out of multiple separate memory allocations.
4811 For example, it is possible to combine multiple small unused at the point
4812 of FFT calculation buffers to form a tempBuffer.
4813 This option also allows Vulkan API to overcome the limit of 4GB for a single
4814 memory allocation - due to the fact that Vulkan can only use 32-bit numbers
4815 for addressing (other APIs support 64-bit addressing).
4816 
4817\end_layout
4818
4819\begin_layout Standard
4820To use the buffers other than the main buffer, the user has to specify this
4821 in configuration at the application creation stage (set to zero by default,
4822 optional parameters): 
4823\end_layout
4824
4825\begin_layout Itemize
4826uint64_t userTempBuffer - enables manual temporary buffer allocation (otherwise
4827 it is managed by VkFFT)
4828\end_layout
4829
4830\begin_layout Itemize
4831uint64_t isInputFormatted - specifies that initial read is performed from
4832 a separate buffer (inputBuffer)
4833\end_layout
4834
4835\begin_layout Itemize
4836uint64_t isOutputFormatted - specifies that final write is performed to
4837 a separate buffer (outputBuffer)
4838\end_layout
4839
4840\begin_layout Itemize
4841uint64_t performConvolution - enables convolution calculations, which requires
4842 precomputed kernel (kernel)
4843\end_layout
4844
4845\begin_layout Standard
4846Buffer sizes (bufferSize/tempBufferSize/inputBufferSize/outputBufferSize/kernelS
4847ize) are provided as a uint64_t pointer to an array, where each element
4848 corresponds to the buffer size of the buffer with the same placement in
4849 the buffer array.
4850 Buffer sizes have to be provided in Vulkan API (due to the stricter memory
4851 management model and multiple buffer support) and are optional in other
4852 backends (they can be useful to determine when to switch for 64-bit addressing).
4853\end_layout
4854
4855\begin_layout Standard
4856Buffer number (bufferNum/tempBufferNum/inputBufferNum/outputBufferNum/kernelNum)
4857 corresponds to how many elements are in the buffer and buffer size array.
4858 By default it is set to 1 and is not required to be provided by the user.
4859 Non-Vulkan backends currently don't support values other than default.
4860 Optional parameter.
4861\end_layout
4862
4863\begin_layout Standard
4864Buffer offset (bufferOffset/ tempBufferOffset/ inputBufferOffset/ outputBufferOf
4865fset/ kernelOffset) specifies offset from the start of the buffer sequence.
4866 It must be specified in bytes and must be divisible by the number type
4867 size used in the corresponding array (otherwise, the offset will be truncated).
4868 It is provided as a single uint64_t value.
4869 Can be provided at launch time, if specifyOffsetsAtLaunch parameter is
4870 enabled during initialization call.
4871 Optional parameters.
4872\end_layout
4873
4874\begin_layout Standard
4875User can provide custom dimension strides for buffer/inputBuffer/outputBuffer
4876 buffers - uint64_t[VKFFT_MAX_FFT_DIMENSIONS] array.
4877 Strides are specified in elements used in the array (not bytes).
4878 The first element corresponds to the stride between elements in the H direction
4879, the second corresponds to the D direction and the third to C (or N, if
4880 the number of elements in C is 1).
4881 The first axis is assumed to be non-strided.
4882 Must be at least of the same size as default strides, otherwise the behavior
4883 is undefined.
4884 Optional parameters.
4885\end_layout
4886
4887\begin_layout Standard
4888uint64_t inverseReturnToInputBuffer - an option that allows setting the
4889 final output buffer of the inverse transform to the same buffer, initial
4890 read of forward transform is performed from (inputBuffer, if isInputFormatted
4891 enabled).
4892 Optional parameter.
4893\end_layout
4894
4895\begin_layout Subsubsection
4896General FFT parameters 
4897\end_layout
4898
4899\begin_layout Standard
4900This section describes part of the configuration structure responsible for
4901 FFT specification.
4902 
4903\end_layout
4904
4905\begin_layout Standard
4906uint64_t FFTdim - dimensionality of the transform (up to VKFFT_MAX_FFT_DIMENSION
4907S).
4908 Required parameter.
4909\end_layout
4910
4911\begin_layout Standard
4912uint64_t size[VKFFT_MAX_FFT_DIMENSIONS] - WHD+ dimensions of the transform.
4913 Required parameter.
4914\end_layout
4915
4916\begin_layout Standard
4917uint64_t numberBatches - N parameter of the transform.
4918 By default, it is set to 1.
4919 Optional parameter.
4920\end_layout
4921
4922\begin_layout Standard
4923uint64_t performR2C - perform R2C/C2R decomposition.
4924 performDCT and performDST must be set to 0.
4925 Default 0, set to 1 to enable.
4926 Optional parameter.
4927\end_layout
4928
4929\begin_layout Standard
4930uint64_t performDCT - perform DCT transformation.
4931 performR2C and performDST must be set to 0.
4932 Default 0, set to X for DCT-X (currently supported X: 1, 2, 3 and 4).
4933 Optional parameter.
4934\end_layout
4935
4936\begin_layout Standard
4937uint64_t performDST - perform DST transformation.
4938 performR2C and performDCT must be set to 0.
4939 Default 0, set to X for DST-X (currently supported X: 1, 2, 3 and 4).
4940 Optional parameter.
4941\end_layout
4942
4943\begin_layout Standard
4944uint64_t normalize - enabling this parameter will make the inverse transform
4945 divide the result by the FFT length.
4946 Default 0, set to 1 to enable.
4947 Optional parameter.
4948\end_layout
4949
4950\begin_layout Subsubsection
4951Precision parameters (and some things that can affect it):
4952\end_layout
4953
4954\begin_layout Standard
4955uint64_t doublePrecision - perform calculations in double precision.
4956 Default 0, set to 1 to enable.
4957 In Vulkan/OpenCL/Level Zero your device must support double precision functiona
4958lity.
4959 Metal API does not support double precision.
4960 Optional parameter.
4961\end_layout
4962
4963\begin_layout Standard
4964uint64_t doublePrecisionFloatMemory - perform calculations in double precision,
4965 but all intermediate and final storage in float.
4966 Input/Output/main buffers must have single-precision layout.
4967 doublePrecision must be set to 0.
4968 This option increases precision, but not that much to be recommended for
4969 actual use.
4970 Default 0, set to 1 to enable.
4971 In Vulkan/OpenCL/Level Zero your device must support double precision functiona
4972lity.
4973 Metal API does not support double precision.
4974 Optional parameter.
4975\end_layout
4976
4977\begin_layout Standard
4978uint64_t quadDoubleDoublePrecision - perform calculations in double-double
4979 emulation of quad precision (0 - off, 1 - on).
4980 Optional parameter.
4981 Requires quadmath library (for now).
4982\end_layout
4983
4984\begin_layout Standard
4985uint64_t quadDoubleDoublePrecisionDoubleMemory - perform calculations in
4986 double-double emulation of quad precision, while all memory storage is
4987 done in FP64.
4988 Optional parameter.
4989 Requires quadmath library (for now).
4990\end_layout
4991
4992\begin_layout Standard
4993uint64_t halfPrecision - half-precision in VkFFT is implemented only as
4994 memory optimization.
4995 All calculations are done in single precision (similar way as doublePrecisionFl
4996oatMemory works for double and single precision).
4997 Default 0, set to 1 to enable.
4998 Optional parameter.
4999\end_layout
5000
5001\begin_layout Standard
5002uint64_t halfPrecisionMemoryOnly - another way of performing half-precision
5003 in VkFFT, it will use half-precision only for initial and final memory
5004 storage in input/output buffer.
5005 Input/Output have to be allocated as half, buffer/tempBuffer have to be
5006 allocated as float (out-of-place mode only).
5007 Specify isInputFormatted and isOutputFormatted to use.
5008 So, for example, intermediate storage between axes FFTs in the multidimensional
5009 case will be done in single precision, as opposed to half-precision in
5010 the base halfPrecision case.
5011 halfPrecision must be set to 1.
5012 Default 0, set to 1 to enable.
5013 Optional parameter.
5014\end_layout
5015
5016\begin_layout Standard
5017int64_t useLUT - switches from calculating sines and cosines (via special
5018 function units in single precision or as a polynomial approximation in
5019 double precision) to using precomputed Look-Up Tables.
5020 -1 - off, 0 - auto, 1 - on.
5021 Default 0 in single precision, 1 in double precision.
5022 Set to 1 by default for Intel GPUs.
5023 If you have issues with single-precision accuracy on your GPU, try enabling
5024 this parameter (mobile GPUs may be affected).
5025 Optional parameter.
5026\end_layout
5027
5028\begin_layout Standard
5029int64_t useLUT_4step - switches from calculating sincos to using precomputed
5030 LUT tables for intermediate roots of 1 in the Four-step FFT algorithm.
5031 (-1 - off, 0 - auto, 1 - on).
5032 Configured by initialization routine.
5033 Optional parameter.
5034 
5035\end_layout
5036
5037\begin_layout Subsubsection
5038Advanced parameters (code will work fine without using them)
5039\end_layout
5040
5041\begin_layout Standard
5042uint64_t omitDimension[VKFFT_MAX_FFT_DIMENSIONS] - parameter, that disables
5043 the FFT calculation for a particular axis (WHD).
5044 Note, that omitted dimensions still need to be included in FFTdim and size.
5045 This parameter simply works as a switch during execution - by not executing
5046 the particular dimension code.
5047 It doesn't work with the non-strided axis (W) of R2C/C2R mode.
5048 It doesn't work with convolution calculations.
5049 Default 0, set to 1 to enable.
5050 Optional parameter.
5051\end_layout
5052
5053\begin_layout Standard
5054uint64_t useUint64 - forces VkFFT to use 64-bit addressing in generated
5055 kernels.
5056 It is automatically enabled if the estimated buffer size is more than 4GB.
5057 Doesn't work with the Vulkan backend.
5058 By default, it is set to 0.
5059 Optional parameter.
5060\end_layout
5061
5062\begin_layout Standard
5063uint64_t coalescedMemory - number of bytes to coalesce per one transaction.
5064 For Nvidia and AMD is equal to 32, Intel is equal to 64.
5065 Going to work regardless, but if specified by the user correctly, the performan
5066ce will be higher.
5067 Default 64 for other GPUs.
5068 For half-precision should be multiplied by two.
5069 Should be a power of two.
5070 Optional parameter.
5071\end_layout
5072
5073\begin_layout Standard
5074uint64_t numSharedBanks - configure the number of shared banks on the target
5075 GPU.
5076 Default 32.
5077 Minor performance boost as it solves shared memory conflicts for the power
5078 of two systems.
5079 Optional parameter.
5080\end_layout
5081
5082\begin_layout Standard
5083uint64_t aimThreads - try to aim all kernels at this amount of threads.
5084 Gains/losses are not predictable, just a parameter to play with (it is
5085 not guaranteed that the target kernel will use that many threads).
5086 Default 128.
5087 Optional parameter.
5088\end_layout
5089
5090\begin_layout Standard
5091uint64_t useUint64 - forces 64-bit addressing in generated kernels.
5092 Should be enabled automatically for systems spanning more than 4GB, but
5093 it is better to have an option to force it as a failsafe.
5094 Doesn't work in Vulkan API (use multiple buffer binding).
5095 Default 0, set to 1 to enable.
5096 Optional parameter.
5097\end_layout
5098
5099\begin_layout Standard
5100int performBandwidthBoost - try to reduce coalsesced number by a factor
5101 of X to get bigger sequence in one upload for strided axes.
5102 Default: -1(inf) for DCT and DST, 2 for Bluestein's algorithm (or -1 if
5103 DCT and DST), 0 otherwise 
5104\end_layout
5105
5106\begin_layout Standard
5107uint64_t disableMergeSequencesR2C - disable the optimization that performs
5108 merging of two real sequences to reduce calculations (in R2C/C2R and R2R).
5109 If enabled, calculations will be performed by simply setting the imaginary
5110 component to zero.
5111 Default 0, set to 1 to enable.
5112 Optional parameter.
5113\end_layout
5114
5115\begin_layout Standard
5116uint64_t forceCallbackVersionRealTransforms - force callback version of
5117 R2C and R2R algorithms for all usecases (0 - off, 1 - on) 
5118\end_layout
5119
5120\begin_layout Standard
5121uint64_t disableReorderFourStep - disables unshuffling of the Four Step
5122 FFT algorithm (last transposition of data).
5123 With this option enabled, tempBuffer will not be needed (unless it is required
5124 by Bluestein's multi-upload FFT algorithm).
5125 Default 0, set to 1 to enable.
5126 Automatically enabled for convolution calculations and Bluestein's algorithm.
5127 Optional parameter.
5128\end_layout
5129
5130\begin_layout Standard
5131uint64_t makeForwardPlanOnly - generate code only for forward FFT.
5132 Default 0, set to 1 to enable.
5133 Mutually exclusive with makeInversePlanOnly.
5134 Optional parameter.
5135\end_layout
5136
5137\begin_layout Standard
5138uint64_t makeInversePlanOnly - generate code only for inverse FFT.
5139 Default 0, set to 1 to enable.
5140 Mutually exclusive with makeForwardPlan.
5141 Optional parameter.
5142\end_layout
5143
5144\begin_layout Standard
5145uint64_t considerAllAxesStrided - will create a plan for a non-strided axis
5146 similar to a strided axis (used with disableReorderFourStep to get the
5147 same layout for Bluestein kernel).
5148 Default 0, set to 1 to enable.
5149 Optional parameter.
5150\end_layout
5151
5152\begin_layout Standard
5153uint64_t keepShaderCode - debugging option, will keep shader code and print
5154 all executed shaders during the plan execution in order.
5155 Default 0, set to 1 to enable.
5156 Optional parameter.
5157\end_layout
5158
5159\begin_layout Standard
5160uint64_t printMemoryLayout - debugging option, will print order of buffers
5161 used in kernels.
5162 Default 0, set to 1 to enable.
5163 Optional parameter.
5164 
5165\end_layout
5166
5167\begin_layout Standard
5168uint64_t saveApplicationToString - will save all compiled binaries to VkFFTAppli
5169cation.saveApplicationString (will be allocated by VkFFT, deallocated with
5170 deleteVkFFT call).
5171 VkFFTApplication.applicationStringSize will contain size of binary in bytes.
5172 Currently disabled in Metal backend.
5173 Default 0, set to 1 to enable.
5174 Optional parameter.
5175\end_layout
5176
5177\begin_layout Standard
5178uint64_t loadApplicationFromString - will load all binaries from loadApplication
5179String instead of recompiling them (loadApplicationString must be allocated
5180 by user, must contain what saveApplicationToString call generated previously
5181 in VkFFTApplication.saveApplicationString).
5182 Currently disabled in Metal backend.
5183 Default 0, set to 1 to enable.
5184 Optional parameter.
5185 Mutually exclusive with saveApplicationToString 
5186\end_layout
5187
5188\begin_layout Standard
5189void* loadApplicationString - memory binary array through which user can
5190 load VkFFT binaries, must be provided by user if loadApplicationFromString
5191 = 1.
5192 Use rb/wb flags to load/save.
5193\end_layout
5194
5195\begin_layout Standard
5196uint64_t disableSetLocale - disables all VkFFT attempts to set locale to
5197 C - user must ensure that VkFFT has C locale during the plan initialization.
5198 This option is needed for multithreading.
5199 Default 0.
5200\end_layout
5201
5202\begin_layout Standard
5203uint64_t groupedBatch[VKFFT_MAX_FFT_DIMENSIONS] - try to force this many
5204 FFTs to be perfromed by one threadblock for each dimension.
5205 Optional parameter.
5206 
5207\end_layout
5208
5209\begin_layout Subsubsection
5210Rader control parameters
5211\end_layout
5212
5213\begin_layout Standard
5214uint64_t fixMinRaderPrimeMult - start direct multiplication Rader's algorithm
5215 for radix primes from this number.
5216 This means that VkFFT will inline custom Rader kernels if sequence is divisible
5217 by these primes.
5218 Default is 17, as VkFFT has kernels for 2-13.
5219 If you make it less than 13, VkFFT will switch from these kernels to Rader.
5220\end_layout
5221
5222\begin_layout Standard
5223uint64_t fixMaxRaderPrimeMult - switch from Mult Rader's algorithm for radix
5224 primes from this number.
5225 Current limitation for Rader is maxThreadNum/2+1, realistically you would
5226 want to switch somewhere on 30-100 range.
5227 Default is vendor-specific (currently ~40)
5228\end_layout
5229
5230\begin_layout Standard
5231uint64_t fixMinRaderPrimeFFT - start FFT convolution version of Rader for
5232 radix primes from this number.
5233 Better than direct multiplication version for almost all primes (except
5234 small ones, like 17-23 on some GPUs).
5235 Must be bigger or equal to fixMinRaderPrimeMult.
5236 Deafult 29 on AMD and 17 on other GPUs.
5237 
5238\end_layout
5239
5240\begin_layout Standard
5241uint64_t fixMaxRaderPrimeFFT - switch to Bluestein's algorithm for radix
5242 primes from this number.
5243 Switch may happen earlier if prime can't fit in shared memory.
5244 Default is 16384, which is bigger than most current GPU's shared memory.
5245\end_layout
5246
5247\begin_layout Subsubsection
5248Bluestein control parameters
5249\end_layout
5250
5251\begin_layout Standard
5252If the sequence can not be decomposed as a multiplication of primes up to
5253 13, FFT is performed as a convolution.
5254 The sequence to pad to with the best performance is usually device-dependent.
5255 VkFFT uses parameters manually tuned for all sequences between 2 and 4096
5256 for both double and single precision on Nvidia A100 (Nvidia profile) and
5257 AMD MI250 (default profile).
5258 To control this process, VkFFT allows for the following parameters specificatio
5259n:
5260\end_layout
5261
5262\begin_layout Standard
5263uint64_t fixMaxRadixBluestein - controls the padding of sequences in Bluestein
5264 convolution.
5265 If specified, padded sequence will be made of up to fixMaxRadixBluestein
5266 primes.
5267 Default: 2 for CUDA and Vulkan/OpenCL/HIP up to 1048576 combined dimension
5268 FFT system, 7 for Vulkan/OpenCL/HIP past after.
5269 Min = 2, Max = 13.
5270\end_layout
5271
5272\begin_layout Standard
5273uint64_t forceBluesteinSequenceSize - force the sequence size to pad to
5274 in Bluestein's algorithm.
5275 Must be at least 2*N-1 and decomposable with primes 2-13.
5276\end_layout
5277
5278\begin_layout Standard
5279uint64_t useCustomBluesteinPaddingPattern - force the sequence sizes to
5280 pad to in Bluestein's algorithm, but on a range.
5281 This number specifies the number of elements in primeSizes and in paddedSizes
5282 arrays.
5283 primeSizes - array of non-decomposable as radix scheme sizes - 17, 23,
5284 31 etc.
5285 paddedSizes - array of lengths to pad to.
5286 paddedSizes[i] will be the padding size for all non-decomposable sequences
5287 from primeSizes[i] to primeSizes[i+1] (will use default scheme after last
5288 one) - 42, 60, 64 for primeSizes before and 37+ will use default scheme
5289 (for example).
5290 Default is vendor and API-based specified in autoCustomBluesteinPaddingPattern.
5291\end_layout
5292
5293\begin_layout Standard
5294uint64_t* primeSizes - described in useCustomBluesteinPaddingPattern
5295\end_layout
5296
5297\begin_layout Standard
5298uint64_t* paddedSizes - described in useCustomBluesteinPaddingPattern
5299\end_layout
5300
5301\begin_layout Subsubsection
5302Zero padding parameters
5303\end_layout
5304
5305\begin_layout Standard
5306uint64_t performZeropadding[VKFFT_MAX_FFT_DIMENSIONS] - do not read/write
5307 some data/perform computations if some part of the sequence is known to
5308 have zeros.
5309 Set separately for each axis (WHD).
5310 If enabled, all 1D sequences in this direction will be considered padded
5311 (independent of other zero-padded axes).
5312 Default 0, set to 1 to enable.
5313 Optional parameter.
5314 
5315\end_layout
5316
5317\begin_layout Standard
5318uint64_t fft_zeropad_left[VKFFT_MAX_FFT_DIMENSIONS] - specify start boundary
5319 of zero block in the system for each axis.
5320 Default 0, set to the value between 0 and size[X]-1.
5321 Optional parameter.
5322\end_layout
5323
5324\begin_layout Standard
5325uint64_t fft_zeropad_right[VKFFT_MAX_FFT_DIMENSIONS] - specify end boundary
5326 of zero block in the system for each axis.
5327 Default 0, set to the value between fft_zeropad_left[X] and size[X]-1.
5328 Optional parameter.
5329\end_layout
5330
5331\begin_layout Standard
5332uint64_t frequencyZeroPadding - enables zero padding of the frequency domain,
5333 so the first read of inverse FFT will consider the parts of the system
5334 from fft_zeropad_left to fft_zeropad_right as zero.
5335 Default 0 - spatial zero padding, set to 1 to enable.
5336 Optional parameter.
5337 
5338\end_layout
5339
5340\begin_layout Subsubsection
5341Convolution parameters
5342\end_layout
5343
5344\begin_layout Standard
5345uint64_t performConvolution - main parameter that enables convolutions in
5346 the application.
5347 If enabled, you must specify kernel buffer, number of kernel buffers and
5348 kernel sizes (in Vulkan API).
5349 Disables reordering of the Four Step FFT algorithm.
5350 Default 0, set to 1 to enable.
5351 Optional parameter.
5352 
5353\end_layout
5354
5355\begin_layout Standard
5356uint64_t conjugateConvolution - default 0, set to 1 to enable enables conjugatio
5357n of the sequence FFT is currently done on, 2 to enable conjugation of the
5358 convolution kernel.
5359 Optional parameter.
5360 
5361\end_layout
5362
5363\begin_layout Standard
5364uint64_t crossPowerSpectrumNormalization - normalize the FFT * kernel multiplica
5365tion in frequency domain.
5366 Default 0, set to 1 to enable.
5367 Optional parameter.
5368 
5369\end_layout
5370
5371\begin_layout Standard
5372uint64_t coordinateFeatures - max coordinate (C), or dimension of the features
5373 vector.
5374 In matrix convolution - the size of the vector.
5375 The main purpose is to support Matrix-Vector convolutions.
5376 Use numberBatches parameter in tasks, not requiring two separate coordinate-lik
5377e enumerations of data.
5378 Default 1.
5379 Optional parameter.
5380\end_layout
5381
5382\begin_layout Standard
5383uint64_t matrixConvolution - set to 2 to perform 2x2, set to 3 to perform
5384 3x3 matrix-vector convolution.
5385 Matrix-vector convolution is a form of point-wise multiplication in the
5386 Fourier space, used by the convolution theorem, where multiplication takes
5387 the form of Matrix-vector multiplication.
5388 Overrides coordinateFeatures during execution.
5389 Default 0.
5390 Optional parameter.
5391 
5392\end_layout
5393
5394\begin_layout Standard
5395uint64_t symmetricKernel - specify if kernel in 2x2 or 3x3 matrix convolution
5396 is symmetric.
5397 You need to store data as xx, xy, yy (upper-triangular) if enabled and
5398 as xx, xy, yx, yy (along rows then along columns, from left to right) if
5399 disabled.
5400 Default 0, set to 1 to enable.
5401 Optional parameter.
5402 
5403\end_layout
5404
5405\begin_layout Standard
5406uint64_t numberKernels - specify how many kernels were initialized before
5407 performing one input/multiple output convolutions.
5408 Overwrites numberBatches (N).
5409 Only used in convolution step and the following inverse transforms.
5410 Default 1.
5411 Optional parameter.
5412 
5413\end_layout
5414
5415\begin_layout Standard
5416uint64_t kernelConvolution - specify if this application is used to create
5417 kernel for convolution, so it has the same properties/memory layout.
5418 performConvolution has to be set to 0 for the kernel creation.
5419 Default 0, set to 1 to enable.
5420 Optional parameter, but it is a required parameter for kernel generation.
5421\end_layout
5422
5423\begin_layout Subsubsection
5424Register overutilization
5425\end_layout
5426
5427\begin_layout Standard
5428Only works in C2C mode, without convolution support.
5429 Enabled in Vulkan, OpenCL and Level Zero APIs only (it works in other APIs,
5430 but worse, does not work in Metal).
5431 Experimental feature.
5432\end_layout
5433
5434\begin_layout Standard
5435uint64_t registerBoost - specify if the register file size is bigger than
5436 shared memory and can be used to extend it X times (on Nvidia 256KB register
5437 file can be used instead of 32KB of shared memory, set this constant to
5438 4 to emulate 128KB of shared memory).
5439 Default 1 - no overutilization.
5440 In Vulkan, OpenCL and Level Zero it is set to 4 on Nvidia GPUs, to 2 if
5441 the driver shows 64KB or more of shared memory on AMD, to 2 if the driver
5442 shows less than 64KB of shared memory on AMD, to 1 if the driver shows
5443 64KB or more of shared memory on Intel, to 2 if the driver shows less than
5444 64KB of shared memory on Intel.
5445 Optional parameter.
5446\end_layout
5447
5448\begin_layout Standard
5449uint64_t registerBoostNonPow2 - specify if register overutilization should
5450 be used on non-power of 2 sequences.
5451 Default 0, set to 1 to enable.
5452 Optional parameter.
5453\end_layout
5454
5455\begin_layout Standard
5456uint64_t registerBoost4Step - specify if register file overutilization should
5457 be used in big sequences (>2^14), same definition as registerBoost.
5458 Default 1.
5459 Optional parameter.
5460\end_layout
5461
5462\begin_layout Subsubsection
5463Extra advanced parameters (filled automatically)
5464\end_layout
5465
5466\begin_layout Standard
5467uint64_t computeCapabilityMajor - CUDA/HIP compute capability of the device
5468\end_layout
5469
5470\begin_layout Standard
5471uint64_t computeCapabilityMinor - CUDA/HIP compute capability of the device
5472 
5473\end_layout
5474
5475\begin_layout Standard
5476uint64_t maxComputeWorkGroupCount[3] - how many workgroups can be launched
5477 at one dispatch.
5478 Automatically derived from the driver, can be artificially lowered.
5479 Then VkFFT will perform a logical split and extension of the number of
5480 workgroups to cover the required range.
5481\end_layout
5482
5483\begin_layout Standard
5484uint64_t maxComputeWorkGroupSize[3] - max dimensions of the workgroup.
5485 Automatically derived from the driver.
5486 Can be modified if there are some issues with the driver (as there were
5487 with ROCm 4.0, when it returned 1024 for maxComputeWorkGroupSize and actually
5488 supported only up to 256 threads).
5489\end_layout
5490
5491\begin_layout Standard
5492uint64_t maxThreadsNum - max number of threads per block.
5493 Similar to maxComputeWorkGroupSize, but aggregated.
5494 Automatically derived from the driver.
5495\end_layout
5496
5497\begin_layout Standard
5498uint64_t sharedMemorySizeStatic - available for static allocation shared
5499 memory size, in bytes.
5500 Automatically derived from the driver.
5501 Can be controlled by the user, if desired.
5502\end_layout
5503
5504\begin_layout Standard
5505uint64_t sharedMemorySize - available for allocation shared memory size,
5506 in bytes.
5507 VkFFT uses dynamic shared memory in CUDA/HIP as it allows for bigger allocation
5508s.
5509 Automatically derived from the driver.
5510 Can be controlled by the user, if desired.
5511\end_layout
5512
5513\begin_layout Standard
5514uint64_t sharedMemorySizePow2 - the power of 2 which is less or equal to
5515 sharedMemorySize, in bytes.
5516 Automatically computed.
5517\end_layout
5518
5519\begin_layout Standard
5520uint64_t warpSize - number of threads per warp/wavefront.
5521 Automatically derived from the driver, but can be modified (can increase
5522 performance, though unpredictable as defaults have good values).
5523 Must be a power of two.
5524\end_layout
5525
5526\begin_layout Standard
5527uint64_t halfThreads - Intel GPU fix, tries to reduce the amount of dispatched
5528 threads in half to solve performance degradation in the Four Step FFT algorithm.
5529 Default 0 for other GPUs, try enabling it if performance degrades in the
5530 Four Step FFT algorithm for your GPU as well.
5531 
5532\end_layout
5533
5534\begin_layout Standard
5535int64_t maxCodeLength - specify how big can the buffer used for code generation
5536 be (in char).
5537 Default 1000000 chars.
5538 
5539\end_layout
5540
5541\begin_layout Standard
5542int64_t maxTempLength - specify how big can the buffer used for intermediate
5543 string sprintf's be (in char).
5544 Default 5000 chars.
5545 If code segfaults for some reason - try increasing this number.
5546\end_layout
5547
5548\begin_layout Standard
5549uint64_t autoCustomBluesteinPaddingPattern - default value for useCustomBluestei
5550nPaddingPattern
5551\end_layout
5552
5553\begin_layout Standard
5554uint64_t useRaderUintLUT - allocate additional LUT to store g_pow 
5555\end_layout
5556
5557\begin_layout Standard
5558uint64_t vendorID - vendorID 0x10DE - NVIDIA, 0x8086 - Intel, 0x1002 - AMD,
5559 etc.
5560\end_layout
5561
5562\begin_layout Standard
5563\begin_inset Newpage newpage
5564\end_inset
5565
5566
5567\end_layout
5568
5569\begin_layout Section
5570VkFFT Benchmark/Precision Suite and utils_VkFFT helper routines
5571\end_layout
5572
5573\begin_layout Standard
5574The only licensed (MIT) part of the VkFFT repository is the VkFFT header
5575 file - core library.
5576 Other files are either external helper libraries (half, glslang, with their
5577 respective licenses) or unlicensed code that is intended for simple copy-pastin
5578g (benchmark_scripts, utils_VkFFT.h).
5579 It is the easiest way to understand how to use VkFFT by taking the provided
5580 scripts and tinker them to the particular task.
5581 The current version of the benchmark and precision verification suite has
5582 the following codes available:
5583\end_layout
5584
5585\begin_layout Itemize
5586user_benchmark_VkFFT - generalization of the main configuration parameters
5587 that can be used to launch simplest in-place transforms for the most important
5588 supported functionality
5589\end_layout
5590
5591\begin_layout Itemize
5592Sample 0 - FFT + iFFT C2C benchmark 1D batched in single precision
5593\end_layout
5594
5595\begin_layout Itemize
5596Sample 1 - FFT + iFFT C2C benchmark 1D batched in double precision
5597\end_layout
5598
5599\begin_layout Itemize
5600Sample 2 - FFT + iFFT C2C benchmark 1D batched in half precision
5601\end_layout
5602
5603\begin_layout Itemize
5604Sample 3 - FFT + iFFT C2C multidimensional benchmark in single precision
5605\end_layout
5606
5607\begin_layout Itemize
5608Sample 4 - FFT + iFFT C2C multidimensional benchmark in single precision,
5609 native zeropadding
5610\end_layout
5611
5612\begin_layout Itemize
5613Sample 5 - FFT + iFFT C2C benchmark 1D batched in single precision, no reshuffli
5614ng
5615\end_layout
5616
5617\begin_layout Itemize
5618Sample 6 - FFT + iFFT R2C / C2R benchmark, in-place.
5619\end_layout
5620
5621\begin_layout Itemize
5622Sample 7 - FFT + iFFT C2C Bluestein benchmark in single precision
5623\end_layout
5624
5625\begin_layout Itemize
5626Sample 8 - FFT + iFFT C2C Bluestein benchmark in double precision
5627\end_layout
5628
5629\begin_layout Itemize
5630Sample 9 - FFT + iFFT C2C benchmark 1D batched in double-double emulation
5631 of quad precision
5632\end_layout
5633
5634\begin_layout Itemize
5635Sample 10 - multiple buffers (4 by default) split version of benchmark 0
5636\end_layout
5637
5638\begin_layout Itemize
5639Sample 11 - VkFFT / xFFT / FFTW C2C precision test in single precision (xFFT
5640 can be cuFFT or rocFFT)
5641\end_layout
5642
5643\begin_layout Itemize
5644Sample 12 - VkFFT / xFFT / FFTW C2C precision test in double precision (xFFT
5645 can be cuFFT or rocFFT)
5646\end_layout
5647
5648\begin_layout Itemize
5649Sample 13 - VkFFT / cuFFT / FFTW C2C precision test in half precision
5650\end_layout
5651
5652\begin_layout Itemize
5653Sample 14 - VkFFT / FFTW C2C radix 3 / 5 / 7 / 11 / 13 / Bluestein precision
5654 test in single precision
5655\end_layout
5656
5657\begin_layout Itemize
5658Sample 15 - VkFFT / xFFT / FFTW R2C+C2R precision test in single precision,
5659 out-of-place.
5660 (xFFT can be cuFFT or rocFFT)
5661\end_layout
5662
5663\begin_layout Itemize
5664Sample 16 - VkFFT / FFTW R2R DCT-I, II, III and IV precision test in single
5665 precision
5666\end_layout
5667
5668\begin_layout Itemize
5669Sample 17 - VkFFT / FFTW R2R DCT-I, II, III and IV precision test in double
5670 precision
5671\end_layout
5672
5673\begin_layout Itemize
5674Sample 18 - VkFFT / FFTW C2C radix 3 / 5 / 7 / 11 / 13 / Bluestein precision
5675 test in double precision
5676\end_layout
5677
5678\begin_layout Itemize
5679Sample 19 - VkFFT / FFTW C2C precision test in double-double emulation of
5680 quad precision
5681\end_layout
5682
5683\begin_layout Itemize
5684Sample 50 - convolution example with identity kernel
5685\end_layout
5686
5687\begin_layout Itemize
5688Sample 51 - zero padding convolution example with identity kernel
5689\end_layout
5690
5691\begin_layout Itemize
5692Sample 52 - batched convolution example with identity kernel
5693\end_layout
5694
5695\begin_layout Itemize
5696Sample 100 - VkFFT FFT + iFFT R2R DCT multidimensional benchmark in single
5697 precision
5698\end_layout
5699
5700\begin_layout Itemize
5701Sample 101 - VkFFT FFT + iFFT R2R DCT multidimensional benchmark in double
5702 precision
5703\end_layout
5704
5705\begin_layout Itemize
5706Sample 1000 - FFT + iFFT C2C benchmark 1D batched in single precision: all
5707 supported systems from 2 to 4096
5708\end_layout
5709
5710\begin_layout Itemize
5711Sample 1001 - FFT + iFFT C2C benchmark 1D batched in double precision: all
5712 supported systems from 2 to 4096
5713\end_layout
5714
5715\begin_layout Itemize
5716Sample 1002 - FFT + iFFT C2C benchmark 1D batched in half precision: all
5717 supported systems from 2 to 4096
5718\end_layout
5719
5720\begin_layout Itemize
5721Sample 1003 - FFT + iFFT C2C benchmark 1D batched in single precision: all
5722 supported systems from 2 to 4096
5723\end_layout
5724
5725\begin_layout Itemize
5726Sample 1004 - FFT + iFFT C2C benchmark 1D batched in double-double emulation
5727 of quad precision: all supported systems from 2 to 4096
5728\end_layout
5729
5730\begin_layout Subsection
5731utils_VkFFT helper routines
5732\end_layout
5733
5734\begin_layout Standard
5735Launching even the simplest Vulkan application can be a non-trivial task.
5736 To help with this, utils_VkFFT contains the routines that can help to create
5737 the simplest Vulkan application, allocate memory, record command buffers
5738 and launch them.
5739 Code has some comments explaining what is going on at each step.
5740 It also has some useful struct defines (like vkGPU) that keep the most
5741 important handles used in Vulkan Compute.
5742 This section may be expanded in the future to the proper step-by-step guide
5743 on Vulkan Compute simple application creation.
5744 I also encourage to check https://github.com/DTolm/VulkanComputeSamples-Transpos
5745ition repository for another example of a compute algorithm (matrix transpositio
5746n) implemented with Vulkan API.
5747\end_layout
5748
5749\begin_layout Standard
5750utils_VkFFT also has a routine that prints the list of available devices.
5751\end_layout
5752
5753\begin_layout Standard
5754vkGPU struct has the following definition:
5755\end_layout
5756
5757\begin_layout Standard
5758\begin_inset ERT
5759status open
5760
5761\begin_layout Plain Layout
5762
5763
5764\backslash
5765begin{mdframed}[backgroundcolor=bg]
5766\end_layout
5767
5768\begin_layout Plain Layout
5769
5770
5771\backslash
5772begin{minted}[tabsize=4,obeytabs,breaklines]{C}
5773\end_layout
5774
5775\begin_layout Plain Layout
5776
5777typedef struct {
5778\end_layout
5779
5780\begin_layout Plain Layout
5781
5782#if(VKFFT_BACKEND==0) //Vulkan API
5783\end_layout
5784
5785\begin_layout Plain Layout
5786
5787VkInstance instance; //a connection between the application and the Vulkan
5788 library
5789\end_layout
5790
5791\begin_layout Plain Layout
5792
5793VkPhysicalDevice physicalDevice; //a handle for the graphics card used in
5794 the application
5795\end_layout
5796
5797\begin_layout Plain Layout
5798
5799VkPhysicalDeviceProperties physicalDeviceProperties; //bastic device properties
5800\end_layout
5801
5802\begin_layout Plain Layout
5803
5804VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties; //basic
5805 memory properties of the device
5806\end_layout
5807
5808\begin_layout Plain Layout
5809
5810VkDevice device; //a logical device, interacting with physical device
5811\end_layout
5812
5813\begin_layout Plain Layout
5814
5815VkDebugUtilsMessengerEXT debugMessenger; //extension for debugging
5816\end_layout
5817
5818\begin_layout Plain Layout
5819
5820uint64_t queueFamilyIndex; //if multiple queues are available, specify the
5821 used one
5822\end_layout
5823
5824\begin_layout Plain Layout
5825
5826VkQueue queue; //a place, where all operations are submitted
5827\end_layout
5828
5829\begin_layout Plain Layout
5830
5831VkCommandPool commandPool; //an opaque objects that command buffer memory
5832 is allocated from
5833\end_layout
5834
5835\begin_layout Plain Layout
5836
5837VkFence fence; //a vkGPU->fence used to synchronize dispatches
5838\end_layout
5839
5840\begin_layout Plain Layout
5841
5842std::vector<const char*> enabledDeviceExtensions;
5843\end_layout
5844
5845\begin_layout Plain Layout
5846
5847uint64_t enableValidationLayers;
5848\end_layout
5849
5850\begin_layout Plain Layout
5851
5852#elif(VKFFT_BACKEND==1) //CUDA API
5853\end_layout
5854
5855\begin_layout Plain Layout
5856
5857CUdevice device;
5858\end_layout
5859
5860\begin_layout Plain Layout
5861
5862CUcontext context;
5863\end_layout
5864
5865\begin_layout Plain Layout
5866
5867#elif(VKFFT_BACKEND==2) //HIP API
5868\end_layout
5869
5870\begin_layout Plain Layout
5871
5872hipDevice_t device;
5873\end_layout
5874
5875\begin_layout Plain Layout
5876
5877hipCtx_t context;
5878\end_layout
5879
5880\begin_layout Plain Layout
5881
5882#elif(VKFFT_BACKEND==3) //OpenCL API
5883\end_layout
5884
5885\begin_layout Plain Layout
5886
5887cl_platform_id platform;
5888\end_layout
5889
5890\begin_layout Plain Layout
5891
5892cl_device_id device;
5893\end_layout
5894
5895\begin_layout Plain Layout
5896
5897cl_context context;
5898\end_layout
5899
5900\begin_layout Plain Layout
5901
5902cl_command_queue commandQueue;
5903\end_layout
5904
5905\begin_layout Plain Layout
5906
5907#elif(VKFFT_BACKEND==4) //Level Zero API
5908\end_layout
5909
5910\begin_layout Plain Layout
5911
5912ze_driver_handle_t driver;
5913\end_layout
5914
5915\begin_layout Plain Layout
5916
5917ze_device_handle_t device;
5918\end_layout
5919
5920\begin_layout Plain Layout
5921
5922ze_context_handle_t context;
5923\end_layout
5924
5925\begin_layout Plain Layout
5926
5927ze_command_queue_handle_t commandQueue;
5928\end_layout
5929
5930\begin_layout Plain Layout
5931
5932uint32_t commandQueueID;
5933\end_layout
5934
5935\begin_layout Plain Layout
5936
5937#elif(VKFFT_BACKEND==5) //Metal API
5938\end_layout
5939
5940\begin_layout Plain Layout
5941
5942MTL::Device* device;
5943\end_layout
5944
5945\begin_layout Plain Layout
5946
5947MTL::CommandQueue* queue;
5948\end_layout
5949
5950\begin_layout Plain Layout
5951
5952#endif
5953\end_layout
5954
5955\begin_layout Plain Layout
5956
5957uint64_t device_id; //an id of a device, reported by devices_list call
5958\end_layout
5959
5960\begin_layout Plain Layout
5961
5962} VkGPU;
5963\end_layout
5964
5965\begin_layout Plain Layout
5966
5967
5968\backslash
5969end{minted}
5970\end_layout
5971
5972\begin_layout Plain Layout
5973
5974
5975\backslash
5976end{mdframed}
5977\end_layout
5978
5979\end_inset
5980
5981
5982\begin_inset Newpage newpage
5983\end_inset
5984
5985
5986\end_layout
5987
5988\begin_layout Section
5989VkFFT Code Examples
5990\end_layout
5991
5992\begin_layout Standard
5993This section will provide some simple pseudocode for VkFFT usage, which
5994 will once again outline important steps required to launch FFT with VkFFT.
5995 More information (and fully working code) can be found in this folder of
5996 the VkFFT repository:
5997\end_layout
5998
5999\begin_layout Standard
6000/benchmark_samples/vkFFT_scripts/src/
6001\end_layout
6002
6003\begin_layout Subsection
6004Driver initializations
6005\end_layout
6006
6007\begin_layout Standard
6008Before launching VkFFT, do not forget to do all necessary driver initializations.
6009 The following code specifies them for all the supported backends, though
6010 the final implementation may be different depending on the particular user's
6011 configuration.
6012\end_layout
6013
6014\begin_layout Standard
6015\begin_inset ERT
6016status open
6017
6018\begin_layout Plain Layout
6019
6020
6021\backslash
6022begin{mdframed}[backgroundcolor=bg]
6023\end_layout
6024
6025\begin_layout Plain Layout
6026
6027
6028\backslash
6029begin{minted}[tabsize=4,obeytabs,breaklines]{C}
6030\end_layout
6031
6032\begin_layout Plain Layout
6033
6034#if(VKFFT_BACKEND==0) //Vulkan API
6035\end_layout
6036
6037\begin_layout Plain Layout
6038
6039VkResult res = VK_SUCCESS;
6040\end_layout
6041
6042\begin_layout Plain Layout
6043
6044//create instance - a connection between the application and the Vulkan
6045 library
6046\end_layout
6047
6048\begin_layout Plain Layout
6049
6050res = createInstance(vkGPU, sample_id);
6051\end_layout
6052
6053\begin_layout Plain Layout
6054
6055if (res != 0) {
6056\end_layout
6057
6058\begin_layout Plain Layout
6059
6060	//printf("Instance creation failed, error code: %" PRIu64 "
6061\backslash
6062n", res);
6063\end_layout
6064
6065\begin_layout Plain Layout
6066
6067	return VKFFT_ERROR_FAILED_TO_CREATE_INSTANCE;
6068\end_layout
6069
6070\begin_layout Plain Layout
6071
6072} 	
6073\end_layout
6074
6075\begin_layout Plain Layout
6076
6077//set up the debugging messenger
6078\end_layout
6079
6080\begin_layout Plain Layout
6081
6082res = setupDebugMessenger(vkGPU);
6083\end_layout
6084
6085\begin_layout Plain Layout
6086
6087if (res != 0) {
6088\end_layout
6089
6090\begin_layout Plain Layout
6091
6092//printf("Debug messenger creation failed, error code: %" PRIu64 "
6093\backslash
6094n", res);
6095\end_layout
6096
6097\begin_layout Plain Layout
6098
6099	return VKFFT_ERROR_FAILED_TO_SETUP_DEBUG_MESSENGER;
6100\end_layout
6101
6102\begin_layout Plain Layout
6103
6104}
6105\end_layout
6106
6107\begin_layout Plain Layout
6108
6109//check if there are GPUs that support Vulkan and select one
6110\end_layout
6111
6112\begin_layout Plain Layout
6113
6114res = findPhysicalDevice(vkGPU);
6115\end_layout
6116
6117\begin_layout Plain Layout
6118
6119if (res != 0) {
6120\end_layout
6121
6122\begin_layout Plain Layout
6123
6124//printf("Physical device not found, error code: %" PRIu64 "
6125\backslash
6126n", res);
6127\end_layout
6128
6129\begin_layout Plain Layout
6130
6131	return VKFFT_ERROR_FAILED_TO_FIND_PHYSICAL_DEVICE;
6132\end_layout
6133
6134\begin_layout Plain Layout
6135
6136}
6137\end_layout
6138
6139\begin_layout Plain Layout
6140
6141//create logical device representation
6142\end_layout
6143
6144\begin_layout Plain Layout
6145
6146res = createDevice(vkGPU, sample_id);
6147\end_layout
6148
6149\begin_layout Plain Layout
6150
6151if (res != 0) {
6152\end_layout
6153
6154\begin_layout Plain Layout
6155
6156//printf("Device creation failed, error code: %" PRIu64 "
6157\backslash
6158n", res);
6159\end_layout
6160
6161\begin_layout Plain Layout
6162
6163	return VKFFT_ERROR_FAILED_TO_CREATE_DEVICE;
6164\end_layout
6165
6166\begin_layout Plain Layout
6167
6168}
6169\end_layout
6170
6171\begin_layout Plain Layout
6172
6173//create fence for synchronization
6174\end_layout
6175
6176\begin_layout Plain Layout
6177
6178res = createFence(vkGPU);
6179\end_layout
6180
6181\begin_layout Plain Layout
6182
6183if (res != 0) {
6184\end_layout
6185
6186\begin_layout Plain Layout
6187
6188//printf("Fence creation failed, error code: %" PRIu64 "
6189\backslash
6190n", res);
6191\end_layout
6192
6193\begin_layout Plain Layout
6194
6195	return VKFFT_ERROR_FAILED_TO_CREATE_FENCE;
6196\end_layout
6197
6198\begin_layout Plain Layout
6199
6200}
6201\end_layout
6202
6203\begin_layout Plain Layout
6204
6205//create a place, command buffer memory is allocated from
6206\end_layout
6207
6208\begin_layout Plain Layout
6209
6210res = createCommandPool(vkGPU);
6211\end_layout
6212
6213\begin_layout Plain Layout
6214
6215if (res != 0) {
6216\end_layout
6217
6218\begin_layout Plain Layout
6219
6220	//printf("Fence creation failed, error code: %" PRIu64 "
6221\backslash
6222n", res);
6223\end_layout
6224
6225\begin_layout Plain Layout
6226
6227	return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_POOL;
6228\end_layout
6229
6230\begin_layout Plain Layout
6231
6232}
6233\end_layout
6234
6235\begin_layout Plain Layout
6236
6237vkGetPhysicalDeviceProperties(vkGPU->physicalDevice, &vkGPU->physicalDevicePrope
6238rties);
6239\end_layout
6240
6241\begin_layout Plain Layout
6242
6243vkGetPhysicalDeviceMemoryProperties(vkGPU->physicalDevice, &vkGPU->physicalDevic
6244eMemoryProperties);
6245\end_layout
6246
6247\begin_layout Plain Layout
6248
6249glslang_initialize_process();
6250\end_layout
6251
6252\begin_layout Plain Layout
6253
6254//compiler can be initialized before VkFFT
6255\end_layout
6256
6257\begin_layout Plain Layout
6258
6259\end_layout
6260
6261\begin_layout Plain Layout
6262
6263#elif(VKFFT_BACKEND==1) //CUDA API
6264\end_layout
6265
6266\begin_layout Plain Layout
6267
6268CUresult res = CUDA_SUCCESS;
6269\end_layout
6270
6271\begin_layout Plain Layout
6272
6273cudaError_t res2 = cudaSuccess;
6274\end_layout
6275
6276\begin_layout Plain Layout
6277
6278res = cuInit(0);
6279\end_layout
6280
6281\begin_layout Plain Layout
6282
6283if (res != CUDA_SUCCESS) return VKFFT_ERROR_FAILED_TO_INITIALIZE;
6284\end_layout
6285
6286\begin_layout Plain Layout
6287
6288res2 = cudaSetDevice((int)vkGPU->device_id);
6289\end_layout
6290
6291\begin_layout Plain Layout
6292
6293if (res2 != cudaSuccess) return VKFFT_ERROR_FAILED_TO_SET_DEVICE_ID;
6294\end_layout
6295
6296\begin_layout Plain Layout
6297
6298res = cuDeviceGet(&vkGPU->device, (int)vkGPU->device_id);
6299\end_layout
6300
6301\begin_layout Plain Layout
6302
6303if (res != CUDA_SUCCESS) return VKFFT_ERROR_FAILED_TO_GET_DEVICE;
6304\end_layout
6305
6306\begin_layout Plain Layout
6307
6308res = cuCtxCreate(&vkGPU->context, 0, (int)vkGPU->device);
6309\end_layout
6310
6311\begin_layout Plain Layout
6312
6313if (res != CUDA_SUCCESS) return VKFFT_ERROR_FAILED_TO_CREATE_CONTEXT;
6314\end_layout
6315
6316\begin_layout Plain Layout
6317
6318#elif(VKFFT_BACKEND==2) //HIP API
6319\end_layout
6320
6321\begin_layout Plain Layout
6322
6323hipError_t res = hipSuccess;
6324\end_layout
6325
6326\begin_layout Plain Layout
6327
6328res = hipInit(0);
6329\end_layout
6330
6331\begin_layout Plain Layout
6332
6333if (res != hipSuccess) return VKFFT_ERROR_FAILED_TO_INITIALIZE;
6334\end_layout
6335
6336\begin_layout Plain Layout
6337
6338res = hipSetDevice((int)vkGPU->device_id);
6339\end_layout
6340
6341\begin_layout Plain Layout
6342
6343if (res != hipSuccess) return VKFFT_ERROR_FAILED_TO_SET_DEVICE_ID;
6344\end_layout
6345
6346\begin_layout Plain Layout
6347
6348res = hipDeviceGet(&vkGPU->device, (int)vkGPU->device_id);
6349\end_layout
6350
6351\begin_layout Plain Layout
6352
6353if (res != hipSuccess) return VKFFT_ERROR_FAILED_TO_GET_DEVICE; 
6354\end_layout
6355
6356\begin_layout Plain Layout
6357
6358res = hipCtxCreate(&vkGPU->context, 0, (int)vkGPU->device);
6359\end_layout
6360
6361\begin_layout Plain Layout
6362
6363if (res != hipSuccess) return VKFFT_ERROR_FAILED_TO_CREATE_CONTEXT;
6364\end_layout
6365
6366\begin_layout Plain Layout
6367
6368#elif(VKFFT_BACKEND==3) //OpenCL API
6369\end_layout
6370
6371\begin_layout Plain Layout
6372
6373cl_int res = CL_SUCCESS;
6374\end_layout
6375
6376\begin_layout Plain Layout
6377
6378cl_uint numPlatforms;
6379\end_layout
6380
6381\begin_layout Plain Layout
6382
6383res = clGetPlatformIDs(0, 0, &numPlatforms);
6384\end_layout
6385
6386\begin_layout Plain Layout
6387
6388if (res != CL_SUCCESS) return VKFFT_ERROR_FAILED_TO_INITIALIZE;
6389\end_layout
6390
6391\begin_layout Plain Layout
6392
6393cl_platform_id* platforms = (cl_platform_id*)malloc(sizeof(cl_platform_id)
6394 * numPlatforms);
6395\end_layout
6396
6397\begin_layout Plain Layout
6398
6399if (!platforms) return VKFFT_ERROR_MALLOC_FAILED;
6400\end_layout
6401
6402\begin_layout Plain Layout
6403
6404res = clGetPlatformIDs(numPlatforms, platforms, 0);
6405\end_layout
6406
6407\begin_layout Plain Layout
6408
6409if (res != CL_SUCCESS) return VKFFT_ERROR_FAILED_TO_INITIALIZE;
6410\end_layout
6411
6412\begin_layout Plain Layout
6413
6414uint64_t k = 0;
6415\end_layout
6416
6417\begin_layout Plain Layout
6418
6419for (uint64_t j = 0; j < numPlatforms; j++) {
6420\end_layout
6421
6422\begin_layout Plain Layout
6423
6424	cl_uint numDevices;
6425\end_layout
6426
6427\begin_layout Plain Layout
6428
6429	res = clGetDeviceIDs(platforms[j], CL_DEVICE_TYPE_ALL, 0, 0, &numDevices);
6430\end_layout
6431
6432\begin_layout Plain Layout
6433
6434	cl_device_id* deviceList = (cl_device_id*)malloc(sizeof(cl_device_id) *
6435 numDevices);
6436\end_layout
6437
6438\begin_layout Plain Layout
6439
6440	if (!deviceList) return VKFFT_ERROR_MALLOC_FAILED;
6441\end_layout
6442
6443\begin_layout Plain Layout
6444
6445	res = clGetDeviceIDs(platforms[j], CL_DEVICE_TYPE_ALL, numDevices, deviceList,
6446 0);
6447\end_layout
6448
6449\begin_layout Plain Layout
6450
6451	if (res != CL_SUCCESS) return VKFFT_ERROR_FAILED_TO_GET_DEVICE;
6452\end_layout
6453
6454\begin_layout Plain Layout
6455
6456	for (uint64_t i = 0; i < numDevices; i++) {
6457\end_layout
6458
6459\begin_layout Plain Layout
6460
6461		if (k == vkGPU->device_id) {
6462\end_layout
6463
6464\begin_layout Plain Layout
6465
6466			vkGPU->platform = platforms[j];
6467\end_layout
6468
6469\begin_layout Plain Layout
6470
6471			vkGPU->device = deviceList[i];
6472\end_layout
6473
6474\begin_layout Plain Layout
6475
6476			vkGPU->context = clCreateContext(NULL, 1, &vkGPU->device, NULL, NULL,
6477 &res);
6478\end_layout
6479
6480\begin_layout Plain Layout
6481
6482			if (res != CL_SUCCESS) return VKFFT_ERROR_FAILED_TO_CREATE_CONTEXT;
6483\end_layout
6484
6485\begin_layout Plain Layout
6486
6487			cl_command_queue commandQueue = clCreateCommandQueue(vkGPU->context,
6488 vkGPU->device, 0, &res);
6489\end_layout
6490
6491\begin_layout Plain Layout
6492
6493			if (res != CL_SUCCESS) return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_QUEUE;
6494\end_layout
6495
6496\begin_layout Plain Layout
6497
6498			vkGPU->commandQueue = commandQueue;
6499\end_layout
6500
6501\begin_layout Plain Layout
6502
6503			i=numDevices; 		
6504\end_layout
6505
6506\begin_layout Plain Layout
6507
6508			j=numPlatforms;
6509\end_layout
6510
6511\begin_layout Plain Layout
6512
6513		}
6514\end_layout
6515
6516\begin_layout Plain Layout
6517
6518		else {
6519\end_layout
6520
6521\begin_layout Plain Layout
6522
6523			k++;
6524\end_layout
6525
6526\begin_layout Plain Layout
6527
6528		}
6529\end_layout
6530
6531\begin_layout Plain Layout
6532
6533	}
6534\end_layout
6535
6536\begin_layout Plain Layout
6537
6538	free(deviceList);
6539\end_layout
6540
6541\begin_layout Plain Layout
6542
6543}
6544\end_layout
6545
6546\begin_layout Plain Layout
6547
6548free(platforms);
6549\end_layout
6550
6551\begin_layout Plain Layout
6552
6553#elif(VKFFT_BACKEND==4)
6554\end_layout
6555
6556\begin_layout Plain Layout
6557
6558	ze_result_t res = ZE_RESULT_SUCCESS;
6559\end_layout
6560
6561\begin_layout Plain Layout
6562
6563	res = zeInit(0);
6564\end_layout
6565
6566\begin_layout Plain Layout
6567
6568	if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_INITIALIZE;
6569\end_layout
6570
6571\begin_layout Plain Layout
6572
6573	uint32_t numDrivers = 0;
6574\end_layout
6575
6576\begin_layout Plain Layout
6577
6578	res = zeDriverGet(&numDrivers, 0);
6579\end_layout
6580
6581\begin_layout Plain Layout
6582
6583	if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_INITIALIZE;
6584\end_layout
6585
6586\begin_layout Plain Layout
6587
6588	ze_driver_handle_t* drivers = (ze_driver_handle_t*)malloc(numDrivers *
6589 sizeof(ze_driver_handle_t));
6590\end_layout
6591
6592\begin_layout Plain Layout
6593
6594	if (!drivers) return VKFFT_ERROR_MALLOC_FAILED;
6595\end_layout
6596
6597\begin_layout Plain Layout
6598
6599	res = zeDriverGet(&numDrivers, drivers);
6600\end_layout
6601
6602\begin_layout Plain Layout
6603
6604	if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_INITIALIZE;
6605\end_layout
6606
6607\begin_layout Plain Layout
6608
6609	uint64_t k = 0;
6610\end_layout
6611
6612\begin_layout Plain Layout
6613
6614	for (uint64_t j = 0; j < numDrivers; j++) {
6615\end_layout
6616
6617\begin_layout Plain Layout
6618
6619		uint32_t numDevices = 0;
6620\end_layout
6621
6622\begin_layout Plain Layout
6623
6624		res = zeDeviceGet(drivers[j], &numDevices, nullptr);
6625\end_layout
6626
6627\begin_layout Plain Layout
6628
6629		if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_GET_DEVICE;
6630\end_layout
6631
6632\begin_layout Plain Layout
6633
6634		ze_device_handle_t* deviceList = (ze_device_handle_t*)malloc(numDevices
6635 * sizeof(ze_device_handle_t));
6636\end_layout
6637
6638\begin_layout Plain Layout
6639
6640		if (!deviceList) return VKFFT_ERROR_MALLOC_FAILED;
6641\end_layout
6642
6643\begin_layout Plain Layout
6644
6645		res = zeDeviceGet(drivers[j], &numDevices, deviceList);
6646\end_layout
6647
6648\begin_layout Plain Layout
6649
6650		if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_GET_DEVICE;
6651\end_layout
6652
6653\begin_layout Plain Layout
6654
6655		for (uint64_t i = 0; i < numDevices; i++) {
6656\end_layout
6657
6658\begin_layout Plain Layout
6659
6660			if (k == vkGPU->device_id) {
6661\end_layout
6662
6663\begin_layout Plain Layout
6664
6665				vkGPU->driver = drivers[j];
6666\end_layout
6667
6668\begin_layout Plain Layout
6669
6670				vkGPU->device = deviceList[i];
6671\end_layout
6672
6673\begin_layout Plain Layout
6674
6675				ze_context_desc_t contextDescription = {};
6676\end_layout
6677
6678\begin_layout Plain Layout
6679
6680				contextDescription.stype = ZE_STRUCTURE_TYPE_CONTEXT_DESC;
6681\end_layout
6682
6683\begin_layout Plain Layout
6684
6685				res = zeContextCreate(vkGPU->driver, &contextDescription, &vkGPU->context);
6686\end_layout
6687
6688\begin_layout Plain Layout
6689
6690				if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_CREATE_CONTEXT;
6691\end_layout
6692
6693\begin_layout Plain Layout
6694
6695\end_layout
6696
6697\begin_layout Plain Layout
6698
6699				uint32_t queueGroupCount = 0;
6700\end_layout
6701
6702\begin_layout Plain Layout
6703
6704				res = zeDeviceGetCommandQueueGroupProperties(vkGPU->device, &queueGroupCount
6705, 0);
6706\end_layout
6707
6708\begin_layout Plain Layout
6709
6710				if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_QU
6711EUE;
6712\end_layout
6713
6714\begin_layout Plain Layout
6715
6716\end_layout
6717
6718\begin_layout Plain Layout
6719
6720				ze_command_queue_group_properties_t* cmdqueueGroupProperties = (ze_command_q
6721ueue_group_properties_t*) malloc(queueGroupCount * sizeof(ze_command_queue_group
6722_properties_t));
6723\end_layout
6724
6725\begin_layout Plain Layout
6726
6727				if (!cmdqueueGroupProperties) return VKFFT_ERROR_MALLOC_FAILED;
6728\end_layout
6729
6730\begin_layout Plain Layout
6731
6732				res = zeDeviceGetCommandQueueGroupProperties(vkGPU->device, &queueGroupCount
6733, cmdqueueGroupProperties);
6734\end_layout
6735
6736\begin_layout Plain Layout
6737
6738				if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_QU
6739EUE;
6740\end_layout
6741
6742\begin_layout Plain Layout
6743
6744\end_layout
6745
6746\begin_layout Plain Layout
6747
6748				uint32_t commandQueueID = -1;
6749\end_layout
6750
6751\begin_layout Plain Layout
6752
6753				for (uint32_t i = 0; i < queueGroupCount; ++i) {
6754\end_layout
6755
6756\begin_layout Plain Layout
6757
6758					if ((cmdqueueGroupProperties[i].flags && ZE_COMMAND_QUEUE_GROUP_PROPERTY_FLA
6759G_COMPUTE) && (cmdqueueGroupProperties[i].flags && ZE_COMMAND_QUEUE_GROUP_PROPERT
6760Y_FLAG_COPY)) {
6761\end_layout
6762
6763\begin_layout Plain Layout
6764
6765						commandQueueID = i;
6766\end_layout
6767
6768\begin_layout Plain Layout
6769
6770						break;
6771\end_layout
6772
6773\begin_layout Plain Layout
6774
6775					}
6776\end_layout
6777
6778\begin_layout Plain Layout
6779
6780				}
6781\end_layout
6782
6783\begin_layout Plain Layout
6784
6785				if (commandQueueID == -1) return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_QUEUE;
6786\end_layout
6787
6788\begin_layout Plain Layout
6789
6790				vkGPU->commandQueueID = commandQueueID;
6791\end_layout
6792
6793\begin_layout Plain Layout
6794
6795				ze_command_queue_desc_t commandQueueDescription = {};
6796\end_layout
6797
6798\begin_layout Plain Layout
6799
6800				commandQueueDescription.stype = ZE_STRUCTURE_TYPE_COMMAND_QUEUE_DESC;
6801\end_layout
6802
6803\begin_layout Plain Layout
6804
6805				commandQueueDescription.ordinal = commandQueueID;
6806\end_layout
6807
6808\begin_layout Plain Layout
6809
6810				commandQueueDescription.priority = ZE_COMMAND_QUEUE_PRIORITY_NORMAL;
6811\end_layout
6812
6813\begin_layout Plain Layout
6814
6815				commandQueueDescription.mode = ZE_COMMAND_QUEUE_MODE_DEFAULT;
6816\end_layout
6817
6818\begin_layout Plain Layout
6819
6820				res = zeCommandQueueCreate(vkGPU->context, vkGPU->device, &commandQueueDescr
6821iption, &vkGPU->commandQueue);
6822\end_layout
6823
6824\begin_layout Plain Layout
6825
6826				if (res != ZE_RESULT_SUCCESS) return VKFFT_ERROR_FAILED_TO_CREATE_COMMAND_QU
6827EUE;
6828\end_layout
6829
6830\begin_layout Plain Layout
6831
6832				free(cmdqueueGroupProperties);
6833\end_layout
6834
6835\begin_layout Plain Layout
6836
6837				i=numDevices; 		
6838\end_layout
6839
6840\begin_layout Plain Layout
6841
6842				j=numPlatforms;
6843\end_layout
6844
6845\begin_layout Plain Layout
6846
6847			}
6848\end_layout
6849
6850\begin_layout Plain Layout
6851
6852			else {
6853\end_layout
6854
6855\begin_layout Plain Layout
6856
6857				k++;
6858\end_layout
6859
6860\begin_layout Plain Layout
6861
6862			}
6863\end_layout
6864
6865\begin_layout Plain Layout
6866
6867		}
6868\end_layout
6869
6870\begin_layout Plain Layout
6871
6872\end_layout
6873
6874\begin_layout Plain Layout
6875
6876		free(deviceList);
6877\end_layout
6878
6879\begin_layout Plain Layout
6880
6881	}
6882\end_layout
6883
6884\begin_layout Plain Layout
6885
6886	free(drivers);
6887\end_layout
6888
6889\begin_layout Plain Layout
6890
6891#elif(VKFFT_BACKEND==5)
6892\end_layout
6893
6894\begin_layout Plain Layout
6895
6896    NS::Array* devices = MTL::CopyAllDevices();
6897\end_layout
6898
6899\begin_layout Plain Layout
6900
6901    MTL::Device* device = (MTL::Device*)devices->object(vkGPU->device_id);
6902\end_layout
6903
6904\begin_layout Plain Layout
6905
6906    vkGPU->device = device;
6907\end_layout
6908
6909\begin_layout Plain Layout
6910
6911    MTL::CommandQueue* queue = device->newCommandQueue();
6912\end_layout
6913
6914\begin_layout Plain Layout
6915
6916    vkGPU->queue = queue;
6917\end_layout
6918
6919\begin_layout Plain Layout
6920
6921#endif
6922\end_layout
6923
6924\begin_layout Plain Layout
6925
6926
6927\backslash
6928end{minted}
6929\end_layout
6930
6931\begin_layout Plain Layout
6932
6933
6934\backslash
6935end{mdframed}
6936\end_layout
6937
6938\end_inset
6939
6940
6941\end_layout
6942
6943\begin_layout Subsection
6944Simple FFT application example: 1D (one dimensional) C2C (complex to complex)
6945 FP32 (single precision) FFT
6946\end_layout
6947
6948\begin_layout Standard
6949This example performs the simplest case of FFT.
6950 It shows all the necessary fields that the user must fill during the configurat
6951ion and the submission process.
6952 Other samples will build on this one, as driver parameters initialization
6953 and code execution commands are the same for all configurations (except
6954 for the launch parameters that can be configured after application creation).
6955\end_layout
6956
6957\begin_layout Standard
6958\begin_inset ERT
6959status open
6960
6961\begin_layout Plain Layout
6962
6963
6964\backslash
6965begin{mdframed}[backgroundcolor=bg]
6966\end_layout
6967
6968\begin_layout Plain Layout
6969
6970
6971\backslash
6972begin{minted}[tabsize=4,obeytabs,breaklines]{C}
6973\end_layout
6974
6975\begin_layout Plain Layout
6976
6977//zero-initialize configuration + FFT application
6978\end_layout
6979
6980\begin_layout Plain Layout
6981
6982VkFFTConfiguration configuration = {};
6983\end_layout
6984
6985\begin_layout Plain Layout
6986
6987VkFFTApplication app = {};
6988\end_layout
6989
6990\begin_layout Plain Layout
6991
6992\end_layout
6993
6994\begin_layout Plain Layout
6995
6996configuration.FFTdim = 1; //FFT dimension
6997\end_layout
6998
6999\begin_layout Plain Layout
7000
7001configuration.size[0] = Nx; //FFT size
7002\end_layout
7003
7004\begin_layout Plain Layout
7005
7006uint64_t bufferSize = (uint64_t)sizeof(float) * 2 * configuration.size[0];
7007\end_layout
7008
7009\begin_layout Plain Layout
7010
7011\end_layout
7012
7013\begin_layout Plain Layout
7014
7015//Device management + code submission
7016\end_layout
7017
7018\begin_layout Plain Layout
7019
7020#if(VKFFT_BACKEND==5)
7021\end_layout
7022
7023\begin_layout Plain Layout
7024
7025configuration.device = vkGPU->device;
7026\end_layout
7027
7028\begin_layout Plain Layout
7029
7030#else
7031\end_layout
7032
7033\begin_layout Plain Layout
7034
7035configuration.device = &vkGPU->device;
7036\end_layout
7037
7038\begin_layout Plain Layout
7039
7040#endif
7041\end_layout
7042
7043\begin_layout Plain Layout
7044
7045\end_layout
7046
7047\begin_layout Plain Layout
7048
7049#if(VKFFT_BACKEND==0) //Vulkan API		
7050\end_layout
7051
7052\begin_layout Plain Layout
7053
7054configuration.queue = &vkGPU->queue;
7055\end_layout
7056
7057\begin_layout Plain Layout
7058
7059configuration.fence = &vkGPU->fence; 			
7060\end_layout
7061
7062\begin_layout Plain Layout
7063
7064configuration.commandPool = &vkGPU->commandPool; 			
7065\end_layout
7066
7067\begin_layout Plain Layout
7068
7069configuration.physicalDevice = &vkGPU->physicalDevice; 			
7070\end_layout
7071
7072\begin_layout Plain Layout
7073
7074configuration.isCompilerInitialized = isCompilerInitialized; //glslang compiler
7075 can be initialized before VkFFT plan creation.
7076 if not, VkFFT will create and destroy one after initialization 
7077\end_layout
7078
7079\begin_layout Plain Layout
7080
7081#elif(VKFFT_BACKEND==3) //OpenCL API		
7082\end_layout
7083
7084\begin_layout Plain Layout
7085
7086configuration.context = &vkGPU->context; 
7087\end_layout
7088
7089\begin_layout Plain Layout
7090
7091#elif(VKFFT_BACKEND==4)
7092\end_layout
7093
7094\begin_layout Plain Layout
7095
7096configuration.context = &vkGPU->context;
7097\end_layout
7098
7099\begin_layout Plain Layout
7100
7101configuration.commandQueue = &vkGPU->commandQueue;
7102\end_layout
7103
7104\begin_layout Plain Layout
7105
7106configuration.commandQueueID = vkGPU->commandQueueID;
7107\end_layout
7108
7109\begin_layout Plain Layout
7110
7111#elif(VKFFT_BACKEND==5)             
7112\end_layout
7113
7114\begin_layout Plain Layout
7115
7116configuration.queue = vkGPU->queue;
7117\end_layout
7118
7119\begin_layout Plain Layout
7120
7121#endif
7122\end_layout
7123
7124\begin_layout Plain Layout
7125
7126\end_layout
7127
7128\begin_layout Plain Layout
7129
7130allocateBuffer(buffer, bufferSize); //Pseudocode for buffer allocation,
7131 differs between APIs
7132\end_layout
7133
7134\begin_layout Plain Layout
7135
7136transferDataFromCPU(buffer, cpu_buffer); //Pseudocode for data transfer
7137 from CPU to GPU, differs between APIs
7138\end_layout
7139
7140\begin_layout Plain Layout
7141
7142\end_layout
7143
7144\begin_layout Plain Layout
7145
7146#if(VKFFT_BACKEND==0) //Vulkan API needs bufferSize at initialization	
7147\end_layout
7148
7149\begin_layout Plain Layout
7150
7151configuration.bufferSize = &bufferSize; 
7152\end_layout
7153
7154\begin_layout Plain Layout
7155
7156#endif
7157\end_layout
7158
7159\begin_layout Plain Layout
7160
7161\end_layout
7162
7163\begin_layout Plain Layout
7164
7165VkFFTResult resFFT = initializeVkFFT(&app, configuration);
7166\end_layout
7167
7168\begin_layout Plain Layout
7169
7170\end_layout
7171
7172\begin_layout Plain Layout
7173
7174VkFFTLaunchParams launchParams = {};
7175\end_layout
7176
7177\begin_layout Plain Layout
7178
7179launchParams.buffer = &buffer;
7180\end_layout
7181
7182\begin_layout Plain Layout
7183
7184#if(VKFFT_BACKEND==0) //Vulkan API 
7185\end_layout
7186
7187\begin_layout Plain Layout
7188
7189launchParams.commandBuffer = &commandBuffer;
7190\end_layout
7191
7192\begin_layout Plain Layout
7193
7194#elif(VKFFT_BACKEND==3) //OpenCL API
7195\end_layout
7196
7197\begin_layout Plain Layout
7198
7199launchParams.commandQueue = &commandQueue;
7200\end_layout
7201
7202\begin_layout Plain Layout
7203
7204#elif(VKFFT_BACKEND==4) //Level Zero API
7205\end_layout
7206
7207\begin_layout Plain Layout
7208
7209launchParams->commandList = &commandList;
7210\end_layout
7211
7212\begin_layout Plain Layout
7213
7214#elif(VKFFT_BACKEND==5) //Metal API
7215\end_layout
7216
7217\begin_layout Plain Layout
7218
7219launchParams->commandBuffer = commandBuffer;
7220\end_layout
7221
7222\begin_layout Plain Layout
7223
7224launchParams->commandEncoder = commandEncoder;
7225\end_layout
7226
7227\begin_layout Plain Layout
7228
7229#endif
7230\end_layout
7231
7232\begin_layout Plain Layout
7233
7234resFFT = VkFFTAppend(app, -1, &launchParams);
7235\end_layout
7236
7237\begin_layout Plain Layout
7238
7239\end_layout
7240
7241\begin_layout Plain Layout
7242
7243//add synchronization relevant to your API - vkWaitForFences/cudaDeviceSynchroni
7244ze/hipDeviceSynchronize/clFinish
7245\end_layout
7246
7247\begin_layout Plain Layout
7248
7249transferDataToCPU(cpu_buffer, buffer); //Pseudocode for data transfer from
7250 GPU to CPU, differs between APIs
7251\end_layout
7252
7253\begin_layout Plain Layout
7254
7255\end_layout
7256
7257\begin_layout Plain Layout
7258
7259freeBuffer(buffer, bufferSize); //Pseudocode for buffer deallocation, differs
7260 between APIs
7261\end_layout
7262
7263\begin_layout Plain Layout
7264
7265\end_layout
7266
7267\begin_layout Plain Layout
7268
7269deleteVkFFT(&app);
7270\end_layout
7271
7272\begin_layout Plain Layout
7273
7274
7275\backslash
7276end{minted}
7277\end_layout
7278
7279\begin_layout Plain Layout
7280
7281
7282\backslash
7283end{mdframed} 
7284\end_layout
7285
7286\end_inset
7287
7288
7289\end_layout
7290
7291\begin_layout Subsection
7292Advanced FFT application example: ND, C2C/R2C/R2R, different precisions,
7293 batched FFT
7294\end_layout
7295
7296\begin_layout Standard
7297This example shows how to configure the main parameters of interest in the
7298 VkFFT library: multidimensional case, different types of transforms, different
7299 precision, perform batched transforms.
7300\end_layout
7301
7302\begin_layout Standard
7303In the code below X, Y and Z are the dimensions of FFT, B - number of batches,
7304 R2C - real to complex mode 0 or 1 (on/off), DCT - 0, 1, 2, 3 or 4 (off/DCT
7305 type), P - precision (0 - single, 1 - double, 2 - half).
7306\end_layout
7307
7308\begin_layout Standard
7309\begin_inset ERT
7310status open
7311
7312\begin_layout Plain Layout
7313
7314
7315\backslash
7316begin{mdframed}[backgroundcolor=bg]
7317\end_layout
7318
7319\begin_layout Plain Layout
7320
7321
7322\backslash
7323begin{minted}[tabsize=4,obeytabs,breaklines]{C}
7324\end_layout
7325
7326\begin_layout Plain Layout
7327
7328//zero-initialize configuration + FFT application
7329\end_layout
7330
7331\begin_layout Plain Layout
7332
7333VkFFTConfiguration configuration = {};
7334\end_layout
7335
7336\begin_layout Plain Layout
7337
7338VkFFTApplication app = {};
7339\end_layout
7340
7341\begin_layout Plain Layout
7342
7343\end_layout
7344
7345\begin_layout Plain Layout
7346
7347configuration.FFTdim = 1; //FFT dimension
7348\end_layout
7349
7350\begin_layout Plain Layout
7351
7352configuration.size[0] = X;
7353\end_layout
7354
7355\begin_layout Plain Layout
7356
7357configuration.size[1] = Y;
7358\end_layout
7359
7360\begin_layout Plain Layout
7361
7362configuration.size[2] = Z;
7363\end_layout
7364
7365\begin_layout Plain Layout
7366
7367if (Y > 1) configuration.FFTdim++;
7368\end_layout
7369
7370\begin_layout Plain Layout
7371
7372if (Z > 1) configuration.FFTdim++;
7373\end_layout
7374
7375\begin_layout Plain Layout
7376
7377configuration.numberBatches = B;
7378\end_layout
7379
7380\begin_layout Plain Layout
7381
7382configuration.performR2C = R2C;
7383\end_layout
7384
7385\begin_layout Plain Layout
7386
7387configuration.performDCT = DCT;
7388\end_layout
7389
7390\begin_layout Plain Layout
7391
7392if (P == 1) configuration.doublePrecision = 1; 
7393\end_layout
7394
7395\begin_layout Plain Layout
7396
7397if (P == 2) configuration.halfPrecision = 1;
7398\end_layout
7399
7400\begin_layout Plain Layout
7401
7402if (P == 3) configuration.quadDoubleDoublePrecision = 1;
7403\end_layout
7404
7405\begin_layout Plain Layout
7406
7407\end_layout
7408
7409\begin_layout Plain Layout
7410
7411uint64_t bufferSize = 0;
7412\end_layout
7413
7414\begin_layout Plain Layout
7415
7416\end_layout
7417
7418\begin_layout Plain Layout
7419
7420if (R2C) {
7421\end_layout
7422
7423\begin_layout Plain Layout
7424
7425	bufferSize = (uint64_t)(storageComplexSize / 2) * (configuration.size[0]
7426 + 2) * configuration.size[1] * configuration.size[2] * configuration.numberBatches
7427;
7428\end_layout
7429
7430\begin_layout Plain Layout
7431
7432}
7433\end_layout
7434
7435\begin_layout Plain Layout
7436
7437else {
7438\end_layout
7439
7440\begin_layout Plain Layout
7441
7442	if (DCT) {
7443\end_layout
7444
7445\begin_layout Plain Layout
7446
7447		bufferSize = (uint64_t)(storageComplexSize / 2) * configuration.size[0]
7448 * configuration.size[1] * configuration.size[2] * configuration.numberBatches;
7449\end_layout
7450
7451\begin_layout Plain Layout
7452
7453	}
7454\end_layout
7455
7456\begin_layout Plain Layout
7457
7458	else {
7459\end_layout
7460
7461\begin_layout Plain Layout
7462
7463		bufferSize = (uint64_t)storageComplexSize * configuration.size[0] * configurati
7464on.size[1] * configuration.size[2] * configuration.numberBatches;
7465\end_layout
7466
7467\begin_layout Plain Layout
7468
7469	}
7470\end_layout
7471
7472\begin_layout Plain Layout
7473
7474} // storageComplexSize - 4/8/16 for FP16/FP32/FP64 respectively.
7475\end_layout
7476
7477\begin_layout Plain Layout
7478
7479\end_layout
7480
7481\begin_layout Plain Layout
7482
7483//Device management + code submission - code is identical to the previous
7484 example
7485\end_layout
7486
7487\begin_layout Plain Layout
7488
7489
7490\backslash
7491end{minted}
7492\end_layout
7493
7494\begin_layout Plain Layout
7495
7496
7497\backslash
7498end{mdframed}
7499\end_layout
7500
7501\end_inset
7502
7503
7504\end_layout
7505
7506\begin_layout Subsection
7507Advanced FFT application example: out-of-place R2C FFT with custom strides
7508\end_layout
7509
7510\begin_layout Standard
7511In this example, VkFFT is configured to calculate a 3D out-of-place R2C
7512 FFT of a system with custom strides.
7513 VkFFT reads data from the inputBuffer and produces the result in the buffer.
7514 
7515\end_layout
7516
7517\begin_layout Standard
7518\begin_inset ERT
7519status open
7520
7521\begin_layout Plain Layout
7522
7523
7524\backslash
7525begin{mdframed}[backgroundcolor=bg]
7526\end_layout
7527
7528\begin_layout Plain Layout
7529
7530
7531\backslash
7532begin{minted}[tabsize=4,obeytabs,breaklines]{C}
7533\end_layout
7534
7535\begin_layout Plain Layout
7536
7537//zero-initialize configuration + FFT application
7538\end_layout
7539
7540\begin_layout Plain Layout
7541
7542VkFFTConfiguration configuration = {};
7543\end_layout
7544
7545\begin_layout Plain Layout
7546
7547VkFFTApplication app = {};
7548\end_layout
7549
7550\begin_layout Plain Layout
7551
7552\end_layout
7553
7554\begin_layout Plain Layout
7555
7556configuration.FFTdim = 3; //FFT dimension
7557\end_layout
7558
7559\begin_layout Plain Layout
7560
7561configuration.size[0] = Nx;
7562\end_layout
7563
7564\begin_layout Plain Layout
7565
7566configuration.size[1] = Ny;
7567\end_layout
7568
7569\begin_layout Plain Layout
7570
7571configuration.size[2] = Nz;
7572\end_layout
7573
7574\begin_layout Plain Layout
7575
7576\end_layout
7577
7578\begin_layout Plain Layout
7579
7580configuration.performR2C = 1;
7581\end_layout
7582
7583\begin_layout Plain Layout
7584
7585\end_layout
7586
7587\begin_layout Plain Layout
7588
7589//out-of-place - we need to specify that input buffer is separate from the
7590 main buffer
7591\end_layout
7592
7593\begin_layout Plain Layout
7594
7595configuration.isInputFormatted = 1;
7596\end_layout
7597
7598\begin_layout Plain Layout
7599
7600configuration.inputBufferStride[0] = configuration.size[0];
7601\end_layout
7602
7603\begin_layout Plain Layout
7604
7605configuration.inputBufferStride[1] = configuration.inputBufferStride[0] *
7606 configuration.size[1];
7607\end_layout
7608
7609\begin_layout Plain Layout
7610
7611configuration.inputBufferStride[2] = configuration.inputBufferStride[1] *
7612 configuration.size[2];
7613\end_layout
7614
7615\begin_layout Plain Layout
7616
7617			
7618\end_layout
7619
7620\begin_layout Plain Layout
7621
7622configuration.bufferStride[0] = (uint64_t) (configuration.size[0] / 2) + 1;
7623\end_layout
7624
7625\begin_layout Plain Layout
7626
7627configuration.bufferStride[1] = configuration.bufferStride[0] * configuration.size[
76281];
7629\end_layout
7630
7631\begin_layout Plain Layout
7632
7633configuration.bufferStride[2] = configuration.bufferStride[1]* configuration.size[2
7634];
7635\end_layout
7636
7637\begin_layout Plain Layout
7638
7639\end_layout
7640
7641\begin_layout Plain Layout
7642
7643uint64_t inputBufferSize = (uint64_t)sizeof(float) * configuration.size[0]
7644 * configuration.size[1] * configuration.size[2];
7645\end_layout
7646
7647\begin_layout Plain Layout
7648
7649\end_layout
7650
7651\begin_layout Plain Layout
7652
7653uint64_t bufferSize = (uint64_t)sizeof(float) * 2 * (configuration.size[0]/2+1)
7654 * configuration.size[1] * configuration.size[2];
7655\end_layout
7656
7657\begin_layout Plain Layout
7658
7659\end_layout
7660
7661\begin_layout Plain Layout
7662
7663//Device management + code submission - code is identical to the first example,
7664 except that you need to allocate two buffers (and provide them in the launch
7665 configuration).
7666\end_layout
7667
7668\begin_layout Plain Layout
7669
7670\end_layout
7671
7672\begin_layout Plain Layout
7673
7674
7675\backslash
7676end{minted}
7677\end_layout
7678
7679\begin_layout Plain Layout
7680
7681
7682\backslash
7683end{mdframed}
7684\end_layout
7685
7686\end_inset
7687
7688
7689\end_layout
7690
7691\begin_layout Subsection
7692Advanced FFT application example: 3D FFT with innermost batching
7693\end_layout
7694
7695\begin_layout Standard
7696In this example, VkFFT is configured to calculate a 3D in-place C2C FFT
7697 of a system with innermost (fast axis) batching.
7698 
7699\end_layout
7700
7701\begin_layout Standard
7702\begin_inset ERT
7703status open
7704
7705\begin_layout Plain Layout
7706
7707
7708\backslash
7709begin{mdframed}[backgroundcolor=bg]
7710\end_layout
7711
7712\begin_layout Plain Layout
7713
7714
7715\backslash
7716begin{minted}[tabsize=4,obeytabs,breaklines]{C}
7717\end_layout
7718
7719\begin_layout Plain Layout
7720
7721//zero-initialize configuration + FFT application
7722\end_layout
7723
7724\begin_layout Plain Layout
7725
7726VkFFTConfiguration configuration = {};
7727\end_layout
7728
7729\begin_layout Plain Layout
7730
7731VkFFTApplication app = {};
7732\end_layout
7733
7734\begin_layout Plain Layout
7735
7736\end_layout
7737
7738\begin_layout Plain Layout
7739
7740configuration.FFTdim = 4; //FFT dimension, 3+1
7741\end_layout
7742
7743\begin_layout Plain Layout
7744
7745configuration.size[0] = Nbatch;
7746\end_layout
7747
7748\begin_layout Plain Layout
7749
7750configuration.size[1] = Nx;
7751\end_layout
7752
7753\begin_layout Plain Layout
7754
7755configuration.size[2] = Ny;
7756\end_layout
7757
7758\begin_layout Plain Layout
7759
7760configuration.size[3] = Nz;
7761\end_layout
7762
7763\begin_layout Plain Layout
7764
7765\end_layout
7766
7767\begin_layout Plain Layout
7768
7769configuration.omitDimension[0] = 1; // disable FFT over the batching dimension
7770\end_layout
7771
7772\begin_layout Plain Layout
7773
7774\end_layout
7775
7776\begin_layout Plain Layout
7777
7778uint64_t bufferSize = (uint64_t)sizeof(float) * configuration.size[0] * configura
7779tion.size[1] * configuration.size[2] * configuration.size[3];
7780\end_layout
7781
7782\begin_layout Plain Layout
7783
7784\end_layout
7785
7786\begin_layout Plain Layout
7787
7788//Device management + code submission - code is identical to the first example,
7789 except that you need to allocate two buffers (and provide them in the launch
7790 configuration).
7791\end_layout
7792
7793\begin_layout Plain Layout
7794
7795\end_layout
7796
7797\begin_layout Plain Layout
7798
7799
7800\backslash
7801end{minted}
7802\end_layout
7803
7804\begin_layout Plain Layout
7805
7806
7807\backslash
7808end{mdframed}
7809\end_layout
7810
7811\end_inset
7812
7813
7814\end_layout
7815
7816\begin_layout Subsection
7817Advanced FFT application example: 3D zero-padded FFT
7818\end_layout
7819
7820\begin_layout Standard
7821In this example, VkFFT is configured to calculate a 3D FFT of a system.
7822 The meaningful data is located in the first octant of the buffer, the rest
7823 is padded with zeros.
7824 This configuration removes the circular part of the convolution and allows
7825 modelling of open systems.
7826\end_layout
7827
7828\begin_layout Standard
7829\begin_inset ERT
7830status open
7831
7832\begin_layout Plain Layout
7833
7834
7835\backslash
7836begin{mdframed}[backgroundcolor=bg]
7837\end_layout
7838
7839\begin_layout Plain Layout
7840
7841
7842\backslash
7843begin{minted}[tabsize=4,obeytabs,breaklines]{C}
7844\end_layout
7845
7846\begin_layout Plain Layout
7847
7848//zero-initialize configuration + FFT application
7849\end_layout
7850
7851\begin_layout Plain Layout
7852
7853VkFFTConfiguration configuration = {};
7854\end_layout
7855
7856\begin_layout Plain Layout
7857
7858VkFFTApplication app = {};
7859\end_layout
7860
7861\begin_layout Plain Layout
7862
7863\end_layout
7864
7865\begin_layout Plain Layout
7866
7867configuration.FFTdim = 3; //FFT dimension
7868\end_layout
7869
7870\begin_layout Plain Layout
7871
7872configuration.size[0] = Nx;
7873\end_layout
7874
7875\begin_layout Plain Layout
7876
7877configuration.size[1] = Ny;
7878\end_layout
7879
7880\begin_layout Plain Layout
7881
7882configuration.size[2] = Nz;
7883\end_layout
7884
7885\begin_layout Plain Layout
7886
7887\end_layout
7888
7889\begin_layout Plain Layout
7890
7891configuration.performZeropadding[0] = 1; //Perform padding with zeros on
7892 GPU.
7893 Still need to properly align input data (no need to fill padding area with
7894 meaningful data) but this will increase performance due to the lower amount
7895 of the memory reads/writes and omitting sequences only consisting of zeros.
7896\end_layout
7897
7898\begin_layout Plain Layout
7899
7900configuration.performZeropadding[1] = 1;
7901\end_layout
7902
7903\begin_layout Plain Layout
7904
7905configuration.performZeropadding[2] = 1;
7906\end_layout
7907
7908\begin_layout Plain Layout
7909
7910configuration.fft_zeropad_left[0] = (uint64_t)ceil(configuration.size[0] /
7911 2.0);
7912\end_layout
7913
7914\begin_layout Plain Layout
7915
7916configuration.fft_zeropad_right[0] = configuration.size[0];
7917\end_layout
7918
7919\begin_layout Plain Layout
7920
7921configuration.fft_zeropad_left[1] = (uint64_t)ceil(configuration.size[1] /
7922 2.0);
7923\end_layout
7924
7925\begin_layout Plain Layout
7926
7927configuration.fft_zeropad_right[1] = configuration.size[1];
7928\end_layout
7929
7930\begin_layout Plain Layout
7931
7932configuration.fft_zeropad_left[2] = (uint64_t)ceil(configuration.size[2] /
7933 2.0);
7934\end_layout
7935
7936\begin_layout Plain Layout
7937
7938configuration.fft_zeropad_right[2] = configuration.size[2];
7939\end_layout
7940
7941\begin_layout Plain Layout
7942
7943\end_layout
7944
7945\begin_layout Plain Layout
7946
7947uint64_t bufferSize = (uint64_t)storageComplexSize * configuration.size[0]
7948 * configuration.size[1] * configuration.size[2];
7949\end_layout
7950
7951\begin_layout Plain Layout
7952
7953\end_layout
7954
7955\begin_layout Plain Layout
7956
7957\end_layout
7958
7959\begin_layout Plain Layout
7960
7961//Device management + code submission - code is identical to the first example
7962\end_layout
7963
7964\begin_layout Plain Layout
7965
7966\end_layout
7967
7968\begin_layout Plain Layout
7969
7970
7971\backslash
7972end{minted}
7973\end_layout
7974
7975\begin_layout Plain Layout
7976
7977
7978\backslash
7979end{mdframed}
7980\end_layout
7981
7982\end_inset
7983
7984
7985\end_layout
7986
7987\begin_layout Subsection
7988Convolution application example: 3x3 matrix-vector convolution in 1D
7989\end_layout
7990
7991\begin_layout Standard
7992In this example, VkFFT is configured to calculate a kernel, represented
7993 by a 3x3 matrix and a system, represented by a 3D vector.
7994 Their convolution is a matrix-vector multiplication in the frequency domain.
7995\end_layout
7996
7997\begin_layout Standard
7998\begin_inset ERT
7999status open
8000
8001\begin_layout Plain Layout
8002
8003
8004\backslash
8005begin{mdframed}[backgroundcolor=bg]
8006\end_layout
8007
8008\begin_layout Plain Layout
8009
8010
8011\backslash
8012begin{minted}[tabsize=4,obeytabs,breaklines]{C}
8013\end_layout
8014
8015\begin_layout Plain Layout
8016
8017//zero-initialize configuration + FFT application, we need two - one for
8018 kernel calculation
8019\end_layout
8020
8021\begin_layout Plain Layout
8022
8023VkFFTConfiguration kernel_configuration = {};
8024\end_layout
8025
8026\begin_layout Plain Layout
8027
8028VkFFTConfiguration convolution_configuration = {};
8029\end_layout
8030
8031\begin_layout Plain Layout
8032
8033VkFFTApplication app_kernel = {};
8034\end_layout
8035
8036\begin_layout Plain Layout
8037
8038VkFFTApplication app_convolution = {};
8039\end_layout
8040
8041\begin_layout Plain Layout
8042
8043\end_layout
8044
8045\begin_layout Plain Layout
8046
8047\end_layout
8048
8049\begin_layout Plain Layout
8050
8051kernel_configuration.FFTdim = 1; //FFT dimension
8052\end_layout
8053
8054\begin_layout Plain Layout
8055
8056kernel_configuration.size[0] = Nx; //FFT size
8057\end_layout
8058
8059\begin_layout Plain Layout
8060
8061\end_layout
8062
8063\begin_layout Plain Layout
8064
8065uint64_t bufferSize = (uint64_t)sizeof(float) * 2 * kernel_configuration.size[0];
8066\end_layout
8067
8068\begin_layout Plain Layout
8069
8070\end_layout
8071
8072\begin_layout Plain Layout
8073
8074//configure kernel 
8075\end_layout
8076
8077\begin_layout Plain Layout
8078
8079kernel_configuration.kernelConvolution = 1; //specify if this plan is used
8080 to create kernel for convolution
8081\end_layout
8082
8083\begin_layout Plain Layout
8084
8085kernel_configuration.coordinateFeatures = 9; //Specify dimensionality of
8086 the input feature vector (default 1).
8087 Each component is stored not as a vector, but as a separate system and
8088 padded on it's own according to other options (i.e.
8089 for x*y system of 3-vector, first x*y elements correspond to the first
8090 dimension, then goes x*y for the second, etc).
8091\end_layout
8092
8093\begin_layout Plain Layout
8094
8095//coordinateFeatures number is an important constant for convolution.
8096 If we perform 1x1 convolution, it is equal to number of features, but matrixCon
8097volution should be equal to 1.
8098 For matrix convolution, it must be equal to matrixConvolution parameter.
8099 If we perform 2x2 convolution, it is equal to 3 for symmetric kernel (stored
8100 as xx, xy, yy) and 4 for nonsymmetric (stored as xx, xy, yx, yy).
8101 Similarly, 6 (stored as xx, xy, xz, yy, yz, zz) and 9 (stored as xx, xy,
8102 xz, yx, yy, yz, zx, zy, zz) for 3x3 convolutions.
8103 
8104\end_layout
8105
8106\begin_layout Plain Layout
8107
8108kernel_configuration.normalize = 1;
8109\end_layout
8110
8111\begin_layout Plain Layout
8112
8113\end_layout
8114
8115\begin_layout Plain Layout
8116
8117//Initialize app_kernel and perform a single forward FFT like in examples
8118 before.
8119 You pass kernel as a buffer for the preparation stage.
8120\end_layout
8121
8122\begin_layout Plain Layout
8123
8124\end_layout
8125
8126\begin_layout Plain Layout
8127
8128convolution_configuration = kernel_configuration;
8129\end_layout
8130
8131\begin_layout Plain Layout
8132
8133convolution_configuration.kernelConvolution = 0;
8134\end_layout
8135
8136\begin_layout Plain Layout
8137
8138convolution_configuration.performConvolution = 1;
8139\end_layout
8140
8141\begin_layout Plain Layout
8142
8143convolution_configuration.symmetricKernel = 0;//Specify if convolution kernel
8144 is symmetric.
8145 In this case we only pass upper triangle part of it in the form of: (xx,
8146 xy, yy) for 2d and (xx, xy, xz, yy, yz, zz) for 3d.
8147\end_layout
8148
8149\begin_layout Plain Layout
8150
8151convolution_configuration.matrixConvolution = 3;//we do matrix convolution,
8152 so kernel is 9 numbers (3x3), but vector dimension is 3
8153\end_layout
8154
8155\begin_layout Plain Layout
8156
8157convolution_configuration.coordinateFeatures = 3;//equal to matrixConvolution
8158 size
8159\end_layout
8160
8161\begin_layout Plain Layout
8162
8163\end_layout
8164
8165\begin_layout Plain Layout
8166
8167//Initialize app_convolution and perform a single forward FFT like in examples
8168 before.
8169 You pass kernel as kernel and system to be convolved with it as buffer
8170\end_layout
8171
8172\begin_layout Plain Layout
8173
8174\end_layout
8175
8176\begin_layout Plain Layout
8177
8178
8179\backslash
8180end{minted}
8181\end_layout
8182
8183\begin_layout Plain Layout
8184
8185
8186\backslash
8187end{mdframed}
8188\end_layout
8189
8190\end_inset
8191
8192
8193\end_layout
8194
8195\begin_layout Subsection
8196Convolution application example: R2C cross-correlation between two sets
8197 of N images
8198\end_layout
8199
8200\begin_layout Standard
8201In this example, VkFFT is configured to calculate a kernel, represented
8202 by three 2D vectors (RGB values of a pixel) and a system, also represented
8203 by three 2D vectors.
8204 There are N kernels and N systems.
8205 Their cross-correlation is a conjugate convolution in the frequency domain.
8206 Images are usually stored as real, not complex numbers, so code uses R2C
8207 optimization as well.
8208\end_layout
8209
8210\begin_layout Standard
8211\begin_inset ERT
8212status open
8213
8214\begin_layout Plain Layout
8215
8216
8217\backslash
8218begin{mdframed}[backgroundcolor=bg]
8219\end_layout
8220
8221\begin_layout Plain Layout
8222
8223
8224\backslash
8225begin{minted}[tabsize=4,obeytabs,breaklines]{C}
8226\end_layout
8227
8228\begin_layout Plain Layout
8229
8230//zero-initialize configuration + FFT application, we need two - one for
8231 kernel calculation
8232\end_layout
8233
8234\begin_layout Plain Layout
8235
8236VkFFTConfiguration kernel_configuration = {};
8237\end_layout
8238
8239\begin_layout Plain Layout
8240
8241VkFFTConfiguration convolution_configuration = {};
8242\end_layout
8243
8244\begin_layout Plain Layout
8245
8246VkFFTApplication app_kernel = {};
8247\end_layout
8248
8249\begin_layout Plain Layout
8250
8251VkFFTApplication app_convolution = {};
8252\end_layout
8253
8254\begin_layout Plain Layout
8255
8256\end_layout
8257
8258\begin_layout Plain Layout
8259
8260\end_layout
8261
8262\begin_layout Plain Layout
8263
8264kernel_configuration.FFTdim = 2; //FFT dimension
8265\end_layout
8266
8267\begin_layout Plain Layout
8268
8269kernel_configuration.size[0] = Nx;
8270\end_layout
8271
8272\begin_layout Plain Layout
8273
8274kernel_configuration.size[1] = Ny; 
8275\end_layout
8276
8277\begin_layout Plain Layout
8278
8279kernel_configuration.coordinateFeatures = 3;
8280\end_layout
8281
8282\begin_layout Plain Layout
8283
8284kernel_configuration.numberBatches = N;
8285\end_layout
8286
8287\begin_layout Plain Layout
8288
8289kernel_configuration.performR2C = 1;
8290\end_layout
8291
8292\begin_layout Plain Layout
8293
8294kernel_configuration.normalize = 1;
8295\end_layout
8296
8297\begin_layout Plain Layout
8298
8299\end_layout
8300
8301\begin_layout Plain Layout
8302
8303uint64_t bufferSize = (uint64_t)sizeof(float) * 2 * (kernel_configuration.size[0]
8304/2+1) * kernel_configuration.size[1] * kernel_configuration.coordinateFeatures
8305 * kernel_configuration.numberBatches; 
8306\end_layout
8307
8308\begin_layout Plain Layout
8309
8310	
8311\end_layout
8312
8313\begin_layout Plain Layout
8314
8315kernel_configuration.kernelConvolution = 1; //specify if this plan is used
8316 to create kernel for convolution
8317\end_layout
8318
8319\begin_layout Plain Layout
8320
8321\end_layout
8322
8323\begin_layout Plain Layout
8324
8325//Initialize app_kernel and perform a single forward FFT like in examples
8326 before.
8327 Pad in-place R2C system like this:
8328\end_layout
8329
8330\begin_layout Plain Layout
8331
8332\end_layout
8333
8334\begin_layout Plain Layout
8335
8336for (uint64_t n = 0; n < kernel_configuration.numberBatches; n++) {
8337\end_layout
8338
8339\begin_layout Plain Layout
8340
8341	for (uint64_t c = 0; c < kernel_configuration.coordinateFeatures; c++) {
8342\end_layout
8343
8344\begin_layout Plain Layout
8345
8346		for (uint64_t j = 0; j < kernel_configuration.size[1]; j++) {
8347\end_layout
8348
8349\begin_layout Plain Layout
8350
8351			for (uint64_t i = 0; i < kernel_configuration.size[0]; i++) {
8352\end_layout
8353
8354\begin_layout Plain Layout
8355
8356				kernel_padded_GPU[i + j * 2 * (kernel_configuration.size[0]/2 + 1) +
8357 c * 2 * (kernel_configuration.size[0]/2 + 1) * kernel_configuration.size[1]
8358 + n * 2 * (kernel_configuration.size[0]/2 + 1) * kernel_configuration.size[1]
8359 * kernel_configuration.coordinateFeatures] = kernel_input[i + j * kernel_configu
8360ration.size[0] + c * kernel_configuration.size[0] * kernel_configuration.size[1]
8361 + n * kernel_configuration.size[0] * kernel_configuration.size[1] * kernel_config
8362uration.coordinateFeatures];
8363\end_layout
8364
8365\begin_layout Plain Layout
8366
8367			}
8368\end_layout
8369
8370\begin_layout Plain Layout
8371
8372		}
8373\end_layout
8374
8375\begin_layout Plain Layout
8376
8377	}
8378\end_layout
8379
8380\begin_layout Plain Layout
8381
8382}
8383\end_layout
8384
8385\begin_layout Plain Layout
8386
8387convolution_configuration = kernel_configuration;
8388\end_layout
8389
8390\begin_layout Plain Layout
8391
8392convolution_configuration.kernelConvolution = 0;
8393\end_layout
8394
8395\begin_layout Plain Layout
8396
8397convolution_configuration.performConvolution = 1;
8398\end_layout
8399
8400\begin_layout Plain Layout
8401
8402convolution_configuration.conjugateConvolution = 1;
8403\end_layout
8404
8405\begin_layout Plain Layout
8406
8407\end_layout
8408
8409\begin_layout Plain Layout
8410
8411//Initialize app_convolution and perform a single forward FFT like in examples
8412 before.
8413 Pad the system in the same way as the kernel
8414\end_layout
8415
8416\begin_layout Plain Layout
8417
8418\end_layout
8419
8420\begin_layout Plain Layout
8421
8422
8423\backslash
8424end{minted}
8425\end_layout
8426
8427\begin_layout Plain Layout
8428
8429
8430\backslash
8431end{mdframed}
8432\end_layout
8433
8434\end_inset
8435
8436
8437\end_layout
8438
8439\begin_layout Subsection
8440Simple FFT application binary reuse application
8441\end_layout
8442
8443\begin_layout Standard
8444This example shows how to save/load binaries generated by VkFFT.
8445 This can reduce time taken by initializeVkFFT call by removing RTC components
8446 from it.
8447 Be sure that rest of the configuration stays the same to reuse the binary.
8448 Use rb/wb flags to load/save.
8449 This does not currently work in Metal backend.
8450\end_layout
8451
8452\begin_layout Standard
8453\begin_inset ERT
8454status open
8455
8456\begin_layout Plain Layout
8457
8458
8459\backslash
8460begin{mdframed}[backgroundcolor=bg]
8461\end_layout
8462
8463\begin_layout Plain Layout
8464
8465
8466\backslash
8467begin{minted}[tabsize=4,obeytabs,breaklines]{C}
8468\end_layout
8469
8470\begin_layout Plain Layout
8471
8472VkFFTConfiguration configuration = {};
8473\end_layout
8474
8475\begin_layout Plain Layout
8476
8477VkFFTApplication app = {};
8478\end_layout
8479
8480\begin_layout Plain Layout
8481
8482\end_layout
8483
8484\begin_layout Plain Layout
8485
8486//configuration is initialized like in other examples
8487\end_layout
8488
8489\begin_layout Plain Layout
8490
8491configuration.saveApplicationToString = 1;
8492\end_layout
8493
8494\begin_layout Plain Layout
8495
8496//configuration.loadApplicationFromString = 1; //choose one to save/load
8497 binary file
8498\end_layout
8499
8500\begin_layout Plain Layout
8501
8502\end_layout
8503
8504\begin_layout Plain Layout
8505
8506if (configuration.loadApplicationFromString) {
8507\end_layout
8508
8509\begin_layout Plain Layout
8510
8511	FILE* kernelCache;
8512\end_layout
8513
8514\begin_layout Plain Layout
8515
8516	uint64_t str_len;
8517\end_layout
8518
8519\begin_layout Plain Layout
8520
8521	kernelCache = fopen("VkFFT_binary", "rb");
8522\end_layout
8523
8524\begin_layout Plain Layout
8525
8526	fseek(kernelCache, 0, SEEK_END);
8527\end_layout
8528
8529\begin_layout Plain Layout
8530
8531	str_len = ftell(kernelCache);
8532\end_layout
8533
8534\begin_layout Plain Layout
8535
8536	fseek(kernelCache, 0, SEEK_SET);
8537\end_layout
8538
8539\begin_layout Plain Layout
8540
8541	configuration.loadApplicationString = malloc(str_len);
8542\end_layout
8543
8544\begin_layout Plain Layout
8545
8546	fread(configuration.loadApplicationString, str_len, 1, kernelCache);
8547\end_layout
8548
8549\begin_layout Plain Layout
8550
8551	fclose(kernelCache);
8552\end_layout
8553
8554\begin_layout Plain Layout
8555
8556}
8557\end_layout
8558
8559\begin_layout Plain Layout
8560
8561\end_layout
8562
8563\begin_layout Plain Layout
8564
8565resFFT = initializeVkFFT(&app, configuration);
8566\end_layout
8567
8568\begin_layout Plain Layout
8569
8570if (resFFT != VKFFT_SUCCESS) return resFFT;
8571\end_layout
8572
8573\begin_layout Plain Layout
8574
8575\end_layout
8576
8577\begin_layout Plain Layout
8578
8579if (configuration.loadApplicationFromString)
8580\end_layout
8581
8582\begin_layout Plain Layout
8583
8584	free(configuration.loadApplicationString);
8585\end_layout
8586
8587\begin_layout Plain Layout
8588
8589\end_layout
8590
8591\begin_layout Plain Layout
8592
8593if (configuration.saveApplicationToString) {
8594\end_layout
8595
8596\begin_layout Plain Layout
8597
8598	FILE* kernelCache;
8599\end_layout
8600
8601\begin_layout Plain Layout
8602
8603	kernelCache = fopen("VkFFT_binary", "wb");
8604\end_layout
8605
8606\begin_layout Plain Layout
8607
8608	fwrite(app.saveApplicationString, app.applicationStringSize, 1, kernelCache);
8609\end_layout
8610
8611\begin_layout Plain Layout
8612
8613	fclose(kernelCache);
8614\end_layout
8615
8616\begin_layout Plain Layout
8617
8618}
8619\end_layout
8620
8621\begin_layout Plain Layout
8622
8623\end_layout
8624
8625\begin_layout Plain Layout
8626
8627//application is launched like in other examples
8628\end_layout
8629
8630\begin_layout Plain Layout
8631
8632
8633\backslash
8634end{minted}
8635\end_layout
8636
8637\begin_layout Plain Layout
8638
8639
8640\backslash
8641end{mdframed} 
8642\end_layout
8643
8644\end_inset
8645
8646
8647\end_layout
8648
8649\end_body
8650\end_document