@@ -142,17 +142,37 @@ impl OutputColorInfo {
142142 }
143143}
144144
145+ /// Precomputed per-frame constants for `xyb_process`.
146+ struct XybParams {
147+ mat : [ f32 ; 9 ] ,
148+ bias_cbrt : [ f32 ; 3 ] ,
149+ scaled_bias : [ f32 ; 3 ] ,
150+ intensity_scale : f32 ,
151+ }
152+
153+ impl XybParams {
154+ fn new ( opsin : & OpsinInverseMatrix , intensity_target : f32 ) -> Self {
155+ let intensity_scale = 255.0 / intensity_target;
156+ Self {
157+ mat : opsin. inverse_matrix ,
158+ bias_cbrt : opsin. opsin_biases . map ( |x| x. cbrt ( ) ) ,
159+ scaled_bias : opsin. opsin_biases . map ( |x| x * intensity_scale) ,
160+ intensity_scale,
161+ }
162+ }
163+ }
164+
145165/// Convert XYB to linear RGB with appropriate primaries, where 1.0 corresponds to `intensity_target` nits.
146166pub struct XybStage {
147167 first_channel : usize ,
148- output_color_info : OutputColorInfo ,
168+ params : XybParams ,
149169}
150170
151171impl XybStage {
152172 pub fn new ( first_channel : usize , output_color_info : OutputColorInfo ) -> Self {
153173 Self {
154174 first_channel,
155- output_color_info,
175+ params : XybParams :: new ( & output_color_info. opsin , output_color_info . intensity_target ) ,
156176 }
157177 }
158178}
@@ -174,24 +194,16 @@ simd_function!(
174194 xyb_process_dispatch,
175195 d: D ,
176196 fn xyb_process(
177- opsin: & OpsinInverseMatrix ,
178- intensity_target: f32 ,
197+ params: & XybParams ,
179198 xsize: usize ,
180199 row_x: & mut [ f32 ] ,
181200 row_y: & mut [ f32 ] ,
182201 row_b: & mut [ f32 ] ,
183202 ) {
184- let OpsinInverseMatrix {
185- inverse_matrix: mat,
186- opsin_biases: bias,
187- ..
188- } = opsin;
189- // TODO(veluca): consider computing the cbrt in advance.
190- let bias_cbrt = bias. map( |x| D :: F32Vec :: splat( d, x. cbrt( ) ) ) ;
191- let intensity_scale = 255.0 / intensity_target;
192- let scaled_bias = bias. map( |x| D :: F32Vec :: splat( d, x * intensity_scale) ) ;
193- let mat = mat. map( |x| D :: F32Vec :: splat( d, x) ) ;
194- let intensity_scale = D :: F32Vec :: splat( d, intensity_scale) ;
203+ let mat = params. mat. map( |x| D :: F32Vec :: splat( d, x) ) ;
204+ let bias_cbrt = params. bias_cbrt. map( |x| D :: F32Vec :: splat( d, x) ) ;
205+ let scaled_bias = params. scaled_bias. map( |x| D :: F32Vec :: splat( d, x) ) ;
206+ let intensity_scale = D :: F32Vec :: splat( d, params. intensity_scale) ;
195207
196208 for idx in ( 0 ..xsize) . step_by( D :: F32Vec :: LEN ) {
197209 let x = D :: F32Vec :: load( d, & row_x[ idx..] ) ;
@@ -246,14 +258,7 @@ impl RenderPipelineInPlaceStage for XybStage {
246258 ) ;
247259 } ;
248260
249- xyb_process_dispatch (
250- & self . output_color_info . opsin ,
251- self . output_color_info . intensity_target ,
252- xsize,
253- row_x,
254- row_y,
255- row_b,
256- ) ;
261+ xyb_process_dispatch ( & self . params , xsize, row_x, row_y, row_b) ;
257262 }
258263}
259264
@@ -324,20 +329,12 @@ mod test {
324329 let mut scalar_y = row_y. clone ( ) ;
325330 let mut scalar_b = row_b. clone ( ) ;
326331
327- xyb_process (
328- d,
329- & opsin,
330- intensity_target,
331- xsize,
332- & mut row_x,
333- & mut row_y,
334- & mut row_b,
335- ) ;
332+ let params = XybParams :: new ( & opsin, intensity_target) ;
336333
334+ xyb_process ( d, & params, xsize, & mut row_x, & mut row_y, & mut row_b) ;
337335 xyb_process (
338336 ScalarDescriptor :: new ( ) . unwrap ( ) ,
339- & opsin,
340- intensity_target,
337+ & params,
341338 xsize,
342339 & mut scalar_x,
343340 & mut scalar_y,
0 commit comments