@@ -262,6 +262,29 @@ def _match_pixel_shuffle(slices, height, width):
262262 return phase , nodes
263263
264264
265+ def _match_previous_flow (concat , customs , nodes ):
266+ flow_transpose = customs [0 ].args [0 ][1 ]
267+ residuals = [n for n in flow_transpose .users if n not in customs ]
268+ if len (residuals ) != 1 or not _is_op (residuals [0 ], TOSA .RESCALE .default , 5 ):
269+ raise ValueError ("Expected one previous-flow rescale." )
270+ residual = residuals [0 ]
271+ if (
272+ residual .args [1 ] != torch .int32
273+ or len (residual .args [2 ]) != 1
274+ or residual .args [4 ] != 0
275+ or any (residual .kwargs .values ())
276+ ):
277+ raise ValueError ("Expected a signed per-tensor INT32 previous-flow rescale." )
278+ nodes .add (flow_transpose )
279+ allowed = nodes | set (customs ) | {concat , residual }
280+ if any (user not in allowed for node in nodes for user in node .users ):
281+ raise ValueError ("The block0 tail has additional consumers." )
282+ positions = {node : i for i , node in enumerate (concat .graph .nodes )}
283+ if any (positions [user ] <= positions [concat ] for user in residual .users ):
284+ raise ValueError ("Previous flow is needed before the packed shader." )
285+ return residual
286+
287+
265288def _match_block0_tail (concat , customs ):
266289 _ , height , width , _ = _tensor_shape (concat )
267290 if height % 4 or width % 4 :
@@ -291,26 +314,62 @@ def _match_block0_tail(concat, customs):
291314 slices .append (source )
292315 phase , shuffle_nodes = _match_pixel_shuffle (slices , height , width )
293316 nodes .update (shuffle_nodes )
294- flow_transpose = customs [0 ].args [0 ][1 ]
295- residuals = [n for n in flow_transpose .users if n not in customs ]
296- if len (residuals ) != 1 or not _is_op (residuals [0 ], TOSA .RESCALE .default , 5 ):
297- raise ValueError ("Expected one previous-flow rescale." )
298- residual = residuals [0 ]
299- if (
300- residual .args [1 ] != torch .int32
301- or len (residual .args [2 ]) != 1
302- or residual .args [4 ] != 0
303- or any (residual .kwargs .values ())
304- ):
305- raise ValueError ("Expected a signed per-tensor INT32 previous-flow rescale." )
306- nodes .add (flow_transpose )
307- allowed = nodes | set (customs ) | {concat , residual }
308- if any (user not in allowed for node in nodes for user in node .users ):
309- raise ValueError ("The block0 tail has additional consumers." )
310- positions = {node : i for i , node in enumerate (concat .graph .nodes )}
311- if any (positions [user ] <= positions [concat ] for user in residual .users ):
312- raise ValueError ("Previous flow is needed before the packed shader." )
313- return phase , residual
317+ return phase , _match_previous_flow (concat , customs , nodes )
318+
319+
320+ def _match_direct_head_tail (concat , customs ):
321+ _ , height , width , _ = _tensor_shape (concat )
322+ nodes = set ()
323+ head = None
324+ factor = None
325+ for rescale , offset , channels in zip (concat .args [0 ][5 :], (4 , 5 , 0 ), (1 , 8 , 4 )):
326+ if not _is_op (rescale , TOSA .RESCALE .default , 5 ):
327+ raise ValueError ("Expected a resized head rescale." )
328+ resize = rescale .args [0 ]
329+ if not _is_op (resize , TOSA .RESIZE .default , 4 ):
330+ raise ValueError ("Expected a resized head slice." )
331+ source = resize .args [0 ]
332+ if not _is_op (source , TOSA .SLICE .default , 3 ):
333+ raise ValueError ("Expected an NHWC head slice." )
334+ current_head = source .args [0 ]
335+ batch , h , w , c = _tensor_shape (current_head )
336+ if batch != 1 or c != 13 or h <= 0 or w <= 0 or height % h or width % w :
337+ raise ValueError ("Expected a 13-channel integer-scale head." )
338+ current_factor = height // h
339+ if current_factor not in (2 , 4 , 8 ) or width // w != current_factor :
340+ raise ValueError ("Expected a uniform 2x, 4x or 8x head resize." )
341+ if head is not None and (head is not current_head or factor != current_factor ):
342+ raise ValueError ("Expected one shared head for all state slices." )
343+ head , factor = current_head , current_factor
344+ denominator = 2 * factor
345+ if (
346+ current_head .meta ["val" ].dtype != torch .int8
347+ or _shape_values (source .args [1 ]) != [0 , 0 , 0 , offset ]
348+ or _shape_values (source .args [2 ]) != [1 , h , w , channels ]
349+ or resize .meta ["val" ].dtype != torch .int32
350+ or resize .kwargs != {"resize_mode" : "bilinear" }
351+ or [_shape_values (v ) for v in resize .args [1 :]]
352+ != [
353+ [denominator , 2 , denominator , 2 ],
354+ [1 - factor , 1 - factor ],
355+ [factor - 1 , factor - 1 ],
356+ ]
357+ or rescale .args [1 :] != (torch .int8 , [1.0 / denominator ** 2 ], 0 , 0 )
358+ or any (rescale .kwargs .values ())
359+ ):
360+ raise ValueError ("Expected the original signed integer head resize." )
361+ nodes .update ((source , resize , rescale ))
362+ return (head , _match_previous_flow (concat , customs , nodes )), factor
363+
364+
365+ def _match_head_tail (program , concat , customs ):
366+ try :
367+ tail = _match_block0_tail (concat , customs )
368+ parameters = _phase_major_parameters (program , tail [0 ])
369+ return tail , parameters , True , 2
370+ except ValueError :
371+ tail , factor = _match_direct_head_tail (concat , customs )
372+ return tail , None , False , factor
314373
315374
316375def _phase_major_parameters (program , phase ):
@@ -348,6 +407,8 @@ def _phase_major_parameters(program, phase):
348407
349408
350409def _reorder_pixel_shuffle_output (program , phase , parameters ):
410+ if parameters is None :
411+ return
351412 producer , weight , bias , scales = parameters
352413 graph = phase .graph
353414 constants = []
@@ -368,7 +429,7 @@ def _reorder_pixel_shuffle_output(program, phase, parameters):
368429class PackRifeWarpsAndConcatPass (ArmPass ):
369430 """Pack four private RIFE warps and their C28 concat into one C32 shader.
370431
371- Fuse a compatible block0 PixelShuffle and state preparation into the shader.
432+ Fuse compatible block0 head resizing and state preparation into the shader.
372433 Reorder block0 output channels during export so each PixelShuffle read
373434 accesses 13 contiguous channels. Keep sampling quantization boundaries.
374435 Four zero weight columns make the following convolution ignore padding.
@@ -489,18 +550,25 @@ def call(self, graph_module: GraphModule) -> PassResult:
489550 return PassResult (graph_module , False )
490551
491552 phase_parameters = None
553+ pixel_shuffle = True
554+ resize_scale = 2
492555 try :
493- tail = _match_block0_tail (concat , customs )
494- phase_parameters = _phase_major_parameters (exported_program , tail [0 ])
556+ tail , phase_parameters , pixel_shuffle , resize_scale = _match_head_tail (
557+ exported_program , concat , customs
558+ )
495559 except ValueError as error :
496- logger .debug ("Keeping the original PixelShuffle layout: %s" , error )
560+ logger .debug ("Keeping the original head layout: %s" , error )
497561 tail = None
498562 if tail is None :
499563 payload = build_packed_warp_payload (payloads , timestep )
500564 shader_inputs = [* images , * concat .args [0 ][5 :]]
501565 else :
502566 payload = build_packed_warp_payload (
503- payloads , timestep , fuse_block0_tail = True
567+ payloads ,
568+ timestep ,
569+ fuse_block0_tail = True ,
570+ pixel_shuffle = pixel_shuffle ,
571+ resize_scale = resize_scale ,
504572 )
505573 shader_inputs = [* images , tail [0 ]]
506574 _reorder_pixel_shuffle_output (exported_program , tail [0 ], phase_parameters )
0 commit comments