1 | // Copyright 2009-2021 Intel Corporation |
2 | // SPDX-License-Identifier: Apache-2.0 |
3 | |
4 | #pragma once |
5 | |
6 | namespace embree |
7 | { |
8 | /* adjust discret tessellation level for feature-adaptive pre-subdivision */ |
9 | __forceinline float adjustTessellationLevel(float l, const size_t sublevel) |
10 | { |
11 | for (size_t i=0; i<sublevel; i++) l *= 0.5f; |
12 | float r = ceilf(l); |
13 | for (size_t i=0; i<sublevel; i++) r *= 2.0f; |
14 | return r; |
15 | } |
16 | |
17 | __forceinline int stitch(const int x, const int fine, const int coarse) { |
18 | return (2*x+1)*coarse/(2*fine); |
19 | } |
20 | |
21 | __forceinline void stitchGridEdges(const unsigned int low_rate, |
22 | const unsigned int high_rate, |
23 | const unsigned int x0, |
24 | const unsigned int x1, |
25 | float * __restrict__ const uv_array, |
26 | const unsigned int uv_array_step) |
27 | { |
28 | #if 1 |
29 | const float inv_low_rate = rcp((float)(low_rate-1)); |
30 | for (unsigned x=x0; x<=x1; x++) { |
31 | uv_array[(x-x0)*uv_array_step] = float(stitch(x,high_rate-1,low_rate-1))*inv_low_rate; |
32 | } |
33 | if (unlikely(x1 == high_rate-1)) |
34 | uv_array[(x1-x0)*uv_array_step] = 1.0f; |
35 | #else |
36 | assert(low_rate < high_rate); |
37 | assert(high_rate >= 2); |
38 | |
39 | const float inv_low_rate = rcp((float)(low_rate-1)); |
40 | const unsigned int dy = low_rate - 1; |
41 | const unsigned int dx = high_rate - 1; |
42 | |
43 | int p = 2*dy-dx; |
44 | |
45 | unsigned int offset = 0; |
46 | unsigned int y = 0; |
47 | float value = 0.0f; |
48 | for(unsigned int x=0;x<high_rate-1; x++) // '<=' would be correct but we will leave the 1.0f at the end |
49 | { |
50 | uv_array[offset] = value; |
51 | |
52 | offset += uv_array_step; |
53 | if (unlikely(p > 0)) |
54 | { |
55 | y++; |
56 | value = (float)y * inv_low_rate; |
57 | p -= 2*dx; |
58 | } |
59 | p += 2*dy; |
60 | } |
61 | #endif |
62 | } |
63 | |
64 | __forceinline void stitchUVGrid(const float edge_levels[4], |
65 | const unsigned int swidth, |
66 | const unsigned int sheight, |
67 | const unsigned int x0, |
68 | const unsigned int y0, |
69 | const unsigned int grid_u_res, |
70 | const unsigned int grid_v_res, |
71 | float * __restrict__ const u_array, |
72 | float * __restrict__ const v_array) |
73 | { |
74 | const unsigned int x1 = x0+grid_u_res-1; |
75 | const unsigned int y1 = y0+grid_v_res-1; |
76 | const unsigned int int_edge_points0 = (unsigned int)edge_levels[0] + 1; |
77 | const unsigned int int_edge_points1 = (unsigned int)edge_levels[1] + 1; |
78 | const unsigned int int_edge_points2 = (unsigned int)edge_levels[2] + 1; |
79 | const unsigned int int_edge_points3 = (unsigned int)edge_levels[3] + 1; |
80 | |
81 | if (unlikely(y0 == 0 && int_edge_points0 < swidth)) |
82 | stitchGridEdges(int_edge_points0,swidth,x0,x1,u_array,1); |
83 | |
84 | if (unlikely(y1 == sheight-1 && int_edge_points2 < swidth)) |
85 | stitchGridEdges(int_edge_points2,swidth,x0,x1,&u_array[(grid_v_res-1)*grid_u_res],1); |
86 | |
87 | if (unlikely(x0 == 0 && int_edge_points1 < sheight)) |
88 | stitchGridEdges(int_edge_points1,sheight,y0,y1,&v_array[grid_u_res-1],grid_u_res); |
89 | |
90 | if (unlikely(x1 == swidth-1 && int_edge_points3 < sheight)) |
91 | stitchGridEdges(int_edge_points3,sheight,y0,y1,v_array,grid_u_res); |
92 | } |
93 | |
94 | __forceinline void gridUVTessellator(const float edge_levels[4], |
95 | const unsigned int swidth, |
96 | const unsigned int sheight, |
97 | const unsigned int x0, |
98 | const unsigned int y0, |
99 | const unsigned int grid_u_res, |
100 | const unsigned int grid_v_res, |
101 | float * __restrict__ const u_array, |
102 | float * __restrict__ const v_array) |
103 | { |
104 | assert( grid_u_res >= 1); |
105 | assert( grid_v_res >= 1); |
106 | assert( edge_levels[0] >= 1.0f ); |
107 | assert( edge_levels[1] >= 1.0f ); |
108 | assert( edge_levels[2] >= 1.0f ); |
109 | assert( edge_levels[3] >= 1.0f ); |
110 | |
111 | #if defined(__AVX__) |
112 | const vint8 grid_u_segments = vint8(swidth)-1; |
113 | const vint8 grid_v_segments = vint8(sheight)-1; |
114 | |
115 | const vfloat8 inv_grid_u_segments = rcp(vfloat8(grid_u_segments)); |
116 | const vfloat8 inv_grid_v_segments = rcp(vfloat8(grid_v_segments)); |
117 | |
118 | unsigned int index = 0; |
119 | vint8 v_i( zero ); |
120 | for (unsigned int y=0;y<grid_v_res;y++,index+=grid_u_res,v_i += 1) |
121 | { |
122 | vint8 u_i ( step ); |
123 | |
124 | const vbool8 m_v = v_i < grid_v_segments; |
125 | |
126 | for (unsigned int x=0;x<grid_u_res;x+=8, u_i += 8) |
127 | { |
128 | const vbool8 m_u = u_i < grid_u_segments; |
129 | const vfloat8 u = select(m_u, vfloat8(x0+u_i) * inv_grid_u_segments, 1.0f); |
130 | const vfloat8 v = select(m_v, vfloat8(y0+v_i) * inv_grid_v_segments, 1.0f); |
131 | vfloat8::storeu(&u_array[index + x],u); |
132 | vfloat8::storeu(&v_array[index + x],v); |
133 | } |
134 | } |
135 | #else |
136 | const vint4 grid_u_segments = vint4(swidth)-1; |
137 | const vint4 grid_v_segments = vint4(sheight)-1; |
138 | |
139 | const vfloat4 inv_grid_u_segments = rcp(vfloat4(grid_u_segments)); |
140 | const vfloat4 inv_grid_v_segments = rcp(vfloat4(grid_v_segments)); |
141 | |
142 | unsigned int index = 0; |
143 | vint4 v_i( zero ); |
144 | for (unsigned int y=0;y<grid_v_res;y++,index+=grid_u_res,v_i += 1) |
145 | { |
146 | vint4 u_i ( step ); |
147 | |
148 | const vbool4 m_v = v_i < grid_v_segments; |
149 | |
150 | for (unsigned int x=0;x<grid_u_res;x+=4, u_i += 4) |
151 | { |
152 | const vbool4 m_u = u_i < grid_u_segments; |
153 | const vfloat4 u = select(m_u, vfloat4(x0+u_i) * inv_grid_u_segments, 1.0f); |
154 | const vfloat4 v = select(m_v, vfloat4(y0+v_i) * inv_grid_v_segments, 1.0f); |
155 | vfloat4::storeu(&u_array[index + x],u); |
156 | vfloat4::storeu(&v_array[index + x],v); |
157 | } |
158 | } |
159 | #endif |
160 | } |
161 | } |
162 | |