Loewolf commited on
Commit
f506002
·
verified ·
1 Parent(s): ec4ebe8

Fix SM8650 VAE decoder with validated FP16 context

Browse files

Replace the collapsed W8A16 QNN VAE decoder with the directly compiled FP16 context. Device validation against the raw ONNX decoder reached 59.77 dB PSNR.

README.md CHANGED
@@ -39,7 +39,7 @@ splitting the network into smaller graphs suitable for mobile integration.
39
  | Batch size | 1 |
40
  | Activations | FP16 (A16) |
41
  | DiT block weights | INT4 (W4A16) |
42
- | Auxiliary/final graph weights | INT8 (W8A16) |
43
  | Total DLC size | 1,736,469,708 bytes / 1.617 GiB |
44
 
45
  ## Files
@@ -56,11 +56,33 @@ The graphs must be executed in the order shown below.
56
  | 6 | `vosr_dit_blocks_18_24.dlc` | W4A16 | 222.62 MiB |
57
  | 7 | `vosr_dit_blocks_24_36.dlc` | W4A16 | 444.86 MiB |
58
  | 8 | `vosr_dit_final.dlc` | W8A16 | 4.90 MiB |
59
- | 9 | `vosr_qwen_vae_decoder.dlc` | W8A16 | 24.97 MiB |
60
 
61
  `manifest.json` contains the same graph order, precision assignment, and exact
62
  byte size for programmatic use.
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  ## Tensor interface
65
 
66
  All image and latent tensors use NCHW layout.
@@ -89,8 +111,9 @@ noise generation, the one-step latent update, tiling, and image postprocessing.
89
  `lq_latent` and `z` along the channel axis, and use the result as `latent_pair`.
90
  4. For the one-step schedule, run DiT prepare with `timestep = [1.0]` and
91
  `next_timestep = [0.0]`.
92
- 5. Pass `hidden` sequentially through all four DiT block-stage DLCs. Reuse
93
- `block_conditioning` and `projected_dino` for every stage.
 
94
  6. Run DiT final and apply the one-step update `z = z - velocity`.
95
  7. Decode the updated latent with the Qwen VAE decoder, clamp the output to
96
  `[-1, 1]`, convert it back to RGB, and blend overlapping tiles when tiling.
@@ -101,13 +124,23 @@ resolution.
101
 
102
  ## Validation status
103
 
104
- - All nine graphs were quantized with representative intermediate activations.
105
- - All nine graphs were successfully compiled to QNN DLC format for SM8650.
 
106
  - The Qwen VAE encoder and DiT prepare graphs were profiled on the Snapdragon 8
107
  Gen 3 NPU.
108
- - A single pre-linked QNN context is intentionally not included. Linking the entire
109
- hybrid package exceeded the cloud linker memory limit, so applications should
110
- execute the DLC sequence or link it with a compatible local QNN SDK.
 
 
 
 
 
 
 
 
 
111
 
112
  Performance, memory use, and image quality depend on the QNN SDK version, device
113
  firmware, thermal state, tiling implementation, and host-side orchestration. Test on
 
39
  | Batch size | 1 |
40
  | Activations | FP16 (A16) |
41
  | DiT block weights | INT4 (W4A16) |
42
+ | Auxiliary/final graph weights | INT8 (W8A16), except the FP16 VAE decoder |
43
  | Total DLC size | 1,736,469,708 bytes / 1.617 GiB |
44
 
45
  ## Files
 
56
  | 6 | `vosr_dit_blocks_18_24.dlc` | W4A16 | 222.62 MiB |
57
  | 7 | `vosr_dit_blocks_24_36.dlc` | W4A16 | 444.86 MiB |
58
  | 8 | `vosr_dit_final.dlc` | W8A16 | 4.90 MiB |
59
+ | 9 | `vosr_qwen_vae_decoder.dlc` | Legacy W8A16 DLC; EPContext uses FP16 | 24.97 MiB |
60
 
61
  `manifest.json` contains the same graph order, precision assignment, and exact
62
  byte size for programmatic use.
63
 
64
+ ### Ready-to-run SM8650 EPContext package
65
+
66
+ `sd8g3/qnn-context/` contains eleven pre-linked QNN context binaries for the
67
+ Snapdragon 8 Gen 3 HTP. They were linked with QAIRT `2.45.0.260326154327`,
68
+ target DSP v75 / SoC model 57, and use O1 graph finalization to stay inside the
69
+ device's 8 MiB VTCM budget.
70
+
71
+ The DiT is split into six contiguous stages: `00_06`, `06_12`, `12_18`,
72
+ `18_24`, `24_30`, and `30_36`. RMSNorm pointwise multiplications are divided
73
+ along the token axis before linking; a CPU reference comparison against the
74
+ unmodified QDQ block measured 72.9 dB PSNR.
75
+
76
+ The complete context package is 1,140,031,488 bytes (1.062 GiB). The small
77
+ EPContext ONNX wrappers and their exact SHA-256, byte-size, tensor, graph-order,
78
+ and immutable Hub-revision contracts are stored in
79
+ `sd8g3/vosr_runtime_manifest.json`.
80
+
81
+ The Qwen VAE decoder is compiled directly from the original FP16 ONNX graph.
82
+ The earlier W8A16 QDQ decoder removed nearly all spatial detail. The FP16
83
+ SM8650 context matches the CPU ONNX decoder at 59.77 dB PSNR with a maximum
84
+ per-channel error of one RGB level.
85
+
86
  ## Tensor interface
87
 
88
  All image and latent tensors use NCHW layout.
 
111
  `lq_latent` and `z` along the channel axis, and use the result as `latent_pair`.
