Fix #35684: cycles unable to use full 6GB of memory on NVidia Titan GPU. We now
[blender.git] / intern / cycles / kernel / kernel_primitive.h
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16
17 #ifndef __KERNEL_ATTRIBUTE_CL__
18 #define __KERNEL_ATTRIBUTE_CL__
19
20 CCL_NAMESPACE_BEGIN
21
22 /* attribute lookup */
23
24 __device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id, AttributeElement *elem)
25 {
26         if(sd->object == ~0)
27                 return (int)ATTR_STD_NOT_FOUND;
28
29 #ifdef __OSL__
30         if (kg->osl) {
31                 return OSLShader::find_attribute(kg, sd, id, elem);
32         }
33         else
34 #endif
35         {
36                 /* for SVM, find attribute by unique id */
37                 uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
38 #ifdef __HAIR__
39                 attr_offset = (sd->segment == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
40 #endif
41                 uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
42                 
43                 while(attr_map.x != id) {
44                         attr_offset += ATTR_PRIM_TYPES;
45                         attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
46                 }
47
48                 *elem = (AttributeElement)attr_map.y;
49                 
50                 /* return result */
51                 return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
52         }
53 }
54
55 __device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
56 {
57 #ifdef __HAIR__
58         if(sd->segment == ~0)
59 #endif
60                 return triangle_attribute_float(kg, sd, elem, offset, dx, dy);
61 #ifdef __HAIR__
62         else
63                 return curve_attribute_float(kg, sd, elem, offset, dx, dy);
64 #endif
65 }
66
67 __device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
68 {
69 #ifdef __HAIR__
70         if(sd->segment == ~0)
71 #endif
72                 return triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
73 #ifdef __HAIR__
74         else
75                 return curve_attribute_float3(kg, sd, elem, offset, dx, dy);
76 #endif
77 }
78
79 __device float3 primitive_uv(KernelGlobals *kg, ShaderData *sd)
80 {
81         AttributeElement elem_uv;
82         int offset_uv = find_attribute(kg, sd, ATTR_STD_UV, &elem_uv);
83
84         if(offset_uv == ATTR_STD_NOT_FOUND)
85                 return make_float3(0.0f, 0.0f, 0.0f);
86
87         float3 uv = primitive_attribute_float3(kg, sd, elem_uv, offset_uv, NULL, NULL);
88         uv.z = 1.0f;
89         return uv;
90 }
91
92 __device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
93 {
94 #ifdef __HAIR__
95         if(sd->segment != ~0)
96 #ifdef __DPDU__
97                 return normalize(sd->dPdu);
98 #else
99                 return make_float3(0.0f, 0.0f, 0.0f);
100 #endif
101 #endif
102
103         /* try to create spherical tangent from generated coordinates */
104         AttributeElement attr_elem;
105         int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED, &attr_elem);
106
107         if(attr_offset != ATTR_STD_NOT_FOUND) {
108                 float3 data = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
109                 data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f);
110                 object_normal_transform(kg, sd, &data);
111                 return cross(sd->N, normalize(cross(data, sd->N)));
112         }
113         else {
114                 /* otherwise use surface derivatives */
115 #ifdef __DPDU__
116                 return normalize(sd->dPdu);
117 #else
118                 return make_float3(0.0f, 0.0f, 0.0f);
119 #endif
120         }
121 }
122
123 /* motion */
124
125 __device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd)
126 {
127         float3 motion_pre = sd->P, motion_post = sd->P;
128
129         /* deformation motion */
130         AttributeElement elem_pre, elem_post;
131         int offset_pre = find_attribute(kg, sd, ATTR_STD_MOTION_PRE, &elem_pre);
132         int offset_post = find_attribute(kg, sd, ATTR_STD_MOTION_POST, &elem_post);
133
134         if(offset_pre != ATTR_STD_NOT_FOUND)
135                 motion_pre = primitive_attribute_float3(kg, sd, elem_pre, offset_pre, NULL, NULL);
136         if(offset_post != ATTR_STD_NOT_FOUND)
137                 motion_post = primitive_attribute_float3(kg, sd, elem_post, offset_post, NULL, NULL);
138
139         /* object motion. note that depending on the mesh having motion vectors, this
140          * transformation was set match the world/object space of motion_pre/post */
141         Transform tfm;
142         
143         tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_PRE);
144         motion_pre = transform_point(&tfm, motion_pre);
145
146         tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_POST);
147         motion_post = transform_point(&tfm, motion_post);
148
149         float3 P;
150
151         /* camera motion, for perspective/orthographic motion.pre/post will be a
152          * world-to-raster matrix, for panorama it's world-to-camera */
153         if (kernel_data.cam.type != CAMERA_PANORAMA) {
154                 tfm = kernel_data.cam.worldtoraster;
155                 P = transform_perspective(&tfm, sd->P);
156
157                 tfm = kernel_data.cam.motion.pre;
158                 motion_pre = transform_perspective(&tfm, motion_pre);
159
160                 tfm = kernel_data.cam.motion.post;
161                 motion_post = transform_perspective(&tfm, motion_post);
162         }
163         else {
164                 tfm = kernel_data.cam.worldtocamera;
165                 P = normalize(transform_point(&tfm, sd->P));
166                 P = float2_to_float3(direction_to_panorama(kg, P));
167                 P.x *= kernel_data.cam.width;
168                 P.y *= kernel_data.cam.height;
169
170                 tfm = kernel_data.cam.motion.pre;
171                 motion_pre = normalize(transform_point(&tfm, motion_pre));
172                 motion_pre = float2_to_float3(direction_to_panorama(kg, motion_pre));
173                 motion_pre.x *= kernel_data.cam.width;
174                 motion_pre.y *= kernel_data.cam.height;
175
176                 tfm = kernel_data.cam.motion.post;
177                 motion_post = normalize(transform_point(&tfm, motion_post));
178                 motion_post = float2_to_float3(direction_to_panorama(kg, motion_post));
179                 motion_post.x *= kernel_data.cam.width;
180                 motion_post.y *= kernel_data.cam.height;
181         }
182
183         motion_pre = motion_pre - P;
184         motion_post = P - motion_post;
185
186         return make_float4(motion_pre.x, motion_pre.y, motion_post.x, motion_post.y);
187 }
188
189 CCL_NAMESPACE_END
190
191 #endif /* __KERNEL_ATTRIBUTE_CL__ */