Vulkan GLSL değil SPIR-V kabul eder — ve SPIR-V onu hangi dilin
ürettiğini umursamaz. Microsoft’un dxc‘si (DirectX Shader Compiler)
doğrudan SPIR-V üretir, yani mevcut bir HLSL kod tabanı yeniden yazmadan
bir Vulkan renderer’ı besleyebilir. Boşluklar eşlemede: register
annotation’ları vs descriptor binding’leri, CBV vs UBO ve her daim var
olan row_major vs column_major varsayılanı.
Derleme
build.sh
dxc -spirv -T ps_6_0 -E main shader.hlsl -Fo shader.spv
# ^SPIR-V çıktısı ^profil ^entry
# Genelde istediğiniz Vulkan hedefli düğmeler:
dxc -spirv -fvk-use-gl-layout # std430/GL layout kuralları
-fvk-use-dx-layout # veya DX offset'lerini koru
-fvk-b-shift 0 0 # register b* → binding'e kaydır
-fvk-t-shift 0 0 # t* kaydırma
-fvk-s-shift 0 0 # s* kaydırma
-fvk-u-shift 0 0 # u* (UAV) kaydırma
-fspv-target-env=vulkan1.3 # SPIR-V env hedefi
-Zi # debug bilgisi → RenderDoc okunabilir-fvk-*-shift flag’leri HLSL register space’lerini (b0, t0, u0,
s0) Vulkan’ın düz binding = N numaralandırmasına yeniden eşler —
aynı shader iki API’yi de beslerken şarttır.
Isıran eşleme
mapping.txt
HLSL: cbuffer Params : register(b0) → VK: layout(set=0,binding=0) UBO
HLSL: Texture2D t : register(t0) → VK: layout(set=0,binding=1) texture2D
HLSL: SamplerState s : register(s0) → VK: layout(set=0,binding=2) sampler
HLSL: RWTexture2D u : register(u0) → VK: layout(set=0,binding=3) image2D
HLSL: register(b0, space1) → VK: set=1, binding=0space → set, register → binding — -fvk-*-shift flag’leri
onları offset’ler, böylece birden çok space tek Vulkan set’inde bir
arada olabilir.
Gerçek tuzaklar
pitfalls.txt
row_major vs column_major:
HLSL cbuffer varsayılanı column_major, GLSL std140 row_major —
-fvk-use-gl-layout veya #pragma pack_matrix ile BİRİNİ seçin —
sessizce transpoz edilen matrix'ler 1 numaralı porting bug'ıdır
push constants:
HLSL'de push constant kavramı yoktur — dxc, [[vk::push_constant]]
işaretli özel bir cbuffer'ı VK'nin push_constant bloğuna eşler —
veya -fvk-use-dx-layout ile normal UBO gibi davranın
vertex inputs:
HLSL semantik isimler (POSITION, TEXCOORD0) kullanır; Vulkan
numaralı location'lar ister — [[vk::location(N)]] kullanın veya
pipeline oluşturmada attribute'ları eşleyin
combined sampler:
HLSL t0 (texture) ve s0 (sampler)'ı ayırır — Vulkan
texture2D+sample() tek descriptor kullanır; dxc bunu halleder
ama binding numaraları farklıdırshader.hlsl
// minimal Vulkan-dostu HLSL:
[[vk::binding(0,0)]] cbuffer Params { row_major float4x4 mvp; };
[[vk::binding(1,0)]] Texture2D tex;
[[vk::binding(2,0)]] SamplerState smp;
[[vk::location(0)]] float4 main([[vk::location(0)]] float3 pos : POSITION,
[[vk::location(1)]] float2 uv : TEXCOORD0)
: SV_Position { return mul(mvp, float4(pos,1)); }Ne zaman değer
- Mevcut bir D3D renderer’ı port edin — HLSL kaynağını koruyun, SPIR-V üretin, çift-kaynak bakımı yok.
- Shader lib’i çapraz derleyin — tek
.hlsl→ D3D12 için DXIL + Vulkan için SPIR-V; reflection içinspirv-cross(diğer yazı). - DXIL özellikleri — dxc’de wave op’ları,
WaveMultiPrefixOpve glslang’in GLSL’inin yalnızca uzantılarla sunduğu yeni HLSL intrinsic’leri var.
Pratik kurallar
-fspv-target-env=vulkan1.3önemlidir — varsayılan daha az kabiliyetli eski bir SPIR-V sürümünü hedefler.- CI’da
-Zi+spirv-val— DXC’nin SPIR-V’si geçerlidir ama attribute eşlemesi-fvk-*flag’lerinin açıkça yazılmasını ister. [[vk::binding(N,S)]]+[[vk::location(N)]]DXC’ye özgü attribute’lardır — register/space heuristiklerini temiz şekilde ezer.row_majoruyumsuzluğu sessiz katildir — layout’lar uyuşmazsa shader’a verilen her matrix yanlıştır; pipeline build’de bir kez assert edin.
If this post helped you, please consider buying me a coffee or donating via PayPal to support research & publishing of new posts on TechOverflow