Recursive AI

Performance

All oneshader docs

OneShader compiles a shader about 2.4 times faster than DXC when both run as native processes, and about 14 times slower when it runs as an ordinary .NET process that has to start the runtime and JIT-compile the compiler first. Both are measured below, on the same 68 entry points, with the compiler's SPIR-V compared against DXC's SPIR-V. This page prints all of it: the tables, the losses and the method.

Every number comes from the files in bench/results/, measured on one workstation (see Method). Treat them as local measurements, not promises for your hardware.

Results at a glance

One shader compile per process, for each of the 68 (file, entry point) pairs the repository's execution-parity cases compile (25 2D-renderer, 24 3D, 11 compute, 8 language-feature entry points). DXC is the released binary run with -spirv; its default optimization. OneShader is a small command-line wrapper around ShaderCompiler.CompileFile, built three ways: as a NativeAOT binary, as a framework-dependent ReadyToRun build, and as a plain framework-dependent (JIT) build. Time is wall-clock from creating the process to its exit, with the blob written to disk. The ratio is DXC's time divided by ours per entry point, summarized by the geometric mean; a time within 5% of DXC's is a tie.

Bar chart: how many times faster or slower OneShader's compile is than DXC's, per task, log scale. NativeAOT is about 2.4 times faster warm and 2.7 times faster cold. ReadyToRun is about 5 to 6 times slower and the JIT build 13 to 14 times slower.

The chart is drawn from the results file by bench/make-report.py.

Task (one process per entry point)Entry pointsTime vs DXC (geometric mean)FastestSlowestEntry points slower than DXC
NativeAOT, warm: 2D renderer252.46× faster2.82× faster2.09× faster0
NativeAOT, warm: 3D (PBR set)242.41× faster3.14× faster2.13× faster0
NativeAOT, warm: compute112.49× faster2.81× faster2.21× faster0
NativeAOT, warm: language features82.30× faster2.72× faster2.08× faster0
NativeAOT, warm: all682.43× faster3.14× faster2.08× faster0
NativeAOT, cold: all682.68× faster3.57× faster1.51× faster0
ReadyToRun, warm: all686.10× slower3.21× slower7.74× slower68
ReadyToRun, cold: all685.30× slower2.78× slower7.00× slower68
JIT, warm: all6814.3× slower7.28× slower17.7× slower68
JIT, cold: all6812.9× slower6.73× slower16.3× slower68

"Warm" is the median of 15 repeated runs per entry point; "cold" is the first run of each entry point right after the corpus was written to a fresh directory.

