Merge branch 'master' into blender2.8
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Tue, 30 Oct 2018 13:13:47 +0000 (14:13 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Tue, 30 Oct 2018 13:13:47 +0000 (14:13 +0100)
1  2 
intern/cycles/blender/addon/engine.py
intern/cycles/blender/addon/ui.py
intern/cycles/blender/blender_session.cpp
intern/cycles/blender/blender_sync.cpp

index 25708a0f888534f966f1c6167fb7ca1b8e400ef0,55638415e663bd182e23ea6de5d024547307f155..778aa2dba8de0047ed041ba84be2317d4a1dfb49
@@@ -133,12 -133,13 +133,12 @@@ def exit()
      _cycles.exit()
  
  
 -def create(engine, data, scene, region=None, v3d=None, rv3d=None, preview_osl=False):
 -    import bpy
 +def create(engine, data, region=None, v3d=None, rv3d=None, preview_osl=False):
      import _cycles
 +    import bpy
  
      data = data.as_pointer()
      userpref = bpy.context.user_preferences.as_pointer()
 -    scene = scene.as_pointer()
      if region:
          region = region.as_pointer()
      if v3d:
      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)
 +    engine.session = _cycles.create(
 +            engine.as_pointer(), userpref, data, region, v3d, rv3d, preview_osl)
  
  
  def free(engine):
          del engine.session
  
  
 -def render(engine):
 +def render(engine, depsgraph):
      import _cycles
      if hasattr(engine, "session"):
 -        _cycles.render(engine.session)
 +        _cycles.render(engine.session, depsgraph.as_pointer())
  
  
 -def bake(engine, obj, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result):
 +def bake(engine, depsgraph, 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())
 +        _cycles.bake(engine.session, depsgraph.as_pointer(), obj.as_pointer(), pass_type, pass_filter, object_id, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer())
  
  
 -def reset(engine, data, scene):
 +def reset(engine, data, depsgraph):
      import _cycles
 +    import bpy
 +
 +    if bpy.app.debug_value == 256:
 +        _cycles.debug_flags_update(depsgraph.scene.as_pointer())
 +    else:
 +        _cycles.debug_flags_reset()
 +
      data = data.as_pointer()
 -    scene = scene.as_pointer()
 -    _cycles.reset(engine.session, data, scene)
 +    depsgraph = depsgraph.as_pointer()
 +    _cycles.reset(engine.session, data, depsgraph)
  
  
 -def update(engine, data, scene):
 +def sync(engine, depsgraph, data):
      import _cycles
 -    _cycles.sync(engine.session)
 +    _cycles.sync(engine.session, depsgraph.as_pointer())
  
  
 -def draw(engine, region, v3d, rv3d):
 +def draw(engine, depsgraph, region, v3d, rv3d):
      import _cycles
 +    depsgraph = depsgraph.as_pointer()
      v3d = v3d.as_pointer()
      rv3d = rv3d.as_pointer()
  
      # draw render image
 -    _cycles.draw(engine.session, v3d, rv3d)
 +    _cycles.draw(engine.session, depsgraph, v3d, rv3d)
  
  
  def available_devices():
@@@ -268,7 -265,7 +268,7 @@@ def register_passes(engine, scene, srl)
          for i in range(0, srl.cycles.pass_crypto_depth, 2):
              engine.register_pass(scene, srl, "CryptoAsset" + '{:02d}'.format(i), 4, "RGBA", 'COLOR')
  
-     if crl.use_denoising:
+     if crl.use_denoising or crl.denoising_store_passes:
          engine.register_pass(scene, srl, "Noisy Image", 3, "RGBA", 'COLOR')
          if crl.denoising_store_passes:
              engine.register_pass(scene, srl, "Denoising Normal",          3, "XYZ", 'VECTOR')
index 7aa66fac31fd2292e4a1c7e76155fea3a773fdf8,0fdefe5d4424aa69b76accf429f7a02576d6af74..d172fd0b4c80496c19dfb808947a085cc59dca48
@@@ -17,8 -17,6 +17,8 @@@
  # <pep8 compliant>
  
  import bpy
 +from bpy_extras.node_utils import find_node_input
 +from bl_operators.presets import PresetMenu
  
  from bpy.types import (
      Panel,
  )
  
  
 -class CYCLES_MT_sampling_presets(Menu):
 +class CYCLES_PT_sampling_presets(PresetMenu):
      bl_label = "Sampling Presets"
      preset_subdir = "cycles/sampling"
      preset_operator = "script.execute_preset"
 +    preset_add_operator = "render.cycles_sampling_preset_add"
      COMPAT_ENGINES = {'CYCLES'}
 -    draw = Menu.draw_preset
  
  
 -class CYCLES_MT_integrator_presets(Menu):
 +class CYCLES_PT_integrator_presets(PresetMenu):
      bl_label = "Integrator Presets"
      preset_subdir = "cycles/integrator"
      preset_operator = "script.execute_preset"
 +    preset_add_operator = "render.cycles_integrator_preset_add"
      COMPAT_ENGINES = {'CYCLES'}
 -    draw = Menu.draw_preset
  
  
  class CyclesButtonsPanel:
@@@ -51,7 -49,8 +51,7 @@@
  
      @classmethod
      def poll(cls, context):
 -        rd = context.scene.render
 -        return rd.engine in cls.COMPAT_ENGINES
 +        return context.engine in cls.COMPAT_ENGINES
  
  
  def get_device_type(context):
