This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/intern/cycles/blender/addon/engine.py
Sergey Sharybin f8b9f4e9bb Cycles: Resumable render implementation for Cycles
This feature is also known by the name Samples Offset, which allows
artists to render animation with given amount of samples N, but then
render more samples, starting from N and ending with M (where M > N)
and merge renders together as if they rendered exactly M samples.

Surely such effect could be achieved by changing Seed variable, but
that has possible issues with correlation artifacts and requiring to
manually deal with per render layer samples and such.

While we can't support all possible renderfarm-related features in
Cycles it's nice to support really commonly used stuff.

Here's a command how to run Blender with the new feature enabled:

  blender -- --cycles-resumable-num-chunks 24 --cycles-resumable-current-chunk 2

This command will divide samples range in 24 parts and render
range #2 (chunk number is 1-based).

This feature might be changed a bit after we'll do some tests here
in the studio with it.
2016-03-30 16:02:27 +02:00

192 lines
5.5 KiB
Python

#
# Copyright 2011-2013 Blender Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# <pep8 compliant>
def _is_using_buggy_driver():
import bgl
# We need to be conservative here because in multi-GPU systems display card
# might be quite old, but others one might be just good.
#
# So We shouldn't disable possible good dedicated cards just because display
# card seems weak. And instead we only blacklist configurations which are
# proven to cause problems.
if bgl.glGetString(bgl.GL_VENDOR) == "ATI Technologies Inc.":
import re
version = bgl.glGetString(bgl.GL_VERSION)
if version.endswith("Compatibility Profile Context"):
# Old HD 4xxx and 5xxx series drivers did not have driver version
# in the version string, but those cards do not quite work and
# causing crashes.
return True
regex = re.compile(".*Compatibility Profile Context ([0-9]+(\.[0-9]+)+)$")
if not regex.match(version):
# Skip cards like FireGL
return False
version = regex.sub("\\1", version).split('.')
return int(version[0]) == 8
return False
def _workaround_buggy_drivers():
if _is_using_buggy_driver():
import _cycles
if hasattr(_cycles, "opencl_disable"):
print("Cycles: OpenGL driver known to be buggy, disabling OpenCL platform.")
_cycles.opencl_disable()
def _parse_command_line():
import sys
argv = sys.argv
if "--" not in argv:
return
argv = argv[argv.index("--") + 1:]
num_resumable_chunks = None
current_resumable_chunk = None
# TODO(sergey): Add some nice error ptins if argument is not used properly.
idx = 0
while idx < len(argv) - 1:
arg = argv[idx]
if arg == '--cycles-resumable-num-chunks':
num_resumable_chunks = int(argv[idx + 1])
elif arg == '--cycles-resumable-current-chunk':
current_resumable_chunk = int(argv[idx + 1])
idx += 1
if num_resumable_chunks is not None and current_resumable_chunk is not None:
import _cycles
_cycles.set_resumable_chunks(num_resumable_chunks,
current_resumable_chunk)
def init():
import bpy
import _cycles
import os.path
import sys
# Workaround possibly buggy legacy drivers which crashes on the OpenCL
# device enumeration.
#
# This checks are not really correct because they might still fail
# in the case of multiple GPUs. However, currently buggy drivers
# are really old and likely to be used in single GPU systems only
# anyway.
#
# Can't do it in the background mode, so we hope OpenCL is no enabled
# in the user preferences.
if not bpy.app.background:
_workaround_buggy_drivers()
path = os.path.dirname(__file__)
user_path = os.path.dirname(os.path.abspath(bpy.utils.user_resource('CONFIG', '')))
_cycles.init(path, user_path, bpy.app.background)
_parse_command_line()
def exit():
import _cycles
_cycles.exit()
def create(engine, data, scene, region=None, v3d=None, rv3d=None, preview_osl=False):
import bpy
import _cycles
data = data.as_pointer()
userpref = bpy.context.user_preferences.as_pointer()
scene = scene.as_pointer()
if region:
region = region.as_pointer()
if v3d:
v3d = v3d.as_pointer()
if rv3d:
rv3d = rv3d.as_pointer()
if bpy.app.debug_value == 256:
_cycles.debug_flags_update(scene)
else:
_cycles.debug_flags_reset()
engine.session = _cycles.create(engine.as_pointer(), userpref, data, scene, region, v3d, rv3d, preview_osl)
def free(engine):
if hasattr(engine, "session"):
if engine.session:
import _cycles
_cycles.free(engine.session)
del engine.session
def render(engine):
import _cycles
if hasattr(engine, "session"):
_cycles.render(engine.session)
def bake(engine, obj, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result):
import _cycles
session = getattr(engine, "session", None)
if session is not None:
_cycles.bake(engine.session, obj.as_pointer(), pass_type, pass_filter, object_id, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer())
def reset(engine, data, scene):
import _cycles
data = data.as_pointer()
scene = scene.as_pointer()
_cycles.reset(engine.session, data, scene)
def update(engine, data, scene):
import _cycles
_cycles.sync(engine.session)
def draw(engine, region, v3d, rv3d):
import _cycles
v3d = v3d.as_pointer()
rv3d = rv3d.as_pointer()
# draw render image
_cycles.draw(engine.session, v3d, rv3d)
def available_devices():
import _cycles
return _cycles.available_devices()
def with_osl():
import _cycles
return _cycles.with_osl
def with_network():
import _cycles
return _cycles.with_network
def system_info():
import _cycles
return _cycles.system_info()