The losses

  • Started as a .NET process, OneShader is slower than DXC on every entry point. The JIT build is 14.3× slower warm (113 ms median per entry point against DXC's 7.6 ms) and 12.9× slower cold; ReadyToRun is 6.1× and 5.3× slower (48 ms median). Almost all of that is starting the runtime and compiling or loading the compiler's code, not compiling the shader: the same compile inside a running process takes 0.34 ms at the median (in-process). The NativeAOT build is the one that wins, so a command-line tool that compiles shaders should ship NativeAOT; the MSBuild task runs inside the build's own long-lived .NET process, where the runtime start-up is paid once per build, not once per shader (that case, the first compile in a fresh process, is not measured here).
  • The SPIR-V is larger than DXC's with debug names on, which is the default. 57 of 68 entry points are larger, 46,620 words against DXC's 44,126 (+5.7%); the worst are lang/sizeof_static.hlsl:CSMain (+90%), 3d/skinned.hlsl:VSMain (+60%) and 3d/stage_io.hlsl:VSMain (+36%). With names off (CompileOptions.KeepNames = false) the total is 40,258 words, 8.8% below DXC, with 61 entry points smaller and 7 larger. DXC emits no names unless asked, so the second comparison is the like-for-like one; the first is what the compiler gives you by default (table).
  • The optimizer is the largest cost of a compile. With it off, SPIR-V takes 0.13 ms at the median instead of 0.34 ms (2.5× less); the worst file, 3d/bloom_downsample.hlsl, takes 1.18 ms with the optimizer and 0.22 ms without (5.5×). That is the price of the smaller output; see the in-process table.
  • MSL and WGSL are not on the chart. DXC has no such outputs, so there is nothing to compare; their in-process times are in the table. They also refuse some corpus shaders, which are left out of those columns: MSL refuses compute/append_consume.hlsl; WGSL refuses that file, 3d/stage_io.hlsl and lang/resource_arrays.hlsl (the diagnostics are in bench/results/inproc/).
  • No in-process comparison with DXC. DXC is timed as a process only. Its in-process cost is not measured, so the in-process numbers below stand alone.

In-process compile time

ShaderCompiler.Compile called on the source text in a warm process, every entry point of a file in one call, SPIR-V with the default optimizer unless the column says otherwise. BenchmarkDotNet 0.15.8 with the memory diagnoser, in-process toolchain, 3 warm-up and 12 measured iterations of at least 150 ms each (10 to 12 kept after outlier removal); the mean in milliseconds, then the standard deviation in brackets, and the managed allocation per call in KiB. Includes (3d/brdf.hlsli) are read from disk during the compile; the shader text is read once beforehand.

Over the 41 files: the median file compiles in 0.34 ms and allocates 0.85 MiB; the slowest is 2d/renderer/ui.hlsl at 2.0 ms and 4.2 MiB. MSL and WGSL cost about 3 to 5% more than SPIR-V. The first row, 2d/blit.hlsl with SPIR-V, was the first benchmark the process ran and shows it (a standard deviation of 34% of its mean; the same file with MSL, run later, takes 0.12 ms): read that one cell as a warm-up artifact.

FileSPIR-V msalloc KiBSPIR-V, optimizer off msalloc KiBMSL msalloc KiBWGSL msalloc KiB
2d/blit.hlsl0.224 (±0.076)3350.055 (±0.001)1950.124 (±0.000)3530.125 (±0.001)360
2d/blur.hlsl0.264 (±0.000)6890.106 (±0.000)3460.281 (±0.000)7210.280 (±0.000)733
2d/color_grade.hlsl0.278 (±0.003)7280.116 (±0.000)3830.292 (±0.001)7630.294 (±0.001)789
2d/msdf_text.hlsl0.313 (±0.000)8220.130 (±0.000)4290.335 (±0.001)8730.334 (±0.001)893
2d/renderer/quad.hlsl0.654 (±0.001)17040.256 (±0.001)8590.692 (±0.001)17890.695 (±0.003)1835
2d/renderer/tile.hlsl0.551 (±0.001)14370.227 (±0.003)7440.586 (±0.001)15080.586 (±0.001)1543
2d/renderer/ui.hlsl2.018 (±0.007)42680.666 (±0.004)16842.131 (±0.020)45912.194 (±0.022)4668
2d/sdf_text.hlsl0.248 (±0.000)6820.107 (±0.000)3680.269 (±0.001)7280.266 (±0.000)747
2d/sprite.hlsl0.163 (±0.000)4460.077 (±0.001)2480.179 (±0.000)4780.178 (±0.000)502
2d/tilemap.hlsl0.269 (±0.000)6970.116 (±0.001)3740.288 (±0.001)7380.288 (±0.000)760
2d/ui_rect.hlsl0.666 (±0.005)17070.242 (±0.001)7850.707 (±0.001)18210.710 (±0.001)1909
3d/bloom_downsample.hlsl1.181 (±0.002)29410.215 (±0.001)7411.187 (±0.003)31011.191 (±0.004)3135
3d/bloom_upsample.hlsl0.343 (±0.006)8680.133 (±0.000)4460.351 (±0.000)9150.350 (±0.000)939
3d/clustered_lights.hlsl0.953 (±0.011)23320.355 (±0.002)10601.002 (±0.001)24670.997 (±0.004)2478
3d/ibl.hlsl0.649 (±0.001)16620.318 (±0.003)10140.660 (±0.001)17930.646 (±0.001)1760
3d/pbr_forward.hlsl1.403 (±0.029)31430.561 (±0.007)13941.423 (±0.005)33451.402 (±0.002)3361
3d/shadow_cascades.hlsl1.104 (±0.003)26790.363 (±0.002)10801.175 (±0.003)28331.162 (±0.002)2862
3d/shadow_depth.hlsl0.100 (±0.000)2540.048 (±0.000)1430.109 (±0.000)2740.110 (±0.000)300
3d/skinned.hlsl0.334 (±0.001)8880.133 (±0.001)4540.345 (±0.001)9470.359 (±0.001)1083
3d/ssao.hlsl0.528 (±0.009)12990.198 (±0.003)6490.542 (±0.001)13700.540 (±0.001)1407
3d/stage_io.hlsl0.367 (±0.001)9620.147 (±0.001)4840.387 (±0.001)1006refused–
3d/tonemap.hlsl0.502 (±0.001)11790.189 (±0.001)5560.522 (±0.001)12180.516 (±0.001)1228
compute/append_consume.hlsl0.162 (±0.002)4170.073 (±0.001)228refused–refused–
compute/cluster_build.hlsl0.419 (±0.001)11070.129 (±0.001)4120.440 (±0.001)11550.441 (±0.002)1205
compute/cull_instances.hlsl0.353 (±0.007)8360.125 (±0.002)3730.368 (±0.000)8760.362 (±0.001)871
compute/depth_bounds.hlsl0.209 (±0.000)5620.093 (±0.001)3070.223 (±0.002)5940.220 (±0.001)599
compute/histogram.hlsl0.152 (±0.000)4090.072 (±0.001)2280.161 (±0.001)4260.156 (±0.000)423
compute/ibl_prefilter.hlsl0.655 (±0.006)16320.232 (±0.002)7530.697 (±0.001)17230.687 (±0.001)1734
compute/image_filter.hlsl0.314 (±0.000)8030.126 (±0.002)4040.323 (±0.000)8230.329 (±0.001)853
compute/light_cull.hlsl0.264 (±0.000)6900.108 (±0.002)3550.278 (±0.000)7240.272 (±0.001)731
compute/particles.hlsl0.291 (±0.000)7410.108 (±0.002)3700.312 (±0.000)8030.313 (±0.001)831
compute/prefix_sum.hlsl0.164 (±0.000)4330.068 (±0.001)2210.169 (±0.001)4420.171 (±0.000)457
compute/stage_layouts.hlsl0.210 (±0.000)5920.095 (±0.000)3440.213 (±0.000)6060.217 (±0.001)631
lang/inheritance.hlsl0.358 (±0.001)9200.125 (±0.002)4090.367 (±0.000)9370.364 (±0.000)944
lang/members.hlsl0.397 (±0.003)10350.124 (±0.000)4110.405 (±0.001)10500.405 (±0.003)1071
lang/operators.hlsl0.657 (±0.002)18740.224 (±0.003)7780.659 (±0.002)18720.660 (±0.001)1882
lang/resource_arrays.hlsl0.269 (±0.002)6970.123 (±0.001)3990.274 (±0.001)711refused–
lang/resource_locals.hlsl0.278 (±0.001)7590.105 (±0.002)3570.285 (±0.000)7680.287 (±0.001)794
lang/sizeof_static.hlsl0.227 (±0.000)6460.083 (±0.001)3000.230 (±0.000)6530.234 (±0.000)680
lang/statics_and_literals.hlsl0.431 (±0.000)11840.216 (±0.001)7250.442 (±0.001)12060.435 (±0.001)1210
lang/templates.hlsl0.586 (±0.012)15180.232 (±0.002)7760.581 (±0.001)15260.585 (±0.001)1559

"refused" marks a file the target does not support; it is left out rather than timed as a failure.

Process time per entry point

Median of 15 warm runs in milliseconds, with the fastest and slowest run in brackets, for each entry point. "vs DXC" is DXC's median divided by the OneShader median.

Entry pointDXC msNativeAOT msvs DXCReadyToRun msvs DXCJIT msvs DXC
2d/blit.hlsl:PSMain(ps)6.40 (5.98–7.61)2.57 (2.33–3.88)2.49× faster42.2 (38.5–46.6)6.59× slower99.8 (98.2–106)15.6× slower
2d/blit.hlsl:VSMain(vs)6.49 (6.02–7.83)2.56 (2.39–3.90)2.53× faster42.4 (40.0–47.2)6.52× slower101 (99.1–107)15.5× slower
2d/blur.hlsl:PSMain(ps)7.32 (6.96–8.60)2.99 (2.52–5.00)2.45× faster49.0 (44.9–51.8)6.70× slower115 (113–123)15.8× slower
2d/blur.hlsl:VSMain(vs)6.43 (6.13–7.75)2.72 (2.51–4.94)2.37× faster46.4 (41.0–48.7)7.22× slower108 (107–115)16.9× slower
2d/color_grade.hlsl:PSMain(ps)7.43 (6.97–8.46)2.95 (2.54–5.47)2.52× faster48.8 (44.2–50.4)6.56× slower117 (113–127)15.7× slower
2d/color_grade.hlsl:VSMain(vs)6.95 (6.23–9.36)2.71 (2.51–4.40)2.57× faster48.2 (42.6–50.5)6.94× slower112 (106–121)16.1× slower
2d/msdf_text.hlsl:PSMain(ps)7.47 (7.04–8.57)3.12 (2.97–4.83)2.39× faster48.6 (43.9–51.3)6.51× slower114 (109–126)15.2× slower
2d/msdf_text.hlsl:VSMain(vs)6.75 (6.22–8.14)2.78 (2.54–4.56)2.43× faster46.9 (42.5–49.3)6.94× slower109 (107–122)16.1× slower
2d/renderer/quad.hlsl:PSBlur(ps)7.34 (6.85–8.52)3.27 (3.02–3.54)2.25× faster48.2 (44.6–52.9)6.56× slower116 (112–120)15.8× slower
2d/renderer/quad.hlsl:PSGrade(ps)7.95 (7.55–8.95)3.42 (3.25–5.33)2.32× faster49.6 (43.2–52.8)6.23× slower117 (113–129)14.7× slower
2d/renderer/quad.hlsl:PSSprite(ps)6.74 (6.30–8.99)3.04 (2.68–5.46)2.22× faster47.5 (44.3–50.8)7.05× slower111 (108–116)16.4× slower
2d/renderer/quad.hlsl:VSMain(vs)7.76 (7.41–10.2)3.42 (3.03–5.55)2.27× faster49.0 (45.4–51.3)6.32× slower115 (114–121)14.9× slower
2d/renderer/tile.hlsl:PSFlat(ps)8.15 (7.61–9.41)3.00 (2.71–3.76)2.72× faster48.5 (44.7–52.3)5.95× slower114 (110–118)13.9× slower
2d/renderer/tile.hlsl:PSIds(ps)9.14 (8.47–10.4)3.25 (2.82–3.56)2.82× faster49.8 (45.2–52.0)5.45× slower118 (114–126)12.9× slower
2d/renderer/tile.hlsl:VSMain(vs)9.53 (8.51–10.6)3.39 (3.12–4.66)2.81× faster48.5 (43.3–50.2)5.09× slower118 (115–126)12.3× slower
2d/renderer/ui.hlsl:PSMain(ps)17.2 (15.7–18.7)6.45 (6.06–8.82)2.67× faster55.3 (50.2–57.1)3.21× slower125 (124–127)7.28× slower
2d/renderer/ui.hlsl:VSMain(vs)9.30 (8.75–10.7)4.41 (3.89–6.69)2.11× faster50.2 (45.6–53.6)5.40× slower119 (116–121)12.8× slower
2d/sdf_text.hlsl:PSMain(ps)7.49 (6.69–8.48)2.87 (2.67–4.68)2.61× faster48.6 (45.0–50.4)6.49× slower113 (110–116)15.1× slower
2d/sdf_text.hlsl:VSMain(vs)6.80 (6.23–8.94)2.73 (2.52–3.49)2.49× faster46.5 (44.8–50.6)6.84× slower108 (106–114)15.9× slower
2d/sprite.hlsl:PSMain(ps)6.36 (6.15–7.43)2.65 (2.41–4.38)2.40× faster47.3 (43.1–51.3)7.44× slower106 (105–117)16.7× slower
2d/sprite.hlsl:VSMain(vs)6.48 (6.12–7.84)2.61 (2.31–5.55)2.48× faster45.7 (43.6–49.0)7.05× slower106 (105–116)16.4× slower
2d/tilemap.hlsl:PSMain(ps)7.02 (6.74–9.96)2.87 (2.59–3.11)2.45× faster48.2 (45.5–51.3)6.86× slower112 (109–118)16.0× slower
2d/tilemap.hlsl:VSMain(vs)7.62 (6.81–9.16)2.85 (2.71–4.82)2.67× faster47.1 (43.9–51.2)6.18× slower112 (109–119)14.6× slower
2d/ui_rect.hlsl:PSMain(ps)9.95 (9.32–11.1)3.73 (3.36–5.78)2.67× faster50.9 (44.5–53.2)5.11× slower119 (114–124)12.0× slower
2d/ui_rect.hlsl:VSMain(vs)7.03 (6.46–8.40)3.36 (3.02–3.65)2.09× faster49.0 (44.4–52.2)6.97× slower118 (111–127)16.8× slower
3d/bloom_downsample.hlsl:PSMain(ps)11.0 (10.5–12.3)5.14 (4.43–6.03)2.14× faster52.3 (47.7–55.4)4.75× slower119 (113–131)10.8× slower
3d/bloom_downsample.hlsl:VSMain(vs)7.17 (6.38–8.15)2.99 (2.62–4.94)2.40× faster47.8 (40.0–49.4)6.67× slower112 (106–119)15.6× slower
3d/bloom_upsample.hlsl:PSMain(ps)7.70 (7.21–11.3)3.15 (2.83–5.36)2.44× faster46.4 (41.4–49.5)6.03× slower109 (107–116)14.2× slower
3d/bloom_upsample.hlsl:VSMain(vs)6.51 (6.12–7.91)2.75 (2.54–4.39)2.37× faster45.2 (41.5–46.0)6.94× slower104 (103–114)16.0× slower
3d/clustered_lights.hlsl:PSMain(ps)10.9 (9.93–13.1)4.64 (4.28–5.79)2.35× faster51.7 (47.9–53.8)4.73× slower122 (119–129)11.2× slower
3d/clustered_lights.hlsl:VSMain(vs)7.39 (6.41–8.20)3.47 (3.13–3.85)2.13× faster48.7 (44.7–50.9)6.59× slower117 (112–128)15.8× slower
3d/ibl.hlsl:PSMain(ps)8.31 (7.94–9.83)3.57 (3.27–5.80)2.33× faster49.8 (45.3–52.8)6.00× slower118 (116–129)14.2× slower
3d/ibl.hlsl:PSSky(ps)8.44 (7.44–9.07)3.42 (3.13–6.33)2.46× faster48.8 (44.4–52.1)5.79× slower119 (115–123)14.1× slower
3d/ibl.hlsl:VSMain(vs)7.77 (7.17–8.80)3.29 (2.92–3.75)2.36× faster48.6 (45.0–51.9)6.26× slower113 (111–119)14.6× slower
3d/ibl.hlsl:VSSky(vs)7.61 (7.12–8.97)3.39 (3.03–6.16)2.24× faster48.4 (44.4–50.9)6.36× slower113 (111–117)14.9× slower
3d/pbr_forward.hlsl:PSMain(ps)12.9 (12.2–14.1)5.47 (5.00–6.28)2.36× faster54.3 (51.7–56.7)4.22× slower127 (124–133)9.90× slower
3d/pbr_forward.hlsl:VSMain(vs)8.32 (7.67–9.40)3.75 (3.54–6.05)2.22× faster49.9 (43.7–53.3)6.00× slower119 (116–130)14.3× slower
3d/shadow_cascades.hlsl:PSMain(ps)12.5 (11.3–14.9)4.00 (3.83–4.81)3.14× faster51.4 (49.2–55.1)4.10× slower125 (122–131)9.98× slower
3d/shadow_cascades.hlsl:PSSpiral(ps)12.9 (12.0–13.9)4.11 (3.61–4.79)3.13× faster51.6 (46.2–54.3)4.01× slower126 (123–132)9.76× slower
3d/shadow_cascades.hlsl:VSMain(vs)8.19 (6.96–8.99)3.43 (3.08–5.52)2.39× faster47.7 (44.3–53.4)5.82× slower119 (115–125)14.5× slower
3d/shadow_depth.hlsl:VSMain(vs)6.23 (5.63–8.00)2.61 (2.21–3.61)2.39× faster46.3 (43.1–48.4)7.44× slower107 (105–116)17.2× slower
3d/skinned.hlsl:PSMain(ps)6.18 (5.85–8.11)2.82 (2.51–4.72)2.19× faster47.8 (43.0–50.8)7.74× slower109 (108–111)17.7× slower
3d/skinned.hlsl:VSMain(vs)6.80 (6.59–9.80)3.03 (2.87–4.23)2.25× faster48.1 (45.7–49.2)7.07× slower110 (107–115)16.1× slower
3d/ssao.hlsl:PSMain(ps)9.53 (9.11–10.8)3.64 (3.12–4.01)2.62× faster51.3 (48.9–53.9)5.38× slower121 (119–125)12.7× slower
3d/ssao.hlsl:VSMain(vs)7.21 (6.78–8.53)3.04 (2.64–4.54)2.37× faster48.1 (44.3–50.7)6.67× slower115 (112–124)16.0× slower
3d/stage_io.hlsl:PSMain(ps)7.93 (7.52–9.05)2.93 (2.68–3.59)2.70× faster48.4 (44.2–50.0)6.10× slower109 (108–133)13.8× slower
3d/stage_io.hlsl:VSMain(vs)7.62 (7.19–8.79)3.03 (2.74–3.41)2.52× faster48.4 (44.2–51.9)6.36× slower108 (106–117)14.2× slower
3d/tonemap.hlsl:PSMain(ps)8.24 (8.08–10.0)3.60 (3.09–4.41)2.29× faster50.0 (47.1–51.8)6.07× slower120 (119–129)14.6× slower
3d/tonemap.hlsl:VSMain(vs)6.75 (6.34–7.49)2.93 (2.66–3.06)2.30× faster48.0 (44.7–50.2)7.11× slower114 (112–118)16.8× slower
compute/append_consume.hlsl:CSMain(cs)6.60 (6.07–7.72)2.70 (2.44–2.96)2.44× faster45.9 (43.5–49.1)6.96× slower105 (103–115)15.9× slower
compute/cluster_build.hlsl:CSMain(cs)7.68 (7.46–8.84)3.47 (3.11–4.12)2.21× faster49.6 (45.7–51.9)6.47× slower116 (114–125)15.1× slower
compute/cull_instances.hlsl:CSMain(cs)8.74 (7.90–9.77)3.39 (3.05–5.06)2.58× faster49.7 (44.5–52.7)5.69× slower122 (116–125)13.9× slower
compute/depth_bounds.hlsl:CSMain(cs)8.08 (7.16–8.64)3.03 (2.67–3.31)2.67× faster48.5 (46.4–52.2)6.00× slower118 (114–125)14.6× slower
compute/histogram.hlsl:CSMain(cs)6.54 (6.01–7.13)2.80 (2.46–4.71)2.34× faster47.1 (44.8–48.6)7.20× slower107 (104–112)16.3× slower
compute/ibl_prefilter.hlsl:CSMain(cs)11.1 (10.6–12.2)4.30 (4.03–5.57)2.59× faster51.9 (48.5–54.1)4.66× slower121 (119–129)10.9× slower
compute/image_filter.hlsl:CSMain(cs)9.30 (8.48–10.2)3.31 (2.71–5.50)2.81× faster47.4 (44.9–49.2)5.10× slower113 (111–118)12.1× slower
compute/light_cull.hlsl:CSMain(cs)7.66 (7.19–8.47)3.09 (2.76–5.33)2.48× faster48.2 (44.9–51.0)6.30× slower113 (111–119)14.8× slower
compute/particles.hlsl:CSMain(cs)7.71 (7.37–9.05)3.12 (2.75–4.00)2.47× faster49.6 (45.1–53.1)6.43× slower114 (111–119)14.8× slower
compute/prefix_sum.hlsl:CSMain(cs)6.58 (6.05–7.69)2.77 (2.57–3.11)2.38× faster46.4 (44.2–48.8)7.05× slower105 (102–111)15.9× slower
compute/stage_layouts.hlsl:CSMain(cs)7.58 (7.25–9.14)3.03 (2.79–5.30)2.50× faster48.4 (44.0–50.8)6.39× slower109 (107–112)14.3× slower
lang/inheritance.hlsl:CSMain(cs)7.42 (6.99–8.21)3.26 (3.03–4.24)2.28× faster48.6 (45.2–51.8)6.55× slower113 (109–118)15.3× slower
lang/members.hlsl:CSMain(cs)7.25 (6.92–8.76)3.48 (2.85–3.94)2.08× faster48.0 (45.5–51.8)6.61× slower112 (111–121)15.5× slower
lang/operators.hlsl:CSMain(cs)9.05 (8.54–10.3)4.32 (4.05–5.04)2.10× faster49.4 (46.6–53.2)5.46× slower112 (110–121)12.4× slower
lang/resource_arrays.hlsl:CSMain(cs)8.24 (7.79–9.33)3.16 (2.82–3.98)2.61× faster46.8 (45.0–49.2)5.68× slower116 (112–127)14.0× slower
lang/resource_locals.hlsl:CSMain(cs)8.36 (7.97–9.40)3.07 (2.92–5.03)2.72× faster47.6 (42.3–51.3)5.70× slower113 (110–116)13.5× slower
lang/sizeof_static.hlsl:CSMain(cs)6.71 (6.38–8.42)3.05 (2.94–3.25)2.20× faster46.9 (43.0–47.9)7.00× slower110 (106–118)16.3× slower
lang/statics_and_literals.hlsl:CSMain(cs)7.84 (7.58–9.43)3.55 (3.39–6.07)2.21× faster50.0 (46.6–53.5)6.37× slower119 (118–128)15.2× slower
lang/templates.hlsl:CSMain(cs)8.95 (7.86–10.0)3.93 (3.77–5.75)2.28× faster49.6 (47.1–52.1)5.54× slower121 (119–133)13.5× slower

Cold runs

The first run of each entry point after the corpus was copied to a fresh directory, one sample each (no spread to show). The page cache was not dropped (that needs privileges the benchmark does not use), so "cold" here means first run, not a cold disk: the JIT and ReadyToRun builds pay for loading and compiling code on every process start, and every process, warm or cold, is a new process.

Entry pointDXC msNativeAOT msvs DXCReadyToRun msvs DXCJIT msvs DXC
2d/blit.hlsl:PSMain(ps)7.972.513.18× faster44.25.55× slower10313.0× slower
2d/blit.hlsl:VSMain(vs)7.782.722.86× faster42.95.52× slower99.512.8× slower
2d/blur.hlsl:PSMain(ps)8.232.892.85× faster49.76.04× slower11213.6× slower
2d/blur.hlsl:VSMain(vs)6.682.722.46× faster45.86.85× slower10916.3× slower
2d/color_grade.hlsl:PSMain(ps)8.442.922.90× faster49.15.81× slower11914.1× slower
2d/color_grade.hlsl:VSMain(vs)7.292.772.63× faster45.16.19× slower11415.7× slower
2d/msdf_text.hlsl:PSMain(ps)9.073.062.97× faster48.05.29× slower12113.3× slower
2d/msdf_text.hlsl:VSMain(vs)8.542.673.19× faster46.55.45× slower11012.9× slower
2d/renderer/quad.hlsl:PSBlur(ps)8.302.932.83× faster50.46.07× slower11213.5× slower
2d/renderer/quad.hlsl:PSGrade(ps)8.273.992.07× faster46.05.57× slower12415.0× slower
2d/renderer/quad.hlsl:PSSprite(ps)7.972.882.76× faster45.55.71× slower11314.2× slower
2d/renderer/quad.hlsl:VSMain(vs)8.813.862.28× faster49.35.60× slower11412.9× slower
2d/renderer/tile.hlsl:PSFlat(ps)9.773.922.49× faster44.84.59× slower11111.3× slower
2d/renderer/tile.hlsl:PSIds(ps)10.64.142.56× faster48.14.53× slower11510.9× slower
2d/renderer/tile.hlsl:VSMain(vs)11.03.293.35× faster49.64.51× slower11610.5× slower
2d/renderer/ui.hlsl:PSMain(ps)18.86.562.87× faster52.42.78× slower1276.73× slower
2d/renderer/ui.hlsl:VSMain(vs)9.433.642.59× faster47.75.06× slower11612.3× slower
2d/sdf_text.hlsl:PSMain(ps)8.072.902.78× faster47.75.91× slower11514.3× slower
2d/sdf_text.hlsl:VSMain(vs)7.792.483.14× faster47.46.08× slower11214.3× slower
2d/sprite.hlsl:PSMain(ps)7.912.383.32× faster48.16.08× slower10713.6× slower
2d/sprite.hlsl:VSMain(vs)7.602.562.97× faster45.86.02× slower10814.2× slower
2d/tilemap.hlsl:PSMain(ps)8.412.583.26× faster48.65.79× slower11013.1× slower
2d/tilemap.hlsl:VSMain(vs)8.465.621.51× faster42.04.96× slower11213.2× slower
2d/ui_rect.hlsl:PSMain(ps)11.33.513.23× faster53.04.68× slower12411.0× slower
2d/ui_rect.hlsl:VSMain(vs)8.253.162.61× faster47.65.77× slower12314.9× slower
3d/bloom_downsample.hlsl:PSMain(ps)12.85.202.47× faster51.84.03× slower1209.36× slower
3d/bloom_downsample.hlsl:VSMain(vs)6.782.972.28× faster44.36.54× slower11016.3× slower
3d/bloom_upsample.hlsl:PSMain(ps)8.244.681.76× faster43.95.33× slower11313.7× slower
3d/bloom_upsample.hlsl:VSMain(vs)6.902.283.02× faster44.36.42× slower10815.6× slower
3d/clustered_lights.hlsl:PSMain(ps)12.84.342.95× faster50.13.91× slower1229.54× slower
3d/clustered_lights.hlsl:VSMain(vs)8.253.192.59× faster48.35.86× slower11814.3× slower
3d/ibl.hlsl:PSMain(ps)8.803.412.58× faster49.25.60× slower12213.9× slower
3d/ibl.hlsl:PSSky(ps)8.223.102.65× faster48.15.86× slower12715.5× slower
3d/ibl.hlsl:VSMain(vs)8.203.402.41× faster47.45.78× slower12815.6× slower
3d/ibl.hlsl:VSSky(vs)9.013.272.76× faster50.15.56× slower12213.5× slower
3d/pbr_forward.hlsl:PSMain(ps)16.17.262.22× faster50.03.10× slower1318.14× slower
3d/pbr_forward.hlsl:VSMain(vs)9.633.792.54× faster46.64.84× slower13013.5× slower
3d/shadow_cascades.hlsl:PSMain(ps)14.34.003.57× faster48.93.43× slower1208.41× slower
3d/shadow_cascades.hlsl:PSSpiral(ps)14.64.383.33× faster50.03.43× slower1258.61× slower
3d/shadow_cascades.hlsl:VSMain(vs)9.683.362.88× faster51.05.26× slower12512.9× slower
3d/shadow_depth.hlsl:VSMain(vs)7.892.513.14× faster43.55.50× slower10713.6× slower
3d/skinned.hlsl:PSMain(ps)6.732.622.57× faster47.17.00× slower10715.9× slower
3d/skinned.hlsl:VSMain(vs)7.472.932.54× faster46.06.16× slower10914.6× slower
3d/ssao.hlsl:PSMain(ps)10.24.362.34× faster46.94.59× slower12612.3× slower
3d/ssao.hlsl:VSMain(vs)9.452.883.28× faster47.65.04× slower11412.1× slower
3d/stage_io.hlsl:PSMain(ps)8.443.142.69× faster48.15.71× slower10812.8× slower
3d/stage_io.hlsl:VSMain(vs)7.772.792.78× faster47.36.09× slower11314.6× slower
3d/tonemap.hlsl:PSMain(ps)9.093.442.64× faster48.85.37× slower12313.5× slower
3d/tonemap.hlsl:VSMain(vs)8.032.902.77× faster45.65.67× slower11314.1× slower
compute/append_consume.hlsl:CSMain(cs)7.002.352.98× faster44.96.42× slower10815.4× slower
compute/cluster_build.hlsl:CSMain(cs)8.193.802.16× faster47.85.83× slower11914.5× slower
compute/cull_instances.hlsl:CSMain(cs)9.413.232.92× faster46.84.98× slower12212.9× slower
compute/depth_bounds.hlsl:CSMain(cs)7.612.932.60× faster47.66.25× slower11515.1× slower
compute/histogram.hlsl:CSMain(cs)6.473.042.13× faster44.96.95× slower10416.1× slower
compute/ibl_prefilter.hlsl:CSMain(cs)13.95.662.46× faster48.83.51× slower1238.87× slower
compute/image_filter.hlsl:CSMain(cs)10.63.143.36× faster47.44.49× slower11410.8× slower
compute/light_cull.hlsl:CSMain(cs)7.713.052.53× faster48.46.27× slower11414.8× slower
compute/particles.hlsl:CSMain(cs)9.643.262.96× faster45.64.73× slower12613.0× slower
compute/prefix_sum.hlsl:CSMain(cs)7.922.613.03× faster43.25.46× slower10813.7× slower
compute/stage_layouts.hlsl:CSMain(cs)7.792.762.82× faster47.76.12× slower11014.1× slower
lang/inheritance.hlsl:CSMain(cs)7.173.242.22× faster47.06.55× slower11015.3× slower
lang/members.hlsl:CSMain(cs)8.743.652.39× faster45.45.20× slower11312.9× slower
lang/operators.hlsl:CSMain(cs)10.14.342.32× faster48.24.79× slower11611.5× slower
lang/resource_arrays.hlsl:CSMain(cs)8.203.162.60× faster49.15.99× slower11213.7× slower
lang/resource_locals.hlsl:CSMain(cs)10.24.212.43× faster45.34.42× slower11210.9× slower
lang/sizeof_static.hlsl:CSMain(cs)7.562.992.53× faster47.96.34× slower10814.3× slower
lang/statics_and_literals.hlsl:CSMain(cs)8.903.362.65× faster48.75.47× slower13214.8× slower
lang/templates.hlsl:CSMain(cs)11.13.972.81× faster46.54.17× slower11810.6× slower

Output size

SPIR-V words (a word is 4 bytes) for the same entry points, from the NativeAOT build (the other two builds write identical bytes). "Without debug names" is the same compile with KeepNames = false. DXC is run with its defaults, which emit no names.

Entry pointDXC wordsOneShader wordsOneShader vs DXCWithout debug namesvs DXC
2d/blit.hlsl:PSMain(ps)193192-0.5%155-19.7%
2d/blit.hlsl:VSMain(vs)187202+8.0%178-4.8%
2d/blur.hlsl:PSMain(ps)526565+7.4%488-7.2%
2d/blur.hlsl:VSMain(vs)187202+8.0%178-4.8%
2d/color_grade.hlsl:PSMain(ps)651678+4.1%596-8.4%
2d/color_grade.hlsl:VSMain(vs)187202+8.0%178-4.8%
2d/msdf_text.hlsl:PSMain(ps)650676+4.0%594-8.6%
2d/msdf_text.hlsl:VSMain(vs)237246+3.8%194-18.1%
2d/renderer/quad.hlsl:PSBlur(ps)466496+6.4%442-5.2%
2d/renderer/quad.hlsl:PSGrade(ps)680673-1.0%618-9.1%
2d/renderer/quad.hlsl:PSSprite(ps)221214-3.2%174-21.3%
2d/renderer/quad.hlsl:VSMain(vs)635659+3.8%575-9.4%
2d/renderer/tile.hlsl:PSFlat(ps)292282-3.4%242-17.1%
2d/renderer/tile.hlsl:PSIds(ps)622599-3.7%529-15.0%
2d/renderer/tile.hlsl:VSMain(vs)680703+3.4%607-10.7%
2d/renderer/ui.hlsl:PSMain(ps)29612770-6.5%2641-10.8%
2d/renderer/ui.hlsl:VSMain(vs)846838-0.9%690-18.4%
2d/sdf_text.hlsl:PSMain(ps)555581+4.7%498-10.3%
2d/sdf_text.hlsl:VSMain(vs)237246+3.8%194-18.1%
2d/sprite.hlsl:PSMain(ps)265267+0.8%223-15.8%
2d/sprite.hlsl:VSMain(vs)278287+3.2%223-19.8%
2d/tilemap.hlsl:PSMain(ps)347359+3.5%311-10.4%
2d/tilemap.hlsl:VSMain(vs)517549+6.2%454-12.2%
2d/ui_rect.hlsl:PSMain(ps)10761118+3.9%947-12.0%
2d/ui_rect.hlsl:VSMain(vs)612747+22.1%554-9.5%
3d/bloom_downsample.hlsl:PSMain(ps)16211746+7.7%1672+3.1%
3d/bloom_downsample.hlsl:VSMain(vs)187202+8.0%178-4.8%
3d/bloom_upsample.hlsl:PSMain(ps)815853+4.7%779-4.4%
3d/bloom_upsample.hlsl:VSMain(vs)187202+8.0%178-4.8%
3d/clustered_lights.hlsl:PSMain(ps)16081720+7.0%1462-9.1%
3d/clustered_lights.hlsl:VSMain(vs)456470+3.1%333-27.0%
3d/ibl.hlsl:PSMain(ps)827853+3.1%710-14.1%
3d/ibl.hlsl:PSSky(ps)543553+1.8%432-20.4%
3d/ibl.hlsl:VSMain(vs)382396+3.7%270-29.3%
3d/ibl.hlsl:VSSky(vs)187202+8.0%178-4.8%
3d/pbr_forward.hlsl:PSMain(ps)19532215+13.4%1881-3.7%
3d/pbr_forward.hlsl:VSMain(vs)609659+8.2%519-14.8%
3d/shadow_cascades.hlsl:PSMain(ps)14281168-18.2%1009-29.3%
3d/shadow_cascades.hlsl:PSSpiral(ps)17581385-21.2%1224-30.4%
3d/shadow_cascades.hlsl:VSMain(vs)442456+3.2%332-24.9%
3d/shadow_depth.hlsl:VSMain(vs)348380+9.2%301-13.5%
3d/skinned.hlsl:PSMain(ps)396425+7.3%359-9.3%
3d/skinned.hlsl:VSMain(vs)7281168+60.4%1055+44.9%
3d/ssao.hlsl:PSMain(ps)10661159+8.7%1040-2.4%
3d/ssao.hlsl:VSMain(vs)187202+8.0%178-4.8%
3d/stage_io.hlsl:PSMain(ps)587620+5.6%539-8.2%
3d/stage_io.hlsl:VSMain(vs)346471+36.1%389+12.4%
3d/tonemap.hlsl:PSMain(ps)9261017+9.8%922-0.4%
3d/tonemap.hlsl:VSMain(vs)187202+8.0%178-4.8%
compute/append_consume.hlsl:CSMain(cs)588634+7.8%503-14.5%
compute/cluster_build.hlsl:CSMain(cs)897970+8.1%857-4.5%
compute/cull_instances.hlsl:CSMain(cs)893979+9.6%804-10.0%
compute/depth_bounds.hlsl:CSMain(cs)631627-0.6%547-13.3%
compute/histogram.hlsl:CSMain(cs)478514+7.5%425-11.1%
compute/ibl_prefilter.hlsl:CSMain(cs)12491247-0.2%1160-7.1%
compute/image_filter.hlsl:CSMain(cs)706734+4.0%693-1.8%
compute/light_cull.hlsl:CSMain(cs)808923+14.2%697-13.7%
compute/particles.hlsl:CSMain(cs)808910+12.6%753-6.8%
compute/prefix_sum.hlsl:CSMain(cs)451475+5.3%398-11.8%
compute/stage_layouts.hlsl:CSMain(cs)858910+6.1%789-8.0%
lang/inheritance.hlsl:CSMain(cs)406486+19.7%379-6.7%
lang/members.hlsl:CSMain(cs)487609+25.1%525+7.8%
lang/operators.hlsl:CSMain(cs)207234+13.0%203-1.9%
lang/resource_arrays.hlsl:CSMain(cs)806855+6.1%775-3.8%
lang/resource_locals.hlsl:CSMain(cs)551609+10.5%540-2.0%
lang/sizeof_static.hlsl:CSMain(cs)233443+90.1%399+71.2%
lang/statics_and_literals.hlsl:CSMain(cs)556677+21.8%561+0.9%
lang/templates.hlsl:CSMain(cs)631709+12.4%649+2.9%
All 68 entry points4412646620+5.7%40258-8.8%

Method

  • Entry points. Every (file, entry point, stage) that the execution-parity cases in corpus/cases/*.case compile, without duplicates: 68 entry points in 41 files (a file's entry points are compiled together in the in-process benchmark and one per process in the process benchmark). Includes and the cases' preprocessor definitions are passed to both compilers.
  • DXC. The released Linux x64 binary v1.9.2609 (libdxcompiler 1.9.2609.5), pinned with its checksum in tools/oracles.env, run as dxc -spirv -fspv-target-env=vulkan1.2 -HV 2021 -T <vs|ps|cs>_6_0 -E <entry> -I <dir> -Fo <out> <file>; no optimization flags (so its default). It is used only as a black-box binary.
  • OneShader. bench/OneShader.Bench.Cli (oshc): ShaderCompiler.CompileFile with one entry point, SPIR-V, default options (optimizer on, debug names kept), writes the blob. Published three ways: dotnet publish -r linux-x64 -p:PublishAot=true; --self-contained false -p:PublishReadyToRun=true; and --self-contained false (JIT, with the runtime's default tiered compilation). The framework-dependent builds run through their oshc launcher on the machine's .NET runtime.
  • Process timing. The driver creates the process, waits for it to exit and takes the elapsed time on a monotonic clock; standard output and error are captured and discarded. Warm rounds run the tools interleaved (DXC, then each OneShader build) for each entry point, so a drift in machine speed affects all of them alike. Each round visits all 68 entry points; there are 15 rounds.
  • In-process timing. BenchmarkDotNet as described above. The in-process toolchain is used because the repository's build output layout does not suit BenchmarkDotNet's generated projects; the compiler runs in the benchmark's own process.
  • Size. Bytes written by each compiler on the cold pass, divided by 4.
  • Reproduce. bench/run.sh (optionally --warm N, --skip-inproc, --skip-process, --out DIR) builds, publishes the three builds, fetches the pinned DXC with tools/fetch-oracles.sh, runs both benchmarks, writes bench/results/ and regenerates the tables on this page and the charts in docs/img/. It needs the .NET SDK from global.json, Python 3, and a C toolchain with zlib for NativeAOT. bench/OneShader.Bench list prints the 68 entry points.

Machine and load

  • Hardware and software. AMD Ryzen 9 7950X3D (16 cores, 32 logical), 125 GiB RAM, Linux Mint 22.3, .NET SDK 10.0.402 with runtime 10.0.13, DXC v1.9.2609, BenchmarkDotNet 0.15.8. Default runtime settings (no AVX-512 switches, tiered compilation on, workstation non-concurrent GC in the benchmark process).
  • A shared machine, run under a lock. The run was the only benchmark on the machine: it held the machine's benchmark lock for the whole run and no other project's heavy job overlapped. Load averages (1 minute) were sampled every 5 seconds by the benchmark itself: at the start 1.24 (1-minute), 1.44 (5-minute), 1.49 (15-minute); during the process timing 1.03 to 1.24 over 41 samples; during the in-process benchmark 1.02 to 1.42 over 95 samples; at the end of the process timing 1.13, 1.26 and 1.41, and 1.09, 1.14 and 1.28 when the whole run finished. The remaining load of about 1 is background work on the machine that the benchmark did not control.
  • One run. The published numbers are from a single full run (2026-10-25). The spread between repeated warm runs is shown in the process table: a NativeAOT process lasts about 3 ms, so its slowest run is typically 1.5× its entry point's median (at most 2.1×), while DXC's slowest run is typically 1.15× its median (at most 1.5×). The ratios use medians. In-process results are kept as BenchmarkDotNet's *-report-full.json in bench/results/inproc/, with the file list per target (params-*.tsv) the report uses to restore the file names BenchmarkDotNet shortens.
  • Not measured. Memory use of either compiler (the NativeAOT binary is 2.9 MB; DXC is a 0.76 MB launcher plus a 31.8 MB compiler library); Windows or macOS; ARM64; multi-threaded or batch compiles (DXC and OneShader are each run one entry point at a time); compile time against other shader compilers.