@@@ -129,15 -128,15 +129,15 @@@ def draw_samples_info(layout, context)
      if use_branched_path(context) or (cscene.use_square_samples and integrator == 'PATH'):
          col = layout.column(align=True)
          col.scale_y = 0.6
 -        col.label("Total Samples:")
 +        col.label(text="Total Samples:")
          col.separator()
          if integrator == 'PATH':
 -            col.label("%s AA" % aa)
 +            col.label(text="%s AA" % aa)
          else:
 -            col.label("%s AA, %s Diffuse, %s Glossy, %s Transmission" %
 +            col.label(text="%s AA, %s Diffuse, %s Glossy, %s Transmission" %
                        (aa, d * aa, g * aa, t * aa))
              col.separator()
 -            col.label("%s AO, %s Mesh Light, %s Subsurface, %s Volume" %
 +            col.label(text="%s AO, %s Mesh Light, %s Subsurface, %s Volume" %
                        (ao * aa, ml * aa, sss * aa, vol * aa))
  
  
@@@ -145,312 -144,174 +145,312 @@@ class CYCLES_RENDER_PT_sampling(CyclesB
      bl_label = "Sampling"
      bl_options = {'DEFAULT_CLOSED'}
  
 +    def draw_header_preset(self, context):
 +        CYCLES_PT_sampling_presets.draw_panel_header(self.layout)
 +
      def draw(self, context):
          layout = self.layout
  
          scene = context.scene
          cscene = scene.cycles
  
 -        row = layout.row(align=True)
 -        row.menu("CYCLES_MT_sampling_presets", text=bpy.types.CYCLES_MT_sampling_presets.bl_label)
 -        row.operator("render.cycles_sampling_preset_add", text="", icon="ZOOMIN")
 -        row.operator("render.cycles_sampling_preset_add", text="", icon="ZOOMOUT").remove_active = True
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
 -        row = layout.row()
 -        sub = row.row()
 -        sub.prop(cscene, "progressive", text="")
 -        row.prop(cscene, "use_square_samples")
 +        layout.prop(cscene, "progressive")
  
 -        split = layout.split()
 -
 -        col = split.column()
 -        sub = col.column(align=True)
 -        sub.label("Settings:")
 +        if cscene.progressive == 'PATH' or use_branched_path(context) is False:
 +            col = layout.column(align=True)
 +            col.prop(cscene, "samples", text="Render")
 +            col.prop(cscene, "preview_samples", text="Viewport")
  
 -        seed_sub = sub.row(align=True)
 -        seed_sub.prop(cscene, "seed")
 -        seed_sub.prop(cscene, "use_animated_seed", text="", icon="TIME")
 +            draw_samples_info(layout, context)
 +        else:
 +            col = layout.column(align=True)
 +            col.prop(cscene, "aa_samples", text="Render")
 +            col.prop(cscene, "preview_aa_samples", text="Viewport")
  
 -        sub.prop(cscene, "sample_clamp_direct")
 -        sub.prop(cscene, "sample_clamp_indirect")
 -        sub.prop(cscene, "light_sampling_threshold")
  
 -        if cscene.progressive == 'PATH' or use_branched_path(context) is False:
 -            col = split.column()
 -            sub = col.column(align=True)
 -            sub.label(text="Samples:")
 -            sub.prop(cscene, "samples", text="Render")
 -            sub.prop(cscene, "preview_samples", text="Preview")
 -        else:
 -            sub.label(text="AA Samples:")
 -            sub.prop(cscene, "aa_samples", text="Render")
 -            sub.prop(cscene, "preview_aa_samples", text="Preview")
 +class CYCLES_RENDER_PT_sampling_light(CyclesButtonsPanel, Panel):
 +    bl_label = "Light"
 +    bl_parent_id = "CYCLES_RENDER_PT_sampling"
 +    bl_options = {'DEFAULT_CLOSED'}
  
 -            col = split.column()
 -            sub = col.column(align=True)
 -            sub.label(text="Samples:")
 -            sub.prop(cscene, "diffuse_samples", text="Diffuse")
 -            sub.prop(cscene, "glossy_samples", text="Glossy")
 -            sub.prop(cscene, "transmission_samples", text="Transmission")
 -            sub.prop(cscene, "ao_samples", text="AO")
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
 -            subsub = sub.row(align=True)
 -            subsub.active = use_sample_all_lights(context)
 -            subsub.prop(cscene, "mesh_light_samples", text="Mesh Light")
 +        scene = context.scene
 +        cscene = scene.cycles
  
 -            sub.prop(cscene, "subsurface_samples", text="Subsurface")
 -            sub.prop(cscene, "volume_samples", text="Volume")
 +        col = layout.column(align=True)
 +        col.prop(cscene, "light_sampling_threshold", text="Light Threshold")
  
 +        if cscene.progressive != 'PATH' and use_branched_path(context):
              col = layout.column(align=True)
              col.prop(cscene, "sample_all_lights_direct")
              col.prop(cscene, "sample_all_lights_indirect")
  
 -        layout.row().prop(cscene, "sampling_pattern", text="Pattern")
 +        col = layout.column(align=True)
 +        col.prop(cscene, "sample_clamp_direct")
 +        col.prop(cscene, "sample_clamp_indirect")
 +
  
 -        for rl in scene.render.layers:
 -            if rl.samples > 0:
 -                layout.separator()
 -                layout.row().prop(cscene, "use_layer_samples")
 -                break
 +class CYCLES_RENDER_PT_sampling_sub_samples(CyclesButtonsPanel, Panel):
 +    bl_label = "Sub Samples"
 +    bl_parent_id = "CYCLES_RENDER_PT_sampling"
 +
 +    @classmethod
 +    def poll(self, context):
 +        scene = context.scene
 +        cscene = scene.cycles
 +        return cscene.progressive != 'PATH' and use_branched_path(context)
 +
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
 +
 +        scene = context.scene
 +        cscene = scene.cycles
 +
 +        col = layout.column(align=True)
 +        col.prop(cscene, "diffuse_samples", text="Diffuse")
 +        col.prop(cscene, "glossy_samples", text="Glossy")
 +        col.prop(cscene, "transmission_samples", text="Transmission")
 +        col.prop(cscene, "ao_samples", text="AO")
 +
 +        sub = col.row(align=True)
 +        sub.active = use_sample_all_lights(context)
 +        sub.prop(cscene, "mesh_light_samples", text="Mesh Light")
 +        col.prop(cscene, "subsurface_samples", text="Subsurface")
 +        col.prop(cscene, "volume_samples", text="Volume")
  
          draw_samples_info(layout, context)
  
  
 +class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
 +    bl_label = "Advanced"
 +    bl_parent_id = "CYCLES_RENDER_PT_sampling"
 +    bl_options = {'DEFAULT_CLOSED'}
 +
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
 +
 +        scene = context.scene
 +        cscene = scene.cycles
 +
 +        row = layout.row(align=True)
 +        row.prop(cscene, "seed")
 +        row.prop(cscene, "use_animated_seed", text="", icon='TIME')
 +
 +        layout.prop(cscene, "sampling_pattern", text="Pattern")
 +
 +        layout.prop(cscene, "use_square_samples")
 +
 +
 +class CYCLES_RENDER_PT_sampling_total(CyclesButtonsPanel, Panel):
 +    bl_label = "Total Samples"
 +    bl_parent_id = "CYCLES_RENDER_PT_sampling"
 +
 +    @classmethod
 +    def poll(self, context):
 +        scene = context.scene
 +        cscene = scene.cycles
 +
 +        if cscene.use_square_samples:
 +            return True
 +
 +        return cscene.progressive != 'PATH' and use_branched_path(context)
 +
 +    def draw(self, context):
 +        layout = self.layout
 +        cscene = context.scene.cycles
 +        integrator = cscene.progressive
 +
 +        # Calculate sample values
 +        if integrator == 'PATH':
 +            aa = cscene.samples
 +            if cscene.use_square_samples:
 +                aa = aa * aa
 +        else:
 +            aa = cscene.aa_samples
 +            d = cscene.diffuse_samples
 +            g = cscene.glossy_samples
 +            t = cscene.transmission_samples
 +            ao = cscene.ao_samples
 +            ml = cscene.mesh_light_samples
 +            sss = cscene.subsurface_samples
 +            vol = cscene.volume_samples
 +
 +            if cscene.use_square_samples:
 +                aa = aa * aa
 +                d = d * d
 +                g = g * g
 +                t = t * t
 +                ao = ao * ao
 +                ml = ml * ml
 +                sss = sss * sss
 +                vol = vol * vol
 +
 +        col = layout.column(align=True)
 +        col.scale_y = 0.6
 +        if integrator == 'PATH':
 +            col.label(text="%s AA" % aa)
 +        else:
 +            col.label(text="%s AA, %s Diffuse, %s Glossy, %s Transmission" %
 +                      (aa, d * aa, g * aa, t * aa))
 +            col.separator()
 +            col.label(text="%s AO, %s Mesh Light, %s Subsurface, %s Volume" %
 +                      (ao * aa, ml * aa, sss * aa, vol * aa))
 +
 +
  class CYCLES_RENDER_PT_geometry(CyclesButtonsPanel, Panel):
      bl_label = "Geometry"
      bl_options = {'DEFAULT_CLOSED'}
  
 +    def draw(self, context):
 +        pass
 +
 +
 +class CYCLES_RENDER_PT_geometry_subdivision(CyclesButtonsPanel, Panel):
 +    bl_label = "Subdivision"
 +    bl_parent_id = "CYCLES_RENDER_PT_geometry"
 +
 +    @classmethod
 +    def poll(self, context):
 +        return context.scene.cycles.feature_set == 'EXPERIMENTAL'
 +
      def draw(self, context):
          layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
          scene = context.scene
          cscene = scene.cycles
 -        ccscene = scene.cycles_curves
  
 -        row = layout.row()
 -        row.label("Volume Sampling:")
 -        row = layout.row()
 -        row.prop(cscene, "volume_step_size")
 -        row.prop(cscene, "volume_max_steps")
 +        col = layout.column()
 +        sub = col.column(align=True)
 +        sub.prop(cscene, "dicing_rate", text="Dicing Rate Render")
 +        sub.prop(cscene, "preview_dicing_rate", text="Preview")
  
 -        layout.separator()
 +        col.separator()
  
 -        if cscene.feature_set == 'EXPERIMENTAL':
 -            layout.label("Subdivision Rate:")
 -            split = layout.split()
 +        col.prop(cscene, "offscreen_dicing_scale", text="Offscreen Scale")
 +        col.prop(cscene, "max_subdivisions")
  
 -            col = split.column()
 -            sub = col.column(align=True)
 -            sub.prop(cscene, "dicing_rate", text="Render")
 -            sub.prop(cscene, "preview_dicing_rate", text="Preview")
 +        col.prop(cscene, "dicing_camera")
  
 -            col = split.column()
 -            col.prop(cscene, "offscreen_dicing_scale", text="Offscreen Scale")
 -            col.prop(cscene, "max_subdivisions")
  
 -            layout.prop(cscene, "dicing_camera")
 +class CYCLES_RENDER_PT_geometry_volume(CyclesButtonsPanel, Panel):
 +    bl_label = "Volume"
 +    bl_parent_id = "CYCLES_RENDER_PT_geometry"
  
 -            layout.separator()
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
 +
 +        scene = context.scene
 +        cscene = scene.cycles
 +        ccscene = scene.cycles_curves
  
 -        layout.label("Hair:")
 -        layout.prop(ccscene, "use_curves", text="Use Hair")
          col = layout.column()
 -        col.active = ccscene.use_curves
 +        col.prop(cscene, "volume_step_size", text="Step Size")
 +        col.prop(cscene, "volume_max_steps", text="Max Steps")
  
 -        col.prop(ccscene, "primitive", text="Primitive")
 -        col.prop(ccscene, "shape", text="Shape")
  
 +class CYCLES_RENDER_PT_geometry_hair(CyclesButtonsPanel, Panel):
 +    bl_label = "Hair"
 +    bl_parent_id = "CYCLES_RENDER_PT_geometry"
 +
 +    def draw_header(self, context):
 +        layout = self.layout
 +        scene = context.scene
 +        cscene = scene.cycles
 +        ccscene = scene.cycles_curves
 +
 +        layout.prop(ccscene, "use_curves", text="")
 +
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
 +
 +        scene = context.scene
 +        cscene = scene.cycles
 +        ccscene = scene.cycles_curves
 +
 +        layout.active = ccscene.use_curves
 +
 +        col = layout.column()
 +        col.prop(ccscene, "minimum_width", text="Min Pixels")
 +        col.prop(ccscene, "maximum_width", text="Max Extension")
 +        col.prop(ccscene, "shape", text="Shape")
          if not (ccscene.primitive in {'CURVE_SEGMENTS', 'LINE_SEGMENTS'} and ccscene.shape == 'RIBBONS'):
              col.prop(ccscene, "cull_backfacing", text="Cull back-faces")
 +        col.prop(ccscene, "primitive", text="Primitive")
  
          if ccscene.primitive == 'TRIANGLES' and ccscene.shape == 'THICK':
              col.prop(ccscene, "resolution", text="Resolution")
          elif ccscene.primitive == 'CURVE_SEGMENTS':
              col.prop(ccscene, "subdivisions", text="Curve subdivisions")
  
 -        row = col.row()
 -        row.prop(ccscene, "minimum_width", text="Min Pixels")
 -        row.prop(ccscene, "maximum_width", text="Max Extension")
 -
  
  class CYCLES_RENDER_PT_light_paths(CyclesButtonsPanel, Panel):
      bl_label = "Light Paths"
      bl_options = {'DEFAULT_CLOSED'}
  
 +    def draw_header_preset(self, context):
 +        CYCLES_PT_integrator_presets.draw_panel_header(self.layout)
 +
 +    def draw(self, context):
 +        pass
 +
 +
 +class CYCLES_RENDER_PT_light_paths_max_bounces(CyclesButtonsPanel, Panel):
 +    bl_label = "Max Bounces"
 +    bl_parent_id = "CYCLES_RENDER_PT_light_paths"
 +
      def draw(self, context):
          layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
          scene = context.scene
          cscene = scene.cycles
  
 -        row = layout.row(align=True)
 -        row.menu("CYCLES_MT_integrator_presets", text=bpy.types.CYCLES_MT_integrator_presets.bl_label)
 -        row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMIN")
 -        row.operator("render.cycles_integrator_preset_add", text="", icon="ZOOMOUT").remove_active = True
 +        col = layout.column(align=True)
 +        col.prop(cscene, "max_bounces", text="Total")
  
 -        split = layout.split()
 +        col = layout.column(align=True)
 +        col.prop(cscene, "diffuse_bounces", text="Diffuse")
 +        col.prop(cscene, "glossy_bounces", text="Glossy")
 +        col.prop(cscene, "transparent_max_bounces", text="Transparency")
 +        col.prop(cscene, "transmission_bounces", text="Transmission")
 +        col.prop(cscene, "volume_bounces", text="Volume")
  
 -        col = split.column()
  
 -        sub = col.column(align=True)
 -        sub.label("Transparency:")
 -        sub.prop(cscene, "transparent_max_bounces", text="Max")
 +class CYCLES_RENDER_PT_light_paths_caustics(CyclesButtonsPanel, Panel):
 +    bl_label = "Caustics"
 +    bl_parent_id = "CYCLES_RENDER_PT_light_paths"
 +    bl_options = {'DEFAULT_CLOSED'}
  
 -        col.separator()
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
 +
 +        scene = context.scene
 +        cscene = scene.cycles
  
 +        col = layout.column()
 +        col.prop(cscene, "blur_glossy")
          col.prop(cscene, "caustics_reflective")
          col.prop(cscene, "caustics_refractive")
 -        col.prop(cscene, "blur_glossy")
 -
 -        col = split.column()
 -
 -        sub = col.column(align=True)
 -        sub.label(text="Bounces:")
 -        sub.prop(cscene, "max_bounces", text="Max")
 -
 -        sub = col.column(align=True)
 -        sub.prop(cscene, "diffuse_bounces", text="Diffuse")
 -        sub.prop(cscene, "glossy_bounces", text="Glossy")
 -        sub.prop(cscene, "transmission_bounces", text="Transmission")
 -        sub.prop(cscene, "volume_bounces", text="Volume")
  
  
  class CYCLES_RENDER_PT_motion_blur(CyclesButtonsPanel, Panel):
  
      def draw(self, context):
          layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
          scene = context.scene
          cscene = scene.cycles
          col = layout.column()
          col.prop(cscene, "motion_blur_position", text="Position")
          col.prop(rd, "motion_blur_shutter")
 +        col.separator()
 +        col.prop(cscene, "rolling_shutter_type", text="Rolling Shutter")
 +        sub = col.column()
 +        sub.active = cscene.rolling_shutter_type != 'NONE'
 +        sub.prop(cscene, "rolling_shutter_duration")
 +
 +
 +class CYCLES_RENDER_PT_motion_blur_curve(CyclesButtonsPanel, Panel):
 +    bl_label = "Shutter Curve"
 +    bl_parent_id = "CYCLES_RENDER_PT_motion_blur"
 +    bl_options = {'DEFAULT_CLOSED'}
 +
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
 +
 +        scene = context.scene
 +        cscene = scene.cycles
 +        rd = scene.render
 +        layout.active = rd.use_motion_blur
  
          col = layout.column()
 -        col.label("Shutter curve:")
 +
          col.template_curve_mapping(rd, "motion_blur_shutter_curve")
  
          col = layout.column(align=True)
          row.operator("render.shutter_curve_preset", icon='LINCURVE', text="").shape = 'LINE'
          row.operator("render.shutter_curve_preset", icon='NOCURVE', text="").shape = 'MAX'
  
 -        col = layout.column()
 -        col.prop(cscene, "rolling_shutter_type")
 -        row = col.row()
 -        row.active = cscene.rolling_shutter_type != 'NONE'
 -        row.prop(cscene, "rolling_shutter_duration")
 -
  
  class CYCLES_RENDER_PT_film(CyclesButtonsPanel, Panel):
      bl_label = "Film"
 +    bl_options = {'DEFAULT_CLOSED'}
  
      def draw(self, context):
          layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
 +        scene = context.scene
 +        cscene = scene.cycles
 +
 +        col = layout.column()
 +        col.prop(cscene, "film_exposure")
 +
 +
 +class CYCLES_RENDER_PT_film_transparency(CyclesButtonsPanel, Panel):
 +    bl_label = "Transparency"
 +    bl_parent_id = "CYCLES_RENDER_PT_film"
 +
 +    def draw_header(self, context):
 +        layout = self.layout
 +        rd = context.scene.render
  
          scene = context.scene
          cscene = scene.cycles
  
 -        split = layout.split()
 +        layout.prop(cscene, "film_transparent", text="")
  
 -        col = split.column()
 -        col.prop(cscene, "film_exposure")
 -        col.separator()
 -        sub = col.column(align=True)
 -        sub.prop(cscene, "pixel_filter_type", text="")
 -        if cscene.pixel_filter_type != 'BOX':
 -            sub.prop(cscene, "filter_width", text="Width")
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
 +        scene = context.scene
 +        cscene = scene.cycles
  
 -        col = split.column()
 -        col.prop(cscene, "film_transparent")
 -        sub = col.row()
 -        sub.prop(cscene, "film_transparent_glass", text="Transparent Glass")
 -        sub.active = cscene.film_transparent
 -        sub = col.row()
 -        sub.prop(cscene, "film_transparent_roughness", text="Roughness Threshold")
 +        layout.active = cscene.film_transparent
 +
 +        col = layout.column()
 +        col.prop(cscene, "film_transparent_glass", text="Transparent Glass")
 +
 +        sub = col.column()
          sub.active = cscene.film_transparent and cscene.film_transparent_glass
 +        sub.prop(cscene, "film_transparent_roughness", text="Roughness Threshold")
 +
 +
 +class CYCLES_RENDER_PT_film_pixel_filter(CyclesButtonsPanel, Panel):
 +    bl_label = "Pixel Filter"
 +    bl_parent_id = "CYCLES_RENDER_PT_film"
 +    bl_options = {'DEFAULT_CLOSED'}
 +
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
 +        scene = context.scene
 +        cscene = scene.cycles
 +
 +        col = layout.column()
 +        col.prop(cscene, "pixel_filter_type", text="Type")
 +        if cscene.pixel_filter_type != 'BOX':
 +            col.prop(cscene, "filter_width", text="Width")
  
  
  class CYCLES_RENDER_PT_performance(CyclesButtonsPanel, Panel):
  
      def draw(self, context):
          layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
          scene = context.scene
          rd = scene.render
          cscene = scene.cycles
  
 -        split = layout.split()
 +        col = layout.column()
 +        col.active = show_device_active(context)
 +        col.prop(cscene, "device")
 +
 +        from . import engine
 +        if engine.with_osl() and use_cpu(context):
 +            col.prop(cscene, "shading_system")
 +
  
 -        col = split.column(align=True)
 +class CYCLES_RENDER_PT_performance_threads(CyclesButtonsPanel, Panel):
 +    bl_label = "Threads"
 +    bl_parent_id = "CYCLES_RENDER_PT_performance"
  
 -        col.label(text="Threads:")
 -        col.row(align=True).prop(rd, "threads_mode", expand=True)
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
 +
 +        scene = context.scene
 +        rd = scene.render
 +        cscene = scene.cycles
 +
 +        col = layout.column()
 +
 +        col.prop(rd, "threads_mode")
          sub = col.column(align=True)
          sub.enabled = rd.threads_mode == 'FIXED'
          sub.prop(rd, "threads")
  
 -        col.separator()
  
 -        sub = col.column(align=True)
 -        sub.label(text="Tiles:")
 -        sub.prop(cscene, "tile_order", text="")
 +class CYCLES_RENDER_PT_performance_tiles(CyclesButtonsPanel, Panel):
 +    bl_label = "Tiles"
 +    bl_parent_id = "CYCLES_RENDER_PT_performance"
 +
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
 +
 +        scene = context.scene
 +        rd = scene.render
 +        cscene = scene.cycles
 +
 +        col = layout.column()
  
 -        sub.prop(rd, "tile_x", text="X")
 +        sub = col.column(align=True)
 +        sub.prop(rd, "tile_x", text="Tiles X")
          sub.prop(rd, "tile_y", text="Y")
 +        col.prop(cscene, "tile_order", text="Order")
  
 -        subsub = sub.column()
 -        subsub.active = not rd.use_save_buffers
 -        for rl in rd.layers:
 -            if rl.cycles.use_denoising:
 -                subsub.active = False
 -        subsub.prop(cscene, "use_progressive_refine")
 +        sub = col.column()
 +        sub.active = not rd.use_save_buffers
 +        for view_layer in scene.view_layers:
 +            if view_layer.cycles.use_denoising:
 +                sub.active = False
 +        sub.prop(cscene, "use_progressive_refine")
  
 -        col = split.column()
  
 -        col.label(text="Final Render:")
 -        col.prop(rd, "use_save_buffers")
 -        col.prop(rd, "use_persistent_data", text="Persistent Images")
 +class CYCLES_RENDER_PT_performance_acceleration_structure(CyclesButtonsPanel, Panel):
 +    bl_label = "Acceleration Structure"
 +    bl_parent_id = "CYCLES_RENDER_PT_performance"
 +    bl_options = {'DEFAULT_CLOSED'}
  
 -        col.separator()
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
 +
 +        scene = context.scene
 +        rd = scene.render
 +        cscene = scene.cycles
 +
 +        col = layout.column()
  
 -        col.label(text="Acceleration structure:")
          col.prop(cscene, "debug_use_spatial_splits")
          col.prop(cscene, "debug_use_hair_bvh")
 +        sub = col.column()
 +        sub.active = not cscene.debug_use_spatial_splits
 +        sub.prop(cscene, "debug_bvh_time_steps")
  
 -        row = col.row()
 -        row.active = not cscene.debug_use_spatial_splits
 -        row.prop(cscene, "debug_bvh_time_steps")
 +
 +class CYCLES_RENDER_PT_performance_final_render(CyclesButtonsPanel, Panel):
 +    bl_label = "Final Render"
 +    bl_parent_id = "CYCLES_RENDER_PT_performance"
 +    bl_options = {'DEFAULT_CLOSED'}
 +
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
 +
 +        scene = context.scene
 +        rd = scene.render
 +        cscene = scene.cycles
  
          col = layout.column()
 -        col.label(text="Viewport Resolution:")
 -        split = col.split()
 -        split.prop(rd, "preview_pixel_size", text="")
 -        split.prop(cscene, "preview_start_resolution")
 +
 +        col.prop(rd, "use_save_buffers")
 +        col.prop(rd, "use_persistent_data", text="Persistent Images")
  
  
 -class CYCLES_RENDER_PT_layer_options(CyclesButtonsPanel, Panel):
 -    bl_label = "Layer"
 -    bl_context = "render_layer"
 +class CYCLES_RENDER_PT_performance_viewport(CyclesButtonsPanel, Panel):
 +    bl_label = "Viewport"
 +    bl_parent_id = "CYCLES_RENDER_PT_performance"
 +    bl_options = {'DEFAULT_CLOSED'}
  
      def draw(self, context):
          layout = self.layout
 -        with_freestyle = bpy.app.build_options.freestyle
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
          scene = context.scene
          rd = scene.render
 -        rl = rd.layers.active
 +        cscene = scene.cycles
  
 -        split = layout.split()
 +        col = layout.column()
 +        col.prop(rd, "preview_pixel_size", text="Pixel Size")
 +        col.prop(cscene, "preview_start_resolution", text="Start Pixels")
  
 -        col = split.column()
 -        col.prop(scene, "layers", text="Scene")
 -        col.prop(rl, "layers_exclude", text="Exclude")
  
 -        col = split.column()
 -        col.prop(rl, "layers", text="Layer")
 -        col.prop(rl, "layers_zmask", text="Mask Layer")
 +class CYCLES_RENDER_PT_filter(CyclesButtonsPanel, Panel):
 +    bl_label = "Filter"
 +    bl_options = {'DEFAULT_CLOSED'}
 +    bl_context = "view_layer"
  
 -        split = layout.split()
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
 -        col = split.column()
 -        col.label(text="Material:")
 -        col.prop(rl, "material_override", text="")
 -        col.separator()
 -        col.prop(rl, "samples")
 +        with_freestyle = bpy.app.build_options.freestyle
  
 -        col = split.column()
 -        col.prop(rl, "use_sky", "Use Environment")
 -        col.prop(rl, "use_ao", "Use AO")
 -        col.prop(rl, "use_solid", "Use Surfaces")
 -        col.prop(rl, "use_strand", "Use Hair")
 +        scene = context.scene
 +        rd = scene.render
 +        view_layer = context.view_layer
 +
 +        flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
 +
 +        col = flow.column()
 +        col.prop(view_layer, "use_sky", text="Use Environment")
 +        col = flow.column()
 +        col.prop(view_layer, "use_ao", text="Use Ambient Occlusion")
 +        col = flow.column()
 +        col.prop(view_layer, "use_solid", text="Use Surfaces")
 +        col = flow.column()
 +        col.prop(view_layer, "use_strand", text="Use Hair")
          if with_freestyle:
 -            row = col.row()
 -            row.prop(rl, "use_freestyle", "Use Freestyle")
 -            row.active = rd.use_freestyle
 +            col = flow.column()
 +            col.prop(view_layer, "use_freestyle", text="Use Freestyle")
 +            col.active = rd.use_freestyle
  
  
  class CYCLES_RENDER_PT_layer_passes(CyclesButtonsPanel, Panel):
      bl_label = "Passes"
 -    bl_context = "render_layer"
 +    bl_context = "view_layer"
      bl_options = {'DEFAULT_CLOSED'}
  
      def draw(self, context):
  
          scene = context.scene
          rd = scene.render
 -        rl = rd.layers.active
 -        crl = rl.cycles
 +        view_layer = context.view_layer
 +        cycles_view_layer = view_layer.cycles
  
          split = layout.split()
  
          col = split.column()
 -        col.prop(rl, "use_pass_combined")
 -        col.prop(rl, "use_pass_z")
 -        col.prop(rl, "use_pass_mist")
 -        col.prop(rl, "use_pass_normal")
 +        col.prop(view_layer, "use_pass_combined")
 +        col.prop(view_layer, "use_pass_z")
 +        col.prop(view_layer, "use_pass_mist")
 +        col.prop(view_layer, "use_pass_normal")
          row = col.row()
 -        row.prop(rl, "use_pass_vector")
 +        row.prop(view_layer, "use_pass_vector")
          row.active = not rd.use_motion_blur
 -        col.prop(rl, "use_pass_uv")
 -        col.prop(rl, "use_pass_object_index")
 -        col.prop(rl, "use_pass_material_index")
 +        col.prop(view_layer, "use_pass_uv")
 +        col.prop(view_layer, "use_pass_object_index")
 +        col.prop(view_layer, "use_pass_material_index")
          col.separator()
 -        col.prop(rl, "use_pass_shadow")
 -        col.prop(rl, "use_pass_ambient_occlusion")
 +        col.prop(view_layer, "use_pass_shadow")
 +        col.prop(view_layer, "use_pass_ambient_occlusion", text="Ambient Occlusion")
          col.separator()
 -        col.prop(crl, "denoising_store_passes", text="Denoising Data")
++        col.prop(cycles_view_layer, "denoising_store_passes", text="Denoising Data")
+         col.separator()
 -        col.prop(rl, "pass_alpha_threshold")
 +        col.prop(view_layer, "pass_alpha_threshold")
  
          col = split.column()
          col.label(text="Diffuse:")
          row = col.row(align=True)
 -        row.prop(rl, "use_pass_diffuse_direct", text="Direct", toggle=True)
 -        row.prop(rl, "use_pass_diffuse_indirect", text="Indirect", toggle=True)
 -        row.prop(rl, "use_pass_diffuse_color", text="Color", toggle=True)
 +        row.prop(view_layer, "use_pass_diffuse_direct", text="Direct", toggle=True)
 +        row.prop(view_layer, "use_pass_diffuse_indirect", text="Indirect", toggle=True)
 +        row.prop(view_layer, "use_pass_diffuse_color", text="Color", toggle=True)
          col.label(text="Glossy:")
          row = col.row(align=True)
 -        row.prop(rl, "use_pass_glossy_direct", text="Direct", toggle=True)
 -        row.prop(rl, "use_pass_glossy_indirect", text="Indirect", toggle=True)
 -        row.prop(rl, "use_pass_glossy_color", text="Color", toggle=True)
 +        row.prop(view_layer, "use_pass_glossy_direct", text="Direct", toggle=True)
 +        row.prop(view_layer, "use_pass_glossy_indirect", text="Indirect", toggle=True)
 +        row.prop(view_layer, "use_pass_glossy_color", text="Color", toggle=True)
          col.label(text="Transmission:")
          row = col.row(align=True)
 -        row.prop(rl, "use_pass_transmission_direct", text="Direct", toggle=True)
 -        row.prop(rl, "use_pass_transmission_indirect", text="Indirect", toggle=True)
 -        row.prop(rl, "use_pass_transmission_color", text="Color", toggle=True)
 +        row.prop(view_layer, "use_pass_transmission_direct", text="Direct", toggle=True)
 +        row.prop(view_layer, "use_pass_transmission_indirect", text="Indirect", toggle=True)
 +        row.prop(view_layer, "use_pass_transmission_color", text="Color", toggle=True)
          col.label(text="Subsurface:")
          row = col.row(align=True)
 -        row.prop(rl, "use_pass_subsurface_direct", text="Direct", toggle=True)
 -        row.prop(rl, "use_pass_subsurface_indirect", text="Indirect", toggle=True)
 -        row.prop(rl, "use_pass_subsurface_color", text="Color", toggle=True)
 +        row.prop(view_layer, "use_pass_subsurface_direct", text="Direct", toggle=True)
 +        row.prop(view_layer, "use_pass_subsurface_indirect", text="Indirect", toggle=True)
 +        row.prop(view_layer, "use_pass_subsurface_color", text="Color", toggle=True)
          col.label(text="Volume:")
          row = col.row(align=True)
 -        row.prop(crl, "use_pass_volume_direct", text="Direct", toggle=True)
 -        row.prop(crl, "use_pass_volume_indirect", text="Indirect", toggle=True)
 +        row.prop(cycles_view_layer, "use_pass_volume_direct", text="Direct", toggle=True)
 +        row.prop(cycles_view_layer, "use_pass_volume_indirect", text="Indirect", toggle=True)
  
          col.separator()
 -        col.prop(rl, "use_pass_emit", text="Emission")
 -        col.prop(rl, "use_pass_environment")
 +        col.prop(view_layer, "use_pass_emit", text="Emission")
 +        col.prop(view_layer, "use_pass_environment")
  
-         if context.scene.cycles.feature_set == 'EXPERIMENTAL':
-             col.separator()
-             sub = col.column()
-             sub.active = cycles_view_layer.use_denoising
-             sub.prop(cycles_view_layer, "denoising_store_passes", text="Denoising")
          col = layout.column()
 -        col.prop(crl, "pass_debug_render_time")
 +        col.prop(cycles_view_layer, "pass_debug_render_time")
          if _cycles.with_cycles_debug:
 -            col.prop(crl, "pass_debug_bvh_traversed_nodes")
 -            col.prop(crl, "pass_debug_bvh_traversed_instances")
 -            col.prop(crl, "pass_debug_bvh_intersections")
 -            col.prop(crl, "pass_debug_ray_bounces")
 +            col.prop(cycles_view_layer, "pass_debug_bvh_traversed_nodes")
 +            col.prop(cycles_view_layer, "pass_debug_bvh_traversed_instances")
 +            col.prop(cycles_view_layer, "pass_debug_bvh_intersections")
 +            col.prop(cycles_view_layer, "pass_debug_ray_bounces")
  
 -        crl = rl.cycles
 -        layout.label("Cryptomatte:")
 +        layout.label(text="Cryptomatte:")
          row = layout.row(align=True)
 -        row.prop(crl, "use_pass_crypto_object", text="Object", toggle=True)
 -        row.prop(crl, "use_pass_crypto_material", text="Material", toggle=True)
 -        row.prop(crl, "use_pass_crypto_asset", text="Asset", toggle=True)
 +        row.prop(cycles_view_layer, "use_pass_crypto_object", text="Object", toggle=True)
 +        row.prop(cycles_view_layer, "use_pass_crypto_material", text="Material", toggle=True)
 +        row.prop(cycles_view_layer, "use_pass_crypto_asset", text="Asset", toggle=True)
          row = layout.row(align=True)
 -        row.prop(crl, "pass_crypto_depth")
 +        row.prop(cycles_view_layer, "pass_crypto_depth")
          row = layout.row(align=True)
          row.active = use_cpu(context)
 -        row.prop(crl, "pass_crypto_accurate", text="Accurate Mode")
 -
 -class CYCLES_RENDER_PT_views(CyclesButtonsPanel, Panel):
 -    bl_label = "Views"
 -    bl_context = "render_layer"
 -    bl_options = {'DEFAULT_CLOSED'}
 -
 -    def draw_header(self, context):
 -        rd = context.scene.render
 -        self.layout.prop(rd, "use_multiview", text="")
 -
 -    def draw(self, context):
 -        layout = self.layout
 -
 -        scene = context.scene
 -        rd = scene.render
 -        rv = rd.views.active
 -
 -        layout.active = rd.use_multiview
 -        basic_stereo = (rd.views_format == 'STEREO_3D')
 -
 -        row = layout.row()
 -        row.prop(rd, "views_format", expand=True)
 -
 -        if basic_stereo:
 -            row = layout.row()
 -            row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "stereo_views", rd.views, "active_index", rows=2)
 -
 -            row = layout.row()
 -            row.label(text="File Suffix:")
 -            row.prop(rv, "file_suffix", text="")
 -
 -        else:
 -            row = layout.row()
 -            row.template_list("RENDERLAYER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2)
 -
 -            col = row.column(align=True)
 -            col.operator("scene.render_view_add", icon='ZOOMIN', text="")
 -            col.operator("scene.render_view_remove", icon='ZOOMOUT', text="")
 -
 -            row = layout.row()
 -            row.label(text="Camera Suffix:")
 -            row.prop(rv, "camera_suffix", text="")
 +        row.prop(cycles_view_layer, "pass_crypto_accurate", text="Accurate Mode")
  
  
  class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel):
      bl_label = "Denoising"
 -    bl_context = "render_layer"
 +    bl_context = "view_layer"
      bl_options = {'DEFAULT_CLOSED'}
  
      def draw_header(self, context):
 -        rd = context.scene.render
 -        rl = rd.layers.active
 -        crl = rl.cycles
 -        cscene = context.scene.cycles
 +        scene = context.scene
 +        view_layer = context.view_layer
 +        cycles_view_layer = view_layer.cycles
 +        cscene = scene.cycles
          layout = self.layout
  
 -        layout.prop(crl, "use_denoising", text="")
 +        layout.prop(cycles_view_layer, "use_denoising", text="")
  
      def draw(self, context):
          layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
          scene = context.scene
          cscene = scene.cycles
 -        rd = scene.render
 -        rl = rd.layers.active
 -        crl = rl.cycles
 +        view_layer = context.view_layer
 +        cycles_view_layer = view_layer.cycles
  
-         layout.active = cycles_view_layer.use_denoising
-         col = layout.column()
-         sub = col.column()
-         sub.prop(cycles_view_layer, "denoising_radius", text="Radius")
-         sub.prop(cycles_view_layer, "denoising_strength", slider=True, text="Strength")
-         sub = col.column(align=True)
-         sub.prop(cycles_view_layer, "denoising_feature_strength", slider=True, text="Feature Strength")
-         sub.prop(cycles_view_layer, "denoising_relative_pca")
+         split = layout.split()
 -        split.active = crl.use_denoising
++        split.active = cycles_view_layer.use_denoising
  
- #        layout.use_property_split = False
 -        col = split.column()
 -        sub = col.column(align=True)
 -        sub.prop(crl, "denoising_radius", text="Radius")
 -        sub.prop(crl, "denoising_strength", slider=True, text="Strength")
 -
 -        col = split.column()
 -        sub = col.column(align=True)
 -        sub.prop(crl, "denoising_feature_strength", slider=True, text="Feature Strength")
 -        sub.prop(crl, "denoising_relative_pca")
++        layout = layout.column(align=True)
++        layout.prop(cycles_view_layer, "denoising_feature_strength", slider=True, text="Feature Strength")
++        layout.prop(cycles_view_layer, "denoising_relative_pca")
  
-         """
          layout.separator()
  
-         col = layout.column(align=True)
-         col.prop(cycles_view_layer, "denoising_diffuse_direct", text="Diffuse Direct")
-         col.prop(cycles_view_layer, "denoising_diffuse_indirect", text="Indirect")
-         col = layout.column(align=True)
-         col.prop(cycles_view_layer, "denoising_glossy_direct", text="Glossy Direct")
-         col.prop(cycles_view_layer, "denoising_glossy_indirect", text="Indirect")
-         col = layout.column(align=True)
-         col.prop(cycles_view_layer, "denoising_transmission_direct", text="Transmission Direct")
-         col.prop(cycles_view_layer, "denoising_transmission_indirect", text="Indirect")
-         col = layout.column(align=True)
-         col.prop(cycles_view_layer, "denoising_subsurface_direct", text="Subsurface Direct")
-         col.prop(cycles_view_layer, "denoising_subsurface_indirect", text="Indirect")
-         """
-         layout.use_property_split = False
-         split = layout.split(factor=0.5)
-         split.label(text="Diffuse")
-         col = split.column()
-         row = col.row(align=True)
 -        row = layout.row()
 -        row.active = crl.use_denoising or crl.denoising_store_passes
 -        row.label(text="Diffuse:")
 -        sub = row.row(align=True)
 -        sub.prop(crl, "denoising_diffuse_direct", text="Direct", toggle=True)
 -        sub.prop(crl, "denoising_diffuse_indirect", text="Indirect", toggle=True)
++        row = layout.row(align=True)
++        row.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
++        row.label(text="Diffuse")
++        row.use_property_split = False
 +        row.prop(cycles_view_layer, "denoising_diffuse_direct", text="Direct", toggle=True)
 +        row.prop(cycles_view_layer, "denoising_diffuse_indirect", text="Indirect", toggle=True)
  
-         split = layout.split(factor=0.5)
-         split.label(text="Glossy")
-         col = split.column()
-         row = col.row(align=True)
 -        row = layout.row()
 -        row.active = crl.use_denoising or crl.denoising_store_passes
 -        row.label(text="Glossy:")
 -        sub = row.row(align=True)
 -        sub.prop(crl, "denoising_glossy_direct", text="Direct", toggle=True)
 -        sub.prop(crl, "denoising_glossy_indirect", text="Indirect", toggle=True)
++        row = layout.row(align=True)
++        row.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
++        row.label(text="Glossy")
++        row.use_property_split = False
 +        row.prop(cycles_view_layer, "denoising_glossy_direct", text="Direct", toggle=True)
 +        row.prop(cycles_view_layer, "denoising_glossy_indirect", text="Indirect", toggle=True)
  
-         split = layout.split(factor=0.5)
-         split.label(text="Transmission")
-         col = split.column()
-         row = col.row(align=True)
 -        row = layout.row()
 -        row.active = crl.use_denoising or crl.denoising_store_passes
 -        row.label(text="Transmission:")
 -        sub = row.row(align=True)
 -        sub.prop(crl, "denoising_transmission_direct", text="Direct", toggle=True)
 -        sub.prop(crl, "denoising_transmission_indirect", text="Indirect", toggle=True)
++        row = layout.row(align=True)
++        row.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
++        row.label(text="Transmission")
++        row.use_property_split = False
 +        row.prop(cycles_view_layer, "denoising_transmission_direct", text="Direct", toggle=True)
 +        row.prop(cycles_view_layer, "denoising_transmission_indirect", text="Indirect", toggle=True)
  
-         split = layout.split(factor=0.5)
-         split.label(text="Subsurface")
-         col = split.column()
-         row = col.row(align=True)
 -        row = layout.row()
 -        row.active = crl.use_denoising or crl.denoising_store_passes
 -        row.label(text="Subsurface:")
 -        sub = row.row(align=True)
 -        sub.prop(crl, "denoising_subsurface_direct", text="Direct", toggle=True)
 -        sub.prop(crl, "denoising_subsurface_indirect", text="Indirect", toggle=True)
++        row = layout.row(align=True)
++        row.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
++        row.label(text="Subsurface")
++        row.use_property_split = False
 +        row.prop(cycles_view_layer, "denoising_subsurface_direct", text="Direct", toggle=True)
 +        row.prop(cycles_view_layer, "denoising_subsurface_indirect", text="Indirect", toggle=True)
  
  
  class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel):
  
      def draw(self, context):
          layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
          rd = context.scene.render
  
 -        split = layout.split()
 -
 -        col = split.column()
 +        col = layout.column(align=True)
          col.prop(rd, "use_compositing")
          col.prop(rd, "use_sequencer")
  
 -        col = split.column()
 -        col.prop(rd, "dither_intensity", text="Dither", slider=True)
 +        layout.prop(rd, "dither_intensity", text="Dither", slider=True)
  
  
  class CYCLES_CAMERA_PT_dof(CyclesButtonsPanel, Panel):
  
      def draw(self, context):
          layout = self.layout
 +        layout.use_property_split = True
  
          cam = context.camera
          ccam = cam.cycles
          split = layout.split()
  
          col = split.column()
 -        col.label("Focus:")
 -        col.prop(cam, "dof_object", text="")
 +        col.prop(cam, "dof_object", text="Focus Object")
  
          sub = col.row()
          sub.active = cam.dof_object is None
          sub.prop(cam, "dof_distance", text="Distance")
  
 -        hq_support = dof_options.is_hq_supported
 -        sub = col.column(align=True)
 -        sub.label("Viewport:")
 -        subhq = sub.column()
 -        subhq.active = hq_support
 -        subhq.prop(dof_options, "use_high_quality")
 -        sub.prop(dof_options, "fstop")
 -        if dof_options.use_high_quality and hq_support:
 -            sub.prop(dof_options, "blades")
  
 -        col = split.column()
 +class CYCLES_CAMERA_PT_dof_aperture(CyclesButtonsPanel, Panel):
 +    bl_label = "Aperture"
 +    bl_parent_id = "CYCLES_CAMERA_PT_dof"
  
 -        col.label("Aperture:")
 -        sub = col.column(align=True)
 -        sub.prop(ccam, "aperture_type", text="")
 +    @classmethod
 +    def poll(cls, context):
 +        return context.camera and CyclesButtonsPanel.poll(context)
 +
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
 +
 +        cam = context.camera
 +        ccam = cam.cycles
 +        dof_options = cam.gpu_dof
 +
 +        col = flow.column()
 +        col.prop(ccam, "aperture_type")
          if ccam.aperture_type == 'RADIUS':
 -            sub.prop(ccam, "aperture_size", text="Size")
 +            col.prop(ccam, "aperture_size", text="Size")
          elif ccam.aperture_type == 'FSTOP':
 -            sub.prop(ccam, "aperture_fstop", text="Number")
 +            col.prop(ccam, "aperture_fstop", text="Number")
 +        col.separator()
  
 -        sub = col.column(align=True)
 -        sub.prop(ccam, "aperture_blades", text="Blades")
 -        sub.prop(ccam, "aperture_rotation", text="Rotation")
 -        sub.prop(ccam, "aperture_ratio", text="Ratio")
 +        col = flow.column()
 +        col.prop(ccam, "aperture_blades", text="Blades")
 +        col.prop(ccam, "aperture_rotation", text="Rotation")
 +        col.prop(ccam, "aperture_ratio", text="Ratio")
 +
 +
 +class CYCLES_CAMERA_PT_dof_viewport(CyclesButtonsPanel, Panel):
 +    bl_label = "Viewport"
 +    bl_parent_id = "CYCLES_CAMERA_PT_dof"
 +
 +    @classmethod
 +    def poll(cls, context):
 +        return context.camera and CyclesButtonsPanel.poll(context)
 +
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
 +
 +        cam = context.camera
 +        dof_options = cam.gpu_dof
 +
 +        sub = flow.column(align=True)
 +        sub.prop(dof_options, "fstop")
 +        sub.prop(dof_options, "blades")
  
  
  class CYCLES_PT_context_material(CyclesButtonsPanel, Panel):
  
      @classmethod
      def poll(cls, context):
 -        return (context.material or context.object) and CyclesButtonsPanel.poll(context)
 +        if context.active_object and context.active_object.type == 'GPENCIL':
 +            return False
 +        else:
 +            return (context.material or context.object) and CyclesButtonsPanel.poll(context)
  
      def draw(self, context):
          layout = self.layout
              row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows)
  
              col = row.column(align=True)
 -            col.operator("object.material_slot_add", icon='ZOOMIN', text="")
 -            col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
 +            col.operator("object.material_slot_add", icon='ADD', text="")
 +            col.operator("object.material_slot_remove", icon='REMOVE', text="")
  
              col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
  
                  row.operator("object.material_slot_select", text="Select")
                  row.operator("object.material_slot_deselect", text="Deselect")
  
 -        split = layout.split(percentage=0.65)
 +        split = layout.split(factor=0.65)
  
          if ob:
              split.template_ID(ob, "active_material", new="material.new")
