@@ -72,7 +72,7 @@ if(NOT GPU_BACKEND STREQUAL "ROCM")
7272 else ()
7373 # Best-effort probe of the visible GPU (mirrors build.sh detect_with_torch).
7474 execute_process (
75- COMMAND "${Python_EXECUTABLE} " -c "import torch; assert torch.cuda.is_available(); mj, mn = torch.cuda.get_device_capability(0); print(f'{mj}.{mn}a' if (mj, mn) in ((9, 0), (12, 0)) else f'{mj}.{mn}')"
75+ COMMAND "${Python_EXECUTABLE} " -c "import torch; assert torch.cuda.is_available(); mj, mn = torch.cuda.get_device_capability(0); print(f'{mj}.{mn}a' if (mj, mn) in ((9, 0), (12, 0), (12, 1) ) else f'{mj}.{mn}')"
7676 OUTPUT_VARIABLE _FV_ARCH_LIST
7777 OUTPUT_STRIP_TRAILING_WHITESPACE
7878 RESULT_VARIABLE _fv_detect_rc
@@ -208,10 +208,13 @@ else()
208208 set (_WANTS_ATTN_QAT_INFER ON )
209209 elseif (FASTVIDEO_KERNEL_BUILD_ATTN_QAT_INFER STREQUAL "AUTO" )
210210 if (TORCH_CUDA_ARCH_LIST)
211+ # Consumer/workstation Blackwell: sm_120a (RTX 5090 / PRO 6000) and
212+ # sm_121a (DGX Spark GB10). The block-scaled FP4 MMA is valid on both
213+ # (GB10-verified: cos ~0.98 vs bf16 SDPA across shapes).
211214 string (REGEX MATCH
212- "(^|[; ,])((12\\ .0a)|(120a)|(sm_120a))([; ,]|$)"
213- _HAS_120A "${TORCH_CUDA_ARCH_LIST} " )
214- if (_HAS_120A )
215+ "(^|[; ,])((12\\ .0a)|(120a)|(sm_120a)|(12 \\ .1a)|(121a)|(sm_121a) )([; ,]|$)"
216+ _HAS_BLACKWELL_FP4 "${TORCH_CUDA_ARCH_LIST} " )
217+ if (_HAS_BLACKWELL_FP4 )
215218 set (_WANTS_ATTN_QAT_INFER ON )
216219 endif ()
217220 else ()
@@ -243,7 +246,7 @@ else()
243246 else ()
244247 message (STATUS
245248 "attn_qat_infer kernels: DISABLED "
246- "(requires CUDA 12.8+ and Blackwell sm_120a)" )
249+ "(requires CUDA 12.8+ and Blackwell sm_120a/sm_121a )" )
247250 endif ()
248251endif ()
249252
@@ -253,12 +256,12 @@ set(BUILD_CXX_KERNELS ON)
253256# ---------------------------------------------------------------------------
254257# Per-arch split for the Blackwell FP4 (attn_qat_infer) build
255258# ---------------------------------------------------------------------------
256- # The FP4 kernels are sm_120a -only (they emit `cvt.e2m1x2` etc.), while the main
259+ # The FP4 kernels are Blackwell -only (sm_120a/sm_121a; they emit `cvt.e2m1x2` etc.), while the main
257260# extension (Hopper-only TK + generic turbodiffusion) targets the full arch list.
258261# find_package(Torch) injects ONE global -gencode list into CMAKE_CUDA_FLAGS that
259262# forces every target onto every arch, so the FP4 sources also get the sm_90a pass
260263# and ptxas rejects their Blackwell instructions. Strip that global list and drive
261- # arch per target via CUDA_ARCHITECTURES instead (the fp4* targets pin 120a below;
264+ # arch per target via CUDA_ARCHITECTURES instead (the fp4* targets pin the Blackwell archs below;
262265# the main extension gets the full list). Only do this for the FP4 build with an
263266# explicit arch list, so the cu126 / local autodetect paths stay untouched.
264267if (ENABLE_ATTN_QAT_INFER AND TORCH_CUDA_ARCH_LIST)
@@ -270,7 +273,7 @@ if(ENABLE_ATTN_QAT_INFER AND TORCH_CUDA_ARCH_LIST)
270273 set (FASTVIDEO_MAIN_CUDA_ARCHS "${TORCH_CUDA_ARCH_LIST} " )
271274 string (REPLACE "sm_" "" FASTVIDEO_MAIN_CUDA_ARCHS "${FASTVIDEO_MAIN_CUDA_ARCHS} " )
272275 string (REPLACE "." "" FASTVIDEO_MAIN_CUDA_ARCHS "${FASTVIDEO_MAIN_CUDA_ARCHS} " )
273- message (STATUS "[per-arch] main extension archs=${FASTVIDEO_MAIN_CUDA_ARCHS} , fp4* archs=120a " )
276+ message (STATUS "[per-arch] main extension archs=${FASTVIDEO_MAIN_CUDA_ARCHS} , fp4* archs=sm_120a/sm_121a " )
274277endif ()
275278
276279# Compiler flags
@@ -410,8 +413,18 @@ if(ENABLE_ATTN_QAT_INFER)
410413 $<$<COMPILE_LANGUAGE :CXX >:-O3 -std =c ++17>
411414 $<$<COMPILE_LANGUAGE :CUDA >:${ATTN_QAT_INFER_CUDA_FLAGS} >
412415 )
416+ # FP4 kernels target consumer/workstation Blackwell: sm_120a (RTX 5090 /
417+ # PRO 6000) and sm_121a (DGX Spark GB10). sm_121a needs CUDA 13's ptxas
418+ # (12.8 lacks it), so it is added only on CUDA >= 12.9 — pre-13 toolchains
419+ # keep the original sm_120a-only build unchanged. sm_121a GB10-verified
420+ # (cos ~0.98 vs bf16).
421+ set (FASTVIDEO_FP4_CUDA_ARCHS "120a" )
422+ if (NOT CUDAToolkit_VERSION VERSION_LESS 12.9)
423+ list (APPEND FASTVIDEO_FP4_CUDA_ARCHS "121a" )
424+ endif ()
425+ message (STATUS "fp4* CUDA architectures: ${FASTVIDEO_FP4_CUDA_ARCHS} " )
413426 set_target_properties (fp4attn_cuda PROPERTIES
414- CUDA_ARCHITECTURES "120a "
427+ CUDA_ARCHITECTURES "${FASTVIDEO_FP4_CUDA_ARCHS} "
415428 CXX_STANDARD 17
416429 CUDA_STANDARD 17
417430 )
@@ -427,7 +440,7 @@ if(ENABLE_ATTN_QAT_INFER)
427440 $<$<COMPILE_LANGUAGE :CUDA >:${ATTN_QAT_INFER_CUDA_FLAGS} >
428441 )
429442 set_target_properties (fp4quant_cuda PROPERTIES
430- CUDA_ARCHITECTURES "120a "
443+ CUDA_ARCHITECTURES "${FASTVIDEO_FP4_CUDA_ARCHS} "
431444 CXX_STANDARD 17
432445 CUDA_STANDARD 17
433446 )
@@ -449,6 +462,6 @@ message(STATUS "host / backend: ${CMAKE_SYSTEM_PROCESSOR} / ${GPU_BACKEND}
449462message (STATUS "TORCH_CUDA_ARCH_LIST: ${TORCH_CUDA_ARCH_LIST} " )
450463message (STATUS "fastvideo_kernel_ops: ON (turbodiffusion int8-gemm/quant/rmsnorm/layernorm, all listed archs)" )
451464message (STATUS " + TK sta/block_sparse (sm_90a only): ${ENABLE_TK_KERNELS} " )
452- message (STATUS "fp4attn/fp4quant (sm_120a only , CUDA >= 12.8): ${ENABLE_ATTN_QAT_INFER} " )
465+ message (STATUS "fp4attn/fp4quant (sm_120a/sm_121a , CUDA >= 12.8): ${ENABLE_ATTN_QAT_INFER} " )
453466message (STATUS "Triton fallbacks ship in python/fastvideo_kernel/triton_kernels regardless." )
454467message (STATUS "============================================================" )
0 commit comments