Cycles: Some more inline policy tweaks for CUDA 8
[blender.git] / intern / cycles / kernel / svm / svm_attribute.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 CCL_NAMESPACE_BEGIN
18
19 /* Attribute Node */
20
21 ccl_device void svm_node_attr_init(KernelGlobals *kg, ShaderData *sd,
22         uint4 node, NodeAttributeType *type,
23         NodeAttributeType *mesh_type, AttributeElement *elem, int *offset, uint *out_offset)
24 {
25         *out_offset = node.z;
26         *type = (NodeAttributeType)node.w;
27         if(ccl_fetch(sd, object) != OBJECT_NONE) {
28                 /* find attribute by unique id */
29                 uint id = node.y;
30                 uint attr_offset = ccl_fetch(sd, object)*kernel_data.bvh.attributes_map_stride;
31                 attr_offset += attribute_primitive_type(kg, sd);
32                 uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
33                 
34                 while(attr_map.x != id) {
35                         if(UNLIKELY(attr_map.x == ATTR_STD_NONE)) {
36                                 *elem = ATTR_ELEMENT_NONE;
37                                 *offset = 0;
38                                 *mesh_type = (NodeAttributeType)node.w;
39                                 return;
40                         }
41                         attr_offset += ATTR_PRIM_TYPES;
42                         attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
43                 }
44
45                 /* return result */
46                 *elem = (AttributeElement)attr_map.y;
47                 *offset = as_int(attr_map.z);
48                 *mesh_type = (NodeAttributeType)attr_map.w;
49         }
50         else {
51                 /* background */
52                 *elem = ATTR_ELEMENT_NONE;
53                 *offset = 0;
54                 *mesh_type = (NodeAttributeType)node.w;
55         }
56 }
57
58 ccl_device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
59 {
60         NodeAttributeType type, mesh_type;
61         AttributeElement elem;
62         uint out_offset;
63         int offset;
64
65         svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
66
67         /* fetch and store attribute */
68         if(type == NODE_ATTR_FLOAT) {
69                 if(mesh_type == NODE_ATTR_FLOAT) {
70                         float f = primitive_attribute_float(kg, sd, elem, offset, NULL, NULL);
71                         stack_store_float(stack, out_offset, f);
72                 }
73                 else {
74                         float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
75                         stack_store_float(stack, out_offset, average(f));
76                 }
77         }
78         else {
79                 if(mesh_type == NODE_ATTR_FLOAT3) {
80                         float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
81                         stack_store_float3(stack, out_offset, f);
82                 }
83                 else {
84                         float f = primitive_attribute_float(kg, sd, elem, offset, NULL, NULL);
85                         stack_store_float3(stack, out_offset, make_float3(f, f, f));
86                 }
87         }
88 }
89
90 #ifndef __KERNEL_CUDS__
91 ccl_device
92 #else
93 ccl_device_noinline
94 #endif
95 void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
96 {
97         NodeAttributeType type, mesh_type;
98         AttributeElement elem;
99         uint out_offset;
100         int offset;
101
102         svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
103
104         /* fetch and store attribute */
105         if(type == NODE_ATTR_FLOAT) {
106                 if(mesh_type == NODE_ATTR_FLOAT) {
107                         float dx;
108                         float f = primitive_attribute_float(kg, sd, elem, offset, &dx, NULL);
109                         stack_store_float(stack, out_offset, f+dx);
110                 }
111                 else {
112                         float3 dx;
113                         float3 f = primitive_attribute_float3(kg, sd, elem, offset, &dx, NULL);
114                         stack_store_float(stack, out_offset, average(f+dx));
115                 }
116         }
117         else {
118                 if(mesh_type == NODE_ATTR_FLOAT3) {
119                         float3 dx;
120                         float3 f = primitive_attribute_float3(kg, sd, elem, offset, &dx, NULL);
121                         stack_store_float3(stack, out_offset, f+dx);
122                 }
123                 else {
124                         float dx;
125                         float f = primitive_attribute_float(kg, sd, elem, offset, &dx, NULL);
126                         stack_store_float3(stack, out_offset, make_float3(f+dx, f+dx, f+dx));
127                 }
128         }
129 }
130
131 #ifndef __KERNEL_CUDS__
132 ccl_device
133 #else
134 ccl_device_noinline
135 #endif
136 void svm_node_attr_bump_dy(KernelGlobals *kg,
137                            ShaderData *sd,
138                            float *stack,
139                            uint4 node)
140 {
141         NodeAttributeType type, mesh_type;
142         AttributeElement elem;
143         uint out_offset;
144         int offset;
145
146         svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
147
148         /* fetch and store attribute */
149         if(type == NODE_ATTR_FLOAT) {
150                 if(mesh_type == NODE_ATTR_FLOAT) {
151                         float dy;
152                         float f = primitive_attribute_float(kg, sd, elem, offset, NULL, &dy);
153                         stack_store_float(stack, out_offset, f+dy);
154                 }
155                 else {
156                         float3 dy;
157                         float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, &dy);
158                         stack_store_float(stack, out_offset, average(f+dy));
159                 }
160         }
161         else {
162                 if(mesh_type == NODE_ATTR_FLOAT3) {
163                         float3 dy;
164                         float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, &dy);
165                         stack_store_float3(stack, out_offset, f+dy);
166                 }
167                 else {
168                         float dy;
169                         float f = primitive_attribute_float(kg, sd, elem, offset, NULL, &dy);
170                         stack_store_float3(stack, out_offset, make_float3(f+dy, f+dy, f+dy));
171                 }
172         }
173 }
174
175 CCL_NAMESPACE_END
176