@@@ -1087,7 -822,7 +1057,7 @@@ class CYCLES_OBJECT_PT_motion_blur(Cycl
          if CyclesButtonsPanel.poll(context) and ob:
              if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'CAMERA'}:
                  return True
 -            if ob.dupli_type == 'GROUP' and ob.dupli_group:
 +            if ob.dupli_type == 'COLLECTION' and ob.dupli_group:
                  return True
              # TODO(sergey): More duplicator types here?
          return False
@@@ -1131,22 -866,11 +1101,22 @@@ class CYCLES_OBJECT_PT_cycles_settings(
      def poll(cls, context):
          ob = context.object
          return (CyclesButtonsPanel.poll(context) and
 -                ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LAMP'}) or
 -                        (ob.dupli_type == 'GROUP' and ob.dupli_group)))
 +                ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LIGHT'}) or
 +                        (ob.dupli_type == 'COLLECTION' and ob.dupli_group)))
 +
 +    def draw(self, context):
 +        pass
 +
 +
 +class CYCLES_OBJECT_PT_cycles_settings_ray_visibility(CyclesButtonsPanel, Panel):
 +    bl_label = "Ray Visibility"
 +    bl_parent_id = "CYCLES_OBJECT_PT_cycles_settings"
 +    bl_context = "object"
  
      def draw(self, context):
          layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
          scene = context.scene
          cscene = scene.cycles
          cob = ob.cycles
          visibility = ob.cycles_visibility
  
 -        layout.label(text="Ray Visibility:")
 -        flow = layout.column_flow()
 +        flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
  
 -        flow.prop(visibility, "camera")
 -        flow.prop(visibility, "diffuse")
 -        flow.prop(visibility, "glossy")
 -        flow.prop(visibility, "transmission")
 -        flow.prop(visibility, "scatter")
 +        col = flow.column()
 +        col.prop(visibility, "camera")
 +        col = flow.column()
 +        col.prop(visibility, "diffuse")
 +        col = flow.column()
 +        col.prop(visibility, "glossy")
 +        col = flow.column()
 +        col.prop(visibility, "transmission")
 +        col = flow.column()
 +        col.prop(visibility, "scatter")
  
 -        if ob.type != 'LAMP':
 -            flow.prop(visibility, "shadow")
 +        if ob.type != 'LIGHT':
 +            col = flow.column()
 +            col.prop(visibility, "shadow")
  
 -        row = layout.row()
 -        row.prop(cob, "is_shadow_catcher")
 -        row.prop(cob, "is_holdout")
 +        layout.separator()
  
 -        col = layout.column()
 -        col.label(text="Performance:")
 -        row = col.row()
 -        sub = row.row()
 -        sub.active = scene.render.use_simplify and cscene.use_camera_cull
 -        sub.prop(cob, "use_camera_cull")
 +        flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
 +
 +        col = flow.column()
 +        col.prop(cob, "is_shadow_catcher")
 +        col = flow.column()
 +        col.prop(cob, "is_holdout")
  
 -        sub = row.row()
 -        sub.active = scene.render.use_simplify and cscene.use_distance_cull
 -        sub.prop(cob, "use_distance_cull")
 +
 +class CYCLES_OBJECT_PT_cycles_settings_performance(CyclesButtonsPanel, Panel):
 +    bl_label = "Performance"
 +    bl_parent_id = "CYCLES_OBJECT_PT_cycles_settings"
 +    bl_context = "object"
 +
 +
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
 +
 +        scene = context.scene
 +        cscene = scene.cycles
 +        ob = context.object
 +        cob = ob.cycles
 +        visibility = ob.cycles_visibility
 +
 +        flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
 +
 +        col = flow.column()
 +        col.active = scene.render.use_simplify and cscene.use_camera_cull
 +        col.prop(cob, "use_camera_cull")
 +
 +        col = flow.column()
 +        col.active = scene.render.use_simplify and cscene.use_distance_cull
 +        col.prop(cob, "use_distance_cull")
  
  
  class CYCLES_OT_use_shading_nodes(Operator):
 -    """Enable nodes on a material, world or lamp"""
 +    """Enable nodes on a material, world or light"""
      bl_idname = "cycles.use_shading_nodes"
      bl_label = "Use Nodes"
  
      @classmethod
      def poll(cls, context):
          return (getattr(context, "material", False) or getattr(context, "world", False) or
 -                getattr(context, "lamp", False))
 +                getattr(context, "light", False))
  
      def execute(self, context):
          if context.material:
              context.material.use_nodes = True
          elif context.world:
              context.world.use_nodes = True
 -        elif context.lamp:
 -            context.lamp.use_nodes = True
 +        elif context.light:
 +            context.light.use_nodes = True
  
          return {'FINISHED'}
  
  
 -def find_node(material, nodetype):
 -    if material and material.node_tree:
 -        ntree = material.node_tree
 -
 -        active_output_node = None
 -        for node in ntree.nodes:
 -            if getattr(node, "type", None) == nodetype:
 -                if getattr(node, "is_active_output", True):
 -                    return node
 -                if not active_output_node:
 -                    active_output_node = node
 -        return active_output_node
 -
 -    return None
 -
 -
 -def find_node_input(node, name):
 -    for input in node.inputs:
 -        if input.name == name:
 -            return input
 -
 -    return None
 -
 -
  def panel_node_draw(layout, id_data, output_type, input_name):
      if not id_data.use_nodes:
          layout.operator("cycles.use_shading_nodes", icon='NODETREE')
  
      ntree = id_data.node_tree
  
 -    node = find_node(id_data, output_type)
 -    if not node:
 -        layout.label(text="No output node")
 -    else:
 +    node = ntree.get_output_node('CYCLES')
 +    if node:
          input = find_node_input(node, input_name)
 -        layout.template_node_view(ntree, node, input)
 +        if input:
 +            layout.template_node_view(ntree, node, input)
 +        else:
 +            layout.label(text="Incompatible output node")
 +    else:
 +        layout.label(text="No output node")
  
      return True
  
  
 -class CYCLES_LAMP_PT_preview(CyclesButtonsPanel, Panel):
 +class CYCLES_LIGHT_PT_preview(CyclesButtonsPanel, Panel):
      bl_label = "Preview"
      bl_context = "data"
      bl_options = {'DEFAULT_CLOSED'}
  
      @classmethod
      def poll(cls, context):
 -        return context.lamp and \
 -            not (context.lamp.type == 'AREA' and
 -                 context.lamp.cycles.is_portal) \
 -            and CyclesButtonsPanel.poll(context)
 +        return (
 +            context.light and
 +            not (
 +                context.light.type == 'AREA' and
 +                context.light.cycles.is_portal
 +            ) and
 +            CyclesButtonsPanel.poll(context)
 +        )
  
      def draw(self, context):
 -        self.layout.template_preview(context.lamp)
 +        self.layout.template_preview(context.light)
  
  
 -class CYCLES_LAMP_PT_lamp(CyclesButtonsPanel, Panel):
 -    bl_label = "Lamp"
 +class CYCLES_LIGHT_PT_light(CyclesButtonsPanel, Panel):
 +    bl_label = "Light"
      bl_context = "data"
  
      @classmethod
      def poll(cls, context):
 -        return context.lamp and CyclesButtonsPanel.poll(context)
 +        return context.light and CyclesButtonsPanel.poll(context)
  
      def draw(self, context):
          layout = self.layout
  
 -        lamp = context.lamp
 -        clamp = lamp.cycles
 +        light = context.light
 +        clamp = light.cycles
          # cscene = context.scene.cycles
  
 -        layout.prop(lamp, "type", expand=True)
 +        layout.prop(light, "type", expand=True)
  
 -        split = layout.split()
 -        col = split.column(align=True)
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
 +
 +        col = layout.column()
  
 -        if lamp.type in {'POINT', 'SUN', 'SPOT'}:
 -            col.prop(lamp, "shadow_soft_size", text="Size")
 -        elif lamp.type == 'AREA':
 -            col.prop(lamp, "shape", text="")
 +        if light.type in {'POINT', 'SUN', 'SPOT'}:
 +            col.prop(light, "shadow_soft_size", text="Size")
 +        elif light.type == 'AREA':
 +            col.prop(light, "shape", text="Shape")
              sub = col.column(align=True)
  
 -            if lamp.shape == 'SQUARE':
 -                sub.prop(lamp, "size")
 -            elif lamp.shape == 'RECTANGLE':
 -                sub.prop(lamp, "size", text="Size X")
 -                sub.prop(lamp, "size_y", text="Size Y")
 +            if light.shape in {'SQUARE', 'DISK'}:
 +                sub.prop(light, "size")
 +            elif light.shape in {'RECTANGLE', 'ELLIPSE'}:
 +                sub.prop(light, "size", text="Size X")
 +                sub.prop(light, "size_y", text="Y")
  
 -        if not (lamp.type == 'AREA' and clamp.is_portal):
 -            sub = col.column(align=True)
 +        if not (light.type == 'AREA' and clamp.is_portal):
 +            sub = col.column()
              if use_branched_path(context):
                  subsub = sub.row(align=True)
                  subsub.active = use_sample_all_lights(context)
                  subsub.prop(clamp, "samples")
              sub.prop(clamp, "max_bounces")
  
 -        col = split.column()
 -
          sub = col.column(align=True)
 -        sub.active = not (lamp.type == 'AREA' and clamp.is_portal)
 +        sub.active = not (light.type == 'AREA' and clamp.is_portal)
          sub.prop(clamp, "cast_shadow")
          sub.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance")
  
 -        if lamp.type == 'AREA':
 +        if light.type == 'AREA':
              col.prop(clamp, "is_portal", text="Portal")
  
 -        if lamp.type == 'HEMI':
 -            layout.label(text="Not supported, interpreted as sun lamp")
 +        if light.type == 'HEMI':
 +            layout.label(text="Not supported, interpreted as sun light")
  
  
 -class CYCLES_LAMP_PT_nodes(CyclesButtonsPanel, Panel):
 +class CYCLES_LIGHT_PT_nodes(CyclesButtonsPanel, Panel):
      bl_label = "Nodes"
      bl_context = "data"
  
      @classmethod
      def poll(cls, context):
 -        return context.lamp and not (context.lamp.type == 'AREA' and
 -                                     context.lamp.cycles.is_portal) and \
 +        return context.light and not (context.light.type == 'AREA' and
 +                                      context.light.cycles.is_portal) and \
              CyclesButtonsPanel.poll(context)
  
      def draw(self, context):
          layout = self.layout
  
 -        lamp = context.lamp
 -        if not panel_node_draw(layout, lamp, 'OUTPUT_LAMP', 'Surface'):
 -            layout.prop(lamp, "color")
 +        light = context.light
 +        if not panel_node_draw(layout, light, 'OUTPUT_LIGHT', 'Surface'):
 +            layout.prop(light, "color")
  
  
 -class CYCLES_LAMP_PT_spot(CyclesButtonsPanel, Panel):
 +class CYCLES_LIGHT_PT_spot(CyclesButtonsPanel, Panel):
      bl_label = "Spot Shape"
      bl_context = "data"
  
      @classmethod
      def poll(cls, context):
 -        lamp = context.lamp
 -        return (lamp and lamp.type == 'SPOT') and CyclesButtonsPanel.poll(context)
 +        light = context.light
 +        return (light and light.type == 'SPOT') and CyclesButtonsPanel.poll(context)
  
      def draw(self, context):
          layout = self.layout
 +        light = context.light
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
 -        lamp = context.lamp
 -
 -        split = layout.split()
 -
 -        col = split.column()
 -        sub = col.column()
 -        sub.prop(lamp, "spot_size", text="Size")
 -        sub.prop(lamp, "spot_blend", text="Blend", slider=True)
 -
 -        col = split.column()
 -        col.prop(lamp, "show_cone")
 +        col = layout.column()
 +        col.prop(light, "spot_size", text="Size")
 +        col.prop(light, "spot_blend", text="Blend", slider=True)
 +        col.prop(light, "show_cone")
  
  
  class CYCLES_WORLD_PT_preview(CyclesButtonsPanel, Panel):