112
  4. For the one-step schedule, run DiT prepare with `timestep = [1.0]` and
113
  `next_timestep = [0.0]`.
114
+ 5. Pass `hidden` sequentially through all four DiT block-stage DLCs, or through
115
+ all six `sd8g3/qnn-context` DiT stages when using the EPContext package.
116
+ Reuse `block_conditioning` and `projected_dino` for every stage.
117
  6. Run DiT final and apply the one-step update `z = z - velocity`.
118
  7. Decode the updated latent with the Qwen VAE decoder, clamp the output to
119
  `[-1, 1]`, convert it back to RGB, and blend overlapping tiles when tiling.
 
124
 
125
  ## Validation status
126
 
127
+ - The DINO, VAE encoder, DiT prepare/final, and DiT blocks use their documented
128
+ mobile quantization. The VAE decoder deliberately remains FP16.
129
+ - All runtime graphs were successfully compiled and linked for SM8650.
130
  - The Qwen VAE encoder and DiT prepare graphs were profiled on the Snapdragon 8
131
  Gen 3 NPU.
132
+ - All eleven split EPContext graphs were linked and inspected as DSP v75 / SoC
133
+ model 57 contexts. The runtime disables CPU execution-provider fallback.
134
+ - The complete on-device chain preserves generated detail: on the S24 Ultra
135
+ regression patch, edge energy rose from 1.54 for the bicubic input to 15.19
136
+ after VOSR.
137
+ - The `00_06` six-block context was profiled successfully on the Galaxy S24
138
+ target: 382.9 ms estimated warm inference, 230.9 ms warm load, and 119.5 MB
139
+ estimated peak memory. Every reported operator, including the VTCM chunks,
140
+ executed on the NPU.
141
+ - A monolithic context is intentionally not included. Splitting the DiT into six
142
+ VTCM-safe contexts avoids the cloud linker's memory explosion and allows the
143
+ application to release each session before opening the next one.
144
 
145
  Performance, memory use, and image quality depend on the QNN SDK version, device
146
  firmware, thermal state, tiling implementation, and host-side orchestration. Test on
sd8g3/qnn-context/vosr_qwen_vae_decoder.bin CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:a31aaf7356f4bdab6e31f7cbdd162cee038a16b5f6124ea3aae4d674eaa474c3
3
- size 38879232
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a3e0b355634a2f41fc6f830141671c5da158f36c7e68070790431419fa71b002
3
+ size 53456896
sd8g3/qnn-context/vosr_qwen_vae_decoder.json CHANGED
@@ -20,7 +20,7 @@
20
  "backendApiVersion": "5.45.0",
21
  "socVersion": "",
22
  "contextBlobVersion": "3.3.4",
23
- "contextBlobSize": 38875136,
24
  "numContextTensors": 0,
25
  "contextTensors": [],
26
  "numGraphs": 1,
@@ -59,7 +59,7 @@
59
  {
60
  "version": "QNN_TENSOR_VERSION_2",
61
  "info": {
62
- "id": 517,
63
  "name": "output_0",
64
  "type": "QNN_TENSOR_TYPE_APP_READ",
65
  "dataFormat": "QNN_TENSOR_DATA_FORMAT_FLAT_BUFFER",
@@ -85,8 +85,8 @@
85
  "graphBlobInfo": {
86
  "version": "QNN_SYSTEM_CONTEXT_HTP_GRAPH_INFO_BLOB_VERSION_V1",
87
  "info": {
88
- "spillFillBufferSize": 272433152,
89
- "optimizationLevel": 3,
90
  "vtcmSize": 8,
91
  "htpDlbc": 0,
92
  "numHvxThreads": 0
@@ -98,13 +98,13 @@
98
  "nativeVChannelSize": 64,
99
  "isSafeShareIO": 0,
100
  "ioTensorSize": 1703936,
101
- "opDataSize": 23295232,
102
- "constSize": 25858048,
103
- "ddrTensorSize": 18874880,
104
  "sharedWeightsSize": 0
105
  },
106
- "startOpIndex": 6881350,
107
- "endOpIndex": 6619244
108
  }
109
  }
110
  ],
 
20
  "backendApiVersion": "5.45.0",
21
  "socVersion": "",
22
  "contextBlobVersion": "3.3.4",
23
+ "contextBlobSize": 53452800,
24
  "numContextTensors": 0,
25
  "contextTensors": [],
26
  "numGraphs": 1,
 
59
  {
60
  "version": "QNN_TENSOR_VERSION_2",
61
  "info": {
62
+ "id": 452,
63
  "name": "output_0",
64
  "type": "QNN_TENSOR_TYPE_APP_READ",
65
  "dataFormat": "QNN_TENSOR_DATA_FORMAT_FLAT_BUFFER",
 
85
  "graphBlobInfo": {
86
  "version": "QNN_SYSTEM_CONTEXT_HTP_GRAPH_INFO_BLOB_VERSION_V1",
87
  "info": {
88
+ "spillFillBufferSize": 133758976,
89
+ "optimizationLevel": 1,
90
  "vtcmSize": 8,
91
  "htpDlbc": 0,
92
  "numHvxThreads": 0
 
98
  "nativeVChannelSize": 64,
99
  "isSafeShareIO": 0,
100
  "ioTensorSize": 1703936,
101
+ "opDataSize": 9052416,
102
+ "constSize": 51228672,
103
+ "ddrTensorSize": 23593472,
104
  "sharedWeightsSize": 0
105
  },
106
+ "startOpIndex": 0,
107
+ "endOpIndex": 0
108
  }
109
  }
110
  ],