Best Practices & Common Pitfalls
43.1 Code style
Prefix convention: g for globals/resources (gAlbedo), s for groupshared, k for constants; suffix spaces (posW, posV, posH, nTS).
Put all shared structs in .hlsli files; give every resource an explicit register(xN, spaceM).
Use ConstantBuffer<T> and structs mirrored in C++ with static_assert on sizes.
Pick one matrix convention (mul(M, v) or mul(v, M)) and one packing (column/row-major) for the entire codebase.
Compile with -WX in CI for every target (DXIL, SPIR-V) and every shipped permutation.
Format with clang-format; HLSL Tools for VS Code / Visual Studio gives IntelliSense.
43.2 Common pitfalls
Using * for matrix multiplication Row/column-major mismatch mesh invisible or distorted transpose on upload, or row_major / -Zpr, consistently cbuffer packing mismatch (float3 + 16-byte rules, float arrays) values shifted/corrupted pad C++ structs, use float4 arrays, check -Fc offsets CBV not 256-byte aligned (D3D12) align buffer offsets/sizes to 256 Missing NonUniformResourceIndex flickering/wrong textures on some GPUs wrap divergent descriptor indices
Sample in divergent control flow / compute mip artifacts, compile errors
SampleLevel/SampleGrad, hoist derivatives Sampling sRGB data as linear (or vice versa) washed-out or too dark
_SRGB formats for color, linear for data Not normalizing interpolated normals faceted, wrong highlights normalize in the PS Barrier inside divergent if hang/undefined behavior barriers must be reached by all threads Out-of-bounds compute threads writes past edges guard with if (any(id.xy >= size)) return; Race conditions on UAVs flicker, nondeterminism atomics, barriers, separate passes VS output/PS input struct mismatch PSO creation failure share one struct Assuming wave size 32 wrong results on AMD/Intel use WaveGetLaneCount() or [WaveSize]
Forgetting D3D's [0,1] depth and flipped texture V shadows/projections off uv = ndc.xy * float2(0.5, -0.5) + 0.5
NaNs from normalize(0), pow(neg, x), sqrt(neg), acos(>1) black/white pixels spreading through bloom/TAA clamp inputs, max(eps,...), NaN checks huge build times, PSO hitches prune variants, uniform branches, PSO caches
43.3 Performance checklist
Profile before optimizing; know whether you're ALU, bandwidth, occupancy, fixed-function, or CPU bound.
Minimize overdraw (depth prepass, front-to-back sorting) and full-resolution passes.
Compress and mip all textures; pack channels; use 16-bit math where safe.
Batch, instance, and go GPU-driven (indirect, bindless, mesh shaders) for large scenes.
Pre-compile shaders and PSOs; never compile in the middle of gameplay.