@@@ -1390,7 -1108,7 +1360,7 @@@ class CYCLES_WORLD_PT_surface(CyclesBut
          world = context.world
  
          if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
 -            layout.prop(world, "horizon_color", text="Color")
 +            layout.prop(world, "color")
  
  
  class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel):
  class CYCLES_WORLD_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
      bl_label = "Ambient Occlusion"
      bl_context = "world"
 +    bl_options = {'DEFAULT_CLOSED'}
  
      @classmethod
      def poll(cls, context):
  
      def draw(self, context):
          layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
          light = context.world.light_settings
          scene = context.scene
  
 -        row = layout.row()
 -        sub = row.row()
 +        col = layout.column()
 +        sub = col.column()
          sub.active = light.use_ambient_occlusion or scene.render.use_simplify
          sub.prop(light, "ao_factor", text="Factor")
 -        row.prop(light, "distance", text="Distance")
 +        col.prop(light, "distance", text="Distance")
  
  
  class CYCLES_WORLD_PT_mist(CyclesButtonsPanel, Panel):
      def poll(cls, context):
          if CyclesButtonsPanel.poll(context):
              if context.world:
 -                for rl in context.scene.render.layers:
 -                    if rl.use_pass_mist:
 +                for view_layer in context.scene.view_layers:
 +                    if view_layer.use_pass_mist:
                          return True
  
          return False
