2 # Copyright 2011-2013 Blender Foundation
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
8 # http://www.apache.org/licenses/LICENSE-2.0
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.
20 def _is_using_buggy_driver():
22 # We need to be conservative here because in multi-GPU systems display card
23 # might be quite old, but others one might be just good.
25 # So We shouldn't disable possible good dedicated cards just because display
26 # card seems weak. And instead we only blacklist configurations which are
27 # proven to cause problems.
28 if bgl.glGetString(bgl.GL_VENDOR) == "ATI Technologies Inc.":
30 version = bgl.glGetString(bgl.GL_VERSION)
31 if version.endswith("Compatibility Profile Context"):
32 # Old HD 4xxx and 5xxx series drivers did not have driver version
33 # in the version string, but those cards do not quite work and
36 regex = re.compile(".*Compatibility Profile Context ([0-9]+(\.[0-9]+)+)$")
37 if not regex.match(version):
38 # Skip cards like FireGL
40 version = regex.sub("\\1", version).split('.')
41 return int(version[0]) == 8
45 def _workaround_buggy_drivers():
46 if _is_using_buggy_driver():
48 if hasattr(_cycles, "opencl_disable"):
49 print("Cycles: OpenGL driver known to be buggy, disabling OpenCL platform.")
50 _cycles.opencl_disable()
53 def _configure_argument_parser():
55 # No help because it conflicts with general Python scripts argument parsing
56 parser = argparse.ArgumentParser(description="Cycles Addon argument parser",
58 parser.add_argument("--cycles-resumable-num-chunks",
59 help="Number of chunks to split sample range into",
61 parser.add_argument("--cycles-resumable-current-chunk",
62 help="Current chunk of samples range to render",
64 parser.add_argument("--cycles-resumable-start-chunk",
65 help="Start chunk to render",
67 parser.add_argument("--cycles-resumable-end-chunk",
68 help="End chunk to render",
70 parser.add_argument("--cycles-print-stats",
71 help="Print rendering statistics to stderr",
76 def _parse_command_line():
83 parser = _configure_argument_parser()
84 args, unknown = parser.parse_known_args(argv[argv.index("--") + 1:])
86 if args.cycles_resumable_num_chunks is not None:
87 if args.cycles_resumable_current_chunk is not None:
89 _cycles.set_resumable_chunk(
90 int(args.cycles_resumable_num_chunks),
91 int(args.cycles_resumable_current_chunk),
93 elif args.cycles_resumable_start_chunk is not None and \
94 args.cycles_resumable_end_chunk:
96 _cycles.set_resumable_chunk_range(
97 int(args.cycles_resumable_num_chunks),
98 int(args.cycles_resumable_start_chunk),
99 int(args.cycles_resumable_end_chunk),
101 if args.cycles_print_stats:
103 _cycles.enable_print_stats()
111 # Workaround possibly buggy legacy drivers which crashes on the OpenCL
112 # device enumeration.
114 # This checks are not really correct because they might still fail
115 # in the case of multiple GPUs. However, currently buggy drivers
116 # are really old and likely to be used in single GPU systems only
119 # Can't do it in the background mode, so we hope OpenCL is no enabled
120 # in the user preferences.
121 if not bpy.app.background:
122 _workaround_buggy_drivers()
124 path = os.path.dirname(__file__)
125 user_path = os.path.dirname(os.path.abspath(bpy.utils.user_resource('CONFIG', '')))
127 _cycles.init(path, user_path, bpy.app.background)
128 _parse_command_line()
136 def create(engine, data, scene, region=None, v3d=None, rv3d=None, preview_osl=False):
140 data = data.as_pointer()
141 userpref = bpy.context.user_preferences.as_pointer()
142 scene = scene.as_pointer()
144 region = region.as_pointer()
146 v3d = v3d.as_pointer()
148 rv3d = rv3d.as_pointer()
150 if bpy.app.debug_value == 256:
151 _cycles.debug_flags_update(scene)
153 _cycles.debug_flags_reset()
155 engine.session = _cycles.create(engine.as_pointer(), userpref, data, scene, region, v3d, rv3d, preview_osl)
159 if hasattr(engine, "session"):
162 _cycles.free(engine.session)
168 if hasattr(engine, "session"):
169 _cycles.render(engine.session)
172 def bake(engine, obj, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result):
174 session = getattr(engine, "session", None)
175 if session is not None:
176 _cycles.bake(engine.session, obj.as_pointer(), pass_type, pass_filter, object_id, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer())
179 def reset(engine, data, scene):
181 data = data.as_pointer()
182 scene = scene.as_pointer()
183 _cycles.reset(engine.session, data, scene)
186 def update(engine, data, scene):
188 _cycles.sync(engine.session)
191 def draw(engine, region, v3d, rv3d):
193 v3d = v3d.as_pointer()
194 rv3d = rv3d.as_pointer()
197 _cycles.draw(engine.session, v3d, rv3d)
200 def available_devices():
202 return _cycles.available_devices()
207 return _cycles.with_osl
212 return _cycles.with_network
217 return _cycles.system_info()
220 def register_passes(engine, scene, srl):
221 engine.register_pass(scene, srl, "Combined", 4, "RGBA", 'COLOR')
223 if srl.use_pass_z: engine.register_pass(scene, srl, "Depth", 1, "Z", 'VALUE')
224 if srl.use_pass_mist: engine.register_pass(scene, srl, "Mist", 1, "Z", 'VALUE')
225 if srl.use_pass_normal: engine.register_pass(scene, srl, "Normal", 3, "XYZ", 'VECTOR')
226 if srl.use_pass_vector: engine.register_pass(scene, srl, "Vector", 4, "XYZW", 'VECTOR')
227 if srl.use_pass_uv: engine.register_pass(scene, srl, "UV", 3, "UVA", 'VECTOR')
228 if srl.use_pass_object_index: engine.register_pass(scene, srl, "IndexOB", 1, "X", 'VALUE')
229 if srl.use_pass_material_index: engine.register_pass(scene, srl, "IndexMA", 1, "X", 'VALUE')
230 if srl.use_pass_shadow: engine.register_pass(scene, srl, "Shadow", 3, "RGB", 'COLOR')
231 if srl.use_pass_ambient_occlusion: engine.register_pass(scene, srl, "AO", 3, "RGB", 'COLOR')
232 if srl.use_pass_diffuse_direct: engine.register_pass(scene, srl, "DiffDir", 3, "RGB", 'COLOR')
233 if srl.use_pass_diffuse_indirect: engine.register_pass(scene, srl, "DiffInd", 3, "RGB", 'COLOR')
234 if srl.use_pass_diffuse_color: engine.register_pass(scene, srl, "DiffCol", 3, "RGB", 'COLOR')
235 if srl.use_pass_glossy_direct: engine.register_pass(scene, srl, "GlossDir", 3, "RGB", 'COLOR')
236 if srl.use_pass_glossy_indirect: engine.register_pass(scene, srl, "GlossInd", 3, "RGB", 'COLOR')
237 if srl.use_pass_glossy_color: engine.register_pass(scene, srl, "GlossCol", 3, "RGB", 'COLOR')
238 if srl.use_pass_transmission_direct: engine.register_pass(scene, srl, "TransDir", 3, "RGB", 'COLOR')
239 if srl.use_pass_transmission_indirect: engine.register_pass(scene, srl, "TransInd", 3, "RGB", 'COLOR')
240 if srl.use_pass_transmission_color: engine.register_pass(scene, srl, "TransCol", 3, "RGB", 'COLOR')
241 if srl.use_pass_subsurface_direct: engine.register_pass(scene, srl, "SubsurfaceDir", 3, "RGB", 'COLOR')
242 if srl.use_pass_subsurface_indirect: engine.register_pass(scene, srl, "SubsurfaceInd", 3, "RGB", 'COLOR')
243 if srl.use_pass_subsurface_color: engine.register_pass(scene, srl, "SubsurfaceCol", 3, "RGB", 'COLOR')
244 if srl.use_pass_emit: engine.register_pass(scene, srl, "Emit", 3, "RGB", 'COLOR')
245 if srl.use_pass_environment: engine.register_pass(scene, srl, "Env", 3, "RGB", 'COLOR')
248 if crl.pass_debug_render_time: engine.register_pass(scene, srl, "Debug Render Time", 1, "X", 'VALUE')
249 if crl.pass_debug_bvh_traversed_nodes: engine.register_pass(scene, srl, "Debug BVH Traversed Nodes", 1, "X", 'VALUE')
250 if crl.pass_debug_bvh_traversed_instances: engine.register_pass(scene, srl, "Debug BVH Traversed Instances", 1, "X", 'VALUE')
251 if crl.pass_debug_bvh_intersections: engine.register_pass(scene, srl, "Debug BVH Intersections", 1, "X", 'VALUE')
252 if crl.pass_debug_ray_bounces: engine.register_pass(scene, srl, "Debug Ray Bounces", 1, "X", 'VALUE')
253 if crl.use_pass_volume_direct: engine.register_pass(scene, srl, "VolumeDir", 3, "RGB", 'COLOR')
254 if crl.use_pass_volume_indirect: engine.register_pass(scene, srl, "VolumeInd", 3, "RGB", 'COLOR')
256 cscene = scene.cycles
258 if crl.use_pass_crypto_object:
259 for i in range(0, crl.pass_crypto_depth, 2):
260 engine.register_pass(scene, srl, "CryptoObject" + '{:02d}'.format(i), 4, "RGBA", 'COLOR')
261 if crl.use_pass_crypto_material:
262 for i in range(0, crl.pass_crypto_depth, 2):
263 engine.register_pass(scene, srl, "CryptoMaterial" + '{:02d}'.format(i), 4, "RGBA", 'COLOR')
264 if srl.cycles.use_pass_crypto_asset:
265 for i in range(0, srl.cycles.pass_crypto_depth, 2):
266 engine.register_pass(scene, srl, "CryptoAsset" + '{:02d}'.format(i), 4, "RGBA", 'COLOR')
268 if crl.use_denoising:
269 engine.register_pass(scene, srl, "Noisy Image", 3, "RGBA", 'COLOR')
270 if crl.denoising_store_passes:
271 engine.register_pass(scene, srl, "Denoising Normal", 3, "XYZ", 'VECTOR')
272 engine.register_pass(scene, srl, "Denoising Normal Variance", 3, "XYZ", 'VECTOR')
273 engine.register_pass(scene, srl, "Denoising Albedo", 3, "RGB", 'COLOR')
274 engine.register_pass(scene, srl, "Denoising Albedo Variance", 3, "RGB", 'COLOR')
275 engine.register_pass(scene, srl, "Denoising Depth", 1, "Z", 'VALUE')
276 engine.register_pass(scene, srl, "Denoising Depth Variance", 1, "Z", 'VALUE')
277 engine.register_pass(scene, srl, "Denoising Shadow A", 3, "XYV", 'VECTOR')
278 engine.register_pass(scene, srl, "Denoising Shadow B", 3, "XYV", 'VECTOR')
279 engine.register_pass(scene, srl, "Denoising Image Variance", 3, "RGB", 'COLOR')
280 clean_options = ("denoising_diffuse_direct", "denoising_diffuse_indirect",
281 "denoising_glossy_direct", "denoising_glossy_indirect",
282 "denoising_transmission_direct", "denoising_transmission_indirect",
283 "denoising_subsurface_direct", "denoising_subsurface_indirect")
284 if any(getattr(crl, option) for option in clean_options):
285 engine.register_pass(scene, srl, "Denoising Clean", 3, "RGB", 'COLOR')