@@ -103,38 +103,49 @@ namespace embree
103103 const NativeCurve3fa curve3Di (v0,v1,v2,v3);
104104 const NativeCurve3fa curve3D = enlargeRadiusToMinWidth (context,geom,ray.org ,curve3Di);
105105 const NativeCurve3fa curve2D = curve3D.xfm_pr (pre .ray_space ,ray.org );
106-
107- /* evaluate the bezier curve */
108- vboolx valid = vfloatx (step) < vfloatx (float (N));
109- const Vec4vfx p0 = curve2D.template eval0 <W>(0 ,N);
110- const Vec4vfx p1 = curve2D.template eval1 <W>(0 ,N);
111-
112- /* approximative intersection with cone */
113- const Vec4vfx v = p1-p0;
114- const Vec4vfx w = -p0;
115- const vfloatx d0 = madd (w.x ,v.x ,w.y *v.y );
116- const vfloatx d1 = madd (v.x ,v.x ,v.y *v.y );
117- const vfloatx u = clamp (d0*rcp (d1),vfloatx (zero),vfloatx (one));
118- const Vec4vfx p = madd (u,v,p0);
119- const vfloatx t = p.z *pre .depth_scale ;
120- const vfloatx d2 = madd (p.x ,p.x ,p.y *p.y );
121- const vfloatx r = p.w ;
122- const vfloatx r2 = r*r;
123- valid &= (d2 <= r2) & (vfloatx (ray.tnear ()) <= t) & (t <= vfloatx (ray.tfar ));
124- if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0 .0f )
125- valid &= t > float (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR )*r*pre .depth_scale ; // ignore self intersections
126106
127- /* update hit information */
128107 bool ishit = false ;
129- if (unlikely (any (valid))) {
130- DistanceCurveHit<NativeCurve3fa,W> hit (valid,u,0 .0f ,t,0 ,N,curve3D);
131- ishit = ishit | epilog (valid,hit);
108+ int i = 0 ;
109+
110+ #if !defined(__SYCL_DEVICE_ONLY__)
111+ /* unrolled first iteration: on CPU SIMD this lets the compiler keep
112+ the first chunk of segments in registers and skip the loop overhead.
113+ On SYCL (W=1) it duplicates code without benefit and just bloats the
114+ kernel, so the SYCL path falls straight into the unified loop. */
115+ {
116+ /* evaluate the bezier curve */
117+ vboolx valid = vfloatx (step) < vfloatx (float (N));
118+ const Vec4vfx p0 = curve2D.template eval0 <W>(0 ,N);
119+ const Vec4vfx p1 = curve2D.template eval1 <W>(0 ,N);
120+
121+ /* approximative intersection with cone */
122+ const Vec4vfx v = p1-p0;
123+ const Vec4vfx w = -p0;
124+ const vfloatx d0 = madd (w.x ,v.x ,w.y *v.y );
125+ const vfloatx d1 = madd (v.x ,v.x ,v.y *v.y );
126+ const vfloatx u = clamp (d0*rcp (d1),vfloatx (zero),vfloatx (one));
127+ const Vec4vfx p = madd (u,v,p0);
128+ const vfloatx t = p.z *pre .depth_scale ;
129+ const vfloatx d2 = madd (p.x ,p.x ,p.y *p.y );
130+ const vfloatx r = p.w ;
131+ const vfloatx r2 = r*r;
132+ valid &= (d2 <= r2) & (vfloatx (ray.tnear ()) <= t) & (t <= vfloatx (ray.tfar ));
133+ if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0 .0f )
134+ valid &= t > float (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR )*r*pre .depth_scale ; // ignore self intersections
135+
136+ /* update hit information */
137+ if (unlikely (any (valid))) {
138+ DistanceCurveHit<NativeCurve3fa,W> hit (valid,u,0 .0f ,t,0 ,N,curve3D);
139+ ishit = ishit | epilog (valid,hit);
140+ }
141+ i = W;
132142 }
143+ #endif
133144
134- if (unlikely (W < N))
145+ if (unlikely (i < N))
135146 {
136147 /* process SIMD-size many segments per iteration */
137- for (int i=W ; i<N; i+=W)
148+ for (; i<N; i+=W)
138149 {
139150 /* evaluate the bezier curve */
140151 vboolx valid = vintx (i)+vintx (step) < vintx (N);
0 commit comments