@@@ -1500,71 -1215,35 +1470,71 @@@ class CYCLES_WORLD_PT_settings(CyclesBu
  
      def draw(self, context):
          layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
          world = context.world
          cworld = world.cycles
          # cscene = context.scene.cycles
  
 -        split = layout.split()
 +        col = layout.column()
  
 -        col = split.column()
  
 -        col.label(text="Surface:")
 +class CYCLES_WORLD_PT_settings_surface(CyclesButtonsPanel, Panel):
 +    bl_label = "Surface"
 +    bl_parent_id = "CYCLES_WORLD_PT_settings"
 +    bl_context = "world"
 +
 +    @classmethod
 +    def poll(cls, context):
 +        return context.world and CyclesButtonsPanel.poll(context)
 +
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
 +
 +        world = context.world
 +        cworld = world.cycles
 +
 +        col = layout.column()
          col.prop(cworld, "sampling_method", text="Sampling")
  
 -        sub = col.column(align=True)
 +        sub = col.column()
          sub.active = cworld.sampling_method != 'NONE'
          subsub = sub.row(align=True)
          subsub.active = cworld.sampling_method == 'MANUAL'
          subsub.prop(cworld, "sample_map_resolution")
          if use_branched_path(context):
 -            subsub = sub.row(align=True)
 +            subsub = sub.column(align=True)
              subsub.active = use_sample_all_lights(context)
              subsub.prop(cworld, "samples")
          sub.prop(cworld, "max_bounces")
  
 -        col = split.column()
 -        col.label(text="Volume:")
 +
 +class CYCLES_WORLD_PT_settings_volume(CyclesButtonsPanel, Panel):
 +    bl_label = "Volume"
 +    bl_parent_id = "CYCLES_WORLD_PT_settings"
 +    bl_context = "world"
 +
 +    @classmethod
 +    def poll(cls, context):
 +        return context.world and CyclesButtonsPanel.poll(context)
 +
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
 +
 +        world = context.world
 +        cworld = world.cycles
 +
 +        col = layout.column()
 +
          sub = col.column()
          sub.active = use_cpu(context)
 -        sub.prop(cworld, "volume_sampling", text="")
 -        col.prop(cworld, "volume_interpolation", text="")
 +        sub.prop(cworld, "volume_sampling", text="Sampling")
 +        col.prop(cworld, "volume_interpolation", text="Interpolation")
          col.prop(cworld, "homogeneous_volume", text="Homogeneous")
  
  
@@@ -1635,7 -1314,6 +1605,7 @@@ class CYCLES_MATERIAL_PT_displacement(C
  class CYCLES_MATERIAL_PT_settings(CyclesButtonsPanel, Panel):
      bl_label = "Settings"
      bl_context = "material"
 +    bl_options = {'DEFAULT_CLOSED'}
  
      @classmethod
      def poll(cls, context):
  
      def draw(self, context):
          layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
          mat = context.material
          cmat = mat.cycles
  
 -        split = layout.split()
 -        col = split.column()
 -        col.label(text="Surface:")
 -        col.prop(cmat, "sample_as_light", text="Multiple Importance")
 -        col.prop(cmat, "use_transparent_shadow")
 -
 -        col.separator()
 -        col.label(text="Geometry:")
 -        col.prop(cmat, "displacement_method", text="")
 -
 -        col = split.column()
 -        col.label(text="Volume:")
 -        sub = col.column()
 -        sub.active = use_cpu(context)
 -        sub.prop(cmat, "volume_sampling", text="")
 -        col.prop(cmat, "volume_interpolation", text="")
 -        col.prop(cmat, "homogeneous_volume", text="Homogeneous")
 -
 -        col.separator()
 -        col.prop(mat, "pass_index")
 +        layout.prop(mat, "pass_index")
  
  
 -class CYCLES_MATERIAL_PT_viewport(CyclesButtonsPanel, Panel):
 -    bl_label = "Viewport"
 +class CYCLES_MATERIAL_PT_settings_surface(CyclesButtonsPanel, Panel):
 +    bl_label = "Surface"
 +    bl_parent_id = "CYCLES_MATERIAL_PT_settings"
      bl_context = "material"
 -    bl_options = {'DEFAULT_CLOSED'}
  
      @classmethod
      def poll(cls, context):
          return context.material and CyclesButtonsPanel.poll(context)
  
 -    def draw(self, context):
 -        mat = context.material
 -
 -        layout = self.layout
 -        split = layout.split()
 -
 -        col = split.column(align=True)
 -        col.label("Color:")
 -        col.prop(mat, "diffuse_color", text="")
 -        col.prop(mat, "alpha")
 -
 -        col.separator()
 -        col.label("Alpha:")
 -        col.prop(mat.game_settings, "alpha_blend", text="")
 -
 -        col = split.column(align=True)
 -        col.label("Specular:")
 -        col.prop(mat, "specular_color", text="")
 -        col.prop(mat, "specular_hardness", text="Hardness")
 -
 -
 -class CYCLES_TEXTURE_PT_context(CyclesButtonsPanel, Panel):
 -    bl_label = ""
 -    bl_context = "texture"
 -    bl_options = {'HIDE_HEADER'}
 -    COMPAT_ENGINES = {'CYCLES'}
 -
 -    def draw(self, context):
 -        layout = self.layout
 -
 -        tex = context.texture
 -        space = context.space_data
 -        pin_id = space.pin_id
 -        use_pin_id = space.use_pin_id
 -        user = context.texture_user
 -
 -        space.use_limited_texture_context = False
 -
 -        if not (use_pin_id and isinstance(pin_id, bpy.types.Texture)):
 -            pin_id = None
 -
 -        if not pin_id:
 -            layout.template_texture_user()
 -
 -        if user or pin_id:
 -            layout.separator()
 -
 -            split = layout.split(percentage=0.65)
 -            col = split.column()
 -
 -            if pin_id:
 -                col.template_ID(space, "pin_id")
 -            else:
 -                propname = context.texture_user_property.identifier
 -                col.template_ID(user, propname, new="texture.new")
 -
 -            if tex:
 -                split = layout.split(percentage=0.2)
 -                split.label(text="Type:")
 -                split.prop(tex, "type", text="")
 -
 -
 -class CYCLES_TEXTURE_PT_node(CyclesButtonsPanel, Panel):
 -    bl_label = "Node"
 -    bl_context = "texture"
 -
 -    @classmethod
 -    def poll(cls, context):
 -        node = context.texture_node
 -        return node and CyclesButtonsPanel.poll(context)
 -
 -    def draw(self, context):
 -        layout = self.layout
 -
 -        node = context.texture_node
 -        ntree = node.id_data
 -        layout.template_node_view(ntree, node, None)
 -
 -
 -class CYCLES_TEXTURE_PT_mapping(CyclesButtonsPanel, Panel):
 -    bl_label = "Mapping"
 -    bl_context = "texture"
 -
 -    @classmethod
 -    def poll(cls, context):
 -        node = context.texture_node
 -        # TODO(sergey): perform a faster/nicer check?
 -        return node and hasattr(node, 'texture_mapping') and CyclesButtonsPanel.poll(context)
 -
 -    def draw(self, context):
 -        layout = self.layout
 -
 -        node = context.texture_node
 -
 -        mapping = node.texture_mapping
 -
 -        layout.prop(mapping, "vector_type", expand=True)
 -
 -        row = layout.row()
 -
 -        row.column().prop(mapping, "translation")
 -        row.column().prop(mapping, "rotation")
 -        row.column().prop(mapping, "scale")
 -
 -        layout.label(text="Projection:")
 -
 -        row = layout.row()
 -        row.prop(mapping, "mapping_x", text="")
 -        row.prop(mapping, "mapping_y", text="")
 -        row.prop(mapping, "mapping_z", text="")
 -
 -
 -class CYCLES_TEXTURE_PT_colors(CyclesButtonsPanel, Panel):
 -    bl_label = "Color"
 -    bl_context = "texture"
 -    bl_options = {'DEFAULT_CLOSED'}
 -
 -    @classmethod
 -    def poll(cls, context):
 -        # node = context.texture_node
 -        return False
 -        # return node and CyclesButtonsPanel.poll(context)
 -
      def draw(self, context):
          layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
 -        node = context.texture_node
 -
 -        mapping = node.color_mapping
 -
 -        split = layout.split()
 -
 -        col = split.column()
 -        col.label(text="Blend:")
 -        col.prop(mapping, "blend_type", text="")
 -        col.prop(mapping, "blend_factor", text="Factor")
 -        col.prop(mapping, "blend_color", text="")
 -
 -        col = split.column()
 -        col.label(text="Adjust:")
 -        col.prop(mapping, "brightness")
 -        col.prop(mapping, "contrast")
 -        col.prop(mapping, "saturation")
 -
 -        layout.separator()
 +        mat = context.material
 +        cmat = mat.cycles
  
 -        layout.prop(mapping, "use_color_ramp", text="Ramp")
 -        if mapping.use_color_ramp:
 -            layout.template_color_ramp(mapping, "color_ramp", expand=True)
 +        col = layout.column()
 +        col.prop(cmat, "sample_as_light", text="Multiple Importance")
 +        col.prop(cmat, "use_transparent_shadow")
 +        col.prop(cmat, "displacement_method", text="Displacement Method")
  
  
 -class CYCLES_PARTICLE_PT_textures(CyclesButtonsPanel, Panel):
 -    bl_label = "Textures"
 -    bl_context = "particle"
 -    bl_options = {'DEFAULT_CLOSED'}
 +class CYCLES_MATERIAL_PT_settings_volume(CyclesButtonsPanel, Panel):
 +    bl_label = "Volume"
 +    bl_parent_id = "CYCLES_MATERIAL_PT_settings"
 +    bl_context = "material"
  
      @classmethod
      def poll(cls, context):
 -        psys = context.particle_system
 -        return psys and CyclesButtonsPanel.poll(context)
 +        return context.material and CyclesButtonsPanel.poll(context)
  
      def draw(self, context):
          layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
 -        psys = context.particle_system
 -        part = psys.settings
 -
 -        row = layout.row()
 -        row.template_list("TEXTURE_UL_texslots", "", part, "texture_slots", part, "active_texture_index", rows=2)
 -
 -        col = row.column(align=True)
 -        col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
 -        col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
 -        col.menu("TEXTURE_MT_specials", icon='DOWNARROW_HLT', text="")
 +        mat = context.material
 +        cmat = mat.cycles
  
 -        if not part.active_texture:
 -            layout.template_ID(part, "active_texture", new="texture.new")
 -        else:
 -            slot = part.texture_slots[part.active_texture_index]
 -            layout.template_ID(slot, "texture", new="texture.new")
 +        col = layout.column()
 +        sub = col.column()
 +        sub.active = use_cpu(context)
 +        sub.prop(cmat, "volume_sampling", text="Sampling")
 +        col.prop(cmat, "volume_interpolation", text="Interpolation")
 +        col.prop(cmat, "homogeneous_volume", text="Homogeneous")
  
  
  class CYCLES_RENDER_PT_bake(CyclesButtonsPanel, Panel):
  
      def draw(self, context):
          layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False  # No animation.
  
          scene = context.scene
          cscene = scene.cycles
          cbk = scene.render.bake
 -
 -        layout.operator("object.bake", icon='RENDER_STILL').type = cscene.bake_type
 -
 -        col = layout.column()
 -        col.prop(cscene, "bake_type")
 +        rd = scene.render
  
          col = layout.column()
 +        col.prop(rd, "use_bake_multires")
 +        if rd.use_bake_multires:
 +            col.prop(rd, "bake_type")
  
 -        if cscene.bake_type == 'NORMAL':
 -            col.prop(cbk, "normal_space", text="Space")
 -
 -            row = col.row(align=True)
 -            row.label(text="Swizzle:")
 -            row.prop(cbk, "normal_r", text="")
 -            row.prop(cbk, "normal_g", text="")
 -            row.prop(cbk, "normal_b", text="")
 +            col = layout.column()
 +            col.prop(rd, "bake_margin")
 +            col.prop(rd, "use_bake_clear")
  
 -        elif cscene.bake_type == 'COMBINED':
 -            row = col.row(align=True)
 -            row.prop(cbk, "use_pass_direct", toggle=True)
 -            row.prop(cbk, "use_pass_indirect", toggle=True)
 +            if rd.bake_type == 'DISPLACEMENT':
 +                col.prop(rd, "use_bake_lores_mesh")
  
 -            split = col.split()
 -            split.active = cbk.use_pass_direct or cbk.use_pass_indirect
 +            col.operator("object.bake_image", icon='RENDER_STILL')
  
 -            col = split.column()
 -            col.prop(cbk, "use_pass_diffuse")
 -            col.prop(cbk, "use_pass_glossy")
 -            col.prop(cbk, "use_pass_transmission")
 +        else:
 +            col.prop(cscene, "bake_type")
 +
 +            col = layout.column()
 +
 +            if cscene.bake_type == 'NORMAL':
 +                col.prop(cbk, "normal_space", text="Space")
 +
 +                sub = col.column(align=True)
 +                sub.prop(cbk, "normal_r", text="Swizzle R")
 +                sub.prop(cbk, "normal_g", text="G")
 +                sub.prop(cbk, "normal_b", text="B")
 +
 +            elif cscene.bake_type == 'COMBINED':
 +                row = col.row(align=True)
 +                row.use_property_split = False
 +                row.prop(cbk, "use_pass_direct", toggle=True)
 +                row.prop(cbk, "use_pass_indirect", toggle=True)
 +
 +                col = col.column()
 +                col.active = cbk.use_pass_direct or cbk.use_pass_indirect
 +                col.prop(cbk, "use_pass_diffuse")
 +                col.prop(cbk, "use_pass_glossy")
 +                col.prop(cbk, "use_pass_transmission")
 +                col.prop(cbk, "use_pass_subsurface")
 +                col.prop(cbk, "use_pass_ambient_occlusion")
 +                col.prop(cbk, "use_pass_emit")
 +
 +            elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION', 'SUBSURFACE'}:
 +                row = col.row(align=True)
 +                row.use_property_split = False
 +                row.prop(cbk, "use_pass_direct", toggle=True)
 +                row.prop(cbk, "use_pass_indirect", toggle=True)
 +                row.prop(cbk, "use_pass_color", toggle=True)
  
 -            col = split.column()
 -            col.prop(cbk, "use_pass_subsurface")
 -            col.prop(cbk, "use_pass_ambient_occlusion")
 -            col.prop(cbk, "use_pass_emit")
 +            layout.separator()
  
 -        elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION', 'SUBSURFACE'}:
 -            row = col.row(align=True)
 -            row.prop(cbk, "use_pass_direct", toggle=True)
 -            row.prop(cbk, "use_pass_indirect", toggle=True)
 -            row.prop(cbk, "use_pass_color", toggle=True)
 +            col = layout.column()
 +            col.prop(cbk, "margin")
 +            col.prop(cbk, "use_clear", text="Clear Image")
  
 -        layout.separator()
 +            col.separator()
  
 -        split = layout.split()
 +            col.prop(cbk, "use_selected_to_active")
 +            sub = col.column()
 +            sub.active = cbk.use_selected_to_active
 +            sub.prop(cbk, "use_cage", text="Cage")
 +            if cbk.use_cage:
 +                sub.prop(cbk, "cage_extrusion", text="Extrusion")
 +                sub.prop_search(cbk, "cage_object", scene, "objects", text="Cage Object")
 +            else:
 +                sub.prop(cbk, "cage_extrusion", text="Ray Distance")
  
 -        col = split.column()
 -        col.prop(cbk, "margin")
 -        col.prop(cbk, "use_clear")
 +            layout.separator()
  
 -        col = split.column()
 -        col.prop(cbk, "use_selected_to_active")
 -        sub = col.column()
 -        sub.active = cbk.use_selected_to_active
 -        sub.prop(cbk, "use_cage", text="Cage")
 -        if cbk.use_cage:
 -            sub.prop(cbk, "cage_extrusion", text="Extrusion")
 -            sub.prop_search(cbk, "cage_object", scene, "objects", text="")
 -        else:
 -            sub.prop(cbk, "cage_extrusion", text="Ray Distance")
 +            layout.operator("object.bake", icon='RENDER_STILL').type = cscene.bake_type
  
  
  class CYCLES_RENDER_PT_debug(CyclesButtonsPanel, Panel):
  
          col = layout.column()
  
 -        col.label('CPU Flags:')
 +        col.label(text="CPU Flags:")
          row = col.row(align=True)
          row.prop(cscene, "debug_use_cpu_sse2", toggle=True)
          row.prop(cscene, "debug_use_cpu_sse3", toggle=True)
          col.separator()
  
          col = layout.column()
 -        col.label('CUDA Flags:')
 +        col.label(text="CUDA Flags:")
          col.prop(cscene, "debug_use_cuda_adaptive_compile")
          col.prop(cscene, "debug_use_cuda_split_kernel")
  
          col.separator()
  
          col = layout.column()
 -        col.label('OpenCL Flags:')
 +        col.label(text="OpenCL Flags:")
          col.prop(cscene, "debug_opencl_kernel_type", text="Kernel")
          col.prop(cscene, "debug_opencl_device_type", text="Device")
          col.prop(cscene, "debug_opencl_kernel_single_program", text="Single Program")
          col.prop(cscene, "debug_bvh_type")
  
  
 -class CYCLES_PARTICLE_PT_curve_settings(CyclesButtonsPanel, Panel):
 -    bl_label = "Cycles Hair Settings"
 -    bl_context = "particle"
 +class CYCLES_SCENE_PT_simplify(CyclesButtonsPanel, Panel):
 +    bl_label = "Simplify"
 +    bl_context = "scene"
 +    bl_options = {'DEFAULT_CLOSED'}
 +    COMPAT_ENGINES = {'CYCLES'}
  
 -    @classmethod
 -    def poll(cls, context):
 -        scene = context.scene
 -        ccscene = scene.cycles_curves
 -        psys = context.particle_system
 -        use_curves = ccscene.use_curves and psys
 -        return CyclesButtonsPanel.poll(context) and use_curves and psys.settings.type == 'HAIR'
 +    def draw_header(self, context):
 +        rd = context.scene.render
 +        self.layout.prop(rd, "use_simplify", text="")
  
      def draw(self, context):
 -        layout = self.layout
 +        pass
  
 -        psys = context.particle_settings
 -        cpsys = psys.cycles
  
 -        row = layout.row()
 -        row.prop(cpsys, "shape", text="Shape")
 +class CYCLES_SCENE_PT_simplify_viewport(CyclesButtonsPanel, Panel):
 +    bl_label = "Viewport"
 +    bl_context = "scene"
 +    bl_parent_id = "CYCLES_SCENE_PT_simplify"
 +    COMPAT_ENGINES = {'CYCLES'}
  
 -        layout.label(text="Thickness:")
 -        row = layout.row()
 -        row.prop(cpsys, "root_width", text="Root")
 -        row.prop(cpsys, "tip_width", text="Tip")
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
 -        row = layout.row()
 -        row.prop(cpsys, "radius_scale", text="Scaling")
 -        row.prop(cpsys, "use_closetip", text="Close tip")
 +        scene = context.scene
 +        rd = scene.render
 +        cscene = scene.cycles
  
 +        layout.active = rd.use_simplify
  
 -class CYCLES_SCENE_PT_simplify(CyclesButtonsPanel, Panel):
 -    bl_label = "Simplify"
 +        col = layout.column()
 +        col.prop(rd, "simplify_subdivision", text="Max Subdivision")
 +        col.prop(rd, "simplify_child_particles", text="Child Particles")
 +        col.prop(cscene, "texture_limit", text="Texture Limit")
 +        col.prop(cscene, "ao_bounces", text="AO Bounces")
 +
 +
 +class CYCLES_SCENE_PT_simplify_render(CyclesButtonsPanel, Panel):
 +    bl_label = "Render"
      bl_context = "scene"
 +    bl_parent_id = "CYCLES_SCENE_PT_simplify"
      COMPAT_ENGINES = {'CYCLES'}
  
 -    def draw_header(self, context):
 -        rd = context.scene.render
 -        self.layout.prop(rd, "use_simplify", text="")
 -
      def draw(self, context):
          layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
          scene = context.scene
          rd = scene.render
  
          layout.active = rd.use_simplify
  
 -        col = layout.column(align=True)
 -        col.label(text="Subdivision")
 -        row = col.row(align=True)
 -        row.prop(rd, "simplify_subdivision", text="Viewport")
 -        row.prop(rd, "simplify_subdivision_render", text="Render")
 +        col = layout.column()
  
 -        col = layout.column(align=True)
 -        col.label(text="Child Particles")
 -        row = col.row(align=True)
 -        row.prop(rd, "simplify_child_particles", text="Viewport")
 -        row.prop(rd, "simplify_child_particles_render", text="Render")
 +        col.prop(rd, "simplify_subdivision_render", text="Max Subdivision")
 +        col.prop(rd, "simplify_child_particles_render", text="Child Particles")
 +        col.prop(cscene, "texture_limit_render", text="Texture Limit")
 +        col.prop(cscene, "ao_bounces_render", text="AO Bounces")
  
 -        col = layout.column(align=True)
 -        split = col.split()
 -        sub = split.column()
 -        sub.label(text="Texture Limit Viewport")
 -        sub.prop(cscene, "texture_limit", text="")
 -        sub = split.column()
 -        sub.label(text="Texture Limit Render")
 -        sub.prop(cscene, "texture_limit_render", text="")
  
 -        split = layout.split()
 -        col = split.column()
 -        col.prop(cscene, "use_camera_cull")
 -        row = col.row()
 -        row.active = cscene.use_camera_cull
 -        row.prop(cscene, "camera_cull_margin")
 +class CYCLES_SCENE_PT_simplify_culling(CyclesButtonsPanel, Panel):
 +    bl_label = "Culling"
 +    bl_context = "scene"
 +    bl_parent_id = "CYCLES_SCENE_PT_simplify"
 +    bl_options = {'DEFAULT_CLOSED'}
 +    COMPAT_ENGINES = {'CYCLES'}
  
 -        col = split.column()
 -        col.prop(cscene, "use_distance_cull")
 -        row = col.row()
 -        row.active = cscene.use_distance_cull
 -        row.prop(cscene, "distance_cull_margin", text="Distance")
 +    def draw(self, context):
 +        layout = self.layout
 +        layout.use_property_split = True
 +        layout.use_property_decorate = False
  
 -        split = layout.split()
 -        col = split.column()
 -        col.prop(cscene, "ao_bounces")
 +        scene = context.scene
 +        rd = scene.render
 +        cscene = scene.cycles
  
 -        col = split.column()
 -        col.prop(cscene, "ao_bounces_render")
 +        layout.active = rd.use_simplify
 +
 +        col = layout.column()
 +        col.prop(cscene, "use_camera_cull")
 +        sub = col.column()
 +        sub.active = cscene.use_camera_cull
 +        sub.prop(cscene, "camera_cull_margin")
 +
 +        col = layout.column()
 +        col.prop(cscene, "use_distance_cull")
 +        sub = col.column()
 +        sub.active = cscene.use_distance_cull
 +        sub.prop(cscene, "distance_cull_margin", text="Distance")
  
  
  def draw_device(self, context):
      scene = context.scene
      layout = self.layout
 +    layout.use_property_split = True
 +    layout.use_property_decorate = False
  
 -    if scene.render.engine == 'CYCLES':
 +    if context.engine == 'CYCLES':
          from . import engine
          cscene = scene.cycles
  
 -        layout.prop(cscene, "feature_set")
 -
 -        split = layout.split(percentage=1 / 3)
 -        split.label("Device:")
 -        row = split.row()
 -        row.active = show_device_active(context)
 -        row.prop(cscene, "device", text="")
 -
 -        if engine.with_osl() and use_cpu(context):
 -            layout.prop(cscene, "shading_system")
 +        col = layout.column()
 +        col.prop(cscene, "feature_set")
  
  
  def draw_pause(self, context):
      layout = self.layout
      scene = context.scene
  
 -    if scene.render.engine == "CYCLES":
 +    if context.engine == "CYCLES":
          view = context.space_data
  
 -        if view.viewport_shade == 'RENDERED':
 +        if view.shading.type == 'RENDERED':
              cscene = scene.cycles
 -            layername = scene.render.layers.active.name
 -            layout.prop(cscene, "preview_pause", icon="PAUSE", text="")
 -            layout.prop(cscene, "preview_active_layer", icon="RENDERLAYERS", text=layername)
 +            layout.prop(cscene, "preview_pause", icon='PAUSE', text="")
  
  
  def get_panels():
          'DATA_PT_area',
          'DATA_PT_camera_dof',
          'DATA_PT_falloff_curve',
 -        'DATA_PT_lamp',
 +        'DATA_PT_light',
          'DATA_PT_preview',
 -        'DATA_PT_shadow',
          'DATA_PT_spot',
 -        'DATA_PT_sunsky',
          'MATERIAL_PT_context_material',
 -        'MATERIAL_PT_diffuse',
 -        'MATERIAL_PT_flare',
 -        'MATERIAL_PT_halo',
 -        'MATERIAL_PT_mirror',
 -        'MATERIAL_PT_options',
 -        'MATERIAL_PT_pipeline',
          'MATERIAL_PT_preview',
 -        'MATERIAL_PT_shading',
 -        'MATERIAL_PT_shadow',
 -        'MATERIAL_PT_specular',
 -        'MATERIAL_PT_sss',
 -        'MATERIAL_PT_strand',
 -        'MATERIAL_PT_transp',
 -        'MATERIAL_PT_volume_density',
 -        'MATERIAL_PT_volume_integration',
 -        'MATERIAL_PT_volume_lighting',
 -        'MATERIAL_PT_volume_options',
 -        'MATERIAL_PT_volume_shading',
 -        'MATERIAL_PT_volume_transp',
 -        'RENDERLAYER_PT_layer_options',
 -        'RENDERLAYER_PT_layer_passes',
 -        'RENDERLAYER_PT_views',
 -        'RENDER_PT_antialiasing',
 -        'RENDER_PT_bake',
 -        'RENDER_PT_motion_blur',
 -        'RENDER_PT_performance',
 +        'VIEWLAYER_PT_filter',
 +        'VIEWLAYER_PT_layer_passes',
          'RENDER_PT_post_processing',
 -        'RENDER_PT_shading',
          'SCENE_PT_simplify',
 -        'TEXTURE_PT_context_texture',
 -        'WORLD_PT_ambient_occlusion',
 -        'WORLD_PT_environment_lighting',
 -        'WORLD_PT_gather',
 -        'WORLD_PT_indirect_lighting',
 -        'WORLD_PT_mist',
 -        'WORLD_PT_preview',
 -        'WORLD_PT_world'
      }
  
      panels = []
  
  
  classes = (
 -    CYCLES_MT_sampling_presets,
 -    CYCLES_MT_integrator_presets,
 +    CYCLES_PT_sampling_presets,
 +    CYCLES_PT_integrator_presets,
      CYCLES_RENDER_PT_sampling,
 +    CYCLES_RENDER_PT_sampling_light,
 +    CYCLES_RENDER_PT_sampling_sub_samples,
 +    CYCLES_RENDER_PT_sampling_advanced,
      CYCLES_RENDER_PT_geometry,
 +    CYCLES_RENDER_PT_geometry_subdivision,
 +    CYCLES_RENDER_PT_geometry_volume,
 +    CYCLES_RENDER_PT_geometry_hair,
      CYCLES_RENDER_PT_light_paths,
 +    CYCLES_RENDER_PT_light_paths_max_bounces,
 +    CYCLES_RENDER_PT_light_paths_caustics,
      CYCLES_RENDER_PT_motion_blur,
 +    CYCLES_RENDER_PT_motion_blur_curve,
      CYCLES_RENDER_PT_film,
 +    CYCLES_RENDER_PT_film_transparency,
 +    CYCLES_RENDER_PT_film_pixel_filter,
      CYCLES_RENDER_PT_performance,
 -    CYCLES_RENDER_PT_layer_options,
 +    CYCLES_RENDER_PT_performance_threads,
 +    CYCLES_RENDER_PT_performance_tiles,
 +    CYCLES_RENDER_PT_performance_acceleration_structure,
 +    CYCLES_RENDER_PT_performance_final_render,
 +    CYCLES_RENDER_PT_performance_viewport,
 +    CYCLES_RENDER_PT_filter,
      CYCLES_RENDER_PT_layer_passes,
 -    CYCLES_RENDER_PT_views,
      CYCLES_RENDER_PT_denoising,
      CYCLES_PT_post_processing,
      CYCLES_CAMERA_PT_dof,
 +    CYCLES_CAMERA_PT_dof_aperture,
 +    CYCLES_CAMERA_PT_dof_viewport,
      CYCLES_PT_context_material,
      CYCLES_OBJECT_PT_motion_blur,
      CYCLES_OBJECT_PT_cycles_settings,
 +    CYCLES_OBJECT_PT_cycles_settings_ray_visibility,
 +    CYCLES_OBJECT_PT_cycles_settings_performance,
      CYCLES_OT_use_shading_nodes,
 -    CYCLES_LAMP_PT_preview,
 -    CYCLES_LAMP_PT_lamp,
 -    CYCLES_LAMP_PT_nodes,
 -    CYCLES_LAMP_PT_spot,
 +    CYCLES_LIGHT_PT_preview,
 +    CYCLES_LIGHT_PT_light,
 +    CYCLES_LIGHT_PT_nodes,
 +    CYCLES_LIGHT_PT_spot,
      CYCLES_WORLD_PT_preview,
      CYCLES_WORLD_PT_surface,
      CYCLES_WORLD_PT_volume,
      CYCLES_WORLD_PT_mist,
      CYCLES_WORLD_PT_ray_visibility,
      CYCLES_WORLD_PT_settings,
 +    CYCLES_WORLD_PT_settings_surface,
 +    CYCLES_WORLD_PT_settings_volume,
      CYCLES_MATERIAL_PT_preview,
      CYCLES_MATERIAL_PT_surface,
      CYCLES_MATERIAL_PT_volume,
      CYCLES_MATERIAL_PT_displacement,
      CYCLES_MATERIAL_PT_settings,
 -    CYCLES_MATERIAL_PT_viewport,
 -    CYCLES_TEXTURE_PT_context,
 -    CYCLES_TEXTURE_PT_node,
 -    CYCLES_TEXTURE_PT_mapping,
 -    CYCLES_TEXTURE_PT_colors,
 -    CYCLES_PARTICLE_PT_textures,
 +    CYCLES_MATERIAL_PT_settings_surface,
 +    CYCLES_MATERIAL_PT_settings_volume,
      CYCLES_RENDER_PT_bake,
      CYCLES_RENDER_PT_debug,
 -    CYCLES_PARTICLE_PT_curve_settings,
      CYCLES_SCENE_PT_simplify,
 +    CYCLES_SCENE_PT_simplify_viewport,
 +    CYCLES_SCENE_PT_simplify_render,
 +    CYCLES_SCENE_PT_simplify_culling,
  )
  
  
  def register():
      from bpy.utils import register_class
  
 -    bpy.types.RENDER_PT_render.append(draw_device)
 +    bpy.types.RENDER_PT_context.append(draw_device)
      bpy.types.VIEW3D_HT_header.append(draw_pause)
  
      for panel in get_panels():
  def unregister():
      from bpy.utils import unregister_class
  
 -    bpy.types.RENDER_PT_render.remove(draw_device)
 +    bpy.types.RENDER_PT_context.remove(draw_device)
      bpy.types.VIEW3D_HT_header.remove(draw_pause)
  
      for panel in get_panels():
index 1ff15284bc1ae7c2f094a94e7e4474c447b18c60,e05351eea40e82eb3d642ac0512d05cb87e34547..22a64df0c846a7d7b0a694763df4390c44b3b4fe
@@@ -54,23 -54,21 +54,23 @@@ bool BlenderSession::print_render_stat
  BlenderSession::BlenderSession(BL::RenderEngine& b_engine,
                                 BL::UserPreferences& b_userpref,
                                 BL::BlendData& b_data,
 -                               BL::Scene& b_scene)
 -: b_engine(b_engine),
 +                               bool preview_osl)
 +: session(NULL),
 +  sync(NULL),
 +  b_engine(b_engine),
    b_userpref(b_userpref),
    b_data(b_data),
    b_render(b_engine.render()),
 -  b_scene(b_scene),
 +  b_depsgraph(PointerRNA_NULL),
 +  b_scene(PointerRNA_NULL),
    b_v3d(PointerRNA_NULL),
    b_rv3d(PointerRNA_NULL),
 +  width(0),
 +  height(0),
 +  preview_osl(preview_osl),
    python_thread_state(NULL)
  {
        /* offline render */
 -
 -      width = render_resolution_x(b_render);
 -      height = render_resolution_y(b_render);
 -
        background = true;
        last_redraw_time = 0.0;
        start_resize_time = 0.0;
  BlenderSession::BlenderSession(BL::RenderEngine& b_engine,
                                 BL::UserPreferences& b_userpref,
                                 BL::BlendData& b_data,
 -                               BL::Scene& b_scene,
                                 BL::SpaceView3D& b_v3d,
                                 BL::RegionView3D& b_rv3d,
                                 int width, int height)
 -: b_engine(b_engine),
 +: session(NULL),
 +  sync(NULL),
 +  b_engine(b_engine),
    b_userpref(b_userpref),
    b_data(b_data),
 -  b_render(b_scene.render()),
 -  b_scene(b_scene),
 +  b_render(b_engine.render()),
 +  b_depsgraph(PointerRNA_NULL),
 +  b_scene(PointerRNA_NULL),
    b_v3d(b_v3d),
    b_rv3d(b_rv3d),
    width(width),
    height(height),
 +  preview_osl(false),
    python_thread_state(NULL)
  {
        /* 3d view render */
 -
        background = false;
        last_redraw_time = 0.0;
        start_resize_time = 0.0;
@@@ -147,19 -143,26 +147,19 @@@ void BlenderSession::create_session(
  
        session->scene = scene;
  
 +      /* There is no single depsgraph to use for the entire render.
 +       * So we need to handle this differently.
 +       *
 +       * We could loop over the final render result render layers in pipeline and keep Cycles unaware of multiple layers,
 +       * or perhaps move syncing further down in the pipeline.
 +       */
        /* create sync */
        sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
        BL::Object b_camera_override(b_engine.camera_override());
        if(b_v3d) {
 -              if(session_pause == false) {
 -                      /* full data sync */
 -                      sync->sync_view(b_v3d, b_rv3d, width, height);
 -                      sync->sync_data(b_render,
 -                                      b_v3d,
 -                                      b_camera_override,
 -                                      width, height,
 -                                      &python_thread_state,
 -                                      b_rlay_name.c_str());
 -              }
 +              sync->sync_view(b_v3d, b_rv3d, width, height);
        }
        else {
 -              /* for final render we will do full data sync per render layer, only
 -               * do some basic syncing here, no objects or materials for speed */
 -              sync->sync_render_layers(b_v3d, NULL);
 -              sync->sync_integrator();
                sync->sync_camera(b_render, b_camera_override, width, height, "");
        }
  
        update_resumable_tile_manager(session_params.samples);
  }
  
 -void BlenderSession::reset_session(BL::BlendData& b_data_, BL::Scene& b_scene_)
 +void BlenderSession::reset_session(BL::BlendData& b_data, BL::Depsgraph& b_depsgraph)
  {
 -      b_data = b_data_;
 -      b_render = b_engine.render();
 -      b_scene = b_scene_;
 +      this->b_data = b_data;
 +      this->b_depsgraph = b_depsgraph;
 +      this->b_scene = b_depsgraph.scene_eval();
 +
 +      if (preview_osl) {
 +              PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
 +              RNA_boolean_set(&cscene, "shading_system", preview_osl);
 +      }
 +
 +      if (b_v3d) {
 +              this->b_render = b_scene.render();
 +      }
 +      else {
 +              this->b_render = b_engine.render();
 +              width = render_resolution_x(b_render);
 +              height = render_resolution_y(b_render);
 +      }
 +
 +      if (session == NULL) {
 +              create();
 +      }
 +
 +      if (b_v3d) {
 +              /* NOTE: We need to create session, but all the code from below
 +               * will make viewport render to stuck on initialization.
 +               */
 +              return;
 +      }
  
        SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
        SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
  
 -      width = render_resolution_x(b_render);
 -      height = render_resolution_y(b_render);
 -
        if(scene->params.modified(scene_params) ||
           session->params.modified(session_params) ||
           !scene_params.persistent_data)
                /* if scene or session parameters changed, it's easier to simply re-create
                 * them rather than trying to distinguish which settings need to be updated
                 */
 -
 -              delete session;
 -
 +              free_session();
                create_session();
 -
                return;
        }
  
         */
        session->stats.mem_peak = session->stats.mem_used;
  
 +      /* There is no single depsgraph to use for the entire render.
 +       * See note on create_session().
 +       */
        /* sync object should be re-created */
        sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
  
 -      /* for final render we will do full data sync per render layer, only
 -       * do some basic syncing here, no objects or materials for speed */
 -      BL::Object b_camera_override(b_engine.camera_override());
 -      sync->sync_render_layers(b_v3d, NULL);
 -      sync->sync_integrator();
 -      sync->sync_camera(b_render, b_camera_override, width, height, "");
 -
        BL::SpaceView3D b_null_space_view3d(PointerRNA_NULL);
        BL::RegionView3D b_null_region_view3d(PointerRNA_NULL);
        BufferParams buffer_params = BlenderSync::get_buffer_params(b_render,
@@@ -382,10 -370,8 +382,10 @@@ void BlenderSession::update_render_tile
                do_write_update_render_tile(rtile, false, false);
  }
  
 -void BlenderSession::render()
 +void BlenderSession::render(BL::Depsgraph& b_depsgraph_)
  {
 +      b_depsgraph = b_depsgraph_;
 +
        /* set callback to write out render results */
        session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1);
        session->update_render_tile_cb = function_bind(&BlenderSession::update_render_tile, this, _1, _2);
        BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height);
  
        /* render each layer */
 -      BL::RenderSettings r = b_scene.render();
 -      BL::RenderSettings::layers_iterator b_layer_iter;
 -      BL::RenderResult::views_iterator b_view_iter;
 +      BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
  
        /* We do some special meta attributes when we only have single layer. */
 -      const bool is_single_layer = (r.layers.length() == 1);
 +      const bool is_single_layer = (b_scene.view_layers.length() == 1);
  
 -      for(r.layers.begin(b_layer_iter); b_layer_iter != r.layers.end(); ++b_layer_iter) {
 -              b_rlay_name = b_layer_iter->name();
 -
 -              /* temporary render result to find needed passes and views */
 -              BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_rlay_name.c_str(), NULL);
 -              BL::RenderResult::layers_iterator b_single_rlay;
 -              b_rr.layers.begin(b_single_rlay);
 -
 -              /* layer will be missing if it was disabled in the UI */
 -              if(b_single_rlay == b_rr.layers.end()) {
 -                      end_render_result(b_engine, b_rr, true, true, false);
 -                      continue;
 -              }
 +      /* temporary render result to find needed passes and views */
 +      BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_view_layer.name().c_str(), NULL);
 +      BL::RenderResult::layers_iterator b_single_rlay;
 +      b_rr.layers.begin(b_single_rlay);
 +      BL::RenderLayer b_rlay = *b_single_rlay;
  
 -              BL::RenderLayer b_rlay = *b_single_rlay;
 -
 -              /* add passes */
 -              vector<Pass> passes = sync->sync_render_passes(b_rlay, *b_layer_iter, session_params);
 -              buffer_params.passes = passes;
 -
 -              PointerRNA crl = RNA_pointer_get(&b_layer_iter->ptr, "cycles");
 -              bool use_denoising = get_boolean(crl, "use_denoising");
 -              bool denoising_passes = use_denoising || get_boolean(crl, "denoising_store_passes");
 -
 -              session->tile_manager.schedule_denoising = use_denoising;
 -              buffer_params.denoising_data_pass = denoising_passes;
 -              buffer_params.denoising_clean_pass = (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES);
 -
 -              session->params.use_denoising = use_denoising;
 -              session->params.denoising_passes = denoising_passes;
 -              session->params.denoising_radius = get_int(crl, "denoising_radius");
 -              session->params.denoising_strength = get_float(crl, "denoising_strength");
 -              session->params.denoising_feature_strength = get_float(crl, "denoising_feature_strength");
 -              session->params.denoising_relative_pca = get_boolean(crl, "denoising_relative_pca");
 -
 -              scene->film->denoising_data_pass = buffer_params.denoising_data_pass;
 -              scene->film->denoising_clean_pass = buffer_params.denoising_clean_pass;
 -              scene->film->pass_alpha_threshold = b_layer_iter->pass_alpha_threshold();
 -              scene->film->tag_passes_update(scene, passes);
 -              scene->film->tag_update(scene);
 -              scene->integrator->tag_update(scene);
 -
 -              int view_index = 0;
 -              for(b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end(); ++b_view_iter, ++view_index) {
 -                      b_rview_name = b_view_iter->name();
 -
 -                      /* set the current view */
 -                      b_engine.active_view_set(b_rview_name.c_str());
 -
 -                      /* update scene */
 -                      BL::Object b_camera_override(b_engine.camera_override());
 -                      sync->sync_camera(b_render, b_camera_override, width, height, b_rview_name.c_str());
 -                      sync->sync_data(b_render,
 -                                      b_v3d,
 -                                      b_camera_override,
 -                                      width, height,
 -                                      &python_thread_state,
 -                                      b_rlay_name.c_str());
 -
 -                      /* Make sure all views have different noise patterns. - hardcoded value just to make it random */
 -                      if(view_index != 0) {
 -                              scene->integrator->seed += hash_int_2d(scene->integrator->seed, hash_int(view_index * 0xdeadbeef));
 -                              scene->integrator->tag_update(scene);
 -                      }
 +      /* add passes */
 +      vector<Pass> passes = sync->sync_render_passes(b_rlay, b_view_layer, session_params);
 +      buffer_params.passes = passes;
 +
 +      PointerRNA crl = RNA_pointer_get(&b_view_layer.ptr, "cycles");
 +      bool use_denoising = get_boolean(crl, "use_denoising");
++      bool denoising_passes = use_denoising || get_boolean(crl, "denoising_store_passes");
 +
 +      session->tile_manager.schedule_denoising = use_denoising;
-       buffer_params.denoising_data_pass = use_denoising;
++      buffer_params.denoising_data_pass = denoising_passes;
 +      buffer_params.denoising_clean_pass = (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES);
 +
 +      session->params.use_denoising = use_denoising;
++      session->params.denoising_passes = denoising_passes;
 +      session->params.denoising_radius = get_int(crl, "denoising_radius");
 +      session->params.denoising_strength = get_float(crl, "denoising_strength");
 +      session->params.denoising_feature_strength = get_float(crl, "denoising_feature_strength");
 +      session->params.denoising_relative_pca = get_boolean(crl, "denoising_relative_pca");
 +
 +      scene->film->denoising_data_pass = buffer_params.denoising_data_pass;
 +      scene->film->denoising_clean_pass = buffer_params.denoising_clean_pass;
 +      session->params.denoising_radius = get_int(crl, "denoising_radius");
 +      session->params.denoising_strength = get_float(crl, "denoising_strength");
 +      session->params.denoising_feature_strength = get_float(crl, "denoising_feature_strength");
 +      session->params.denoising_relative_pca = get_boolean(crl, "denoising_relative_pca");
 +
 +      scene->film->pass_alpha_threshold = b_view_layer.pass_alpha_threshold();
 +      scene->film->tag_passes_update(scene, passes);
 +      scene->film->tag_update(scene);
 +      scene->integrator->tag_update(scene);
  
 -                      /* Update number of samples per layer. */
 -                      int samples = sync->get_layer_samples();
 -                      bool bound_samples = sync->get_layer_bound_samples();
 -                      int effective_layer_samples;
 +      BL::RenderResult::views_iterator b_view_iter;
 +      int view_index = 0;
 +      for(b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end(); ++b_view_iter, ++view_index) {
 +              b_rlay_name = b_view_layer.name();
 +              b_rview_name = b_view_iter->name();
  
 -                      if(samples != 0 && (!bound_samples || (samples < session_params.samples)))
 -                              effective_layer_samples = samples;
 -                      else
 -                              effective_layer_samples = session_params.samples;
 +              /* set the current view */
 +              b_engine.active_view_set(b_rview_name.c_str());
  
 -                      /* Update tile manager if we're doing resumable render. */
 -                      update_resumable_tile_manager(effective_layer_samples);
 +              /* update scene */
 +              BL::Object b_camera_override(b_engine.camera_override());
 +              sync->sync_camera(b_render, b_camera_override, width, height, b_rview_name.c_str());
 +              sync->sync_data(b_render,
 +                              b_depsgraph,
 +                              b_v3d,
 +                              b_camera_override,
 +                              width, height,
 +                              &python_thread_state);
 +              builtin_images_load();
 +
 +              /* Make sure all views have different noise patterns. - hardcoded value just to make it random */
 +              if(view_index != 0) {
 +                      scene->integrator->seed += hash_int_2d(scene->integrator->seed, hash_int(view_index * 0xdeadbeef));
 +                      scene->integrator->tag_update(scene);
 +              }
  
 -                      /* Update session itself. */
 -                      session->reset(buffer_params, effective_layer_samples);
 +              int effective_layer_samples = session_params.samples;
  
 -                      /* render */
 -                      session->start();
 -                      session->wait();
 +              /* TODO: Update number of samples per layer. */
 +#if 0
 +              if(samples != 0 && (!bound_samples || (samples < session_params.samples)))
 +                      effective_layer_samples = samples;
 +#endif
  
 -                      if(session->progress.get_cancel())
 -                              break;
 -              }
 +              /* Update tile manager if we're doing resumable render. */
 +              update_resumable_tile_manager(effective_layer_samples);
  
 -              if(is_single_layer) {
 -                      BL::RenderResult b_rr = b_engine.get_result();
 -                      string num_aa_samples = string_printf("%d", session->params.samples);
 -                      b_rr.stamp_data_add_field("Cycles Samples", num_aa_samples.c_str());
 -                      /* TODO(sergey): Report whether we're doing resumable render
 -                       * and also start/end sample if so.
 -                       */
 -              }
 +              /* Update session itself. */
 +              session->reset(buffer_params, effective_layer_samples);
  
 -              /* free result without merging */
 -              end_render_result(b_engine, b_rr, true, true, false);
 +              /* render */
 +              session->start();
 +              session->wait();
  
                if(!b_engine.is_preview() && background && print_render_stats) {
                        RenderStats stats;
                        break;
        }
  
 +      if(is_single_layer) {
 +              BL::RenderResult b_rr = b_engine.get_result();
 +              string num_aa_samples = string_printf("%d", session->params.samples);
 +              b_rr.stamp_data_add_field("Cycles Samples", num_aa_samples.c_str());
 +              /* TODO(sergey): Report whether we're doing resumable render
 +               * and also start/end sample if so.
 +               */
 +      }
 +
 +      /* free result without merging */
 +      end_render_result(b_engine, b_rr, true, true, false);
 +
        double total_time, render_time;
        session->progress.get_time(total_time, render_time);
        VLOG(1) << "Total render time: " << total_time;
        session->write_render_tile_cb = function_null;
        session->update_render_tile_cb = function_null;
  
 +      /* TODO: find a way to clear this data for persistent data render */
 +#if 0
        /* free all memory used (host and device), so we wouldn't leave render
         * engine with extra memory allocated
         */
  
        delete sync;
        sync = NULL;
 +#endif
  }
  
  static void populate_bake_data(BakeData *data, const
@@@ -569,8 -564,7 +571,8 @@@ static int bake_pass_filter_get(const i
        return flag;
  }
  
 -void BlenderSession::bake(BL::Object& b_object,
 +void BlenderSession::bake(BL::Depsgraph& b_depsgraph_,
 +                          BL::Object& b_object,
                            const string& pass_type,
                            const int pass_filter,
                            const int object_id,
                            const int /*depth*/,
                            float result[])
  {
 +      b_depsgraph = b_depsgraph_;
 +
        ShaderEvalType shader_type = get_shader_type(pass_type);
  
        /* Set baking flag in advance, so kernel loading can check if we need
                BL::Object b_camera_override(b_engine.camera_override());
                sync->sync_camera(b_render, b_camera_override, width, height, "");
                sync->sync_data(b_render,
 -                                              b_v3d,
 -                                              b_camera_override,
 -                                              width, height,
 -                                              &python_thread_state,
 -                                              b_rlay_name.c_str());
 +                              b_depsgraph,
 +                              b_v3d,
 +                              b_camera_override,
 +                              width, height,
 +                              &python_thread_state);
 +              builtin_images_load();
        }
  
        BakeData *bake_data = NULL;
@@@ -752,7 -743,7 +754,7 @@@ void BlenderSession::update_render_resu
        do_write_update_render_result(b_rr, b_rlay, rtile, true);
  }
  
 -void BlenderSession::synchronize()
 +void BlenderSession::synchronize(BL::Depsgraph& b_depsgraph_)
  {
        /* only used for viewport render */
        if(!b_v3d)
  
        /* copy recalc flags, outside of mutex so we can decide to do the real
         * synchronization at a later time to not block on running updates */
 -      sync->sync_recalc();
 +      sync->sync_recalc(b_depsgraph_);
  
        /* don't do synchronization if on pause */
        if(session_pause) {
        }
  
        /* data and camera synchronize */
 +      b_depsgraph = b_depsgraph_;
 +
        BL::Object b_camera_override(b_engine.camera_override());
        sync->sync_data(b_render,
 +                      b_depsgraph,
                        b_v3d,
                        b_camera_override,
                        width, height,
 -                      &python_thread_state,
 -                      b_rlay_name.c_str());
 +                      &python_thread_state);
  
        if(b_rv3d)
                sync->sync_view(b_v3d, b_rv3d, width, height);
        else
                sync->sync_camera(b_render, b_camera_override, width, height, "");
  
 +      builtin_images_load();
 +
        /* unlock */
        session->scene->mutex.unlock();
  
@@@ -1317,9 -1304,6 +1319,9 @@@ bool BlenderSession::builtin_image_floa
                fprintf(stderr, "Cycles error: unexpected smoke volume resolution, skipping\n");
        }
        else {
 +              /* We originally were passing view_layer here but in reality we need a
 +               * a depsgraph to pass to the RE_point_density_minmax() function.
 +               */
                /* TODO(sergey): Check we're indeed in shader node tree. */
                PointerRNA ptr;
                RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr);
                if(b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
                        BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
                        int length;
 -                      int settings = background ? 1 : 0;  /* 1 - render settings, 0 - vewport settings. */
 -                      b_point_density_node.calc_point_density(b_scene, settings, &length, &pixels);
 +                      b_point_density_node.calc_point_density(b_depsgraph, &length, &pixels);
                }
        }
  
        return false;
  }
  
 +void BlenderSession::builtin_images_load()
 +{
 +      /* Force builtin images to be loaded along with Blender data sync. This
 +       * is needed because we may be reading from depsgraph evaluated data which
 +       * can be freed by Blender before Cycles reads it. */
 +      ImageManager *manager = session->scene->image_manager;
 +      Device *device = session->device;
 +      manager->device_load_builtin(device, session->scene, session->progress);
 +}
 +
  void BlenderSession::update_resumable_tile_manager(int num_samples)
  {
        const int num_resumable_chunks = BlenderSession::num_resumable_chunks,
index 424894387807b29ac0afda7f55067508a4a9b622,70bb6de8b1d83130d0758718be25258437cffd6f..1a3d94b5276fb68d8e00923ea8b9ad0500fc70e8
@@@ -78,12 -78,31 +78,12 @@@ BlenderSync::~BlenderSync(
  
  /* Sync */
  
 -bool BlenderSync::sync_recalc()
 +void BlenderSync::sync_recalc(BL::Depsgraph& b_depsgraph)
  {
 -      /* sync recalc flags from blender to cycles. actual update is done separate,
 -       * so we can do it later on if doing it immediate is not suitable */
 -
 -      BL::BlendData::materials_iterator b_mat;
 -      bool has_updated_objects = b_data.objects.is_updated();
 -      for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) {
 -              if(b_mat->is_updated() || (b_mat->node_tree() && b_mat->node_tree().is_updated())) {
 -                      shader_map.set_recalc(*b_mat);
 -              }
 -              else {
 -                      Shader *shader = shader_map.find(*b_mat);
 -                      if(has_updated_objects && shader != NULL && shader->has_object_dependency) {
 -                              shader_map.set_recalc(*b_mat);
 -                      }
 -              }
 -      }
 -
 -      BL::BlendData::lamps_iterator b_lamp;
 -
 -      for(b_data.lamps.begin(b_lamp); b_lamp != b_data.lamps.end(); ++b_lamp)
 -              if(b_lamp->is_updated() || (b_lamp->node_tree() && b_lamp->node_tree().is_updated()))
 -                      shader_map.set_recalc(*b_lamp);
 +      /* Sync recalc flags from blender to cycles. Actual update is done separate,
 +       * so we can do it later on if doing it immediate is not suitable. */
  
 +      bool has_updated_objects = b_depsgraph.id_type_updated(BL::DriverTarget::id_type_OBJECT);
        bool dicing_prop_changed = false;
  
        if(experimental) {
                }
        }
  
 -      BL::BlendData::objects_iterator b_ob;
 +      /* Iterate over all IDs in this depsgraph. */
 +      BL::Depsgraph::updates_iterator b_update;
 +      for(b_depsgraph.updates.begin(b_update); b_update != b_depsgraph.updates.end(); ++b_update) {
 +              BL::ID b_id(b_update->id());
  
 -      for(b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) {
 -              if(b_ob->is_updated()) {
 -                      object_map.set_recalc(*b_ob);
 -                      light_map.set_recalc(*b_ob);
 +              /* Material */
 +              if (b_id.is_a(&RNA_Material)) {
 +                      BL::Material b_mat(b_id);
 +                      shader_map.set_recalc(b_mat);
                }
 +              /* Light */
 +              else if (b_id.is_a(&RNA_Light)) {
 +                      BL::Light b_light(b_id);
 +                      shader_map.set_recalc(b_light);
 +              }
 +              /* Object */
 +              else if (b_id.is_a(&RNA_Object)) {
 +                      BL::Object b_ob(b_id);
 +                      const bool updated_geometry = !b_update->is_dirty_geometry();
 +
 +                      if (!b_update->is_dirty_transform()) {
 +                              object_map.set_recalc(b_ob);
 +                              light_map.set_recalc(b_ob);
 +                      }
 +
 +                      if(object_is_mesh(b_ob)) {
 +                              if(updated_geometry ||
 +                                 (dicing_prop_changed && object_subdivision_type(b_ob, preview, experimental) != Mesh::SUBDIVISION_NONE))
 +                              {
 +                                      BL::ID key = BKE_object_is_modified(b_ob)? b_ob: b_ob.data();
 +                                      mesh_map.set_recalc(key);
 +                              }
 +                      }
 +                      else if(object_is_light(b_ob)) {
 +                              if(updated_geometry) {
 +                                      light_map.set_recalc(b_ob);
 +                              }
 +                      }
  
 -              if(object_is_mesh(*b_ob)) {
 -                      if(b_ob->is_updated_data() || b_ob->data().is_updated() ||
 -                         (dicing_prop_changed && object_subdivision_type(*b_ob, preview, experimental) != Mesh::SUBDIVISION_NONE))
 -                      {
 -                              BL::ID key = BKE_object_is_modified(*b_ob)? *b_ob: b_ob->data();
 -                              mesh_map.set_recalc(key);
 +                      if(updated_geometry) {
 +                              BL::Object::particle_systems_iterator b_psys;
 +                              for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys)
 +                                      particle_system_map.set_recalc(b_ob);
                        }
                }
 -              else if(object_is_light(*b_ob)) {
 -                      if(b_ob->is_updated_data() || b_ob->data().is_updated())
 -                              light_map.set_recalc(*b_ob);
 +              /* Mesh */
 +              else if (b_id.is_a(&RNA_Mesh)) {
 +                      BL::Mesh b_mesh(b_id);
 +                      mesh_map.set_recalc(b_mesh);
                }
 -
 -              if(b_ob->is_updated_data()) {
 -                      BL::Object::particle_systems_iterator b_psys;
 -                      for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys)
 -                              particle_system_map.set_recalc(*b_ob);
 +              /* World */
 +              else if (b_id.is_a(&RNA_World)) {
 +                      BL::World b_world(b_id);
 +                      if(world_map == b_world.ptr.data) {
 +                              world_recalc = true;
 +                      }
                }
        }
  
 -      BL::BlendData::meshes_iterator b_mesh;
 -
 -      for(b_data.meshes.begin(b_mesh); b_mesh != b_data.meshes.end(); ++b_mesh) {
 -              if(b_mesh->is_updated()) {
 -                      mesh_map.set_recalc(*b_mesh);
 +      /* Updates shader with object dependency if objects changed. */
 +      if (has_updated_objects) {
 +              if(scene->default_background->has_object_dependency) {
 +                      world_recalc = true;
                }
 -      }
 -
 -      BL::BlendData::worlds_iterator b_world;
  
 -      for(b_data.worlds.begin(b_world); b_world != b_data.worlds.end(); ++b_world) {
 -              if(world_map == b_world->ptr.data) {
 -                      if(b_world->is_updated() ||
 -                         (b_world->node_tree() && b_world->node_tree().is_updated()))
 -                      {
 -                              world_recalc = true;
 -                      }
 -                      else if(b_world->node_tree() && b_world->use_nodes()) {
 -                              Shader *shader = scene->default_background;
 -                              if(has_updated_objects && shader->has_object_dependency) {
 -                                      world_recalc = true;
 -                              }
 +              foreach(Shader *shader, scene->shaders) {
 +                      if (shader->has_object_dependency) {
 +                              shader->need_sync_object = true;
                        }
                }
        }
 -
 -      bool recalc =
 -              shader_map.has_recalc() ||
 -              object_map.has_recalc() ||
 -              light_map.has_recalc() ||
 -              mesh_map.has_recalc() ||
 -              particle_system_map.has_recalc() ||
 -              BlendDataObjects_is_updated_get(&b_data.ptr) ||
 -              world_recalc;
 -
 -      return recalc;
  }
  
  void BlenderSync::sync_data(BL::RenderSettings& b_render,
 +                            BL::Depsgraph& b_depsgraph,
                              BL::SpaceView3D& b_v3d,
                              BL::Object& b_override,
                              int width, int height,
 -                            void **python_thread_state,
 -                            const char *layer)
 +                            void **python_thread_state)
  {
 -      sync_render_layers(b_v3d, layer);
 +      BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
 +
 +      sync_view_layer(b_v3d, b_view_layer);
        sync_integrator();
        sync_film();
 -      sync_shaders();
 +      sync_shaders(b_depsgraph);
        sync_images();
        sync_curve_settings();
  
           scene->need_motion() == Scene::MOTION_NONE ||
           scene->camera->motion_position == Camera::MOTION_POSITION_CENTER)
        {
 -              sync_objects();
 +              sync_objects(b_depsgraph);
        }
        sync_motion(b_render,
 +                  b_depsgraph,
                    b_override,
                    width, height,
                    python_thread_state);
  
        mesh_synced.clear();
 +
 +      free_data_after_sync(b_depsgraph);
  }
  
  /* Integrator */
@@@ -364,14 -371,75 +364,14 @@@ void BlenderSync::sync_film(
  
  /* Render Layer */
  
 -void BlenderSync::sync_render_layers(BL::SpaceView3D& b_v3d, const char *layer)
 +void BlenderSync::sync_view_layer(BL::SpaceView3D& /*b_v3d*/, BL::ViewLayer& b_view_layer)
  {
 -      PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
 -      string layername;
 -
 -      /* 3d view */
 -      if(b_v3d) {
 -              if(RNA_boolean_get(&cscene, "preview_active_layer")) {
 -                      BL::RenderLayers layers(b_scene.render().ptr);
 -                      layername = layers.active().name();
 -                      layer = layername.c_str();
 -              }
 -              else {
 -                      render_layer.scene_layer = get_layer(b_v3d.layers(), b_v3d.layers_local_view());
 -                      render_layer.layer = render_layer.scene_layer;
 -                      render_layer.exclude_layer = 0;
 -                      render_layer.holdout_layer = 0;
 -                      render_layer.material_override = PointerRNA_NULL;
 -                      render_layer.use_background_shader = true;
 -                      render_layer.use_background_ao = true;
 -                      render_layer.use_hair = true;
 -                      render_layer.use_surfaces = true;
 -                      render_layer.use_viewport_visibility = true;
 -                      render_layer.samples = 0;
 -                      render_layer.bound_samples = false;
 -                      return;
 -              }
 -      }
 -
        /* render layer */
 -      BL::RenderSettings r = b_scene.render();
 -      BL::RenderSettings::layers_iterator b_rlay;
 -      int use_layer_samples = get_enum(cscene, "use_layer_samples");
 -      bool first_layer = true;
 -      uint layer_override = get_layer(b_engine.layer_override());
 -      uint scene_layers = layer_override ? layer_override : get_layer(b_scene.layers());
 -
 -      for(r.layers.begin(b_rlay); b_rlay != r.layers.end(); ++b_rlay) {
 -              if((!layer && first_layer) || (layer && b_rlay->name() == layer)) {
 -                      render_layer.name = b_rlay->name();
 -
 -                      render_layer.holdout_layer = get_layer(b_rlay->layers_zmask());
 -                      render_layer.exclude_layer = get_layer(b_rlay->layers_exclude());
 -
 -                      render_layer.scene_layer = scene_layers & ~render_layer.exclude_layer;
 -                      render_layer.scene_layer |= render_layer.exclude_layer & render_layer.holdout_layer;
 -
 -                      render_layer.layer = get_layer(b_rlay->layers());
 -                      render_layer.layer |= render_layer.holdout_layer;
 -
 -                      render_layer.material_override = b_rlay->material_override();
 -                      render_layer.use_background_shader = b_rlay->use_sky();
 -                      render_layer.use_background_ao = b_rlay->use_ao();
 -                      render_layer.use_surfaces = b_rlay->use_solid();
 -                      render_layer.use_hair = b_rlay->use_strand();
 -                      render_layer.use_viewport_visibility = false;
 -
 -                      render_layer.bound_samples = (use_layer_samples == 1);
 -                      if(use_layer_samples != 2) {
 -                              int samples = b_rlay->samples();
 -                              if(get_boolean(cscene, "use_square_samples"))
 -                                      render_layer.samples = samples * samples;
 -                              else
 -                                      render_layer.samples = samples;
 -                      }
 -              }
 -
 -              first_layer = false;
 -      }
 +      view_layer.name = b_view_layer.name();
 +      view_layer.use_background_shader = b_view_layer.use_sky();
 +      view_layer.use_background_ao = b_view_layer.use_ao();
 +      view_layer.use_surfaces = b_view_layer.use_solid();
 +      view_layer.use_hair = b_view_layer.use_strand();
  }
  
  /* Images */
@@@ -487,7 -555,7 +487,7 @@@ int BlenderSync::get_denoising_pass(BL:
  }
  
  vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
 -                                             BL::SceneRenderLayer& b_srlay,
 +                                             BL::ViewLayer& b_view_layer,
                                               const SessionParams &session_params)
  {
        vector<Pass> passes;
                        Pass::add(pass_type, passes);
        }
  
-       scene->film->denoising_flags = 0;
 -      PointerRNA crp = RNA_pointer_get(&b_srlay.ptr, "cycles");
 +      PointerRNA crp = RNA_pointer_get(&b_view_layer.ptr, "cycles");
-       if(get_boolean(crp, "use_denoising")) {
+       bool use_denoising = get_boolean(crp, "use_denoising");
+       bool store_denoising_passes = get_boolean(crp, "denoising_store_passes");
+       scene->film->denoising_flags = 0;
+       if(use_denoising || store_denoising_passes) {
  #define MAP_OPTION(name, flag) if(!get_boolean(crp, name)) scene->film->denoising_flags |= flag;
                MAP_OPTION("denoising_diffuse_direct",        DENOISING_CLEAN_DIFFUSE_DIR);
                MAP_OPTION("denoising_diffuse_indirect",      DENOISING_CLEAN_DIFFUSE_IND);
                MAP_OPTION("denoising_subsurface_direct",     DENOISING_CLEAN_SUBSURFACE_DIR);
                MAP_OPTION("denoising_subsurface_indirect",   DENOISING_CLEAN_SUBSURFACE_IND);
  #undef MAP_OPTION
 -              b_engine.add_pass("Noisy Image", 4, "RGBA", b_srlay.name().c_str());
 +              b_engine.add_pass("Noisy Image", 4, "RGBA", b_view_layer.name().c_str());
-               if(get_boolean(crp, "denoising_store_passes")) {
-                       b_engine.add_pass("Denoising Normal",          3, "XYZ", b_view_layer.name().c_str());
-                       b_engine.add_pass("Denoising Normal Variance", 3, "XYZ", b_view_layer.name().c_str());
-                       b_engine.add_pass("Denoising Albedo",          3, "RGB", b_view_layer.name().c_str());
-                       b_engine.add_pass("Denoising Albedo Variance", 3, "RGB", b_view_layer.name().c_str());
-                       b_engine.add_pass("Denoising Depth",           1, "Z",   b_view_layer.name().c_str());
-                       b_engine.add_pass("Denoising Depth Variance",  1, "Z",   b_view_layer.name().c_str());
-                       b_engine.add_pass("Denoising Shadow A",        3, "XYV", b_view_layer.name().c_str());
-                       b_engine.add_pass("Denoising Shadow B",        3, "XYV", b_view_layer.name().c_str());
-                       b_engine.add_pass("Denoising Image Variance",  3, "RGB", b_view_layer.name().c_str());
-                       if(scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES) {
-                               b_engine.add_pass("Denoising Clean",   3, "RGB", b_view_layer.name().c_str());
-                       }
+       }
+       if(store_denoising_passes) {
 -              b_engine.add_pass("Denoising Normal",          3, "XYZ", b_srlay.name().c_str());
 -              b_engine.add_pass("Denoising Normal Variance", 3, "XYZ", b_srlay.name().c_str());
 -              b_engine.add_pass("Denoising Albedo",          3, "RGB", b_srlay.name().c_str());
 -              b_engine.add_pass("Denoising Albedo Variance", 3, "RGB", b_srlay.name().c_str());
 -              b_engine.add_pass("Denoising Depth",           1, "Z",   b_srlay.name().c_str());
 -              b_engine.add_pass("Denoising Depth Variance",  1, "Z",   b_srlay.name().c_str());
 -              b_engine.add_pass("Denoising Shadow A",        3, "XYV", b_srlay.name().c_str());
 -              b_engine.add_pass("Denoising Shadow B",        3, "XYV", b_srlay.name().c_str());
 -              b_engine.add_pass("Denoising Image Variance",  3, "RGB", b_srlay.name().c_str());
++              b_engine.add_pass("Denoising Normal",          3, "XYZ", b_view_layer.name().c_str());
++              b_engine.add_pass("Denoising Normal Variance", 3, "XYZ", b_view_layer.name().c_str());
++              b_engine.add_pass("Denoising Albedo",          3, "RGB", b_view_layer.name().c_str());
++              b_engine.add_pass("Denoising Albedo Variance", 3, "RGB", b_view_layer.name().c_str());
++              b_engine.add_pass("Denoising Depth",           1, "Z",   b_view_layer.name().c_str());
++              b_engine.add_pass("Denoising Depth Variance",  1, "Z",   b_view_layer.name().c_str());
++              b_engine.add_pass("Denoising Shadow A",        3, "XYV", b_view_layer.name().c_str());
++              b_engine.add_pass("Denoising Shadow B",        3, "XYV", b_view_layer.name().c_str());
++              b_engine.add_pass("Denoising Image Variance",  3, "RGB", b_view_layer.name().c_str());
+               if(scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES) {
 -                      b_engine.add_pass("Denoising Clean",   3, "RGB", b_srlay.name().c_str());
++                      b_engine.add_pass("Denoising Clean",   3, "RGB", b_view_layer.name().c_str());
                }
        }
  #ifdef __KERNEL_DEBUG__
        if(get_boolean(crp, "pass_debug_bvh_traversed_nodes")) {
 -              b_engine.add_pass("Debug BVH Traversed Nodes", 1, "X", b_srlay.name().c_str());
 +              b_engine.add_pass("Debug BVH Traversed Nodes", 1, "X", b_view_layer.name().c_str());
                Pass::add(PASS_BVH_TRAVERSED_NODES, passes);
        }
        if(get_boolean(crp, "pass_debug_bvh_traversed_instances")) {
 -              b_engine.add_pass("Debug BVH Traversed Instances", 1, "X", b_srlay.name().c_str());
 +              b_engine.add_pass("Debug BVH Traversed Instances", 1, "X", b_view_layer.name().c_str());
                Pass::add(PASS_BVH_TRAVERSED_INSTANCES, passes);
        }
        if(get_boolean(crp, "pass_debug_bvh_intersections")) {
 -              b_engine.add_pass("Debug BVH Intersections", 1, "X", b_srlay.name().c_str());
 +              b_engine.add_pass("Debug BVH Intersections", 1, "X", b_view_layer.name().c_str());
                Pass::add(PASS_BVH_INTERSECTIONS, passes);
        }
        if(get_boolean(crp, "pass_debug_ray_bounces")) {
 -              b_engine.add_pass("Debug Ray Bounces", 1, "X", b_srlay.name().c_str());
 +              b_engine.add_pass("Debug Ray Bounces", 1, "X", b_view_layer.name().c_str());
                Pass::add(PASS_RAY_BOUNCES, passes);
        }
  #endif
        if(get_boolean(crp, "pass_debug_render_time")) {
 -              b_engine.add_pass("Debug Render Time", 1, "X", b_srlay.name().c_str());
 +              b_engine.add_pass("Debug Render Time", 1, "X", b_view_layer.name().c_str());
                Pass::add(PASS_RENDER_TIME, passes);
        }
        if(get_boolean(crp, "use_pass_volume_direct")) {
 -              b_engine.add_pass("VolumeDir", 3, "RGB", b_srlay.name().c_str());
 +              b_engine.add_pass("VolumeDir", 3, "RGB", b_view_layer.name().c_str());
                Pass::add(PASS_VOLUME_DIRECT, passes);
        }
        if(get_boolean(crp, "use_pass_volume_indirect")) {
 -              b_engine.add_pass("VolumeInd", 3, "RGB", b_srlay.name().c_str());
 +              b_engine.add_pass("VolumeInd", 3, "RGB", b_view_layer.name().c_str());
                Pass::add(PASS_VOLUME_INDIRECT, passes);
        }
  
        if(get_boolean(crp, "use_pass_crypto_object")) {
                for(int i = 0; i < crypto_depth; ++i) {
                        string passname = cryptomatte_prefix + string_printf("Object%02d", i);
 -                      b_engine.add_pass(passname.c_str(), 4, "RGBA", b_srlay.name().c_str());
 +                      b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str());
                        Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str());
                }
                scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes | CRYPT_OBJECT);
        if(get_boolean(crp, "use_pass_crypto_material")) {
                for(int i = 0; i < crypto_depth; ++i) {
                        string passname = cryptomatte_prefix + string_printf("Material%02d", i);
 -                      b_engine.add_pass(passname.c_str(), 4, "RGBA", b_srlay.name().c_str());
 +                      b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str());
                        Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str());
                }
                scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes | CRYPT_MATERIAL);
        if(get_boolean(crp, "use_pass_crypto_asset")) {
                for(int i = 0; i < crypto_depth; ++i) {
                        string passname = cryptomatte_prefix + string_printf("Asset%02d", i);
 -                      b_engine.add_pass(passname.c_str(), 4, "RGBA", b_srlay.name().c_str());
 +                      b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str());
                        Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str());
                }
                scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes | CRYPT_ASSET);
        return passes;
  }
  
 +void BlenderSync::free_data_after_sync(BL::Depsgraph& b_depsgraph)
 +{
 +      /* When viewport display is not needed during render we can force some
 +       * caches to be releases from blender side in order to reduce peak memory
 +       * footprint during synchronization process.
 +       */
 +      const bool is_interface_locked = b_engine.render() &&
 +                                       b_engine.render().use_lock_interface();
 +      const bool can_free_caches = BlenderSession::headless || is_interface_locked;
 +      if (!can_free_caches) {
 +              return;
 +      }
 +      /* TODO(sergey): We can actually remove the whole dependency graph,
 +       * but that will need some API support first.
 +       */
 +      BL::Depsgraph::objects_iterator b_ob;
 +      for(b_depsgraph.objects.begin(b_ob);
 +          b_ob != b_depsgraph.objects.end();
 +          ++b_ob)
 +      {
 +              b_ob->cache_release();
 +      }
 +}
 +
  /* Scene Parameters */
  
  SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene,
@@@ -858,14 -904,13 +860,14 @@@ SessionParams BlenderSync::get_session_
        params.text_timeout = (double)get_float(cscene, "debug_text_timeout");
  
        /* progressive refine */
 -      params.progressive_refine = get_boolean(cscene, "use_progressive_refine") &&
 +      params.progressive_refine = (b_engine.is_preview() ||
 +                                   get_boolean(cscene, "use_progressive_refine")) &&
                                    !b_r.use_save_buffers();
  
        if(params.progressive_refine) {
 -              BL::RenderSettings::layers_iterator b_rlay;
 -              for(b_r.layers.begin(b_rlay); b_rlay != b_r.layers.end(); ++b_rlay) {
 -                      PointerRNA crl = RNA_pointer_get(&b_rlay->ptr, "cycles");
 +              BL::Scene::view_layers_iterator b_view_layer;
 +              for(b_scene.view_layers.begin(b_view_layer); b_view_layer != b_scene.view_layers.end(); ++b_view_layer) {
 +                      PointerRNA crl = RNA_pointer_get(&b_view_layer->ptr, "cycles");
                        if(get_boolean(crl, "use_denoising")) {
                                params.progressive_refine = false;
                        }
                params.shadingsystem = SHADINGSYSTEM_OSL;
  
        /* color managagement */
 -#ifdef GLEW_MX
 -      /* When using GLEW MX we need to check whether we've got an OpenGL
 -       * context for current window. This is because command line rendering
 -       * doesn't have OpenGL context actually.
 -       */
 -      if(glewGetContext() != NULL)
 -#endif
 -      {
 -              params.display_buffer_linear = GLEW_ARB_half_float_pixel &&
 -                                             b_engine.support_display_space_shader(b_scene);
 -      }
 +      params.display_buffer_linear = b_engine.support_display_space_shader(b_scene);
  
        if(b_engine.is_preview()) {
                /* For preview rendering we're using same timeout as