diff options
91 files changed, 2839 insertions, 2177 deletions
diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index 7c58df68011..1cb7835d14d 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -102,6 +102,9 @@ class CyclesRender(bpy.types.RenderEngine): else: self.report({'ERROR'}, "OSL support disabled in this build.") + def update_render_passes(self, scene, srl): + engine.register_passes(self, scene, srl) + def engine_exit(): engine.exit() diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index a418cdd6821..d74ae5f3061 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -208,3 +208,36 @@ def with_network(): def system_info(): import _cycles return _cycles.system_info() + +def register_passes(engine, scene, srl): + engine.register_pass(scene, srl, "Combined", 4, "RGBA", 'COLOR') + + if srl.use_pass_z: engine.register_pass(scene, srl, "Depth", 1, "Z", 'VALUE') + if srl.use_pass_mist: engine.register_pass(scene, srl, "Mist", 1, "Z", 'VALUE') + if srl.use_pass_normal: engine.register_pass(scene, srl, "Normal", 3, "XYZ", 'VECTOR') + if srl.use_pass_vector: engine.register_pass(scene, srl, "Vector", 4, "XYZW", 'VECTOR') + if srl.use_pass_uv: engine.register_pass(scene, srl, "UV", 3, "UVA", 'VECTOR') + if srl.use_pass_object_index: engine.register_pass(scene, srl, "IndexOB", 1, "X", 'VALUE') + if srl.use_pass_material_index: engine.register_pass(scene, srl, "IndexMA", 1, "X", 'VALUE') + if srl.use_pass_shadow: engine.register_pass(scene, srl, "Shadow", 3, "RGB", 'COLOR') + if srl.use_pass_ambient_occlusion: engine.register_pass(scene, srl, "AO", 3, "RGB", 'COLOR') + if srl.use_pass_diffuse_direct: engine.register_pass(scene, srl, "DiffDir", 3, "RGB", 'COLOR') + if srl.use_pass_diffuse_indirect: engine.register_pass(scene, srl, "DiffInd", 3, "RGB", 'COLOR') + if srl.use_pass_diffuse_color: engine.register_pass(scene, srl, "DiffCol", 3, "RGB", 'COLOR') + if srl.use_pass_glossy_direct: engine.register_pass(scene, srl, "GlossDir", 3, "RGB", 'COLOR') + if srl.use_pass_glossy_indirect: engine.register_pass(scene, srl, "GlossInd", 3, "RGB", 'COLOR') + if srl.use_pass_glossy_color: engine.register_pass(scene, srl, "GlossCol", 3, "RGB", 'COLOR') + if srl.use_pass_transmission_direct: engine.register_pass(scene, srl, "TransDir", 3, "RGB", 'COLOR') + if srl.use_pass_transmission_indirect: engine.register_pass(scene, srl, "TransInd", 3, "RGB", 'COLOR') + if srl.use_pass_transmission_color: engine.register_pass(scene, srl, "TransCol", 3, "RGB", 'COLOR') + if srl.use_pass_subsurface_direct: engine.register_pass(scene, srl, "SubsurfaceDir", 3, "RGB", 'COLOR') + if srl.use_pass_subsurface_indirect: engine.register_pass(scene, srl, "SubsurfaceInd", 3, "RGB", 'COLOR') + if srl.use_pass_subsurface_color: engine.register_pass(scene, srl, "SubsurfaceCol", 3, "RGB", 'COLOR') + if srl.use_pass_emit: engine.register_pass(scene, srl, "Emit", 3, "RGB", 'COLOR') + if srl.use_pass_environment: engine.register_pass(scene, srl, "Env", 3, "RGB", 'COLOR') + + crl = srl.cycles + if crl.pass_debug_bvh_traversed_nodes: engine.register_pass(scene, srl, "Debug BVH Traversed Nodes", 1, "X", 'VALUE') + if crl.pass_debug_bvh_traversed_instances: engine.register_pass(scene, srl, "Debug BVH Traversed Instances", 1, "X", 'VALUE') + if crl.pass_debug_bvh_intersections: engine.register_pass(scene, srl, "Debug BVH Intersections", 1, "X", 'VALUE') + if crl.pass_debug_ray_bounces: engine.register_pass(scene, srl, "Debug Ray Bounces", 1, "X", 'VALUE') diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 53740efb627..a8a0f0bfc70 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1166,6 +1166,39 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup): def unregister(cls): del bpy.types.Scene.cycles_curves +class CyclesRenderLayerSettings(bpy.types.PropertyGroup): + @classmethod + def register(cls): + bpy.types.SceneRenderLayer.cycles = PointerProperty( + name="Cycles SceneRenderLayer Settings", + description="Cycles SceneRenderLayer Settings", + type=cls, + ) + cls.pass_debug_bvh_traversed_nodes = BoolProperty( + name="Debug BVH Traversed Nodes", + description="Store Debug BVH Traversed Nodes pass", + default=False, + ) + cls.pass_debug_bvh_traversed_instances = BoolProperty( + name="Debug BVH Traversed Instances", + description="Store Debug BVH Traversed Instances pass", + default=False, + ) + cls.pass_debug_bvh_intersections = BoolProperty( + name="Debug BVH Intersections", + description="Store Debug BVH Intersections", + default=False, + ) + cls.pass_debug_ray_bounces = BoolProperty( + name="Debug Ray Bounces", + description="Store Debug Ray Bounces pass", + default=False, + ) + + @classmethod + def unregister(cls): + del bpy.types.SceneRenderLayer.cycles + class CyclesCurveSettings(bpy.types.PropertyGroup): @classmethod @@ -1324,6 +1357,7 @@ def register(): bpy.utils.register_class(CyclesCurveSettings) bpy.utils.register_class(CyclesDeviceSettings) bpy.utils.register_class(CyclesPreferences) + bpy.utils.register_class(CyclesRenderLayerSettings) def unregister(): @@ -1339,3 +1373,4 @@ def unregister(): bpy.utils.unregister_class(CyclesCurveSettings) bpy.utils.unregister_class(CyclesDeviceSettings) bpy.utils.unregister_class(CyclesPreferences) + bpy.utils.unregister_class(CyclesRenderLayerSettings) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 4423f3c266b..e81f7ba52b3 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -78,7 +78,7 @@ def use_cuda(context): def use_branched_path(context): cscene = context.scene.cycles - return (cscene.progressive == 'BRANCHED_PATH' and not use_opencl(context)) + return (cscene.progressive == 'BRANCHED_PATH') def use_sample_all_lights(context): @@ -156,7 +156,6 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel): row = layout.row() sub = row.row() - sub.active = get_device_type(context) != 'OPENCL' or use_cpu(context) sub.prop(cscene, "progressive", text="") row.prop(cscene, "use_square_samples") @@ -477,11 +476,14 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel): bl_options = {'DEFAULT_CLOSED'} def draw(self, context): + import _cycles + layout = self.layout scene = context.scene rd = scene.render rl = rd.layers.active + crl = rl.cycles split = layout.split() @@ -528,8 +530,12 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel): col.prop(rl, "use_pass_emit", text="Emission") col.prop(rl, "use_pass_environment") - if hasattr(rd, "debug_pass_type"): - layout.prop(rd, "debug_pass_type") + if _cycles.with_cycles_debug: + col = layout.column() + 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") class CyclesRender_PT_views(CyclesButtonsPanel, Panel): diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index ed361cc971e..42b985305ea 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -776,17 +776,17 @@ static void ExportCurveTriangleVcol(ParticleCurveData *CData, for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) { for(int section = 0; section < resol; section++) { - cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve])); + cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve])); vertexindex++; - cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve])); + cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve])); vertexindex++; - cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve])); + cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve])); vertexindex++; - cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve])); + cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve])); vertexindex++; - cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve])); + cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve])); vertexindex++; - cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve])); + cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear_v3(CData->curve_vcol[curve])); vertexindex++; } } @@ -1004,7 +1004,7 @@ void BlenderSync::sync_curves(Mesh *mesh, for(size_t curve = 0; curve < CData.curve_vcol.size(); curve++) if(!(CData.curve_keynum[curve] <= 1 || CData.curve_length[curve] == 0.0f)) - fdata[i++] = color_srgb_to_scene_linear(CData.curve_vcol[curve]); + fdata[i++] = color_srgb_to_scene_linear_v3(CData.curve_vcol[curve]); } } } diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 54571b1fea1..f13b9db7013 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -356,7 +356,7 @@ static void attr_create_vertex_color(Scene *scene, int n = p->loop_total(); for(int i = 0; i < n; i++) { float3 color = get_float3(l->data[p->loop_start() + i].color()); - *(cdata++) = color_float_to_byte(color_srgb_to_scene_linear(color)); + *(cdata++) = color_float_to_byte(color_srgb_to_scene_linear_v3(color)); } } } @@ -380,11 +380,11 @@ static void attr_create_vertex_color(Scene *scene, face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b); uchar4 colors[4]; - colors[0] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color1()))); - colors[1] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color2()))); - colors[2] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color3()))); + colors[0] = color_float_to_byte(color_srgb_to_scene_linear_v3(get_float3(c->color1()))); + colors[1] = color_float_to_byte(color_srgb_to_scene_linear_v3(get_float3(c->color2()))); + colors[2] = color_float_to_byte(color_srgb_to_scene_linear_v3(get_float3(c->color3()))); if(nverts[i] == 4) { - colors[3] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color4()))); + colors[3] = color_float_to_byte(color_srgb_to_scene_linear_v3(get_float3(c->color4()))); } cdata[0] = colors[tri_a[0]]; diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index 92393c10893..3c769881bb7 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -815,6 +815,14 @@ void *CCL_python_module_init() PyModule_AddStringConstant(mod, "osl_version_string", "unknown"); #endif +#ifdef WITH_CYCLES_DEBUG + PyModule_AddObject(mod, "with_cycles_debug", Py_True); + Py_INCREF(Py_True); +#else + PyModule_AddObject(mod, "with_cycles_debug", Py_False); + Py_INCREF(Py_False); +#endif + #ifdef WITH_NETWORK PyModule_AddObject(mod, "with_network", Py_True); Py_INCREF(Py_True); diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 3e851adbf54..6f2e7065d97 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -247,90 +247,6 @@ void BlenderSession::free_session() delete session; } -static PassType get_pass_type(BL::RenderPass& b_pass) -{ - switch(b_pass.type()) { - case BL::RenderPass::type_COMBINED: - return PASS_COMBINED; - - case BL::RenderPass::type_Z: - return PASS_DEPTH; - case BL::RenderPass::type_MIST: - return PASS_MIST; - case BL::RenderPass::type_NORMAL: - return PASS_NORMAL; - case BL::RenderPass::type_OBJECT_INDEX: - return PASS_OBJECT_ID; - case BL::RenderPass::type_UV: - return PASS_UV; - case BL::RenderPass::type_VECTOR: - return PASS_MOTION; - case BL::RenderPass::type_MATERIAL_INDEX: - return PASS_MATERIAL_ID; - - case BL::RenderPass::type_DIFFUSE_DIRECT: - return PASS_DIFFUSE_DIRECT; - case BL::RenderPass::type_GLOSSY_DIRECT: - return PASS_GLOSSY_DIRECT; - case BL::RenderPass::type_TRANSMISSION_DIRECT: - return PASS_TRANSMISSION_DIRECT; - case BL::RenderPass::type_SUBSURFACE_DIRECT: - return PASS_SUBSURFACE_DIRECT; - - case BL::RenderPass::type_DIFFUSE_INDIRECT: - return PASS_DIFFUSE_INDIRECT; - case BL::RenderPass::type_GLOSSY_INDIRECT: - return PASS_GLOSSY_INDIRECT; - case BL::RenderPass::type_TRANSMISSION_INDIRECT: - return PASS_TRANSMISSION_INDIRECT; - case BL::RenderPass::type_SUBSURFACE_INDIRECT: - return PASS_SUBSURFACE_INDIRECT; - - case BL::RenderPass::type_DIFFUSE_COLOR: - return PASS_DIFFUSE_COLOR; - case BL::RenderPass::type_GLOSSY_COLOR: - return PASS_GLOSSY_COLOR; - case BL::RenderPass::type_TRANSMISSION_COLOR: - return PASS_TRANSMISSION_COLOR; - case BL::RenderPass::type_SUBSURFACE_COLOR: - return PASS_SUBSURFACE_COLOR; - - case BL::RenderPass::type_EMIT: - return PASS_EMISSION; - case BL::RenderPass::type_ENVIRONMENT: - return PASS_BACKGROUND; - case BL::RenderPass::type_AO: - return PASS_AO; - case BL::RenderPass::type_SHADOW: - return PASS_SHADOW; - - case BL::RenderPass::type_DIFFUSE: - case BL::RenderPass::type_COLOR: - case BL::RenderPass::type_REFRACTION: - case BL::RenderPass::type_SPECULAR: - case BL::RenderPass::type_REFLECTION: - return PASS_NONE; -#ifdef WITH_CYCLES_DEBUG - case BL::RenderPass::type_DEBUG: - { - switch(b_pass.debug_type()) { - case BL::RenderPass::debug_type_BVH_TRAVERSED_NODES: - return PASS_BVH_TRAVERSED_NODES; - case BL::RenderPass::debug_type_BVH_TRAVERSED_INSTANCES: - return PASS_BVH_TRAVERSED_INSTANCES; - case BL::RenderPass::debug_type_BVH_INTERSECTIONS: - return PASS_BVH_INTERSECTIONS; - case BL::RenderPass::debug_type_RAY_BOUNCES: - return PASS_RAY_BOUNCES; - } - break; - } -#endif - } - - return PASS_NONE; -} - static ShaderEvalType get_shader_type(const string& pass_type) { const char *shader_type = pass_type.c_str(); @@ -487,22 +403,11 @@ void BlenderSession::render() /* add passes */ array<Pass> passes; - Pass::add(PASS_COMBINED, passes); - if(session_params.device.advanced_shading) { - - /* loop over passes */ - BL::RenderLayer::passes_iterator b_pass_iter; - - for(b_rlay.passes.begin(b_pass_iter); b_pass_iter != b_rlay.passes.end(); ++b_pass_iter) { - BL::RenderPass b_pass(*b_pass_iter); - PassType pass_type = get_pass_type(b_pass); - - if(pass_type == PASS_MOTION && scene->integrator->motion_blur) - continue; - if(pass_type != PASS_NONE) - Pass::add(pass_type, passes); - } + passes = sync->sync_render_passes(b_rlay, *b_layer_iter); + } + else { + Pass::add(PASS_COMBINED, passes); } buffer_params.passes = passes; @@ -757,19 +662,25 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult& b_rr, BL::RenderPass b_pass(*b_iter); /* find matching pass type */ - PassType pass_type = get_pass_type(b_pass); + PassType pass_type = BlenderSync::get_pass_type(b_pass); int components = b_pass.channels(); - /* copy pixels */ - if(!buffers->get_pass_rect(pass_type, exposure, sample, components, &pixels[0])) + bool read = false; + if(pass_type != PASS_NONE) { + /* copy pixels */ + read = buffers->get_pass_rect(pass_type, exposure, sample, components, &pixels[0]); + } + + if(!read) { memset(&pixels[0], 0, pixels.size()*sizeof(float)); + } b_pass.rect(&pixels[0]); } } else { /* copy combined pass */ - BL::RenderPass b_combined_pass(b_rlay.passes.find_by_type(BL::RenderPass::type_COMBINED, b_rview_name.c_str())); + BL::RenderPass b_combined_pass(b_rlay.passes.find_by_name("Combined", b_rview_name.c_str())); if(buffers->get_pass_rect(PASS_COMBINED, exposure, sample, 4, &pixels[0])) b_combined_pass.rect(&pixels[0]); } diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index abec9616cff..08120a2ca28 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -481,6 +481,94 @@ void BlenderSync::sync_images() } } +/* Passes */ +PassType BlenderSync::get_pass_type(BL::RenderPass& b_pass) +{ + string name = b_pass.name(); +#define MAP_PASS(passname, passtype) if(name == passname) return passtype; + /* NOTE: Keep in sync with defined names from DNA_scene_types.h */ + MAP_PASS("Combined", PASS_COMBINED); + MAP_PASS("Depth", PASS_DEPTH); + MAP_PASS("Mist", PASS_MIST); + MAP_PASS("Normal", PASS_NORMAL); + MAP_PASS("IndexOB", PASS_OBJECT_ID); + MAP_PASS("UV", PASS_UV); + MAP_PASS("Vector", PASS_MOTION); + MAP_PASS("IndexMA", PASS_MATERIAL_ID); + + MAP_PASS("DiffDir", PASS_DIFFUSE_DIRECT); + MAP_PASS("GlossDir", PASS_GLOSSY_DIRECT); + MAP_PASS("TransDir", PASS_TRANSMISSION_DIRECT); + MAP_PASS("SubsurfaceDir", PASS_SUBSURFACE_DIRECT); + + MAP_PASS("DiffInd", PASS_DIFFUSE_INDIRECT); + MAP_PASS("GlossInd", PASS_GLOSSY_INDIRECT); + MAP_PASS("TransInd", PASS_TRANSMISSION_INDIRECT); + MAP_PASS("SubsurfaceInd", PASS_SUBSURFACE_INDIRECT); + + MAP_PASS("DiffCol", PASS_DIFFUSE_COLOR); + MAP_PASS("GlossCol", PASS_GLOSSY_COLOR); + MAP_PASS("TransCol", PASS_TRANSMISSION_COLOR); + MAP_PASS("SubsurfaceCol", PASS_SUBSURFACE_COLOR); + + MAP_PASS("Emit", PASS_EMISSION); + MAP_PASS("Env", PASS_BACKGROUND); + MAP_PASS("AO", PASS_AO); + MAP_PASS("Shadow", PASS_SHADOW); + +#ifdef __KERNEL_DEBUG__ + MAP_PASS("Debug BVH Traversed Nodes", PASS_BVH_TRAVERSED_NODES); + MAP_PASS("Debug BVH Traversed Instances", PASS_BVH_TRAVERSED_INSTANCES); + MAP_PASS("Debug BVH Intersections", PASS_BVH_INTERSECTIONS); + MAP_PASS("Debug Ray Bounces", PASS_RAY_BOUNCES); +#endif +#undef MAP_PASS + + return PASS_NONE; +} + +array<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay, + BL::SceneRenderLayer& b_srlay) +{ + array<Pass> passes; + Pass::add(PASS_COMBINED, passes); + + /* loop over passes */ + BL::RenderLayer::passes_iterator b_pass_iter; + + for(b_rlay.passes.begin(b_pass_iter); b_pass_iter != b_rlay.passes.end(); ++b_pass_iter) { + BL::RenderPass b_pass(*b_pass_iter); + PassType pass_type = get_pass_type(b_pass); + + if(pass_type == PASS_MOTION && scene->integrator->motion_blur) + continue; + if(pass_type != PASS_NONE) + Pass::add(pass_type, passes); + } + +#ifdef __KERNEL_DEBUG__ + PointerRNA crp = RNA_pointer_get(&b_srlay.ptr, "cycles"); + if(get_boolean(crp, "pass_debug_bvh_traversed_nodes")) { + b_engine.add_pass("Debug BVH Traversed Nodes", 1, "X", b_srlay.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()); + 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()); + 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()); + Pass::add(PASS_RAY_BOUNCES, passes); + } +#endif + + return passes; +} + /* Scene Parameters */ SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene, diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 1388e59f36d..bc7a4de3b36 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -68,6 +68,8 @@ public: void **python_thread_state, const char *layer = 0); void sync_render_layers(BL::SpaceView3D& b_v3d, const char *layer); + array<Pass> sync_render_passes(BL::RenderLayer& b_rlay, + BL::SceneRenderLayer& b_srlay); void sync_integrator(); void sync_camera(BL::RenderSettings& b_render, BL::Object& b_override, @@ -94,6 +96,8 @@ public: Camera *cam, int width, int height); + static PassType get_pass_type(BL::RenderPass& b_pass); + private: /* sync */ void sync_lamps(bool update_all); diff --git a/intern/cycles/device/device_split_kernel.cpp b/intern/cycles/device/device_split_kernel.cpp index 71d52bb8097..9118793aad6 100644 --- a/intern/cycles/device/device_split_kernel.cpp +++ b/intern/cycles/device/device_split_kernel.cpp @@ -19,6 +19,7 @@ #include "kernel/kernel_types.h" #include "kernel/split/kernel_split_data_types.h" +#include "util/util_logging.h" #include "util/util_time.h" CCL_NAMESPACE_BEGIN @@ -38,6 +39,8 @@ DeviceSplitKernel::DeviceSplitKernel(Device *device) : device(device) kernel_do_volume = NULL; kernel_queue_enqueue = NULL; kernel_indirect_background = NULL; + kernel_shader_setup = NULL; + kernel_shader_sort = NULL; kernel_shader_eval = NULL; kernel_holdout_emission_blurring_pathtermination_ao = NULL; kernel_subsurface_scatter = NULL; @@ -63,6 +66,8 @@ DeviceSplitKernel::~DeviceSplitKernel() delete kernel_do_volume; delete kernel_queue_enqueue; delete kernel_indirect_background; + delete kernel_shader_setup; + delete kernel_shader_sort; delete kernel_shader_eval; delete kernel_holdout_emission_blurring_pathtermination_ao; delete kernel_subsurface_scatter; @@ -88,6 +93,8 @@ bool DeviceSplitKernel::load_kernels(const DeviceRequestedFeatures& requested_fe LOAD_KERNEL(do_volume); LOAD_KERNEL(queue_enqueue); LOAD_KERNEL(indirect_background); + LOAD_KERNEL(shader_setup); + LOAD_KERNEL(shader_sort); LOAD_KERNEL(shader_eval); LOAD_KERNEL(holdout_emission_blurring_pathtermination_ao); LOAD_KERNEL(subsurface_scatter); @@ -108,6 +115,9 @@ bool DeviceSplitKernel::load_kernels(const DeviceRequestedFeatures& requested_fe size_t DeviceSplitKernel::max_elements_for_max_buffer_size(device_memory& kg, device_memory& data, uint64_t max_buffer_size) { uint64_t size_per_element = state_buffer_size(kg, data, 1024) / 1024; + VLOG(1) << "Split state element size: " + << string_human_readable_number(size_per_element) << " bytes. (" + << string_human_readable_size(size_per_element) << ")."; return max_buffer_size / size_per_element; } @@ -237,9 +247,12 @@ bool DeviceSplitKernel::path_trace(DeviceTask *task, ENQUEUE_SPLIT_KERNEL(do_volume, global_size, local_size); ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, local_size); ENQUEUE_SPLIT_KERNEL(indirect_background, global_size, local_size); + ENQUEUE_SPLIT_KERNEL(shader_setup, global_size, local_size); + ENQUEUE_SPLIT_KERNEL(shader_sort, global_size, local_size); ENQUEUE_SPLIT_KERNEL(shader_eval, global_size, local_size); ENQUEUE_SPLIT_KERNEL(holdout_emission_blurring_pathtermination_ao, global_size, local_size); ENQUEUE_SPLIT_KERNEL(subsurface_scatter, global_size, local_size); + ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, local_size); ENQUEUE_SPLIT_KERNEL(direct_lighting, global_size, local_size); ENQUEUE_SPLIT_KERNEL(shadow_blocked_ao, global_size, local_size); ENQUEUE_SPLIT_KERNEL(shadow_blocked_dl, global_size, local_size); diff --git a/intern/cycles/device/device_split_kernel.h b/intern/cycles/device/device_split_kernel.h index 55548122c0c..58c2fdbb077 100644 --- a/intern/cycles/device/device_split_kernel.h +++ b/intern/cycles/device/device_split_kernel.h @@ -61,6 +61,8 @@ private: SplitKernelFunction *kernel_do_volume; SplitKernelFunction *kernel_queue_enqueue; SplitKernelFunction *kernel_indirect_background; + SplitKernelFunction *kernel_shader_setup; + SplitKernelFunction *kernel_shader_sort; SplitKernelFunction *kernel_shader_eval; SplitKernelFunction *kernel_holdout_emission_blurring_pathtermination_ao; SplitKernelFunction *kernel_subsurface_scatter; diff --git a/intern/cycles/device/opencl/opencl.h b/intern/cycles/device/opencl/opencl.h index 764216d0dfa..d061973dcb7 100644 --- a/intern/cycles/device/opencl/opencl.h +++ b/intern/cycles/device/opencl/opencl.h @@ -31,19 +31,16 @@ CCL_NAMESPACE_BEGIN /* Work around AMD driver hangs by ensuring each command is finished before doing anything else. */ # undef clEnqueueNDRangeKernel # define clEnqueueNDRangeKernel(a, b, c, d, e, f, g, h, i) \ - clFinish(a); \ CLEW_GET_FUN(__clewEnqueueNDRangeKernel)(a, b, c, d, e, f, g, h, i); \ clFinish(a); # undef clEnqueueWriteBuffer # define clEnqueueWriteBuffer(a, b, c, d, e, f, g, h, i) \ - clFinish(a); \ CLEW_GET_FUN(__clewEnqueueWriteBuffer)(a, b, c, d, e, f, g, h, i); \ clFinish(a); # undef clEnqueueReadBuffer # define clEnqueueReadBuffer(a, b, c, d, e, f, g, h, i) \ - clFinish(a); \ CLEW_GET_FUN(__clewEnqueueReadBuffer)(a, b, c, d, e, f, g, h, i); \ clFinish(a); #endif /* CYCLES_DISABLE_DRIVER_WORKAROUNDS */ diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 3750225571d..9bb0455b9d5 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -21,6 +21,8 @@ set(SRC kernels/opencl/kernel_lamp_emission.cl kernels/opencl/kernel_do_volume.cl kernels/opencl/kernel_indirect_background.cl + kernels/opencl/kernel_shader_setup.cl + kernels/opencl/kernel_shader_sort.cl kernels/opencl/kernel_shader_eval.cl kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl kernels/opencl/kernel_subsurface_scatter.cl @@ -235,6 +237,7 @@ set(SRC_UTIL_HEADERS ) set(SRC_SPLIT_HEADERS + split/kernel_branched.h split/kernel_buffer_update.h split/kernel_data_init.h split/kernel_direct_lighting.h @@ -247,6 +250,8 @@ set(SRC_SPLIT_HEADERS split/kernel_path_init.h split/kernel_queue_enqueue.h split/kernel_scene_intersect.h + split/kernel_shader_setup.h + split/kernel_shader_sort.h split/kernel_shader_eval.h split/kernel_shadow_blocked_ao.h split/kernel_shadow_blocked_dl.h @@ -456,6 +461,8 @@ delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_scene_interse delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_lamp_emission.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl) delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_do_volume.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl) delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_indirect_background.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl) +delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shader_setup.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl) +delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shader_sort.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl) delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shader_eval.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl) delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl) delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_subsurface_scatter.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl) diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index e7957042182..58da141aed3 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -58,7 +58,7 @@ ccl_device_noinline void kernel_path_ao(KernelGlobals *kg, ShaderData *sd, ShaderData *emission_sd, PathRadiance *L, - PathState *state, + ccl_addr_space PathState *state, RNG *rng, float3 throughput, float3 ao_alpha) @@ -98,6 +98,8 @@ ccl_device_noinline void kernel_path_ao(KernelGlobals *kg, } } +#ifndef __SPLIT_KERNEL__ + ccl_device void kernel_path_indirect(KernelGlobals *kg, ShaderData *sd, ShaderData *emission_sd, @@ -818,5 +820,7 @@ ccl_device void kernel_path_trace(KernelGlobals *kg, path_rng_end(kg, rng_state, rng); } +#endif /* __SPLIT_KERNEL__ */ + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h index 085eb42325d..ddcb57161ea 100644 --- a/intern/cycles/kernel/kernel_path_branched.h +++ b/intern/cycles/kernel/kernel_path_branched.h @@ -22,7 +22,7 @@ ccl_device_inline void kernel_branched_path_ao(KernelGlobals *kg, ShaderData *sd, ShaderData *emission_sd, PathRadiance *L, - PathState *state, + ccl_addr_space PathState *state, RNG *rng, float3 throughput) { @@ -65,6 +65,7 @@ ccl_device_inline void kernel_branched_path_ao(KernelGlobals *kg, } } +#ifndef __SPLIT_KERNEL__ /* bounce off surface and integrate indirect light */ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGlobals *kg, @@ -648,6 +649,8 @@ ccl_device void kernel_branched_path_trace(KernelGlobals *kg, path_rng_end(kg, rng_state, rng); } +#endif /* __SPLIT_KERNEL__ */ + #endif /* __BRANCHED_PATH__ */ CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_path_surface.h b/intern/cycles/kernel/kernel_path_surface.h index 076c82f3853..bd4ba775b4d 100644 --- a/intern/cycles/kernel/kernel_path_surface.h +++ b/intern/cycles/kernel/kernel_path_surface.h @@ -155,7 +155,7 @@ ccl_device bool kernel_branched_path_surface_bounce( ccl_addr_space float3 *throughput, ccl_addr_space PathState *state, PathRadiance *L, - Ray *ray) + ccl_addr_space Ray *ray) { /* sample BSDF */ float bsdf_pdf; diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h index baf629342b9..274713addc2 100644 --- a/intern/cycles/kernel/kernel_subsurface.h +++ b/intern/cycles/kernel/kernel_subsurface.h @@ -417,9 +417,8 @@ ccl_device_noinline void subsurface_scatter_multi_setup( subsurface_scatter_setup_diffuse_bsdf(sd, sc, weight, true, N); } -#ifndef __SPLIT_KERNEL__ /* subsurface scattering step, from a point on the surface to another nearby point on the same object */ -ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, PathState *state, +ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, ccl_global PathState *state, int state_flag, ShaderClosure *sc, uint *lcg_state, float disk_u, float disk_v, bool all) { float3 eval = make_float3(0.0f, 0.0f, 0.0f); @@ -507,7 +506,6 @@ ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, PathS /* setup diffuse bsdf */ subsurface_scatter_setup_diffuse_bsdf(sd, sc, eval, (ss_isect.num_hits > 0), N); } -#endif /* ! __SPLIT_KERNEL__ */ CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index b1269cdb6b4..9b354457b91 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -64,6 +64,18 @@ CCL_NAMESPACE_BEGIN # define WORK_POOL_SIZE WORK_POOL_SIZE_CPU #endif + +#define SHADER_SORT_BLOCK_SIZE 2048 + +#ifdef __KERNEL_OPENCL__ +# define SHADER_SORT_LOCAL_SIZE 64 +#elif defined(__KERNEL_CUDA__) +# define SHADER_SORT_LOCAL_SIZE 32 +#else +# define SHADER_SORT_LOCAL_SIZE 1 +#endif + + /* device capabilities */ #ifdef __KERNEL_CPU__ # ifdef __KERNEL_SSE2__ @@ -71,22 +83,18 @@ CCL_NAMESPACE_BEGIN # endif # define __KERNEL_SHADING__ # define __KERNEL_ADV_SHADING__ -# ifndef __SPLIT_KERNEL__ -# define __BRANCHED_PATH__ -# endif +# define __BRANCHED_PATH__ # ifdef WITH_OSL # define __OSL__ # endif -# define __SUBSURFACE__ # define __PRINCIPLED__ +# define __SUBSURFACE__ # define __CMJ__ # define __VOLUME__ # define __VOLUME_SCATTER__ # define __SHADOW_RECORD_ALL__ -# ifndef __SPLIT_KERNEL__ -# define __VOLUME_DECOUPLED__ -# define __VOLUME_RECORD_ALL__ -# endif +# define __VOLUME_DECOUPLED__ +# define __VOLUME_RECORD_ALL__ #endif /* __KERNEL_CPU__ */ #ifdef __KERNEL_CUDA__ @@ -138,6 +146,7 @@ CCL_NAMESPACE_BEGIN # define __VOLUME_SCATTER__ # define __SHADOW_RECORD_ALL__ # define __CMJ__ +# define __BRANCHED_PATH__ # endif /* __KERNEL_OPENCL_AMD__ */ # ifdef __KERNEL_OPENCL_INTEL_CPU__ @@ -1300,7 +1309,6 @@ typedef ccl_addr_space struct DebugData { * Queue 3 - Shadow ray cast kernel - AO * Queeu 4 - Shadow ray cast kernel - direct lighting */ -#define NUM_QUEUES 4 /* Queue names */ enum QueueNumber { @@ -1313,22 +1321,40 @@ enum QueueNumber { * 3. Rays to be regenerated * are enqueued here. */ - QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS = 1, + QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS, /* All rays for which a shadow ray should be cast to determine radiance * contribution for AO are enqueued here. */ - QUEUE_SHADOW_RAY_CAST_AO_RAYS = 2, + QUEUE_SHADOW_RAY_CAST_AO_RAYS, /* All rays for which a shadow ray should be cast to determine radiance * contributing for direct lighting are enqueued here. */ - QUEUE_SHADOW_RAY_CAST_DL_RAYS = 3, + QUEUE_SHADOW_RAY_CAST_DL_RAYS, + + /* Rays sorted according to shader->id */ + QUEUE_SHADER_SORTED_RAYS, + +#ifdef __BRANCHED_PATH__ + /* All rays moving to next iteration of the indirect loop for light */ + QUEUE_LIGHT_INDIRECT_ITER, +# ifdef __VOLUME__ + /* All rays moving to next iteration of the indirect loop for volumes */ + QUEUE_VOLUME_INDIRECT_ITER, +# endif +# ifdef __SUBSURFACE__ + /* All rays moving to next iteration of the indirect loop for subsurface */ + QUEUE_SUBSURFACE_INDIRECT_ITER, +# endif +#endif /* __BRANCHED_PATH__ */ + + NUM_QUEUES }; -/* We use RAY_STATE_MASK to get ray_state (enums 0 to 5) */ -#define RAY_STATE_MASK 0x007 -#define RAY_FLAG_MASK 0x0F8 +/* We use RAY_STATE_MASK to get ray_state */ +#define RAY_STATE_MASK 0x0F +#define RAY_FLAG_MASK 0xF0 enum RayState { RAY_INVALID = 0, /* Denotes ray is actively involved in path-iteration. */ @@ -1343,14 +1369,22 @@ enum RayState { RAY_TO_REGENERATE, /* Denotes ray has been regenerated */ RAY_REGENERATED, - /* Flag's ray has to execute shadow blocked function in AO part */ - RAY_SHADOW_RAY_CAST_AO = 16, - /* Flag's ray has to execute shadow blocked function in direct lighting part. */ - RAY_SHADOW_RAY_CAST_DL = 32, + /* Denotes ray is moving to next iteration of the branched indirect loop */ + RAY_LIGHT_INDIRECT_NEXT_ITER, + RAY_VOLUME_INDIRECT_NEXT_ITER, + RAY_SUBSURFACE_INDIRECT_NEXT_ITER, + + /* Ray flags */ + + /* Flags to denote that the ray is currently evaluating the branched indirect loop */ + RAY_BRANCHED_LIGHT_INDIRECT = (1 << 4), + RAY_BRANCHED_VOLUME_INDIRECT = (1 << 5), + RAY_BRANCHED_SUBSURFACE_INDIRECT = (1 << 6), + RAY_BRANCHED_INDIRECT = (RAY_BRANCHED_LIGHT_INDIRECT | RAY_BRANCHED_VOLUME_INDIRECT | RAY_BRANCHED_SUBSURFACE_INDIRECT), }; #define ASSIGN_RAY_STATE(ray_state, ray_index, state) (ray_state[ray_index] = ((ray_state[ray_index] & RAY_FLAG_MASK) | state)) -#define IS_STATE(ray_state, ray_index, state) ((ray_state[ray_index] & RAY_STATE_MASK) == state) +#define IS_STATE(ray_state, ray_index, state) ((ray_index) != QUEUE_EMPTY_SLOT && ((ray_state)[(ray_index)] & RAY_STATE_MASK) == (state)) #define ADD_RAY_FLAG(ray_state, ray_index, flag) (ray_state[ray_index] = (ray_state[ray_index] | flag)) #define REMOVE_RAY_FLAG(ray_state, ray_index, flag) (ray_state[ray_index] = (ray_state[ray_index] & (~flag))) #define IS_FLAG(ray_state, ray_index, flag) (ray_state[ray_index] & flag) diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu.h index 896b80d783e..39c9a9cf33c 100644 --- a/intern/cycles/kernel/kernels/cpu/kernel_cpu.h +++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu.h @@ -77,6 +77,8 @@ DECLARE_SPLIT_KERNEL_FUNCTION(lamp_emission) DECLARE_SPLIT_KERNEL_FUNCTION(do_volume) DECLARE_SPLIT_KERNEL_FUNCTION(queue_enqueue) DECLARE_SPLIT_KERNEL_FUNCTION(indirect_background) +DECLARE_SPLIT_KERNEL_FUNCTION(shader_setup) +DECLARE_SPLIT_KERNEL_FUNCTION(shader_sort) DECLARE_SPLIT_KERNEL_FUNCTION(shader_eval) DECLARE_SPLIT_KERNEL_FUNCTION(holdout_emission_blurring_pathtermination_ao) DECLARE_SPLIT_KERNEL_FUNCTION(subsurface_scatter) diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h index 148b2eef568..8c05dd1d9ef 100644 --- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h +++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h @@ -44,6 +44,8 @@ # include "kernel/split/kernel_do_volume.h" # include "kernel/split/kernel_queue_enqueue.h" # include "kernel/split/kernel_indirect_background.h" +# include "kernel/split/kernel_shader_setup.h" +# include "kernel/split/kernel_shader_sort.h" # include "kernel/split/kernel_shader_eval.h" # include "kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h" # include "kernel/split/kernel_subsurface_scatter.h" @@ -181,9 +183,11 @@ DEFINE_SPLIT_KERNEL_FUNCTION(lamp_emission) DEFINE_SPLIT_KERNEL_FUNCTION(do_volume) DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(queue_enqueue, QueueEnqueueLocals) DEFINE_SPLIT_KERNEL_FUNCTION(indirect_background) -DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(shader_eval, uint) +DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(shader_setup, uint) +DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(shader_sort, ShaderSortLocals) +DEFINE_SPLIT_KERNEL_FUNCTION(shader_eval) DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(holdout_emission_blurring_pathtermination_ao, BackgroundAOLocals) -DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(subsurface_scatter, uint) +DEFINE_SPLIT_KERNEL_FUNCTION(subsurface_scatter) DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(direct_lighting, uint) DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_ao) DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_dl) @@ -209,6 +213,8 @@ void KERNEL_FUNCTION_FULL_NAME(register_functions)(void(*reg)(const char* name, REGISTER(do_volume); REGISTER(queue_enqueue); REGISTER(indirect_background); + REGISTER(shader_setup); + REGISTER(shader_sort); REGISTER(shader_eval); REGISTER(holdout_emission_blurring_pathtermination_ao); REGISTER(subsurface_scatter); diff --git a/intern/cycles/kernel/kernels/cuda/kernel_split.cu b/intern/cycles/kernel/kernels/cuda/kernel_split.cu index a679eff8409..8b7f1a8d405 100644 --- a/intern/cycles/kernel/kernels/cuda/kernel_split.cu +++ b/intern/cycles/kernel/kernels/cuda/kernel_split.cu @@ -31,6 +31,8 @@ #include "kernel/split/kernel_do_volume.h" #include "kernel/split/kernel_queue_enqueue.h" #include "kernel/split/kernel_indirect_background.h" +#include "kernel/split/kernel_shader_setup.h" +#include "kernel/split/kernel_shader_sort.h" #include "kernel/split/kernel_shader_eval.h" #include "kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h" #include "kernel/split/kernel_subsurface_scatter.h" @@ -108,9 +110,11 @@ DEFINE_SPLIT_KERNEL_FUNCTION(lamp_emission) DEFINE_SPLIT_KERNEL_FUNCTION(do_volume) DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(queue_enqueue, QueueEnqueueLocals) DEFINE_SPLIT_KERNEL_FUNCTION(indirect_background) -DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(shader_eval, uint) +DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(shader_setup, uint) +DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(shader_sort, ShaderSortLocals) +DEFINE_SPLIT_KERNEL_FUNCTION(shader_eval) DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(holdout_emission_blurring_pathtermination_ao, BackgroundAOLocals) -DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(subsurface_scatter, uint) +DEFINE_SPLIT_KERNEL_FUNCTION(subsurface_scatter) DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(direct_lighting, uint) DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_ao) DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_dl) diff --git a/intern/cycles/kernel/kernels/opencl/kernel_shader_eval.cl b/intern/cycles/kernel/kernels/opencl/kernel_shader_eval.cl index 6baee460986..5bfb31b193a 100644 --- a/intern/cycles/kernel/kernels/opencl/kernel_shader_eval.cl +++ b/intern/cycles/kernel/kernels/opencl/kernel_shader_eval.cl @@ -22,6 +22,5 @@ __kernel void kernel_ocl_path_trace_shader_eval( ccl_global char *kg, ccl_constant KernelData *data) { - ccl_local unsigned int local_queue_atomics; - kernel_shader_eval((KernelGlobals*)kg, &local_queue_atomics); + kernel_shader_eval((KernelGlobals*)kg); } diff --git a/intern/cycles/kernel/kernels/opencl/kernel_shader_setup.cl b/intern/cycles/kernel/kernels/opencl/kernel_shader_setup.cl new file mode 100644 index 00000000000..38bfd04ad4c --- /dev/null +++ b/intern/cycles/kernel/kernels/opencl/kernel_shader_setup.cl @@ -0,0 +1,27 @@ +/* + * Copyright 2011-2017 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kernel/kernel_compat_opencl.h" +#include "kernel/split/kernel_split_common.h" +#include "kernel/split/kernel_shader_setup.h" + +__kernel void kernel_ocl_path_trace_shader_setup( + ccl_global char *kg, + ccl_constant KernelData *data) +{ + ccl_local unsigned int local_queue_atomics; + kernel_shader_setup((KernelGlobals*)kg, &local_queue_atomics); +} diff --git a/intern/cycles/kernel/kernels/opencl/kernel_shader_sort.cl b/intern/cycles/kernel/kernels/opencl/kernel_shader_sort.cl new file mode 100644 index 00000000000..6f722915d45 --- /dev/null +++ b/intern/cycles/kernel/kernels/opencl/kernel_shader_sort.cl @@ -0,0 +1,28 @@ +/* + * Copyright 2011-2017 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kernel/kernel_compat_opencl.h" +#include "kernel/split/kernel_split_common.h" +#include "kernel/split/kernel_shader_sort.h" + +__attribute__((reqd_work_group_size(64, 1, 1))) +__kernel void kernel_ocl_path_trace_shader_sort( + ccl_global char *kg, + ccl_constant KernelData *data) +{ + ccl_local ShaderSortLocals locals; + kernel_shader_sort((KernelGlobals*)kg, &locals); +} diff --git a/intern/cycles/kernel/kernels/opencl/kernel_split.cl b/intern/cycles/kernel/kernels/opencl/kernel_split.cl index 732cda30115..8de82db7afe 100644 --- a/intern/cycles/kernel/kernels/opencl/kernel_split.cl +++ b/intern/cycles/kernel/kernels/opencl/kernel_split.cl @@ -23,6 +23,8 @@ #include "kernel/kernels/opencl/kernel_do_volume.cl" #include "kernel/kernels/opencl/kernel_indirect_background.cl" #include "kernel/kernels/opencl/kernel_queue_enqueue.cl" +#include "kernel/kernels/opencl/kernel_shader_setup.cl" +#include "kernel/kernels/opencl/kernel_shader_sort.cl" #include "kernel/kernels/opencl/kernel_shader_eval.cl" #include "kernel/kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl" #include "kernel/kernels/opencl/kernel_subsurface_scatter.cl" diff --git a/intern/cycles/kernel/kernels/opencl/kernel_subsurface_scatter.cl b/intern/cycles/kernel/kernels/opencl/kernel_subsurface_scatter.cl index 7a1838e485f..99b74a1802b 100644 --- a/intern/cycles/kernel/kernels/opencl/kernel_subsurface_scatter.cl +++ b/intern/cycles/kernel/kernels/opencl/kernel_subsurface_scatter.cl @@ -22,6 +22,5 @@ __kernel void kernel_ocl_path_trace_subsurface_scatter( ccl_global char *kg, ccl_constant KernelData *data) { - ccl_local unsigned int local_queue_atomics; - kernel_subsurface_scatter((KernelGlobals*)kg, &local_queue_atomics); + kernel_subsurface_scatter((KernelGlobals*)kg); } diff --git a/intern/cycles/kernel/split/kernel_branched.h b/intern/cycles/kernel/split/kernel_branched.h new file mode 100644 index 00000000000..c7bc1b4df0a --- /dev/null +++ b/intern/cycles/kernel/split/kernel_branched.h @@ -0,0 +1,150 @@ +/* + * Copyright 2011-2017 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +CCL_NAMESPACE_BEGIN + +#ifdef __BRANCHED_PATH__ + +/* sets up the various state needed to do an indirect loop */ +ccl_device_inline void kernel_split_branched_path_indirect_loop_init(KernelGlobals *kg, int ray_index) +{ + SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index]; + + /* save a copy of the state to restore later */ +#define BRANCHED_STORE(name) \ + branched_state->name = kernel_split_state.name[ray_index]; + + BRANCHED_STORE(path_state); + BRANCHED_STORE(throughput); + BRANCHED_STORE(ray); + BRANCHED_STORE(sd); + BRANCHED_STORE(isect); + BRANCHED_STORE(ray_state); + +#undef BRANCHED_STORE + + /* set loop counters to intial position */ + branched_state->next_closure = 0; + branched_state->next_sample = 0; +} + +/* ends an indirect loop and restores the previous state */ +ccl_device_inline void kernel_split_branched_path_indirect_loop_end(KernelGlobals *kg, int ray_index) +{ + SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index]; + + /* restore state */ +#define BRANCHED_RESTORE(name) \ + kernel_split_state.name[ray_index] = branched_state->name; + + BRANCHED_RESTORE(path_state); + BRANCHED_RESTORE(throughput); + BRANCHED_RESTORE(ray); + BRANCHED_RESTORE(sd); + BRANCHED_RESTORE(isect); + BRANCHED_RESTORE(ray_state); + +#undef BRANCHED_RESTORE + + /* leave indirect loop */ + REMOVE_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_INDIRECT); +} + +/* bounce off surface and integrate indirect light */ +ccl_device_noinline bool kernel_split_branched_path_surface_indirect_light_iter(KernelGlobals *kg, + int ray_index, + float num_samples_adjust, + ShaderData *saved_sd, + bool reset_path_state) +{ + SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index]; + + ShaderData *sd = saved_sd; + RNG rng = kernel_split_state.rng[ray_index]; + PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; + float3 throughput = branched_state->throughput; + + for(int i = branched_state->next_closure; i < sd->num_closure; i++) { + const ShaderClosure *sc = &sd->closure[i]; + + if(!CLOSURE_IS_BSDF(sc->type)) + continue; + /* transparency is not handled here, but in outer loop */ + if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) + continue; + + int num_samples; + + if(CLOSURE_IS_BSDF_DIFFUSE(sc->type)) + num_samples = kernel_data.integrator.diffuse_samples; + else if(CLOSURE_IS_BSDF_BSSRDF(sc->type)) + num_samples = 1; + else if(CLOSURE_IS_BSDF_GLOSSY(sc->type)) + num_samples = kernel_data.integrator.glossy_samples; + else + num_samples = kernel_data.integrator.transmission_samples; + + num_samples = ceil_to_int(num_samples_adjust*num_samples); + + float num_samples_inv = num_samples_adjust/num_samples; + RNG bsdf_rng = cmj_hash(rng, i); + + for(int j = branched_state->next_sample; j < num_samples; j++) { + ccl_global PathState *ps = &kernel_split_state.path_state[ray_index]; + if(reset_path_state) { + *ps = branched_state->path_state; + } + + ccl_global float3 *tp = &kernel_split_state.throughput[ray_index]; + *tp = throughput; + + ccl_global Ray *bsdf_ray = &kernel_split_state.ray[ray_index]; + + if(!kernel_branched_path_surface_bounce(kg, + &bsdf_rng, + sd, + sc, + j, + num_samples, + tp, + ps, + L, + bsdf_ray)) + { + continue; + } + + /* update state for next iteration */ + branched_state->next_closure = i; + branched_state->next_sample = j+1; + branched_state->num_samples = num_samples; + + /* start the indirect path */ + *tp *= num_samples_inv; + + return true; + } + + branched_state->next_sample = 0; + } + + return false; +} + +#endif /* __BRANCHED_PATH__ */ + +CCL_NAMESPACE_END + diff --git a/intern/cycles/kernel/split/kernel_data_init.h b/intern/cycles/kernel/split/kernel_data_init.h index 9d3d01fff75..642ccac8239 100644 --- a/intern/cycles/kernel/split/kernel_data_init.h +++ b/intern/cycles/kernel/split/kernel_data_init.h @@ -105,21 +105,16 @@ void KERNEL_FUNCTION_FULL_NAME(data_init)( /* Initialize queue data and queue index. */ if(thread_index < queuesize) { - /* Initialize active ray queue. */ - kernel_split_state.queue_data[QUEUE_ACTIVE_AND_REGENERATED_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT; - /* Initialize background and buffer update queue. */ - kernel_split_state.queue_data[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT; - /* Initialize shadow ray cast of AO queue. */ - kernel_split_state.queue_data[QUEUE_SHADOW_RAY_CAST_AO_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT; - /* Initialize shadow ray cast of direct lighting queue. */ - kernel_split_state.queue_data[QUEUE_SHADOW_RAY_CAST_DL_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT; + for(int i = 0; i < NUM_QUEUES; i++) { + kernel_split_state.queue_data[i * queuesize + thread_index] = QUEUE_EMPTY_SLOT; + } } if(thread_index == 0) { - Queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS] = 0; - Queue_index[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] = 0; - Queue_index[QUEUE_SHADOW_RAY_CAST_AO_RAYS] = 0; - Queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS] = 0; + for(int i = 0; i < NUM_QUEUES; i++) { + Queue_index[i] = 0; + } + /* The scene-intersect kernel should not use the queues very first time. * since the queue would be empty. */ diff --git a/intern/cycles/kernel/split/kernel_direct_lighting.h b/intern/cycles/kernel/split/kernel_direct_lighting.h index bdbf7387b95..3336c968a44 100644 --- a/intern/cycles/kernel/split/kernel_direct_lighting.h +++ b/intern/cycles/kernel/split/kernel_direct_lighting.h @@ -56,23 +56,6 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg, kernel_split_params.queue_size, 0); -#ifdef __COMPUTE_DEVICE_GPU__ - /* If we are executing on a GPU device, we exit all threads that are not - * required. - * - * If we are executing on a CPU device, then we need to keep all threads - * active since we have barrier() calls later in the kernel. CPU devices, - * expect all threads to execute barrier statement. - */ - if(ray_index == QUEUE_EMPTY_SLOT) { - return; - } -#endif - -#ifndef __COMPUTE_DEVICE_GPU__ - if(ray_index != QUEUE_EMPTY_SLOT) { -#endif - if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE)) { ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; ShaderData *sd = &kernel_split_state.sd[ray_index]; @@ -80,25 +63,24 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg, /* direct lighting */ #ifdef __EMISSION__ RNG rng = kernel_split_state.rng[ray_index]; + bool flag = (kernel_data.integrator.use_direct_light && (sd->flag & SD_BSDF_HAS_EVAL)); + +# ifdef __BRANCHED_PATH__ + if(flag && kernel_data.integrator.branched) { + flag = false; + enqueue_flag = 1; + } +# endif /* __BRANCHED_PATH__ */ + # ifdef __SHADOW_TRICKS__ if(flag && state->flag & PATH_RAY_SHADOW_CATCHER) { flag = false; - ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index]; - float3 throughput = kernel_split_state.throughput[ray_index]; - PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; - kernel_branched_path_surface_connect_light(kg, - &rng, - sd, - emission_sd, - state, - throughput, - 1.0f, - L, - 1); + enqueue_flag = 1; } # endif /* __SHADOW_TRICKS__ */ + if(flag) { /* Sample illumination from lights to find path contribution. */ float light_t = path_state_rng_1D(kg, &rng, state, PRNG_LIGHT); @@ -129,7 +111,6 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg, kernel_split_state.bsdf_eval[ray_index] = L_light; kernel_split_state.is_lamp[ray_index] = is_lamp; /* Mark ray state for next shadow kernel. */ - ADD_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL); enqueue_flag = 1; } } @@ -138,10 +119,6 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg, #endif /* __EMISSION__ */ } -#ifndef __COMPUTE_DEVICE_GPU__ - } -#endif - #ifdef __EMISSION__ /* Enqueue RAY_SHADOW_RAY_CAST_DL rays. */ enqueue_ray_index_local(ray_index, @@ -152,6 +129,27 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg, kernel_split_state.queue_data, kernel_split_params.queue_index); #endif + +#ifdef __BRANCHED_PATH__ + /* Enqueue RAY_LIGHT_INDIRECT_NEXT_ITER rays + * this is the last kernel before next_iteration_setup that uses local atomics so we do this here + */ + ccl_barrier(CCL_LOCAL_MEM_FENCE); + if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) { + *local_queue_atomics = 0; + } + ccl_barrier(CCL_LOCAL_MEM_FENCE); + + ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0); + enqueue_ray_index_local(ray_index, + QUEUE_LIGHT_INDIRECT_ITER, + IS_STATE(kernel_split_state.ray_state, ray_index, RAY_LIGHT_INDIRECT_NEXT_ITER), + kernel_split_params.queue_size, + local_queue_atomics, + kernel_split_state.queue_data, + kernel_split_params.queue_index); + +#endif /* __BRANCHED_PATH__ */ } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/split/kernel_do_volume.h b/intern/cycles/kernel/split/kernel_do_volume.h index 47d3c280831..182e6c6e4fa 100644 --- a/intern/cycles/kernel/split/kernel_do_volume.h +++ b/intern/cycles/kernel/split/kernel_do_volume.h @@ -16,6 +16,81 @@ CCL_NAMESPACE_BEGIN +#if defined(__BRANCHED_PATH__) && defined(__VOLUME__) + +ccl_device_inline void kernel_split_branched_path_volume_indirect_light_init(KernelGlobals *kg, int ray_index) +{ + kernel_split_branched_path_indirect_loop_init(kg, ray_index); + + ADD_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_VOLUME_INDIRECT); +} + +ccl_device_noinline bool kernel_split_branched_path_volume_indirect_light_iter(KernelGlobals *kg, int ray_index) +{ + SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index]; + + ShaderData *sd = &kernel_split_state.sd[ray_index]; + RNG rng = kernel_split_state.rng[ray_index]; + PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; + ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index]; + + /* GPU: no decoupled ray marching, scatter probalistically */ + int num_samples = kernel_data.integrator.volume_samples; + float num_samples_inv = 1.0f/num_samples; + + Ray volume_ray = branched_state->ray; + volume_ray.t = (!IS_STATE(&branched_state->ray_state, 0, RAY_HIT_BACKGROUND)) ? branched_state->isect.t : FLT_MAX; + + bool heterogeneous = volume_stack_is_heterogeneous(kg, branched_state->path_state.volume_stack); + + for(int j = branched_state->next_sample; j < num_samples; j++) { + ccl_global PathState *ps = &kernel_split_state.path_state[ray_index]; + *ps = branched_state->path_state; + + ccl_global Ray *pray = &kernel_split_state.ray[ray_index]; + *pray = branched_state->ray; + + ccl_global float3 *tp = &kernel_split_state.throughput[ray_index]; + *tp = branched_state->throughput * num_samples_inv; + + /* branch RNG state */ + path_state_branch(ps, j, num_samples); + + /* integrate along volume segment with distance sampling */ + VolumeIntegrateResult result = kernel_volume_integrate( + kg, ps, sd, &volume_ray, L, tp, &rng, heterogeneous); + +# ifdef __VOLUME_SCATTER__ + if(result == VOLUME_PATH_SCATTERED) { + /* direct lighting */ + kernel_path_volume_connect_light(kg, &rng, sd, emission_sd, *tp, &branched_state->path_state, L); + + /* indirect light bounce */ + if(!kernel_path_volume_bounce(kg, &rng, sd, tp, ps, L, pray)) { + continue; + } + + /* start the indirect path */ + branched_state->next_closure = 0; + branched_state->next_sample = j+1; + branched_state->num_samples = num_samples; + + return true; + } +# endif + } + + kernel_split_branched_path_indirect_loop_end(kg, ray_index); + + /* todo: avoid this calculation using decoupled ray marching */ + float3 throughput = kernel_split_state.throughput[ray_index]; + kernel_volume_shadow(kg, emission_sd, &kernel_split_state.path_state[ray_index], &volume_ray, &throughput); + kernel_split_state.throughput[ray_index] = throughput; + + return false; +} + +#endif /* __BRANCHED_PATH__ && __VOLUME__ */ ccl_device void kernel_do_volume(KernelGlobals *kg) { @@ -23,37 +98,37 @@ ccl_device void kernel_do_volume(KernelGlobals *kg) /* We will empty this queue in this kernel. */ if(ccl_global_id(0) == 0 && ccl_global_id(1) == 0) { kernel_split_params.queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS] = 0; +# ifdef __BRANCHED_PATH__ + kernel_split_params.queue_index[QUEUE_VOLUME_INDIRECT_ITER] = 0; +# endif /* __BRANCHED_PATH__ */ } - /* Fetch use_queues_flag. */ - char local_use_queues_flag = *kernel_split_params.use_queues_flag; - ccl_barrier(CCL_LOCAL_MEM_FENCE); int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0); - if(local_use_queues_flag) { + + if(*kernel_split_params.use_queues_flag) { ray_index = get_ray_index(kg, ray_index, QUEUE_ACTIVE_AND_REGENERATED_RAYS, kernel_split_state.queue_data, kernel_split_params.queue_size, 1); - if(ray_index == QUEUE_EMPTY_SLOT) { - return; - } } - if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE) || - IS_STATE(kernel_split_state.ray_state, ray_index, RAY_HIT_BACKGROUND)) { + ccl_global char *ray_state = kernel_split_state.ray_state; - bool hit = ! IS_STATE(kernel_split_state.ray_state, ray_index, RAY_HIT_BACKGROUND); + PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; + ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; - PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; - ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; + ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index]; + ccl_global Ray *ray = &kernel_split_state.ray[ray_index]; + RNG rng = kernel_split_state.rng[ray_index]; + ccl_global Intersection *isect = &kernel_split_state.isect[ray_index]; + ShaderData *sd = &kernel_split_state.sd[ray_index]; + ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index]; - ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index]; - ccl_global Ray *ray = &kernel_split_state.ray[ray_index]; - RNG rng = kernel_split_state.rng[ray_index]; - ccl_global Intersection *isect = &kernel_split_state.isect[ray_index]; - ShaderData *sd = &kernel_split_state.sd[ray_index]; - ShaderData *sd_input = &kernel_split_state.sd_DL_shadow[ray_index]; + if(IS_STATE(ray_state, ray_index, RAY_ACTIVE) || + IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) { + + bool hit = ! IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND); /* Sanitize volume stack. */ if(!hit) { @@ -64,31 +139,68 @@ ccl_device void kernel_do_volume(KernelGlobals *kg) Ray volume_ray = *ray; volume_ray.t = (hit)? isect->t: FLT_MAX; - bool heterogeneous = volume_stack_is_heterogeneous(kg, state->volume_stack); +# ifdef __BRANCHED_PATH__ + if(!kernel_data.integrator.branched || IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) { +# endif /* __BRANCHED_PATH__ */ + bool heterogeneous = volume_stack_is_heterogeneous(kg, state->volume_stack); - { - /* integrate along volume segment with distance sampling */ - VolumeIntegrateResult result = kernel_volume_integrate( - kg, state, sd, &volume_ray, L, throughput, &rng, heterogeneous); + { + /* integrate along volume segment with distance sampling */ + VolumeIntegrateResult result = kernel_volume_integrate( + kg, state, sd, &volume_ray, L, throughput, &rng, heterogeneous); # ifdef __VOLUME_SCATTER__ - if(result == VOLUME_PATH_SCATTERED) { - /* direct lighting */ - kernel_path_volume_connect_light(kg, &rng, sd, sd_input, *throughput, state, L); - - /* indirect light bounce */ - if(kernel_path_volume_bounce(kg, &rng, sd, throughput, state, L, ray)) - ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_REGENERATED); - else - ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_UPDATE_BUFFER); + if(result == VOLUME_PATH_SCATTERED) { + /* direct lighting */ + kernel_path_volume_connect_light(kg, &rng, sd, emission_sd, *throughput, state, L); + + /* indirect light bounce */ + if(kernel_path_volume_bounce(kg, &rng, sd, throughput, state, L, ray)) { + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED); + } + else { + kernel_split_path_end(kg, ray_index); + } + } +# endif /* __VOLUME_SCATTER__ */ + } + +# ifdef __BRANCHED_PATH__ + } + else { + kernel_split_branched_path_volume_indirect_light_init(kg, ray_index); + + if(kernel_split_branched_path_volume_indirect_light_iter(kg, ray_index)) { + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED); } -# endif } +# endif /* __BRANCHED_PATH__ */ } + kernel_split_state.rng[ray_index] = rng; } -#endif +# ifdef __BRANCHED_PATH__ + /* iter loop */ + ray_index = get_ray_index(kg, ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0), + QUEUE_VOLUME_INDIRECT_ITER, + kernel_split_state.queue_data, + kernel_split_params.queue_size, + 1); + + if(IS_STATE(ray_state, ray_index, RAY_VOLUME_INDIRECT_NEXT_ITER)) { + /* for render passes, sum and reset indirect light pass variables + * for the next samples */ + path_radiance_sum_indirect(&kernel_split_state.path_radiance[ray_index]); + path_radiance_reset_indirect(&kernel_split_state.path_radiance[ray_index]); + + if(kernel_split_branched_path_volume_indirect_light_iter(kg, ray_index)) { + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED); + } + } +# endif /* __BRANCHED_PATH__ */ + +#endif /* __VOLUME__ */ } diff --git a/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h index 89adeb64c8a..87498910d38 100644 --- a/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h +++ b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h @@ -52,6 +52,7 @@ CCL_NAMESPACE_BEGIN * - QUEUE_SHADOW_RAY_CAST_AO_RAYS will be filled with rays marked with * flag RAY_SHADOW_RAY_CAST_AO */ + ccl_device void kernel_holdout_emission_blurring_pathtermination_ao( KernelGlobals *kg, ccl_local_param BackgroundAOLocals *locals) @@ -62,8 +63,9 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao( } ccl_barrier(CCL_LOCAL_MEM_FENCE); +#ifdef __AO__ char enqueue_flag = 0; - char enqueue_flag_AO_SHADOW_RAY_CAST = 0; +#endif int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0); ray_index = get_ray_index(kg, ray_index, QUEUE_ACTIVE_AND_REGENERATED_RAYS, @@ -155,8 +157,7 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao( kernel_split_state.L_transparent[ray_index] += average(holdout_weight*throughput); } if(sd->object_flag & SD_OBJECT_HOLDOUT_MASK) { - ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); - enqueue_flag = 1; + kernel_split_path_end(kg, ray_index); } } #endif /* __HOLDOUT__ */ @@ -164,18 +165,31 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao( if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; - /* Holdout mask objects do not write data passes. */ - kernel_write_data_passes(kg, - buffer, - L, - sd, - sample, - state, - throughput); + +#ifdef __BRANCHED_PATH__ + if(!IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) +#endif /* __BRANCHED_PATH__ */ + { + /* Holdout mask objects do not write data passes. */ + kernel_write_data_passes(kg, + buffer, + L, + sd, + sample, + state, + throughput); + } + /* Blurring of bsdf after bounces, for rays that have a small likelihood * of following this particular path (diffuse, rough glossy. */ - if(kernel_data.integrator.filter_glossy != FLT_MAX) { +#ifndef __BRANCHED_PATH__ + if(kernel_data.integrator.filter_glossy != FLT_MAX) +#else + if(kernel_data.integrator.filter_glossy != FLT_MAX && + (!kernel_data.integrator.branched || IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT))) +#endif /* __BRANCHED_PATH__ */ + { float blur_pdf = kernel_data.integrator.filter_glossy*state->min_ray_pdf; if(blur_pdf < 1.0f) { float blur_roughness = sqrtf(1.0f - blur_pdf)*0.5f; @@ -201,19 +215,32 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao( * mainly due to the mixed in MIS that we use. gives too many unneeded * shader evaluations, only need emission if we are going to terminate. */ +#ifndef __BRANCHED_PATH__ float probability = path_state_terminate_probability(kg, state, throughput); +#else + float probability = 1.0f; + + if(!kernel_data.integrator.branched) { + probability = path_state_terminate_probability(kg, state, throughput); + } + else if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) { + int num_samples = kernel_split_state.branched_state[ray_index].num_samples; + probability = path_state_terminate_probability(kg, state, throughput*num_samples); + } + else if(state->flag & PATH_RAY_TRANSPARENT) { + probability = path_state_terminate_probability(kg, state, throughput); + } +#endif if(probability == 0.0f) { - ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); - enqueue_flag = 1; + kernel_split_path_end(kg, ray_index); } if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { if(probability != 1.0f) { float terminate = path_state_rng_1D_for_decision(kg, &rng, state, PRNG_TERMINATE); if(terminate >= probability) { - ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); - enqueue_flag = 1; + kernel_split_path_end(kg, ray_index); } else { kernel_split_state.throughput[ray_index] = throughput/probability; @@ -225,61 +252,23 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao( #ifdef __AO__ if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { /* ambient occlusion */ - if(kernel_data.integrator.use_ambient_occlusion || - (sd->flag & SD_AO)) - { - /* todo: solve correlation */ - float bsdf_u, bsdf_v; - path_state_rng_2D(kg, &rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v); - - float ao_factor = kernel_data.background.ao_factor; - float3 ao_N; - kernel_split_state.ao_bsdf[ray_index] = shader_bsdf_ao(kg, sd, ao_factor, &ao_N); - kernel_split_state.ao_alpha[ray_index] = shader_bsdf_alpha(kg, sd); - - float3 ao_D; - float ao_pdf; - sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); - - if(dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f) { - Ray _ray; - _ray.P = ray_offset(sd->P, sd->Ng); - _ray.D = ao_D; - _ray.t = kernel_data.background.ao_distance; -#ifdef __OBJECT_MOTION__ - _ray.time = sd->time; -#endif - _ray.dP = sd->dP; - _ray.dD = differential3_zero(); - kernel_split_state.ao_light_ray[ray_index] = _ray; - - ADD_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO); - enqueue_flag_AO_SHADOW_RAY_CAST = 1; - } + if(kernel_data.integrator.use_ambient_occlusion || (sd->flag & SD_AO)) { + enqueue_flag = 1; } } #endif /* __AO__ */ - kernel_split_state.rng[ray_index] = rng; + kernel_split_state.rng[ray_index] = rng; #ifndef __COMPUTE_DEVICE_GPU__ } #endif - /* Enqueue RAY_UPDATE_BUFFER rays. */ - enqueue_ray_index_local(ray_index, - QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS, - enqueue_flag, - kernel_split_params.queue_size, - &locals->queue_atomics_bg, - kernel_split_state.queue_data, - kernel_split_params.queue_index); - #ifdef __AO__ /* Enqueue to-shadow-ray-cast rays. */ enqueue_ray_index_local(ray_index, QUEUE_SHADOW_RAY_CAST_AO_RAYS, - enqueue_flag_AO_SHADOW_RAY_CAST, + enqueue_flag, kernel_split_params.queue_size, &locals->queue_atomics_ao, kernel_split_state.queue_data, diff --git a/intern/cycles/kernel/split/kernel_indirect_background.h b/intern/cycles/kernel/split/kernel_indirect_background.h index 8192528622e..6fbc888e358 100644 --- a/intern/cycles/kernel/split/kernel_indirect_background.h +++ b/intern/cycles/kernel/split/kernel_indirect_background.h @@ -34,7 +34,7 @@ ccl_device void kernel_indirect_background(KernelGlobals *kg) if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; if(state->bounce > kernel_data.integrator.ao_bounces) { - ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); + kernel_split_path_end(kg, ray_index); } } } @@ -63,7 +63,7 @@ ccl_device void kernel_indirect_background(KernelGlobals *kg) #ifdef __PASSES__ if(!(kernel_data.film.pass_flag & PASS_BACKGROUND)) #endif - ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); + kernel_split_path_end(kg, ray_index); } if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) { @@ -72,7 +72,7 @@ ccl_device void kernel_indirect_background(KernelGlobals *kg) float3 L_background = indirect_background(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, ray); path_radiance_accum_background(L, state, (*throughput), L_background); #endif - ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); + kernel_split_path_end(kg, ray_index); } } diff --git a/intern/cycles/kernel/split/kernel_indirect_subsurface.h b/intern/cycles/kernel/split/kernel_indirect_subsurface.h index a56e85abeb9..82bc2f01fd7 100644 --- a/intern/cycles/kernel/split/kernel_indirect_subsurface.h +++ b/intern/cycles/kernel/split/kernel_indirect_subsurface.h @@ -49,26 +49,29 @@ ccl_device void kernel_indirect_subsurface(KernelGlobals *kg) ccl_global Ray *ray = &kernel_split_state.ray[ray_index]; ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index]; - if(IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER)) { - ccl_addr_space SubsurfaceIndirectRays *ss_indirect = &kernel_split_state.ss_rays[ray_index]; - kernel_path_subsurface_accum_indirect(ss_indirect, L); +#ifdef __BRANCHED_PATH__ + if(!kernel_data.integrator.branched) { +#endif + if(IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER)) { + ccl_addr_space SubsurfaceIndirectRays *ss_indirect = &kernel_split_state.ss_rays[ray_index]; + kernel_path_subsurface_accum_indirect(ss_indirect, L); - /* Trace indirect subsurface rays by restarting the loop. this uses less - * stack memory than invoking kernel_path_indirect. - */ - if(ss_indirect->num_rays) { - kernel_path_subsurface_setup_indirect(kg, - ss_indirect, - state, - ray, - L, - throughput); - ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED); - } - else { - ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); + /* Trace indirect subsurface rays by restarting the loop. this uses less + * stack memory than invoking kernel_path_indirect. + */ + if(ss_indirect->num_rays) { + kernel_path_subsurface_setup_indirect(kg, + ss_indirect, + state, + ray, + L, + throughput); + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED); + } } +#ifdef __BRANCHED_PATH__ } +#endif #endif /* __SUBSURFACE__ */ diff --git a/intern/cycles/kernel/split/kernel_next_iteration_setup.h b/intern/cycles/kernel/split/kernel_next_iteration_setup.h index 1bebc16e25b..71017fed19e 100644 --- a/intern/cycles/kernel/split/kernel_next_iteration_setup.h +++ b/intern/cycles/kernel/split/kernel_next_iteration_setup.h @@ -44,6 +44,52 @@ CCL_NAMESPACE_BEGIN * - QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with * RAY_TO_REGENERATE and more RAY_UPDATE_BUFFER rays. */ + +#ifdef __BRANCHED_PATH__ +ccl_device_inline void kernel_split_branched_indirect_light_init(KernelGlobals *kg, int ray_index) +{ + kernel_split_branched_path_indirect_loop_init(kg, ray_index); + + ADD_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_LIGHT_INDIRECT); +} + +ccl_device void kernel_split_branched_indirect_light_end(KernelGlobals *kg, int ray_index) +{ + kernel_split_branched_path_indirect_loop_end(kg, ray_index); + + ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index]; + ShaderData *sd = &kernel_split_state.sd[ray_index]; + ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; + ccl_global Ray *ray = &kernel_split_state.ray[ray_index]; + + /* continue in case of transparency */ + *throughput *= shader_bsdf_transparency(kg, sd); + + if(is_zero(*throughput)) { + kernel_split_path_end(kg, ray_index); + } + else { + /* Update Path State */ + state->flag |= PATH_RAY_TRANSPARENT; + state->transparent_bounce++; + + ray->P = ray_offset(sd->P, -sd->Ng); + ray->t -= sd->ray_length; /* clipping works through transparent */ + +# ifdef __RAY_DIFFERENTIALS__ + ray->dP = sd->dP; + ray->dD.dx = -sd->dI.dx; + ray->dD.dy = -sd->dI.dy; +# endif /* __RAY_DIFFERENTIALS__ */ + +# ifdef __VOLUME__ + /* enter/exit volume */ + kernel_volume_stack_enter_exit(kg, sd, state->volume_stack); +# endif /* __VOLUME__ */ + } +} +#endif /* __BRANCHED_PATH__ */ + ccl_device void kernel_next_iteration_setup(KernelGlobals *kg, ccl_local_param unsigned int *local_queue_atomics) { @@ -67,7 +113,6 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg, kernel_split_params.queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS] = 0; } - char enqueue_flag = 0; int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0); ray_index = get_ray_index(kg, ray_index, QUEUE_ACTIVE_AND_REGENERATED_RAYS, @@ -75,102 +120,125 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg, kernel_split_params.queue_size, 0); -#ifdef __COMPUTE_DEVICE_GPU__ - /* If we are executing on a GPU device, we exit all threads that are not - * required. - * - * If we are executing on a CPU device, then we need to keep all threads - * active since we have barrier() calls later in the kernel. CPU devices, - * expect all threads to execute barrier statement. - */ - if(ray_index == QUEUE_EMPTY_SLOT) { - return; - } -#endif - -#ifndef __COMPUTE_DEVICE_GPU__ - if(ray_index != QUEUE_EMPTY_SLOT) { -#endif - - /* Load ShaderData structure. */ - PathRadiance *L = NULL; - ccl_global PathState *state = NULL; ccl_global char *ray_state = kernel_split_state.ray_state; - /* Path radiance update for AO/Direct_lighting's shadow blocked. */ - if(IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL) || - IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO)) - { - state = &kernel_split_state.path_state[ray_index]; - L = &kernel_split_state.path_radiance[ray_index]; - float3 _throughput = kernel_split_state.throughput[ray_index]; - - if(IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO)) { - float3 shadow = kernel_split_state.ao_light_ray[ray_index].P; - // TODO(mai): investigate correctness here - char update_path_radiance = (char)kernel_split_state.ao_light_ray[ray_index].t; - if(update_path_radiance) { - path_radiance_accum_ao(L, - _throughput, - kernel_split_state.ao_alpha[ray_index], - kernel_split_state.ao_bsdf[ray_index], - shadow, - state->bounce); - } - else { - path_radiance_accum_total_ao(L, _throughput, kernel_split_state.ao_bsdf[ray_index]); + bool active = IS_STATE(ray_state, ray_index, RAY_ACTIVE); + if(active) { + ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index]; + ccl_global Ray *ray = &kernel_split_state.ray[ray_index]; + RNG rng = kernel_split_state.rng[ray_index]; + ShaderData *sd = &kernel_split_state.sd[ray_index]; + ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; + PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; + +#ifdef __BRANCHED_PATH__ + if(!kernel_data.integrator.branched || IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) { +#endif + /* Compute direct lighting and next bounce. */ + if(!kernel_path_surface_bounce(kg, &rng, sd, throughput, state, L, ray)) { + kernel_split_path_end(kg, ray_index); } - REMOVE_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO); +#ifdef __BRANCHED_PATH__ } - - if(IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL)) { - float3 shadow = kernel_split_state.light_ray[ray_index].P; - // TODO(mai): investigate correctness here - char update_path_radiance = (char)kernel_split_state.light_ray[ray_index].t; - BsdfEval L_light = kernel_split_state.bsdf_eval[ray_index]; - if(update_path_radiance) { - path_radiance_accum_light(L, - _throughput, - &L_light, - shadow, - 1.0f, - state->bounce, - kernel_split_state.is_lamp[ray_index]); + else { + kernel_split_branched_indirect_light_init(kg, ray_index); + + if(kernel_split_branched_path_surface_indirect_light_iter(kg, + ray_index, + 1.0f, + &kernel_split_state.branched_state[ray_index].sd, + true)) + { + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED); } else { - path_radiance_accum_total_light(L, _throughput, &L_light); + kernel_split_branched_indirect_light_end(kg, ray_index); } - REMOVE_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL); } +#endif /* __BRANCHED_PATH__ */ + + kernel_split_state.rng[ray_index] = rng; } - if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { - ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index]; - ccl_global Ray *ray = &kernel_split_state.ray[ray_index]; - RNG rng = kernel_split_state.rng[ray_index]; - state = &kernel_split_state.path_state[ray_index]; - L = &kernel_split_state.path_radiance[ray_index]; + /* Enqueue RAY_UPDATE_BUFFER rays. */ + enqueue_ray_index_local(ray_index, + QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS, + IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER) && active, + kernel_split_params.queue_size, + local_queue_atomics, + kernel_split_state.queue_data, + kernel_split_params.queue_index); + +#ifdef __BRANCHED_PATH__ + /* iter loop */ + if(ccl_global_id(0) == 0 && ccl_global_id(1) == 0) { + kernel_split_params.queue_index[QUEUE_LIGHT_INDIRECT_ITER] = 0; + } - /* Compute direct lighting and next bounce. */ - if(!kernel_path_surface_bounce(kg, &rng, &kernel_split_state.sd[ray_index], throughput, state, L, ray)) { - ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); - enqueue_flag = 1; + ray_index = get_ray_index(kg, ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0), + QUEUE_LIGHT_INDIRECT_ITER, + kernel_split_state.queue_data, + kernel_split_params.queue_size, + 1); + + if(IS_STATE(ray_state, ray_index, RAY_LIGHT_INDIRECT_NEXT_ITER)) { + /* for render passes, sum and reset indirect light pass variables + * for the next samples */ + PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; + + path_radiance_sum_indirect(L); + path_radiance_reset_indirect(L); + + if(kernel_split_branched_path_surface_indirect_light_iter(kg, + ray_index, + 1.0f, + &kernel_split_state.branched_state[ray_index].sd, + true)) + { + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED); + } + else { + kernel_split_branched_indirect_light_end(kg, ray_index); } - kernel_split_state.rng[ray_index] = rng; } -#ifndef __COMPUTE_DEVICE_GPU__ +# ifdef __VOLUME__ + /* Enqueue RAY_VOLUME_INDIRECT_NEXT_ITER rays */ + ccl_barrier(CCL_LOCAL_MEM_FENCE); + if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) { + *local_queue_atomics = 0; } -#endif + ccl_barrier(CCL_LOCAL_MEM_FENCE); - /* Enqueue RAY_UPDATE_BUFFER rays. */ + ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0); enqueue_ray_index_local(ray_index, - QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS, - enqueue_flag, + QUEUE_VOLUME_INDIRECT_ITER, + IS_STATE(kernel_split_state.ray_state, ray_index, RAY_VOLUME_INDIRECT_NEXT_ITER), + kernel_split_params.queue_size, + local_queue_atomics, + kernel_split_state.queue_data, + kernel_split_params.queue_index); + +# endif /* __VOLUME__ */ + +# ifdef __SUBSURFACE__ + /* Enqueue RAY_SUBSURFACE_INDIRECT_NEXT_ITER rays */ + ccl_barrier(CCL_LOCAL_MEM_FENCE); + if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) { + *local_queue_atomics = 0; + } + ccl_barrier(CCL_LOCAL_MEM_FENCE); + + ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0); + enqueue_ray_index_local(ray_index, + QUEUE_SUBSURFACE_INDIRECT_ITER, + IS_STATE(kernel_split_state.ray_state, ray_index, RAY_SUBSURFACE_INDIRECT_NEXT_ITER), kernel_split_params.queue_size, local_queue_atomics, kernel_split_state.queue_data, kernel_split_params.queue_index); +# endif /* __SUBSURFACE__ */ +#endif /* __BRANCHED_PATH__ */ } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/split/kernel_shader_eval.h b/intern/cycles/kernel/split/kernel_shader_eval.h index 0f1696e34a0..2801b32f285 100644 --- a/intern/cycles/kernel/split/kernel_shader_eval.h +++ b/intern/cycles/kernel/split/kernel_shader_eval.h @@ -1,5 +1,5 @@ /* - * Copyright 2011-2015 Blender Foundation + * Copyright 2011-2017 Blender Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,54 +16,61 @@ CCL_NAMESPACE_BEGIN -/* This kernel sets up the ShaderData structure from the values computed +/* This kernel evaluates ShaderData structure from the values computed * by the previous kernels. - * - * It also identifies the rays of state RAY_TO_REGENERATE and enqueues them - * in QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. */ -ccl_device void kernel_shader_eval(KernelGlobals *kg, - ccl_local_param unsigned int *local_queue_atomics) +ccl_device void kernel_shader_eval(KernelGlobals *kg) { - /* Enqeueue RAY_TO_REGENERATE rays into QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. */ - if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) { - *local_queue_atomics = 0; - } - ccl_barrier(CCL_LOCAL_MEM_FENCE); int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0); + /* Sorting on cuda split is not implemented */ +#ifdef __KERNEL_CUDA__ + int queue_index = kernel_split_params.queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS]; +#else + int queue_index = kernel_split_params.queue_index[QUEUE_SHADER_SORTED_RAYS]; +#endif + if(ray_index >= queue_index) { + return; + } ray_index = get_ray_index(kg, ray_index, +#ifdef __KERNEL_CUDA__ QUEUE_ACTIVE_AND_REGENERATED_RAYS, +#else + QUEUE_SHADER_SORTED_RAYS, +#endif kernel_split_state.queue_data, kernel_split_params.queue_size, 0); - char enqueue_flag = 0; - if((ray_index != QUEUE_EMPTY_SLOT) && IS_STATE(kernel_split_state.ray_state, ray_index, RAY_TO_REGENERATE)) { - enqueue_flag = 1; + if(ray_index == QUEUE_EMPTY_SLOT) { + return; } - enqueue_ray_index_local(ray_index, - QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS, - enqueue_flag, - kernel_split_params.queue_size, - local_queue_atomics, - kernel_split_state.queue_data, - kernel_split_params.queue_index); - - /* Continue on with shader evaluation. */ - if((ray_index != QUEUE_EMPTY_SLOT) && IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE)) { - Intersection isect = kernel_split_state.isect[ray_index]; + ccl_global char *ray_state = kernel_split_state.ray_state; + if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { RNG rng = kernel_split_state.rng[ray_index]; ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; - Ray ray = kernel_split_state.ray[ray_index]; - shader_setup_from_ray(kg, - &kernel_split_state.sd[ray_index], - &isect, - &ray); +#ifndef __BRANCHED_PATH__ float rbsdf = path_state_rng_1D_for_decision(kg, &rng, state, PRNG_BSDF); shader_eval_surface(kg, &kernel_split_state.sd[ray_index], &rng, state, rbsdf, state->flag, SHADER_CONTEXT_MAIN); +#else + ShaderContext ctx = SHADER_CONTEXT_MAIN; + float rbsdf = 0.0f; + + if(!kernel_data.integrator.branched || IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) { + rbsdf = path_state_rng_1D_for_decision(kg, &rng, state, PRNG_BSDF); + + } + + if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) { + ctx = SHADER_CONTEXT_INDIRECT; + } + + shader_eval_surface(kg, &kernel_split_state.sd[ray_index], &rng, state, rbsdf, state->flag, ctx); + shader_merge_closures(&kernel_split_state.sd[ray_index]); +#endif /* __BRANCHED_PATH__ */ + kernel_split_state.rng[ray_index] = rng; } } diff --git a/intern/cycles/kernel/split/kernel_shader_setup.h b/intern/cycles/kernel/split/kernel_shader_setup.h new file mode 100644 index 00000000000..0432689d9fa --- /dev/null +++ b/intern/cycles/kernel/split/kernel_shader_setup.h @@ -0,0 +1,70 @@ +/* + * Copyright 2011-2017 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +CCL_NAMESPACE_BEGIN + +/* This kernel sets up the ShaderData structure from the values computed + * by the previous kernels. + * + * It also identifies the rays of state RAY_TO_REGENERATE and enqueues them + * in QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. + */ +ccl_device void kernel_shader_setup(KernelGlobals *kg, + ccl_local_param unsigned int *local_queue_atomics) +{ + /* Enqeueue RAY_TO_REGENERATE rays into QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. */ + if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) { + *local_queue_atomics = 0; + } + ccl_barrier(CCL_LOCAL_MEM_FENCE); + + int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0); + int queue_index = kernel_split_params.queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS]; + if(ray_index >= queue_index) { + return; + } + ray_index = get_ray_index(kg, ray_index, + QUEUE_ACTIVE_AND_REGENERATED_RAYS, + kernel_split_state.queue_data, + kernel_split_params.queue_size, + 0); + + if(ray_index == QUEUE_EMPTY_SLOT) { + return; + } + + char enqueue_flag = (IS_STATE(kernel_split_state.ray_state, ray_index, RAY_TO_REGENERATE)) ? 1 : 0; + enqueue_ray_index_local(ray_index, + QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS, + enqueue_flag, + kernel_split_params.queue_size, + local_queue_atomics, + kernel_split_state.queue_data, + kernel_split_params.queue_index); + + /* Continue on with shader evaluation. */ + if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE)) { + Intersection isect = kernel_split_state.isect[ray_index]; + Ray ray = kernel_split_state.ray[ray_index]; + + shader_setup_from_ray(kg, + &kernel_split_state.sd[ray_index], + &isect, + &ray); + } +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/split/kernel_shader_sort.h b/intern/cycles/kernel/split/kernel_shader_sort.h new file mode 100644 index 00000000000..297decb0bc2 --- /dev/null +++ b/intern/cycles/kernel/split/kernel_shader_sort.h @@ -0,0 +1,97 @@ +/* + * Copyright 2011-2017 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +CCL_NAMESPACE_BEGIN + + +ccl_device void kernel_shader_sort(KernelGlobals *kg, + ccl_local_param ShaderSortLocals *locals) +{ +#ifndef __KERNEL_CUDA__ + int tid = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0); + uint qsize = kernel_split_params.queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS]; + if(tid == 0) { + kernel_split_params.queue_index[QUEUE_SHADER_SORTED_RAYS] = qsize; + } + + uint offset = (tid/SHADER_SORT_LOCAL_SIZE)*SHADER_SORT_BLOCK_SIZE; + if(offset >= qsize) { + return; + } + + int lid = ccl_local_id(1) * ccl_local_size(0) + ccl_local_id(0); + uint input = QUEUE_ACTIVE_AND_REGENERATED_RAYS * (kernel_split_params.queue_size); + uint output = QUEUE_SHADER_SORTED_RAYS * (kernel_split_params.queue_size); + ccl_local uint *local_value = &locals->local_value[0]; + ccl_local ushort *local_index = &locals->local_index[0]; + + /* copy to local memory */ + for (uint i = 0; i < SHADER_SORT_BLOCK_SIZE; i += SHADER_SORT_LOCAL_SIZE) { + uint idx = offset + i + lid; + uint add = input + idx; + uint value = (~0); + if(idx < qsize) { + int ray_index = kernel_split_state.queue_data[add]; + bool valid = (ray_index != QUEUE_EMPTY_SLOT) && IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE); + if(valid) { + value = kernel_split_state.sd[ray_index].shader & SHADER_MASK; + } + } + local_value[i + lid] = value; + local_index[i + lid] = i + lid; + } + ccl_barrier(CCL_LOCAL_MEM_FENCE); + + /* skip sorting for cpu split kernel */ +# ifdef __KERNEL_OPENCL__ + + /* bitonic sort */ + for (uint length = 1; length < SHADER_SORT_BLOCK_SIZE; length <<= 1) { + for (uint inc = length; inc > 0; inc >>= 1) { + for (uint ii = 0; ii < SHADER_SORT_BLOCK_SIZE; ii += SHADER_SORT_LOCAL_SIZE) { + uint i = lid + ii; + bool direction = ((i & (length << 1)) != 0); + uint j = i ^ inc; + ushort ioff = local_index[i]; + ushort joff = local_index[j]; + uint iKey = local_value[ioff]; + uint jKey = local_value[joff]; + bool smaller = (jKey < iKey) || (jKey == iKey && j < i); + bool swap = smaller ^ (j < i) ^ direction; + ccl_barrier(CCL_LOCAL_MEM_FENCE); + local_index[i] = (swap) ? joff : ioff; + local_index[j] = (swap) ? ioff : joff; + ccl_barrier(CCL_LOCAL_MEM_FENCE); + } + } + } +# endif /* __KERNEL_OPENCL__ */ + + /* copy to destination */ + for (uint i = 0; i < SHADER_SORT_BLOCK_SIZE; i += SHADER_SORT_LOCAL_SIZE) { + uint idx = offset + i + lid; + uint lidx = local_index[i + lid]; + uint outi = output + idx; + uint ini = input + offset + lidx; + uint value = local_value[lidx]; + if(idx < qsize) { + kernel_split_state.queue_data[outi] = (value == (~0)) ? QUEUE_EMPTY_SLOT : kernel_split_state.queue_data[ini]; + } + } +#endif /* __KERNEL_CUDA__ */ +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/split/kernel_shadow_blocked_ao.h b/intern/cycles/kernel/split/kernel_shadow_blocked_ao.h index 4243e18de72..474286285a9 100644 --- a/intern/cycles/kernel/split/kernel_shadow_blocked_ao.h +++ b/intern/cycles/kernel/split/kernel_shadow_blocked_ao.h @@ -29,31 +29,29 @@ ccl_device void kernel_shadow_blocked_ao(KernelGlobals *kg) kernel_split_state.queue_data, kernel_split_params.queue_size, 1); } - if(ray_index == QUEUE_EMPTY_SLOT) + if(ray_index == QUEUE_EMPTY_SLOT) { return; + } - /* Flag determining if we need to update L. */ - char update_path_radiance = 0; - - if(IS_FLAG(kernel_split_state.ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO)) { - ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; - ccl_global Ray *light_ray_global = &kernel_split_state.ao_light_ray[ray_index]; - - float3 shadow; - Ray ray = *light_ray_global; - update_path_radiance = !(shadow_blocked(kg, - &kernel_split_state.sd_DL_shadow[ray_index], - state, - &ray, - &shadow)); - - *light_ray_global = ray; - /* We use light_ray_global's P and t to store shadow and - * update_path_radiance. - */ - light_ray_global->P = shadow; - light_ray_global->t = update_path_radiance; + ShaderData *sd = &kernel_split_state.sd[ray_index]; + ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index]; + PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; + ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; + RNG rng = kernel_split_state.rng[ray_index]; + float3 throughput = kernel_split_state.throughput[ray_index]; + +#ifdef __BRANCHED_PATH__ + if(!kernel_data.integrator.branched || IS_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_INDIRECT)) { +#endif + kernel_path_ao(kg, sd, emission_sd, L, state, &rng, throughput, shader_bsdf_alpha(kg, sd)); +#ifdef __BRANCHED_PATH__ + } + else { + kernel_branched_path_ao(kg, sd, emission_sd, L, state, &rng, throughput); } +#endif + + kernel_split_state.rng[ray_index] = rng; } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h b/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h index bb8f0157965..452b6e45a36 100644 --- a/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h +++ b/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h @@ -32,28 +32,71 @@ ccl_device void kernel_shadow_blocked_dl(KernelGlobals *kg) if(ray_index == QUEUE_EMPTY_SLOT) return; - /* Flag determining if we need to update L. */ - char update_path_radiance = 0; + ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; + Ray ray = kernel_split_state.light_ray[ray_index]; + PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; + ShaderData *sd = &kernel_split_state.sd[ray_index]; + float3 throughput = kernel_split_state.throughput[ray_index]; + RNG rng = kernel_split_state.rng[ray_index]; - if(IS_FLAG(kernel_split_state.ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL)) { - ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; - ccl_global Ray *light_ray_global = &kernel_split_state.light_ray[ray_index]; + BsdfEval L_light = kernel_split_state.bsdf_eval[ray_index]; + ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index]; + bool is_lamp = kernel_split_state.is_lamp[ray_index]; +# if defined(__BRANCHED_PATH__) || defined(__SHADOW_TRICKS__) + bool use_branched = false; + int all = 0; + + if(state->flag & PATH_RAY_SHADOW_CATCHER) { + use_branched = true; + all = 1; + } +# if defined(__BRANCHED_PATH__) + else if(kernel_data.integrator.branched) { + use_branched = true; + + if(IS_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_INDIRECT)) { + all = (kernel_data.integrator.sample_all_lights_indirect); + } + else + { + all = (kernel_data.integrator.sample_all_lights_direct); + } + } +# endif /* __BRANCHED_PATH__ */ + + if(use_branched) { + kernel_branched_path_surface_connect_light(kg, + &rng, + sd, + emission_sd, + state, + throughput, + 1.0f, + L, + all); + } + else +# endif /* defined(__BRANCHED_PATH__) || defined(__SHADOW_TRICKS__)*/ + { + /* trace shadow ray */ float3 shadow; - Ray ray = *light_ray_global; - update_path_radiance = !(shadow_blocked(kg, - &kernel_split_state.sd_DL_shadow[ray_index], - state, - &ray, - &shadow)); - - *light_ray_global = ray; - /* We use light_ray_global's P and t to store shadow and - * update_path_radiance. - */ - light_ray_global->P = shadow; - light_ray_global->t = update_path_radiance; + + if(!shadow_blocked(kg, + emission_sd, + state, + &ray, + &shadow)) + { + /* accumulate */ + path_radiance_accum_light(L, throughput, &L_light, shadow, 1.0f, state->bounce, is_lamp); + } + else { + path_radiance_accum_total_light(L, throughput, &L_light); + } } + + kernel_split_state.rng[ray_index] = rng; } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/split/kernel_split_common.h b/intern/cycles/kernel/split/kernel_split_common.h index 4303ba0a905..57f070d51e0 100644 --- a/intern/cycles/kernel/split/kernel_split_common.h +++ b/intern/cycles/kernel/split/kernel_split_common.h @@ -37,41 +37,42 @@ #include "util/util_atomic.h" -#include "kernel/kernel_random.h" -#include "kernel/kernel_projection.h" -#include "kernel/kernel_montecarlo.h" -#include "kernel/kernel_differential.h" -#include "kernel/kernel_camera.h" - -#include "kernel/geom/geom.h" -#include "kernel/bvh/bvh.h" - -#include "kernel/kernel_accumulate.h" -#include "kernel/kernel_shader.h" -#include "kernel/kernel_light.h" -#include "kernel/kernel_passes.h" - -#ifdef __SUBSURFACE__ -# include "kernel/kernel_subsurface.h" +#include "kernel/kernel_path.h" +#ifdef __BRANCHED_PATH__ +# include "kernel/kernel_path_branched.h" #endif -#ifdef __VOLUME__ -# include "kernel/kernel_volume.h" -#endif +#include "kernel/kernel_queues.h" +#include "kernel/kernel_work_stealing.h" -#include "kernel/kernel_path_state.h" -#include "kernel/kernel_shadow.h" -#include "kernel/kernel_emission.h" -#include "kernel/kernel_path_common.h" -#include "kernel/kernel_path_surface.h" -#include "kernel/kernel_path_volume.h" -#include "kernel/kernel_path_subsurface.h" +#ifdef __BRANCHED_PATH__ +# include "kernel/split/kernel_branched.h" +#endif -#ifdef __KERNEL_DEBUG__ -# include "kernel/kernel_debug.h" +CCL_NAMESPACE_BEGIN + +ccl_device_inline void kernel_split_path_end(KernelGlobals *kg, int ray_index) +{ + ccl_global char *ray_state = kernel_split_state.ray_state; + +#ifdef __BRANCHED_PATH__ + if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_LIGHT_INDIRECT)) { + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_LIGHT_INDIRECT_NEXT_ITER); + } + else if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_VOLUME_INDIRECT)) { + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_VOLUME_INDIRECT_NEXT_ITER); + } + else if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_SUBSURFACE_INDIRECT)) { + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_SUBSURFACE_INDIRECT_NEXT_ITER); + } + else { + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); + } +#else + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); #endif +} -#include "kernel/kernel_queues.h" -#include "kernel/kernel_work_stealing.h" +CCL_NAMESPACE_END #endif /* __KERNEL_SPLIT_H__ */ diff --git a/intern/cycles/kernel/split/kernel_split_data_types.h b/intern/cycles/kernel/split/kernel_split_data_types.h index 0af8bfc89d5..913e0dfd08d 100644 --- a/intern/cycles/kernel/split/kernel_split_data_types.h +++ b/intern/cycles/kernel/split/kernel_split_data_types.h @@ -62,7 +62,46 @@ typedef struct SplitParams { SPLIT_DATA_ENTRY(DebugData, debug_data, 1) #else # define SPLIT_DATA_DEBUG_ENTRIES -#endif +#endif /* DEBUG */ + +#ifdef __BRANCHED_PATH__ + +typedef ccl_global struct SplitBranchedState { + /* various state that must be kept and restored after an indirect loop */ + PathState path_state; + float3 throughput; + Ray ray; + + struct ShaderData sd; + Intersection isect; + + char ray_state; + + /* indirect loop state */ + int next_closure; + int next_sample; + int num_samples; + +#ifdef __SUBSURFACE__ + int ss_next_closure; + int ss_next_sample; + int next_hit; + int num_hits; + + uint lcg_state; + SubsurfaceIntersection ss_isect; + +# ifdef __VOLUME__ + VolumeStack volume_stack[VOLUME_STACK_SIZE]; +# endif /* __VOLUME__ */ +#endif /*__SUBSURFACE__ */ +} SplitBranchedState; + +#define SPLIT_DATA_BRANCHED_ENTRIES \ + SPLIT_DATA_ENTRY( SplitBranchedState, branched_state, 1) +#else +#define SPLIT_DATA_BRANCHED_ENTRIES +#endif /* __BRANCHED_PATH__ */ #define SPLIT_DATA_ENTRIES \ SPLIT_DATA_ENTRY(ccl_global RNG, rng, 1) \ @@ -72,9 +111,6 @@ typedef struct SplitParams { SPLIT_DATA_ENTRY(ccl_global Ray, ray, 1) \ SPLIT_DATA_ENTRY(ccl_global PathState, path_state, 1) \ SPLIT_DATA_ENTRY(ccl_global Intersection, isect, 1) \ - SPLIT_DATA_ENTRY(ccl_global float3, ao_alpha, 1) \ - SPLIT_DATA_ENTRY(ccl_global float3, ao_bsdf, 1) \ - SPLIT_DATA_ENTRY(ccl_global Ray, ao_light_ray, 1) \ SPLIT_DATA_ENTRY(ccl_global BsdfEval, bsdf_eval, 1) \ SPLIT_DATA_ENTRY(ccl_global int, is_lamp, 1) \ SPLIT_DATA_ENTRY(ccl_global Ray, light_ray, 1) \ @@ -82,6 +118,7 @@ typedef struct SplitParams { SPLIT_DATA_ENTRY(ccl_global uint, work_array, 1) \ SPLIT_DATA_ENTRY(ShaderData, sd, 1) \ SPLIT_DATA_ENTRY(ShaderData, sd_DL_shadow, 1) \ + SPLIT_DATA_BRANCHED_ENTRIES \ SPLIT_DATA_DEBUG_ENTRIES \ /* struct that holds pointers to data in the shared state buffer */ @@ -125,6 +162,11 @@ typedef struct BackgroundAOLocals { uint queue_atomics_ao; } BackgroundAOLocals; +typedef struct ShaderSortLocals { + uint local_value[SHADER_SORT_BLOCK_SIZE]; + ushort local_index[SHADER_SORT_BLOCK_SIZE]; +} ShaderSortLocals; + CCL_NAMESPACE_END #endif /* __KERNEL_SPLIT_DATA_TYPES_H__ */ diff --git a/intern/cycles/kernel/split/kernel_subsurface_scatter.h b/intern/cycles/kernel/split/kernel_subsurface_scatter.h index 0b4d50c70ee..8364f185d75 100644 --- a/intern/cycles/kernel/split/kernel_subsurface_scatter.h +++ b/intern/cycles/kernel/split/kernel_subsurface_scatter.h @@ -16,42 +16,206 @@ CCL_NAMESPACE_BEGIN +#if defined(__BRANCHED_PATH__) && defined(__SUBSURFACE__) -ccl_device void kernel_subsurface_scatter(KernelGlobals *kg, - ccl_local_param unsigned int* local_queue_atomics) +ccl_device_inline void kernel_split_branched_path_subsurface_indirect_light_init(KernelGlobals *kg, int ray_index) { -#ifdef __SUBSURFACE__ - if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) { - *local_queue_atomics = 0; + kernel_split_branched_path_indirect_loop_init(kg, ray_index); + + SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index]; + + branched_state->ss_next_closure = 0; + branched_state->ss_next_sample = 0; + + branched_state->num_hits = 0; + branched_state->next_hit = 0; + + ADD_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_SUBSURFACE_INDIRECT); +} + +ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_iter(KernelGlobals *kg, int ray_index) +{ + SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index]; + + ShaderData *sd = &branched_state->sd; + RNG rng = kernel_split_state.rng[ray_index]; + PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; + ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index]; + + for(int i = branched_state->ss_next_closure; i < sd->num_closure; i++) { + ShaderClosure *sc = &sd->closure[i]; + + if(!CLOSURE_IS_BSSRDF(sc->type)) + continue; + + /* set up random number generator */ + if(branched_state->ss_next_sample == 0 && branched_state->next_hit == 0 && + branched_state->next_closure == 0 && branched_state->next_sample == 0) + { + branched_state->lcg_state = lcg_state_init(&rng, + branched_state->path_state.rng_offset, + branched_state->path_state.sample, + 0x68bc21eb); + } + int num_samples = kernel_data.integrator.subsurface_samples; + float num_samples_inv = 1.0f/num_samples; + RNG bssrdf_rng = cmj_hash(rng, i); + + /* do subsurface scatter step with copy of shader data, this will + * replace the BSSRDF with a diffuse BSDF closure */ + for(int j = branched_state->ss_next_sample; j < num_samples; j++) { + ccl_global SubsurfaceIntersection *ss_isect = &branched_state->ss_isect; + float bssrdf_u, bssrdf_v; + path_branched_rng_2D(kg, + &bssrdf_rng, + &branched_state->path_state, + j, + num_samples, + PRNG_BSDF_U, + &bssrdf_u, + &bssrdf_v); + + /* intersection is expensive so avoid doing multiple times for the same input */ + if(branched_state->next_hit == 0 && branched_state->next_closure == 0 && branched_state->next_sample == 0) { + RNG lcg_state = branched_state->lcg_state; + SubsurfaceIntersection ss_isect_private; + + branched_state->num_hits = subsurface_scatter_multi_intersect(kg, + &ss_isect_private, + sd, + sc, + &lcg_state, + bssrdf_u, bssrdf_v, + true); + + branched_state->lcg_state = lcg_state; + *ss_isect = ss_isect_private; + } + +#ifdef __VOLUME__ + Ray volume_ray = branched_state->ray; + bool need_update_volume_stack = + kernel_data.integrator.use_volumes && + sd->object_flag & SD_OBJECT_INTERSECTS_VOLUME; +#endif /* __VOLUME__ */ + + /* compute lighting with the BSDF closure */ + for(int hit = branched_state->next_hit; hit < branched_state->num_hits; hit++) { + ShaderData *bssrdf_sd = &kernel_split_state.sd[ray_index]; + *bssrdf_sd = *sd; /* note: copy happens each iteration of inner loop, this is + * important as the indirect path will write into bssrdf_sd */ + + SubsurfaceIntersection ss_isect_private = *ss_isect; + subsurface_scatter_multi_setup(kg, + &ss_isect_private, + hit, + bssrdf_sd, + &branched_state->path_state, + branched_state->path_state.flag, + sc, + true); + *ss_isect = ss_isect_private; + + ccl_global PathState *hit_state = &kernel_split_state.path_state[ray_index]; + *hit_state = branched_state->path_state; + + path_state_branch(hit_state, j, num_samples); + +#ifdef __VOLUME__ + if(need_update_volume_stack) { + /* Setup ray from previous surface point to the new one. */ + float3 P = ray_offset(bssrdf_sd->P, -bssrdf_sd->Ng); + volume_ray.D = normalize_len(P - volume_ray.P, &volume_ray.t); + + /* this next part is expensive as it does scene intersection so only do once */ + if(branched_state->next_closure == 0 && branched_state->next_sample == 0) { + for(int k = 0; k < VOLUME_STACK_SIZE; k++) { + branched_state->volume_stack[k] = hit_state->volume_stack[k]; + } + + kernel_volume_stack_update_for_subsurface(kg, + emission_sd, + &volume_ray, + branched_state->volume_stack); + } + + for(int k = 0; k < VOLUME_STACK_SIZE; k++) { + hit_state->volume_stack[k] = branched_state->volume_stack[k]; + } + } +#endif /* __VOLUME__ */ + +#ifdef __EMISSION__ + if(branched_state->next_closure == 0 && branched_state->next_sample == 0) { + /* direct light */ + if(kernel_data.integrator.use_direct_light) { + int all = (kernel_data.integrator.sample_all_lights_direct) || + (branched_state->path_state.flag & PATH_RAY_SHADOW_CATCHER); + kernel_branched_path_surface_connect_light(kg, + &rng, + bssrdf_sd, + emission_sd, + hit_state, + branched_state->throughput, + num_samples_inv, + L, + all); + } + } +#endif /* __EMISSION__ */ + + /* indirect light */ + if(kernel_split_branched_path_surface_indirect_light_iter(kg, + ray_index, + num_samples_inv, + bssrdf_sd, + false)) + { + branched_state->ss_next_closure = i; + branched_state->ss_next_sample = j; + branched_state->next_hit = hit; + + return true; + } + + branched_state->next_closure = 0; + } + + branched_state->next_hit = 0; + } + + branched_state->ss_next_sample = 0; + } + + kernel_split_branched_path_indirect_loop_end(kg, ray_index); + + return false; +} + +#endif /* __BRANCHED_PATH__ && __SUBSURFACE__ */ + +ccl_device void kernel_subsurface_scatter(KernelGlobals *kg) +{ + int thread_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0); + if(thread_index == 0) { + /* We will empty both queues in this kernel. */ + kernel_split_params.queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS] = 0; + kernel_split_params.queue_index[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] = 0; } - ccl_barrier(CCL_LOCAL_MEM_FENCE); int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0); ray_index = get_ray_index(kg, ray_index, QUEUE_ACTIVE_AND_REGENERATED_RAYS, kernel_split_state.queue_data, kernel_split_params.queue_size, - 0); - -#ifdef __COMPUTE_DEVICE_GPU__ - /* If we are executing on a GPU device, we exit all threads that are not - * required. - * - * If we are executing on a CPU device, then we need to keep all threads - * active since we have barrier() calls later in the kernel. CPU devices, - * expect all threads to execute barrier statement. - */ - if(ray_index == QUEUE_EMPTY_SLOT) { - return; - } -#endif - - char enqueue_flag = 0; - -#ifndef __COMPUTE_DEVICE_GPU__ - if(ray_index != QUEUE_EMPTY_SLOT) { -#endif + 1); + get_ray_index(kg, thread_index, + QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS, + kernel_split_state.queue_data, + kernel_split_params.queue_size, + 1); +#ifdef __SUBSURFACE__ ccl_global char *ray_state = kernel_split_state.ray_state; ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; @@ -64,34 +228,85 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg, if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { if(sd->flag & SD_BSSRDF) { - if(kernel_path_subsurface_scatter(kg, - sd, - emission_sd, - L, - state, - &rng, - ray, - throughput, - ss_indirect)) { - ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); - enqueue_flag = 1; + +#ifdef __BRANCHED_PATH__ + if(!kernel_data.integrator.branched) { +#endif + if(kernel_path_subsurface_scatter(kg, + sd, + emission_sd, + L, + state, + &rng, + ray, + throughput, + ss_indirect)) { + kernel_split_path_end(kg, ray_index); + } +#ifdef __BRANCHED_PATH__ + } + else if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) { + float bssrdf_probability; + ShaderClosure *sc = subsurface_scatter_pick_closure(kg, sd, &bssrdf_probability); + + /* modify throughput for picking bssrdf or bsdf */ + *throughput *= bssrdf_probability; + + /* do bssrdf scatter step if we picked a bssrdf closure */ + if(sc) { + uint lcg_state = lcg_state_init(&rng, state->rng_offset, state->sample, 0x68bc21eb); + + float bssrdf_u, bssrdf_v; + path_state_rng_2D(kg, + &rng, + state, + PRNG_BSDF_U, + &bssrdf_u, &bssrdf_v); + subsurface_scatter_step(kg, + sd, + state, + state->flag, + sc, + &lcg_state, + bssrdf_u, bssrdf_v, + false); + } + } + else { + kernel_split_branched_path_subsurface_indirect_light_init(kg, ray_index); + + if(kernel_split_branched_path_subsurface_indirect_light_iter(kg, ray_index)) { + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED); + } } +#endif } kernel_split_state.rng[ray_index] = rng; } -#ifndef __COMPUTE_DEVICE_GPU__ +# ifdef __BRANCHED_PATH__ + if(ccl_global_id(0) == 0 && ccl_global_id(1) == 0) { + kernel_split_params.queue_index[QUEUE_SUBSURFACE_INDIRECT_ITER] = 0; } -#endif - /* Enqueue RAY_UPDATE_BUFFER rays. */ - enqueue_ray_index_local(ray_index, - QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS, - enqueue_flag, - kernel_split_params.queue_size, - local_queue_atomics, - kernel_split_state.queue_data, - kernel_split_params.queue_index); + /* iter loop */ + ray_index = get_ray_index(kg, ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0), + QUEUE_SUBSURFACE_INDIRECT_ITER, + kernel_split_state.queue_data, + kernel_split_params.queue_size, + 1); + + if(IS_STATE(ray_state, ray_index, RAY_SUBSURFACE_INDIRECT_NEXT_ITER)) { + /* for render passes, sum and reset indirect light pass variables + * for the next samples */ + path_radiance_sum_indirect(&kernel_split_state.path_radiance[ray_index]); + path_radiance_reset_indirect(&kernel_split_state.path_radiance[ray_index]); + + if(kernel_split_branched_path_subsurface_indirect_light_iter(kg, ray_index)) { + ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED); + } + } +# endif /* __BRANCHED_PATH__ */ #endif /* __SUBSURFACE__ */ diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index 4b5e4ebac00..328ff79223b 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -32,13 +32,7 @@ CCL_NAMESPACE_BEGIN ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, uint srgb, uint use_alpha) { #ifdef __KERNEL_CPU__ -# ifdef __KERNEL_SSE2__ - ssef r_ssef; - float4 &r = (float4 &)r_ssef; - r = kernel_tex_image_interp(id, x, y); -# else float4 r = kernel_tex_image_interp(id, x, y); -# endif #elif defined(__KERNEL_OPENCL__) float4 r = kernel_tex_image_interp(kg, id, x, y); #else @@ -152,7 +146,10 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, CUtexObject tex = kernel_tex_fetch(__bindless_mapping, id); /* float4, byte4 and half4 */ const int texture_type = kernel_tex_type(id); - if(texture_type == IMAGE_DATA_TYPE_FLOAT4 || texture_type == IMAGE_DATA_TYPE_BYTE4 || texture_type == IMAGE_DATA_TYPE_HALF4) { + if(texture_type == IMAGE_DATA_TYPE_FLOAT4 || + texture_type == IMAGE_DATA_TYPE_BYTE4 || + texture_type == IMAGE_DATA_TYPE_HALF4) + { r = kernel_tex_image_interp_float4(tex, x, y); } /* float, byte and half */ @@ -163,43 +160,22 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, # endif #endif -#ifdef __KERNEL_SSE2__ - float alpha = r.w; + const float alpha = r.w; if(use_alpha && alpha != 1.0f && alpha != 0.0f) { - r_ssef = r_ssef / ssef(alpha); + r /= alpha; const int texture_type = kernel_tex_type(id); - if(texture_type == IMAGE_DATA_TYPE_BYTE4 || texture_type == IMAGE_DATA_TYPE_BYTE) { - r_ssef = min(r_ssef, ssef(1.0f)); + if(texture_type == IMAGE_DATA_TYPE_BYTE4 || + texture_type == IMAGE_DATA_TYPE_BYTE) + { + r = min(r, make_float4(1.0f, 1.0f, 1.0f, 1.0f)); } r.w = alpha; } if(srgb) { - r_ssef = color_srgb_to_scene_linear(r_ssef); - r.w = alpha; + r = color_srgb_to_scene_linear_v4(r); } -#else - if(use_alpha && r.w != 1.0f && r.w != 0.0f) { - float invw = 1.0f/r.w; - r.x *= invw; - r.y *= invw; - r.z *= invw; - - const int texture_type = kernel_tex_type(id); - if(texture_type == IMAGE_DATA_TYPE_BYTE4 || texture_type == IMAGE_DATA_TYPE_BYTE) { - r.x = min(r.x, 1.0f); - r.y = min(r.y, 1.0f); - r.z = min(r.z, 1.0f); - } - } - - if(srgb) { - r.x = color_srgb_to_scene_linear(r.x); - r.y = color_srgb_to_scene_linear(r.y); - r.z = color_srgb_to_scene_linear(r.z); - } -#endif return r; } diff --git a/intern/cycles/util/util_color.h b/intern/cycles/util/util_color.h index 4d673dc34d8..c73beab98dc 100644 --- a/intern/cycles/util/util_color.h +++ b/intern/cycles/util/util_color.h @@ -157,16 +157,6 @@ ccl_device float3 xyz_to_rgb(float x, float y, float z) 0.055648f * x + -0.204043f * y + 1.057311f * z); } -#ifndef __KERNEL_OPENCL__ - -ccl_device float3 color_srgb_to_scene_linear(float3 c) -{ - return make_float3( - color_srgb_to_scene_linear(c.x), - color_srgb_to_scene_linear(c.y), - color_srgb_to_scene_linear(c.z)); -} - #ifdef __KERNEL_SSE2__ /* * Calculate initial guess for arg^exp based on float representation @@ -222,17 +212,38 @@ ccl_device ssef color_srgb_to_scene_linear(const ssef &c) ssef gte = fastpow24(gtebase); return select(cmp, lt, gte); } -#endif +#endif /* __KERNEL_SSE2__ */ -ccl_device float3 color_scene_linear_to_srgb(float3 c) +ccl_device float3 color_srgb_to_scene_linear_v3(float3 c) { - return make_float3( - color_scene_linear_to_srgb(c.x), - color_scene_linear_to_srgb(c.y), - color_scene_linear_to_srgb(c.z)); + return make_float3(color_srgb_to_scene_linear(c.x), + color_srgb_to_scene_linear(c.y), + color_srgb_to_scene_linear(c.z)); } +ccl_device float3 color_scene_linear_to_srgb_v3(float3 c) +{ + return make_float3(color_scene_linear_to_srgb(c.x), + color_scene_linear_to_srgb(c.y), + color_scene_linear_to_srgb(c.z)); +} + +ccl_device float4 color_srgb_to_scene_linear_v4(float4 c) +{ +#ifdef __KERNEL_SSE2__ + ssef r_ssef; + float4 &r = (float4 &)r_ssef; + r = c; + r_ssef = color_srgb_to_scene_linear(r_ssef); + r.w = c.w; + return r; +#else + return make_float4(color_srgb_to_scene_linear(c.x), + color_srgb_to_scene_linear(c.y), + color_srgb_to_scene_linear(c.z), + c.w); #endif +} ccl_device float linear_rgb_to_gray(float3 c) { diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 42d62297243..e87bd5e3a39 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -983,7 +983,8 @@ void ntreeCompositExecTree(struct Scene *scene, struct bNodeTree *ntree, struct void ntreeCompositTagRender(struct Scene *sce); int ntreeCompositTagAnimated(struct bNodeTree *ntree); void ntreeCompositTagGenerators(struct bNodeTree *ntree); -void ntreeCompositForceHidden(struct bNodeTree *ntree); +void ntreeCompositUpdateRLayers(struct bNodeTree *ntree); +void ntreeCompositRegisterPass(struct bNodeTree *ntree, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int type); void ntreeCompositClearTags(struct bNodeTree *ntree); struct bNodeSocket *ntreeCompositOutputFileAddSocket(struct bNodeTree *ntree, struct bNode *node, diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 8a01e120d6d..2db13f9c778 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2739,7 +2739,6 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) } } -#define PASSTYPE_UNSET -1 /* return renderpass for a given pass index and active view */ /* fallback to available if there are missing passes for active view */ static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const int view, int *r_passindex) @@ -2748,7 +2747,7 @@ static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const RenderPass *rpass; int rp_index = 0; - int rp_passtype = PASSTYPE_UNSET; + const char *rp_name = ""; for (rpass = rl->passes.first; rpass; rpass = rpass->next, rp_index++) { if (rp_index == pass) { @@ -2758,12 +2757,12 @@ static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const break; } else { - rp_passtype = rpass->passtype; + rp_name = rpass->name; } } /* multiview */ - else if ((rp_passtype != PASSTYPE_UNSET) && - (rpass->passtype == rp_passtype) && + else if (rp_name[0] && + STREQ(rpass->name, rp_name) && (rpass->view_id == view)) { rpass_ret = rpass; @@ -2783,7 +2782,6 @@ static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const return rpass_ret; } -#undef PASSTYPE_UNSET /* if layer or pass changes, we need an index for the imbufs list */ /* note it is called for rendered results, but it doesnt use the index! */ @@ -3753,7 +3751,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc } for (rpass = rl->passes.first; rpass; rpass = rpass->next) - if (rpass->passtype == SCE_PASS_Z) + if (STREQ(rpass->name, RE_PASSNAME_Z) && rpass->view_id == actview) rectz = rpass->rect; } } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index b2ed9668c31..44e29e5b994 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1623,6 +1623,11 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer * BKE_freestyle_config_free(&srl->freestyleConfig); + if (srl->prop) { + IDP_FreeProperty(srl->prop); + MEM_freeN(srl->prop); + } + BLI_remlink(&scene->r.layers, srl); MEM_freeN(srl); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 7567fce3778..5f533f02bd1 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2110,8 +2110,19 @@ static void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, FileData BLI_endian_switch_int32(&prop->data.val2); BLI_endian_switch_int64((int64_t *)&prop->data.val); } - break; + case IDP_INT: + case IDP_FLOAT: + case IDP_ID: + break; /* Nothing special to do here. */ + default: + /* Unknown IDP type, nuke it (we cannot handle unknown types everywhere in code, + * IDP are way too polymorphic to do it safely. */ + printf("%s: found unknown IDProperty type %d, reset to Integer one !\n", __func__, prop->type); + /* Note: we do not attempt to free unknown prop, we have no way to know how to do that! */ + prop->type = IDP_INT; + prop->subtype = 0; + IDP_Int(prop) = 0; } } @@ -3112,7 +3123,7 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree) else if (ntree->type==NTREE_COMPOSIT) { if (ELEM(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT)) direct_link_curvemapping(fd, node->storage); - else if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) + else if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_R_LAYERS, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) ((ImageUser *)node->storage)->ok = 1; } else if ( ntree->type==NTREE_TEXTURE) { @@ -6240,6 +6251,11 @@ static void direct_link_scene(FileData *fd, Scene *sce) link_list(fd, &(sce->r.layers)); link_list(fd, &(sce->r.views)); + + for (srl = sce->r.layers.first; srl; srl = srl->next) { + srl->prop = newdataadr(fd, srl->prop); + IDP_DirectLinkGroup_OrFree(&srl->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + } for (srl = sce->r.layers.first; srl; srl = srl->next) { link_list(fd, &(srl->freestyleConfig.modules)); } diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 0b6be6ab08d..a097e0a9e48 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -80,6 +80,7 @@ #include "NOD_common.h" #include "NOD_socket.h" +#include "NOD_composite.h" #include "readfile.h" @@ -1559,8 +1560,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } - /* To be added to next subversion bump! */ - { + if (!MAIN_VERSION_ATLEAST(main, 278, 5)) { /* Mask primitive adding code was not initializing correctly id_type of its points' parent. */ for (Mask *mask = main->mask.first; mask; mask = mask->id.next) { for (MaskLayer *mlayer = mask->masklayers.first; mlayer; mlayer = mlayer->next) { @@ -1609,6 +1609,30 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } } + + FOREACH_NODETREE(main, ntree, id) { + if (ntree->type == NTREE_COMPOSIT) { + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == CMP_NODE_R_LAYERS) { + int pass_index = 0; + const char *sockname; + for (bNodeSocket *sock = node->outputs.first; sock && pass_index < 31; sock = sock->next, pass_index++) { + if (sock->storage == NULL) { + NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); + sock->storage = sockdata; + BLI_strncpy(sockdata->pass_name, node_cmp_rlayers_sock_to_pass(pass_index), sizeof(sockdata->pass_name)); + + if (pass_index == 0) sockname = "Image"; + else if (pass_index == 1) sockname = "Alpha"; + else sockname = node_cmp_rlayers_sock_to_pass(pass_index); + BLI_strncpy(sock->name, sockname, sizeof(sock->name)); + } + } + } + } + } + } FOREACH_NODETREE_END } { diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index dae8e180282..c82877063fd 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1053,7 +1053,7 @@ static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree) writestruct(wd, DATA, NodeImageMultiFileSocket, 1, sock->storage); } } - if (node->type == CMP_NODE_IMAGE) { + if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_R_LAYERS)) { /* write extra socket info */ for (sock = node->outputs.first; sock; sock = sock->next) { writestruct(wd, DATA, NodeImageLayer, 1, sock->storage); @@ -2738,6 +2738,9 @@ static void write_scene(WriteData *wd, Scene *sce) for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) { writestruct(wd, DATA, SceneRenderLayer, 1, srl); + if (srl->prop) { + IDP_WriteProperty(srl->prop, wd); + } for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) { writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc); } diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 3180e7e4154..3e1dd83112a 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -551,8 +551,4 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -if(WITH_CYCLES AND WITH_CYCLES_DEBUG) - add_definitions(-DWITH_CYCLES_DEBUG) -endif() - blender_add_lib(bf_compositor "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/compositor/intern/COM_NodeGraph.cpp b/source/blender/compositor/intern/COM_NodeGraph.cpp index c5096a6b352..891e64ed12b 100644 --- a/source/blender/compositor/intern/COM_NodeGraph.cpp +++ b/source/blender/compositor/intern/COM_NodeGraph.cpp @@ -179,7 +179,8 @@ void NodeGraph::add_bNodeLink(const NodeRange &node_range, bNodeLink *b_nodelink /// @note: ignore invalid links if (!(b_nodelink->flag & NODE_LINK_VALID)) return; - if ((b_nodelink->fromsock->flag & SOCK_UNAVAIL) || (b_nodelink->tosock->flag & SOCK_UNAVAIL)) + const int unavail_mask = SOCK_UNAVAIL | SOCK_VIRTUAL; + if ((b_nodelink->fromsock->flag & unavail_mask) || (b_nodelink->tosock->flag & unavail_mask)) return; /* Note: a DNA input socket can have multiple NodeInput in the compositor tree! (proxies) diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp index facd422c217..462947f32a3 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.cpp +++ b/source/blender/compositor/nodes/COM_ImageNode.cpp @@ -95,18 +95,10 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo NodeOperation *operation = NULL; socket = this->getOutputSocket(index); bNodeSocket *bnodeSocket = socket->getbNodeSocket(); - RenderPass *rpass = (RenderPass *)BLI_findstring(&rl->passes, bnodeSocket->identifier, offsetof(RenderPass, internal_name)); + NodeImageLayer *storage = (NodeImageLayer *)bnodeSocket->storage; + RenderPass *rpass = (RenderPass *)BLI_findstring(&rl->passes, storage->pass_name, offsetof(RenderPass, name)); int view = 0; - /* Passes in the file can differ from passes stored in sockets (#36755). - * Look up the correct file pass using the socket identifier instead. - */ -#if 0 - NodeImageLayer *storage = (NodeImageLayer *)bnodeSocket->storage;*/ - int passindex = storage->pass_index;*/ - RenderPass *rpass = (RenderPass *)BLI_findlink(&rl->passes, passindex); -#endif - /* returns the image view to use for the current active view */ if (BLI_listbase_count_ex(&image->rr->views, 2) > 1) { const int view_image = imageuser->view; @@ -147,7 +139,7 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo if (index == 0 && operation) { converter.addPreview(operation->getOutputSocket()); } - if (rpass->passtype == SCE_PASS_COMBINED) { + if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) { BLI_assert(operation != NULL); BLI_assert(index < numberOfOutputs - 1); NodeOutput *outputSocket = this->getOutputSocket(index + 1); diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp index 842edcf35c9..75128de2d84 100644 --- a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp +++ b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp @@ -27,76 +27,61 @@ #include "COM_ScaleOperation.h" #include "COM_SetValueOperation.h" -#ifdef WITH_CYCLES_DEBUG -# include "RE_pipeline.h" -#endif - RenderLayersNode::RenderLayersNode(bNode *editorNode) : Node(editorNode) { /* pass */ } void RenderLayersNode::testSocketLink(NodeConverter &converter, const CompositorContext &context, - int outputSocketNumber, RenderLayersBaseProg *operation) const + NodeOutput *output, RenderLayersProg *operation, + Scene *scene, int layerId, bool is_preview) const { - NodeOutput *outputSocket = this->getOutputSocket(outputSocketNumber); - Scene *scene = (Scene *)this->getbNode()->id; - short layerId = this->getbNode()->custom1; - operation->setScene(scene); operation->setLayerId(layerId); operation->setRenderData(context.getRenderData()); operation->setViewName(context.getViewName()); - converter.mapOutputSocket(outputSocket, operation->getOutputSocket()); + converter.mapOutputSocket(output, operation->getOutputSocket()); converter.addOperation(operation); - if (outputSocketNumber == 0) /* only for image socket */ + if (is_preview) /* only for image socket */ converter.addPreview(operation->getOutputSocket()); } void RenderLayersNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const { - testSocketLink(converter, context, 0, new RenderLayersColorProg()); - testSocketLink(converter, context, 1, new RenderLayersAlphaProg()); - testSocketLink(converter, context, 2, new RenderLayersDepthProg()); - testSocketLink(converter, context, 3, new RenderLayersNormalOperation()); - testSocketLink(converter, context, 4, new RenderLayersUVOperation()); - testSocketLink(converter, context, 5, new RenderLayersSpeedOperation()); - testSocketLink(converter, context, 6, new RenderLayersColorOperation()); - testSocketLink(converter, context, 7, new RenderLayersDiffuseOperation()); - testSocketLink(converter, context, 8, new RenderLayersSpecularOperation()); - testSocketLink(converter, context, 9, new RenderLayersShadowOperation()); - testSocketLink(converter, context, 10, new RenderLayersAOOperation()); - testSocketLink(converter, context, 11, new RenderLayersReflectionOperation()); - testSocketLink(converter, context, 12, new RenderLayersRefractionOperation()); - testSocketLink(converter, context, 13, new RenderLayersIndirectOperation()); - testSocketLink(converter, context, 14, new RenderLayersObjectIndexOperation()); - testSocketLink(converter, context, 15, new RenderLayersMaterialIndexOperation()); - testSocketLink(converter, context, 16, new RenderLayersMistOperation()); - testSocketLink(converter, context, 17, new RenderLayersEmitOperation()); - testSocketLink(converter, context, 18, new RenderLayersEnvironmentOperation()); + Scene *scene = (Scene *)this->getbNode()->id; + short layerId = this->getbNode()->custom1; + Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL; + int numberOfOutputs = this->getNumberOfOutputSockets(); - // cycles passes - testSocketLink(converter, context, 19, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_DIRECT)); - testSocketLink(converter, context, 20, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_INDIRECT)); - testSocketLink(converter, context, 21, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_COLOR)); - testSocketLink(converter, context, 22, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_DIRECT)); - testSocketLink(converter, context, 23, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_INDIRECT)); - testSocketLink(converter, context, 24, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_COLOR)); - testSocketLink(converter, context, 25, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_DIRECT)); - testSocketLink(converter, context, 26, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_INDIRECT)); - testSocketLink(converter, context, 27, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_COLOR)); - testSocketLink(converter, context, 28, new RenderLayersCyclesOperation(SCE_PASS_SUBSURFACE_DIRECT)); - testSocketLink(converter, context, 29, new RenderLayersCyclesOperation(SCE_PASS_SUBSURFACE_INDIRECT)); - testSocketLink(converter, context, 30, new RenderLayersCyclesOperation(SCE_PASS_SUBSURFACE_COLOR)); - -#ifdef WITH_CYCLES_DEBUG - { - Scene *scene = (Scene *)this->getbNode()->id; - Render *re = RE_GetRender(scene->id.name); - int debug_pass_type = ((re != NULL) ? RE_debug_pass_type_get(re) : scene->r.debug_pass_type); - testSocketLink(converter, context, 31, new RenderLayersCyclesDebugOperation(SCE_PASS_DEBUG, debug_pass_type)); + if (re) { + RenderResult *rr = RE_AcquireResultRead(re); + if (rr) { + SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&scene->r.layers, layerId); + if (srl) { + RenderLayer *rl = RE_GetRenderLayer(rr, srl->name); + if (rl) { + for (int i = 0; i < numberOfOutputs; i++) { + NodeOutput *output = this->getOutputSocket(i); + NodeImageLayer *storage = (NodeImageLayer*) output->getbNodeSocket()->storage; + RenderPass *rpass = (RenderPass*) BLI_findstring(&rl->passes, storage->pass_name, offsetof(RenderPass, name)); + if (rpass) { + if (STREQ(rpass->name, RE_PASSNAME_COMBINED) && STREQ(output->getbNodeSocket()->name, "Alpha")) { + testSocketLink(converter, context, output, new RenderLayersAlphaProg(rpass->name, COM_DT_VALUE, rpass->channels), scene, layerId, false); + } + else if (STREQ(rpass->name, RE_PASSNAME_Z)) { + testSocketLink(converter, context, output, new RenderLayersDepthProg(rpass->name, COM_DT_VALUE, rpass->channels), scene, layerId, false); + } + else { + DataType type = ((rpass->channels == 4)? COM_DT_COLOR : ((rpass->channels == 3)? COM_DT_VECTOR : COM_DT_VALUE)); + testSocketLink(converter, context, output, new RenderLayersProg(rpass->name, type, rpass->channels), scene, layerId, STREQ(output->getbNodeSocket()->name, "Image")); + } + } + } + } + } + } + RE_ReleaseResult(re); } -#endif } diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.h b/source/blender/compositor/nodes/COM_RenderLayersNode.h index 5863cbb390c..1f733a9f4bb 100644 --- a/source/blender/compositor/nodes/COM_RenderLayersNode.h +++ b/source/blender/compositor/nodes/COM_RenderLayersNode.h @@ -33,5 +33,11 @@ public: RenderLayersNode(bNode *editorNode); void convertToOperations(NodeConverter &converter, const CompositorContext &context) const; private: - void testSocketLink(NodeConverter &converter, const CompositorContext &context, int outputSocketNumber, RenderLayersBaseProg *operation) const; + void testSocketLink(NodeConverter &converter, + const CompositorContext &context, + NodeOutput *output, + RenderLayersProg *operation, + Scene *scene, + int layerId, + bool is_preview) const; }; diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp index 099208ce600..f2f1b211a97 100644 --- a/source/blender/compositor/operations/COM_RenderLayersProg.cpp +++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp @@ -34,17 +34,18 @@ extern "C" { /* ******** Render Layers Base Prog ******** */ -RenderLayersBaseProg::RenderLayersBaseProg(int renderpass, int elementsize) : NodeOperation() +RenderLayersProg::RenderLayersProg(const char *passName, DataType type, int elementsize) : NodeOperation(), m_passName(passName) { - this->m_renderpass = renderpass; this->setScene(NULL); this->m_inputBuffer = NULL; this->m_elementsize = elementsize; this->m_rd = NULL; + + this->addOutputSocket(type); } -void RenderLayersBaseProg::initExecution() +void RenderLayersProg::initExecution() { Scene *scene = this->getScene(); Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL; @@ -59,10 +60,7 @@ void RenderLayersBaseProg::initExecution() RenderLayer *rl = RE_GetRenderLayer(rr, srl->name); if (rl) { - this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_renderpass, this->m_viewName); - if (this->m_inputBuffer == NULL && this->m_renderpass == SCE_PASS_COMBINED) { - this->m_inputBuffer = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, this->m_viewName); - } + this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_passName.c_str(), this->m_viewName); } } } @@ -72,7 +70,7 @@ void RenderLayersBaseProg::initExecution() } } -void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler) +void RenderLayersProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler) { unsigned int offset; int width = this->getWidth(), height = this->getHeight(); @@ -111,7 +109,7 @@ void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, Pi } } -void RenderLayersBaseProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void RenderLayersProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { #if 0 const RenderData *rd = this->m_rd; @@ -173,12 +171,12 @@ void RenderLayersBaseProg::executePixelSampled(float output[4], float x, float y } } -void RenderLayersBaseProg::deinitExecution() +void RenderLayersProg::deinitExecution() { this->m_inputBuffer = NULL; } -void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) +void RenderLayersProg::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) { Scene *sce = this->getScene(); Render *re = (sce) ? RE_GetRender(sce->id.name) : NULL; @@ -207,13 +205,6 @@ void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsig } /* ******** Render Layers AO Operation ******** */ - -RenderLayersAOOperation::RenderLayersAOOperation() : RenderLayersBaseProg(SCE_PASS_AO, 3) -{ - this->addOutputSocket(COM_DT_COLOR); -} - - void RenderLayersAOOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { float *inputBuffer = this->getInputBuffer(); @@ -227,12 +218,6 @@ void RenderLayersAOOperation::executePixelSampled(float output[4], float x, floa } /* ******** Render Layers Alpha Operation ******** */ - -RenderLayersAlphaProg::RenderLayersAlphaProg() : RenderLayersBaseProg(SCE_PASS_COMBINED, 4) -{ - this->addOutputSocket(COM_DT_VALUE); -} - void RenderLayersAlphaProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { float *inputBuffer = this->getInputBuffer(); @@ -247,27 +232,7 @@ void RenderLayersAlphaProg::executePixelSampled(float output[4], float x, float } } -/* ******** Render Layers Color Operation ******** */ - -RenderLayersColorOperation::RenderLayersColorOperation() : RenderLayersBaseProg(SCE_PASS_RGBA, 4) -{ - this->addOutputSocket(COM_DT_COLOR); -} - -/* ******** Render Layers Cycles Operation ******** */ - -RenderLayersCyclesOperation::RenderLayersCyclesOperation(int pass) : RenderLayersBaseProg(pass, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - /* ******** Render Layers Depth Operation ******** */ - -RenderLayersDepthProg::RenderLayersDepthProg() : RenderLayersBaseProg(SCE_PASS_Z, 1) -{ - this->addOutputSocket(COM_DT_VALUE); -} - void RenderLayersDepthProg::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) { int ix = x; @@ -281,135 +246,4 @@ void RenderLayersDepthProg::executePixelSampled(float output[4], float x, float unsigned int offset = (iy * this->getWidth() + ix); output[0] = inputBuffer[offset]; } -} - -/* ******** Render Layers Diffuse Operation ******** */ - -RenderLayersDiffuseOperation::RenderLayersDiffuseOperation() : RenderLayersBaseProg(SCE_PASS_DIFFUSE, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Render Layers Emit Operation ******** */ - -RenderLayersEmitOperation::RenderLayersEmitOperation() : RenderLayersBaseProg(SCE_PASS_EMIT, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Render Layers Environment Operation ******** */ - -RenderLayersEnvironmentOperation::RenderLayersEnvironmentOperation() : RenderLayersBaseProg(SCE_PASS_ENVIRONMENT, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Render Layers Image Operation ******** */ - -RenderLayersColorProg::RenderLayersColorProg() : RenderLayersBaseProg(SCE_PASS_COMBINED, 4) -{ - this->addOutputSocket(COM_DT_COLOR); -} - -/* ******** Render Layers Indirect Operation ******** */ - -RenderLayersIndirectOperation::RenderLayersIndirectOperation() : RenderLayersBaseProg(SCE_PASS_INDIRECT, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Render Layers Material Index Operation ******** */ - -RenderLayersMaterialIndexOperation::RenderLayersMaterialIndexOperation() : RenderLayersBaseProg(SCE_PASS_INDEXMA, 1) -{ - this->addOutputSocket(COM_DT_VALUE); -} - -/* ******** Render Layers Mist Operation ******** */ - -RenderLayersMistOperation::RenderLayersMistOperation() : RenderLayersBaseProg(SCE_PASS_MIST, 1) -{ - this->addOutputSocket(COM_DT_VALUE); -} - -/* ******** Render Layers Normal Operation ******** */ - -RenderLayersNormalOperation::RenderLayersNormalOperation() : RenderLayersBaseProg(SCE_PASS_NORMAL, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Render Layers Object Index Operation ******** */ - -RenderLayersObjectIndexOperation::RenderLayersObjectIndexOperation() : RenderLayersBaseProg(SCE_PASS_INDEXOB, 1) -{ - this->addOutputSocket(COM_DT_VALUE); -} - -/* ******** Render Layers Reflection Operation ******** */ - -RenderLayersReflectionOperation::RenderLayersReflectionOperation() : RenderLayersBaseProg(SCE_PASS_REFLECT, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Render Layers Refraction Operation ******** */ - -RenderLayersRefractionOperation::RenderLayersRefractionOperation() : RenderLayersBaseProg(SCE_PASS_REFRACT, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Render Layers Shadow Operation ******** */ - -RenderLayersShadowOperation::RenderLayersShadowOperation() : RenderLayersBaseProg(SCE_PASS_SHADOW, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Render Layers Specular Operation ******** */ - -RenderLayersSpecularOperation::RenderLayersSpecularOperation() : RenderLayersBaseProg(SCE_PASS_SPEC, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Render Layers Speed Operation ******** */ - -RenderLayersSpeedOperation::RenderLayersSpeedOperation() : RenderLayersBaseProg(SCE_PASS_VECTOR, 4) -{ - this->addOutputSocket(COM_DT_COLOR); -} - -/* ******** Render Layers UV Operation ******** */ - -RenderLayersUVOperation::RenderLayersUVOperation() : RenderLayersBaseProg(SCE_PASS_UV, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Debug Render Layers Cycles Operation ******** */ - -#ifdef WITH_CYCLES_DEBUG - -RenderLayersCyclesDebugOperation::RenderLayersCyclesDebugOperation( - int pass, - int debug_pass_type) - : RenderLayersBaseProg(pass, RE_debug_pass_num_channels_get(debug_pass_type)) -{ - switch (m_elementsize) { - case 1: - this->addOutputSocket(COM_DT_VALUE); - break; - case 3: - this->addOutputSocket(COM_DT_VECTOR); - break; - case 4: - this->addOutputSocket(COM_DT_COLOR); - break; - default: - BLI_assert(!"Unkown debug pass type element size."); - } -} - -#endif +}
\ No newline at end of file diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.h b/source/blender/compositor/operations/COM_RenderLayersProg.h index 89eb2a6954d..1be15906770 100644 --- a/source/blender/compositor/operations/COM_RenderLayersProg.h +++ b/source/blender/compositor/operations/COM_RenderLayersProg.h @@ -40,7 +40,7 @@ extern "C" { * * @todo: rename to operation. */ -class RenderLayersBaseProg : public NodeOperation { +class RenderLayersProg : public NodeOperation { protected: /** * Reference to the scene object. @@ -65,7 +65,7 @@ protected: /** * renderpass where this operation needs to get its data from */ - int m_renderpass; + std::string m_passName; int m_elementsize; @@ -73,11 +73,6 @@ protected: * @brief render data used for active rendering */ const RenderData *m_rd; - - /** - * Constructor - */ - RenderLayersBaseProg(int renderpass, int elementsize); /** * Determine the output resolution. The resolution is retrieved from the Renderer @@ -92,6 +87,10 @@ protected: void doInterpolation(float output[4], float x, float y, PixelSampler sampler); public: /** + * Constructor + */ + RenderLayersProg(const char *passName, DataType type, int elementsize); + /** * setter for the scene field. Will be called from * @see RenderLayerNode to set the actual scene where * the data will be retrieved from. @@ -108,116 +107,25 @@ public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; -class RenderLayersAOOperation : public RenderLayersBaseProg { +class RenderLayersAOOperation : public RenderLayersProg { public: - RenderLayersAOOperation(); + RenderLayersAOOperation(const char *passName, DataType type, int elementsize) + : RenderLayersProg(passName, type, elementsize) {} void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; -class RenderLayersAlphaProg : public RenderLayersBaseProg { +class RenderLayersAlphaProg : public RenderLayersProg { public: - RenderLayersAlphaProg(); + RenderLayersAlphaProg(const char *passName, DataType type, int elementsize) + : RenderLayersProg(passName, type, elementsize) {} void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; -class RenderLayersColorOperation : public RenderLayersBaseProg { -public: - RenderLayersColorOperation(); -}; - -class RenderLayersCyclesOperation : public RenderLayersBaseProg { -public: - RenderLayersCyclesOperation(int pass); -}; - -class RenderLayersDepthProg : public RenderLayersBaseProg { +class RenderLayersDepthProg : public RenderLayersProg { public: - RenderLayersDepthProg(); + RenderLayersDepthProg(const char *passName, DataType type, int elementsize) + : RenderLayersProg(passName, type, elementsize) {} void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; -class RenderLayersDiffuseOperation : public RenderLayersBaseProg { -public: - RenderLayersDiffuseOperation(); -}; - -class RenderLayersEmitOperation : public RenderLayersBaseProg { -public: - RenderLayersEmitOperation(); -}; - -class RenderLayersEnvironmentOperation : public RenderLayersBaseProg { -public: - RenderLayersEnvironmentOperation(); -}; - -/// @todo rename to image operation -class RenderLayersColorProg : public RenderLayersBaseProg { -public: - RenderLayersColorProg(); -}; - -class RenderLayersIndirectOperation : public RenderLayersBaseProg { -public: - RenderLayersIndirectOperation(); -}; - -class RenderLayersMaterialIndexOperation : public RenderLayersBaseProg { -public: - RenderLayersMaterialIndexOperation(); -}; - -class RenderLayersMistOperation : public RenderLayersBaseProg { -public: - RenderLayersMistOperation(); -}; - -class RenderLayersNormalOperation : public RenderLayersBaseProg { -public: - RenderLayersNormalOperation(); -}; - -class RenderLayersObjectIndexOperation : public RenderLayersBaseProg { -public: - RenderLayersObjectIndexOperation(); -}; - -class RenderLayersReflectionOperation : public RenderLayersBaseProg { -public: - RenderLayersReflectionOperation(); -}; - -class RenderLayersRefractionOperation : public RenderLayersBaseProg { -public: - RenderLayersRefractionOperation(); -}; - -class RenderLayersShadowOperation : public RenderLayersBaseProg { -public: - RenderLayersShadowOperation(); -}; - -class RenderLayersSpecularOperation : public RenderLayersBaseProg { -public: - RenderLayersSpecularOperation(); -}; - -class RenderLayersSpeedOperation : public RenderLayersBaseProg { -public: - RenderLayersSpeedOperation(); -}; - -class RenderLayersUVOperation : public RenderLayersBaseProg { -public: - RenderLayersUVOperation(); -}; - -#ifdef WITH_CYCLES_DEBUG -class RenderLayersCyclesDebugOperation : public RenderLayersBaseProg { -public: - RenderLayersCyclesDebugOperation(int pass, - int debug_pass_type); -}; -#endif - #endif diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c index bdcdefe414a..169c67f9702 100644 --- a/source/blender/draw/engines/basic/basic_engine.c +++ b/source/blender/draw/engines/basic/basic_engine.c @@ -248,7 +248,7 @@ DrawEngineType draw_engine_basic_type = { RenderEngineType DRW_engine_viewport_basic_type = { NULL, NULL, BASIC_ENGINE, N_("Basic"), RE_INTERNAL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &draw_engine_basic_type, {NULL, NULL, NULL} }; diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c index 6f3e0c4e8b9..8ac8ed50cdc 100644 --- a/source/blender/draw/engines/clay/clay_engine.c +++ b/source/blender/draw/engines/clay/clay_engine.c @@ -658,7 +658,7 @@ DrawEngineType draw_engine_clay_type = { RenderEngineType DRW_engine_viewport_clay_type = { NULL, NULL, CLAY_ENGINE, N_("Clay"), RE_INTERNAL, - NULL, NULL, NULL, NULL, NULL, NULL, &CLAY_collection_settings_create, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, &CLAY_collection_settings_create, &draw_engine_clay_type, {NULL, NULL, NULL} }; diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 6572abde728..5fbf98e3003 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -712,7 +712,7 @@ DrawEngineType draw_engine_eevee_type = { RenderEngineType DRW_engine_viewport_eevee_type = { NULL, NULL, EEVEE_ENGINE, N_("Eevee"), RE_INTERNAL | RE_USE_SHADING_NODES, - NULL, NULL, NULL, NULL, NULL, NULL, &EEVEE_collection_settings_create, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, &EEVEE_collection_settings_create, &draw_engine_eevee_type, {NULL, NULL, NULL} }; diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c index 5c7f507b34b..7b6b4e51147 100644 --- a/source/blender/draw/engines/external/external_engine.c +++ b/source/blender/draw/engines/external/external_engine.c @@ -214,7 +214,7 @@ DrawEngineType draw_engine_external_type = { RenderEngineType DRW_engine_viewport_external_type = { NULL, NULL, EXTERNAL_ENGINE, N_("External"), RE_INTERNAL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &draw_engine_external_type, {NULL, NULL, NULL} }; diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 2de4b2da023..88ad3be982c 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -211,7 +211,7 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu } else { if (rr->renlay == NULL) return; - rectf = RE_RenderLayerGetPass(rr->renlay, SCE_PASS_COMBINED, viewname); + rectf = RE_RenderLayerGetPass(rr->renlay, RE_PASSNAME_COMBINED, viewname); } } if (rectf == NULL) return; diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index 8167acdd331..e019bc9f697 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -191,8 +191,12 @@ void ED_render_engine_changed(Main *bmain) RE_FreePersistentData(); - for (scene = bmain->scene.first; scene; scene = scene->id.next) + for (scene = bmain->scene.first; scene; scene = scene->id.next) { ED_render_id_flush_update(bmain, &scene->id); + if (scene->nodetree) { + ntreeCompositUpdateRLayers(scene->nodetree); + } + } } /***************************** Updates *********************************** diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index b9d98dfe794..db917b0cdf5 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -428,7 +428,6 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void * RenderPass *rpass; const char *fake_name; int nr; - int passflag = 0; /* may have been freed since drawing */ rr = BKE_image_acquire_renderresult(scene, image); @@ -450,30 +449,31 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void * fake_name = ui_imageuser_pass_fake_name(rl); if (fake_name) { - BLI_strncpy(rpass_fake.internal_name, fake_name, sizeof(rpass_fake.internal_name)); + BLI_strncpy(rpass_fake.name, fake_name, sizeof(rpass_fake.name)); nr += 1; } + ListBase added_passes; + BLI_listbase_clear(&added_passes); + /* rendered results don't have a Combined pass */ /* multiview: the ordering must be ascending, so the left-most pass is always the one picked */ for (rpass = rl ? rl->passes.first : NULL; rpass; rpass = rpass->next, nr++) { - /* just show one pass of each kind */ - if (passflag & rpass->passtype) + if (BLI_findstring_ptr(&added_passes, rpass->name, offsetof(LinkData, data))) { continue; + } + BLI_addtail(&added_passes, BLI_genericNodeN(rpass->name)); - passflag |= rpass->passtype; - -final: - uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->internal_name), 0, 0, + uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->name), 0, 0, UI_UNIT_X * 5, UI_UNIT_X, &iuser->pass, (float) nr, 0.0, 0, -1, ""); } + BLI_freelistN(&added_passes); + if (fake_name) { - fake_name = NULL; - rpass = &rpass_fake; - nr = 0; - goto final; + uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass_fake.name), 0, 0, + UI_UNIT_X * 5, UI_UNIT_X, &iuser->pass, 0.0f, 0.0, 0, -1, ""); } BKE_image_release_renderresult(scene, image); @@ -633,7 +633,7 @@ static bool ui_imageuser_pass_menu_step(bContext *C, int direction, void *rnd_pt int rp_index = iuser->pass + 1; for (rp = rpass->next; rp; rp = rp->next, rp_index++) { - if (rp->passtype != rpass->passtype) { + if (!STREQ(rp->name, rpass->name)) { iuser->pass = rp_index; changed = true; break; @@ -650,7 +650,7 @@ static bool ui_imageuser_pass_menu_step(bContext *C, int direction, void *rnd_pt } for (rp = rl->passes.first; rp; rp = rp->next, rp_index++) { - if (rp->passtype == rpass->passtype) { + if (STREQ(rp->name, rpass->name)) { iuser->pass = rp_index - 1; changed = true; break; @@ -769,7 +769,7 @@ static void uiblock_layer_pass_buttons( fake_name = ui_imageuser_pass_fake_name(rl); rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass - (fake_name ? 1 : 0)) : NULL); - display_name = rpass ? rpass->internal_name : (fake_name ? fake_name : ""); + display_name = rpass ? rpass->name : (fake_name ? fake_name : ""); rnd_pt = ui_imageuser_data_copy(&rnd_pt_local); but = uiDefMenuBut( block, ui_imageuser_pass_menu, rnd_pt, IFACE_(display_name), diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 8170ee9b2b3..b6b015e216c 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3037,6 +3037,7 @@ static void std_node_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr, bNode *node = node_ptr->data; bNodeSocket *sock = ptr->data; int type = sock->typeinfo->type; + bool connected_to_virtual = (sock->link && (sock->link->fromsock->flag & SOCK_VIRTUAL)); /*int subtype = sock->typeinfo->subtype;*/ /* XXX not nice, eventually give this node its own socket type ... */ @@ -3044,8 +3045,8 @@ static void std_node_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr, node_file_output_socket_draw(C, layout, ptr, node_ptr); return; } - - if ((sock->in_out == SOCK_OUT) || (sock->flag & SOCK_IN_USE) || (sock->flag & SOCK_HIDE_VALUE)) { + + if ((sock->in_out == SOCK_OUT) || ((sock->flag & SOCK_IN_USE) && !connected_to_virtual) || (sock->flag & SOCK_HIDE_VALUE)) { node_socket_button_label(C, layout, ptr, node_ptr, text); return; } @@ -3487,6 +3488,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) { bool do_shaded = false; bool do_triple = false; + bool do_dashed = false; int th_col1 = TH_WIRE_INNER, th_col2 = TH_WIRE_INNER, th_col3 = TH_WIRE; if (link->fromsock == NULL && link->tosock == NULL) @@ -3503,7 +3505,9 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) return; if (link->fromsock->flag & SOCK_UNAVAIL) return; - + if ((link->fromsock->flag & SOCK_VIRTUAL) || (link->fromsock->flag & SOCK_VIRTUAL)) + do_dashed = true; + if (link->flag & NODE_LINK_VALID) { /* special indicated link, on drop-node */ if (link->flag & NODE_LINKFLAG_HILITE) { @@ -3523,8 +3527,10 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) th_col1 = TH_REDALERT; } } - + + if (do_dashed) setlinestyle(3); node_draw_link_bezier(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3); + if (do_dashed) setlinestyle(0); // node_draw_link_straight(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3); } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index fc3180680f8..107a84cf530 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -513,8 +513,6 @@ void ED_node_composit_default(const bContext *C, struct Scene *sce) nodeAddLink(sce->nodetree, in, fromsock, out, tosock); ntreeUpdateTree(CTX_data_main(C), sce->nodetree); - - // XXX ntreeCompositForceHidden(sce->nodetree); } /* assumes nothing being done in ntree yet, sets the default in/out node */ @@ -593,14 +591,6 @@ void snode_set_context(const bContext *C) if (snode->nodetree != ntree || snode->id != id || snode->from != from || snode->treepath.last == NULL) { ED_node_tree_start(snode, ntree, id, from); } - - /* XXX Legacy hack to update render layer node outputs. - * This should be handled by the depsgraph eventually ... - */ - if (ED_node_is_compositor(snode) && snode->nodetree) { - /* update output sockets based on available layers */ - ntreeCompositForceHidden(snode->nodetree); - } } void snode_update(SpaceNode *snode, bNode *node) diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp index 223bc607e21..ea22633c50e 100644 --- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp +++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp @@ -448,15 +448,13 @@ static void prepare(Render *re, SceneRenderLayer *srl) RenderLayer *rl = RE_GetRenderLayer(re->result, srl->name); bool diffuse = false, z = false; for (RenderPass *rpass = (RenderPass *)rl->passes.first; rpass; rpass = rpass->next) { - switch (rpass->passtype) { - case SCE_PASS_DIFFUSE: + if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) { controller->setPassDiffuse(rpass->rect, rpass->rectx, rpass->recty); diffuse = true; - break; - case SCE_PASS_Z: + } + if (STREQ(rpass->name, RE_PASSNAME_Z)) { controller->setPassZ(rpass->rect, rpass->rectx, rpass->recty); z = true; - break; } } if (G.debug & G_DEBUG_FREESTYLE) { @@ -492,7 +490,7 @@ void FRS_composite_result(Render *re, SceneRenderLayer *srl, Render *freestyle_r return; } - src = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, freestyle_render->viewname); + src = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, freestyle_render->viewname); if (!src) { if (G.debug & G_DEBUG_FREESTYLE) { cout << "No source result image to composite" << endl; @@ -512,7 +510,7 @@ void FRS_composite_result(Render *re, SceneRenderLayer *srl, Render *freestyle_r } return; } - dest = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname); + dest = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, re->viewname); if (!dest) { if (G.debug & G_DEBUG_FREESTYLE) { cout << "No destination result image to composite to" << endl; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 47677e50451..0ba3e013c23 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -159,7 +159,8 @@ typedef enum eNodeSocketFlag { SOCK_COLLAPSED = 64, /* socket collapsed in UI */ SOCK_HIDE_VALUE = 128, /* hide socket value, if it gets auto default */ SOCK_AUTO_HIDDEN__DEPRECATED = 256, /* socket hidden automatically, to distinguish from manually hidden */ - SOCK_NO_INTERNAL_LINK = 512 + SOCK_NO_INTERNAL_LINK = 512, + SOCK_VIRTUAL = 1024 /* socket behaves like SOCK_UNAVAIL, but is drawn with dashed links */ } eNodeSocketFlag; /* limit data in bNode to what we want to see saved? */ @@ -569,9 +570,9 @@ typedef struct NodeEllipseMask { /* layer info for image node outputs */ typedef struct NodeImageLayer { /* index in the Image->layers->passes lists */ - int pass_index; - /* render pass flag, in case this is an original render pass */ - int pass_flag; + int pass_index DNA_DEPRECATED; + /* render pass name */ + char pass_name[64]; /* amount defined in openexr_multi.h */ } NodeImageLayer; typedef struct NodeBlurData { diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 7812e69da17..6815375b918 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -226,7 +226,9 @@ typedef struct SceneRenderLayer { int samples; float pass_alpha_threshold; - + + IDProperty *prop; + struct FreestyleConfig freestyleConfig; } SceneRenderLayer; @@ -280,9 +282,43 @@ typedef enum ScenePassType { SCE_PASS_SUBSURFACE_DIRECT = (1 << 28), SCE_PASS_SUBSURFACE_INDIRECT = (1 << 29), SCE_PASS_SUBSURFACE_COLOR = (1 << 30), - SCE_PASS_DEBUG = (1 << 31), /* This is a virtual pass. */ } ScenePassType; +#define RE_PASSNAME_COMBINED "Combined" +#define RE_PASSNAME_Z "Depth" +#define RE_PASSNAME_VECTOR "Vector" +#define RE_PASSNAME_NORMAL "Normal" +#define RE_PASSNAME_UV "UV" +#define RE_PASSNAME_RGBA "Color" +#define RE_PASSNAME_EMIT "Emit" +#define RE_PASSNAME_DIFFUSE "Diffuse" +#define RE_PASSNAME_SPEC "Spec" +#define RE_PASSNAME_SHADOW "Shadow" + +#define RE_PASSNAME_AO "AO" +#define RE_PASSNAME_ENVIRONMENT "Env" +#define RE_PASSNAME_INDIRECT "Indirect" +#define RE_PASSNAME_REFLECT "Reflect" +#define RE_PASSNAME_REFRACT "Refract" +#define RE_PASSNAME_INDEXOB "IndexOB" +#define RE_PASSNAME_INDEXMA "IndexMA" +#define RE_PASSNAME_MIST "Mist" + +#define RE_PASSNAME_RAYHITS "RayHits" +#define RE_PASSNAME_DIFFUSE_DIRECT "DiffDir" +#define RE_PASSNAME_DIFFUSE_INDIRECT "DiffInd" +#define RE_PASSNAME_DIFFUSE_COLOR "DiffCol" +#define RE_PASSNAME_GLOSSY_DIRECT "GlossDir" +#define RE_PASSNAME_GLOSSY_INDIRECT "GlossInd" +#define RE_PASSNAME_GLOSSY_COLOR "GlossCol" +#define RE_PASSNAME_TRANSM_DIRECT "TransDir" +#define RE_PASSNAME_TRANSM_INDIRECT "TransInd" +#define RE_PASSNAME_TRANSM_COLOR "TransCol" + +#define RE_PASSNAME_SUBSURFACE_DIRECT "SubsurfaceDir" +#define RE_PASSNAME_SUBSURFACE_INDIRECT "SubsurfaceInd" +#define RE_PASSNAME_SUBSURFACE_COLOR "SubsurfaceCol" + /* note, srl->passflag is treestore element 'nr' in outliner, short still... */ /* View - MultiView */ diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 0bf2bbb6109..020c3a755c1 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -176,9 +176,6 @@ set(INC_SYS if(WITH_CYCLES) add_definitions(-DWITH_CYCLES) - if(WITH_CYCLES_DEBUG) - add_definitions(-DWITH_CYCLES_DEBUG) - endif() endif() if(WITH_PYTHON) diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index c3477644979..dfdd2ff293a 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -64,6 +64,8 @@ #include "RE_render_ext.h" +#include "NOD_composite.h" + EnumPropertyItem rna_enum_node_socket_in_out_items[] = { { SOCK_IN, "IN", 0, "Input", "" }, { SOCK_OUT, "OUT", 0, "Output", "" }, @@ -2608,7 +2610,7 @@ static void rna_Node_image_layer_update(Main *bmain, Scene *scene, PointerRNA *p rna_Node_update(bmain, scene, ptr); if (scene->nodetree != NULL) { - ntreeCompositForceHidden(scene->nodetree); + ntreeCompositUpdateRLayers(scene->nodetree); } } @@ -2747,7 +2749,7 @@ static void rna_Node_scene_layer_update(Main *bmain, Scene *scene, PointerRNA *p { rna_Node_update(bmain, scene, ptr); if (scene->nodetree != NULL) { - ntreeCompositForceHidden(scene->nodetree); + ntreeCompositUpdateRLayers(scene->nodetree); } } @@ -4796,7 +4798,7 @@ static void def_cmp_render_layers(StructRNA *srna) RNA_def_property_struct_type(prop, "Scene"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Scene", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_scene_layer_update"); prop = RNA_def_property(srna, "layer", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); @@ -6922,6 +6924,11 @@ static void rna_def_node_socket(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Enabled", "Enable the socket"); RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL); + prop = RNA_def_property(srna, "is_virtual", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_VIRTUAL); + RNA_def_property_ui_text(prop, "Virtual", "Socket is Virtual"); + RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL); + prop = RNA_def_property(srna, "link_limit", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "limit"); RNA_def_property_int_funcs(prop, NULL, "rna_NodeSocket_link_limit_set", NULL); diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 69dea2a46c2..1819f11d292 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -26,6 +26,7 @@ #include <stdlib.h> +#include "DNA_node_types.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" @@ -43,6 +44,7 @@ #include "RE_pipeline.h" +/* Deprecated, only provided for API compatibility. */ EnumPropertyItem rna_enum_render_pass_type_items[] = { {SCE_PASS_COMBINED, "COMBINED", 0, "Combined", ""}, {SCE_PASS_Z, "Z", 0, "Z", ""}, @@ -79,18 +81,6 @@ EnumPropertyItem rna_enum_render_pass_type_items[] = { {0, NULL, 0, NULL, NULL} }; -EnumPropertyItem rna_enum_render_pass_debug_type_items[] = { - {RENDER_PASS_DEBUG_BVH_TRAVERSED_NODES, "BVH_TRAVERSED_NODES", 0, "BVH Traversed Nodes", - "Number of nodes traversed in BVH for the camera rays"}, - {RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES, "BVH_TRAVERSED_INSTANCES", 0, "BVH Traversed Instances", - "Number of BVH instances traversed by camera rays"}, - {RENDER_PASS_DEBUG_BVH_INTERSECTIONS, "BVH_INTERSECTIONS", 0, "BVH Intersections", - "Number of primitive intersections performed by the camera rays"}, - {RENDER_PASS_DEBUG_RAY_BOUNCES, "RAY_BOUNCES", 0, "Ray Steps", - "Number of bounces done by the main integration loop"}, - {0, NULL, 0, NULL, NULL} -}; - EnumPropertyItem rna_enum_bake_pass_type_items[] = { {SCE_PASS_COMBINED, "COMBINED", 0, "Combined", ""}, {SCE_PASS_AO, "AO", 0, "AO", ""}, @@ -281,6 +271,24 @@ static void engine_collection_settings_create(RenderEngine *engine, struct IDPro RNA_parameter_list_free(&list); } +static void engine_update_render_passes(RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl) +{ + extern FunctionRNA rna_RenderEngine_update_render_passes_func; + PointerRNA ptr; + ParameterList list; + FunctionRNA *func; + + RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr); + func = &rna_RenderEngine_update_render_passes_func; + + RNA_parameter_list_create(&list, &ptr, func); + RNA_parameter_set_lookup(&list, "scene", &scene); + RNA_parameter_set_lookup(&list, "renderlayer", &srl); + engine->type->ext.call(NULL, &ptr, func, &list); + + RNA_parameter_list_free(&list); +} + /* RenderEngine registration */ static void rna_RenderEngine_unregister(Main *UNUSED(bmain), StructRNA *type) @@ -301,7 +309,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo RenderEngineType *et, dummyet = {NULL}; RenderEngine dummyengine = {NULL}; PointerRNA dummyptr; - int have_function[7]; + int have_function[8]; /* setup dummy engine & engine type to store static properties in */ dummyengine.type = &dummyet; @@ -343,7 +351,8 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo et->view_update = (have_function[3]) ? engine_view_update : NULL; et->render_to_view = (have_function[4]) ? engine_render_to_view : NULL; et->update_script_node = (have_function[5]) ? engine_update_script_node : NULL; - et->collection_settings_create = (have_function[6]) ? engine_collection_settings_create : NULL; + et->update_render_passes = (have_function[6]) ? engine_update_render_passes : NULL; + et->collection_settings_create = (have_function[7]) ? engine_collection_settings_create : NULL; RE_engines_register(bmain, et); @@ -440,6 +449,11 @@ static RenderPass *rna_RenderPass_find_by_type(RenderLayer *rl, int passtype, co return RE_pass_find_by_type(rl, passtype, view); } +static RenderPass *rna_RenderPass_find_by_name(RenderLayer *rl, const char *name, const char *view) +{ + return RE_pass_find_by_name(rl, name, view); +} + #else /* RNA_RUNTIME */ static void rna_def_render_engine(BlenderRNA *brna) @@ -450,6 +464,13 @@ static void rna_def_render_engine(BlenderRNA *brna) FunctionRNA *func; PropertyRNA *parm; + static EnumPropertyItem render_pass_type_items[] = { + {SOCK_FLOAT, "VALUE", 0, "Value", ""}, + {SOCK_VECTOR, "VECTOR", 0, "Vector", ""}, + {SOCK_RGBA, "COLOR", 0, "Color", ""}, + {0, NULL, 0, NULL, NULL} + }; + srna = RNA_def_struct(brna, "RenderEngine", NULL); RNA_def_struct_sdna(srna, "RenderEngine"); RNA_def_struct_ui_text(srna, "Render Engine", "Render engine"); @@ -511,6 +532,12 @@ static void rna_def_render_engine(BlenderRNA *brna) parm = RNA_def_pointer(func, "node", "Node", "", ""); RNA_def_parameter_flags(parm, 0, PARM_RNAPTR); + func = RNA_def_function(srna, "update_render_passes", NULL); + RNA_def_function_ui_description(func, "Update the render passes that will be generated"); + RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE); + parm = RNA_def_pointer(func, "scene", "Scene", "", ""); + parm = RNA_def_pointer(func, "renderlayer", "SceneRenderLayer", "", ""); + /* per-collection engine settings initialization */ func = RNA_def_function(srna, "collection_settings_create", NULL); RNA_def_function_ui_description(func, "Create the per collection settings for the engine"); @@ -553,6 +580,17 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_boolean(func, "cancel", 0, "Cancel", "Don't mark tile as done, don't merge results unless forced"); RNA_def_boolean(func, "do_merge_results", 0, "Merge Results", "Merge results even if cancel=true"); + func = RNA_def_function(srna, "add_pass", "RE_engine_add_pass"); + RNA_def_function_ui_description(func, "Add a pass to the render layer"); + parm = RNA_def_string(func, "name", NULL, 0, "Name", "Name of the Pass, without view or channel tag"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_int(func, "channels", 0, 0, INT_MAX, "Channels", "", 0, INT_MAX); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_string(func, "chan_id", NULL, 0, "Channel IDs", "Channel names, one character per channel"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + RNA_def_string(func, "layer", NULL, 0, "Layer", "Single layer to add render pass to"); /* NULL ok here */ + + func = RNA_def_function(srna, "test_break", "RE_engine_test_break"); RNA_def_function_ui_description(func, "Test if the render operation should been canceled, this is a fast call that should be used regularly for responsiveness"); parm = RNA_def_boolean(func, "do_break", 0, "Break", ""); @@ -675,6 +713,21 @@ static void rna_def_render_engine(BlenderRNA *brna) prop = RNA_def_property(srna, "use_highlight_tiles", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", RE_ENGINE_HIGHLIGHT_TILES); + func = RNA_def_function(srna, "register_pass", "RE_engine_register_pass"); + RNA_def_function_ui_description(func, "Register a render pass that will be part of the render with the current settings"); + prop = RNA_def_pointer(func, "scene", "Scene", "", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + prop = RNA_def_pointer(func, "srl", "SceneRenderLayer", "", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + prop = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + prop = RNA_def_int(func, "channels", 1, 1, 8, "Channels", "", 1, 4); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + prop = RNA_def_string(func, "chanid", NULL, 8, "Channel IDs", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + prop = RNA_def_enum(func, "type", render_pass_type_items, SOCK_FLOAT, "Type", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + /* registration */ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); @@ -803,6 +856,15 @@ static void rna_def_render_passes(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_pointer(func, "render_pass", "RenderPass", "", "The matching render pass"); RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "find_by_name", "rna_RenderPass_find_by_name"); + RNA_def_function_ui_description(func, "Get the render pass for a given name and view"); + parm = RNA_def_string(func, "name", RE_PASSNAME_COMBINED, 0, "Pass", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_string(func, "view", NULL, 0, "View", "Render view to get pass from"); /* NULL ok here */ + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer(func, "render_pass", "RenderPass", "", "The matching render pass"); + RNA_def_function_return(func, parm); } static void rna_def_render_layer(BlenderRNA *brna) @@ -851,6 +913,11 @@ static void rna_def_render_pass(BlenderRNA *brna) RNA_define_verify_sdna(0); + prop = RNA_def_property(srna, "fullname", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "fullname"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_struct_name_property(srna, prop); + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "name"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -864,11 +931,6 @@ static void rna_def_render_pass(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "channels"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "passtype"); - RNA_def_property_enum_items(prop, rna_enum_render_pass_type_items); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - prop = RNA_def_property(srna, "rect", PROP_FLOAT, PROP_NONE); RNA_def_property_flag(prop, PROP_DYNAMIC); RNA_def_property_multi_array(prop, 2, NULL); @@ -879,11 +941,6 @@ static void rna_def_render_pass(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "view_id"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - prop = RNA_def_property(srna, "debug_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "debug_type"); - RNA_def_property_enum_items(prop, rna_enum_render_pass_debug_type_items); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_define_verify_sdna(1); } diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index a37c760f9d0..2703faf8036 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -462,6 +462,7 @@ EnumPropertyItem rna_enum_layer_collection_mode_settings_type_items[] = { #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_global.h" +#include "BKE_idprop.h" #include "BKE_image.h" #include "BKE_layer.h" #include "BKE_main.h" @@ -1627,6 +1628,18 @@ static void rna_Scene_use_view_map_cache_update(Main *UNUSED(bmain), Scene *UNUS #endif } +static IDProperty *rna_SceneRenderLayer_idprops(PointerRNA *ptr, bool create) +{ + SceneRenderLayer *srl = (SceneRenderLayer *)ptr->data; + + if (create && !srl->prop) { + IDPropertyTemplate val = {0}; + srl->prop = IDP_New(IDP_GROUP, &val, "SceneRenderLayer ID properties"); + } + + return srl->prop; +} + static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value) { Scene *scene = (Scene *)ptr->id.data; @@ -1731,11 +1744,18 @@ static void rna_SceneRenderLayer_pass_update(Main *bmain, Scene *activescene, Po Scene *scene = (Scene *)ptr->id.data; if (scene->nodetree) - ntreeCompositForceHidden(scene->nodetree); - + ntreeCompositUpdateRLayers(scene->nodetree); + rna_Scene_glsl_update(bmain, activescene, ptr); } +static void rna_SceneRenderLayer_update_render_passes(ID *id) +{ + Scene *scene = (Scene*) id; + if (scene->nodetree) + ntreeCompositUpdateRLayers(scene->nodetree); +} + static void rna_Scene_use_nodes_update(bContext *C, PointerRNA *ptr) { Scene *scene = (Scene *)ptr->data; @@ -6464,14 +6484,20 @@ static void rna_def_scene_render_layer(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; + FunctionRNA *func; srna = RNA_def_struct(brna, "SceneRenderLayer", NULL); RNA_def_struct_ui_text(srna, "Scene Render Layer", "Render layer"); RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS); RNA_def_struct_path_func(srna, "rna_SceneRenderLayer_path"); + RNA_def_struct_idprops_func(srna, "rna_SceneRenderLayer_idprops"); rna_def_render_layer_common(srna, 1); + func = RNA_def_function(srna, "update_render_passes", "rna_SceneRenderLayer_update_render_passes"); + RNA_def_function_ui_description(func, "Requery the enabled render passes from the render engine"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF); + /* Freestyle */ rna_def_freestyle_settings(brna); @@ -8155,14 +8181,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_struct_type(prop, "BakeSettings"); RNA_def_property_ui_text(prop, "Bake Data", ""); - /* Debugging settings. */ -#ifdef WITH_CYCLES_DEBUG - prop = RNA_def_property(srna, "debug_pass_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_enum_render_pass_debug_type_items); - RNA_def_property_ui_text(prop, "Debug Pass Type", "Type of the debug pass to use"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); -#endif - /* Nestled Data */ /* *** Non-Animated *** */ RNA_define_animate_sdna(false); diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 697b649a298..b57e33e85c7 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -291,8 +291,4 @@ if(WITH_FREESTYLE) add_definitions(-DWITH_FREESTYLE) endif() -if(WITH_CYCLES AND WITH_CYCLES_DEBUG) - add_definitions(-DWITH_CYCLES_DEBUG) -endif() - blender_add_lib(bf_nodes "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index 0215db1dd55..a5c2e604f46 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -139,6 +139,8 @@ void register_node_type_cmp_trackpos(void); void register_node_type_cmp_planetrackdeform(void); void register_node_type_cmp_cornerpin(void); -void node_cmp_rlayers_force_hidden_passes(struct bNode *node); +void node_cmp_rlayers_outputs(struct bNodeTree *ntree, struct bNode *node); +void node_cmp_rlayers_register_pass(struct bNodeTree *ntree, struct bNode *node, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int type); +const char *node_cmp_rlayers_sock_to_pass(int sock_index); #endif diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index cb565bd5491..36778a18f77 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -240,8 +240,15 @@ void ntreeCompositExecTree(Scene *scene, bNodeTree *ntree, RenderData *rd, int r /* *********************************************** */ -/* based on rules, force sockets hidden always */ -void ntreeCompositForceHidden(bNodeTree *ntree) +/* Update the outputs of the render layer nodes. + * Since the outputs depend on the render engine, this part is a bit complex: + * - ntreeCompositUpdateRLayers is called and loops over all render layer nodes + * - Each render layer node calls the update function of the render engine that's used for its scene + * - The render engine calls RE_engine_register_pass for each pass + * - RE_engine_register_pass calls ntreeCompositRegisterPass, + * which calls node_cmp_rlayers_register_pass for every render layer node + */ +void ntreeCompositUpdateRLayers(bNodeTree *ntree) { bNode *node; @@ -249,16 +256,20 @@ void ntreeCompositForceHidden(bNodeTree *ntree) for (node = ntree->nodes.first; node; node = node->next) { if (node->type == CMP_NODE_R_LAYERS) - node_cmp_rlayers_force_hidden_passes(node); - - /* XXX this stuff is called all the time, don't want that. - * Updates should only happen when actually necessary. - */ -#if 0 - else if (node->type == CMP_NODE_IMAGE) { - nodeUpdate(ntree, node); - } -#endif + node_cmp_rlayers_outputs(ntree, node); + } + +} + +void ntreeCompositRegisterPass(bNodeTree *ntree, Scene *scene, SceneRenderLayer *srl, const char *name, int type) +{ + bNode *node; + + if (ntree == NULL) return; + + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == CMP_NODE_R_LAYERS) + node_cmp_rlayers_register_pass(ntree, node, scene, srl, name, type); } } diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 4f02c106569..510e24554f0 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -32,192 +32,104 @@ #include "node_composite_util.h" #include "BLI_utildefines.h" +#include "BLI_linklist.h" #include "DNA_scene_types.h" +#include "RE_engine.h" + #include "BKE_context.h" #include "BKE_global.h" #include "BKE_main.h" -#ifdef WITH_CYCLES_DEBUG -# include "RE_pipeline.h" -#endif - /* **************** IMAGE (and RenderResult, multilayer image) ******************** */ static bNodeSocketTemplate cmp_node_rlayers_out[] = { - { SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 0, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 0, N_("Z"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VECTOR, 0, N_("UV"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VECTOR, 0, N_("Speed"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Diffuse"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Specular"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Shadow"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("AO"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Reflect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Refract"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 0, N_("IndexOB"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 0, N_("IndexMA"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 0, N_("Mist"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Emit"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Environment"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Diffuse Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Diffuse Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Diffuse Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Glossy Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Glossy Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Glossy Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Transmission Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Transmission Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Transmission Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Subsurface Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Subsurface Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Subsurface Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, -#ifdef WITH_CYCLES_DEBUG - { SOCK_RGBA, 0, N_("Debug"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, -#endif + { SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_(RE_PASSNAME_Z), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, N_(RE_PASSNAME_NORMAL), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, N_(RE_PASSNAME_UV), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, N_(RE_PASSNAME_VECTOR), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_RGBA), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_SPEC), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_SHADOW), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_AO), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_REFLECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_REFRACT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_(RE_PASSNAME_INDEXOB), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_(RE_PASSNAME_INDEXMA), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_(RE_PASSNAME_MIST), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_EMIT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_ENVIRONMENT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_GLOSSY_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_GLOSSY_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_GLOSSY_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_TRANSM_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_TRANSM_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_TRANSM_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocket *cmp_node_image_add_render_pass_output(bNodeTree *ntree, bNode *node, int pass, int rres_index) +static void cmp_node_image_add_pass_output(bNodeTree *ntree, bNode *node, + const char *name, const char *passname, + int rres_index, int type, int is_rlayers, + LinkNodePair *available_sockets, int *prev_index) { bNodeSocket *sock; - NodeImageLayer *sockdata; - - sock = node_add_socket_from_template(ntree, node, &cmp_node_rlayers_out[rres_index], SOCK_OUT); - /* extra socket info */ - sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); - sock->storage = sockdata; - - sockdata->pass_flag = pass; - - return sock; -} - -static void cmp_node_image_add_render_pass_outputs(bNodeTree *ntree, bNode *node, int passflag) -{ - if (passflag & SCE_PASS_COMBINED) { - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_IMAGE); - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_ALPHA); - } - - if (passflag & SCE_PASS_Z) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_Z, RRES_OUT_Z); - if (passflag & SCE_PASS_NORMAL) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_NORMAL, RRES_OUT_NORMAL); - if (passflag & SCE_PASS_VECTOR) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_VECTOR, RRES_OUT_VEC); - if (passflag & SCE_PASS_UV) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_UV, RRES_OUT_UV); - if (passflag & SCE_PASS_RGBA) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_RGBA, RRES_OUT_RGBA); - if (passflag & SCE_PASS_DIFFUSE) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE, RRES_OUT_DIFF); - if (passflag & SCE_PASS_SPEC) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SPEC, RRES_OUT_SPEC); - if (passflag & SCE_PASS_SHADOW) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SHADOW, RRES_OUT_SHADOW); - if (passflag & SCE_PASS_AO) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_AO, RRES_OUT_AO); - if (passflag & SCE_PASS_REFLECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFLECT, RRES_OUT_REFLECT); - if (passflag & SCE_PASS_REFRACT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFRACT, RRES_OUT_REFRACT); - if (passflag & SCE_PASS_INDIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDIRECT, RRES_OUT_INDIRECT); - if (passflag & SCE_PASS_INDEXOB) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXOB, RRES_OUT_INDEXOB); - if (passflag & SCE_PASS_INDEXMA) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXMA, RRES_OUT_INDEXMA); - if (passflag & SCE_PASS_MIST) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_MIST, RRES_OUT_MIST); - if (passflag & SCE_PASS_EMIT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_EMIT, RRES_OUT_EMIT); - if (passflag & SCE_PASS_ENVIRONMENT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_ENVIRONMENT, RRES_OUT_ENV); - - if (passflag & SCE_PASS_DIFFUSE_DIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_DIRECT, RRES_OUT_DIFF_DIRECT); - if (passflag & SCE_PASS_DIFFUSE_INDIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_INDIRECT, RRES_OUT_DIFF_INDIRECT); - if (passflag & SCE_PASS_DIFFUSE_COLOR) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_COLOR, RRES_OUT_DIFF_COLOR); - - if (passflag & SCE_PASS_GLOSSY_DIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_DIRECT, RRES_OUT_GLOSSY_DIRECT); - if (passflag & SCE_PASS_GLOSSY_INDIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_INDIRECT, RRES_OUT_GLOSSY_INDIRECT); - if (passflag & SCE_PASS_GLOSSY_COLOR) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_COLOR, RRES_OUT_GLOSSY_COLOR); - - if (passflag & SCE_PASS_TRANSM_DIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_DIRECT, RRES_OUT_TRANSM_DIRECT); - if (passflag & SCE_PASS_TRANSM_INDIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_INDIRECT, RRES_OUT_TRANSM_INDIRECT); - if (passflag & SCE_PASS_TRANSM_COLOR) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_COLOR, RRES_OUT_TRANSM_COLOR); - - if (passflag & SCE_PASS_SUBSURFACE_DIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_DIRECT, RRES_OUT_SUBSURFACE_DIRECT); - if (passflag & SCE_PASS_SUBSURFACE_INDIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_INDIRECT, RRES_OUT_SUBSURFACE_INDIRECT); - if (passflag & SCE_PASS_SUBSURFACE_COLOR) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_COLOR, RRES_OUT_SUBSURFACE_COLOR); - -#ifdef WITH_CYCLES_DEBUG - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DEBUG, RRES_OUT_DEBUG); -#endif -} - -static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node, RenderLayer *rl) -{ - bNodeSocket *sock; - NodeImageLayer *sockdata; - RenderPass *rpass; - int index; - int passflag = 0; - for (rpass = rl->passes.first, index = 0; rpass; rpass = rpass->next, ++index) { - int type; - if (rpass->channels == 1) - type = SOCK_FLOAT; - else - type = SOCK_RGBA; - - /* we only need one socket per type */ - if (passflag & rpass->passtype) - continue; - - passflag |= rpass->passtype; - - sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, rpass->internal_name, rpass->internal_name); + int sock_index = BLI_findstringindex(&node->outputs, name, offsetof(bNodeSocket, name)); + + if (sock_index < 0) { + /* The first 31 sockets always are the legacy hardcoded sockets. + * Any dynamically allocated sockets follow afterwards, and are sorted in the order in which they were stored in the RenderResult. + * Therefore, we remember the index of the last matched socket. New sockets are placed behind the previously traversed one, but always after the first 31. */ + int after_index = *prev_index; + if (is_rlayers && after_index < 30) + after_index = 30; + + if (rres_index >= 0) { + sock = node_add_socket_from_template(ntree, node, &cmp_node_rlayers_out[rres_index], SOCK_OUT); + } + else { + sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, name, name); + } /* extra socket info */ - sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); + NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); sock->storage = sockdata; - - sockdata->pass_index = index; - sockdata->pass_flag = rpass->passtype; - - if (rpass->passtype == SCE_PASS_COMBINED) { - sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, SOCK_FLOAT, PROP_NONE, "Alpha", "Alpha"); - sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); - sock->storage = sockdata; - sockdata->pass_index = index; - sockdata->pass_flag = rpass->passtype; + + BLI_strncpy(sockdata->pass_name, passname, sizeof(sockdata->pass_name)); + + sock_index = BLI_listbase_count(&node->outputs)-1; + if (sock_index != after_index+1) { + bNodeSocket *after_sock = BLI_findlink(&node->outputs, after_index); + BLI_remlink(&node->outputs, sock); + BLI_insertlinkafter(&node->outputs, after_sock, sock); } } + else { + sock = BLI_findlink(&node->outputs, sock_index); + } + + BLI_linklist_append(available_sockets, sock); + *prev_index = sock_index; } -static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node) +static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node, LinkNodePair *available_sockets) { Image *ima = (Image *)node->id; + ImBuf *ibuf; + int prev_index = -1; if (ima) { ImageUser *iuser = node->storage; ImageUser load_iuser = {NULL}; - ImBuf *ibuf; int offset = BKE_image_sequence_guess_offset(ima); /* It is possible that image user in this node is not @@ -238,104 +150,150 @@ static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node) RenderLayer *rl = BLI_findlink(&ima->rr->layers, iuser->layer); if (rl) { - if (ima->type != IMA_TYPE_MULTILAYER) - cmp_node_image_add_render_pass_outputs(ntree, node, rl->passflag); - else - cmp_node_image_add_multilayer_outputs(ntree, node, rl); + RenderPass *rpass; + for (rpass = rl->passes.first; rpass; rpass = rpass->next) { + int type; + if (rpass->channels == 1) + type = SOCK_FLOAT; + else + type = SOCK_RGBA; + + /* Special handling for the Combined pass to ensure compatibility. */ + if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) { + cmp_node_image_add_pass_output(ntree, node, "Image", rpass->name, -1, type, false, available_sockets, &prev_index); + cmp_node_image_add_pass_output(ntree, node, "Alpha", rpass->name, -1, SOCK_FLOAT, false, available_sockets, &prev_index); + } + else { + cmp_node_image_add_pass_output(ntree, node, rpass->name, rpass->name, -1, type, false, available_sockets, &prev_index); + } + } + BKE_image_release_ibuf(ima, ibuf, NULL); + return; } - else - cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA); } - else - cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA | RRES_OUT_Z); - + } + + cmp_node_image_add_pass_output(ntree, node, "Image", RE_PASSNAME_COMBINED, RRES_OUT_IMAGE, SOCK_RGBA, false, available_sockets, &prev_index); + cmp_node_image_add_pass_output(ntree, node, "Alpha", RE_PASSNAME_COMBINED, RRES_OUT_ALPHA, SOCK_FLOAT, false, available_sockets, &prev_index); + + if (ima) { + if (!ima->rr) { + cmp_node_image_add_pass_output(ntree, node, RE_PASSNAME_Z, RE_PASSNAME_Z, RRES_OUT_Z, SOCK_FLOAT, false, available_sockets, &prev_index); + } BKE_image_release_ibuf(ima, ibuf, NULL); } - else - cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA); } -static bNodeSocket *cmp_node_image_output_find_match(bNode *UNUSED(node), bNodeSocket *newsock, ListBase *oldsocklist) -{ - bNodeSocket *sock; - - for (sock = oldsocklist->first; sock; sock = sock->next) - if (STREQ(sock->name, newsock->name)) - return sock; - return NULL; -} +typedef struct RLayerUpdateData { + LinkNodePair *available_sockets; + int prev_index; +} RLayerUpdateData; -static bNodeSocket *cmp_node_image_output_relink(bNode *node, bNodeSocket *oldsock, int oldindex) +void node_cmp_rlayers_register_pass(bNodeTree *ntree, bNode *node, Scene *scene, SceneRenderLayer *srl, const char *name, int type) { - bNodeSocket *sock; - - /* first try to find matching socket name */ - for (sock = node->outputs.first; sock; sock = sock->next) - if (STREQ(sock->name, oldsock->name)) - return sock; - - /* no matching name, simply link to same index */ - return BLI_findlink(&node->outputs, oldindex); + RLayerUpdateData *data = node->storage; + + if (scene == NULL || srl == NULL || data == NULL || node->id != scene) { + return; + } + + SceneRenderLayer *node_srl = BLI_findlink(&scene->r.layers, node->custom1); + if (node_srl != srl) { + return; + } + + /* Special handling for the Combined pass to ensure compatibility. */ + if (STREQ(name, RE_PASSNAME_COMBINED)) { + cmp_node_image_add_pass_output(ntree, node, "Image", name, -1, type, true, data->available_sockets, &data->prev_index); + cmp_node_image_add_pass_output(ntree, node, "Alpha", name, -1, SOCK_FLOAT, true, data->available_sockets, &data->prev_index); + } + else { + cmp_node_image_add_pass_output(ntree, node, name, name, -1, type, true, data->available_sockets, &data->prev_index); + } } -static void cmp_node_image_sync_output(bNode *UNUSED(node), bNodeSocket *UNUSED(newsock), bNodeSocket *UNUSED(oldsock)) +static void cmp_node_rlayer_create_outputs(bNodeTree *ntree, bNode *node, LinkNodePair *available_sockets) { - /* pass */ + Scene *scene = (Scene *)node->id; + + if (scene) { + RenderEngineType *engine_type = RE_engines_find(scene->r.engine); + if(engine_type && engine_type->update_render_passes) { + SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, node->custom1); + if(srl) { + RLayerUpdateData *data = MEM_mallocN(sizeof(RLayerUpdateData), "render layer update data"); + data->available_sockets = available_sockets; + data->prev_index = -1; + node->storage = data; + + RenderEngine *engine = RE_engine_create(engine_type); + engine_type->update_render_passes(engine, scene, srl); + RE_engine_free(engine); + + MEM_freeN(data); + node->storage = NULL; + + return; + } + } + } + + int prev_index = -1; + cmp_node_image_add_pass_output(ntree, node, "Image", RE_PASSNAME_COMBINED, RRES_OUT_IMAGE, SOCK_RGBA, true, available_sockets, &prev_index); + cmp_node_image_add_pass_output(ntree, node, "Alpha", RE_PASSNAME_COMBINED, RRES_OUT_ALPHA, SOCK_FLOAT, true, available_sockets, &prev_index); } /* XXX make this into a generic socket verification function for dynamic socket replacement (multilayer, groups, static templates) */ -static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node) +static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node, bool rlayer) { - bNodeSocket *newsock, *oldsock, *oldsock_next; - ListBase oldsocklist; - int oldindex; - bNodeLink *link; - - /* store current nodes in oldsocklist, then clear socket list */ - oldsocklist = node->outputs; - BLI_listbase_clear(&node->outputs); + bNodeSocket *sock, *sock_next; + LinkNodePair available_sockets = {NULL, NULL}; + int sock_index; /* XXX make callback */ - cmp_node_image_create_outputs(ntree, node); - - for (newsock = node->outputs.first; newsock; newsock = newsock->next) { - /* XXX make callback */ - oldsock = cmp_node_image_output_find_match(node, newsock, &oldsocklist); - if (oldsock) { - /* XXX make callback */ - cmp_node_image_sync_output(node, newsock, oldsock); + if (rlayer) + cmp_node_rlayer_create_outputs(ntree, node, &available_sockets); + else + cmp_node_image_create_outputs(ntree, node, &available_sockets); + + /* Get rid of sockets whose passes are not available in the image. + * If sockets that are not available would be deleted, the connections to them would be lost + * when e.g. opening a file (since there's no render at all yet). + * Therefore, sockets with connected links will just be set as unavailable. + * + * Another important detail comes from compatibility with the older socket model, where there + * was a fixed socket per pass type that was just hidden or not. Therefore, older versions expect + * the first 31 passes to belong to a specific pass type. + * So, we keep those 31 always allocated before the others as well, even if they have no links attached. */ + sock_index = 0; + for (sock = node->outputs.first; sock; sock = sock_next, sock_index++) { + sock_next = sock->next; + if (BLI_linklist_index(available_sockets.list, sock) >= 0) { + sock->flag &= ~(SOCK_UNAVAIL | SOCK_HIDDEN); } - } - - /* move links to new socket */ - for (oldsock = oldsocklist.first, oldindex = 0; oldsock; oldsock = oldsock->next, ++oldindex) { - newsock = cmp_node_image_output_relink(node, oldsock, oldindex); - - if (newsock) { + else { + bNodeLink *link; for (link = ntree->links.first; link; link = link->next) { - if (link->fromsock == oldsock) - link->fromsock = newsock; + if (link->fromsock == sock) break; + } + if (!link && sock_index > 30) { + MEM_freeN(sock->storage); + nodeRemoveSocket(ntree, node, sock); + } + else { + sock->flag |= SOCK_UNAVAIL; } } } - - /* delete old sockets - * XXX oldsock is not actually in the node->outputs list any more, - * but the nodeRemoveSocket function works anyway. In future this - * should become part of the core code, so can take care of this behavior. - */ - for (oldsock = oldsocklist.first; oldsock; oldsock = oldsock_next) { - oldsock_next = oldsock->next; - MEM_freeN(oldsock->storage); - nodeRemoveSocket(ntree, node, oldsock); - } + + BLI_linklist_free(available_sockets.list, NULL); } static void cmp_node_image_update(bNodeTree *ntree, bNode *node) { /* avoid unnecessary updates, only changes to the image/image user data are of interest */ if (node->update & NODE_UPDATE_ID) - cmp_node_image_verify_outputs(ntree, node); + cmp_node_image_verify_outputs(ntree, node, false); } static void node_composit_init_image(bNodeTree *ntree, bNode *node) @@ -348,7 +306,7 @@ static void node_composit_init_image(bNodeTree *ntree, bNode *node) iuser->ok = 1; /* setup initial outputs */ - cmp_node_image_verify_outputs(ntree, node); + cmp_node_image_verify_outputs(ntree, node, false); } static void node_composit_free_image(bNode *node) @@ -388,87 +346,45 @@ void register_node_type_cmp_image(void) /* **************** RENDER RESULT ******************** */ -static void set_output_visible(bNode *node, int passflag, int index, int pass) +void node_cmp_rlayers_outputs(bNodeTree *ntree, bNode *node) { - bNodeSocket *sock = BLI_findlink(&node->outputs, index); - bool pass_enabled = ((passflag & pass) != 0); -#ifdef WITH_CYCLES_DEBUG - pass_enabled |= (pass == SCE_PASS_DEBUG); -#endif - /* clear the SOCK_HIDDEN flag as well, in case a socket was hidden before */ - if (pass_enabled) - sock->flag &= ~(SOCK_HIDDEN | SOCK_UNAVAIL); - else - sock->flag |= SOCK_UNAVAIL; + cmp_node_image_verify_outputs(ntree, node, true); } -/* clumsy checking... should do dynamic outputs once */ -void node_cmp_rlayers_force_hidden_passes(bNode *node) +const char* node_cmp_rlayers_sock_to_pass(int sock_index) { - Scene *scene = (Scene *)node->id; - SceneRenderLayer *srl; - int passflag; - bNodeSocket *sock; - - /* must always have valid scene pointer */ - if (!scene) - return; - - srl = BLI_findlink(&scene->r.layers, node->custom1); - if (!srl) - return; - - passflag = srl->passflag; - - for (sock = node->outputs.first; sock; sock = sock->next) - sock->flag &= ~SOCK_UNAVAIL; - - set_output_visible(node, passflag, RRES_OUT_IMAGE, SCE_PASS_COMBINED); - set_output_visible(node, passflag, RRES_OUT_ALPHA, SCE_PASS_COMBINED); - - set_output_visible(node, passflag, RRES_OUT_Z, SCE_PASS_Z); - set_output_visible(node, passflag, RRES_OUT_NORMAL, SCE_PASS_NORMAL); - set_output_visible(node, passflag, RRES_OUT_VEC, SCE_PASS_VECTOR); - set_output_visible(node, passflag, RRES_OUT_UV, SCE_PASS_UV); - set_output_visible(node, passflag, RRES_OUT_RGBA, SCE_PASS_RGBA); - set_output_visible(node, passflag, RRES_OUT_DIFF, SCE_PASS_DIFFUSE); - set_output_visible(node, passflag, RRES_OUT_SPEC, SCE_PASS_SPEC); - set_output_visible(node, passflag, RRES_OUT_SHADOW, SCE_PASS_SHADOW); - set_output_visible(node, passflag, RRES_OUT_AO, SCE_PASS_AO); - set_output_visible(node, passflag, RRES_OUT_REFLECT, SCE_PASS_REFLECT); - set_output_visible(node, passflag, RRES_OUT_REFRACT, SCE_PASS_REFRACT); - set_output_visible(node, passflag, RRES_OUT_INDIRECT, SCE_PASS_INDIRECT); - set_output_visible(node, passflag, RRES_OUT_INDEXOB, SCE_PASS_INDEXOB); - set_output_visible(node, passflag, RRES_OUT_INDEXMA, SCE_PASS_INDEXMA); - set_output_visible(node, passflag, RRES_OUT_MIST, SCE_PASS_MIST); - set_output_visible(node, passflag, RRES_OUT_EMIT, SCE_PASS_EMIT); - set_output_visible(node, passflag, RRES_OUT_ENV, SCE_PASS_ENVIRONMENT); - set_output_visible(node, passflag, RRES_OUT_DIFF_DIRECT, SCE_PASS_DIFFUSE_DIRECT); - set_output_visible(node, passflag, RRES_OUT_DIFF_INDIRECT, SCE_PASS_DIFFUSE_INDIRECT); - set_output_visible(node, passflag, RRES_OUT_DIFF_COLOR, SCE_PASS_DIFFUSE_COLOR); - set_output_visible(node, passflag, RRES_OUT_GLOSSY_DIRECT, SCE_PASS_GLOSSY_DIRECT); - set_output_visible(node, passflag, RRES_OUT_GLOSSY_INDIRECT, SCE_PASS_GLOSSY_INDIRECT); - set_output_visible(node, passflag, RRES_OUT_GLOSSY_COLOR, SCE_PASS_GLOSSY_COLOR); - set_output_visible(node, passflag, RRES_OUT_TRANSM_DIRECT, SCE_PASS_TRANSM_DIRECT); - set_output_visible(node, passflag, RRES_OUT_TRANSM_INDIRECT, SCE_PASS_TRANSM_INDIRECT); - set_output_visible(node, passflag, RRES_OUT_TRANSM_COLOR, SCE_PASS_TRANSM_COLOR); - set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_DIRECT, SCE_PASS_SUBSURFACE_DIRECT); - set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_INDIRECT, SCE_PASS_SUBSURFACE_INDIRECT); - set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_COLOR, SCE_PASS_SUBSURFACE_COLOR); - -#ifdef WITH_CYCLES_DEBUG - set_output_visible(node, passflag, RRES_OUT_DEBUG, SCE_PASS_DEBUG); -#endif + const char* sock_to_passname[] = { + RE_PASSNAME_COMBINED, RE_PASSNAME_COMBINED, + RE_PASSNAME_Z, RE_PASSNAME_NORMAL, RE_PASSNAME_UV, RE_PASSNAME_VECTOR, RE_PASSNAME_RGBA, + RE_PASSNAME_DIFFUSE, RE_PASSNAME_SPEC, RE_PASSNAME_SHADOW, RE_PASSNAME_AO, + RE_PASSNAME_REFLECT, RE_PASSNAME_REFRACT, RE_PASSNAME_INDIRECT, + RE_PASSNAME_INDEXOB, RE_PASSNAME_INDEXMA, RE_PASSNAME_MIST, RE_PASSNAME_EMIT, RE_PASSNAME_ENVIRONMENT, + RE_PASSNAME_DIFFUSE_DIRECT, RE_PASSNAME_DIFFUSE_INDIRECT, RE_PASSNAME_DIFFUSE_COLOR, + RE_PASSNAME_GLOSSY_DIRECT, RE_PASSNAME_GLOSSY_INDIRECT, RE_PASSNAME_GLOSSY_COLOR, + RE_PASSNAME_TRANSM_DIRECT, RE_PASSNAME_TRANSM_INDIRECT, RE_PASSNAME_TRANSM_COLOR, + RE_PASSNAME_SUBSURFACE_DIRECT, RE_PASSNAME_SUBSURFACE_INDIRECT, RE_PASSNAME_SUBSURFACE_COLOR + }; + if (sock_index > 30) { + return NULL; + } + return sock_to_passname[sock_index]; } static void node_composit_init_rlayers(const bContext *C, PointerRNA *ptr) { Scene *scene = CTX_data_scene(C); bNode *node = ptr->data; - + int sock_index = 0; + node->id = &scene->id; - - node_cmp_rlayers_force_hidden_passes(node); + + for (bNodeSocket *sock = node->outputs.first; sock; sock = sock->next, sock_index++) + { + NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); + sock->storage = sockdata; + + BLI_strncpy(sockdata->pass_name, node_cmp_rlayers_sock_to_pass(sock_index), sizeof(sockdata->pass_name)); + } } static int node_composit_poll_rlayers(bNodeType *UNUSED(ntype), bNodeTree *ntree) @@ -489,6 +405,29 @@ static int node_composit_poll_rlayers(bNodeType *UNUSED(ntype), bNodeTree *ntree return false; } +static void node_composit_free_rlayers(bNode *node) +{ + bNodeSocket *sock; + + /* free extra socket info */ + for (sock = node->outputs.first; sock; sock = sock->next) + MEM_freeN(sock->storage); +} + +static void node_composit_copy_rlayers(bNodeTree *UNUSED(dest_ntree), bNode *UNUSED(dest_node), bNode *src_node) +{ + bNodeSocket *sock; + + /* copy extra socket info */ + for (sock = src_node->outputs.first; sock; sock = sock->next) + sock->new_sock->storage = MEM_dupallocN(sock->storage); +} + +static void cmp_node_rlayers_update(bNodeTree *ntree, bNode *node) +{ + cmp_node_image_verify_outputs(ntree, node, true); +} + void register_node_type_cmp_rlayers(void) { static bNodeType ntype; @@ -497,6 +436,9 @@ void register_node_type_cmp_rlayers(void) node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out); ntype.initfunc_api = node_composit_init_rlayers; ntype.poll = node_composit_poll_rlayers; + node_type_storage(&ntype, NULL, node_composit_free_rlayers, node_composit_copy_rlayers); + node_type_update(&ntype, cmp_node_rlayers_update, NULL); + node_type_init(&ntype, node_cmp_rlayers_outputs); nodeRegisterType(&ntype); } diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt index 024d8296b8f..282942709f0 100644 --- a/source/blender/render/CMakeLists.txt +++ b/source/blender/render/CMakeLists.txt @@ -34,6 +34,7 @@ set(INC ../depsgraph ../makesdna ../makesrna + ../nodes ../physics ../draw ../../../intern/atomic @@ -166,10 +167,6 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -if(WITH_CYCLES AND WITH_CYCLES_DEBUG) - add_definitions(-DWITH_CYCLES_DEBUG) -endif() - if(APPLE) # SSE math is enabled by default on x86_64 if(CMAKE_OSX_ARCHITECTURES MATCHES "i386") diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index b1add4ee168..13848093899 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -102,6 +102,7 @@ typedef struct RenderEngineType { void (*render_to_view)(struct RenderEngine *engine, const struct bContext *context); void (*update_script_node)(struct RenderEngine *engine, struct bNodeTree *ntree, struct bNode *node); + void (*update_render_passes)(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl); void (*collection_settings_create)(struct RenderEngine *engine, struct IDProperty *props); @@ -149,6 +150,7 @@ void RE_result_load_from_file(struct RenderResult *result, struct ReportList *re struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname); void RE_engine_update_result(RenderEngine *engine, struct RenderResult *result); +void RE_engine_add_pass(RenderEngine *engine, const char *name, int channels, const char *chan_id, const char *layername); void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int cancel, int merge_results); const char *RE_engine_active_view_get(RenderEngine *engine); @@ -170,6 +172,9 @@ bool RE_engine_is_external(struct Render *re); void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe); +void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl, + const char *name, int channels, const char *chanid, int type); + /* Engine Types */ void RE_engines_init(void); diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index babb44ed64e..145186548e6 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -84,25 +84,19 @@ typedef struct RenderView { typedef struct RenderPass { struct RenderPass *next, *prev; - int passtype, channels; + int channels; char name[64]; /* amount defined in openexr_multi.h */ char chan_id[8]; /* amount defined in openexr_multi.h */ float *rect; int rectx, recty; - char internal_name[64]; /* EXR_PASS_MAXNAME */ + char fullname[64]; /* EXR_PASS_MAXNAME */ char view[64]; /* EXR_VIEW_MAXNAME */ int view_id; /* quick lookup */ - int debug_type; + int pad; } RenderPass; -enum { - RENDER_PASS_DEBUG_BVH_TRAVERSED_NODES = 0, - RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES = 1, - RENDER_PASS_DEBUG_RAY_BOUNCES = 2, - RENDER_PASS_DEBUG_BVH_INTERSECTIONS = 3, -}; /* a renderlayer is a full image, but with all passes and samples */ /* size of the rects is defined in RenderResult */ @@ -237,7 +231,7 @@ void RE_render_result_rect_from_ibuf( struct ImBuf *ibuf, const int view_id); struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name); -float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, int passtype, const char *viewname); +float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, const char *name, const char *viewname); /* add passes for grease pencil */ struct RenderPass *RE_create_gp_pass(struct RenderResult *rr, const char *layername, const char *viewname); @@ -347,6 +341,7 @@ int RE_seq_render_active(struct Scene *scene, struct RenderData *rd); bool RE_layers_have_name(struct RenderResult *result); +struct RenderPass *RE_pass_find_by_name(volatile struct RenderLayer *rl, const char *name, const char *viewname); struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname); /* shaded view or baking options */ @@ -396,13 +391,5 @@ struct RenderView *RE_RenderViewGetByName(struct RenderResult *res, const char * RenderResult *RE_DuplicateRenderResult(RenderResult *rr); -/******* Debug pass helper functions *********/ - -#ifdef WITH_CYCLES_DEBUG -int RE_debug_pass_num_channels_get(int pass_type); -const char *RE_debug_pass_name_get(int pass_type); -int RE_debug_pass_type_get(struct Render *re); -#endif - #endif /* __RE_PIPELINE_H__ */ diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h index 0c4f4e20325..4057d8c1052 100644 --- a/source/blender/render/intern/include/render_result.h +++ b/source/blender/render/intern/include/render_result.h @@ -67,6 +67,11 @@ void render_result_views_new(struct RenderResult *rr, struct RenderData *rd); void render_result_merge(struct RenderResult *rr, struct RenderResult *rrpart); +/* Add Passes */ + +void render_result_clone_passes(struct Render *re, struct RenderResult *rr, const char *viewname); +void render_result_add_pass(struct RenderResult *rr, const char *name, int channels, const char *chan_id, const char *layername, const char *viewname); + /* Free */ void render_result_free(struct RenderResult *rr); @@ -84,7 +89,7 @@ void render_result_exr_file_begin(struct Render *re); void render_result_exr_file_end(struct Render *re); /* render pass wrapper for gpencil */ -struct RenderPass *gp_add_pass(struct RenderResult *rr, struct RenderLayer *rl, int channels, int passtype, const char *viewname); +struct RenderPass *gp_add_pass(struct RenderResult *rr, struct RenderLayer *rl, int channels, const char *name, const char *viewname); void render_result_exr_file_merge(struct RenderResult *rr, struct RenderResult *rrpart, const char *viewname); diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h index 7254fd25ee6..f4c4a50ac27 100644 --- a/source/blender/render/intern/include/rendercore.h +++ b/source/blender/render/intern/include/rendercore.h @@ -34,6 +34,12 @@ #include "render_types.h" +#include "RE_engine.h" + +#include "DNA_node_types.h" + +#include "NOD_composite.h" + struct ShadeInput; struct ShadeResult; struct World; @@ -77,6 +83,8 @@ void zbufshade_sss_tile(struct RenderPart *pa); int get_sample_layers(struct RenderPart *pa, struct RenderLayer *rl, struct RenderLayer **rlpp); +void render_internal_update_passes(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl); + /* -------- ray.c ------- */ diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index 33258d04673..c5dec430c53 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -497,7 +497,7 @@ static void render_envmap(Render *re, EnvMap *env) float *rect; /* envmap is rendered independently of multiview */ - rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, ""); + rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, ""); ibuf = IMB_allocImBuf(envre->rectx, envre->recty, 24, IB_rect | IB_rectfloat); memcpy(ibuf->rect_float, rect, ibuf->channels * ibuf->x * ibuf->y * sizeof(float)); diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 059feae71bc..8b9e4a3eff5 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -67,13 +67,14 @@ #include "renderpipeline.h" #include "render_types.h" #include "render_result.h" +#include "rendercore.h" /* Render Engine Types */ static RenderEngineType internal_render_type = { NULL, NULL, "BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL | RE_USE_LEGACY_PIPELINE, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, render_internal_update_passes, NULL, NULL, {NULL, NULL, NULL} }; @@ -82,7 +83,7 @@ static RenderEngineType internal_render_type = { static RenderEngineType internal_game_type = { NULL, NULL, "BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME | RE_USE_LEGACY_PIPELINE, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, {NULL, NULL, NULL} }; @@ -235,6 +236,8 @@ RenderResult *RE_engine_begin_result( /* can be NULL if we CLAMP the width or height to 0 */ if (result) { + render_result_clone_passes(re, result, viewname); + RenderPart *pa; /* Copy EXR tile settings, so pipeline knows whether this is a result @@ -268,6 +271,17 @@ void RE_engine_update_result(RenderEngine *engine, RenderResult *result) } } +void RE_engine_add_pass(RenderEngine *engine, const char *name, int channels, const char *chan_id, const char *layername) +{ + Render *re = engine->re; + + if (!re || !re->result) { + return; + } + + render_result_add_pass(re->result, name, channels, chan_id, layername, NULL); +} + void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel, int merge_results) { Render *re = engine->re; @@ -753,3 +767,16 @@ int RE_engine_render(Render *re, int do_all) return 1; } +void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl, + const char *name, int UNUSED(channels), const char *UNUSED(chanid), int type) +{ + /* The channel information is currently not used, but is part of the API in case it's needed in the future. */ + + if (!(scene && srl && engine)) { + return; + } + + if (scene->nodetree) { + ntreeCompositRegisterPass(scene->nodetree, scene, srl, name, type); + } +} diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 36abdaf339e..ecbb9fbee0b 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -240,9 +240,9 @@ void RE_FreeRenderResult(RenderResult *res) render_result_free(res); } -float *RE_RenderLayerGetPass(volatile RenderLayer *rl, int passtype, const char *viewname) +float *RE_RenderLayerGetPass(volatile RenderLayer *rl, const char *name, const char *viewname) { - RenderPass *rpass = RE_pass_find_by_type(rl, passtype, viewname); + RenderPass *rpass = RE_pass_find_by_name(rl, name, viewname); return rpass ? rpass->rect : NULL; } @@ -383,13 +383,13 @@ void RE_AcquireResultImageViews(Render *re, RenderResult *rr) if (rl) { if (rv->rectf == NULL) { for (rview = (RenderView *)rr->views.first; rview; rview = rview->next) { - rview->rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, rview->name); + rview->rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, rview->name); } } if (rv->rectz == NULL) { for (rview = (RenderView *)rr->views.first; rview; rview = rview->next) { - rview->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z, rview->name); + rview->rectz = RE_RenderLayerGetPass(rl, RE_PASSNAME_Z, rview->name); } } } @@ -443,10 +443,10 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id) if (rl) { if (rv->rectf == NULL) - rr->rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, rv->name); + rr->rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, rv->name); if (rv->rectz == NULL) - rr->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z, rv->name); + rr->rectz = RE_RenderLayerGetPass(rl, RE_PASSNAME_Z, rv->name); } rr->have_combined = (rv->rectf != NULL); @@ -844,7 +844,7 @@ static void render_result_rescale(Render *re) if (src_rectf == NULL) { RenderLayer *rl = render_get_active_layer(re, re->result); if (rl != NULL) { - src_rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, NULL); + src_rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, NULL); } } @@ -863,7 +863,7 @@ static void render_result_rescale(Render *re) RenderLayer *rl; rl = render_get_active_layer(re, re->result); if (rl != NULL) { - dst_rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, NULL); + dst_rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, NULL); } } @@ -1657,7 +1657,7 @@ static void merge_renderresult_blur(RenderResult *rr, RenderResult *brr, float b /* passes are allocated in sync */ rpass1 = rl1->passes.first; for (rpass = rl->passes.first; rpass && rpass1; rpass = rpass->next, rpass1 = rpass1->next) { - if ((rpass->passtype & SCE_PASS_COMBINED) && key_alpha) + if (STREQ(rpass->name, RE_PASSNAME_COMBINED) && key_alpha) addblur_rect_key(rr, rpass->rect, rpass1->rect, blurfac); else addblur_rect(rr, rpass->rect, rpass1->rect, blurfac, rpass->channels); @@ -1857,6 +1857,8 @@ static void render_result_uncrop(Render *re) rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); + render_result_clone_passes(re, rres, NULL); + render_result_merge(rres, re->result); render_result_free(re->result); re->result = rres; @@ -3880,7 +3882,7 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char /* multiview: since the API takes no 'view', we use the first combined pass found */ for (rpass = layer->passes.first; rpass; rpass = rpass->next) - if (rpass->passtype == SCE_PASS_COMBINED) + if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) break; if (rpass == NULL) @@ -4006,13 +4008,12 @@ bool RE_layers_have_name(struct RenderResult *rr) return false; } -RenderPass *RE_pass_find_by_type(volatile RenderLayer *rl, int passtype, const char *viewname) +RenderPass *RE_pass_find_by_name(volatile RenderLayer *rl, const char *name, const char *viewname) { RenderPass *rp = NULL; for (rp = rl->passes.last; rp; rp = rp->prev) { - if (rp->passtype == passtype) { - + if (STREQ(rp->name, name)) { if (viewname == NULL || viewname[0] == '\0') break; else if (STREQ(rp->view, viewname)) @@ -4022,6 +4023,50 @@ RenderPass *RE_pass_find_by_type(volatile RenderLayer *rl, int passtype, const c return rp; } +/* Only provided for API compatibility, don't use this in new code! */ +RenderPass *RE_pass_find_by_type(volatile RenderLayer *rl, int passtype, const char *viewname) +{ +#define CHECK_PASS(NAME) \ + if (passtype == SCE_PASS_ ## NAME) \ + return RE_pass_find_by_name(rl, RE_PASSNAME_ ## NAME, viewname); + + CHECK_PASS(COMBINED); + CHECK_PASS(Z); + CHECK_PASS(VECTOR); + CHECK_PASS(NORMAL); + CHECK_PASS(UV); + CHECK_PASS(RGBA); + CHECK_PASS(EMIT); + CHECK_PASS(DIFFUSE); + CHECK_PASS(SPEC); + CHECK_PASS(SHADOW); + CHECK_PASS(AO); + CHECK_PASS(ENVIRONMENT); + CHECK_PASS(INDIRECT); + CHECK_PASS(REFLECT); + CHECK_PASS(REFRACT); + CHECK_PASS(INDEXOB); + CHECK_PASS(INDEXMA); + CHECK_PASS(MIST); + CHECK_PASS(RAYHITS); + CHECK_PASS(DIFFUSE_DIRECT); + CHECK_PASS(DIFFUSE_INDIRECT); + CHECK_PASS(DIFFUSE_COLOR); + CHECK_PASS(GLOSSY_DIRECT); + CHECK_PASS(GLOSSY_INDIRECT); + CHECK_PASS(GLOSSY_COLOR); + CHECK_PASS(TRANSM_DIRECT); + CHECK_PASS(TRANSM_INDIRECT); + CHECK_PASS(TRANSM_COLOR); + CHECK_PASS(SUBSURFACE_DIRECT); + CHECK_PASS(SUBSURFACE_INDIRECT); + CHECK_PASS(SUBSURFACE_COLOR); + +#undef CHECK_PASS + + return NULL; +} + /* create a renderlayer and renderpass for grease pencil layer */ RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const char *viewname) { @@ -4039,7 +4084,7 @@ RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const cha } /* clear previous pass if exist or the new image will be over previous one*/ - RenderPass *rp = RE_pass_find_by_type(rl, SCE_PASS_COMBINED, viewname); + RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname); if (rp) { if (rp->rect) { MEM_freeN(rp->rect); @@ -4047,5 +4092,5 @@ RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const cha BLI_freelinkN(&rl->passes, rp); } /* create a totally new pass */ - return gp_add_pass(rr, rl, 4, SCE_PASS_COMBINED, viewname); + return gp_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, viewname); } diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index f276c01e86a..8e6e6c9bb7d 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -173,363 +173,72 @@ void render_result_views_shallowdelete(RenderResult *rr) } } -static const char *name_from_passtype(int passtype, int channel) -{ - if (passtype == SCE_PASS_COMBINED) { - if (channel == -1) return "Combined"; - if (channel == 0) return "Combined.R"; - if (channel == 1) return "Combined.G"; - if (channel == 2) return "Combined.B"; - return "Combined.A"; - } - if (passtype == SCE_PASS_Z) { - if (channel == -1) return "Depth"; - return "Depth.Z"; - } - if (passtype == SCE_PASS_VECTOR) { - if (channel == -1) return "Vector"; - if (channel == 0) return "Vector.X"; - if (channel == 1) return "Vector.Y"; - if (channel == 2) return "Vector.Z"; - return "Vector.W"; - } - if (passtype == SCE_PASS_NORMAL) { - if (channel == -1) return "Normal"; - if (channel == 0) return "Normal.X"; - if (channel == 1) return "Normal.Y"; - return "Normal.Z"; - } - if (passtype == SCE_PASS_UV) { - if (channel == -1) return "UV"; - if (channel == 0) return "UV.U"; - if (channel == 1) return "UV.V"; - return "UV.A"; - } - if (passtype == SCE_PASS_RGBA) { - if (channel == -1) return "Color"; - if (channel == 0) return "Color.R"; - if (channel == 1) return "Color.G"; - if (channel == 2) return "Color.B"; - return "Color.A"; - } - if (passtype == SCE_PASS_EMIT) { - if (channel == -1) return "Emit"; - if (channel == 0) return "Emit.R"; - if (channel == 1) return "Emit.G"; - return "Emit.B"; - } - if (passtype == SCE_PASS_DIFFUSE) { - if (channel == -1) return "Diffuse"; - if (channel == 0) return "Diffuse.R"; - if (channel == 1) return "Diffuse.G"; - return "Diffuse.B"; - } - if (passtype == SCE_PASS_SPEC) { - if (channel == -1) return "Spec"; - if (channel == 0) return "Spec.R"; - if (channel == 1) return "Spec.G"; - return "Spec.B"; - } - if (passtype == SCE_PASS_SHADOW) { - if (channel == -1) return "Shadow"; - if (channel == 0) return "Shadow.R"; - if (channel == 1) return "Shadow.G"; - return "Shadow.B"; - } - if (passtype == SCE_PASS_AO) { - if (channel == -1) return "AO"; - if (channel == 0) return "AO.R"; - if (channel == 1) return "AO.G"; - return "AO.B"; - } - if (passtype == SCE_PASS_ENVIRONMENT) { - if (channel == -1) return "Env"; - if (channel == 0) return "Env.R"; - if (channel == 1) return "Env.G"; - return "Env.B"; - } - if (passtype == SCE_PASS_INDIRECT) { - if (channel == -1) return "Indirect"; - if (channel == 0) return "Indirect.R"; - if (channel == 1) return "Indirect.G"; - return "Indirect.B"; - } - if (passtype == SCE_PASS_REFLECT) { - if (channel == -1) return "Reflect"; - if (channel == 0) return "Reflect.R"; - if (channel == 1) return "Reflect.G"; - return "Reflect.B"; - } - if (passtype == SCE_PASS_REFRACT) { - if (channel == -1) return "Refract"; - if (channel == 0) return "Refract.R"; - if (channel == 1) return "Refract.G"; - return "Refract.B"; - } - if (passtype == SCE_PASS_INDEXOB) { - if (channel == -1) return "IndexOB"; - return "IndexOB.X"; - } - if (passtype == SCE_PASS_INDEXMA) { - if (channel == -1) return "IndexMA"; - return "IndexMA.X"; - } - if (passtype == SCE_PASS_MIST) { - if (channel == -1) return "Mist"; - return "Mist.Z"; - } - if (passtype == SCE_PASS_RAYHITS) { - if (channel == -1) return "Rayhits"; - if (channel == 0) return "Rayhits.R"; - if (channel == 1) return "Rayhits.G"; - return "Rayhits.B"; - } - if (passtype == SCE_PASS_DIFFUSE_DIRECT) { - if (channel == -1) return "DiffDir"; - if (channel == 0) return "DiffDir.R"; - if (channel == 1) return "DiffDir.G"; - return "DiffDir.B"; - } - if (passtype == SCE_PASS_DIFFUSE_INDIRECT) { - if (channel == -1) return "DiffInd"; - if (channel == 0) return "DiffInd.R"; - if (channel == 1) return "DiffInd.G"; - return "DiffInd.B"; - } - if (passtype == SCE_PASS_DIFFUSE_COLOR) { - if (channel == -1) return "DiffCol"; - if (channel == 0) return "DiffCol.R"; - if (channel == 1) return "DiffCol.G"; - return "DiffCol.B"; - } - if (passtype == SCE_PASS_GLOSSY_DIRECT) { - if (channel == -1) return "GlossDir"; - if (channel == 0) return "GlossDir.R"; - if (channel == 1) return "GlossDir.G"; - return "GlossDir.B"; - } - if (passtype == SCE_PASS_GLOSSY_INDIRECT) { - if (channel == -1) return "GlossInd"; - if (channel == 0) return "GlossInd.R"; - if (channel == 1) return "GlossInd.G"; - return "GlossInd.B"; - } - if (passtype == SCE_PASS_GLOSSY_COLOR) { - if (channel == -1) return "GlossCol"; - if (channel == 0) return "GlossCol.R"; - if (channel == 1) return "GlossCol.G"; - return "GlossCol.B"; - } - if (passtype == SCE_PASS_TRANSM_DIRECT) { - if (channel == -1) return "TransDir"; - if (channel == 0) return "TransDir.R"; - if (channel == 1) return "TransDir.G"; - return "TransDir.B"; - } - if (passtype == SCE_PASS_TRANSM_INDIRECT) { - if (channel == -1) return "TransInd"; - if (channel == 0) return "TransInd.R"; - if (channel == 1) return "TransInd.G"; - return "TransInd.B"; - } - if (passtype == SCE_PASS_TRANSM_COLOR) { - if (channel == -1) return "TransCol"; - if (channel == 0) return "TransCol.R"; - if (channel == 1) return "TransCol.G"; - return "TransCol.B"; - } - if (passtype == SCE_PASS_SUBSURFACE_DIRECT) { - if (channel == -1) return "SubsurfaceDir"; - if (channel == 0) return "SubsurfaceDir.R"; - if (channel == 1) return "SubsurfaceDir.G"; - return "SubsurfaceDir.B"; - } - if (passtype == SCE_PASS_SUBSURFACE_INDIRECT) { - if (channel == -1) return "SubsurfaceInd"; - if (channel == 0) return "SubsurfaceInd.R"; - if (channel == 1) return "SubsurfaceInd.G"; - return "SubsurfaceInd.B"; - } - if (passtype == SCE_PASS_SUBSURFACE_COLOR) { - if (channel == -1) return "SubsurfaceCol"; - if (channel == 0) return "SubsurfaceCol.R"; - if (channel == 1) return "SubsurfaceCol.G"; - return "SubsurfaceCol.B"; - } - return "Unknown"; -} -static int passtype_from_name(const char *str, int passflag) +static char* set_pass_name(char *outname, const char *name, int channel, const char *chan_id) { - /* We do not really support several pass of the same types, so in case we are opening an EXR file with several pass - * names detected as same pass type, only return that pass type the first time, and return 'uknown' for the others. - * See T48466. */ -#define RETURN_PASS(_passtype) return (passflag & (_passtype)) ? 0 : (_passtype) - - if (STRPREFIX(str, "Combined")) - RETURN_PASS(SCE_PASS_COMBINED); - - if (STRPREFIX(str, "Depth")) - RETURN_PASS(SCE_PASS_Z); - - if (STRPREFIX(str, "Vector")) - RETURN_PASS(SCE_PASS_VECTOR); - - if (STRPREFIX(str, "Normal")) - RETURN_PASS(SCE_PASS_NORMAL); - - if (STRPREFIX(str, "UV")) - RETURN_PASS(SCE_PASS_UV); - - if (STRPREFIX(str, "Color")) - RETURN_PASS(SCE_PASS_RGBA); - - if (STRPREFIX(str, "Emit")) - RETURN_PASS(SCE_PASS_EMIT); - - if (STRPREFIX(str, "Diffuse")) - RETURN_PASS(SCE_PASS_DIFFUSE); - - if (STRPREFIX(str, "Spec")) - RETURN_PASS(SCE_PASS_SPEC); - - if (STRPREFIX(str, "Shadow")) - RETURN_PASS(SCE_PASS_SHADOW); - - if (STRPREFIX(str, "AO")) - RETURN_PASS(SCE_PASS_AO); - - if (STRPREFIX(str, "Env")) - RETURN_PASS(SCE_PASS_ENVIRONMENT); - - if (STRPREFIX(str, "Indirect")) - RETURN_PASS(SCE_PASS_INDIRECT); - - if (STRPREFIX(str, "Reflect")) - RETURN_PASS(SCE_PASS_REFLECT); - - if (STRPREFIX(str, "Refract")) - RETURN_PASS(SCE_PASS_REFRACT); - - if (STRPREFIX(str, "IndexOB")) - RETURN_PASS(SCE_PASS_INDEXOB); - - if (STRPREFIX(str, "IndexMA")) - RETURN_PASS(SCE_PASS_INDEXMA); - - if (STRPREFIX(str, "Mist")) - RETURN_PASS(SCE_PASS_MIST); - - if (STRPREFIX(str, "RayHits")) - RETURN_PASS(SCE_PASS_RAYHITS); - - if (STRPREFIX(str, "DiffDir")) - RETURN_PASS(SCE_PASS_DIFFUSE_DIRECT); - - if (STRPREFIX(str, "DiffInd")) - RETURN_PASS(SCE_PASS_DIFFUSE_INDIRECT); - - if (STRPREFIX(str, "DiffCol")) - RETURN_PASS(SCE_PASS_DIFFUSE_COLOR); - - if (STRPREFIX(str, "GlossDir")) - RETURN_PASS(SCE_PASS_GLOSSY_DIRECT); - - if (STRPREFIX(str, "GlossInd")) - RETURN_PASS(SCE_PASS_GLOSSY_INDIRECT); - - if (STRPREFIX(str, "GlossCol")) - RETURN_PASS(SCE_PASS_GLOSSY_COLOR); - - if (STRPREFIX(str, "TransDir")) - RETURN_PASS(SCE_PASS_TRANSM_DIRECT); - - if (STRPREFIX(str, "TransInd")) - RETURN_PASS(SCE_PASS_TRANSM_INDIRECT); - - if (STRPREFIX(str, "TransCol")) - RETURN_PASS(SCE_PASS_TRANSM_COLOR); - - if (STRPREFIX(str, "SubsurfaceDir")) - RETURN_PASS(SCE_PASS_SUBSURFACE_DIRECT); - - if (STRPREFIX(str, "SubsurfaceInd")) - RETURN_PASS(SCE_PASS_SUBSURFACE_INDIRECT); - - if (STRPREFIX(str, "SubsurfaceCol")) - RETURN_PASS(SCE_PASS_SUBSURFACE_COLOR); - - return 0; - -#undef RETURN_PASS + BLI_strncpy(outname, name, EXR_PASS_MAXNAME); + if (channel >= 0) { + char token[3] = {'.', chan_id[channel], '\0'}; + strncat(outname, token, EXR_PASS_MAXNAME); + } + return outname; } - -static void set_pass_name(char *passname, int passtype, int channel, const char *view) +static void set_pass_full_name(char *fullname, const char *name, int channel, const char *view, const char *chan_id) { - const char delims[] = {'.', '\0'}; - const char *sep; - const char *token; - size_t len; - - const char *passtype_name = name_from_passtype(passtype, channel); - - if (view == NULL || view[0] == '\0') { - BLI_strncpy(passname, passtype_name, EXR_PASS_MAXNAME); - return; - } - - len = BLI_str_rpartition(passtype_name, delims, &sep, &token); - - if (sep) { - BLI_snprintf(passname, EXR_PASS_MAXNAME, "%.*s.%s.%s", (int)len, passtype_name, view, token); + BLI_strncpy(fullname, name, EXR_PASS_MAXNAME); + if (view && view[0]) { + strncat(fullname, ".", EXR_PASS_MAXNAME); + strncat(fullname, view, EXR_PASS_MAXNAME); } - else { - BLI_snprintf(passname, EXR_PASS_MAXNAME, "%s.%s", passtype_name, view); + if (channel >= 0) { + char token[3] = {'.', chan_id[channel], '\0'}; + strncat(fullname, token, EXR_PASS_MAXNAME); } } /********************************** New **************************************/ -static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype, const char *viewname) +static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, const char *name, const char *viewname, const char *chan_id) { const int view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name)); - const char *typestr = name_from_passtype(passtype, -1); - RenderPass *rpass = MEM_callocN(sizeof(RenderPass), typestr); + RenderPass *rpass = MEM_callocN(sizeof(RenderPass), name); size_t rectsize = ((size_t)rr->rectx) * rr->recty * channels; - rpass->passtype = passtype; rpass->channels = channels; rpass->rectx = rl->rectx; rpass->recty = rl->recty; rpass->view_id = view_id; - set_pass_name(rpass->name, rpass->passtype, -1, viewname); - BLI_strncpy(rpass->internal_name, typestr, sizeof(rpass->internal_name)); + BLI_strncpy(rpass->name, name, sizeof(rpass->name)); + BLI_strncpy(rpass->chan_id, chan_id, sizeof(rpass->chan_id)); BLI_strncpy(rpass->view, viewname, sizeof(rpass->view)); + set_pass_full_name(rpass->fullname, rpass->name, -1, rpass->view, rpass->chan_id); if (rl->exrhandle) { int a; - for (a = 0; a < channels; a++) - IMB_exr_add_channel(rl->exrhandle, rl->name, name_from_passtype(passtype, a), viewname, 0, 0, NULL, false); + for (a = 0; a < channels; a++) { + char passname[EXR_PASS_MAXNAME]; + IMB_exr_add_channel(rl->exrhandle, rl->name, set_pass_name(passname, rpass->name, a, rpass->chan_id), viewname, 0, 0, NULL, false); + } } else { float *rect; int x; - rpass->rect = MEM_mapallocN(sizeof(float) * rectsize, typestr); + rpass->rect = MEM_mapallocN(sizeof(float) * rectsize, name); if (rpass->rect == NULL) { MEM_freeN(rpass); return NULL; } - if (passtype == SCE_PASS_VECTOR) { + if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) { /* initialize to max speed */ rect = rpass->rect; for (x = rectsize - 1; x >= 0; x--) rect[x] = PASS_VECTOR_MAX; } - else if (passtype == SCE_PASS_Z) { + else if (STREQ(rpass->name, RE_PASSNAME_Z)) { rect = rpass->rect; for (x = rectsize - 1; x >= 0; x--) rect[x] = 10e10; @@ -541,58 +250,10 @@ static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int return rpass; } /* wrapper called from render_opengl */ -RenderPass *gp_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype, const char *viewname) -{ - return render_layer_add_pass(rr, rl, channels, passtype, viewname); -} - -#ifdef WITH_CYCLES_DEBUG -const char *RE_debug_pass_name_get(int debug_type) -{ - switch (debug_type) { - case RENDER_PASS_DEBUG_BVH_TRAVERSED_NODES: - return "BVH Traversed Nodes"; - case RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES: - return "BVH Traversed Instances"; - case RENDER_PASS_DEBUG_BVH_INTERSECTIONS: - return "BVH Primitive Intersections"; - case RENDER_PASS_DEBUG_RAY_BOUNCES: - return "Ray Bounces"; - } - return "Unknown"; -} - -int RE_debug_pass_num_channels_get(int UNUSED(debug_type)) -{ - /* Only single case currently, might be handy for further debug passes. */ - return 1; -} - -static RenderPass *render_layer_add_debug_pass(RenderResult *rr, - RenderLayer *rl, - int pass_type, - int debug_type, - const char *view) -{ - const char *name = RE_debug_pass_name_get(debug_type); - int channels = RE_debug_pass_num_channels_get(debug_type); - RenderPass *rpass = render_layer_add_pass(rr, rl, channels, pass_type, view); - if (rpass == NULL) { - return NULL; - } - rpass->debug_type = debug_type; - BLI_strncpy(rpass->name, - name, - sizeof(rpass->name)); - BLI_strncpy(rpass->internal_name, rpass->name, sizeof(rpass->internal_name)); - return rpass; -} - -int RE_debug_pass_type_get(Render *re) +RenderPass *gp_add_pass(RenderResult *rr, RenderLayer *rl, int channels, const char *name, const char *viewname) { - return re->r.debug_pass_type; + return render_layer_add_pass(rr, rl, channels, name, viewname, "RGBA"); } -#endif /* called by main render as well for parts */ /* will read info from Render *re to define layers */ @@ -683,89 +344,77 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf if (rr->do_exr_tile) IMB_exr_add_view(rl->exrhandle, view); -#define RENDER_LAYER_ADD_PASS_SAFE(rr, rl, channels, passtype, viewname) \ +#define RENDER_LAYER_ADD_PASS_SAFE(rr, rl, channels, name, viewname, chan_id) \ do { \ - if (render_layer_add_pass(rr, rl, channels, passtype, viewname) == NULL) { \ + if (render_layer_add_pass(rr, rl, channels, name, viewname, chan_id) == NULL) { \ render_result_free(rr); \ return NULL; \ } \ } while (false) /* a renderlayer should always have a Combined pass*/ - render_layer_add_pass(rr, rl, 4, SCE_PASS_COMBINED, view); + render_layer_add_pass(rr, rl, 4, "Combined", view, "RGBA"); if (srl->passflag & SCE_PASS_Z) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, SCE_PASS_Z, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_Z, view, "Z"); if (srl->passflag & SCE_PASS_VECTOR) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, SCE_PASS_VECTOR, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_VECTOR, view, "XYZW"); if (srl->passflag & SCE_PASS_NORMAL) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_NORMAL, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_NORMAL, view, "XYZ"); if (srl->passflag & SCE_PASS_UV) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_UV, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_UV, view, "UVA"); if (srl->passflag & SCE_PASS_RGBA) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, SCE_PASS_RGBA, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_RGBA, view, "RGBA"); if (srl->passflag & SCE_PASS_EMIT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_EMIT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_EMIT, view, "RGB"); if (srl->passflag & SCE_PASS_DIFFUSE) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_DIFFUSE, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE, view, "RGB"); if (srl->passflag & SCE_PASS_SPEC) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SPEC, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SPEC, view, "RGB"); if (srl->passflag & SCE_PASS_AO) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_AO, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_AO, view, "RGB"); if (srl->passflag & SCE_PASS_ENVIRONMENT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_ENVIRONMENT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_ENVIRONMENT, view, "RGB"); if (srl->passflag & SCE_PASS_INDIRECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_INDIRECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_INDIRECT, view, "RGB"); if (srl->passflag & SCE_PASS_SHADOW) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SHADOW, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SHADOW, view, "RGB"); if (srl->passflag & SCE_PASS_REFLECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_REFLECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_REFLECT, view, "RGB"); if (srl->passflag & SCE_PASS_REFRACT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_REFRACT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_REFRACT, view, "RGB"); if (srl->passflag & SCE_PASS_INDEXOB) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, SCE_PASS_INDEXOB, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXOB, view, "X"); if (srl->passflag & SCE_PASS_INDEXMA) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, SCE_PASS_INDEXMA, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXMA, view, "X"); if (srl->passflag & SCE_PASS_MIST) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, SCE_PASS_MIST, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_MIST, view, "Z"); if (rl->passflag & SCE_PASS_RAYHITS) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, SCE_PASS_RAYHITS, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_RAYHITS, view, "RGB"); if (srl->passflag & SCE_PASS_DIFFUSE_DIRECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_DIFFUSE_DIRECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_DIRECT, view, "RGB"); if (srl->passflag & SCE_PASS_DIFFUSE_INDIRECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_DIFFUSE_INDIRECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_INDIRECT, view, "RGB"); if (srl->passflag & SCE_PASS_DIFFUSE_COLOR) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_DIFFUSE_COLOR, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_COLOR, view, "RGB"); if (srl->passflag & SCE_PASS_GLOSSY_DIRECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_GLOSSY_DIRECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_DIRECT, view, "RGB"); if (srl->passflag & SCE_PASS_GLOSSY_INDIRECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_GLOSSY_INDIRECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_INDIRECT, view, "RGB"); if (srl->passflag & SCE_PASS_GLOSSY_COLOR) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_GLOSSY_COLOR, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_COLOR, view, "RGB"); if (srl->passflag & SCE_PASS_TRANSM_DIRECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_TRANSM_DIRECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_DIRECT, view, "RGB"); if (srl->passflag & SCE_PASS_TRANSM_INDIRECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_TRANSM_INDIRECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_INDIRECT, view, "RGB"); if (srl->passflag & SCE_PASS_TRANSM_COLOR) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_TRANSM_COLOR, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_COLOR, view, "RGB"); if (srl->passflag & SCE_PASS_SUBSURFACE_DIRECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SUBSURFACE_DIRECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_DIRECT, view, "RGB"); if (srl->passflag & SCE_PASS_SUBSURFACE_INDIRECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SUBSURFACE_INDIRECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_INDIRECT, view, "RGB"); if (srl->passflag & SCE_PASS_SUBSURFACE_COLOR) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SUBSURFACE_COLOR, view); - -#ifdef WITH_CYCLES_DEBUG - if (BKE_scene_use_new_shading_nodes(re->scene)) { - if (render_layer_add_debug_pass(rr, rl, SCE_PASS_DEBUG, - re->r.debug_pass_type, view) == NULL) - { - render_result_free(rr); - return NULL; - } - } -#endif - + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_COLOR, view, "RGB"); #undef RENDER_LAYER_ADD_PASS_SAFE } } @@ -794,7 +443,7 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf IMB_exr_add_view(rl->exrhandle, view); /* a renderlayer should always have a Combined pass */ - render_layer_add_pass(rr, rl, 4, SCE_PASS_COMBINED, view); + render_layer_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, view, "RGBA"); } /* note, this has to be in sync with scene.c */ @@ -813,6 +462,60 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf return rr; } +void render_result_clone_passes(Render *re, RenderResult *rr, const char *viewname) +{ + RenderLayer *rl; + RenderPass *main_rp; + + for (rl = rr->layers.first; rl; rl = rl->next) { + RenderLayer *main_rl = BLI_findstring(&re->result->layers, rl->name, offsetof(RenderLayer, name)); + if (!main_rl) { + continue; + } + + for (main_rp = main_rl->passes.first; main_rp; main_rp = main_rp->next) { + if (viewname && viewname[0] && !STREQ(main_rp->view, viewname)) { + continue; + } + + /* Compare fullname to make sure that the view also is equal. */ + RenderPass *rp = BLI_findstring(&rl->passes, main_rp->fullname, offsetof(RenderPass, fullname)); + if (!rp) { + render_layer_add_pass(rr, rl, main_rp->channels, main_rp->name, main_rp->view, main_rp->chan_id); + } + } + } +} + +void render_result_add_pass(RenderResult *rr, const char *name, int channels, const char *chan_id, const char *layername, const char *viewname) +{ + RenderLayer *rl; + RenderPass *rp; + RenderView *rv; + + for (rl = rr->layers.first; rl; rl = rl->next) { + if (layername && layername[0] && !STREQ(rl->name, layername)) { + continue; + } + + for (rv = rr->views.first; rv; rv = rv->next) { + const char *view = rv->name; + + if (viewname && viewname[0] && !STREQ(view, viewname)) continue; + + /* Ensure that the pass doesn't exist yet. */ + for (rp = rl->passes.first; rp; rp = rp->next) { + if (!STREQ(rp->name, name)) continue; + if (!STREQ(rp->view, view)) continue; + } + + if (!rp) { + render_layer_add_pass(rr, rl, channels, name, view, chan_id); + } + } + } +} + /* allocate osa new results for samples */ RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *partrct, int crop, int savebuffers, const char *viewname) { @@ -830,6 +533,50 @@ RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *part return lb->first; } +static int passtype_from_name(const char *name) +{ + const char delim[] = {'.', '\0'}; + const char *sep, *suf; + int len = BLI_str_partition(name, delim, &sep, &suf); + +#define CHECK_PASS(NAME) if (STREQLEN(name, RE_PASSNAME_ ## NAME, len)) return SCE_PASS_ ## NAME + + CHECK_PASS(COMBINED); + CHECK_PASS(Z); + CHECK_PASS(VECTOR); + CHECK_PASS(NORMAL); + CHECK_PASS(UV); + CHECK_PASS(RGBA); + CHECK_PASS(EMIT); + CHECK_PASS(DIFFUSE); + CHECK_PASS(SPEC); + CHECK_PASS(SHADOW); + CHECK_PASS(AO); + CHECK_PASS(ENVIRONMENT); + CHECK_PASS(INDIRECT); + CHECK_PASS(REFLECT); + CHECK_PASS(REFRACT); + CHECK_PASS(INDEXOB); + CHECK_PASS(INDEXMA); + CHECK_PASS(MIST); + CHECK_PASS(RAYHITS); + CHECK_PASS(DIFFUSE_DIRECT); + CHECK_PASS(DIFFUSE_INDIRECT); + CHECK_PASS(DIFFUSE_COLOR); + CHECK_PASS(GLOSSY_DIRECT); + CHECK_PASS(GLOSSY_INDIRECT); + CHECK_PASS(GLOSSY_COLOR); + CHECK_PASS(TRANSM_DIRECT); + CHECK_PASS(TRANSM_INDIRECT); + CHECK_PASS(TRANSM_COLOR); + CHECK_PASS(SUBSURFACE_DIRECT); + CHECK_PASS(SUBSURFACE_INDIRECT); + CHECK_PASS(SUBSURFACE_COLOR); + +#undef CHECK_PASS + return 0; +} + /* callbacks for render_result_new_from_exr */ static void *ml_addlayer_cb(void *base, const char *str) { @@ -843,36 +590,30 @@ static void *ml_addlayer_cb(void *base, const char *str) return rl; } -static void ml_addpass_cb(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id, const char *view) +static void ml_addpass_cb(void *base, void *lay, const char *name, float *rect, int totchan, const char *chan_id, const char *view) { RenderResult *rr = base; RenderLayer *rl = lay; RenderPass *rpass = MEM_callocN(sizeof(RenderPass), "loaded pass"); - int a; - + BLI_addtail(&rl->passes, rpass); rpass->channels = totchan; - rpass->passtype = passtype_from_name(str, rl->passflag); - if (rpass->passtype == 0) - printf("unknown pass %s\n", str); - rl->passflag |= rpass->passtype; - + rl->passflag |= passtype_from_name(name); + /* channel id chars */ - for (a = 0; a < totchan; a++) - rpass->chan_id[a] = chan_id[a]; + BLI_strncpy(rpass->chan_id, chan_id, sizeof(rpass->chan_id)); rpass->rect = rect; + BLI_strncpy(rpass->name, name, EXR_PASS_MAXNAME); + BLI_strncpy(rpass->view, view, sizeof(rpass->view)); + set_pass_full_name(rpass->fullname, name, -1, view, rpass->chan_id); + if (view[0] != '\0') { - BLI_snprintf(rpass->name, sizeof(rpass->name), "%s.%s", str, view); rpass->view_id = BLI_findstringindex(&rr->views, view, offsetof(RenderView, name)); } else { - BLI_strncpy(rpass->name, str, sizeof(rpass->name)); rpass->view_id = 0; } - - BLI_strncpy(rpass->view, view, sizeof(rpass->view)); - BLI_strncpy(rpass->internal_name, str, sizeof(rpass->internal_name)); } static void *ml_addview_cb(void *base, const char *str) @@ -912,12 +653,30 @@ static int order_render_passes(const void *a, const void *b) // 1 if a is after b RenderPass *rpa = (RenderPass *) a; RenderPass *rpb = (RenderPass *) b; + unsigned int passtype_a = passtype_from_name(rpa->name); + unsigned int passtype_b = passtype_from_name(rpb->name); - if (rpa->passtype > rpb->passtype) + /* Render passes with default type always go first. */ + if (passtype_b && !passtype_a) return 1; - else if (rpa->passtype < rpb->passtype) + if (passtype_a && !passtype_b) return 0; + if (passtype_a && passtype_b) { + if (passtype_a > passtype_b) + return 1; + else if (passtype_a < passtype_b) + return 0; + } + else { + int cmp = strncmp(rpa->name, rpb->name, EXR_PASS_MAXNAME); + if (cmp > 0) + return 1; + if (cmp < 0) + return 0; + } + + /* they have the same type */ /* left first */ if (STREQ(rpa->view, STEREO_LEFT_NAME)) @@ -1049,7 +808,7 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart) rpass = rpass->next) { /* renderresult have all passes, renderpart only the active view's passes */ - if (strcmp(rpassp->name, rpass->name) != 0) + if (strcmp(rpassp->fullname, rpass->fullname) != 0) continue; do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels); @@ -1061,21 +820,6 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart) } } -/* for passes read from files, these have names stored */ -static char *make_pass_name(RenderPass *rpass, int chan) -{ - static char name[EXR_PASS_MAXNAME]; - int len; - - BLI_strncpy(name, rpass->name, EXR_PASS_MAXNAME); - len = strlen(name); - name[len] = '.'; - name[len + 1] = rpass->chan_id[chan]; - name[len + 2] = 0; - - return name; -} - /* called from within UI and render pipeline, saves both rendered result as a file-read result * if multiview is true saves all views in a multiview exr * else if view is not NULL saves single view @@ -1136,8 +880,10 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil IMB_exr_add_view(exrhandle, rview->name); if (rview->rectf) { + char passname[EXR_PASS_MAXNAME]; for (a = 0; a < 4; a++) { - IMB_exr_add_channel(exrhandle, "Composite", name_from_passtype(SCE_PASS_COMBINED, a), + set_pass_name(passname, RE_PASSNAME_COMBINED, a, "RGBA"); + IMB_exr_add_channel(exrhandle, RE_PASSNAME_COMBINED, passname, chan_view, 4, 4 * width, rview->rectf + a, use_half_float); } @@ -1150,6 +896,7 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil /* passes are allocated in sync */ for (rpass = rl->passes.first; rpass; rpass = rpass->next) { const int xstride = rpass->channels; + char passname[EXR_PASS_MAXNAME]; if (is_mono) { if (!STREQ(view, rpass->view)) { @@ -1163,16 +910,10 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil } for (a = 0; a < xstride; a++) { - if (rpass->passtype) { - IMB_exr_add_channel(exrhandle, rl->name, name_from_passtype(rpass->passtype, a), chan_view, - xstride, xstride * width, rpass->rect + a, - rpass->passtype == SCE_PASS_Z ? false : use_half_float); - } - else { - IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), chan_view, - xstride, xstride * width, rpass->rect + a, - use_half_float); - } + set_pass_name(passname, rpass->name, a, rpass->chan_id); + IMB_exr_add_channel(exrhandle, rl->name, passname, chan_view, + xstride, xstride * width, rpass->rect + a, + STREQ(rpass->name, RE_PASSNAME_Z) ? false : use_half_float); } } } @@ -1281,12 +1022,12 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, cons for (rpassp = rlp->passes.first; rpassp; rpassp = rpassp->next) { const int xstride = rpassp->channels; int a; - char passname[EXR_PASS_MAXNAME]; + char fullname[EXR_PASS_MAXNAME]; for (a = 0; a < xstride; a++) { - set_pass_name(passname, rpassp->passtype, a, rpassp->view); + set_pass_full_name(fullname, rpassp->name, a, viewname, rpassp->chan_id); - IMB_exr_set_channel(rl->exrhandle, rlp->name, passname, + IMB_exr_set_channel(rl->exrhandle, rlp->name, fullname, xstride, xstride * rrpart->rectx, rpassp->rect + a + xstride * offs); } } @@ -1449,15 +1190,15 @@ int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, c for (rpass = rl->passes.first; rpass; rpass = rpass->next) { const int xstride = rpass->channels; int a; - char passname[EXR_PASS_MAXNAME]; + char fullname[EXR_PASS_MAXNAME]; for (a = 0; a < xstride; a++) { - set_pass_name(passname, rpass->passtype, a, rpass->view); - IMB_exr_set_channel(exrhandle, rl->name, passname, + set_pass_full_name(fullname, rpass->name, a, rpass->view, rpass->chan_id); + IMB_exr_set_channel(exrhandle, rl->name, fullname, xstride, xstride * rectx, rpass->rect + a); } - set_pass_name(rpass->name, rpass->passtype, -1, rpass->view); + set_pass_full_name(rpass->fullname, rpass->name, -1, rpass->view, rpass->chan_id); } } diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 910ea16607e..0b1004c562e 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -182,7 +182,7 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in if (fullsample) { for (sample=0; sample<totsample; sample++) if (ps->mask & (1 << sample)) { - float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); addalphaAddfacFloat(pass + od*4, col, har->add); } } @@ -217,7 +217,7 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in if (fullsample) { for (sample=0; sample<totsample; sample++) if (!(mask & (1 << sample))) { - float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); addalphaAddfacFloat(pass + od*4, col, har->add); } } @@ -228,7 +228,7 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in col[3]= accol[3]; for (sample=0; sample<totsample; sample++) { - float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); addalphaAddfacFloat(pass + od*4, col, har->add); } } @@ -312,7 +312,7 @@ static void halo_tile(RenderPart *pa, RenderLayer *rl) if ((zz> har->zs) || (har->mat && (har->mat->mode & MA_HALO_SOFT))) { if (shadeHaloFloat(har, col, zz, dist, xn, yn, har->flarec)) { for (sample=0; sample<totsample; sample++) { - float * rect= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + float * rect= RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); addalphaAddfacFloat(rect + od*4, col, har->add); } } @@ -367,7 +367,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) if (fullsample) { for (sample=0; sample<totsample; sample++) { if (ps->mask & (1 << sample)) { - pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); pass += od * 4; pass[0]+= col[0]; pass[1]+= col[1]; @@ -379,7 +379,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) } else { fac= ((float)count)/(float)R.osa; - pass = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); + pass = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname); pass += od * 4; pass[0]+= fac*col[0]; pass[1]+= fac*col[1]; @@ -401,7 +401,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) for (sample=0; sample<totsample; sample++) { if (!(mask & (1 << sample))) { - pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); pass += od * 4; pass[0]+= col[0]; pass[1]+= col[1]; @@ -413,7 +413,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) } else { fac= ((float)R.osa-totsamp)/(float)R.osa; - pass = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); + pass = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname); pass += od * 4; pass[0]+= fac*col[0]; pass[1]+= fac*col[1]; @@ -433,7 +433,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) renderspothalo(&shi, col, 1.0f); for (sample=0; sample<totsample; sample++) { - pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); pass += od * 4; pass[0]+= col[0]; pass[1]+= col[1]; @@ -462,101 +462,96 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, float *fp, *col= NULL; int pixsize= 3; - switch (rpass->passtype) { - case SCE_PASS_COMBINED: - add_filt_fmask(curmask, shr->combined, rpass->rect + 4*offset, rectx); - break; - case SCE_PASS_Z: - fp= rpass->rect + offset; - *fp= shr->z; - break; - case SCE_PASS_RGBA: - col= shr->col; - pixsize= 4; - break; - case SCE_PASS_EMIT: - col= shr->emit; - break; - case SCE_PASS_DIFFUSE: - col= shr->diff; - break; - case SCE_PASS_SPEC: - col= shr->spec; - break; - case SCE_PASS_SHADOW: - col= shr->shad; - break; - case SCE_PASS_AO: - col= shr->ao; - break; - case SCE_PASS_ENVIRONMENT: - col= shr->env; - break; - case SCE_PASS_INDIRECT: - col= shr->indirect; - break; - case SCE_PASS_REFLECT: - col= shr->refl; - break; - case SCE_PASS_REFRACT: - col= shr->refr; - break; - case SCE_PASS_NORMAL: - col= shr->nor; - break; - case SCE_PASS_UV: - /* box filter only, gauss will screwup UV too much */ - if (shi->totuv) { - float mult= (float)count_mask(curmask)/(float)R.osa; - fp= rpass->rect + 3*offset; - fp[0]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[0]); - fp[1]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[1]); - fp[2]+= mult; - } - break; - case SCE_PASS_INDEXOB: - /* no filter */ - if (shi->vlr) { - fp= rpass->rect + offset; + if(STREQ(rpass->name, RE_PASSNAME_COMBINED)) { + add_filt_fmask(curmask, shr->combined, rpass->rect + 4*offset, rectx); + } + else if(STREQ(rpass->name, RE_PASSNAME_Z)) { + fp = rpass->rect + offset; + *fp = shr->z; + } + else if(STREQ(rpass->name, RE_PASSNAME_RGBA)) { + col = shr->col; + pixsize = 4; + } + else if(STREQ(rpass->name, RE_PASSNAME_EMIT)) { + col = shr->emit; + } + else if(STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) { + col = shr->diff; + } + else if(STREQ(rpass->name, RE_PASSNAME_SPEC)) { + col = shr->spec; + } + else if(STREQ(rpass->name, RE_PASSNAME_SHADOW)) { + col = shr->shad; + } + else if(STREQ(rpass->name, RE_PASSNAME_AO)) { + col = shr->ao; + } + else if(STREQ(rpass->name, RE_PASSNAME_ENVIRONMENT)) { + col = shr->env; + } + else if(STREQ(rpass->name, RE_PASSNAME_INDIRECT)) { + col = shr->indirect; + } + else if(STREQ(rpass->name, RE_PASSNAME_REFLECT)) { + col = shr->refl; + } + else if(STREQ(rpass->name, RE_PASSNAME_REFRACT)) { + col = shr->refr; + } + else if(STREQ(rpass->name, RE_PASSNAME_NORMAL)) { + col = shr->nor; + } + else if(STREQ(rpass->name, RE_PASSNAME_UV)) { + /* box filter only, gauss will screwup UV too much */ + if (shi->totuv) { + float mult = (float)count_mask(curmask)/(float)R.osa; + fp = rpass->rect + 3*offset; + fp[0]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[0]); + fp[1]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[1]); + fp[2]+= mult; + } + } + else if(STREQ(rpass->name, RE_PASSNAME_INDEXOB)) { + /* no filter */ + if (shi->vlr) { + fp = rpass->rect + offset; + if (*fp==0.0f) + *fp = (float)shi->obr->ob->index; + } + } + else if(STREQ(rpass->name, RE_PASSNAME_INDEXMA)) { + /* no filter */ + if (shi->vlr) { + fp = rpass->rect + offset; if (*fp==0.0f) - *fp= (float)shi->obr->ob->index; - } - break; - case SCE_PASS_INDEXMA: - /* no filter */ - if (shi->vlr) { - fp= rpass->rect + offset; - if (*fp==0.0f) - *fp= (float)shi->mat->index; - } - break; - case SCE_PASS_MIST: - /* */ - col= &shr->mist; - pixsize= 1; - break; - - case SCE_PASS_VECTOR: - { - /* add minimum speed in pixel, no filter */ - fp= rpass->rect + 4*offset; - if ( (ABS(shr->winspeed[0]) + ABS(shr->winspeed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) { - fp[0]= shr->winspeed[0]; - fp[1]= shr->winspeed[1]; - } - if ( (ABS(shr->winspeed[2]) + ABS(shr->winspeed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) { - fp[2]= shr->winspeed[2]; - fp[3]= shr->winspeed[3]; - } - - break; + *fp = (float)shi->mat->index; } - case SCE_PASS_RAYHITS: - /* */ - col= shr->rayhits; - pixsize= 4; - break; } + else if(STREQ(rpass->name, RE_PASSNAME_MIST)) { + /* */ + col = &shr->mist; + pixsize = 1; + } + else if(STREQ(rpass->name, RE_PASSNAME_VECTOR)) { + /* add minimum speed in pixel, no filter */ + fp = rpass->rect + 4*offset; + if ( (ABS(shr->winspeed[0]) + ABS(shr->winspeed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) { + fp[0] = shr->winspeed[0]; + fp[1] = shr->winspeed[1]; + } + if ( (ABS(shr->winspeed[2]) + ABS(shr->winspeed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) { + fp[2] = shr->winspeed[2]; + fp[3] = shr->winspeed[3]; + } + } + else if(STREQ(rpass->name, RE_PASSNAME_RAYHITS)) { + /* */ + col = shr->rayhits; + pixsize= 4; + } + if (col) { fp= rpass->rect + pixsize*offset; add_filt_fmask_pixsize(curmask, col, fp, rectx, pixsize); @@ -574,86 +569,85 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult float *col= NULL, uvcol[3]; int a, pixsize= 3; - switch (rpass->passtype) { - case SCE_PASS_COMBINED: - /* copy combined to use for preview */ - copy_v4_v4(rpass->rect + 4*offset, shr->combined); - break; - case SCE_PASS_Z: - fp= rpass->rect + offset; - *fp= shr->z; - break; - case SCE_PASS_RGBA: - col= shr->col; - pixsize= 4; - break; - case SCE_PASS_EMIT: - col= shr->emit; - break; - case SCE_PASS_DIFFUSE: - col= shr->diff; - break; - case SCE_PASS_SPEC: - col= shr->spec; - break; - case SCE_PASS_SHADOW: - col= shr->shad; - break; - case SCE_PASS_AO: - col= shr->ao; - break; - case SCE_PASS_ENVIRONMENT: - col= shr->env; - break; - case SCE_PASS_INDIRECT: - col= shr->indirect; - break; - case SCE_PASS_REFLECT: - col= shr->refl; - break; - case SCE_PASS_REFRACT: - col= shr->refr; - break; - case SCE_PASS_NORMAL: - col= shr->nor; - break; - case SCE_PASS_UV: - if (shi->totuv) { - uvcol[0]= 0.5f + 0.5f*shi->uv[shi->actuv].uv[0]; - uvcol[1]= 0.5f + 0.5f*shi->uv[shi->actuv].uv[1]; - uvcol[2]= 1.0f; - col= uvcol; - } - break; - case SCE_PASS_VECTOR: - col= shr->winspeed; - pixsize= 4; - break; - case SCE_PASS_INDEXOB: - if (shi->vlr) { - fp= rpass->rect + offset; - *fp= (float)shi->obr->ob->index; - } - break; - case SCE_PASS_INDEXMA: - if (shi->vlr) { - fp= rpass->rect + offset; - *fp= (float)shi->mat->index; - } - break; - case SCE_PASS_MIST: - fp= rpass->rect + offset; - *fp= shr->mist; - break; - case SCE_PASS_RAYHITS: - col= shr->rayhits; - pixsize= 4; - break; + if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) { + /* copy combined to use for preview */ + copy_v4_v4(rpass->rect + 4*offset, shr->combined); + } + else if (STREQ(rpass->name, RE_PASSNAME_Z)) { + fp = rpass->rect + offset; + *fp = shr->z; + } + else if (STREQ(rpass->name, RE_PASSNAME_RGBA)) { + col = shr->col; + pixsize = 4; + } + else if (STREQ(rpass->name, RE_PASSNAME_EMIT)) { + col = shr->emit; + } + else if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) { + col = shr->diff; + } + else if (STREQ(rpass->name, RE_PASSNAME_SPEC)) { + col = shr->spec; + } + else if (STREQ(rpass->name, RE_PASSNAME_SHADOW)) { + col = shr->shad; + } + else if (STREQ(rpass->name, RE_PASSNAME_AO)) { + col = shr->ao; + } + else if (STREQ(rpass->name, RE_PASSNAME_ENVIRONMENT)) { + col = shr->env; + } + else if (STREQ(rpass->name, RE_PASSNAME_INDIRECT)) { + col = shr->indirect; + } + else if (STREQ(rpass->name, RE_PASSNAME_REFLECT)) { + col = shr->refl; + } + else if (STREQ(rpass->name, RE_PASSNAME_REFRACT)) { + col = shr->refr; + } + else if (STREQ(rpass->name, RE_PASSNAME_NORMAL)) { + col = shr->nor; + } + else if (STREQ(rpass->name, RE_PASSNAME_UV)) { + if (shi->totuv) { + uvcol[0] = 0.5f + 0.5f*shi->uv[shi->actuv].uv[0]; + uvcol[1] = 0.5f + 0.5f*shi->uv[shi->actuv].uv[1]; + uvcol[2] = 1.0f; + col = uvcol; + } } + else if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) { + col = shr->winspeed; + pixsize = 4; + } + else if (STREQ(rpass->name, RE_PASSNAME_INDEXOB)) { + if (shi->vlr) { + fp = rpass->rect + offset; + *fp = (float)shi->obr->ob->index; + } + } + else if (STREQ(rpass->name, RE_PASSNAME_INDEXMA)) { + if (shi->vlr) { + fp = rpass->rect + offset; + *fp = (float)shi->mat->index; + } + } + else if (STREQ(rpass->name, RE_PASSNAME_MIST)) { + fp = rpass->rect + offset; + *fp = shr->mist; + } + else if (STREQ(rpass->name, RE_PASSNAME_RAYHITS)) { + col = shr->rayhits; + pixsize = 4; + } + if (col) { - fp= rpass->rect + pixsize*offset; + fp = rpass->rect + pixsize*offset; for (a=0; a<pixsize; a++) - fp[a]= col[a]; + fp[a] = col[a]; } } } @@ -696,7 +690,7 @@ static void sky_tile(RenderPart *pa, RenderLayer *rl) bool done = false; for (sample= 0; sample<totsample; sample++) { - float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); pass += od; if (pass[3]<1.0f) { @@ -737,7 +731,7 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl) /* check that z pass is enabled */ if (pa->rectz==NULL) return; for (zpass= rl->passes.first; zpass; zpass= zpass->next) - if (zpass->passtype==SCE_PASS_Z) + if (STREQ(zpass->name, RE_PASSNAME_Z)) break; if (zpass==NULL) return; @@ -758,8 +752,8 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl) int sample; for (sample=0; sample<totsample; sample++) { - const float *zrect = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_Z, R.viewname) + od; - float *rgbrect = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname) + 4*od; + const float *zrect = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_Z, R.viewname) + od; + float *rgbrect = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname) + 4*od; float rgb[3] = {0}; bool done = false; @@ -994,7 +988,7 @@ static void clamp_alpha_rgb_range(RenderPart *pa, RenderLayer *rl) return; for (sample= 0; sample<totsample; sample++) { - float *rectf = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + float *rectf = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); for (y= pa->rectx*pa->recty; y>0; y--, rectf+=4) { rectf[0] = MAX2(rectf[0], 0.0f); @@ -1076,7 +1070,7 @@ static void reset_sky_speed(RenderPart *pa, RenderLayer *rl) totsample= get_sample_layers(pa, rl, rlpp); for (sample= 0; sample<totsample; sample++) { - fp= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_VECTOR, R.viewname); + fp= RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_VECTOR, R.viewname); if (fp==NULL) break; for (a= 4*pa->rectx*pa->recty - 1; a>=0; a--) @@ -1187,7 +1181,7 @@ void zbufshadeDA_tile(RenderPart *pa) pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp"); pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); for (rl= rr->layers.first; rl; rl= rl->next) { - float *rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); + float *rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname); if ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK)) pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask"); @@ -1339,7 +1333,7 @@ void zbufshade_tile(RenderPart *pa) pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); for (rl= rr->layers.first; rl; rl= rl->next) { - float *rect= RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); + float *rect= RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname); if ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK)) pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask"); @@ -1676,7 +1670,7 @@ void zbufshade_sss_tile(RenderPart *pa) return; } - fcol= RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); + fcol= RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname); co= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSCo"); color= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSColor"); @@ -1969,7 +1963,7 @@ void add_halo_flare(Render *re) if ((rl->layflag & SCE_LAY_HALO) == 0) continue; - rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname); + rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, re->viewname); if (rect==NULL) continue; @@ -1998,3 +1992,37 @@ void add_halo_flare(Render *re) } } +void render_internal_update_passes(RenderEngine *engine, Scene *scene, SceneRenderLayer *srl) +{ + int type; + + RE_engine_register_pass(engine, scene, srl, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA); + +#define CHECK_PASS(name, channels, chanid) \ + if (srl->passflag & (SCE_PASS_ ## name)) { \ + if (channels == 4) type = SOCK_RGBA; \ + else if (channels == 3) type = SOCK_VECTOR; \ + else type = SOCK_FLOAT; \ + RE_engine_register_pass(engine, scene, srl, RE_PASSNAME_ ## name, channels, chanid, type); \ + } + + CHECK_PASS(Z, 1, "Z"); + CHECK_PASS(VECTOR, 4, "XYZW"); + CHECK_PASS(NORMAL, 3, "XYZ"); + CHECK_PASS(UV, 3, "UVA"); + CHECK_PASS(RGBA, 4, "RGBA"); + CHECK_PASS(EMIT, 3, "RGB"); + CHECK_PASS(DIFFUSE, 3, "RGB"); + CHECK_PASS(SPEC, 3, "RGB"); + CHECK_PASS(AO, 3, "RGB"); + CHECK_PASS(ENVIRONMENT, 3, "RGB"); + CHECK_PASS(INDIRECT, 3, "RGB"); + CHECK_PASS(SHADOW, 3, "RGB"); + CHECK_PASS(REFLECT, 3, "RGB"); + CHECK_PASS(REFRACT, 3, "RGB"); + CHECK_PASS(INDEXOB, 1, "X"); + CHECK_PASS(INDEXMA, 1, "X"); + CHECK_PASS(MIST, 1, "Z"); + +#undef CHECK_PASS +} diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 9f777631e52..94e03929c4e 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -3494,7 +3494,7 @@ static void add_transp_speed(RenderLayer *rl, int offset, float speed[4], float RenderPass *rpass; for (rpass= rl->passes.first; rpass; rpass= rpass->next) { - if (rpass->passtype==SCE_PASS_VECTOR) { + if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) { float *fp= rpass->rect + 4*offset; if (speed==NULL) { @@ -3528,7 +3528,7 @@ static void add_transp_obindex(RenderLayer *rl, int offset, Object *ob) RenderPass *rpass; for (rpass= rl->passes.first; rpass; rpass= rpass->next) { - if (rpass->passtype == SCE_PASS_INDEXOB) { + if (STREQ(rpass->name, RE_PASSNAME_INDEXOB)) { float *fp= rpass->rect + offset; *fp= (float)ob->index; break; @@ -3541,7 +3541,7 @@ static void add_transp_material_index(RenderLayer *rl, int offset, Material *mat RenderPass *rpass; for (rpass= rl->passes.first; rpass; rpass= rpass->next) { - if (rpass->passtype == SCE_PASS_INDEXMA) { + if (STREQ(rpass->name, RE_PASSNAME_INDEXMA)) { float *fp= rpass->rect + offset; *fp= (float)mat->index; break; @@ -3558,78 +3558,74 @@ static void merge_transp_passes(RenderLayer *rl, ShadeResult *shr) int delta= sizeof(ShadeResult)/4; for (rpass= rl->passes.first; rpass; rpass= rpass->next) { - float *col= NULL; - int pixsize= 3; + float *col = NULL; + int pixsize = 3; - switch (rpass->passtype) { - case SCE_PASS_RGBA: - col= shr->col; - pixsize= 4; - break; - case SCE_PASS_EMIT: - col= shr->emit; - break; - case SCE_PASS_DIFFUSE: - col= shr->diff; - break; - case SCE_PASS_SPEC: - col= shr->spec; - break; - case SCE_PASS_SHADOW: - col= shr->shad; - break; - case SCE_PASS_AO: - col= shr->ao; - break; - case SCE_PASS_ENVIRONMENT: - col= shr->env; - break; - case SCE_PASS_INDIRECT: - col= shr->indirect; - break; - case SCE_PASS_REFLECT: - col= shr->refl; - break; - case SCE_PASS_REFRACT: - col= shr->refr; - break; - case SCE_PASS_NORMAL: - col= shr->nor; - break; - case SCE_PASS_MIST: - col= &shr->mist; - pixsize= 1; - break; - case SCE_PASS_Z: - col= &shr->z; - pixsize= 1; - break; - case SCE_PASS_VECTOR: + if (STREQ(rpass->name, RE_PASSNAME_RGBA)) { + col = shr->col; + pixsize = 4; + } + else if (STREQ(rpass->name, RE_PASSNAME_EMIT)) { + col = shr->emit; + } + else if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) { + col = shr->diff; + } + else if (STREQ(rpass->name, RE_PASSNAME_SPEC)) { + col = shr->spec; + } + else if (STREQ(rpass->name, RE_PASSNAME_SHADOW)) { + col = shr->shad; + } + else if (STREQ(rpass->name, RE_PASSNAME_AO)) { + col = shr->ao; + } + else if (STREQ(rpass->name, RE_PASSNAME_ENVIRONMENT)) { + col = shr->env; + } + else if (STREQ(rpass->name, RE_PASSNAME_INDIRECT)) { + col = shr->indirect; + } + else if (STREQ(rpass->name, RE_PASSNAME_REFLECT)) { + col = shr->refl; + } + else if (STREQ(rpass->name, RE_PASSNAME_REFRACT)) { + col = shr->refr; + } + else if (STREQ(rpass->name, RE_PASSNAME_NORMAL)) { + col = shr->nor; + } + else if (STREQ(rpass->name, RE_PASSNAME_MIST)) { + col = &shr->mist; + pixsize = 1; + } + else if (STREQ(rpass->name, RE_PASSNAME_Z)) { + col = &shr->z; + pixsize = 1; + } + else if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) { + ShadeResult *shr_t = shr+1; + float *fp = shr->winspeed; /* was initialized */ + int samp; + + /* add minimum speed in pixel */ + for (samp = 1; samp<R.osa; samp++, shr_t++) { - { - ShadeResult *shr_t= shr+1; - float *fp= shr->winspeed; /* was initialized */ - int samp; + if (shr_t->combined[3] > 0.0f) { + const float *speed = shr_t->winspeed; - /* add minimum speed in pixel */ - for (samp= 1; samp<R.osa; samp++, shr_t++) { - - if (shr_t->combined[3] > 0.0f) { - const float *speed= shr_t->winspeed; - - if ( (ABS(speed[0]) + ABS(speed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) { - fp[0]= speed[0]; - fp[1]= speed[1]; - } - if ( (ABS(speed[2]) + ABS(speed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) { - fp[2]= speed[2]; - fp[3]= speed[3]; - } - } + if ( (ABS(speed[0]) + ABS(speed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) { + fp[0] = speed[0]; + fp[1] = speed[1]; + } + if ( (ABS(speed[2]) + ABS(speed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) { + fp[2] = speed[2]; + fp[3] = speed[3]; } } - break; + } } + if (col) { const float *fp= col+delta; int samp; @@ -3661,53 +3657,51 @@ static void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, flo float *fp, *col= NULL; int pixsize= 3; - switch (rpass->passtype) { - case SCE_PASS_Z: - fp= rpass->rect + offset; - if (shr->z < *fp) - *fp= shr->z; - break; - case SCE_PASS_RGBA: - fp= rpass->rect + 4*offset; - addAlphaOverFloat(fp, shr->col); - break; - case SCE_PASS_EMIT: - col= shr->emit; - break; - case SCE_PASS_DIFFUSE: - col= shr->diff; - break; - case SCE_PASS_SPEC: - col= shr->spec; - break; - case SCE_PASS_SHADOW: - col= shr->shad; - break; - case SCE_PASS_AO: - col= shr->ao; - break; - case SCE_PASS_ENVIRONMENT: - col= shr->env; - break; - case SCE_PASS_INDIRECT: - col= shr->indirect; - break; - case SCE_PASS_REFLECT: - col= shr->refl; - break; - case SCE_PASS_REFRACT: - col= shr->refr; - break; - case SCE_PASS_NORMAL: - col= shr->nor; - break; - case SCE_PASS_MIST: - col= &shr->mist; - pixsize= 1; - break; + if (STREQ(rpass->name, RE_PASSNAME_Z)) { + fp = rpass->rect + offset; + if (shr->z < *fp) + *fp = shr->z; + } + else if (STREQ(rpass->name, RE_PASSNAME_RGBA)) { + fp = rpass->rect + 4*offset; + addAlphaOverFloat(fp, shr->col); + } + else if (STREQ(rpass->name, RE_PASSNAME_EMIT)) { + col = shr->emit; + } + else if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) { + col = shr->diff; + } + else if (STREQ(rpass->name, RE_PASSNAME_SPEC)) { + col = shr->spec; + } + else if (STREQ(rpass->name, RE_PASSNAME_SHADOW)) { + col = shr->shad; + } + else if (STREQ(rpass->name, RE_PASSNAME_AO)) { + col = shr->ao; + } + else if (STREQ(rpass->name, RE_PASSNAME_ENVIRONMENT)) { + col = shr->env; + } + else if (STREQ(rpass->name, RE_PASSNAME_INDIRECT)) { + col = shr->indirect; + } + else if (STREQ(rpass->name, RE_PASSNAME_REFLECT)) { + col = shr->refl; + } + else if (STREQ(rpass->name, RE_PASSNAME_REFRACT)) { + col = shr->refr; + } + else if (STREQ(rpass->name, RE_PASSNAME_NORMAL)) { + col = shr->nor; + } + else if (STREQ(rpass->name, RE_PASSNAME_MIST)) { + col = &shr->mist; + pixsize = 1; } - if (col) { + if (col) { fp= rpass->rect + pixsize*offset; fp[0]= col[0] + (1.0f-alpha)*fp[0]; if (pixsize==3) { @@ -3964,7 +3958,7 @@ static void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf float *fp, *col; int a; - fp = RE_RenderLayerGetPass(rl, SCE_PASS_VECTOR, R.viewname); + fp = RE_RenderLayerGetPass(rl, RE_PASSNAME_VECTOR, R.viewname); if (fp==NULL) return; col= rectf+3; @@ -4058,7 +4052,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas /* zero alpha pixels get speed vector max again */ if (addpassflag & SCE_PASS_VECTOR) if (rl->layflag & SCE_LAY_SOLID) { - float *rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); + float *rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname); reset_sky_speedvectors(pa, rl, rl->acolrect ? rl->acolrect : rect); /* if acolrect is set we use it */ } /* filtered render, for now we assume only 1 filter size */ @@ -4246,7 +4240,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas if (alpha != 0.0f) { RenderLayer *rl_other = ssamp.rlpp[a]; - float *rect = RE_RenderLayerGetPass(rl_other , SCE_PASS_COMBINED, R.viewname); + float *rect = RE_RenderLayerGetPass(rl_other , RE_PASSNAME_COMBINED, R.viewname); addAlphaOverFloat(rect + 4 * od, samp_shr[a].combined); add_transp_passes(rl_other , od, &samp_shr[a], alpha); diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 9a25e0131a5..0ab0059fd07 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -234,7 +234,7 @@ void EDBM_mesh_normals_update(struct BMEditMesh *em) RET_NONE void *g_system; bool EDBM_mtexpoly_check(struct BMEditMesh *em) RET_ZERO -float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL +float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, const char *name, const char *viewname) RET_NULL float RE_filter_value(int type, float x) RET_ZERO struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name) RET_NULL void RE_texture_rng_init() RET_NONE @@ -248,6 +248,7 @@ float RE_engine_get_camera_shift_x(struct RenderEngine *engine, struct Object *c int RE_engine_get_spherical_stereo(struct RenderEngine *engine, struct Object *camera) RET_ZERO void RE_SetActiveRenderView(struct Render *re, const char *viewname) RET_NONE +struct RenderPass *RE_pass_find_by_name(volatile struct RenderLayer *rl, const char *name, const char *viewname) RET_NULL struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL bool RE_HasFakeLayer(RenderResult *res) RET_ZERO @@ -667,6 +668,7 @@ struct RenderData *RE_engine_get_render_data(struct Render *re) RET_NULL void RE_engine_update_result(struct RenderEngine *engine, struct RenderResult *result) RET_NONE void RE_engine_update_progress(struct RenderEngine *engine, float progress) RET_NONE void RE_engine_set_error_message(RenderEngine *engine, const char *msg) RET_NONE +void RE_engine_add_pass(RenderEngine *engine, const char *name, int channels, const char *chan_id, const char *layername) RET_NONE void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int cancel, int merge_results) RET_NONE void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info) RET_NONE void RE_layer_load_from_file(struct RenderLayer *layer, struct ReportList *reports, const char *filename, int x, int y) RET_NONE @@ -693,6 +695,7 @@ void RE_point_density_free(struct PointDensity *pd) RET_NONE void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]) RET_NONE void RE_FreeAllPersistentData(void) RET_NONE float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta) RET_ZERO +void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int channels, const char *chanid, int type) RET_NONE /* Draw */ void OBJECT_collection_settings_create(struct IDProperty *properties) RET_NONE diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 3f82c513f7d..339f27aa86e 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -994,8 +994,8 @@ void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, } bool negX = (scale[0] < 0.0f); - bool negY = (scale[0] < 0.0f); - bool negZ = (scale[0] < 0.0f); + bool negY = (scale[1] < 0.0f); + bool negZ = (scale[2] < 0.0f); if (negX || negY || negZ) { m_viewmatrix.tscale((negX)?-1.0f:1.0f, (negY)?-1.0f:1.0f, (negZ)?-1.0f:1.0f, 1.0); } |